0

我将公式字符串拆分"*/+-()"为我的模式(例如a*b+c是字符串),并且我在输出中得到一个列表,(a b c)其中a, b,c是变量并包含一些值,如5, 10, 15

我需要的是:我应该能够直接替换变量中的值并评估表达式。

该公式取自用户并不时更改。因此,如果用户输入(a/b),则应自动将其替换为实际值(5/10),然后返回结果 0.5。

该公式由有限数量的变量(例如a, b, c)组成,它可以使用+, -, *, /, (,)作为运算符。

问题是在拆分变量后,我无法用它们的值替换它们或评估方程。请帮助我用尽可能简短的表达来完成这项任务。提前致谢。

4

2 回答 2

0

如果您知道变量的名称并且它们都不是您使用的其他任何东西的前缀,您可以像这样轻松地转换表达式:

set a 1; set b 2; set c 3
set e "a*b+c"
set value [expr [string map {a $a b $b c $c} $e]]
puts "$e = $value"

注意:第三行的表达式周围没有大括号。这是您想要避免这样的安全性的时候,因为您正在执行表达式的运行时生成。

该映射可以自动生成:

set a 1; set b 2; set c 3
set e "a*b+c"
set vars {a b c}
set value [expr [string map [regsub -all {\w+} "& $&"] $e]]
puts "$e = $value"

但是,如果你有前缀和其他类似的东西,你需要一个更复杂的转换:

# Omitting the variable setup and print at the end...
proc replIfRight {vars word} {
    if {$word in $vars} {return \$$word} else {return $word}
}
set value [expr [subst [regsub -all {\w+} [string map {[ \[ $ \$ \\ \\\\} $e] {[replIfRight $vars &]}]]]

没想到自己会想出这么可怕的事情是绝对正确的!

于 2013-08-25T22:16:54.123 回答
0

它一点也不复杂:

首先,将所有变量替换为 Tcl 变量(准备好 a $)。
您必须小心不要替换sin(a)$sin($a)或类似。

regsub -all -inline {[a-z]+(?![a-z\(])} $input

例子:

set input {a*b+c+sin(d)}
regsub -all -inline {[a-z]+(?![a-z\(])} $input

将 yield $a+$b*$c+sin($c),可以传递给expr.
如果您需要变量名,只需将此表达式与正则表达式一起使用。

于 2013-08-24T19:25:07.593 回答