2016-09-19 164 views
0

我正在创建一个计算器,其中我从输入字段获取一个字符串。该字符串可能是例如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

它会一直更好,如果你将针点更短的代码snipset实际上失败。 请注意,你是否需要自己做表达式解析或者简单地调用eval(_your_string_)就足够了?[link](http://www.w3schools.com/jsref/jsref_eval.asp) –

+0

这没有什么可做的与jQuery。你只用它来获取输入字符串('$('#input-display')。val();'),这与问题无关。 – trincot

+0

另请参阅http://stackoverflow.com/questions/32982719/chrome-app-doing-maths-from-a-string/ – guest271314

回答

1

这正则表达式是错误的结果的原因你:

RegExp('(?:.*?(\\d+[*\/]\\d+)){' + i + '}'); 

它不应该匹配.*?,因为这会让你在删除之前的所有字符接下来的replace

此外,单个\是不必要的。如果您真的想逃避/的正则表达式,则必须加倍前面的反斜杠,因为它也需要在带引号的字符串中转义。但是由于正斜杠不会出现在正则表达式中(如/.../g),所以不必转义。

{' + i + '}部分是没有用的。这只需要多次出现模式,但是在做出几次替换之后,这可能是错误的。事实上,每次都需要匹配第一个匹配项,因为之前的所有匹配项都已被替换。

所以应该只是这样的:

RegExp('(\\d+[*/]\\d+)'); 

...,所以它是没有事实从higher正则表达式的不同,除了全球改性剂。但higher上的全局修饰符不是必需的,因为split无论如何搜索所有的事件,即使没有该修饰符。这意味着你实际上只需要higher(没有g),而不是上面的正则表达式。

其他一些事情,以改善:

  1. 以下调试线是没有多大用处,因为calstr已经被修改,而修改前应用正则表达式:

    console.log('replaced result at : ' + calstr.search(regex)); 
    
  2. 最好不要访问函数内部的输入元素input-display。而是将calstr作为函数参数传递。这使得它独立于您的浏览器上下文。 ()可以做得更短。

这里是更新的代码,这也实现了+-处理,通过将整个事情在另一个循环有3次迭代:一为*/,另外两个为-(必须来之前+!)和+。这有另一个复杂性:单一的减号不应该与正常的减号运算符混淆。您会看到在内部正则表达式中使用(?:^-)?进行管理。

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); 
 
});
<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>

注意,要重新发明轮子,如JavaScript提供了eval函数来评估这样的(控制)的表达。而且,这段代码不会评估更复杂的表达式,就像它们有括号时一样。

+0

谢谢你非常...只做正则表达式修复我的问题似乎已经解决了...这是我正在寻找的解决方案...但我会尝试了解您所写的改进,并完成我的代码。 再次感谢 –

+0

不客气。请注意我刚刚做出的修改。它涉及'{+ i +}'部分:它可以被排除。 – trincot

0

好像你的第一个正则表达式var higher = /(\d+[*\/]\d+)/g;不会检索 “3 * 9/3” 2 + 3 * 9/3-6(在https://regex101.com/#javascript选中)

试试这个将其更改为

var higher = /(\d[^\+\-]*)+/g; 
+0

在第一次迭代它匹配3 * 9和计算结果...这是27,然后取代它会给“2 + 27/3 -6“...下一次迭代它会找到27/3并用9代替......然后我们将有”2 + 9-6“...全局正在工作,因为我满足了......但问题在于当我尝试用3 * 9替换27,然后用9替换27/3 ... 它取代了0到发生。所有这一切...我似乎无法解决这个问题。 大多数内部循环有一个正则表达式,应该替换第n个发生..但它不工作,因为我满足...所以如果我没有错。问题是与内部正则表达式 –

2

仅仅评估输入是不是更简单?

function doEval() { 
 
    try { 
 
    alert(eval(document.querySelector('input').value)); 
 
    } catch (error) { 
 
    alert('Invalid input: ' + error); 
 
    } 
 
}
<input type='text' value='1+(4-3)*10/5' /> 
 
<input type='button' onclick='doEval();' value='Eval' />

+0

这从来没有跨过我的脑海中......但它确实解决了这个问题......我正在使用正则表达式......但我帮助我提高了我的正则表达式技巧...... 再次感谢......。拥有超过1种解决方案总是令人愉快的 –