0

0

如何用C++实现计算器项目 控制台四则运算开发过程

P粉602998670

P粉602998670

发布时间:2025-08-13 18:13:01

|

511人浏览过

|

来源于php中文网

原创

是,用c++++实现一个支持四则运算、括号、小数、负数和运算符优先级的控制台计算器是初学者练手的好项目,可通过递归下降解析法实现,核心思路是将表达式分层为expression(处理加减)、term(处理乘除)和factor(处理数字、括号和负数),利用递归函数按优先级解析输入,结合跳过空白字符、字符串转数字、括号匹配和除零检测等机制,最终在main函数中循环读取用户输入并输出计算结果,完整代码包含错误处理和测试用例,可进一步扩展支持更多运算符或图形界面,是一个涵盖词法分析、语法解析和异常处理的综合性基础练习。

如何用C++实现计算器项目 控制台四则运算开发过程

用C++实现一个控制台四则运算计算器,是一个非常适合初学者练手的项目。它能帮助你掌握基础语法、输入处理、字符串解析和简单的错误处理。下面我来一步步介绍开发过程和关键实现思路。


一、项目目标

实现一个简单的控制台程序,用户输入类似

3 + 5 * 2
的表达式,程序能正确计算并输出结果(注意运算优先级),支持加减乘除四则运算,支持小数和负数。


二、基本设计思路

由于要处理运算符优先级(乘除优先于加减),不能简单从左到右计算。我们可以采用以下两种常见方式之一:

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

短影AI
短影AI

长视频一键生成精彩短视频

下载
  • 中缀表达式转后缀(逆波兰) + 栈计算
  • 递归下降解析器(推荐,更直观)

这里我们采用递归下降法,结构清晰,适合初学者理解。


三、核心代码结构

我们将表达式按优先级分层处理:

  • expression()
    :处理加减(最低优先级)
  • term()
    :处理乘除(中等优先级)
  • factor()
    :处理数字、括号、负数(最高优先级)

四、完整代码实现

#include 
#include 
#include 
#include 

class Calculator {
private:
    std::string input;
    size_t pos;

    // 跳过空白字符
    void skip_whitespace() {
        while (pos < input.length() && std::isspace(input[pos])) {
            pos++;
        }
    }

    // 解析数字(支持小数和负数)
    double parse_number() {
        size_t start = pos;
        if (input[pos] == '-' || input[pos] == '+') {
            pos++;
        }
        while (pos < input.length() && std::isdigit(input[pos])) {
            pos++;
        }
        if (pos < input.length() && input[pos] == '.') {
            pos++;
            while (pos < input.length() && std::isdigit(input[pos])) {
                pos++;
            }
        }
        return std::stod(input.substr(start, pos - start));
    }

    // factor -> number | ( expression ) | -factor | +factor
    double factor() {
        skip_whitespace();

        if (pos >= input.length()) {
            throw std::runtime_error("Unexpected end of input");
        }

        char c = input[pos];

        if (c == '(') {
            pos++;
            double result = expression();
            skip_whitespace();
            if (pos >= input.length() || input[pos] != ')') {
                throw std::runtime_error("Missing closing parenthesis");
            }
            pos++;
            return result;
        } else if (c == '-') {
            pos++;
            return -factor();
        } else if (c == '+') {
            pos++;
            return factor();
        } else if (std::isdigit(c) || c == '.') {
            return parse_number();
        } else {
            throw std::runtime_error("Invalid character: " + std::string(1, c));
        }
    }

    // term -> factor * term | factor / term | factor
    double term() {
        double left = factor();

        while (true) {
            skip_whitespace();
            if (pos >= input.length()) break;

            char op = input[pos];
            if (op == '*' || op == '/') {
                pos++;
                double right = factor();
                if (op == '*') {
                    left *= right;
                } else {
                    if (std::abs(right) < 1e-10) {
                        throw std::runtime_error("Division by zero");
                    }
                    left /= right;
                }
            } else {
                break;
            }
        }

        return left;
    }

    // expression -> term + expression | term - expression | term
    double expression() {
        double left = term();

        while (true) {
            skip_whitespace();
            if (pos >= input.length()) break;

            char op = input[pos];
            if (op == '+' || op == '-') {
                pos++;
                double right = term();
                if (op == '+') {
                    left += right;
                } else {
                    left -= right;
                }
            } else {
                break;
            }
        }

        return left;
    }

public:
    double evaluate(const std::string& expr) {
        input = expr;
        pos = 0;
        skip_whitespace();
        if (pos >= input.length()) {
            throw std::runtime_error("Empty expression");
        }
        double result = expression();
        skip_whitespace();
        if (pos < input.length()) {
            throw std::runtime_error("Unexpected characters after expression");
        }
        return result;
    }
};

五、主函数调用

int main() {
    Calculator calc;
    std::string line;

    std::cout << "简易计算器(输入 'quit' 退出)\n";
    std::cout << "支持 + - * / () 和负数,例如: 3 + 5 * (2 - 1)\n";

    while (true) {
        std::cout << "> ";
        std::getline(std::cin, line);

        if (line == "quit" || line == "exit") {
            break;
        }

        try {
            double result = calc.evaluate(line);
            std::cout << "= " << result << "\n";
        } catch (const std::exception& e) {
            std::cout << "错误: " << e.what() << "\n";
        }
    }

    return 0;
}

六、关键点说明

  • 递归下降解析:将表达式按优先级拆解,每一层处理对应优先级的运算。
  • 负数处理:在
    factor()
    中识别
    -
    作为负号(而非减号),通过递归处理。
  • 括号支持:在
    factor()
    中处理
    (...)
    ,递归调用
    expression()
  • 错误处理:对除零、括号不匹配、非法字符等给出提示。
  • 空格跳过:提升用户体验,允许输入带空格。

七、测试用例

你可以测试以下表达式:

  • 3 + 5 * 2
    → 13
  • (3 + 5) * 2
    → 16
  • -3 + 4
    → 1
  • 10 / -2
    → -5
  • 3.5 + 2.1 * 2
    → 7.7

八、扩展建议

  • 支持更多运算符(如幂运算
    ^
  • 添加变量支持(用
    std::map
    存储)
  • 支持函数调用(如
    sin(30)
  • 改造成图形界面(结合 Qt 或其他库)

基本上就这些。这个项目不复杂,但涵盖了词法分析、语法解析、异常处理等核心编程技巧,是学习C++的好起点。

相关专题

更多
视频后缀名都有哪些
视频后缀名都有哪些

视频后缀名都有avi、mpg、mpeg、rm、rmvb、flv、wmv、mov、mkv、ASF、M1V、M2V、MPE、QT、VOB、RA、RMJ、RMS、RAM、等等。更多关于视频后缀名的相关知识,详情请看本专题下面的文章,php中文网欢迎大家前来学习。

3477

2023.10.31

C++ Qt图形开发
C++ Qt图形开发

本专题专注于 C++ Qt框架在图形界面开发中的应用,系统讲解窗口设计、信号与槽机制、界面布局、事件处理、数据库连接与跨平台打包等核心技能,通过多个桌面应用项目实战,帮助学员快速掌握 Qt 框架并独立完成跨平台GUI软件的开发。

68

2025.08.15

C++ 图形界面开发基础(Qt方向)
C++ 图形界面开发基础(Qt方向)

本专题系统讲解 使用 C++ 与 Qt 进行图形界面(GUI)开发的核心技能,内容涵盖 Qt 项目结构、窗口组件、信号与槽机制、事件处理、布局管理、资源管理,以及跨平台编译与打包流程。通过多个小型桌面应用实战案例,帮助学习者掌握从界面设计到功能实现的完整 GUI 开发能力。

57

2025.12.05

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

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

1468

2023.10.24

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

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

229

2024.02.23

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

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

85

2025.10.17

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

258

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

209

2023.09.04

Python GraphQL API 开发实战
Python GraphQL API 开发实战

本专题系统讲解 Python 在 GraphQL API 开发中的实际应用,涵盖 GraphQL 基础概念、Schema 设计、Query 与 Mutation 实现、权限控制、分页与性能优化,以及与现有 REST 服务和数据库的整合方式。通过完整示例,帮助学习者掌握 使用 Python 构建高扩展性、前后端协作友好的 GraphQL 接口服务,适用于中大型应用与复杂数据查询场景。

1

2026.01.21

热门下载

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

精品课程

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

共94课时 | 7.2万人学习

C 教程
C 教程

共75课时 | 4.1万人学习

C++教程
C++教程

共115课时 | 13.1万人学习

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

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