标记一串表达式

时间:2013-11-27 07:33:12

标签: c++

我有一个以下形式的字符串:

(1 + 2 - 3) / 5

我想提取数字/运算符并将它们放入单独的容器中。最好的方法是什么?谢谢!

更新

字符串之间不一定有“ws”。例如,

(1+2 - 3)/5

应该正确处理。

4 个答案:

答案 0 :(得分:2)

如果您不总是使用分隔符,则可以使用flexflex++为您构建扫描程序。你会给它正则表达式,它会照顾其余的。

答案 1 :(得分:1)

如果数字和运营商之间保证有空格,那么使用例如std::istringstream和普通输入操作符>>将正常工作,因为输入操作符在空格上分隔。

否则你必须一次读一个字符,并检查它是什么类。就像它是一个数字然后你有一个数字,如果它是一个空格然后忽略它,或者如果它是别的东西那么它可能是一个运算符。

因为看起来运营商之间可能没有空格(比如你的例子),所以你必须采用第二种方式。您可能想要搜索“lexer”或“lexical analysis”。


一些简单的伪代码可以帮助您入门:

struct token
{
    enum
    {
        NUMBER,
        OPERATOR
    } type;

    int         num; // If `type` is `NUMBER`
    std::string op;  // If `type` is `OPERATOR`
};

token get_token()
{
    char c = get_single_char();

    // Skip whitespace
    while (std::isspace(c))
        c = get_single_char();

    if (std::isdigit(c))
    {
        // A number
        int n = 0;

        while (std::isdigit(c))
        {
            n = n * 10 + (c - '0');
            c = get_single_char();
        }

        // Here we have gotten one character to many, put it back
        put_back_char(c);

        token t = { NUMBER, n, "" };
        return t;
    }

    // We have an operator
    token t;
    t.type = token::OPERATOR;
    t.op += c;
    return t;
}

答案 2 :(得分:1)

如果您真的想要评估该表达式,那么标记化将是不够的。您可能需要的是shunting yard algorithm。这会生成一堆很好的运算符和值,然后您可以对其进行求值以获得表达式的答案。

此算法是我Leaf解析器的基础。我使用boost::regex提取单个令牌并跳过空格。处理一元' - '可能是最棘手的部分。

如果您真的只想将数字和运算符提取到容器中,那么只需使用两个正则表达式。一个匹配所有数字,一个匹配所有运算符。查看boost regex令牌迭代器。

答案 3 :(得分:0)

对于您的示例,我将使用strtok()

此处示例:http://www.cplusplus.com/reference/cstring/strtok/