当前位置: 首页 > news >正文

C++使用栈实现简易计算器(支持括号)

使用C++实现,使用系统自带stac

  1. 支持括号处理
  2. 支持小数计算
  3. 支持表达式有效性检查
  4. 支持多轮输入。

运行结果示例:

代码:

#include <iostream>
#include <stack>
#include <string>
using namespace std;//判断是否是数字字符
int isNumber(char c)
{if(c>='0' && c<='9')return 1;elsereturn 0;
}//判断字符是否是操作符,这里仅支持+、-、*、/
int isOperator(char c)
{if(c=='+' || c=='-' || c=='*' || c=='/')return 1;elsereturn 0;
}//获取操作符的优先级
int priority(char op)
{if(op=='+' || op=='-')return 1;else if(op=='*' || op=='/')return 2;else if(op=='(')return 0;return 0;
}//有效性判断1:判断是否缺操作符,缺操作符返回1,否则返回0
int isLessOperator(char* p)
{int i = 0,j,k;//考虑一下几种情况://1.数字之间没有操作符,例如 2 3 + 4//2.(前面是数字,例如 2(2+3),这里不支持省略乘号//3.)后面是数字,例如 (2+3)3,这里不支持省略乘号while(p[i]!='\0'){if(p[i]==' '){j = i-1; while(j>=0 && p[j]==' ') j--; //往前遍历,直到遇到非空格k = i+1;while(p[k]==' ') k++;//往后遍历,直到遇到非空格if(j>=0 && isNumber(p[j]) && isNumber(p[k])) //空格前后都是数字return 1; //说明缺少操作符,返回1}else if(p[i]=='('){j = i-1;while(j>=0){if(isOperator(p[j]) || p[j]=='(')break;else if(p[j]==' ')//跳过空格{j--;continue;}else if(isNumber(p[j]))return 1;else if(p[j]==')')//出现 )(这种情况,((这种情况在这里不讨论,会在括号匹配函数中处理return 1; elsereturn 2; //这里可能出现非数字、非操作符、非括号}}else if(p[i]==')'){j = i+1;while(p[j]!='\0'){if(isNumber(p[j]))return 1;else if(isOperator(p[j]))break;else if(p[j]==' '){j++;continue;}else if(p[j]==')')break;else if(p[j]=='(')return 1;elsereturn 2; //出现非数字、非操作符、非括号}}i++;}return 0;
}
//有效性判断2:判断括号是否匹配,匹配返回1,否则返回0
int isComplete(char* p)
{int i=0;int nmb = 0; //(的个数while(p[i]!='\0'){if(p[i]=='(')nmb++;else if(p[i]==')')nmb--;if(nmb<0)return 0;i++;}if(nmb != 0)return 0;return 1;
}
//有效性判断3:是否是连续操作符(负数操作时必须用括号括起来),出现连续操作符返回1,否则返回0
int isMoreOperator(char* p)
{int i=0,j;while(p[i]!='\0'){if(isOperator(p[i])){j=i-1; //向前判断while(j>=0){if(p[j]==' '){j++;continue;}else if(isOperator(p[j]))return 1;else if(isNumber(p[j]))break;else if(p[j]==')'||p[j]=='(') //是括号break;elsereturn 2; //非数字、非空格、非括号、非操作符外的其他符号}}i++;}return 0; //
}//有效性判断4:判断是否是空括号,如2+()+3
int isEmptyKh(char* p)
{int i=0,j;while(p[i]!='\0'){if(p[i]==')'){j= i-1;while(j>=0){if(p[j]=='(')return 1;else if(p[j]==' ')j--;elsebreak;}}i++;}return 0;
}
//判断表达式的有效性
int isValid(char* p)
{int res = 1,t;int len = strlen(p);if(p[len-1]=='=' || p[len-1]=='#') //以=或者#结尾p[len-1]=0;t = isLessOperator(p);if(t == 1){printf("缺少操作符!\n");res = 0;}else if(t == 2){printf("出现符数字、空格、操作符、括号之外的符号\n");res = 0;}t = isComplete(p);if(t==0){printf("括号不匹配\n");res = 0;}t = isMoreOperator(p);if(t == 1){printf("有多个连续运算符\n");res = 0;}else if(t==2){printf("出现符数字、空格、操作符、括号之外的符号\n");res = 0;}t = isEmptyKh(p);if(t==1){printf("有空括号\n");res = 0;}return res;
}
//执行某个运算
int getResult(double a,double b,char c,double *v)
{if(c=='+'){*v = a+b;return 1;}else if(c=='-'){*v = a-b;return 1;}else if(c=='*'){*v = a*b;return 1;}else if(c=='/'){if(b==0)return 0;*v = a/b;return 1;}return 0;
}
//计算
int Caculate(char* p,double *res)
{stack<double> data; //数据stack<char> oper;  //操作符int i=0;double a,b,c;char op1,op2;double mi=1; while(p[i]!='\0'){if(isNumber(p[i])) //当前字符是数字,则读取后续的数字,并入栈{a = p[i]-'0';i++;//继续读取后面的数字while(isNumber(p[i])){a = a*10+(p[i]-'0');i++;}if(p[i]=='.'){i++;//处理小数部分mi = 10;while(isNumber(p[i])){a = a + (p[i]-'0')/mi;mi*=10;i++;}}data.push(a);//数据入栈}else if(isOperator(p[i])) //是运算符{if(oper.empty()){oper.push(p[i]);i++;}else{op1 = oper.top(); //获取栈顶运算符//比较op1和p[i]的优先级,如果op1的优先级高于p[i],则数据出栈并进行计算if(priority(op1) >= priority(p[i])){b = data.top(); //后操作数data.pop();a = data.top(); //前操作数data.pop();oper.pop(); //运算符出栈if(getResult(a,b,op1,&c)){if(!oper.empty()){op2 = oper.top();if(op2=='-' && c<0){oper.pop();oper.push('+');data.push(-c); //减负数等价于加正数oper.push(p[i]);}else{data.push(c); //新数据入栈oper.push(p[i]); //操作符入栈}}else{data.push(c); //新数据入栈oper.push(p[i]); //操作符入栈}i++;}else{printf("除数为0\n");return 0;}}else{oper.push(p[i]); //操作符入栈i++;}}}else if(p[i]=='('){oper.push(p[i]); //入栈i++;}else if(p[i]==')') //出栈计算{op1 = oper.top();if(op1=='('){oper.pop();//(出栈i++;}else {b = data.top(); //获取栈顶元素,该数为后操作数data.pop();a = data.top();data.pop();oper.pop(); //运算符出栈if(getResult(a,b,op1,&c)){if(!oper.empty()){op2 = oper.top();if(op2=='-' && c< 0){oper.pop();oper.push('+');data.push(-c);}elsedata.push(c);}elsedata.push(c);//新数据入栈}else{printf("除数为0\n");return 0;}}} else if(p[i]==' ')i++;}//处理栈内数据while(!oper.empty()){b = data.top();data.pop();a = data.top();data.pop();op1 = oper.top();oper.pop();if(getResult(a,b,op1,&c)){if(!oper.empty()){op2 = oper.top();if(op2 == '-' && c< 0){oper.pop();oper.push('+');data.push(-c);}elsedata.push(c);}elsedata.push(c);}else{printf("除数为0\n");return 0;}}if(data.size() !=1 ){printf("error\n");return 0;}*res = data.top();data.pop();return 1;
}int main()
{char buf[100]={0};int op;while(1){printf("输入表达式:\n");cin.getline(buf,100); //读取一行double res = 0;if(isValid(buf)){if(Caculate(buf,&res))printf("%g\n",res);}printf("是否继续(1:继续   2:退出):");scanf("%d",&op);if(op == 2)break;getchar(); //吸收回车符}return 0;
}

相关文章:

  • 服务器操作系统有哪些
  • 小样本分割的新视角,Learning What Not to Segment【CVPR 2022】
  • LabVIEW开发双目立体系统猪重估算
  • 在RK3588Ubuntu中运行qtCreator报错
  • centos 7 kafka2.6单机安装及动态认证SASL SCRAM配置
  • react条件渲染
  • 如何将word格式的文档转换成markdown格式的文档
  • 如何理解AutoGPT
  • android 给view添加进出动画
  • 206. 反转链表、Leetcode的Python实现
  • 83. 删除排序链表中的重复元素、Leetcode的Python实现
  • nextcloud 安装配置教程
  • C#学习系列之密闭类、接口、结构和类
  • 栅栏密码fence cypher
  • springboot配置https
  • 【108天】Java——《Head First Java》笔记(第1-4章)
  • 30秒的PHP代码片段(1)数组 - Array
  • Akka系列(七):Actor持久化之Akka persistence
  • es的写入过程
  • iOS筛选菜单、分段选择器、导航栏、悬浮窗、转场动画、启动视频等源码
  • java2019面试题北京
  • Twitter赢在开放,三年创造奇迹
  • 对话 CTO〡听神策数据 CTO 曹犟描绘数据分析行业的无限可能
  • 函数式编程与面向对象编程[4]:Scala的类型关联Type Alias
  • 前端_面试
  • 容器化应用: 在阿里云搭建多节点 Openshift 集群
  • 协程
  • 一些关于Rust在2019年的思考
  • 转载:[译] 内容加速黑科技趣谈
  • Linux权限管理(week1_day5)--技术流ken
  • zabbix3.2监控linux磁盘IO
  • ​LeetCode解法汇总2182. 构造限制重复的字符串
  • $$$$GB2312-80区位编码表$$$$
  • (14)目标检测_SSD训练代码基于pytorch搭建代码
  • (带教程)商业版SEO关键词按天计费系统:关键词排名优化、代理服务、手机自适应及搭建教程
  • (附源码)spring boot车辆管理系统 毕业设计 031034
  • (附源码)springboot 校园学生兼职系统 毕业设计 742122
  • (六)什么是Vite——热更新时vite、webpack做了什么
  • (转)视频码率,帧率和分辨率的联系与区别
  • .Net8 Blazor 尝鲜
  • @Autowired自动装配
  • [2017][note]基于空间交叉相位调制的两个连续波在few layer铋Bi中的全光switch——
  • [BUAA软工]第一次博客作业---阅读《构建之法》
  • [BZOJ3223]文艺平衡树
  • [C/C++随笔] char与unsigned char区别
  • [C++]拼图游戏
  • [CQOI 2010]扑克牌
  • [C和指针].(美)Kenneth.A.Reek(ED2000.COM)pdf
  • [Dxperience.8.*]报表预览控件PrintControl设置
  • [ERROR ImagePull]: failed to pull image k8s.gcr.io/kube-controller-manager失败
  • [Java] 图说 注解
  • [Kubernetes]8. K8s使用Helm部署mysql集群(主从数据库集群)
  • [LeeCode]—Wildcard Matching 通配符匹配问题
  • [LeetCode] 178. 分数排名
  • [LeetCode] Max Points on a Line