【C/C++ 08】简单计算器

一、题目

输入算术表达式,可包含空格,检查算术表达式的合法性,若算术表达式不合法,打印错误类型,若合法,则进行运算,打印计算结果。

二、算法

1. 将输入的算术表达式字符串去除空格。

2. 检查输入的算术表达式的合法性,判断算式首字符是否合法(只能是前括号或正负号),判断括号是否匹配,判断连续字符是否合法(运算符后面可跟左括号,右括号后面可跟运算符,左括号后面可跟加减号表正负,左右括号之间不能直接相连,数字后面不能直接跟左括号)。

3. 构造符号栈和数据栈对合法的算术表达式进行计算,计算的过程就是从数据栈取出两个数据和符号栈取出一个数据,然后计算得到一个结果,再将结果压入数据栈。

三、代码

#define _CRT_SECURE_NO_WARNINGS 1#include <iostream>
#include <vector>
#include <stack>
using namespace std;vector<char> g_opt = { '+', '-', '*', '/'};void RemoveSpaces(char* input)
{for (int i = 0; i < strlen(input); ++i){if (input[i] == ' '){for (int j = i; j < strlen(input); ++j){input[j] = input[j + 1];}--i;}}
}bool CheckInput(char* input)
{stack<char> bracket;	// 用于判断括号的合法性for (int i = 0; i < strlen(input); ++i){if (!isdigit(input[i])){if (find(g_opt.begin(), g_opt.end(), input[i]) == g_opt.end()&& input[i] != '(' && input[i] != ')'){cout << "存在非法字符 " << input[i];return false;}if (input[i] == '('){bracket.push(input[i]);}else if (input[i] == ')'){if (bracket.empty()){cout << "括号不匹配";return false;}else{bracket.pop();}}// 第一个字符必须是数字或正负号或左括号if (i == 0 && input[i] != '+' && input[i] != '-' && input[i] != '('){cout << "首字符错误";return false;}if (!isdigit(input[i + 1])){if (input[i] == '('){// 左括号后面可以跟加减表示正负if (input[i + 1] == '*' || input[i + 1] == '/' || input[i + 1] == ')'){cout << "出现连续符号 " << input[i + 1];return false;}}else if (input[i] == ')'){// 有括号后面不能直接跟前括号,可以跟操作符if (input[i + 1] == '('){cout << "出现连续符号 " << input[i + 1];return false;}}else{// 操作符后面可以跟左括号if (input[i + 1] != '('){cout << "出现连续符号 " << input[i + 1];return false;}}}}else{// 数字后面不能直接跟左括号if (input[i + 1] == '('){cout << "括号位置错误 " << input[i + 1];return false;}}}if (!bracket.empty()){cout << "括号不匹配";return false;}return true;
}bool PopCal(stack<int>& datas, stack<char>& symbols)
{if (datas.size() < 2 || symbols.empty())return false;if (symbols.top() == '('){symbols.pop();return false;}int x = datas.top();datas.pop();int y = datas.top();datas.pop();char opt = symbols.top();symbols.pop();int res = (unsigned int)-1;if (opt == '+')res = x + y;else if (opt == '-')res = x - y;else if (opt == '*')res = x * y;else if (opt == '/')res = x / y;datas.push(res);return true;
}int Calculate(char* input)
{// 数据栈和符号栈stack<int> datas;stack<char> symbols;int flag = 1;	// 1表示正,-1表示负数for (int i = 0; i < strlen(input); ++i){if (isdigit(input[i])){// 将连续数字字符转为整型数据存入数据栈string digit = "";digit += input[i];while (isdigit(input[i + 1])){++i;digit += input[i];}int num = atoi(digit.c_str());datas.push(num * flag);flag = 1;// 数据压栈后发现栈顶是乘除号,直接进行计算if (!symbols.empty() && (symbols.top() == '*' || symbols.top() == '/'))PopCal(datas, symbols);}else{// 左括号的优先级最高if (input[i] == '('){symbols.push(input[i]);continue;}// 判断负号if (i == 0 || input[i - 1] == '('){if (input[i] == '-')flag = -1;continue;}if (input[i] == '*' || input[i] == '/'){// 乘除符号直接压入符号栈symbols.push(input[i]);}else if (input[i] == '+' || input[i] == '-'){// 若符号栈存有加减号未计算,先计算再将加减号压栈if (!symbols.empty() && (symbols.top() == '+' || symbols.top() == '-')){PopCal(datas, symbols);}symbols.push(input[i]);}else if (input[i] == ')'){if (symbols.top() == '('){// 表示括号括住了数字,而不是表达式symbols.pop();}else{// 循环出栈计算,直到遇到左括号while (PopCal(datas, symbols)){}}}}}// 循环出栈计算while (PopCal(datas, symbols)){}return datas.top();
}int main()
{while (1){char input[128];cout << "请输入算术表达式:";fgets(input, sizeof(input), stdin);input[strlen(input) - 1] = 0;RemoveSpaces(input);if (strcmp(input, "exit") == 0)break;if (!CheckInput(input)){cout << ",表达式输入格式错误,请重新输入!" << endl;continue;}int res = Calculate(input);cout << input << " = " << res << endl;}return 0;
}

四、测试

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

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

相关文章

电源模块欠压保护点测试方法分享 纳米软件

电源欠压保护原理 欠压保护是指当电源电压低于一定值时&#xff0c;电源的保护功能会及时断开电路&#xff0c;避免设备受到损坏。电源欠压保护一般是通过一个或多个传感器来检测电压&#xff0c;当电压低于设定值时就会触发电源的保护功能&#xff0c;断开电路&#xff0c;保护…

猫用空气净化器真的能除菌吗?除毛可以用宠物空气净化器吗?

猫咪给我们带来了无尽的欢乐&#xff0c;但它们换毛时家里到处都是猫毛。我们会在地板、沙发上发现一大堆&#xff0c;甚至衣服也难逃其影响。这些浮毛中可能携带着微生物和尘螨等。对于免疫力较低的老年人、孩子和孕妇来说&#xff0c;他们更容易感染这些微生物。而对于鼻炎患…

[Tomcat问题]--使用Tomcat 10.x部署项目时,出现实例化Servlet类[xxx]异常

[Tomcat问题]–使用Tomcat 10.x部署项目时&#xff0c;出现实例化Servlet类[xxx]异常 本片博文在知乎同步更新 环境 OS: Windows 11 23H2Java Version: java 21.0.1 2023-10-17 LTSIDE: IntelliJ IDEA 2023.3.3Maven: Apache Maven 3.9.6Tomcat: Tomcat 10.1.18 ReleasedSer…

vulhub中Adminer远程文件读取漏洞复现(CVE-2021-43008)

Adminer是一个PHP编写的开源数据库管理工具&#xff0c;支持MySQL、MariaDB、PostgreSQL、SQLite、MS SQL、Oracle、Elasticsearch、MongoDB等数据库。 在其版本1.12.0到4.6.2之间存在一处因为MySQL LOAD DATA LOCAL导致的文件读取漏洞。 参考链接&#xff1a; https://gith…

JAVA Studynote(7-8)

JAVA Studynote(7-8) 1.DOS系统 ​ *接受指令 *解析指令 *执行指令 2.相对路径和绝对路径 *相对路径 ​ *从当前目录开始定位&#xff0c;形成的一个路径 *绝对路径 ​ *从顶级目录d&#xff0c;开始定位&#xff0c;形成的路径 ​ *示例&#xff1a; 3.常用DOS指令 …

12种算法优化CNN-BiLSTM-Attention多特征输入单步预测,机器学习预测全家桶,持续更新,MATLAB代码...

截止到本期&#xff0c;一共发了12篇关于机器学习预测全家桶MATLAB代码的文章。参考文章如下&#xff1a; 1.五花八门的机器学习预测&#xff1f;一篇搞定不行吗&#xff1f; 2.机器学习预测全家桶&#xff0c;多步预测之BiGRU、BiLSTM、GRU、LSTM&#xff0c;LSSVM、TCN、CNN&…

【lesson8】高并发内存池Central Cache层释放内存的实现

文章目录 Central Cache层释放内存的流程Central Cache层释放内存的实现 Central Cache层释放内存的流程 当thread_cache过长或者线程销毁&#xff0c;则会将内存释放回central cache中的&#xff0c;释放回来时–use_count。当use_count减到0时则表示所有对象都回到了span&am…

备战蓝桥杯---数据结构与STL应用(进阶4)

今天主要围绕并查集的一些今典题目展开&#xff1a; 在这里&#xff0c;我们把逻辑真的组合&#xff0c;用并查集即可。一开始&#xff0c;我觉得把a,b,c等价&#xff0c;把第一个赋a,接下来推即可&#xff0c;但这样在判断矛盾时还需要选择合适的点find&#xff0c;于是我们把…

深度学习(10)-Keras项目详解(递归神经网络)

一.递归神经网络基础概念 递归神经网络(Recursive Neural Network, RNN)可以解决有时间序列的问题&#xff0c;处理诸如树、图这样的递归结构。 CNN主要应用在计算机视觉CV中&#xff0c;RNN主要应用在自然语言处理NLP中。 1.h0&#xff0c;h1.....ht对应的是不同输入得到的中…

debian12 解决 github 访问难的问题

可以在 /etc/hosts 文件中添加几个域名与IP对应关系&#xff0c;从而提高 github.com 的访问速度。 据搜索了解&#xff08;不太确定&#xff09;&#xff0c;可以添加这几个域名&#xff1a;github.com&#xff0c;github.global.ssl.fastly.net&#xff0c;github.global.fa…

银河麒麟 aarch64 Mysql环境安装

一、操作系统版本信息 组件版本操作系统Kylin V10 (SP3) /(Lance)-aarch64-Build23/20230324Kernel4.19.90-52.22.v2207.ky10.aarch64MySQLmysql-8.3.0JDK1.8.0_312 二、MySQL下载 官网下载地址&#xff1a;https://dev.mysql.com/downloads/mysql/ 三、MySQL 安装 3.1 删…

年终奖,还得是腾讯。。。

腾讯年终奖 什么是真正的好公司&#xff1f; 一年到头&#xff0c;出不了几次裁员等劳务纠纷的吃瓜新闻。 只有到年底了&#xff0c;才因为年终奖远高于行业水平&#xff0c;实在没法低调了&#xff0c;"被迫"上热搜。 最近网友爆料了腾讯头牌部门的年终奖&#xff1…

JavaSE——流程控制-循环结构(for循环、while循环、小案例、do-while循环、死循环、循环嵌套)

目录 for循环 while循环 小案例 do-while循环 死循环 循环嵌套 for循环 for(int i 0; i < 5; i) {System.out.println("Hello world"); } 执行的流程&#xff1a; 循环一开始&#xff0c;执行int i0 一次。此时 i 0&#xff0c;接着计算机执行循环条件…

下载RTSP播放器

1.网站1 2.海康播放器 在海康官网上选择【服务支持】【工具软件】&#xff0c;往下滚动&#xff0c;打开VSPlayer_x64

陪女朋友学习计算机二级之栈和队列

栈 栈(堆栈)的定义 堆栈又名栈(stack),它是一种线性表。限定仅在表尾进行插入和删除操作的线性表。是一种后进先出的线性表. 空栈:不含任何元素的空表。 栈顶和栈底 进行插入和删除的这一端(表尾)被称为栈顶&#xff0c;相对地&#xff0c;把另一端称为栈底。 入栈和出栈 …

大小姐驾到!高德地图联合《王者荣耀》推出孙尚香导航语音包

“大小姐驾到&#xff01;统统闪开&#xff01;”如果你是一个手游爱好者&#xff0c;多半会对这句话耳熟能详&#xff0c;来自于国内手游界顶流《王者荣耀》中的高人气角色——孙尚香&#xff0c;并成为一代玩家们的记忆。 如今&#xff0c;随着高德地图与《王者荣耀》达成合…

java之ReentrantLock

在讲RentrantLock之前需要先讲一下AQS和LockSupport&#xff0c;因为rentrantLock底层是用AQS实现的&#xff0c;而AQS中获取阻塞和唤醒底使用LockSupport实现的。 1、LockSupport实现 下面代码中&#xff0c;LockSupport.park方法是当前线程等待&#xff0c;直到获得许可&am…

Istio-解决Zipkin对项目的侵入性问题

Istio采用SideCar模式注入的Enovy代理在某些情况下不能完全解决对项目的无侵入性&#xff0c;比如需要用到Istio的链路追踪功能的时候。需要在代码中手动注入链路追踪需要的header&#xff0c;这样就出现了Istio对业务功能的侵入性。 istio服务网格的调用链跟踪需要依赖在服务之…

大数据环境搭建(一)-Hive

1 hive介绍 由Facebook开源的,用于解决海量结构化日志的数据统计的项目 本质上是将HQL转化为MapReduce、Tez、Spark等程序 Hive表的数据是HDFS上的目录和文件 Hive元数据 metastore&#xff0c;包含Hive表的数据库、表名、列、分区、表类型、表所在目录等。 根据Hive部署模…

axios二次封装用法

axios二次封装 一、request.js import axios from axios import router from "/router";const request axios.create({baseURL: http://localhost:9090,timeout: 5000 })// request 拦截器 // 可以自请求发送前对请求做一些处理 // 比如统一加token&#xff0c;对…