该计算器程序使用中缀表达式转后缀表达式的策略,并通过栈实现计算;其核心步骤为:1.定义运算符优先级函数precedence;2.实现中缀转后缀函数infixtopostfix,利用栈处理运算符并生成后缀队列;3.实现后缀表达式求值函数evaluatepostfix,用栈存储操作数并根据运算符执行计算;4.主函数main接收输入并调用上述函数,同时捕获和处理异常;5.空格处理依赖stringstream自动忽略并分割token;6.扩展新运算符需在precedence添加优先级并在evaluatepostfix的switch中添加逻辑;7.支持函数调用需增加函数注册表、修改infixtopostfix识别函数名、并在evaluatepostfix中调用对应函数。

用C++实现一个简单的计算器,核心在于解析用户输入的字符串,识别数字和运算符,然后按照运算优先级进行计算。 这听起来简单,但细节很多,比如错误处理、不同数据类型的兼容性等等。

解决方案

首先,我们需要一个主函数来接收用户的输入,并调用相应的函数进行处理。
立即学习“C++免费学习笔记(深入)”;
#include <iostream>
#include <string>
#include <stack>
#include <queue>
#include <sstream>
#include <cctype>
#include <stdexcept>
#include <cmath>
using namespace std;
// 定义运算符优先级
int precedence(char op) {
if (op == '+' || op == '-')
return 1;
if (op == '*' || op == '/')
return 2;
if (op == '^') // 指数运算
return 3;
return 0;
}
// 中缀表达式转后缀表达式
queue<string> infixToPostfix(const string& expression) {
queue<string> postfixQueue;
stack<char> operatorStack;
stringstream ss(expression);
string token;
while (ss >> token) {
if (isdigit(token[0]) || (token.size() > 1 && isdigit(token[1]) && (token[0] == '-' || token[0] == '+'))) {
// 数字直接入队列 (处理负数)
postfixQueue.push(token);
} else if (token == "(") {
operatorStack.push('(');
} else if (token == ")") {
while (!operatorStack.empty() && operatorStack.top() != '(') {
postfixQueue.push(string(1, operatorStack.top()));
operatorStack.pop();
}
if (!operatorStack.empty() && operatorStack.top() == '(') {
operatorStack.pop(); // 弹出 '('
} else {
throw invalid_argument("Mismatched parentheses"); // 括号不匹配
}
} else {
// 运算符处理
char op = token[0]; // 假设token长度为1
while (!operatorStack.empty() && precedence(op) <= precedence(operatorStack.top())) {
postfixQueue.push(string(1, operatorStack.top()));
operatorStack.pop();
}
operatorStack.push(op);
}
}
// 将剩余运算符弹出
while (!operatorStack.empty()) {
if (operatorStack.top() == '(') {
throw invalid_argument("Mismatched parentheses"); // 括号不匹配
}
postfixQueue.push(string(1, operatorStack.top()));
operatorStack.pop();
}
return postfixQueue;
}
// 计算后缀表达式
double evaluatePostfix(queue<string> postfixQueue) {
stack<double> operandStack;
while (!postfixQueue.empty()) {
string token = postfixQueue.front();
postfixQueue.pop();
if (isdigit(token[0]) || (token.size() > 1 && isdigit(token[1]) && (token[0] == '-' || token[0] == '+'))) {
// 数字入栈
operandStack.push(stod(token));
} else {
// 运算符处理
if (operandStack.size() < 2) {
throw invalid_argument("Invalid expression"); // 缺少操作数
}
double operand2 = operandStack.top();
operandStack.pop();
double operand1 = operandStack.top();
operandStack.pop();
char op = token[0];
switch (op) {
case '+': operandStack.push(operand1 + operand2); break;
case '-': operandStack.push(operand1 - operand2); break;
case '*': operandStack.push(operand1 * operand2); break;
case '/':
if (operand2 == 0) {
throw invalid_argument("Division by zero"); // 除数为零
}
operandStack.push(operand1 / operand2);
break;
case '^': operandStack.push(pow(operand1, operand2)); break;
default: throw invalid_argument("Invalid operator"); // 无效运算符
}
}
}
if (operandStack.size() != 1) {
throw invalid_argument("Invalid expression"); // 表达式无效
}
return operandStack.top();
}
int main() {
string expression;
cout << "请输入算术表达式(用空格分隔数字和运算符,支持+ - * / ^):" << endl;
getline(cin, expression);
try {
queue<string> postfixQueue = infixToPostfix(expression);
double result = evaluatePostfix(postfixQueue);
cout << "结果: " << result << endl;
} catch (const exception& e) {
cerr << "错误: " << e.what() << endl;
return 1;
}
return 0;
}这段代码首先定义了运算符的优先级,然后实现了一个中缀表达式转后缀表达式的函数
infixToPostfix
evaluatePostfix

在上面的代码中,我们使用了
stringstream
stringstream
要添加更多运算符,首先需要在
precedence
evaluatePostfix
switch
%
// 在 precedence 函数中添加 % 的优先级
int precedence(char op) {
if (op == '+' || op == '-')
return 1;
if (op == '*' || op == '/')
return 2;
if (op == '%') // 求模运算
return 2;
if (op == '^') // 指数运算
return 3;
return 0;
}
// 在 evaluatePostfix 函数的 switch 语句中添加 % 的处理逻辑
switch (op) {
case '+': operandStack.push(operand1 + operand2); break;
case '-': operandStack.push(operand1 - operand2); break;
case '*': operandStack.push(operand1 * operand2); break;
case '/':
if (operand2 == 0) {
throw invalid_argument("Division by zero"); // 除数为零
}
operandStack.push(operand1 / operand2);
break;
case '%':
if (operand2 == 0) {
throw invalid_argument("Division by zero"); // 除数为零
}
operandStack.push(fmod(operand1, operand2)); // 使用 fmod 处理浮点数求模
break;
case '^': operandStack.push(pow(operand1, operand2)); break;
default: throw invalid_argument("Invalid operator"); // 无效运算符
}注意,求模运算需要使用
fmod
处理包含函数调用的表达式会更复杂。 首先,需要在
infixToPostfix
evaluatePostfix
#include <map>
// 定义函数指针类型
typedef double (*FunctionPtr)(double);
// 函数注册表
map<string, FunctionPtr> functionTable;
// 注册函数
void registerFunction(const string& name, FunctionPtr function) {
functionTable[name] = function;
}
// 实现一个示例函数
double sine(double x) {
return sin(x);
}
int main() {
// 注册 sine 函数
registerFunction("sin", sine);
// ... (修改 infixToPostfix 和 evaluatePostfix 函数)
return 0;
}然后,需要修改
infixToPostfix
sin(3.14)
3.14 sin
evaluatePostfix
以上就是如何用C++实现一个简单的计算器 控制台输入输出和基本运算处理的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号