C++,以空格为一个单元解析字符串行

C++, parsing a string line with space as one unit

本文关键字:单元 一个 字符串 空格 C++      更新时间:2023-10-16

我正在用我的编程语言编写一个翻译器,这是一个简单的C++,我对解析一行有疑问。在C++中,我们将一些对象定义为:

class Item{
    string Item;
    string Item2;
};

我想使用关键字add:在我的语言中创建相同的对象

add "Item Item", "Item2 Item2";

如您所见,string变量"Item*"可能是一行带有空格。

但我需要解析它,并制作一个数组的命令堆栈。在这个例子中,我想解析这一行,使3的数组如下:[add, Item Item, Item2 Item2]。因此,我需要保存"ItemItem"之间的空格,并在解析时将其计算为一个字符串行,但仍然使用空格作为add和第一个"Item*"之间的分隔符。我该怎么做?

您需要将行分解为命令,这可以通过getline来实现。然后,您将希望使用quoted来拆分该命令。(请注意,quoted仅为C++14。因此,如果您没有,此解决方案将不起作用。)

这种方法的一个问题是,在语言中使用空格逗号作为分隔符。所以你必须提取逗号。但这可以通过一个简单的if来实现,它给你留下了这样的东西:

vector<vector<string>> result;
string command;
while(getline(input, command, ';')) {
    istringstream i(command);
    string element;
    result.resize(result.size() + 1);
    while( i >> quoted(element)){
        if(element != ",") result.back().push_back(element);
    }
}

其中input是具有命令的istringstream

实时示例

如果使用Boost,则可以使用split函数。我没有发现所有潜在的错误,但它用相当容易理解的代码给出了正确的答案。我所做的是将代码拆分到引号上。在引号之前有一个动作,在第一个引号之间是第一个项目,然后是逗号,在第二组引号之间是第二个项目:

#include <iostream>
#include <vector>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/classification.hpp>
class Item_container
{
    public:
        Item_container(const std::string& s)
        {
            std::cout << "Input string: " << s << std::endl;
            std::vector<std::string> string_vector;
            boost::split(string_vector, s, boost::is_any_of("""));
            // Below, error checking should be implemented
            stack.push_back(string_vector[0]);
            stack.push_back(string_vector[1]);
            stack.push_back(string_vector[3]);
        }
        std::vector<std::string> get_stack() const { return stack; }
    private:
        std::vector<std::string> stack;
};
int main()
{
    Item_container item_container("add "Item Item", "Item2 Item2";");
    for (auto &s : item_container.get_stack())
        std::cout << s << std::endl;
    return 0;
}

这里有一个小标记器。这只是一个样本;它没有错误检查,因此很可能会在意外输入时崩溃。包括的文件有iostream、string、vector和ctype.h。

enum st
{
    inSpace,
    inToken,
    inString
};
static st newstate(const char* p)
{
    if (isalpha(*p))
    {
        return inToken;
    }
    if ('"' == *p)
    {
        return inString;
    }
    return inSpace;
}
int main(int argc, const char * argv[]) {
    // insert code here...
    std::cout << "Hello, World!n";
    char line[128];
    std::cin.getline(line, sizeof(line));
    st state = inSpace;
    char* p = line;
    char* ptok = nullptr; // Will point to the beginning of a token
    std::vector<std::string*> sym;
    while(*p)
    {
        switch(state)
        {
            case inSpace:
                while(isspace(*p) || (',' == *p))
                {
                    ++p;
                }
                state = newstate(p);
                break;
            case inString:
                ptok = p; // Token includes opening quote
                while('"' != *++p);
                sym.push_back(new std::string(ptok, p + 1));
                state = newstate(++p);
                break;
            case inToken:
                ptok = p;
                while(isalpha(*++p));
                sym.push_back(new std::string(ptok, p));
                state = newstate(p);
                break;
            default:
                std:: cout << "Errorn";
        }
    }
    for(int i = 0; sym.size() > i; ++i)
    {
        std::cout << "Symbol #" << i + 1 << " = " << *(sym[i]) << std::endl;
    }
    return 0;
}