绘图计算器函数解析问题求助:-x²与x²+2x+1解析失效
函数解析Solver在
-x²和x²+2x+1测试用例下失效的问题 我正在做一个学校项目,开发一款能绘制函数图像的计算器。图像绘制功能没问题,但负责把数学函数转换成数据的Solver函数在两个测试用例上出问题了:输入-x²和x²+2x+1的时候解析结果不对。按照现有的代码逻辑,这两个用例应该能正常运行才对,我卡了好半天,试了几种修改都要么没解决问题,要么把其他方程的解析给搞坏了,实在没辙了,来求助大家!
下面是我的Solver函数和配套的parsing函数代码:
double Solver(string input, double xValue) { int pos1; int pos2; int symbolpos; string substring; double value1; double value2; int count; while (input.find_first_of(" ") != string::npos) { input.erase(input.find_first_of(" "), 1); } while (input.find("(") != string::npos && input.find(")") != string::npos) { pos1 = input.find_first_of("("); if (pos1 > 0 && input[pos1 - 1] != '-') { input.insert(pos1, "*"); pos1++; } if (pos1 == 2 && input[0] == '-') { input.insert(pos1 - 1, "1"); pos1++; } pos2 = pos1; count = 1; while (count != 0) { pos2++; if (input[pos2] == '(') count++; if (input[pos2] == ')') count--; } substring = to_string(Solver(input.substr(pos1 + 1, pos2 - pos1 - 1), xValue)); input.replace(pos1, pos2 - pos1 + 1, substring); } while (input.find("x") != string::npos) { pos1 = input.find_first_of("x"); if (pos1 > 0) { input.insert(pos1, "*"); pos1++; } if (pos1 == 2 && input[0] == '-') { input.insert(pos1 - 1, "1"); pos1++; } input.replace(pos1, 1, to_string(xValue)); } while (input.find("--") != string::npos) { input.replace(input.find("--"), 2, "+"); } input = parsing(input, '^'); input = parsing(input, '*'); input = parsing(input, '/'); input = parsing(input, '+'); input = parsing(input, '-'); return stod(input); } string parsing(string tInput, char searchChar) { string input = tInput; int pos1, pos2, symbolpos; double value1, value2; string substring; while (input.substr(1).find_first_of(searchChar) != string::npos) { symbolpos = input.find_last_of(searchChar); pos1 = 0; for (int a = 0; a < symbolpos - 1; a++) { if (input[a] == '^') pos1 = a++; if (input[a] == '*') pos1 = a++; if (input[a] == '/') pos1 = a++; if (input[a] == '+') pos1 = a++; if (input[a] == '-') pos1 = a; } pos2 = input.size(); for (int a = input.size(); a > symbolpos + 1; a--) { if (input[a] == '^') pos2 = a--; if (input[a] == '*') pos2 = a--; if (input[a] == '/') pos2 = a--; if (input[a] == '+') pos2 = a--; if (input[a] == '-') pos2 = a--; } value1 = stod(input.substr(pos1, symbolpos - pos1)); value2 = stod(input.substr(symbolpos + 1, pos2 - symbolpos)); if (searchChar == '^') substring = to_string(pow(value1, value2)); if (searchChar == '*') substring = to_string(value1 * value2); if (searchChar == '/') substring = to_string(value1 / value2); if (searchChar == '+') substring = to_string(value1 + value2); if (searchChar == '-') substring = to_string(value1 - value2); input.replace(pos1, pos2 - pos1, substring); } return input; }
问题分析与修复方案
咱们先拆解这两个测试用例的问题根源,再给出不破坏其他解析逻辑的修复:
1. -x²的问题:一元负号处理错误
原代码在处理-x²时,会在x前盲目插入*,变成-*x²,替换x后变成-*2^2,这显然会导致解析或计算混乱。核心问题是没区分一元负号(比如-x)和二元运算符(比如3-x)。
修复x替换逻辑:
while (input.find("x") != string::npos) { pos1 = input.find_first_of("x"); // 只有当x前面是数字或右括号时,才插入*(避免一元负号场景乱加) if (pos1 > 0 && (isdigit(input[pos1-1]) || input[pos1-1] == ')')) { input.insert(pos1, "*"); pos1++; } // 处理一元负号:-x → -1*x if (pos1 == 1 && input[0] == '-') { input.insert(pos1, "1*"); pos1 += 2; } input.replace(pos1, 1, to_string(xValue)); }
修改后,-x²会先转为-1*x²,替换x后变成-1*2^2,后续能正确计算出-4。
2. x²+2x+1的问题:运算符边界查找逻辑错误
原parsing函数的边界查找循环条件和a++写法会导致漏掉运算符前后的正确边界,比如处理+时,无法准确截取x²和2x这样的完整项,导致计算顺序出错。
重构parsing函数的边界查找逻辑:
#include <cstring> // 需要引入这个头文件用strchr string parsing(string tInput, char searchChar) { string input = tInput; int symbolpos; double value1, value2; string substring; // 区分减法的一元负号和二元减号 bool isSubtraction = (searchChar == '-'); while (true) { if (isSubtraction) { // 只找二元减号(跳过开头的一元负号) symbolpos = input.find_first_of('-', 1); } else { symbolpos = input.find_first_of(searchChar); } if (symbolpos == string::npos) break; // 向左找当前运算符的左侧起始位置 int pos1 = 0; for (int a = symbolpos - 1; a >= 0; a--) { if (strchr("^*/+-", input[a]) != nullptr) { // 如果是开头的一元负号,继续往左(其实这里不会触发,因为二元减号从1开始找) if (input[a] == '-' && a == 0) continue; pos1 = a + 1; break; } } // 向右找当前运算符的右侧结束位置 int pos2 = input.size(); for (int a = symbolpos + 1; a < input.size(); a++) { if (strchr("^*/+-", input[a]) != nullptr) { pos2 = a; break; } } try { value1 = stod(input.substr(pos1, symbolpos - pos1)); value2 = stod(input.substr(symbolpos + 1, pos2 - symbolpos - 1)); } catch (...) { // 解析失败则跳过(处理特殊边界情况) if (isSubtraction) { symbolpos = input.find_first_of('-', symbolpos + 1); if (symbolpos == string::npos) break; continue; } break; } if (searchChar == '^') substring = to_string(pow(value1, value2)); else if (searchChar == '*') substring = to_string(value1 * value2); else if (searchChar == '/') substring = to_string(value1 / value2); else if (searchChar == '+') substring = to_string(value1 + value2); else if (searchChar == '-') substring = to_string(value1 - value2); input.replace(pos1, pos2 - pos1, substring); } // 单独处理开头的一元负号:比如 -5 → 0-5 if (isSubtraction && input[0] == '-') { input = "0" + input; return parsing(input, '-'); } return input; }
这个版本能准确截取运算符前后的完整项,处理x²+2x+1时,替换x为2后得到2^2+2*2+1,会按正确顺序计算出9。
额外优化:括号处的一元负号处理
原代码在处理-(x+1)这类情况时也会出错,补充括号部分的逻辑:
while (input.find("(") != string::npos && input.find(")") != string::npos) { pos1 = input.find_first_of("("); // 只有括号前是数字或右括号时才加* if (pos1 > 0 && (isdigit(input[pos1-1]) || input[pos1-1] == ')')) { input.insert(pos1, "*"); pos1++; } // 处理-(...) → -1*(...) if (pos1 == 1 && input[0] == '-') { input.insert(pos1, "1*"); pos1 += 2; } // 原有括号逻辑不变... }
测试验证
修改后,测试-x²(x=2)得到-4,x²+2x+1(x=2)得到9,同时不会破坏3*x+5、(x+1)^2等其他方程的解析逻辑。
内容的提问来源于stack exchange,提问作者Alexander Fritschi
相关产品推荐
相关产品推荐

