栈的应用2——超级计算器(中缀与后缀表达式)C语言
输入中缀表达式输出结果(结果可以是小数,但输入必须是整数)
1 #include<stdio.h> 2 #include<stdlib.h> //需要两个栈,一个储存结果,一个储存运算符 3 #define newpc (stype *)malloc(sizeof(stype)) 4 #define newpi (inttype *)malloc(sizeof(inttype)) //定义两个申请地址的宏 5 typedef struct char_stack 6 { 7 char dat; 8 struct _stack * next; 9 } stype; 10 typedef struct int_stack 11 { 12 double dat; 13 struct _stack * next; //建立两个栈类型 14 } inttype; 15 void charpush(stype** stacktop,char c) //运算符压栈函数,需要传进栈顶指针本身的地址,而不是它指向的地址 16 { 17 stype * ss=newpc; 18 ss->dat=c; 19 ss->next=*stacktop; 20 *stacktop=ss; 21 } 22 char charpop(stype** stacktop) //运算符出栈函数 23 { 24 char c=(*stacktop)->dat; 25 stype *ss=(*stacktop); 26 (*stacktop)=(*stacktop)->next; 27 free(ss); 28 return c; 29 } 30 void intpush(inttype** stacktop,double c) //数字压栈函数 31 { 32 inttype * ss=newpi; 33 ss->dat=c; 34 ss->next=*stacktop; 35 *stacktop=ss; 36 } 37 double intpop(inttype** stacktop) //数字出栈函数 38 { 39 double c=(*stacktop)->dat; 40 inttype *ss=(*stacktop); 41 (*stacktop)=(*stacktop)->next; 42 free(ss); 43 return c; 44 } 45 void tanchu(char c,inttype ** stacktop) //弹出字符,然后运算,然后进栈 46 { 47 double a=intpop(stacktop); 48 double b=intpop(stacktop); 49 if (c=='+') intpush(stacktop,b+a); 50 else if (c=='-') intpush(stacktop,b-a); 51 else if (c=='*') intpush(stacktop,b*a); 52 else if (c=='/') intpush(stacktop,b/a); 53 } 54 int tance(char c) //探测优先级的函数 55 { 56 if (c=='+'||c=='-') return 0; 57 else if (c=='*'||c=='/') return 1; 58 else if (c=='@'||c=='('||c==')') return -1; 59 } 60 int main() //主函数 功能:处理输入的中缀表达式,输出结果(过程中用到了后缀的转化) 61 { 62 stype * sig,* sigtop; 63 inttype * num,* numtop; //每个栈需要两个指针进行操作 64 char c=getchar(); 65 sig=newpc; 66 sig->dat='@'; 67 sig->next=NULL; 68 sigtop=sig; 69 num=newpi; 70 num->next=NULL; 71 numtop=num; //初始化两个栈 72 while (c!='\n') //一直读入,直至读到回车符结束 73 { 74 //接下来要对读入的当前字符进行处理 75 if (c>='0'&&c<='9') 76 { 77 int a=c-48; 78 c=getchar(); 79 while(c>='0'&&c<='9') 80 { 81 a=a*10+(c-48); 82 c=getchar(); 83 } 84 intpush(&numtop,a); //如果是个数字字符,就把这个数字一直读进去(因为不一定是几位数),然后压栈到num里 85 } 86 else if (c=='(') //如果是左括号,直接压栈到sig里 87 { 88 charpush(&sigtop,'('); 89 c=getchar(); 90 } 91 else if (c==')') //如果是右括号,就边弹栈边处理结果,直到遇到左括号 92 { 93 while (sigtop->dat!='(') 94 { 95 tanchu(charpop(&sigtop),&numtop); 96 } 97 c=getchar(); 98 charpop(&sigtop); 99 } 100 else if (c=='+'||c=='-'||c=='*'||c=='/') //如果是+-*/就比较与栈顶的优先级,如果高,直接压入,否则(等于也不能压入),边弹边处理结果,直到可以压入(和上面有点像) 101 { 102 int j=tance(c); 103 int k=tance(sigtop->dat); 104 if (j>k) 105 { 106 charpush(&sigtop,c); 107 c=getchar(); 108 } 109 else{ 110 while(j<=k) 111 { 112 tanchu(charpop(&sigtop),&numtop); 113 k=tance(sigtop->dat); 114 } 115 charpush(&sigtop,c); 116 c=getchar(); 117 } 118 } 119 else //否则,忽略这个符号 ,并且显示输入有误 120 { 121 c='\n'; 122 printf("输入有误\n"); 123 } 124 125 } 126 while (sigtop->dat!='@') //收收尾,把没有弹出的都处理一下 127 { 128 tanchu(charpop(&sigtop),&numtop); 129 } 130 printf("%.2lf\n",numtop->dat); 131 c=getchar(); 132 return 0; 133 }