codeup 1743: 演算法3-4:表示式求值
阿新 • • 發佈:2019-02-05
1743: 演算法3-4:表示式求值
題目描述
算數四則運算的規則是1)先乘除,後加減;2)從左算到右;3)先括號內,後括號外。 由此,算式4+2*3-10/5的計算順序為4+2*3-10/5=4+6-10/5=4+6-2=8。 給定一個以“#”作為結束符的算式,求出算式的結果。 給出嚴蔚敏《資料結構(C語言)》中的一段演算法描述以作參考: 圖1:表示式求值演算法 圖2:表示式求值演算法(續)圖3:表示式求值演算法(續)
輸入
以“#”結尾的表示式,運算數為正整數。每個表示式佔一行。
輸出
輸出表達式運算的結果。
樣例輸入
4+2*3-10/5# 3*(7-2)# 2*3/2#
樣例輸出
8
15
3
置運算子棧為空棧,表示式的起始符'#'為棧底元素
依次讀入表示式的每個字元,若是運算元則進OPND棧,若是運算子O則和OPTR棧的棧頂元素比較優先權後進行相應操作,直至整個表示式求值完畢(即OPTR棧的棧頂元素和當前讀入的字元均為'#').
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define N 1000+10
#define STACK_INIT_SIZE 100
#define STACKINCREMENT 10
#define OK 1
#define OVERFLOW 0
#define ERROR 0
char str[N];
typedef int Status;
typedef int SElemType;
typedef struct{
SElemType *base;
SElemType *top;
int stacksize;
}SqStack;
unsigned char prior[7][7] = {
{'>','>','<','<','<','>','>'},
{'>','>','<','<','<','>','>'},
{'>','>','>','>','<','>','>'},
{'>','>','>','>','<','>','>'},
{'<','<','<','<','<','=',' '},
{'<','<','<','<','<',' ','>'},
{'<','<','<','<','<',' ','='}};
char OPSET[7] = {'+','-','*','/','(',')','#'};
Status InitStack(SqStack *s)//初始化棧
{
s->base = (SElemType*)malloc(STACK_INIT_SIZE*sizeof(SElemType));
if(!s->base)
exit(OVERFLOW);
s->top = s->base ;
s->stacksize = STACK_INIT_SIZE;
return OK;
}
Status Push(SqStack *s,SElemType c)//入棧
{
if((s->top - s->base ) >= s->stacksize )
{
s->base = (SElemType*)realloc(s->base ,(s->stacksize +STACKINCREMENT)*sizeof(SElemType));
if(!s->base )
exit(OVERFLOW);
s->stacksize += STACKINCREMENT;
}
*(s->top)++ = c;
return OK;
}
Status GetTop(SqStack *s)//取棧頂元素
{
SElemType e;
if(s->base == s->top )
return ERROR;
e = *(s->top-1) ;
return e;
}
Status In(char c,char str[])//判斷是否為運算子
{
int i = 0;
while(c != str[i])
{
i++;
}
if(i < 7)
return OK;
return ERROR;
}
void Strcat(char *str1,char *str2)//字串連線函式,把字串str2連線到str1後
{
int i = 0, j = 0;
while(str1[i]!='\0')
{
i++;
}
while(str2[j]!='\0')
{
str1[i++] = str2[j++];
}
str1[i] = '\0';
}
Status Atoi(char *c)//把字串轉為數字
{
int data= 0,d = 0;
int i = 0;
while(c[i]!='\0')
{
data = data*10 + c[i]-'0';
i++;
}
return data;
}
Status precede(int a,char b)//判斷優先順序函式
{
int i = 0,j = 0;
while(OPSET[i] != a)
{
i++;
}
while(OPSET[j] != b)
{
j++;
}
return prior[i][j];
}
Status Pop(SqStack *s)//脫括號函式
{
int e;
if(s->base == s->top )
return ERROR;
e = *--(s->top);
return e;
}
Status Opereta(int a,int b,int c)//運算函式
{
switch(b)
{
case '+':
return a+c;
case '-':
return a-c;
case '*':
return a*c;
case '/':
return a/c;
}
}
int EvaluateExpression(char *MyExpression)//演算法3.4
{//算術表示式求值的算符優先演算法。
//設OPTR和OPND分別為運算子棧和運算數棧
SqStack OPTR;//運算子棧,字元元素
SqStack OPND;//運算數棧,實數元素
char TempData[20];
int data,a,b;
char *c,Dr[2],e;
int theta;
InitStack(&OPTR);
Push(&OPTR,'#');
InitStack(&OPND);
c = MyExpression;
TempData[0] = '\0';
while(*c != '#'|| GetTop(&OPTR) != '#')
{
if(!In(*c,OPSET))//不是運算子則進棧
{
Dr[0] = *c;
Dr[1] = '\0';
Strcat(TempData,Dr);
c++;
if(In(*c,OPSET))//是運算子時
{
data = Atoi(TempData);
Push(&OPND,data);
TempData[0] = '\0';
}
}
else
{
switch(precede(GetTop(&OPTR),*c))
{
case '<':
Push(&OPTR,*c);
c++;
break;
case '=':
Pop(&OPTR);
c++;
break;
case '>':
a = Pop(&OPND);
b = Pop(&OPND);
theta = Pop(&OPTR);
Push(&OPND,Opereta(b,theta,a));
break;
}
}
}
return GetTop(&OPND);
}
int main()
{
while(scanf("%s",str)!=EOF)
{
printf("%d\n",EvaluateExpression(str));
}
return 0;
}