我正在做一个项目,从公式中读取一些字符串反应,例如:(5A + 3B = c + 10D)作为输入。我需要对字符串反应进行解析,以便我可以在char旁边提取&(拆分)整数值并将它们放入一个向量中,即与此处反应相关的向量是:[5 3 1 10]。
我考虑过std::strtok
函数,但我认为它不能分离整数值!
谁能帮我 ??
我试试这里:
int main()
{
std::string input;
std::getline(std::cin, input);
std::stringstream stream(input);
while(1) {
int n;
stream >> n;
char * pch;
pch = strtok (input," ");
while (pch != NULL)
{
printf ("%s\n",pch);
pch = strtok (NULL, " ,.");
}
return 0;
}
}
答案 0 :(得分:1)
要做一些严肃的解析工作,你需要学习一些语言理论。幸运的是,这并不困难。
我们将在这里讨论的方法是我们称之为自上而下的递归解析。
这个源代码的完整列表对于本论坛来说太长了,相反,我将为它提供一些伪代码。
您需要做的第一件事就是定义您的语法。什么被认为是有效的,什么不是,你代表这样的语法:
formula := term
:= term + formula
:= term - formula
term := variable
:= coefficient variable
所以公式C + 2D可以表示为
formula
term
variable
C
+
formula
term
coefficient
2
variable
D
考虑到这一点,我们首先解决一个更简单的问题,输入字符串只需要几种类型的东西
+
-
coefficient
variable
只有这四件事是有效的输入,你可能想跳过空格。将输入字符串拆分为这4种类型的东西称为词法分析。我们通常会实施一个所谓的扫描仪来执行此操作。
扫描仪通常看起来像这样
class Scanner
{
public:
Scanner(const char* text);
Token GetToken(); // The current token
void Scan(); // read the next token
}
接下来,您需要将这些令牌分组到树中,就像我在上面显示的那样。我们通常将此逻辑称为解析,并将其实现为解析器。您可以通过多种方式实现解析器,这是使用自顶向下预测解析器执行此操作的一种方法
class Parser
{
public:
private:
bool ParseVariable()
{
if (s.GetToken() is variable) { s.Scan(); return true; }
}
bool ParseTerm()
{
if (s.GetToken() is variable) { s.Scan(); return true; }
if (s.GetToken() is coefficient) { s.Scan(); return this->ParseVariable(); }
}
Scanner s;
}
类似的代码继续下去。显然,可以扩展那些Parse()方法的返回类型,以返回对其调用者有用的东西,并为您的目的组合所需的表示。
出于个人目的,我为不同语言编写了一些解析器。您可以将它们看作样本。
这是Python中的一个示例。 https://github.com/cshung/MiscLab/blob/master/GreatestCommonDivisor/polynomial_module.py
这是C ++中的一个带有小扭曲的示例,我向后解析字符串以避免左递归' https://github.com/cshung/Competition/blob/master/Competition/LEET_BASIC_CALCULATOR.cpp
要在真实产品中查看自上而下的解析器,请参阅ChakraCore中的这个示例,我很自豪地在之前工作过。 https://github.com/Microsoft/ChakraCore/blob/master/lib/Parser/Parse.cpp