boxmoe_header_banner_img

Hello! 欢迎来到悠悠畅享网!

文章导读

如何用C++实现一个简单的计算器 控制台输入输出和基本运算处理


avatar
站长 2025年8月13日 1

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

如何用C++实现一个简单的计算器 控制台输入输出和基本运算处理

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

如何用C++实现一个简单的计算器 控制台输入输出和基本运算处理

解决方案

如何用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

。 主函数负责接收用户输入,调用这两个函数,并输出结果。当然,这段代码还包含了一些错误处理,比如括号不匹配、除数为零等等。

如何用C++实现一个简单的计算器 控制台输入输出和基本运算处理

如何处理用户输入中的空格?

在上面的代码中,我们使用了

stringstream

来处理用户输入。

stringstream

会自动忽略空格,并将字符串分割成一个个的 token。 因此,用户可以在输入表达式时随意添加空格,程序仍然可以正确解析。

如何扩展计算器的功能,比如添加更多运算符?

要添加更多运算符,首先需要在

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

函数,当遇到函数名时,从函数注册表中查找函数指针,并调用该函数。 这部分代码比较复杂,需要仔细设计和实现。



评论(已关闭)

评论已关闭