我正在用我的编程语言编写一个翻译器,这是一个简单的C ++,我对解析一行有疑问。在C ++中,我们将一些对象定义为:
class Item{
string Item;
string Item2;
};
我想使用关键字add
:
add "Item Item", "Item2 Item2";
如您所见,string
变量"项目*"可能是一个带空格的行。
但我需要解析它并创建一个数组的命令堆栈。在示例中,我想解析该行以使3的数组像这样:[add, Item Item, Item2 Item2]
。所以,我需要在" Item Item"之间保存空间。并在解析时将其计为一个字符串行,但仍然使用空格作为add
和第一个" Item *"之间的分隔符。我该怎么做?
答案 0 :(得分:1)
您希望将这些行划分为命令,这可以通过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
。
答案 1 :(得分:0)
如果您使用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;
}
答案 2 :(得分:-1)
这是一个小标记器。这只是一个样本;它没有错误检查,因此可能会在意外输入时崩溃。包含文件是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 << "Error\n";
}
}
for(int i = 0; sym.size() > i; ++i)
{
std::cout << "Symbol #" << i + 1 << " = " << *(sym[i]) << std::endl;
}
return 0;
}