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 关注
- 128 浏览
添加回答
举报