AI编程助手
AI免费问答

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

P粉602998670   2025-08-13 10:29   361浏览 原创

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

如何用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)  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()  postfixQueue = infixToPostfix(expression);
        double result = evaluatePostfix(postfixQueue);
        cout <p>这段代码首先定义了运算符的优先级,然后实现了一个中缀表达式转后缀表达式的函数<pre class="brush:php;toolbar:false">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;
}</string></map>

然后,需要修改

infixToPostfix
函数,识别函数调用,并将函数名和参数转换为后缀表达式。 例如,将
sin(3.14)
转换为
3.14 sin
。 最后,修改
evaluatePostfix
函数,当遇到函数名时,从函数注册表中查找函数指针,并调用该函数。 这部分代码比较复杂,需要仔细设计和实现。

C++免费学习笔记(深入):立即学习
>在学习笔记中,你将探索 C++ 的入门与实战技巧!

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。