2 回答

TA貢獻1810條經驗 獲得超4個贊
我建議FSM(有限狀態機)而不是正則表達式。3
我們這里有狀態:
既不是變量,也不是數字
0
變量內
1
數以內
2
代碼:
private static IEnumerable<string> Parse(string formula) {
int state = 0;
StringBuilder buffer = new StringBuilder();
foreach (var c in formula) {
if (state == 0) { // neither var nor number
if (char.IsWhiteSpace(c))
continue;
if (char.IsDigit(c)) {
buffer.Append(c);
state = 2;
}
else if (char.IsLetter(c)) {
buffer.Append(c);
state = 1;
}
else
yield return c.ToString();
}
else if (state == 1) { // within variable
if (char.IsDigit(c) || char.IsLetter(c))
buffer.Append(c);
else {
yield return buffer.ToString();
buffer.Clear();
state = 0;
if (!char.IsWhiteSpace(c))
yield return c.ToString();
}
}
else if (state == 2) { // within number
if (char.IsDigit(c))
buffer.Append(c);
else if (char.IsLetter(c)) {
// 123abc we turn into 123 * abc
yield return buffer.ToString();
buffer.Clear();
state = 1;
yield return "*";
buffer.Append(c);
}
else {
yield return buffer.ToString();
buffer.Clear();
state = 0;
if (!char.IsWhiteSpace(c))
yield return c.ToString();
}
}
}
if (buffer.Length > 0)
yield return buffer.ToString();
}
演示:
string[] tests = new string[] {
"C=A+B",
"D= C+50",
"E = (A+B)*C -100",
};
string result = string.Join(Environment.NewLine, tests
.Select(test => new {
formula = test,
parsed = Parse(test)
.SkipWhile(term => term != "=") // we don't want "C = " or alike part
.Skip(1)
})
.Select(test => $"{test.formula,-20} => {string.Join(", ", test.parsed)}"));
Console.Write(result);
結果:
C=A+B => A, +, B
D= C+50 => C, +, 50
E = (A+B)*C -100 => (, A, +, B, ), *, C, -, 100
- 2 回答
- 0 關注
- 172 瀏覽
添加回答
舉報