将带数学问题的文本文件转换为带有这些问题的答案的文本文件

我目前正在尝试处理从用户处获取输入的代码,要求他们打开包含数学问题的文件,然后输出一个解决这些问题的文件。我一直在寻求某种形式的解决方案,这一切都结束了,但这些都是我得到的最接近:将带数学问题的文本文件转换为带有这些问题的答案的文本文件

文本文件的内容:

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


我假设你知道evalexec一般应当避免,因为它们可能会带来安全风险。详情请参阅SO资深人士Ned Batchelder的Eval really is dangerous。但是我猜你在这里没有多少选择,并且可以保证输入文件不会包含恶意代码。

回答:

你在第二次尝试中几乎找到了正确的答案。只需添加一个新的行字符每次你正在写的内容到你的文件,我认为它会得到正确的格式

outfile.write(str(ans) + '\n') 

PS我没有测试过,请检查是否有任何语法错误

回答:

是,你是对的,你想使用eval()而不是exec()。

它看起来像你只需要编写每个解决方案后换行即

outfile.write('\n') 

回答:

为了论证的缘故,我想证明你没有使用eval在所有您的问题!作为PM 2Ring has warned,使用evalexec是在情况下,安全隐患有任何机会,你正在评估的字符串可以被恶意第三方篡改。许多人关闭此安全风险,但如果你读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/val2float第一次转换得到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

回到顶部