后面有深入介绍,并非仅仅是这道题(后面有惊喜)
算数四则运算的规则是1)先乘除,后加减;2)从左算到右;3)先括号内,后括号外。
由此,算式4+23-10/5的计算顺序为4+23-10/5=4+6-10/5=4+6-2=8。
给定一个以“#”作为结束符的算式,求出算式的结果。
以“#”结尾的表达式,运算数为正整数。每个表达式占一行。
输出表达式运算的结果。
4+23-10/5#
3(7-2)#
2*3/2#
8
15
3
题解:
这道题可是磨了我几天啊,开始就不知道怎么确定各个运算符之间的优先关系,由于我们学的数据结构教材和题目所说的严蔚敏《数据结构(C语言)》不一样,导致开始不知如何下手,于是在网上看了大佬的博客,发现了用个二维数组即可(只能说自己太菜了–_--)
其中θ1为存放运算符的栈(我自己定义的为s2)的栈顶元素,θ2为从表达式中读取的操作符
于是就开始一顿猛操作,直接用C++的STL模拟,于是就开始了一直WA,一直爽的漫长过程!!!
开始不能静下心来debug,导致一直没找到自己的错误,今天中午乘着下午没课,又打算再来调试调试,于是发现了在运算时没有考虑位置(比如:在除时,分子分母位置居然弄反了;减法也就一样了)tcl
后面又继续,到处设中间数据,由于吃了个午饭,看了会电视,偷了下懒就去睡觉了,醒来继续肝,发现已经离成功不远了,最后终于发现原来在判断s2的栈顶大于s[i]时,没有实现让s[i]继续循环居然没有break
代码如下:
#include
#include
#include
#include
using namespace std;
char s[10010];
stack<double>s1; //偷了下懒,利用的C++中的STL模拟,用来存放数值
stack<char>s2; //同上,用来存放运算符
const char priority[7][7]= //确定运算符之前的优先级
{
{'>','>','<','<','<','>','>'},
{'>','>','<','<','<','>','>'},
{'>','>','>','>','<','>','>'},
{'>','>','>','>','<','>','>'},
{'<','<','<','<','<','=','0'},
{'>','>','>','>','0','>','>'},
{'<','<','<','<','<','0','='},
};
int getIndex(char c) //确定两个运算符之间在二维数组对应的行和列
{
int index;
switch(c)
{
case'+':
index=0;
break;
case'-':
index=1;
break;
case'*':
index=2;
break;
case'/':
index=3;
break;
case'(':
index=4;
break;
case')':
index=5;
break;
default:
index=6;
break;
}
return index;
}
char getPriority(char a,char b) //确定s2栈顶元素与s[i]的优先级
{
int index1,index2;
index1=getIndex(a);
index2=getIndex(b);
//printf("%d %d\n",index1,index2);
return priority[index1][index2];
}
double calculate(double num1,char c,double num2) //计算,重点注意num2和num1千万别反了
{
double Num;
switch(c)
{
case'+':
Num=num2+num1;
break;
case'-':
Num=num2-num1;
break;
case'*':
Num=num2*num1;
break;
case'/':
Num=num2/num1;
break;
}
return Num;
}
double getAnswer(char s[]) //主要函数
{
s2.push('#'); //提前处理s2,让一个优先级最小的字符入栈
int counter=0;
int len=strlen(s);
int i=0;
while(i<len)
{
if(s[i]-'0'>=0&&s[i]-'0'<=9) //如果是数字
{
if(counter==1) //如果是多位数的情况
{
double num1=s1.top();
s1.pop();
num1=num1*10+(s[i]-'0');
s1.push(num1);
i++;
}
else //一位数的情况
{
s1.push(s[i]-'0');
i++;
counter++;
}
}
else
{
counter=0;
//cout<
char c=getPriority(s2.top(),s[i]); //判断优先级
//cout<
switch(c)
{
case'<': //s2栈顶元素小于当前运算符,当前运算符直接进栈
s2.push(s[i]);
i++;
break;
case'>': //关键,直到s2栈顶元素小于当前运算符为止
{
char c1=s2.top();
//cout<
s2.pop();
//cout<
//cout<
double num2=s1.top();
//cout<
s1.pop();
double num3=s1.top();
//cout<
s1.pop();
double num4=calculate(num2,c1,num3);
//cout<
s1.push(num4);
//cout<
break; //千万别少了
}
case'=':
s2.pop();
i++;
break;
}
}
}
//cout<
return s1.top();
}
int main()
{
while(~scanf("%s",s))
{
while(!s1.empty()) //将上一个的数据清空
s1.pop();
while(!s2.empty()) //同上
s2.pop();
double num=getAnswer(s);
cout<<num<<endl;
}
return 0;
}
自闭了
后面自己还是试着用数组模拟栈,自己手写了下栈,而没有用STL
代码如下:
#include
#include
#include
char s[100010];
typedef struct
{
double data[100010];
int top;
}seq1;
seq1 s1;
typedef struct
{
char data[100010];
int top;
}seq2;
seq2 s2;
char priority[7][7]=
{
{'>','>','<','<','<','>','>'},
{'>','>','<','<','<','>','>'},
{'>','>','>','>','<','>','>'},
{'>','>','>','>','<','>','>'},
{'<','<','<','<','<','=','0'},
{'>','>','>','>','0','>','>'},
{'<','<','<','<','<','0','='},
};
int getIndex(char c)
{
int index;
switch(c)
{
case '+':index=0;break;
case '-':index=1;break;
case '*':index=2;break;
case '/':index=3;break;
case '(':index=4;break;
case ')':index=5;break;
default:index=6;break;
}
return index;
}
char getPriority(char a,char b)
{
int index1=getIndex(a);
int index2=getIndex(b);
return priority[index1][index2];
}
double calculate(double num2,char c,double num1)
{
double num;
switch(c)
{
case '+':num=num2+num1;break;
case '-':num=num2-num1;break;
case '*':num=num2*num1;break;
case '/':num=num2/num1;break;
}
return num;
}
double getAnswer(char s[])
{
s2.top++;
s2.data[s2.top]='#';
int counter=0;
int len=strlen(s);
int i=0;
while(i<len)
{
if(s[i]-'0'>=0&&s[i]-'0'<=9)
{
if(counter==1)
{
double t=s1.data[s1.top];
s1.top--;
t=t*10+(s[i]-'0');
s1.top++;
s1.data[s1.top]=t;
i++;
}
else
{
s1.top++;
s1.data[s1.top]=(s[i]-'0');
counter++;
i++;
}
}
else
{
counter=0;
char ch=getPriority(s2.data[s2.top],s[i]);
switch(ch)
{
case '<':s2.top++;s2.data[s2.top]=s[i];i++;break;
case '>':
{
char c=s2.data[s2.top];
s2.top--;
double num1=s1.data[s1.top];
s1.top--;
double num2=s1.data[s1.top];
s1.top--;
double Num=calculate(num2,c,num1);
s1.top++;
s1.data[s1.top]=Num;
break;
}
case '=':
s2.top--;
i++;
break;
}
}
}
return s1.data[s1.top];
}
int main()
{
while(~scanf("%s",s))
{
s1.top=-1;
s2.top=-1;
double num;
num=getAnswer(s);
printf("%d\n",(int)num);
}
return 0;
}
————————————————————————————————————————————
此处有分隔符
————————————————————————————————————————————
在学期末课程设计中,也是选的这个课题,于是除上面题目的简单要求外,进行了进一步的拓展:
实现了算术、关系、逻辑、以及三者之间综合计算
#include
#include
#include
#include
#define Maxsize 1000
/**
浮点数大小之间判断允许误差范围
*/
const double EPS=1e-6;
/**
定义数值栈结构
*/
struct
{
double data[Maxsize];
int top;
} S1;
/**
定义运算符栈结构
*/
struct
{
char data[Maxsize];
int top;
} S2;
char s[Maxsize]; //输入的表达式
/**
通过二维数组判断运算符之间的优先级
其中'0'表示该种关系不存在会出现
*/
char priority[20][20]=
{
{'>','>','>','>','>','>','>','<','>','>','>','>','>','>','>','>','>','>'}, //'!'
{'<','>','>','<','<','<','<','<','>','>','>','>','>','>','>','>','>','>'}, //'+'
{'<','>','>','<','<','<','<','<','>','>','>','>','>','>','>','>','>','>'}, //'-'
{'<','>','>','>','>','<','>','<','>','>','>','>','>','>','>','>','>','>'}, //'*'
{'<','>','>','>','>','<','>','<','>','>','>','>','>','>','>','>','>','>'}, //'/'
{'<','>','>','>','>','>','>','<','>','>','>','>','>','>','>','>','>','>'}, //'^'
{'<','>','>','<','<','<','<','<','>','>','>','>','>','>','>','>','>','>'}, //'%'
{'<','<','<','<','<','<','<','<','=','<','<','<','<','<','<','<','<','0'}, //'('
{'>','>','>','>','>','>','>','0','>','>','>','>','>','>','>','>','>','>'}, //')'
{'<','<','<','<','<','<','<','<','>','>','>','>','>','>','>','>','>','>'}, //'>'
{'<','<','<','<','<','<','<','<','>','>','>','>','>','>','>','>','>','>'}, //'<'
{'<','<','<','<','<','<','<','<','>','>','>','>','>','>','>','>','>','>'}, //'>='
{'<','<','<','<','<','<','<','<','>','>','>','>','>','>','>','>','>','>'}, //'<='
{'<','<','<','<','<','<','<','<','>','>','>','>','>','>','>','>','>','>'}, //'=='
{'<','<','<','<','<','<','<','<','>','>','>','>','>','>','>','>','>','>'}, //'!='
{'<','<','<','<','<','<','<','<','>','<','<','<','<','<','<','>','>','>'}, //'&&'
{'<','<','<','<','<','<','<','<','>','<','<','<','<','<','<','>','>','>'}, //'||'
{'<','<','<','<','<','<','<','<','0','<','<','<','<','<','<','<','<','='}, //'#'
};
/**
获取运算符对应于二维数组行、列的函数
*/
int getIndex(char ch)
{
int index;
switch(ch)
{
case '!':
index=0;
break;
case '+':
index=1;
break;
case '-':
index=2;
break;
case '*':
index=3;
break;
case '/':
index=4;
break;
case '^':
index=5;
break;
case '%':
index=6;
break;
case '(':
index=7;
break;
case ')':
index=8;
break;
case '>':
index=9;
break;
case '<':
index=10;
break;
case 'X':
index=11;
break;
case 'Y':
index=12;
break;
case 'Z':
index=13;
break;
case 'W':
index=14;
break;
case '&':
index=15;
break;
case '|':
index=16;
break;
case '#':
index=17;
break;
}
return index;
}
/**
获取两运算符之间优先级函数
*/
char getPriority(char a,char b)
{
int index1=getIndex(a);
//printf("index1=%d\n",index1);
int index2=getIndex(b);
//printf("index2=%d\n",index2);
//printf("index1=%d,index2=%d\n",index1,index2);
return priority[index1][index2];
}
/**
直接计算函数
*/
double calculate(double num1,char c,double num2)
{
double Num;
switch(c)
{
case '+':
{
Num=num2+num1;
break;
}
case '-':
{
Num=num2-num1; //注意原来在栈1的相对位置
break;
}
case '*':
{
Num=num2*num1;
break;
}
case '/':
{
Num=num2/num1;
//printf("num2/num1=%.2f\n",Num);
break;
}
case '^':
{
Num=pow(num2,num1);
break;
}
case '%':
{
Num=fmod(num2,num1); //便于小数间取余
break;
}
case '>':
{
if(num2>num1+EPS) //浮点数大小判断
Num=1;
else
Num=0;
//printf("Num=%d\n",(int)Num);
break;
}
case '<':
{
if(num2<(num1-EPS))
Num=1;
else
Num=0;
break;
}
case 'X':
{
if(num2>=(num1+EPS))
Num=1;
else
Num=0;
break;
}
case 'Y':
{
if(num2<=(num1-EPS))
Num=1;
else
Num=0;
break;
}
case 'Z':
{
if(fabs(num2-num1)<=EPS)
Num=1;
else
Num=0;
break;
}
case 'W':
{
if(fabs(num2-num1)>EPS)
Num=1;
else
Num=0;
//printf("Num=%d\n",(int)Num);
break;
}
case '&':
{
if(num2!=0&&num1!=0)
Num=1;
else
Num=0;
//printf("num1=%d num2=%d Num=%d\n",(int)num1,(int)num2,(int)Num);
break;
}
case '|':
{
if(num1==0&&num2==0)
Num=0;
else
Num=1;
break;
}
}
//printf("Num=%.2f\n",Num);
return Num;
}
/**
主要运算函数
*/
double getAnswer(char s[])
{
/**
初始化栈2,便于运算符之间比较
*/
S2.top++;
S2.data[S2.top]='#';
int len=strlen(s);
int i=0;
int counter=0; //计数器,数字有一位和多位数字的形式
int flag=0; //小数标记器
while(i<len)
{
/**
小数点
*/
if(s[i]=='.')
{
flag=1;
counter=0;
i++;
}
/**
如果是是数值则进栈1
*/
if(s[i]>='0'&&s[i]<='9')
{
/**
小数情况
*/
if(flag==1)
{
if(counter==0)
{
double t=S1.data[S1.top];
S1.top--;
t=t+0.1*(s[i]-'0');
//printf("t=%.2f\n",t);
S1.top++;
S1.data[S1.top]=t;
counter++;
i++;
}
else
{
int m=counter+1; //表示该数字为小数点后第几位
double t=S1.data[S1.top];
S1.top--;
t=t+pow(0.1,m)*(s[i]-'0');
//printf("t=%.2f\n",t);
S1.top++;
S1.data[S1.top]=t;
counter++;
i++;
}
}
else
{
if(counter==0)
{
S1.top++;
S1.data[S1.top]=s[i]-'0'; //进栈,并将字符型转化为整形
i++;
counter++;
}
/**
多位数进栈
*/
else
{
/**原栈顶元素出栈*/
double t=S1.data[S1.top];
//printf("t=%.2f\n",t);
S1.top--;
t=t*10+(s[i]-'0');
/**替换栈顶元素*/
S1.top++;
S1.data[S1.top]=t;
//printf("S1.data[S1.top]=%.2f\n",S1.data[S1.top]);
counter++;
i++;
}
}
}
/**
如果是运算符则进栈2
*/
else
{
counter=0; //计数器归零
flag=0; //小数标记器为0
char ch=getPriority(S2.data[S2.top],s[i]);
//printf("%c\n",ch);
switch(ch)
{
case '<':
{
/**
运算符直接进栈
*/
S2.top++;
S2.data[S2.top]=s[i];
i++; //继续访问
break;
}
case '>':
{
/**
当前运算符栈栈顶元素出栈
*/
char c=S2.data[S2.top];
S2.top--;
/**
如果是!(即 非 逻辑符时,则只需数值栈出栈一次即可)
*/
if(c=='!')
{
double num1=S1.data[S1.top];
S1.top--;
if(num1!=0)
{
S1.top++;
S1.data[S1.top]=0;
}
else
{
S1.top++;
S1.data[S1.top]=1;
}
}
/**
如果是其他符号时,数值栈连续出栈两次
*/
else
{
double num1=S1.data[S1.top];
S1.top--;
double num2=S1.data[S1.top];
S1.top--;
/**
计算新的数值然后入栈S1
*/
double Num=calculate(num1,c,num2);
//printf("Num=%f\n",Num);
S1.top++;
S1.data[S1.top]=Num;
}
break;
}
case '=':
{
S2.top--;
i++; //继续访问
break;
}
}
}
}
return S1.data[S1.top];
}
/**
程序声明
*/
void status()
{
printf("*----------------------------------------------------------------*\n");
printf("* 请输入你想要进行的操作 *\n");
printf("* *\n");
printf("* 1.算术表达式计算 *\n");
printf("* *\n");
printf("* 2.关系表达式计算 *\n");
printf("* *\n");
printf("* 3.逻辑表达式计算 *\n");
printf("* *\n");
printf("* 0.退出该程序 *\n");
printf("* *\n");
printf("*----------------------------------------------------------------*\n");
printf("\n");
}
/**
主函数
*/
int main()
{
printf("*-----------------该程序可以实现基本表达式的计算-----------------*\n");
status();
int n;
while(~scanf("%d",&n))
{
switch(n)
{
case(1):
{
printf("请输入算术表达式(以'#'表示结束):\n");
scanf("%s",s);
S1.top=-1;
S2.top=-1;
double num; //最终结果
num=getAnswer(s);
printf("该算术表达式结果为:\n%.3f\n",num);
printf("*----------------------------请继续操作--------------------------*\n");
printf("\n");
status();
break;
}
case (2):
{
printf("请输入关系表达式(其中 >= 用X表示, <= 用Y表示, == 用Z表示, != 用W表示,以'#'表示结束):\n");
scanf("%s",s);
double num=getAnswer(s);
//printf("num=%lf\n",num);
int flag=(int)num;
//printf("flag=%d\n",flag);
if(flag==1)
{
printf("该关系表达式结果为:\nTURE\n");
}
else
{
printf("该关系表达式结果为:\nFLASE\n");
}
printf("*----------------------------请继续操作--------------------------*\n");
printf("\n");
status();
break;
}
case (3):
{
printf("请输入逻辑表达式( && 用'&'表示, || 用'|'表示,以'#'表示结束):\n");
scanf("%s",s);
double num=getAnswer(s);
int flag=(int)num;
//printf("flag=%d\n",flag);
if(flag==1)
{
printf("该逻辑表达式结果为:\nTRUE\n");
}
else
printf("该逻辑表达式结果为:\nFALSE\n");
printf("*----------------------------请继续操作--------------------------*\n");
printf("\n");
status();
break;
}
case (0):
{
printf("*----------------------------------------------------------------*\n");
printf("* *\n");
printf("* 程序结束,谢谢使用! *\n");
printf("* *\n");
printf("*----------------------------------------------------------------*\n");
return 0;
}
}
}
return 0;
}
/**
sample1(算术表达式) :
(0.25*2+8)/5# 1.7 //实数类型
7.25*2-8.3# 6.2 //实数类型
3.2^3-1.33# 31.438 //实数类型
2*3-9/4+4*3/2# 9.75 //实数类型
(15/3-8)*3# -9 //答案负数
(9-9)/8# 0 //答案为0
2^20-512*4# 1046528 //幂指数较大时
(3-1)^4+5*2-16# 10 //多种运算符
(2^3-5)/3+10# 11 //一重括号类型
2*(6+2*(3+6*(6+6)))# 312 //多重括号类型
((2+2)^2-5)%5# 1 //取余运算
2^6%9# 1 //取余运算
(4.5%3.3)/3# 0.4 //小数取余
*/
/**
sample2(关系表达式):
6*3+18X34# TURE //(其中 X 表示 >= )
10^2-9^2Y8^2-2^2# TURE //(其中 Y 表示 <= )
4*8-25>5*2+1# FLASE //
2.26^5<2*5# FALSE //
(30-28)*10Z4*5# TURE //(其中 Z 表示 == )
5^2W20+5# FLASE //(其中 W 表示 != )
*/
/**
sample3(逻辑表达式):
!(1+4^2.3)|0# FALSE //基本逻辑表达式 (其中 | 表示 || )
((8.23+2)/3)|(4.35%2.54)# TURE //基本逻辑表达式求值(其中 | 表示 || )
5%2*4>5|4%2*5<7# TURE //算术、关系、逻辑表达式综合计算
(2^3*5>38)&(4-13+3^2)# FALSE //算术、关系、逻辑表达式综合计算
*/