为何cin.peek() == '\n'对+/-有效,对*/^运算符无效?
问题原因分析
你的循环终止异常是两个核心问题导致的:
1. 运算符未被从输入流中提取
当你用cin.peek()检测到运算符(+、*等)时,只是把运算符添加到了op向量,但没有从输入流中移除这个字符。这个运算符会一直留在输入缓冲区里,后续的输入操作会反复读到它。
2. +/-与*///^的输入行为差异
C++的cin >> float会把+和-当作浮点数的符号位处理(比如+123、-45都是合法的浮点数输入)。所以输入1+2时:
- 第一次
cin >> in读取1 peek()到+,加入op- 第二次
cin >> in会把+2解析成浮点数2,顺带消耗掉流中的+ - 最终流里剩下
\n,peek()检测到后终止循环
但*、/、^不是浮点数的合法前缀,当你输入1/3时:
- 第一次
cin >> in读取1 peek()到/,加入op- 第二次
cin >> in尝试读取/3,这不是合法浮点数,输入流进入错误状态 - 之后所有的
cin.peek()和cin >>操作都会失效,循环无法检测到\n,进入死循环
另外还有一个明显的bug:处理-运算符时,你错误地把它添加成了'+',这会导致减法运算变成加法。
修复方案
针对上述问题,修改input()函数的核心逻辑:
- 检测到运算符时,先从输入流中读取并移除它
- 修正
-运算符的添加错误 - 添加流状态检查,避免死循环
修改后的input()函数代码:
void input () { float in; char ch; for (int i = 0;;i++) { // 先检查流状态,如果出错直接终止循环 if (!cin) { break; } if(cin.peek() == '\n') { break; } // 检测到运算符时,先读取这个字符,再添加到op else if(cin.peek() == '+') { cin.get(ch); // 从流中提取'+' op.push_back('+'); } else if(cin.peek() == '-') { cin.get(ch); // 从流中提取'-' op.push_back('-'); // 修复这里的错误 } else if(cin.peek() == '*') { cin.get(ch); // 从流中提取'*' op.push_back('*'); } else if(cin.peek() == '/') { cin.get(ch); // 从流中提取'/' op.push_back('/'); } else if(cin.peek() == '^') { cin.get(ch); // 从流中提取'^' op.push_back('^'); } cin >> in; num.push_back(in); } // 输出向量内容(保留你的调试代码) for (auto i = num.begin(); i != num.end(); ++i) { cout << *i << " "; } for (auto i = op.begin(); i != op.end(); ++i) { cout << *i << " "; } // 计算逻辑保留,添加边界检查避免崩溃 if (num.size() >=2 && op.size() >=1) { calc(num.at(0),num.at(1),op.at(0)); for (int i = 2; i < num.size(); i++) calc(hasil,num.at(i),op.at(i-1)); } }
额外优化建议
- 全局变量
hasil、num、op容易引发意外问题,建议改为函数内的局部变量,通过返回值或引用传递结果 - 添加除数为0的检查,避免除法运行时错误
- 处理表达式的运算符优先级(当前代码是从左到右依次计算,不考虑
*、/优先于+、-的规则)
内容的提问来源于stack exchange,提问作者Hloandgoodbye
相关产品推荐
相关产品推荐

