题目
表达式求值,(中缀表达式,平时数学中的表达式)
思路
首先,建立两个栈的结构,一个用于存储数字,一个用于存储符号
遍历表达式,如果对应的字符是数字符号则依次向后判断,将连续的数字符号转换成数字,存入数字对应的栈中;如果对应的字符是运算符,则遵循以下原则:
1.当存储符号的栈为空时则直接入栈
2.当该运算符的优先级比栈顶元素的优先级高时,则入栈
3.当该运算符的优先级比栈顶元素的优先级低时,则取出两个数字栈中的元素取出当前栈顶的运算符,进行运算,并将结果放在数字栈的栈顶,按这种方式处理,直到遇到左括号或者当前字符栈中已经没有可以处理的运算符或者栈顶元素比改运算符优先级小时(相当于对与当前运算符优先级相同的符号进行处理);
最后,将栈中剩余的元素进行运算(取两个元素去一个运算符的方式)即可得到最终结果(最后数字栈中的栈顶元素)
代码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
const int maxsize=1000;
typedef struct charstack{
char a[maxsize];
int top;
}charStack;
typedef struct numstack{
double a[maxsize];
int top;
}numStack;
void numStackIn(numStack*p,double a);//数字栈入栈
void charStackIn(charStack*p,char a);//字符栈入栈
void numStackOut(numStack*p,double *p1); //数字栈出栈
void charStackOut(charStack*p,char *p1); //字符栈出栈
void compute(numStack *p,double num1,double num2,char char1);//计算两个数字和一个字符组成表达式的值并放在栈顶
int main()
{
charStack stackchar;
numStack stacknum;
stackchar.top=-1;
stacknum.top=-1;
double num1,num2;
char char1;
memset(stackchar.a,0,sizeof(stackchar.a));
memset(stacknum.a,'\0',sizeof(stacknum.a));
char s[maxsize];
scanf("%s",s);
int len=strlen(s);
for(int i=0;i<len;i++){
if(s[i]>='0'&&s[i]<='9'){
double n=s[i]-'0';
while(s[i+1]!='\0'){
if(s[i+1]>='0'&&s[i+1]<='9'){
n=n*10+s[i+1]-'0';
i++;
}else{
break;
}
}
numStackIn(&stacknum,n);
}else{
switch(s[i]){
case '+':
//当字符栈为空或者当前符号的优先级大于栈顶符号时入栈
if(stackchar.top<0||stackchar.a[stackchar.top]!='+'&&stackchar.a[stackchar.top]!='-'&&stackchar.a[stackchar.top]!='*'&&stackchar.a[stackchar.top]!='/'&&stackchar.a[stackchar.top]!='^'){
charStackIn(&stackchar,s[i]);
}else{ //否则对'('前的表达式或者对当前栈中存储的表达式求值并放在栈顶
while(stackchar.a[stackchar.top]!='('&&stackchar.top>=0){
numStackOut(&stacknum,&num1);
numStackOut(&stacknum,&num2);
charStackOut(&stackchar,&char1);
compute(&stacknum,num1,num2,char1);
}
charStackIn(&stackchar,s[i]);
}
break;
case '-':
if(stackchar.top<0||stackchar.a[stackchar.top]!='+'&&stackchar.a[stackchar.top]!='-'&&stackchar.a[stackchar.top]!='*'&&stackchar.a[stackchar.top]!='/'&&stackchar.a[stackchar.top]!='^'){
charStackIn(&stackchar,s[i]);
}else{
while(stackchar.a[stackchar.top]!='('&&stackchar.top>=0){
numStackOut(&stacknum,&num1);
numStackOut(&stacknum,&num2);
charStackOut(&stackchar,&char1);
compute(&stacknum,num1,num2,char1);
}
charStackIn(&stackchar,s[i]);
}
break;
case '*':
if(stackchar.top<0||stackchar.a[stackchar.top]!='*'&&stackchar.a[stackchar.top]!='/'&&stackchar.a[stackchar.top]!='^'){
charStackIn(&stackchar,s[i]);
}else{
while(stackchar.a[stackchar.top]!='('&&stackchar.a[stackchar.top]!='+'&&stackchar.a[stackchar.top]!='-'&&stackchar.top>=0){
numStackOut(&stacknum,&num1);
numStackOut(&stacknum,&num2);
charStackOut(&stackchar,&char1);
compute(&stacknum,num1,num2,char1);
}
charStackIn(&stackchar,s[i]);
}
break;
case '/':
if(stackchar.top<0||stackchar.a[stackchar.top]!='*'&&stackchar.a[stackchar.top]!='/'&&stackchar.a[stackchar.top]!='^'){
charStackIn(&stackchar,s[i]);
}else{
while(stackchar.a[stackchar.top]!='('&&stackchar.a[stackchar.top]!='+'&&stackchar.a[stackchar.top]!='-'&&stackchar.top>=0){
numStackOut(&stacknum,&num1);
numStackOut(&stacknum,&num2);
charStackOut(&stackchar,&char1);
compute(&stacknum,num1,num2,char1);
}
charStackIn(&stackchar,s[i]);
}
break;
case '^':
if(stackchar.top<0||stackchar.a[stackchar.top]!='^'){
charStackIn(&stackchar,s[i]);
}else{
while(stackchar.a[stackchar.top]!='+'&&stackchar.a[stackchar.top]!='-'&&stackchar.a[stackchar.top]!='*'&&stackchar.a[stackchar.top]!='/'&&stackchar.a[stackchar.top]!='('&&stackchar.top>=0){
numStackOut(&stacknum,&num1);
numStackOut(&stacknum,&num2);
charStackOut(&stackchar,&char1);
compute(&stacknum,num1,num2,char1);
}
charStackIn(&stackchar,s[i]);
}
break;
//遇到左括号直接入栈
case '(':
charStackIn(&stackchar,s[i]);
break;
//遇到右括号计算括号中的值并且放在栈顶
case ')':
while(stackchar.a[stackchar.top]!='('&&stackchar.top>=0){
numStackOut(&stacknum,&num1);
numStackOut(&stacknum,&num2);
charStackOut(&stackchar,&char1);
compute(&stacknum,num1,num2,char1);
}
charStackOut(&stackchar,&char1);
break;
}
}
}
// 进行栈中剩余符号和数对应的值
while(stackchar.top>=0){
numStackOut(&stacknum,&num1);
numStackOut(&stacknum,&num2);
charStackOut(&stackchar,&char1);
compute(&stacknum,num1,num2,char1);
}
printf("%.2lf",stacknum.a[stacknum.top]);
}
//入栈
void numStackIn(numStack*p,double a)
{
if(p->top>=maxsize){
return;
}
p->a[++p->top]=a;
}
void charStackIn(charStack*p,char a)
{
if(p->top>=maxsize){
return;
}
p->a[++p->top]=a;
}
//出栈
void numStackOut(numStack*p,double *p1)
{
if(p->top<0){
return;
}
*p1=p->a[p->top];
p->a[p->top]=0;
p->top--;
}
void charStackOut(charStack*p,char *p1)
{
if(p->top<0){
return;
}
*p1=p->a[p->top];
p->a[p->top]=0;
p->top--;
}
//计算取出来的两个数和对应符号的值
void compute(numStack *p,double num1,double num2,char char1)
{
switch(char1){
case '+':
numStackIn(p,num2+num1);
break;
case '-':
numStackIn(p,num2-num1);
break;
case '*':
numStackIn(p,num2*num1);
break;
case '/':
numStackIn(p,num2/num1);
break;
case '^':
numStackIn(p,pow(num2,num1));
break;
}
}