用std::cin读数字后接字符串需先ignore清除换行符残留,否则getline会读空;读表达式应先getline整行再解析,避免operator>>跳过空白导致失败。

用 std::cin 读数字时,别直接用 operator>> 接字符串
新手常写 std::cin >> input; 然后试图把 input 当表达式解析——这行不通。C++ 标准库不带表达式求值器,std::cin >> 只能读基本类型(如 int、double)或空白分隔的单词,没法自动算 "3 + 4 * 2"。
正确做法是先读整行:std::string line; + std::getline(std::cin, line);,再手动解析。否则一输带空格的式子就卡住或跳过后续输入。
- 如果只支持单个运算(如
"5 + 3"),可拆成三个 token:std::istringstream(line) >> a >> op >> b; - 若要支持括号和优先级,得手写递归下降解析器,或引入轻量库(如
muParser),但对新手建议先砍需求:只做a op b形式 - 注意
std::cin缓冲区残留:前一次输入后没清掉换行符,getline会立刻返回空行——加一句std::cin.ignore();很常见
用 switch 处理运算符比一堆 if-else 更安全
判断 op 是 '+'、'-' 还是 '*' 时,switch(op) 比 if (op == '+') ... else if (op == '-') ... 更清晰,也更容易发现漏掉的分支。
关键点在于:必须检查 op 是否合法,否则除零或未定义行为会直接崩掉程序。
立即学习“C++免费学习笔记(深入)”;
- 在
switch前加守卫:if (op != '+' && op != '-' && op != '*' && op != '/') { std::cout -
case '/'分支里必须判断b != 0,不能只写result = a / b; - 用
double而非int存储操作数,避免整数除法截断(比如5 / 2得2而不是2.5)
循环结构选 while(true) 比 do-while 更好控制退出
计算器要持续运行直到用户输入特定退出指令(如 "quit" 或空行),while(true) 配合 break 最直白。用 do-while 容易把退出逻辑塞进循环体末尾,导致多执行一次无效解析。
退出判断必须放在读入之后、解析之前,否则用户输 quit 后程序仍尝试拆解它,触发异常或崩溃。
- 示例结构:
while (true) { std::cout << "> "; std::string line; std::getline(std::cin, line); if (line.empty() || line == "quit") break; // 解析 line 并计算 } - 别用
std::cin >> line判断退出——它跳过空白,输多个空格或回车不会触发break - Windows 下 Ctrl+Z、Linux/macOS 下 Ctrl+D 触发 EOF,
getline返回false,也要检查并break
编译时加 -std=c++17 避免 std::string_view 或 std::optional 报错
哪怕你没显式用新特性,某些头文件(比如 <string>)在旧标准下行为不同。例如 C++11 默认不启用 std::string 的 SSO(短字符串优化)稳定版本,调试时可能看到奇怪的内存地址;C++17 起 std::string_view 才正式可用,万一以后想优化 token 切分,标准不匹配就编译失败。
- 命令行编译:用
g++ -std=c++17 -o calc calc.cpp - Clang 同理:
clang++ -std=c++17 -o calc calc.cpp - VS 用户在项目属性 → C/C++ → 语言 → C++ 语言标准,选
ISO C++17 Standard (/std:c++17)
真正难的不是写完能算加减乘除,而是让程序在用户乱输、输一半、输负数、输小数点后两位时都不崩——这些边界处理,比主干逻辑花的时间多得多。


















