与えられた文字列が、数式として正しいかを判定するメソッドを作りたいです。
【条件】
・値として使えるのは、数字(小数含む)、仮数となるax(xは数値)という文字列。
・四則演算記号は「+」「-」「*」「/」
・四則演算記号とは別に、カッコ「(」「)」を使用可能。
考えたサンプルコード(失敗作)
c#
1public bool ValidateCalc(string calcText) 2{ 3 // calcTextを1文字ずつのCharに分解 4 var calcTextCharArray = calcText.ToCharArray(); 5 6 // 1文字ずつloop 7 for (var i = 0; i < calcTextCharArray.Length; i++) 8 { 9 var str = calcTextCharArray[i].ToString(); 10 11 // 数値ならそのまま続ける。 12 if (int.TryParse(str, out int nOut)) { continue; } 13 else 14 { 15 switch (str) 16 { 17 case "a": 18 case ".": 19 // a及びピリオドの場合、後続に数値が来なければ数式として間違っていると見做す。 20 if (i == calcTextCharArray.Length - 1) 21 { 22 return false; 23 } 24 25 var str2 = calcTextCharArray[i + 1].ToString(); 26 if (!int.TryParse(str2.ToString(), out int nOut2)) 27 { 28 return false; 29 } 30 31 break; 32 33 case "+": 34 case "-": 35 case "*": 36 case "/": 37 // 後続に数値,"a","("のいずれかが来なければ数式として間違っていると見做す。 38 if (i == calcTextCharArray.Length - 1) 39 { 40 return false; 41 } 42 43 var str3 = calcTextCharArray[i + 1].ToString(); 44 if (str3 == "a" || str3 == "(" || int.TryParse(str3.ToString(), out int nOut3)) { continue; } 45 else { return false; } 46 47 case "(": 48 var insideKakko = calcText.Substring(calcText.IndexOf("(") + 1, calcText.LastIndexOf(")") - calcText.IndexOf("(") - 1); 49 50 // カッコ内数式を判定。(閉じるカッコがない場合は数式として間違っていると見做す。) 51 if (this.ValidateCalc(insideKakko)) 52 { 53 i = i + insideKakko.Length + 1; 54 continue; 55 } 56 else { return false; } 57 58 default: 59 return false; 60 } 61 } 62 } 63 64 return true; 65}
上記コードでは、
c#
1var testString1 = "a1*a2-(a3+a4/a5+(a6-a7))*8"; // OK 2var testString2 = "2-(a3+a4/a5)*8-(a10%a12)"; // NG
となります。
testString2もOKとなるようにするために、お知恵をお貸しいただければ幸いです。
字句解析して構文木を作るのがあらゆる目的に合致しそうです。目的によってはもっと手を抜くことができます。
編集後でも testString2 に % が含まれているので当然 NG です。
数値も扱えないし、当然単項マイナス演算子の処理も含まれていません。
すべての return false; にブレークポイントを設定して、デバッグしてみてください。
と思いましたが、開発環境がわからないので、設定できるかどうかわかりませんでしたね。
理由はわかりませんが、var calcTextCharArray = calcText.ToCharArray();
これが、何度も実行されて、テキストが崩れているようです。
回答2件
あなたの回答
tips
プレビュー