17370845950

c++中如何实现简单的计算器程序_c++四则运算逻辑实现
应使用 std::getline 读整行再用 std::stringstream 解析,避免 cin >> 跳过运算符或因无空格导致读取错误;仅支持单二元运算,多运算需两遍扫描处理优先级;须用 try-catch 处理 stod 异常,检查除零时用 abs(b)

std::stringstreamstd::getline 解析单行表达式

用户输入形如 "3 + 5 * 2" 的字符串时,不能直接用 cin >> 拆分——它会把 "+" 当作分隔符跳过,且无法处理空格不规范的输入(比如 "3+5 *2")。稳妥做法是读整行,再用 std::stringstream 逐词提取:

std::string line;
std::getline(std::cin, line);
std::stringstream ss(line);
double a; char op; double b;
if (ss >> a >> op >> b) {
    // 成功读到两个数和一个运算符
}

注意:这仅适用于**单个二元运算**(如 "10 - 3"),不支持多运算符或括号。若用户输 "1 + 2 + 3"ss >> a >> op >> b 只取前三个 token(即 1'+'2),末尾的 "+ 3" 被忽略。

手写简易运算符优先级处理(无括号)

要支持 "3 + 5 * 2" 正确算出 13 而非 16,必须先识别乘除,再做加减。可采用“两遍扫描”策略:

  • 第一遍:把输入按空格切分(或用 std::stringstream 提取所有 token),存入 std::vector<:string>
  • 第二遍:遍历 token,遇到 "*""/" 就立即计算其左右数字,并用结果替换这三个元素(如 {"3", "+", "5", "*", "2"} → 合并 "5", "*", "2""10",得到 {"3", "+", "10"}
  • 第三遍:对剩余 "+""-" 从左到右计算

关键点:std::stod() 转数字时抛异常(如输入 "abc"),务必用 try-catch 包裹;"-" 既作减号也作负号,简单计算器通常只支持二元减法,不处理 "-5 + 3" 这类前缀负号。

避免 std::cin >> 导致输入阻塞的典型错误

常见错误写法:

double a, b;
char op;
std::cin >> a >> op >> b;  // 若用户输 "3+5"(无空格),op 会读成 '3',b 读失败,流进入 failbit

后果:std::cin 状态卡住,后续所有输入都被跳过。修复方式只有两种:

  • 改用 std::getline + std::stringstream(推荐,见第一个副标题)
  • 若坚持用 >>,每次读后检查状态:if (!std::cin) { std::cin.clear(); std::cin.ignore(1000, '\n'); }

另外,std::cin >>"3.14e2" 这类科学计数法能正确解析,但对 "3,14"(逗号小数点)直接失败——C++ 默认 locale 是英文格式,不支持千位分隔符或本地化小数点。

除零和浮点精度问题怎么处理

除法必须显式检查:if (b == 0.0) 不可靠,因为浮点数比较需容忍误差。应写成:

const double EPS = 1e-9;
if (std::abs(b) < EPS) {
    std::cout << "Error: division by zero\n";
    return;
}

但注意:这只能捕获真正接近零的除数,无法区分 0.0-0.0(它们在 IEEE 754 中不同,但 std::abs(-0.0) 仍是 0.0)。实际中,简单计算器可直接用 b == 0.0 判断,因为用户不会手动输 -0.0。更隐蔽的问题是 std::pow(0, 0) 或开方负数——四则运算不涉及这些,但若后续扩展函数功能,必须单独拦截。

浮点误差本身无法消除,例如 0.1 + 0.2 输出 0.30000000000000004。显示时可用 std::setprecision(10) 控制小数位,但底层值不变。