我正在创建一个计算器,我从输入字段中获取一个字符串。例如,该字符串可以是2+3*9/3-6
。
现在我想首先执行乘法和除法运算,
所以我会得到2+ 9 -6
,其中9
将是更高优先级操作的答案。
到目前为止,我已经这样做了。这是一个完整的功能:
function calculateResult(){
var higher = /(\d+[*\/]\d+)/g;
calstr = $('#input-display').val();
var m = '*';
var res = calstr.split(higher);
console.log(res.length+ ' : ' + res);
// console.log(res);
if(res.length > 2){
console.log('split success');
var index = 0;
do{
for(var i = 1; i < res.length; i+=2){
var a = res[i].split(/([0-9\.]+)/g);
console.log('before calculation : '+calstr);
var regex = RegExp('(?:.*?(\\d+[*\/]\\d+)){' + i + '}');
console.log('regex generated : '+regex);
if(a[2] == '*'){
calstr = calstr.replace(regex , Number(a[1])*Number(a[3]));
}
else if(a[2] == '/'){
calstr = calstr.replace(regex , Number(a[1])/Number(a[3]));
}
console.log('replaced result : ' + calstr);
console.log('replaced result at : ' + calstr.search(regex));
}
// console.log('result : ' + calstr);
console.log('multiplication complete');
res = calstr.split(higher);
console.log('result is : '+res);
}while(res.length > 2);
}
else if(res.length == 1)
console.log('split failed');
}
当我尝试替换字符串中的结果时,替换成功。但是在几个输入上它取代了作为参数传递给该函数的整个字符串,这不是我想要的。
我做错了什么?
如果仍然不清楚,我很乐意澄清。
乘法和除法运行平稳后,我计划更改这些正则表达式,以添加对加法和减法的支持。它将使用相同的代码,但下一次运行较低的优先级运算符。
答案 0 :(得分:2)
仅仅评估输入会不会更简单?
function doEval() {
try {
alert(eval(document.querySelector('input').value));
} catch (error) {
alert('Invalid input: ' + error);
}
}
&#13;
<input type='text' value='1+(4-3)*10/5' />
<input type='button' onclick='doEval();' value='Eval' />
&#13;
答案 1 :(得分:1)
这个正则表达式是导致错误结果的原因:
RegExp('(?:.*?(\\d+[*\/]\\d+)){' + i + '}');
它不应与.*?
匹配,因为这将使您删除后面的replace
中的所有前面的字符。
此外,单\
是不必要的。如果你真的想要转义正则表达式的/
,你必须加倍前面的反斜杠,因为它也需要在引用的字符串中进行转义。但由于正斜杠不会出现在正则表达式文字中(如/.../g
),因此根本不需要进行转义。
{' + i + '}
部分没用。这只需要多次出现一个模式,但是在你已经进行了几次替换之后这可能是错误的。实际上,您需要每次匹配第一个匹配项,因为之前的所有匹配项都已被替换。
所以应该就是这样:
RegExp('(\\d+[*/]\\d+)');
...所以它实际上与higher
正则表达式没有区别,除了全局修饰符。但higher
上的全局修饰符不是必需的,因为split
无论如何都会搜索所有匹配项,即使没有该修饰符也是如此。这意味着您实际上只需要higher
(没有g
),而不是上面的正则表达式。
其他一些需要改进的地方:
以下调试行没什么用处,因为 calstr 已被修改,而正则表达式在修改之前应用了:
console.log('replaced result at : ' + calstr.search(regex));
最好不要访问函数内的输入元素input-display
。而是将calstr
作为函数参数传递。这使它独立于您的浏览器上下文。
Number(...)
)可以缩短 +
。
这是更新的代码,它还实现了+
和-
处理,将整个事物放在另一个循环中,该循环有3次迭代:一个用于*
和{{1其他两个/
(必须在-
之前!)和+
。这有另一个复杂性:单一的减号不应该与正常的减号运算符混淆。您将看到在内部正则表达式中使用+
进行管理。
(?:^-)?
function calculateResult(calstr){
for (var level = 0; level < 3; level++) {
var search = level == 0 ? '(\\d+[*/]\\d+)'
: level == 1 ? '(-?\\d+-\\d+)'
: '(-?\\d+\\+\\d+)';
var higher = RegExp(search);
var res = calstr.split(higher);
while(res.length > 2){
for(var i = 1; i < res.length; i+=2){
var a = res[i].split(/((?:^-)?[0-9\.]+)/g);
calstr = calstr.replace(higher,
a[2] == '*' ? +a[1] * +a[3]
: a[2] == '/' ? +a[1] / +a[3]
: a[2] == '+' ? +a[1] + +a[3]
: +a[1] - +a[3]
);
}
res = calstr.split(higher);
}
}
return res[0];
}
$('button').click(function () {
var input = $('#input-display').val();
var result = calculateResult(input);
$('span').text(result);
});
请注意,您正在重新发明轮子,因为JavaScript提供了<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="input-display" value="2+3*9/3-6">
<button>Calc</button><br>
Result: <span></span>
函数来评估(受控)表达式。此外,此代码不会评估更复杂的表达式,例如它们有括号时。
答案 2 :(得分:0)
好像你的第一个正则表达式var higher = /(\d+[*\/]\d+)/g;
没有检索&#34; 3 * 9/3&#34;从2 + 3 * 9 / 3-6(在https://regex101.com/#javascript中查看)
尝试将其更改为
var higher = /(\d[^\+\-]*)+/g;