【大学课程设计】计算器实现(附源码)

news2025/4/3 21:57:59

🎈 作者:Linux猿

🎈 简介:CSDN博客专家🏆,华为云享专家🏆,Linux、C/C++、云计算、物联网、面试、刷题、算法尽管咨询我,关注我,有问题私聊!

🎈 关注专栏: 数据结构和算法成神路【精讲】优质好文持续更新中……🚀🚀🚀

🎈 欢迎小伙伴们点赞👍、收藏⭐、留言💬


目录

一、整体思路

二、思路解析

2.1 类设计

2.2 界面设计

2.3 表达式计算

三、计算器源码

四、总结


本篇文章使用 C++ 实现了一个简单的计算器,支持基本运算加减乘除,下面来详细讲解下 C++ 计算器的制作过程!

首先,先来看一下效果图:

图1 计算器动图演示

一、整体思路

整体的设计包含两个部分:界面的设计和表达式的计算。设计流程图如下所示:

图2 计算器流程图

二、思路解析

2.1 类设计

计算器类的设计如下所示:

/**
 * C++ 整数计算器
 */
class SimpleCalculator {

public:
    SimpleCalculator() {
        m['+'] = 1;
        m['-'] = 1;
        m['*'] = 2;
        m['/'] = 2;
        m['('] = 0;
        error = false;
    }

    //初始化操作
    void init() {
        system("chcp  65001"); //语言支持
        system("mode con cols=90 lines=30");//设置终端大小
        system("cls");
    }

    int calaulator();  //计算表达式
    int solve(int x,int y,char c);
    void hideCursor(); //隐藏光标
    void getCoord(int x, int y); //光标重定位,用于在光标处输出
    void color(int a);  //设置颜色
    void menu();
    bool isLegal(char ch);
    void printEdge();

private:
    string expStr;
    bool error;
    stack<int> s1;   //存储数字
    stack<char> s2;   //存储符号
    map<int,int> m;  //定义符号优先级
};

2.2 界面设计

界面的设计主要是主菜单的输出,实现如下所示:

//菜单
void SimpleCalculator::menu() {
    system("cls"); //清屏
    hideCursor();
    while(true) {
        system("cls"); //清屏
        printEdge();
        getCoord(55, 5); color(6); cout<<"计 算 器"; color(7);
        getCoord(28, 22); color(2); cout<<"说明:清除表达式请按 c 或 enter "; color(7);
        getCoord(28, 16); color(9); cout<<"计 算 结 果 :"; color(7);
        getCoord(28, 12); color(9); cout<<"请输入表达式:"; color(7);
        cin>>expStr;
        int ans = calaulator();
        if (!error) {
            getCoord(28, 16); color(9); cout<<"计 算 结 果 :"; color(7); cout<<"表达式错误!"; color(7);
        } else {
            getCoord(28, 16); color(9); cout<<"计 算 结 果 :"; color(7); cout<<ans; color(7);
        }

        while (true) {
            char ch = _getch();//选择
            if (ch == 'c' || ch == '\r') {
                break;
            }
        }
    }
}

2.3 表达式计算

输入表达式的计算通过使用两个栈,一个存储数字,一个存储字符,如下所示:

//计算表达式
int SimpleCalculator::calaulator() {
    int len = expStr.size();
    int i = 0;
    error = true;
    while (i < len) {
        if (!isLegal(expStr[i])) {
            error = false;
            return -1;
        }
        if(expStr[i] >= '0' && expStr[i] <= '9') { // 如果是数字
            int num = 0;
            while (expStr[i] >= '0' && expStr[i] <= '9'){
                num = num * 10 + expStr[i] -'0';
                i++;
            }
            s1.push(num);
        } else {
            if (expStr[i] == '('){
                s2.push(expStr[i]);
            } else if (expStr[i] == ')') {
                if(!s2.size()) {
                    error = false;
                    return -1;
                }
                while (s2.top() != '(') {
                    char ch = s2.top();
                    s2.pop();

                    if(!s1.size()) {
                        error = false;
                        return -1;
                    }
                    int x = s1.top();
                    s1.pop();

                    if(!s1.size()) {
                        error = false;
                        return -1;
                    }
                    int y = s1.top();
                    s1.pop();

                    s1.push(solve(y, x, ch));
                }
                s2.pop();
            } else {
                    while(s2.size() && m[s2.top()] >= m[expStr[i]]){
                        char ch = s2.top();
                        s2.pop();

                        if(!s1.size()) {
                            error = false;
                            return -1;
                        }

                        int x = s1.top();
                        s1.pop();

                        if(!s1.size()) {
                            error = false;
                            return -1;
                        }
                        int y = s1.top();
                        s1.pop();

                        s1.push(solve(y, x, ch));
                    }
                    s2.push(expStr[i]);
            }
            i++;
        }
    }

    //判断是否还有剩余的表达式
    while (s2.size()){
        char ch = s2.top();
        s2.pop();
        if(!s1.size()) {
            error = false;
            return -1;
        }
        int x = s1.top();
        s1.pop();
        if(!s1.size()) {
            error = false;
            return -1;
        }
        int y = s1.top();
        s1.pop();
        s1.push(solve(y, x, ch));
    }
    if (s2.size()) {
        error = false;
    }
    return s2.size() ? -1 : s1.top();
}

主要原理是通过两个栈,一个存储数字,一个存储字符,根据运算符优先级模拟表达式的计算,最后注意查看栈中是否还有剩余的表达式。

如果表达式正确,返回表达式计算的值,否则返回 -1。 

三、计算器源码

下面是C++计算器源码实现,如下所示:

#include <iostream>
#include <stack>
#include <string.h>
#include <map>
#include <stdio.h>
#include <conio.h>
#include <windows.h>
using namespace std;

/**
 * C++ 整数计算器
 */
class SimpleCalculator {

public:
    SimpleCalculator() {
        m['+'] = 1;
        m['-'] = 1;
        m['*'] = 2;
        m['/'] = 2;
        m['('] = 0;
        error = false;
    }

    //初始化操作
    void init() {
        system("chcp  65001"); //语言支持
        system("mode con cols=90 lines=30");//设置终端大小
        system("cls");
    }

    int calaulator();  //计算表达式
    int solve(int x,int y,char c);
    void hideCursor(); //隐藏光标
    void getCoord(int x, int y); //光标重定位,用于在光标处输出
    void color(int a);  //设置颜色
    void menu();
    bool isLegal(char ch);
    void printEdge();

private:
    string expStr;
    bool error;
    stack<int> s1;   //存储数字
    stack<char> s2;   //存储符号
    map<int,int> m;  //定义符号优先级
};

//设置颜色
void SimpleCalculator::color(int a)
{
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), a);
}

//光标重定位,用于在光标处输出
void SimpleCalculator::getCoord(int x, int y)
{
    COORD pos = { x,y };
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
}

//隐藏光标
void SimpleCalculator::hideCursor()
{
    CONSOLE_CURSOR_INFO cursor= { 1, 0 };
    SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor);
}

//进行计算
int SimpleCalculator::solve(int x, int y, char c){
    int ret = 0;
    if (c == '*') {
        ret = x*y;
    } else if (c == '/'){
        ret = x/y;
    } else if (c == '+'){
        ret = x+y;
    } else if (c == '-'){
        ret = x-y;
    }
    return ret;
}

//判断字符是否合法
bool SimpleCalculator::isLegal(char ch) {
    if (ch >= '0' && ch <= '9') {
        return true;
    }

    if (ch == '*' || ch == '/' || ch == '+' || ch == '-') {
        return true;
    }

    if (ch == '(' || ch == ')') {
        return true;
    }
    return false;
}

//计算表达式
int SimpleCalculator::calaulator() {
    int len = expStr.size();
    int i = 0;
    error = true;
    while (i < len) {
        if (!isLegal(expStr[i])) {
            error = false;
            return -1;
        }
        if(expStr[i] >= '0' && expStr[i] <= '9') { // 如果是数字
            int num = 0;
            while (expStr[i] >= '0' && expStr[i] <= '9'){
                num = num * 10 + expStr[i] -'0';
                i++;
            }
            s1.push(num);
        } else {
            if (expStr[i] == '('){
                s2.push(expStr[i]);
            } else if (expStr[i] == ')') {
                if(!s2.size()) {
                    error = false;
                    return -1;
                }
                while (s2.top() != '(') {
                    char ch = s2.top();
                    s2.pop();

                    if(!s1.size()) {
                        error = false;
                        return -1;
                    }
                    int x = s1.top();
                    s1.pop();

                    if(!s1.size()) {
                        error = false;
                        return -1;
                    }
                    int y = s1.top();
                    s1.pop();

                    s1.push(solve(y, x, ch));
                }
                s2.pop();
            } else {
                    while(s2.size() && m[s2.top()] >= m[expStr[i]]){
                        char ch = s2.top();
                        s2.pop();

                        if(!s1.size()) {
                            error = false;
                            return -1;
                        }

                        int x = s1.top();
                        s1.pop();

                        if(!s1.size()) {
                            error = false;
                            return -1;
                        }
                        int y = s1.top();
                        s1.pop();

                        s1.push(solve(y, x, ch));
                    }
                    s2.push(expStr[i]);
            }
            i++;
        }
    }

    //判断是否还有剩余的表达式
    while (s2.size()){
        char ch = s2.top();
        s2.pop();
        if(!s1.size()) {
            error = false;
            return -1;
        }
        int x = s1.top();
        s1.pop();
        if(!s1.size()) {
            error = false;
            return -1;
        }
        int y = s1.top();
        s1.pop();
        s1.push(solve(y, x, ch));
    }
    if (s2.size()) {
        error = false;
    }
    return s2.size() ? -1 : s1.top();
}

//打印边框
void SimpleCalculator::printEdge() {
    int x = 10, y = 2;
    for(int i = x; i <= 110; ++i) {
        getCoord(i, y); color(4); cout<<"=";
    }

    x = 10, y = 28;
    for(int i = x; i <= 110; ++i) {
        getCoord(i, y); color(4); cout<<"=";
    }

    x = 10, y = 3;
    for(int i = y; i <= 27; ++i) {
        getCoord(x, i); color(4); cout<<"||";
    }

    x = 109, y = 3;
    for(int i = y; i <= 27; ++i) {
        getCoord(x, i); color(4); cout<<"||";
    }
}

//菜单
void SimpleCalculator::menu() {
    system("cls"); //清屏
    hideCursor();
    while(true) {
        system("cls"); //清屏
        printEdge();
        getCoord(55, 5); color(6); cout<<"计 算 器"; color(7);
        getCoord(28, 22); color(2); cout<<"说明:清除表达式请按 c 或 enter "; color(7);
        getCoord(28, 16); color(9); cout<<"计 算 结 果 :"; color(7);
        getCoord(28, 12); color(9); cout<<"请输入表达式:"; color(7);
        cin>>expStr;
        int ans = calaulator();
        if (!error) {
            getCoord(28, 16); color(9); cout<<"计 算 结 果 :"; color(7); cout<<"表达式错误!"; color(7);
        } else {
            getCoord(28, 16); color(9); cout<<"计 算 结 果 :"; color(7); cout<<ans; color(7);
        }

        while (true) {
            char ch = _getch();//选择
            if (ch == 'c' || ch == '\r') {
                break;
            }
        }
    }
}

//主函数
int main(){
    SimpleCalculator obj;
    obj.menu();
    return 0;
}

四、总结

计算器的实现的重点在输入表达式的计算,通过两个栈,一个存储字符,一个存储输入的数字,实现了对表达式的计算。

⭐优质专栏推荐⭐

 数据结构和算法成神路【精讲】

C/C++面试通关【精讲】

 Linux技术和原理 


🎈 感觉有帮助记得「一键三连支持下哦!有问题可在评论区留言💬,感谢大家的一路支持!🤞猿哥将持续输出「优质文章回馈大家!🤞🌹🌹🌹🌹🌹🌹🤞


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/5547.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

6.Paddle Graph Learning (PGL)图学习之图游走类模型[系列四]

Paddle Graph Learning (PGL)图学习之图游走类模型[系列四] 更多详情参考&#xff1a;Paddle Graph Learning 图学习之图游走类模型[系列四] https://aistudio.baidu.com/aistudio/projectdetail/5002782?contributionType1 相关项目参考&#xff1a; 关于图计算&图学习…

路由规划——运输距离的估算

运输距离的估算1. 常规的拟合距离1.1 欧氏距离1. 2 球面距离拟合2. 一种改进的球面距离拟合参考文献在进行路径规划时&#xff0c;需要获取点与点之间的距离&#xff0c;点之间的距离通常是通过坐标或者经纬度计算得到&#xff0c;可分为拟合距离和导航距离两类。导航距离顾名思…

基础二叉树及其高频面试题

目录 一、树的概念及其结构 1.1 树的概念 1.2 树的相关概念 1.3 树的表示法 二、二叉树的概念及其结构 2.1 概念 2.2 特殊二叉树 2.3 二叉树的性质 2.4 二叉树的存储结构 顺序存储 链式存储 三、链式二叉树 3.1 遍历方式 深度优先遍历:DFS 层序遍历:BFS(广度优先…

【附源码】Python计算机毕业设计社区防疫信息管理系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

Debian11中 Nginx1.22.1 php8.1.12 Mariadb10.5.15的安装

起因&#xff1a;我之前发的关于LEMP的搭建的文章&#xff0c;已经有3年9个月了&#xff0c;各个软件的版本更新了比较多。最主要的是&#xff0c;CentOS系统终止了&#xff0c;我也完全更换到了Debian系统之上。这里重新搭建了一下&#xff0c;主要是计划结合frp&#xff0c;构…

Vue | Vue.js 全家桶 Pinia状态管理

&#x1f5a5;️ Vue .js专栏&#xff1a;Node.js Vue.js 全家桶 Pinia状态管理 &#x1f9d1;‍&#x1f4bc; 个人简介&#xff1a;一个不甘平庸的平凡人&#x1f36c; ✨ 个人主页&#xff1a;CoderHing的个人主页 &#x1f340; 格言: ☀️ 路漫漫其修远兮,吾将上下而求索☀…

[基础服务] [操作系统] 类Linux的文件和目录

&#x1f341;简介 在奔腾70年代的中美建交之际,UNIX 也逐渐展露头角(也有说是60年代末),十五年后Windows诞生了,又过了五年Linux横空出世三大主流操作系统直到现在呈现三足鼎立之势~ 出生时间是&#xff1a; UNIX(70年代初) > Windows(80年代中) > Linux (90年代初) 可以…

基于微信小程序的电影院票务系统设计与实现-计算机毕业设计源码+LW文档

小程序开发说明 开发语言&#xff1a;Java 框架&#xff1a;ssm JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09; 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Mav…

HCIP-Datacom OSPF进阶(二)最常用的路由协议 OSPF各种LSA作用详解

目录 OSPF路由计算&#xff1a; LSA头部信息&#xff1a; Router-LSA&#xff08;1类&#xff09;&#xff1a; 一类LSA&#xff1a; 一类LSA可以描述四种链路类型&#xff1a; Network-LSA&#xff08;2类&#xff09;&#xff1a; 二类&#xff1a; IR、ABR、ASBR是什…

【HTML实战】把专属于她的爱心代码放在自己的网站上是一种什么体验?

一、 写在前面的话 看多了李洵的炫酷爱心&#xff0c;今天来点不一样的爱心代码。需要李洵的炫酷爱心代码请看我的上一篇文章。 最近随着电视剧《点燃我温暖你》的火热播出&#xff0c;剧中帅气学霸李洵的炫酷爱心代码也迅速火出了圈&#xff0c;作为一个喜欢动手实践的我来说…

力扣206 - 反转链表【校招面试高频考题】

乾坤大挪移~一、题目描述二、思路分析1、头插2、三指针迭代三、整体代码展示【需要自取】1、头插2、三指针迭代四、总结与提炼一、题目描述 原题传送门 给你单链表的头节点 head &#xff0c;请你反转链表&#xff0c;并返回反转后的链表。 示例 1&#xff1a; 输入&#xf…

【Redis】CentOs 虚拟机安装 Redis 缓存数据库

一、使用案例&#xff1a; 以淘宝为例&#xff0c;几个人一起登入淘宝&#xff0c;去检索男装&#xff0c;这几个人的访问都得到相同的结果。这时&#xff0c;我们就可以考虑将男装缓存在一个地方&#xff0c;而不是再去访问数据库&#xff0c;这时&#xff0c;就是我们 Redis…

ctfshow文件包含

web78 源码&#xff1a; if(isset($_GET[file])){$file $_GET[file];include($file); }else{highlight_file(__FILE__);//高亮显示当前文件内容 }解法一 - php://input # http://challenge.ctf.show/?filephp://input # [POST DATA] <?php system(ls)?> <?php…

基于可视图法(VG)的路径规划算法简述

可视图法路径规划&#xff08;VG&#xff09; 可视图法由Lozano-Perez和Wesley于1979年在论文&#xff1a;《An Algorithm for Planning Collision-Free Paths among Polyhedral Obstacles.》中提出。 基于可视图法路径规划算法主要包括以下两个步骤&#xff1a;①可视图的构建…

第二章 环境的选择和安装

1、开发环境操作系统 1.1 选择Windows、Mac or Linux 首先明确一点&#xff1a;我们的首要目的是要快速上手使用Elasticsearch&#xff08;以下简称ES&#xff09;&#xff0c;安装和部署ES并非重点&#xff0c;企业中真正需要你去安装的可能性或者机会非常小。大家可以想一想…

C++运算符重载

运算符重载运算符重载一、重载‘’运算符1.非成员函数版本重载2.成员函数版本二、重载关系运算符三、重载左移运算符四、重载下标运算符五、重载赋值运算符六、重载new和delete1.重载2.内存池七、重载括号运算符八、重载一元运算符运算符重载 C将运算符重载扩展到自定义的数据…

23 张图细讲使用 Devtron 简化 K8S 中应用开发

23 张图细讲使用 Devtron 简化 K8S 中应用开发 在本文中&#xff0c;您将学习如何在多集群环境中使用 Devtron 在 K8S 上进行应用开发。 https://devtron.ai/ Devtron 附带用于构建、部署和管理微服务的工具。它通过提供直观的 UI 和 Helm 图表支持来简化 K8S 上的部署。今天&a…

Java数据结构 | 模拟实现优先级队列

目录 一、前言 二、堆模拟实现优先级队列 2.1 堆的概念 2.2 堆的性质 2.3 堆的存储方式 2.4 堆的创建 一、前言 在前面我们学习过队列&#xff0c;队列是一种先进先出(FIFO)的数据结构&#xff0c;但有些情况下&#xff0c;操作的数据可能带有优先级&#xff0c;一般出队…

mybatis-plus代码生成工具

mybatis-plus版本升级尝试遇到的问题 若遇到高版本&#xff1a;【全局覆盖已有文件的配置已失效&#xff0c;已迁移到策略配置中】or【覆盖已有文件&#xff08;已迁移到策略配置中&#xff0c;3.5.4版本会删除此方法&#xff09;】这句话&#xff0c;可参考文章中解决办法 参考…

python机器人编程——基于单目视觉、固定场景下的自动泊车(下)

目录一、前言二、主要思路step0 设定一个中间位置step1 掉转马头step2 直线匀速前进step3 调整姿态step4 视觉匹配三、效果四、全篇总结一、前言 本篇来讨论一下在固定场景下&#xff0c;如何仅通过单目视觉&#xff0c;实现差速小车的自动停靠&#xff0c;这种方式实现成本比…