← |
2024年11月 |
→ |
日 |
月 |
火 |
水 |
木 |
金 |
土 |
|
|
|
|
|
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
|
26 |
27 |
28 |
29 |
30 |
|
というわけで、「1+2+3」等の文字列から、 6という数字を求めるアルゴリズムを、 なんちゃってで作る方法。
まずは、計算式というものは、どういう物かを定義します。 こんな感じです。
ほんとは、NBF記法とかの話があるけど直感的に書くとこんな図面。
あとは、この図面に従ってコードをサクッと書くだけ。
using System; using System.Collections.Generic; using System.Linq; using System.Text;
namespace Str2Num { class Program { /// <summary> /// メイン関数 /// </summary> /// <param name="args"></param> static void Main(string[] args) { string src = "12+34+5*-6+15/2"; double ret = a(src); Console.WriteLine(ret); } /// <summary> /// 関数Aを定義 /// </summary> static double a(string src) { int readPos = 0; //設計通り、必ず関数Bが最初に呼ばれる。 double ret = b(src, ref readPos); //その後、+か-記号で関数Bの実行を繰り返して行う。 while (readPos < src.Length && (src[readPos] == '+' || src[readPos] == '-')) { if (src[readPos] == '+') { readPos++; ret += b(src, ref readPos); } else if (src[readPos] == '-') { readPos++; ret -= b(src, ref readPos); } else { throw new Exception(); } } return ret; } /// <summary> /// 関数Bを定義 /// </summary> static double b(string src, ref int readPos) { //ここも、設計通り、まずは関数Cを呼ぶ。 double ret = c(src, ref readPos); //その後、*か/記号で関数Cの実行を繰り返して行う。 while (readPos < src.Length && (src[readPos] == '*' || src[readPos] == '/')) { if (src[readPos] == '*') { readPos++; ret *= c(src, ref readPos); } else if (src[readPos] == '/') { readPos++; ret /= c(src, ref readPos); } else { throw new Exception(); } } return ret; } /// <summary> /// 関数Cを定義 /// </summary> static double c(string src, ref int readPos) { //最後は関数C int flag = 1; //単項演算子-のフラグ管理 double ret = 0; //まず、1文字目が-ならば、その旨を覚えておく。 if (src[readPos] == '-') { flag = -1; readPos++; } //符号を除けば、まずは1〜9の数値が来るはず。 if ('1' <= src[readPos] && src[readPos] <= '9') { ret = int.Parse(src[readPos].ToString()); readPos++; } else { throw new Exception();//それ以外の文字が来るならばエラー } //2文字目以降の数字があるかを確認する //数値以外が出ていたり、数式を最後まで確認したら終わり。 while (readPos < src.Length && ('0' <= src[readPos] && src[readPos] <= '9')) { //0〜9の数値が見つかったので、戻り値の数値を調整する。 ret *= 10; ret += int.Parse(src[readPos].ToString()); readPos++; } return ret * flag; } } } ね?簡単でしょ?
括弧が欲しければ、関数Cの定義を↓こう書き換えればいい。
以上、BNF表記とか、オートマトンとか、 逆ポーランド記法とかの言葉が分からなくても、 なんちゃってで、文字解析をする方法でした。
|
01:25, Wednesday, Apr 20, 2011 ¦ 固定リンク
¦ 携帯
■コメント
■コメントを書く
※コメントの受け付けは終了しました
|
|