中缀表达式即普通的运算式子,运算符是以中缀形式处于操作数的中间(例:3 + 4),后缀表达式就是逆波兰式(例:3 4 +),中缀表达式转后缀表达式也是学习数据结构中的栈的时候一个典型的例子,结合上一次写到逆波兰式。可以用这种原理即输入普通式子(即中缀表达式),转换成后缀表达式,然后通过后缀表达式(逆波兰式)的计算,可以得出结果。
1 #include <stdio.h> 2 #include <stdlib.h> 3 #define STACK_INIT_SIZE 20 4 #define STACK_INCREMENT 10 5 typedef char ElemType; 6 typedef char Status; 7 8 typedef struct 9 { 10 ElemType *base; 11 ElemType *top; 12 int stacksize; 13 }SqStack; 14 15 Status InitStack( SqStack *S ) 16 { 17 S->base = ( ElemType *) malloc ( STACK_INIT_SIZE*sizeof( ElemType ) ); 18 S->top = S->base ; 19 S->stacksize = STACK_INIT_SIZE; 20 21 return 0; 22 } 23 24 //插入元素e,即入栈 25 Status Push( SqStack *S , ElemType e ) 26 { 27 if ( S->top - S->base >= S->stacksize ) //当前容量大于或等于最大容量 28 { 29 //追加栈的空间 30 S->base = ( ElemType *) realloc ( S->base, S->stacksize + STACK_INCREMENT*sizeof( ElemType ) ); 31 if ( !S->base ) 32 return -1; 33 S->top = S->base + S->stacksize ; 34 S->stacksize = S->stacksize + STACK_INCREMENT; 35 36 } 37 //开始赋值 38 *S->top = e; 39 S->top++; 40 41 return 0; //注意返回值为0,不是e 42 } 43 44 //弹出元素e,即出栈 45 Status Pop ( SqStack *S , ElemType *e )//此处S为结构体指针的变量,所以访问结构体成员用"->" 46 { 47 //首先判断栈内是否为空 48 if ( S->top == S->base ) 49 return -1 ; 50 51 --S->top ; 52 *e = *S->top ; 53 54 return *e; //注意返回值为e,不是0 55 } 56 57 int StackLen ( SqStack S )//S为结构体变量,所以访问结构体成员用"." 58 { 59 return ( S.top - S.base ); 60 } 61 62 int main() 63 { 64 SqStack s; 65 char c,e; 66 InitStack(&s); 67 printf("请按中缀表达式输入式子,以'#'作为结束符: "); 68 scanf("%c",&c); 69 while(c!='#') 70 { 71 while(c>='0'&&c<='9') 72 { 73 printf("%c",c); 74 scanf("%c",&c); 75 if(c<'0'||c>'9') 76 { 77 printf(" "); 78 } 79 } 80 if(')'==c) 81 { 82 Pop(&s,&e); 83 while('('!=e) 84 { 85 printf("%c ",e); 86 Pop(&s,&e); 87 } 88 } 89 else if('+'==c||'-'==c) 90 { 91 if(!StackLen(s)) 92 { 93 Push(&s,c); 94 } 95 else 96 { 97 do 98 { 99 Pop(&s,&e); 100 if('('==e) 101 { 102 Push(&s,e); 103 } 104 else 105 { 106 printf("%c ",e); 107 } 108 }while(StackLen(s)&&'('!=e); 109 Push(&s,c); 110 } 111 } 112 113 else if('*'==c||'/'==c||'('==c) 114 { 115 Push(&s,c); 116 } 117 else if('#'==c) 118 { 119 break; 120 } 121 else 122 { 123 printf(" 出错"); 124 return -1; 125 } 126 scanf("%c",&c); 127 } 128 while(StackLen(s)) 129 { 130 Pop(&s,&e); 131 printf("%c ",e); 132 } 133 return 0; 134 }
上面程序中几个注意点:一是出现iif(')'==c)的表达式,将')'写在了'=='的左边,这有助于调试发现错误,防止有些程序员将'=='打成'=';不然的话即使打成c=')'编译器也不会发现错误,认为是赋值,而')'=c这样的式子式错误的,因为无法将变量赋值给常数;二是入栈函数(Push)和出栈函数(Pop)作为子函数式写有关栈的程序的必备子程序,可以将他们制作成头文件,以后可以直接调用。三是编程的格式,因为while().if(),
else if()这样的语句太多,还有"{}"也很多,格式整齐了就不易出错并且便于调试发现错误。
运算结果中有空格,这也是需要在程序中改进的。