C/C++ 小程序:表达式计算器
程序员文章站
2024-03-19 08:59:52
...
项目简介:
------本程序用来计算运算数与运算结果都在0-10这个范围内的算式,支持加减乘除的计算。小编用两种方法编写了这个程序:
- 自己定义栈的结构体,这种方法把栈用数组表示,不需要指针,栈顶指针top直接用数组的下标表示,比较简单,比较适用于初学栈,初学C语言,想要练习的小白,方便实现,简单易懂。
- 直接用C++的stack栈类型:要想实现这个方法,需要对C++有基本的了解,会C++的人,很容易实现,如果没有接触过C++或者是略懂C++的同志们,略微看一下我的注释,也是可以理解的。
算法步骤:
① 初始化OPTC栈和OPTN栈,将表达式起始符“#”压入OPTC栈。
② 扫描表达式,读入第一个字符ch,如果表达式没有扫描完毕至“#”或OPTR的栈顶元素不为“#”时,则循环执行以下操作:
- 若ch不是运算符,则压入OPTN栈,读入下一字符ch;
- 若ch是运算符,则根据OPTC的栈顶元素和ch的优先级比较结果,做不同的处理:
A、若是栈OPTC的栈顶元素优先级小于ch,则ch压入OPTC栈,读入下一字符ch;
B、若是栈OPTC的栈顶元素优先级大于ch,则弹出OPTC栈顶的运算符,从OPTN栈弹出两个数,进行相应运算,结果压入OPTN栈;
C、若是栈OPTC的栈顶元素优先级等于ch,则OPTC的栈顶元素是“(”且ch是“)”,这时弹出OPTC栈顶的“(”,相当于括号匹配成功,然后读入下一字符ch。
③ OPTN栈顶元素即为表达式求值结果,返回此元素。
关于符号之间的优先级:下图是不同符号之间的优先级关系
程序在进行运算的时候,按照从左到右的顺序从输入的字符串中读入运算数或运算符,在这里符号1指的是两个符号中左边的那个符号,符合二指的是右边的那个符号。如果是>,则先对运算符1进行计算,再对运算符2进行计算;如果是=,则脱括号(这个地方,在程序中有解释,就是直接将左括号从运算符栈中弹出);如果是×,则表示算式读入完成。
算法流程图:
方法一:自定义结构体栈:
#include <bits/stdc++.h>
using namespace std;
/*----------------宏定义-------------------*/
#define MAXSIZE 100
/*----------------定义栈-------------------*/
typedef struct { //定义栈
char a[MAXSIZE];
int top;
} cStack;
/*----------------全局变量-------------------*/
char op[7]= {'+','-','*','/','(',')','#'};
char relation[7][7]= { //定义运算符之间的优先级关系
{'>','>','<','<','<','>','>'},
{'>','>','<','<','<','>','>'},
{'>','>','>','>','<','>','>'},
{'>','>','>','>','<','>','>'},
{'<','<','<','<','<','=',' '},
{'>','>','>','>',' ','>','>'},
{'<','<','<','<','<',' ','='}
};
/*----------------入栈函数-------------------*/
void Push(cStack &zhan,char i) {
zhan.a[zhan.top]=i;
zhan.top++;
}
/*----------------获取栈顶元素函数-------------------*/
char getTop(cStack &zhan) {
int i=zhan.top-1;
return zhan.a[i];
}
/*----------------出栈函数-------------------*/
void Pop(cStack &zhan,char &i) {
zhan.top--;
i=zhan.a[zhan.top];
}
/*----------------运算函数-------------------*/
char Operate(char a,char o,char b) {
int x=a-'0';
int y=b-'0';
int result;
switch(o) {
case'+':
result=x+y;
break;
case'-':
result=x-y;
break;
case'*':
result=x*y;
break;
case'/': //注意分母不能是0的情况
if(y==0) {
cout<<"分母为0!";
return 0;
} else {
result=x/y;
break;
}
default:
cout<<"请输入正确的运算符!";
printf("%c",o);
break;
}
return '0'+result;
}
/*----------------判断ch是否为运算符-------------------*/
int in(char ch) {
if(ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch=='('||ch==')'||ch=='#') return 1;
else return 0;
}
/*----------------比较运算符优先级函数-------------------*/
char Compare(char j,char k) {
int x,y;
switch(j) {
case'+':
x=0;
break;
case'-':
x=1;
break;
case'*':
x=2;
break;
case'/':
x=3;
break;
case'(':
x=4;
break;
case')':
x=5;
break;
case'#':
x=6;
break;
}
switch(k) {
case'+':
y=0;
break;
case'-':
y=1;
break;
case'*':
y=2;
break;
case'/':
y=3;
break;
case'(':
y=4;
break;
case')':
y=5;
break;
case'#':
y=6;
break;
}
return relation[x][y];
}
/*----------------主函数-------------------*/
int main() {
int b=1;
while(b) {
cStack OPTC,OPTN;
OPTC.top=0; //初始化运算符栈
OPTN.top=0; //初始化运算数栈
cout<<"请输入您要计算的算式:";
Push(OPTC,'#');
char ch,a,o,b,n;
ch=getchar();
while(ch!='#'||getTop(OPTC)!='#') { //因为只有当ch=='#'&&getTop(OPTC)=='#'成立时才终止循环,输出运算结果;
if(in(ch)==0) { //如果ch不是运算符,则进入运算数栈OPTN
Push(OPTN,ch);
ch=getchar();
} else {
switch(Compare(getTop(OPTC),ch)) { //比较符号栈栈顶元素与ch的优先级
case'<':
Push(OPTC,ch); //如果符号栈栈顶元素的优先级小于ch,就将ch压入运算符栈OPTC
ch=getchar();
break;
case'>':
Pop(OPTC,o); //如果符号栈栈顶元素的优先级大于ch,就弹出运算符栈OPTC的栈顶指针,并弹出两个运算数,进行计算,将计算结果压入运算数栈
Pop(OPTN,b);
Pop(OPTN,a);
Push(OPTN,Operate(a,o,b));
//ch=getchar(); //不需要再读入一个,因为刚才读进来的那个还没用,用的这个是从栈里出来的
break;
case'=':
Pop(OPTC,n); //如果相等,脱括号
ch=getchar();
break;
}
}
}
cout<<"最终运算结果为:";
cout<<getTop(OPTN)<<endl;
cout<<"请问您是否需要继续计算?(1.继续 0.退出)";
cin>>b;
}
return 0;
}
方法二:直接用C++提供的stack栈类型:
#include <bits/stdc++.h>
using namespace std;
/*----------------全局变量-------------------*/
char op[7]= {'+','-','*','/','(',')','#'};
char relation[7][7]= { //定义运算符之间的优先级关系
{'>','>','<','<','<','>','>'},
{'>','>','<','<','<','>','>'},
{'>','>','>','>','<','>','>'},
{'>','>','>','>','<','>','>'},
{'<','<','<','<','<','=',' '},
{'>','>','>','>',' ','>','>'},
{'<','<','<','<','<',' ','='}
};
/*----------------运算函数-------------------*/
char Operate(char a,char o,char b) {
int x=a-'0';
int y=b-'0';
int result;
switch(o) {
case'+':
result=x+y;
break;
case'-':
result=x-y;
break;
case'*':
result=x*y;
break;
case'/': //注意分母不能是0的情况
if(y==0) {
cout<<"分母为0!";
return 0;
} else {
result=x/y;
break;
}
default:
cout<<"请输入正确的运算符!";
printf("%c",o);
break;
}
return '0'+result;
}
/*----------------判断ch是否为运算符-------------------*/
int in(char ch) {
if(ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch=='('||ch==')'||ch=='#') return 1;
else return 0;
}
/*----------------选择符号函数-------------------*/
int Switch(char i){
switch(i) {
case'+':
return 0;
case'-':
return 1;
case'*':
return 2;
case'/':
return 3;
case'(':
return 4;
case')':
return 5;
case'#':
return 6;
}
}
/*----------------比较运算符优先级函数-------------------*/
char Compare(char j,char k) {
int x,y;
x=Switch(j);
y=Switch(k);
return relation[x][y];
}
/*----------------主函数-------------------*/
int main() {
int flag=1;
cout<<"注意:本计算机支持+、-、*、/运算,且只能进行运算数与运算结果在0-10这个范围内的算式," <<endl;
cout<<" ()必须是英文的(),算式末尾需要加上一个#,以表示算式输入结束,输入格式示例:1+2*(4/2)# "<<endl;
while(flag!=0) {
stack<char> OPTC,OPTN; //调用C++中的栈
cout<<"请输入您要计算的算式:";
OPTC.push('#'); //向运算符栈中压入'#'
char ch,a,o,b,n;
ch=getchar();
while(ch!='#'||OPTC.top()!='#') { //因为只有当ch=='#'&&getTop(OPTC)=='#'成立时才终止循环,输出运算结果;所以当ch!='#'||OPTC.top()!='#'时,可以一直读入输入的算式进行计算
if(in(ch)==0) { //如果ch不是运算符,则进入运算数栈OPTN
OPTN.push(ch);
ch=getchar();
} else {
switch(Compare(OPTC.top(),ch)) { //比较符号栈栈顶元素与ch的优先级
case'<':
OPTC.push(ch); //如果符号栈栈顶元素的优先级小于ch,就将ch压入运算符栈OPTC
ch=getchar();
break;
case'>': //如果符号栈栈顶元素的优先级大于ch,就弹出运算符栈OPTC的栈顶指针,并弹出两个运算数,进行计算,将计算结果压入运算数栈
o=OPTC.top();
OPTC.pop();
b=OPTN.top();
OPTN.pop();
a=OPTN.top();
OPTN.pop();
OPTN.push(Operate(a,o,b));
//ch=getchar(); //不需要再读入一个,因为刚才读进来的那个还没用,用的这个是从栈里出来的
break;
case'=':
OPTC.pop(); //如果相等,脱括号
ch=getchar();
break;
}
}
}
cout<<"最终运算结果为:";
cout<<OPTN.top()<<endl;
cout<<"请问您是否需要继续计算?(1.继续 0.退出):";
cin>>flag;
}
return 0;
}
本期分享到这里就结束啦,大家如果对小编的代码有疑问或者想要小编做其他的程序,都欢迎来私信小编呀!
上一篇: Java学习笔记-简单的用户登录注册界面
推荐阅读
-
c++ primer 笔记第四章表达式
-
C++/Qt/Qml程序使用Camel_CrashReport捕获异常崩溃并定位问题代码行
-
C++程序员学Java系列之十五:自定义类的简单使用
-
(转)Linux C++程序进行性能分析工具gprof使用入门 博客分类: c++转载
-
delete 对象后调用该对象的方法程序不报错 博客分类: c++
-
delete 对象后调用该对象的方法程序不报错 博客分类: c++
-
(转)Linux C++程序进行性能分析工具gprof使用入门 博客分类: c++转载
-
C/C++ 小程序:表达式计算器
-
VS下用C++写第一个EasyX程序
-
一个C++计算器的改良版,可以实现错误时重新输入