括号匹配,实现简单计算器(加减乘除,小括号)
括号匹配算法
利用栈先进后出的特性,思路分三步:
1.遇到左括号,直接入栈,继续向后遍历;
2.遇到右括号,
(1).如果栈为空,说明无对应左括号,则返回表达式不匹配;
(2).如果栈不为为空,将栈顶元素弹出判断是否是相匹配的括号;
如果匹配,将栈顶元素弹出,继续遍历;如果不匹配,说明不是同类括号,直接返回表达式不匹配。
3.遍历到表达式末尾,如果栈中有剩余元素,说明存在多余左括号,返回表达式不匹配;如果栈为空,返回表达式匹配。
测试样例:
//(56-20)/(4+2)//9 * (10 + 11 * (12 + 13)) + 14//(15 + 16) * (17 + 18 * (19 + 20)//((21 + 22) * 23 + (24 * 25)) + 26 * 27)) + 28 //{asdsd{ddads}sa}[]sassada[]sda{{aassaddsd[]}dsad}
完整程序实现如下:
#include<bits/stdc++.h>
using namespace std;bool judge(char str[]){stack<char> s;int n = strlen(str);for(int i = 0; i < n; i++){if(str[i]=='(') s.push(str[i]);//左括号入栈 if(str[i]=='[') s.push(str[i]);if(str[i]=='{') s.push(str[i]);if(str[i]==')'){if(s.empty()) return false;//无左括号不匹配 else if(s.top()=='(') s.pop();//匹配 else return false;//不是同类括号 }if(str[i]==']'){if(s.empty()) return false;else if(s.top()=='[') s.pop();else return false;}if(str[i]=='}'){if(s.empty()) return false;else if(s.top()=='{') s.pop();else return false;}}return s.empty();//空匹配 非空说明存在多余左括号
}
int main(){char str[10000];cin>>str; //(56-20)/(4+2)//9 * (10 + 11 * (12 + 13)) + 14//(15 + 16) * (17 + 18 * (19 + 20)//((21 + 22) * 23 + (24 * 25)) + 26 * 27)) + 28 //{asdsd{ddads}sa}[]sassada[]sda{{aassaddsd[]}dsad}bool v = judge(str);if(v) cout<<"匹配"<<endl;else cout<<"不匹配"<<endl;return 0;
}
简单计算器实现:设计一个计算器,实现加减乘除和小括号的计算。
设计思路:构建两个栈,一个压入要进行计算的数字,一个压入运算符,运算符涉及到优先级问题,括号>乘除>加减。遍历要计算的字符串,数字压入栈num,运算符压入栈s:
1.如果栈s为空,直接将运算符压入栈s;
2.如果栈s不为空,且栈顶运算符优先级大于等于待入栈运算符,将栈顶运算符弹出,从栈num弹出两个数字,进行运算,将计算结果压入栈num,直至栈空或栈顶运算符优先级小于待入栈运算符,将待入栈元素入栈;
3.如果栈s不为空,且栈顶运算符优先级小于待入栈运算符,直接将待入栈运算符入栈;
4.遇到左括号直接入栈,重复2,3步骤,遇到右括号时,若栈s栈顶运算符为左括号,直接将左括号弹出;若不为左括号,将运算符依次弹出进行运算,直至栈顶运算符为左括号,将其弹出。
5.字符串遍历完成后,若栈s为空,栈num栈顶元素即运算结果;栈s不为空,将运算符依次弹出进行计算。
涉及程序时,我们先写一个函数prio来返回运算符的优先级,加减返回1,乘除返回2,小括号返回3和4。
int prio(char ch){switch(ch){case '+':case '-':return 1;case '*':case '/':return 2;case'(':return 3;case ')':return 4;}
}
再写一个运算函数:
int cal(int a,int b,char ch){switch(ch){case '+':return a+b;case '-':return a-b;case '*':return a*b;case '/':return a/b;}
}
上述5步我们慢慢拆分:
首先是遍历字符串:
for(int i=0;i<n;i++)
数字入栈:
if('0'<=str[i]&&str[i]<='9'){x = x*10+(str[i]-'0'); v=1;
}
if(str[i]>'9'||str[i]<'0'||i==n-1){if(v==1){num.push(x); //cout<<"push:"<<x<<endl;x=0;}v=0;
}
加v标记的原因是如果多个运算符相连,会导致压入不必要的数字0。
运算符入栈:
if(str[i]=='+'||str[i]=='-'||str[i]=='*'||str[i]=='/'||str[i]=='('||str[i]==')'){
1.如果栈s为空,直接将运算符压入栈s;
if(s.empty()) s.push(str[i]);
2.如果栈s不为空,且栈顶运算符优先级大于等于待入栈运算符,将栈顶运算符弹出,从栈num弹出两个数字,进行运算,将计算结果压入栈num,直至栈空或栈顶运算符优先级小于待入栈运算符,将待入栈元素入栈;
while(!s.empty()&&prio(s.top())>=prio(str[i])&&s.top()!='('){int x2 = num.top();num.pop();int x1 = num.top();num.pop();char ch = s.top();s.pop();//cout<<x1<<ch<<x2<<" "<<cal(x1,x2,ch)<<endl;num.push(cal(x1,x2,ch));
}
3.如果栈s不为空,且栈顶运算符优先级小于待入栈运算符,直接将待入栈运算符入栈;
s.push(str[i]);
4.遇到左括号直接入栈,重复2,3步骤,遇到右括号时,若栈s栈顶运算符为左括号,直接将左括号弹出;若不为左括号,将运算符依次弹出进行运算,直至栈顶运算符为左括号,将其弹出。
if(str[i]=='('){s.push(str[i]);continue;
}
if(str[i]==')'){while(!s.empty()&&s.top()!='('){int x2 = num.top();num.pop();int x1 = num.top();num.pop();char ch = s.top();s.pop();//cout<<x1<<ch<<x2<<" "<<cal(x1,x2,ch)<<endl;num.push(cal(x1,x2,ch));}s.pop();continue;
}
5.字符串遍历完成后,若栈s为空,栈num栈顶元素即运算结果;栈s不为空,将运算符依次弹出进行计算。
while(!s.empty()){int x2 = num.top();num.pop();int x1 = num.top();num.pop();char ch = s.top();s.pop();//cout<<x1<<ch<<x2<<" "<<cal(x1,x2,ch)<<endl;num.push(cal(x1,x2,ch));
}
return num.top();
完整程序实现如下:
#include<bits/stdc++.h>
using namespace std;int prio(char ch){switch(ch){case '+':case '-':return 1;case '*':case '/':return 2;case'(':return 3;case ')':return 4;}
}int cal(int a,int b,char ch){switch(ch){case '+':return a+b;case '-':return a-b;case '*':return a*b;case '/':return a/b;}
}int calculation(char str[]){stack<char> s;stack<int> num;int n = strlen(str);int x = 0;//用于提出字符串数字 int v = 0;//用于判断何时将数字压入栈 for(int i=0;i<n;i++){//cout<<str[i]<<endl;if('0'<=str[i]&&str[i]<='9'){x = x*10+(str[i]-'0'); v=1;}if(str[i]>'9'||str[i]<'0'||i==n-1){if(v==1){num.push(x); //cout<<"push:"<<x<<endl;x=0;}v=0;}if(str[i]=='+'||str[i]=='-'||str[i]=='*'||str[i]=='/'||str[i]=='('||str[i]==')'){if(str[i]=='('){s.push(str[i]);continue;}if(str[i]==')'){while(!s.empty()&&s.top()!='('){int x2 = num.top();num.pop();int x1 = num.top();num.pop();char ch = s.top();s.pop();//cout<<x1<<ch<<x2<<" "<<cal(x1,x2,ch)<<endl;num.push(cal(x1,x2,ch));}s.pop();continue;}if(s.empty()) s.push(str[i]);else {//cout<<s.top()<<" "<<str[i]<<endl;while(!s.empty()&&prio(s.top())>=prio(str[i])&&s.top()!='('){int x2 = num.top();num.pop();int x1 = num.top();num.pop();char ch = s.top();s.pop();//cout<<x1<<ch<<x2<<" "<<cal(x1,x2,ch)<<endl;num.push(cal(x1,x2,ch));}s.push(str[i]);}}}while(!s.empty()){int x2 = num.top();num.pop();int x1 = num.top();num.pop();char ch = s.top();s.pop();//cout<<x1<<ch<<x2<<" "<<cal(x1,x2,ch)<<endl;num.push(cal(x1,x2,ch));}return num.top();
}int main(){char str[10000];cin>>str; //(56-20)/(4+2)//9*(10+11*(12+13))+14//(15+16)*(17+18*(19+20))//(((21+22)*23+(24*25))+26*27)+28 //10+11*12/12+14-1+2*3*1-5/5*5-5-5-5*5/5*5/5//10+11-12/12+14-1+22/2*5int cnt = calculation(str);cout<<cnt;return 0;
}
也有想过对输入的字符串进行一个合法性的判断,括号匹配,正确的运算符,这两个判断可以简单实现,但下面这两种
1234-1234+-34
12+231*41-
感觉判断起来有些许繁琐,但不判断程序又显得不完美,小记录一下。多给给几组测试样例,因为是整数相除,所以尽量选择整除的数:
//(56-20)/(4+2)//9*(10+11*(12+13))+14//(15+16)*(17+18*(19+20))//(((21+22)*23+(24*25))+26*27)+28 //10+11*12/12+14-1+2*3*1-5/5*5-5-5-5*5/5*5/5//10+133+(4+22)/2*5//10+11-12/12+14-1+22/2*5
有问题敬请大家指正。
括号匹配,实现简单计算器(加减乘除,小括号)相关推荐
- c语言括号匹配输出个数字,C程序括号匹配检查(带详细注释)
编写一程序检查C源程序文件中{}.()等括号是否匹配,并输出第一个检测到的不匹配的括号及所对应括号所在的行号(程序中只有一个括号不匹配). 注意: 1. 除了括号可能不匹配外,输入的C源程序无 ...
- js进阶正则表达式10-分组-多行匹配-正则对象的属性(小括号作用:分组,将小括号里面的东西看成一个整体,因为量词只对前一个字符有效)(多行匹配:m)(属性使用:reg.global)...
js进阶正则表达式10-分组-多行匹配-正则对象的属性(小括号作用:分组,将小括号里面的东西看成一个整体,因为量词只对前一个字符有效)(多行匹配:m)(属性使用:reg.global) 一.总结 1. ...
- 简单计算器——JavaScript小实例
简单计算器--JavaScript小实例 先来看一下下我们要做的计算器(以iQOO neo5手机计算器为例): 这就是我们今天要做的计算器的模板,成品的样子会略有不同,但功能完善. 好,当我们看到这个 ...
- 字符串括号匹配c语言,数据结构C语言括号的检验源程序 , 数据结构(C) 请用类C语言实现括号匹配的检验这个算法...
问题标题 数据结构C语言括号的检验源程序 , 数据结构(C) 请用类C语言实现括号匹配的检验这个算法 2019-8-21来自ip:13.149.196.77的网友咨询 浏览量:270 手机版 问题补充 ...
- python括号匹配问题_支持通配符的括号匹配问题源码+详细流程代码(python)
问题: 判断一个有左括号和右括号.以及其他ASCII字符组成的表达式是合法. 判断条件是左括号-右括号数目.次序配对,可多层嵌套.如果有*,则*可作为0个或者1个右括号,如果匹配则输出ok,不匹配则输 ...
- 判断括号匹配的程序java_java判断左右括号匹配
java判断左右括号匹配 [2021-02-10 16:36:55] 简介: Java进行正则表达式匹配的方法:首先打开eclipse软件:然后运用d来进行数字的匹配,如果字符串中遇到了空白字符的话 ...
- python实现简单计算器加减乘除功能_Python3实现简单加减乘除运算的计算器
这是用Python3编写的一个简易的计算器,只有加减乘除,没有括号. 个人思路:将公式以字符串形式传入: 1.去掉其中的空格,生成新的字符串进行操作: 2.提取其中的数字和运算符号分别生产新的列表: ...
- C程序括号匹配检查(带详细注释)
编写一程序检查C源程序文件中{}.()等括号是否匹配,并输出第一个检测到的不匹配的括号及所对应括号所在的行号(程序中只有一个括号不匹配). 注意: 1. 除了括号可能不匹配外,输入的C源程序无 ...
- 第11.16节 Python正则元字符“()”(小括号)与组(group)匹配模式
一. 什么是组 关于组匹配模式,Python官网上说得比较简单,也没有这个名词,只有组这个名词,老猿查了比较多的资料和做了相关测试之后才理解. 组匹配模式,就是在匹配的正则表达式中使用小括号" ...
最新文章
- Python中使用数据库SQLite
- iframe 内嵌第三方网站 cookie 失效,解决办法
- Kali Linux 安全渗透教程第六更1.4.2 安装至USB驱动器Kali Linux
- mysql C语言API接口及实例
- SpringBoot+MySql+ElementUI实现一对多的数据库的设计以及增删改查的实现
- 《阿里巴巴Android开发手册》v1.0.1更新,优化部分内容和示例代码
- 学校计算机房 作文,第一次去机房作文
- C#捕获控制台(console)关闭事件
- php pop3,php使用smtp,pop3协议收发邮件代码
- Ubuntu各个版本的介绍
- atlas 力矩计算_Atlas 2.1.0 实践(2)—— 安装Atlas
- matlab求单自由度振动方程为,matlab求解振动方程
- 码农小汪-Java Condition
- 一个北大毕业生决定去送外卖
- 自动化测试和软件测试的区别,自动化测试和手动测试之间的区别
- 前端(五)DOM 文档对象模型
- 食物链 (种类并查集)
- C# Action 使用
- 实话实说 —— 心理模型vs实现模型
- 腾讯安全与青藤云安全联合发布“天眼云镜”主机安全产品