0

0

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

P粉602998670

P粉602998670

发布时间:2025-08-13 10:29:01

|

469人浏览过

|

来源于php中文网

原创

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

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

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

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

解决方案

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

首先,我们需要一个主函数来接收用户的输入,并调用相应的函数进行处理。

立即学习C++免费学习笔记(深入)”;

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;

// 定义运算符优先级
int precedence(char op) {
    if (op == '+' || op == '-')
        return 1;
    if (op == '*' || op == '/')
        return 2;
    if (op == '^') // 指数运算
        return 3;
    return 0;
}

// 中缀表达式转后缀表达式
queue infixToPostfix(const string& expression) {
    queue postfixQueue;
    stack 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 postfixQueue) {
    stack 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 postfixQueue = infixToPostfix(expression);
        double result = evaluatePostfix(postfixQueue);
        cout << "结果: " << result << endl;
    } catch (const exception& e) {
        cerr << "错误: " << e.what() << endl;
        return 1;
    }

    return 0;
}

这段代码首先定义了运算符的优先级,然后实现了一个中缀表达式转后缀表达式的函数

infixToPostfix
,最后实现了一个计算后缀表达式的函数
evaluatePostfix
。 主函数负责接收用户输入,调用这两个函数,并输出结果。当然,这段代码还包含了一些错误处理,比如括号不匹配、除数为零等等。

PLC编程入门基础知识 中文doc版
PLC编程入门基础知识 中文doc版

可编程序控制器,英文称Programmable Controller,简称PC。但由于PC容易和个人计算机(Personal Computer)混淆,故人们仍习惯地用PLC作为可编程序控制器的缩写。它是一个以微处理器为核心的数字运算操作的电子系统装置,专为在工业现场应用而设计,它采用可编程序的存储器,用以在其内部存储执行逻辑运算、顺序控制、定时/计数和算术运算等操作指令,并通过数字式或模拟式的输入、输出接口,控制各种类型的机械或生产过程。本平台提供PLC编程入门基础知识下载,需要的朋友们下载看看吧!

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

// 定义函数指针类型
typedef double (*FunctionPtr)(double);

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

相关专题

更多
数据类型有哪几种
数据类型有哪几种

数据类型有整型、浮点型、字符型、字符串型、布尔型、数组、结构体和枚举等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

297

2023.10.31

php数据类型
php数据类型

本专题整合了php数据类型相关内容,阅读专题下面的文章了解更多详细内容。

216

2025.10.31

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1435

2023.10.24

Go语言中的运算符有哪些
Go语言中的运算符有哪些

Go语言中的运算符有:1、加法运算符;2、减法运算符;3、乘法运算符;4、除法运算符;5、取余运算符;6、比较运算符;7、位运算符;8、按位与运算符;9、按位或运算符;10、按位异或运算符等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

222

2024.02.23

php三元运算符用法
php三元运算符用法

本专题整合了php三元运算符相关教程,阅读专题下面的文章了解更多详细内容。

84

2025.10.17

switch语句用法
switch语句用法

switch语句用法:1、Switch语句只能用于整数类型,枚举类型和String类型,不能用于浮点数类型和布尔类型;2、每个case语句后面必须跟着一个break语句,以防止执行其他case的代码块,没有break语句,将会继续执行下一个case的代码块;3、可以在一个case语句中匹配多个值,使用逗号分隔;4、Switch语句中的default代码块是可选的等等。

518

2023.09.21

Java switch的用法
Java switch的用法

Java中的switch语句用于根据不同的条件执行不同的代码块。想了解更多switch的相关内容,可以阅读本专题下面的文章。

404

2024.03.13

登录token无效
登录token无效

登录token无效解决方法:1、检查token的有效期限,如果token已经过期,需要重新获取一个新的token;2、检查token的签名,如果签名不正确,需要重新获取一个新的token;3、检查密钥的正确性,如果密钥不正确,需要重新获取一个新的token;4、使用HTTPS协议传输token,建议使用HTTPS协议进行传输 ;5、使用双因素认证,双因素认证可以提高账户的安全性。

6039

2023.09.14

vlookup函数使用大全
vlookup函数使用大全

本专题整合了vlookup函数相关 教程,阅读专题下面的文章了解更多详细内容。

26

2025.12.30

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C# 教程
C# 教程

共94课时 | 5.6万人学习

C 教程
C 教程

共75课时 | 3.8万人学习

C++教程
C++教程

共115课时 | 10.5万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号