這兩天要複習準備考試,博客沒有及時更新。另一方面,後綴表達式的轉化及求值的程序始終沒有寫好,讓我異常苦惱,心情也是莫名煩躁。現在表達式求值的程序已基本實現,仍有不足之處需要改進,各位可以參考,由於時間關係,無法細緻講解。將在考完試後的更新中加以補充,各位先看代碼後的註釋吧,註釋還是比較詳細的,代碼如下
#include<stdio.h>
#include<stdlib.h>
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAXSIZE 100
#define MAXOP 32
typedef char elemtype;
typedef int status;
/*定義運算符優先級*/
typedef struct calc{
elemtype ch;
int pri;
}calc;
/*同一運算符在棧內和棧外優先級不同,需要加一個數字進行區分*/
calc inpri[]={{'=',0},{'(',1},{'*',5},{'/',5},{'+',3},{'-',3},{')',6}};
calc outpri[]={{'=',0},{'(',6},{'*',4},{'/',4},{'+',2},{'-',2},{')',1}};
/*定義運算符棧*/
typedef struct sqstack{
elemtype data[MAXSIZE];
int top;
}sqstack;
/*定義運算結果棧*/
typedef struct value{
float suffixvalue[MAXSIZE];
int top;
}value;
/*定義棧操作
***************************************/
status traversestack(sqstack *s){
int i=0;
for(i=s->top;i>=0;i--){
printf("%d ",s->data[i]);
}
printf("\n");
}
/*初始化運算符棧*/
status initstack(sqstack *s){
s->top=-1;//置空棧
}
/*初始化運算結果棧*/
status initvstack(value *V){
V->top=-1;
return OK;
}
//將元素壓入棧
status push(sqstack *s,elemtype data)
{
if(s->top==MAXSIZE-1){
return ERROR;//判斷棧是否已滿
}
else{
s->top++;
s->data[s->top]=data;
}
return OK;
}
//返回棧長
status stacklength (sqstack *s){
return s->top+1;
}
//出棧
status pop(sqstack *s,elemtype * data){
if(s->top==-1){
printf("空棧\n");
return ERROR;
}
else{
*data=s->data[s->top];
s->top--;
}
}
/*取棧頂元素*/
status gettop(sqstack *S,elemtype *ch){
if(S->top==-1)
return ERROR;
else
*ch=S->data[S->top];
return OK;
}
/*定義棧操作結束
***************************************/
/*定義運算符相關操作
****************************************/
/*求棧外操作符優先級*/
status Inpri(elemtype op){
int i=0;
for(i=0;i<MAXOP;i++){
if(op==inpri[i].ch)
return inpri[i].pri;
}
}
/*求棧內操作符優先級*/
status Outpri(elemtype op){
int i=0;
for(i=0;i<MAXOP;i++){
if(op==outpri[i].ch)
return outpri[i].pri;
}
}
/*判斷兩運算符優先級關係*/
status precede(elemtype opin,elemtype opout){
if(Inpri(opin)>Outpri(opout))
return 1;
else if(Inpri(opin)<Outpri(opout))
return -1;
else
return 0;
}
/*判斷是否爲運算符*/
status isop(elemtype ch){
if(ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch=='('||ch==')')
return TRUE;
else
return FALSE;
}
/*將中綴表達式轉換爲後綴表達式*/
status trans(char * infix,char suffix[]){
sqstack S;
initstack(&S);
push(&S,'=');/*先讓一個等號入棧,作爲標記*/
char ch;
int i=0,j=0;
while(*infix!='\0'){
/*是數字的情況*/
if(!isop(*infix)){
while((*infix)>='0'&&(*infix)<='9'){
suffix[j++]=*infix;
infix++;
}
suffix[j++]='#';/*數字與數字之間用空格隔開*/
}
/*是運算符的情況*/
else{
gettop(&S,&ch);
switch(precede(ch,*infix)){
case 1:/*棧頂高於棧外*/
suffix[j++]=ch;/*棧頂出棧直到棧頂元素優先級低於棧外爲止*/
pop(&S,&ch);
//infix++;/*向後遍歷*/
break;
case 0:/*棧頂等於棧外,只有括號會出現此情況*/
pop(&S,&ch);/*直接出棧*/
infix++;
break;
case -1:/*棧頂低於棧外*/
push(&S,*infix);/*入棧即可*/
infix++;
break;
}
}
}/*while(*infix!='/0')*/
/*循環結束,開始輸出後綴表達式*/
pop(&S,&ch);
while(ch!='='){/*等號代表了表達式的開頭*/
suffix[j++]=ch;
pop(&S,&ch);
}
}
/*計算後綴表達式的值*/
float compute(char suffix[]){
value V;
initvstack(&V);
char ch;
int t=0;
float d;
ch=suffix[t];
t++;
while(ch!='\0'){
/*讓棧頂兩元素出棧進行運算*/
switch(ch){
case '+':
V.suffixvalue[V.top-1]=V.suffixvalue[V.top-1]+V.suffixvalue[V.top];
V.top--;
break;
case '-':
V.suffixvalue[V.top-1]=V.suffixvalue[V.top-1]-V.suffixvalue[V.top];
V.top--;
break;
case '/':
if(V.suffixvalue[V.top]){
V.suffixvalue[V.top-1]=V.suffixvalue[V.top-1]/V.suffixvalue[V.top];
V.top--;
break;
}
else{
printf("除零錯誤\n");
return ERROR;
}
case '*':
V.suffixvalue[V.top-1]=V.suffixvalue[V.top-1]*V.suffixvalue[V.top];
V.top--;
break;
/*如果後綴表達式中有數字*/
default:
d=0;
while(ch>='0'&&ch<='9'){
d=10*d+ch-'0';/*將字符轉換成數字*/
ch=suffix[t];/*向後遍歷*/
t++;
}
V.top++;
V.suffixvalue[V.top]=d;/*將轉換好的入棧*/
}
ch=suffix[t];/*更新ch的值*/
t++;
}
return V.suffixvalue[V.top];/*返回棧頂值作爲運算結果*/
}
int main(void){
char infix[]="(56-20)/(4+2)";
char suffix[200];
trans(infix,suffix);
printf("中綴表達式:%s\n",infix);
printf("後綴表達式:%s\n",suffix);
printf("後綴表達式的值爲%f",compute(suffix));
return 0;
}
再次吐槽:真心難啊…………
2016-04-21日更新:
今天覆習了表達式求值問題,還是感到存在一些問題,還是對算法的理解理解不夠透徹造成的。
問題主要出現在後綴表達式轉中綴表達式的過程中
status trans(char *infix,char suffix[]){
elemtype ch;
sqstack S;
int i=0;
initstack(&S);
push(&S,'=');
while(*infix!='\0'){
if(!isop(*infix)){
while(*infix<='9'&&*infix>='0'){
suffix[i++]=*infix;
infix++;
}
suffix[i++]='#';
}
else{
gettop(&S,&ch);
switch(precede(ch,*infix)){
case 1:
suffix[i++]=ch;
pop(&S,&ch);
break;
case 0:
pop(&S,&ch);
infix++;
break;
case -1:
push(&S,*infix);
infix++;
break;
}
}
}/*while(*infix!='\0')*/
pop(&S,&ch);
suffix[i]=ch;
while(ch!='='){
suffix[i++]=ch;
pop(&S,&ch);
}
}
在這段代碼的switch語句中,在處理case 0時,對於括號的優先級的理解有所遺忘。正確的處理方式是當棧外爲右括號,棧內爲左括號時,直接出棧即可。
在compute函數中,忘了寫default語句,導致當遇到後綴表達式中的數字時無法處理。
以上就是今天的錯誤,要引以爲戒。