将带数学问题的文本文件转换为带有这些问题的答案的文本文件
我目前正在尝试处理从用户处获取输入的代码,要求他们打开包含数学问题的文件,然后输出一个解决这些问题的文件。我一直在寻求某种形式的解决方案,这一切都结束了,但这些都是我得到的最接近:将带数学问题的文本文件转换为带有这些问题的答案的文本文件
文本文件的内容:
2 + 2
3 * 3
4.5 - 2.3
-8.8 + 1.2
2^4
8.9/2.3
5%3
-2 * -2
尝试1:
input_file_name = input("What file would you like to open? ") output_file_name = input("What file would you like to write to? ")
with open(input_file_name,"r") as input_file:
contents = input_file.readlines()
num = "".join(contents)
contents_length = len(num)
with open(output_file_name, "w") as output_file:
while contents_length >= 0:
num = num.replace("^","**") # change the^to ** so python can properly do the function
contents_value = exec(num)
contents_length = contents_length - 1
output_file.write(str(contents_value))
我接收到的文本文件将返回 “无”
尝试2:
input_file_name = input("What file would you like to open? ") output_file_name = input("What file would you like to write to? ")
infile = open(input_file_name, "r")
outfile = open(output_file_name, "w")
lines = infile.readlines()
i = len(lines) - 1
while i >= 0:
ans = eval(lines[i])
outfile.write(str(ans))
i = i - 1
infile.close()
outfile.close()
而且文本文档文件中有423.86956521739130476-7.60000000000000052.294。
所以,我真的不知道还有什么要做。任何帮助将不胜感激。
回答:
您需要单独处理的每一行,但是这个代码
num = "".join(contents)
结合了所有的线到一个单一串。
另一个问题是不需要的小数位。您可以使用round
函数修复该问题。下面的代码直接从脚本中读取数据,但很容易使其适用于从文件中读取数据,或者使用.readlines
,或者通过简单地循环访问文件对象。
data = '''\ 2 + 2
3 * 3
4.5 - 2.3
-8.8 + 1.2
2^4
8.9/2.3
5 % 3
-2 * -2
'''.splitlines()
for line in data:
line = line.replace('^', '**')
s = round(eval(line), 6)
print(s)
输出
4 9
2.2
-7.6
16
3.869565
2
4
这是输出使用Python 3.在Python 2中创建的,它不是很干净:一切都会被写为浮动。
的Python 2输出
4.0 9.0
2.2
-7.6
16.0
3.869565
2.0
4.0
我假设你知道eval
和exec
一般应当避免,因为它们可能会带来安全风险。详情请参阅SO资深人士Ned Batchelder的Eval really is dangerous。但是我猜你在这里没有多少选择,并且可以保证输入文件不会包含恶意代码。
回答:
你在第二次尝试中几乎找到了正确的答案。只需添加一个新的行字符每次你正在写的内容到你的文件,我认为它会得到正确的格式
outfile.write(str(ans) + '\n')
PS我没有测试过,请检查是否有任何语法错误
回答:
是,你是对的,你想使用eval()而不是exec()。
它看起来像你只需要编写每个解决方案后换行即
outfile.write('\n')
回答:
为了论证的缘故,我想证明你没有使用eval
在所有您的问题!作为PM 2Ring has warned,使用eval
或exec
是在情况下,安全隐患有任何机会,你正在评估的字符串可以被恶意第三方篡改。许多人关闭此安全风险,但如果你读my favourite answer in the subject你可以看到一个显着简单的例子来执行外蟒蛇任意程序一起eval
通话。所以要从未使用上不是100%信任和下控制源eval
/exec
。
回到你的问题,你的例子似乎总是使用 下面是返回结果为您输入的一行的(一个表达)的函数:val1 OP val2
,即两个数字(可能是负数,可能是浮点数)与中缀数学运算符。这个结构非常简单,你可以(我相信应该)为它编写你自己的解析器。这充当了一个演示,通过明确处理我们期望的安全方式的输入,我们可以保证我们的程序在无效和恶意输入上打破。import operator
def evaluate(expr):
'''Evaluate expressions of the form `val1 OP val2`; OP is in [+,-,/,*,%,^]'''
ops = {
'+': operator.add,
'-': operator.sub,
'*': operator.mul,
'/': operator.truediv,
'%': operator.mod,
'^': operator.pow,
}
# gather operators and put minus last so we can handle negative numbers right
opskeys = list(ops)
ind = opskeys.index('-')
implemented_ops = opskeys[ind+1:] + opskeys[:ind+1]
for opnow in implemented_ops:
if opnow in expr:
val1,op,val2 = expr.rpartition(opnow)
# convert the numbers to floats, or ints in case they are integral
val1,val2 = (int(val) if val.is_integer() else val
for val in map(float,[val1,val2]))
break
else:
raise ValueError('Invalid input line "{}"!'.format(expr))
return ops[op](val1,val2) # or round(...,digits) see PM 2Ring's answer
该函数采用输入的单个线,找到合适的数学运算符,分割使用该字符的行,然后评估结果。它使用调度字典根据字符选择实际的数学运算符;一个好处是我们甚至不需要转换电力运营商。我们将整数输入转换为整数,并将其余部分作为浮点数保留。
函数最后处理减法,这保证了负数不乱了所有其他运营商的计算。这不完全万无一失:如果有料想不到和负数无效行,我们很可能会从val1
/val2
到float
第一次转换得到ValueError
。从负数减去数字或类似的角落案例时,它也可能会中断。可以在代码中添加进一步的保护措施(例如捕获来自float()
的异常)我的观点是要证明你可以非常容易地使用安全和可控的方法而不是eval
。
与您的数据(帽尖再次PM 2Ring)加上有意无效的输入行中运行的一个例子:
data = '''\ 2 + 2
3 * 3
4.5 - 2.3
-8.8 + 1.2
2^4
8.9/2.3
5 % 3
-2 * -2
3 @ 4
'''.splitlines()
for line in data:
print(evaluate(line))
在交互式壳的相应的输出:
4 9
2.2
-7.6000000000000005
16
3.8695652173913047
2
4
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
File "foo.py", line 26, in evaluate
raise ValueError('Invalid input line "{}"!'.format(expr))
ValueError: Invalid input line "3 @ 4"!
以上是 将带数学问题的文本文件转换为带有这些问题的答案的文本文件 的全部内容, 来源链接: utcz.com/qa/258534.html