1. 程式人生 > >codeup 1743: 演算法3-4:表示式求值

codeup 1743: 演算法3-4:表示式求值

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;
 }