标记表达式字符串

Tokenizing a string of expression

本文关键字:字符串 表达式      更新时间:2023-10-16

我有一个字符串,格式如下:

(1 + 2 - 3) / 5

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

更新:

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

(1+2 - 3)/5

应正确处理。

如果您不总是使用分隔符,可以使用flexflex++为您构建扫描仪。你会给它正则表达式,它会处理剩下的。

如果您真的想评估该表达式,那么标记化是不够的。你可能想要的是调车场算法。这会生成一个很好的运算符和值堆栈,然后您可以对这些运算符和值进行求值以获得表达式的答案。

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

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

如果保证数字和运算符之间有空格,那么使用例如std::istringstream和普通输入运算符>>将很好,因为输入运算符在空格上分离。

否则,你必须一次读取一个字符,并检查它是什么类。比如,如果它是一个数字,那么你就有一个数字;如果它是空格,那么忽略它;或者如果它是其他字符,那么它可能是一个运算符。

由于运算符之间似乎没有空格(就像您的示例中那样),因此您必须采用第二种方式。您可能想要搜索"lexer"或"词法分析"。


一些简单的伪代码让你开始:

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;
}

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

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