用带符号数字分割字符串算术表达式的算法

时间:2012-11-27 13:09:52

标签: string algorithm

美好的一天,我只是想知道是否有办法将一串算术表达式分段为:

-2+-3+(4+5)

进入预期结果

-2 + -3 + ( 4 + 5 )

这个给定的字符串是使用空格分段的,我打算以这种方式格式化这个表达式,因为我必须用白色空格分隔它来做其他事情。这不是我现在所关注的,我的目标是当我遇到像上面例子那样的有符号数字而不是-2 + -3 + ( 4 + 5 )时,它看起来像- 2 + - 3 + ( 4 + 5 )

已经知道是什么造成了这个因为我用

替换所有标志
<whitespace> <operator> <whitespace>

但是如何排除有符号数字不像预期结果那样分段?

注意: 计划与语言无关,因为截至目前,我不知道使用哪一个,算法更重要,但为了更好地理解,Java会做。

2 个答案:

答案 0 :(得分:0)

通常这个任务是通过基于所谓的finite state machine的词法解析器来解决的。

string s = "-2+-3+(4+5)";
List<string> tokens = new List<string>();
const int ST_NONE = 0, ST_MINUS = 1, ST_DIGITS = 2, ST_PUNCT = 3;
int j = 0; // token start
int st = ST_NONE; // state
for(int i = 0; i < s.Length(); ++i) {
    switch(s[i]) {
        case '0' .. '9':
            if (st != ST_NONE && st != ST_DIGITS) { // any prev token
                tokens.Add(s.SubStr(j, i - j)); // yield prev token
                j = i; // start of new token
            }
            st = ST_DIGITS; // note transition from ST_MINUS
            break;
        case '-': // special case since number can start with it
            if (st == ST_DIGITS) { // "4-" is definitely means "4 - .."
                tokens.Add(s.SubStr(j, i - j)); // yield prev number
                j = i, st = ST_PUNCT;
            }
            else if (st != ST_NONE) {
                tokens.Add(s.SubStr(j, i - j)); // yield prev token
                j = i, st = ST_MINUS;
            }
            else {
                j = i, st = ST_MINUS;
            }
            break;
        case '+': case '*': case '/': case '(': case ')':
            if (st != ST_NONE) { // any prev token
                tokens.Add(s.SubStr(j, i - j)); // yield prev token
                j = i;
            }
            st = ST_PUNCT;
            break;
        default:
            throw new UnexpectedCharacter();
    }
}
if (st != ST_NONE) { // any prev token
    tokens.Add(s.SubStr(j, i - j)); // yield prev token
}

答案 1 :(得分:0)

简单的解决方案是注意-只有在它看起来像值的情况下才是二元运算符,在你的情况下是一个数字或)。因此,如果您迭代令牌(其中令牌是操作员角色或一系列数字),并且只记得最后一个令牌是否为值(数字或)),您可以随时决定是否在当前令牌之后放置一个空格。 (您还可以捕获一些语法错误。)