我有以下问题: 我有一个看起来像这样的输入字符串: string s ="87635+23754*ar+ar*var*0.895+(ar-var)+ar*ar+var*var";
我想拆分这个字符串并执行每个操作,即我想读入所有值,执行数学运算并在 C++ 中输出最终答案。我该怎么做?getline 命令只能拆分一种类型的分隔符。我该如何解决这个问题?
谢谢
妮塔
“正确”的答案是为您的迷你语言编写解析器,但使用string::find_first_of
和/或string::find_first_not_of
将其标记为数字、运算符和命名变量可能更简单
你必须写一个解析器。不要害怕“正确”的解决方案,这是有充分理由的;有用。其他人提供的快捷方式不会使您的任务变得更容易。
我提供了一个基本解决方案,您可以将其用作起点。您应该构建测试用例以确保它是正确的并更彻底地处理错误用例。
希望通过研究此代码,您将了解递归体面解析器的一般概念。我们通过对不同级别的运算符优先级使用单独的函数来分解解析问题。这些函数以自上而下的方式相互调用,使这种类型的解析器更容易理解。
我以简洁的方式对其进行了编码。如果您认为“goto”是邪恶的,请改用 while 循环。此外,将解析函数转换为 Parser 类以摆脱全局变量。
祝你好运和快乐的解析:)
#include <string>
#include <map>
#include <iostream>
#include <sstream>
using namespace std;
stringstream ss;
map<string,double> variables;
string err_string = "";
double parse_add_exp();
int main()
{
// get the expression and variables
ss << "87635+23754*ar+ar*var*0.895+(ar-var)+ar*ar+var*var";
variables["ar"] = -4.5;
variables["var"] = 141.26f;
try
{
// calculate the result
double result = parse_add_exp();
if( result == INFINITY )
cout<<"Runtime error: Division by zero"<<endl;
else
cout<<"Result = "<<result<<endl; // prints 'Result = 1.95143'
}
catch (const char * error)
{
cout<<"Invalid expression: "<<error<<endl;
}
return 0;
}
double parse_number()
{
double f;
if( !(ss>>f) )
throw "Expected number";
return f;
}
double parse_operand()
{
string var("");
while( isalpha(ss.peek()) )
var += ss.get();
if( !var.size() )
return parse_number();
if( variables.find(var) == variables.end() )
throw "Variable is undefined";
return variables[var];
}
double parse_parenthesis()
{
if( ss.peek() != '(' )
return parse_operand();
ss.get();
double f = parse_add_exp();
if( ss.get() != ')' )
throw "Expected closing parenthesis";
return f;
}
double parse_mul_exp()
{
double product = parse_parenthesis();
PEEKOP:
switch( ss.peek() )
{
case '*': ss.get(); product *= parse_parenthesis(); goto PEEKOP;
case '/': ss.get(); product /= parse_parenthesis(); goto PEEKOP;
default: return product;
}
}
double parse_add_exp()
{
double sum = parse_mul_exp();
PEEKOP:
switch( ss.peek() )
{
case '+': ss.get(); sum += parse_mul_exp(); goto PEEKOP;
case '-': ss.get(); sum -= parse_mul_exp(); goto PEEKOP;
default: return sum;
}
}
看看std::stringstream。您可以将字符串放入流中并从中读取,就像从 std::cin 中读取一样!
例如:
#include <iostream>
#include <sstream>
int main()
{
std::stringstream stream(std::stringstream::in | std::stringstream::out);
stream << "22+2";
int operand1, operand2;
char op;
stream >> operand1;
stream >> op;
stream >> operand2;
std::cout << operand1 << " " << op << " " << operand2 << std::endl;
return 0;
}
有关更复杂的示例,请查看我不久前所做的dc-clone : gist.github.com/ae6ebe58a286d6cfd847。尤其是第 467-522 行(主要)。