2016-09-19 120 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種解決方案總是令人愉快的 –