我在C ++中创建了一个函数来评估数学表达式。例如,您将函数传递给字符串20 + 10 * 3
,函数返回一个字符串,该字符串是提供的表达式的结果。在这种情况下,函数将返回50
。
上述功能适用于OSX和Windows以及上面的表达式。但是当您提供包含括号的表达式时,它只能在OSX上正常工作。
例如,(10 + 2) * 2
适用于OSX,但在Windows上会产生此错误:
terminate called after throwing an instance of 'std::invalid_argument'
这是我的功能:
string evalExpression(string expr) {
int res = 0;
int getnextnum = 0;
int iter = 0;
int i = 0;
int temp_i;
int i2;
int temp_n_size;
int ns;
int second_eval_size;
int bcount = 0;
bool bstarted = 0;
string b = "";
string opp = "";
string num = "";
string num1 = "";
string num2 = "";
string ans = "";
vector<string> numholder;
vector<string> temp_numholder;
if (numholder.size() != 0)
numholder.clear();
for (char & c : expr) {
if (c == '0' or c == '1' or c == '2' or c == '3' or c == '4' or c == '5' or
c == '6' or c == '7' or c == '8' or c == '9') {
// c is a number
num += c;
} else if (c == '+' or c == '-' or c == '*' or c == '/') {
// c is an operator
numholder.push_back(num);
if (c == '+') {
opp = "+";
}
else if (c == '-') {
opp = "-";
}
else if (c == '*') {
opp = "*";
}
else if (c == '/') {
opp = "/";
}
else if (c == '%') {
opp = "%";
}
numholder.push_back(opp);
num = "";
}
else if (c == ']') {
// end of expression
numholder.push_back(num);
}
else if (c == '(' or c == ')') {
// c is a round bracket
if (c == '(') {
b = "(";
}
else {
b = ")";
numholder.push_back(num);
}
num = "";
numholder.push_back(b);
}
}
ns = numholder.size();
STARTB:for (i = 0; i < ns; i++) {
if (numholder[i] == "(") {
temp_i = i;
i2 = i;
}
if (numholder[i] == ")") {
temp_i = i - temp_i;
}
}
for (i = 1; i < temp_i; i++) {
temp_numholder.push_back(numholder[i2+i]);
}
temp_n_size = temp_numholder.size();
for (i = 0; i < temp_n_size;i++) {
if (temp_numholder[temp_n_size-i-1] == "/") {
ans = to_string(stof(temp_numholder[temp_n_size-i-2]) / stof(temp_numholder[temp_n_size-i]));
temp_numholder[temp_n_size-i-2] = ans;
temp_numholder.erase(temp_numholder.begin()+temp_n_size-i-1);
temp_numholder.erase(temp_numholder.begin()+temp_n_size-i-1);
}
}
for (i = 0; i < temp_n_size; i++) {
if (temp_numholder[temp_n_size-i-1] == "*") {
ans = to_string(stof(temp_numholder[temp_n_size-i-2]) * stof(temp_numholder[temp_n_size-i]));
temp_numholder[temp_n_size-i-1] = ans;
temp_numholder.erase(temp_numholder.begin()+temp_n_size-i);
temp_numholder.erase(temp_numholder.begin()+temp_n_size-i-2);
}
}
for (i = 0; i < temp_n_size; i++) {
if (temp_numholder[temp_n_size-i-1] == "+") {
//cout << ns-i-3 << endl;
if (temp_n_size-i-3 >= 0) {
if (temp_numholder[temp_n_size-i-3] == "-") {
temp_numholder[temp_n_size-i-2] = to_string(stof(temp_numholder[temp_n_size-i-2]) * -1);
temp_numholder[temp_n_size-i-3] = "+";
}
}
ans = to_string(stof(temp_numholder[temp_n_size-i-2]) + stof(temp_numholder[temp_n_size-i]));
temp_numholder[temp_n_size-i-1] = ans;
temp_numholder.erase(temp_numholder.begin()+temp_n_size-i);
temp_numholder.erase(temp_numholder.begin()+temp_n_size-i-2);
}
}
for (i = 0; i < temp_n_size; i++) {
if (temp_numholder[temp_n_size-i-1] == "-") {
ans = to_string(stof(temp_numholder[temp_n_size-i-2]) - stof(temp_numholder[temp_n_size-i]));
temp_numholder[temp_n_size-i-1] = ans;
temp_numholder.erase(temp_numholder.begin()+temp_n_size-i);
temp_numholder.erase(temp_numholder.begin()+temp_n_size-i-2);
}
}
for (i = 1; i <= temp_i; i++) {
numholder.erase(numholder.begin()+i2+1);
}
if (ans != "")
numholder[i2] = to_string(stoi(ans));
for (i = 0; i < numholder.size(); i++) {
if (numholder[i] == "") {
numholder.erase(numholder.begin()+i);
}
}
if (temp_numholder.size() != 0) {
temp_numholder.clear();
}
for (i = 0; i < numholder.size();i++) {
if (numholder[i] == "(" or numholder[i] == ")") {
goto STARTB;
}
}
for (i = 0; i < ns; i++) {
if (numholder[ns-i-1] == "/") {
ans = to_string(stof(numholder[ns-i-2]) / stof(numholder[ns-i]));
numholder[ns-i-2] = ans;
numholder.erase(numholder.begin()+ns-i-1);
numholder.erase(numholder.begin()+ns-i-1);
}
}
for (i = 0; i < ns; i++) {
if (numholder[ns-i-1] == "*") {
ans = to_string(stof(numholder[ns-i-2]) * stof(numholder[ns-i]));
numholder[ns-i-1] = ans;
numholder.erase(numholder.begin()+ns-i);
numholder.erase(numholder.begin()+ns-i-2);
}
}
for (i = 0; i < ns; i++) {
if (numholder[ns-i-1] == "+") {
//cout << ns-i-3 << endl;
if (ns-i-3 >= 0) {
if (numholder[ns-i-3] == "-") {
numholder[ns-i-2] = to_string(stof(numholder[ns-i-2]) * -1);
numholder[ns-i-3] = "+";
}
}
ans = to_string(stof(numholder[ns-i-2]) + stof(numholder[ns-i]));
numholder[ns-i-1] = ans;
numholder.erase(numholder.begin()+ns-i);
numholder.erase(numholder.begin()+ns-i-2);
}
}
for (i = 0; i < ns; i++) {
if (numholder[ns-i-1] == "-") {
ans = to_string(stof(numholder[ns-i-2]) - stof(numholder[ns-i]));
numholder[ns-i-1] = ans;
numholder.erase(numholder.begin()+ns-i);
numholder.erase(numholder.begin()+ns-i-2);
}
}
i = 0;
for (i = 0; i < ns;i++) {
ans = numholder[ns-i-1];
}
expr = to_string(stoi(ans));
return expr;
}
我很欣赏我的功能很乱,并且可能一切都不正确,但我真的很感激,如果有人能看看,帮我找出错误。
答案 0 :(得分:0)
我很惊讶这个程序有效。有些部分代码我不理解,例如:
STARTB:for (i = 0; i < ns; i++) {
if (numholder[i] == "(") {
temp_i = i;
i2 = i;
}
if (numholder[i] == ")") {
temp_i = i - temp_i;
}
}
变量temp_i
和i2
可能会在循环结束前被覆盖
示例表达式:(6 +(4 * 5))* 2
如果numholder
包含多个左括号。
检查中的更多项目:
if / else /如果梯子难以阅读
在您的程序中,您可以使用switch
和case
语句使代码更易于阅读(在我看来):
switch (c)
{
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
// c is a number
num += c;
break;
case '*':
case '/':
case '+':
case '-':
// c is an operator
numholder.push_back(num);
std::string s(c); // Simplified all nested if statements.
numholder.push_back(s);
break;
// And so on.
重复代码片段
为什么要复制多个代码片段而不是使用变量:
ans = to_string(stof(temp_numholder[temp_n_size-i-2]) / stof(temp_numholder[temp_n_size-i]));
在开始评估表达式之前,您似乎可以创建两个类型为double
的变量:
double argument1 = 0.0;
double argument2 = 0.0;
argument1 = stof(temp_numholder[temp_n_size-i-2]);
argument2 = stof(temp_numholder[temp_n_size-i]);
switch (operator)
{
case '*':
ans = to_string(argument1 * argument2);
break;
case '/':
ans = to_string(argument1 * argument2);
break;
case '+':
ans = to_string(argument1 * argument2);
break;
case '-':
ans = to_string(argument1 * argument2);
break;
}
使用适当的数据结构
您的程序以我向小学生演示数学的方式评估表达式:通过擦除复杂表达式并插入简化并重新启动解析/评估过程。非常非常慢。通过使用其他数据结构,例如 stacks 和 trees ,计算机可以更快地完成这项工作。
在StackOverflow和网页上搜索“c ++表达式评估”,希望会有一些简单而正确的例子。