1. 程式人生 > >算術表示式求值

算術表示式求值

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <conio.h>
#include <ctype.h>
#define OK 1
#define ERROR 0
#define STACK_INIT_SIZE 100
//#define STACKINCREMENT 10

//========================================================
//        以下定義兩種棧,分別存放運算子和數字
//========================================================

//*******************運算子棧部分*************************

struct SqStack  //定義棧
{
    char  *base;  //棧底指標
    char  *top;  //棧頂指標
    int   stacksize;  //棧的長度
};

int InitStack (SqStack &s)  //建立一個空棧S
{
   if (!(s.base = (char *)malloc(50 * sizeof(char))))
     exit(0);
    s.top=s.base;
    s.stacksize=50;
    return OK;
}

char  GetTop(SqStack s,char &e)  //運算子取棧頂元素
{

  if (s.top==s.base)   //棧為空的時候返回ERROR
  {
	  printf("運算子棧為空!\n");
	  return ERROR;
  }
  else
	  e=*(s.top-1);  //棧不為空的時候用e做返回值,返回S的棧頂元素,並返回OK
      return OK;
}

int Push(SqStack &s,char e) //運算子入棧
{

    if (s.top-s.base >= s.stacksize)
	{
		printf("運算子棧滿!\n");

		s.base=(char*)realloc (s.base,(s.stacksize+5)*sizeof(char) );  //棧滿的時候,追加5個儲存空間
        if(!s.base) exit (OVERFLOW);

		s.top=s.base+s.stacksize;
        s.stacksize+=5;
	}
	*(s.top)++=e;  //把e入棧
	return OK;
}

int Pop(SqStack &s,char &e) //運算子出棧
{
	if (s.top==s.base)  //棧為空棧的時候,返回ERROR
	{
	  printf("運算子棧為空!\n");
	  return ERROR;
	}
    else
	{
		e=*--s.top;  //棧不為空的時候用e做返回值,刪除S的棧頂元素,並返回OK
		return OK;
	}
}

int StackTraverse(SqStack &s) //運算子棧的遍歷
{
	char *t;
	t=s.base ;
	if (s.top==s.base)
	{
	  printf("運算子棧為空!\n");  //棧為空棧的時候返回ERROR
	  return ERROR;
	}
	while(t!=s.top)
	{
		printf(" %c",*t); //棧不為空的時候依次取出棧內元素
        t++;
	}
    return ERROR;
}


//**********************數字棧部分***************************

 struct SqStackn //定義數棧
{
    int  *base;  //棧底指標
    int  *top;   //棧頂指標
    int   stacksize;  //棧的長度
};

int InitStackn (SqStackn &s)  //建立一個空棧S
{
    s.base=(int*)malloc(50*sizeof(int));
    if(!s.base)exit(OVERFLOW);  //儲存分配失敗
    s.top=s.base;
    s.stacksize=50;
    return OK;
}


int  GetTopn(SqStackn s,int &e) //數棧取棧頂元素

{
  if (s.top==s.base)
  {
	  printf("運算數棧為空!\n"); //棧為空的時候返回ERROR
	  return ERROR;
  }
  else
	  e=*(s.top-1); //棧不為空的時候,用e作返回值,返回S的棧頂元素,並返回OK
      return OK;
}

int Pushn(SqStackn &s,int e) //數棧入棧
{
    if (s.top-s.base >=s.stacksize)
	{
		printf("運算數棧滿!\n"); //棧滿的時候,追加5個儲存空間

		s.base=(int*)realloc (s.base,(s.stacksize+5)*sizeof(int) );
        if(!s.base) exit (OVERFLOW);

		s.top=s.base+s.stacksize; //插入元素e為新的棧頂元素
        s.stacksize+=5;
	}
	*(s.top)++=e; //棧頂指標變化
	return OK;
}

int Popn(SqStackn &s,int &e) //數棧出棧
{
	if (s.top==s.base)
	{
	  printf(" 運算子棧為空!\n"); //棧為空棧的視時候,返回ERROR

	  return ERROR;
	}
    else
	{
		e=*--s.top;  //棧不空的時候,則刪除S的棧頂元素,用e返回其值,並返回OK
		return OK;
	}
}

int StackTraversen(SqStackn &s) //數棧遍歷

{
	int *t;
	t=s.base ;
	if (s.top==s.base)
	{
	  printf(" 運算數棧為空!\n"); //棧為空棧的時候返回ERROR
	  return ERROR;
	}
	while(t!=s.top)
	{
		printf(" %d",*t); //棧不為空的時候依次輸出
        t++;
	}
    return ERROR;
}

//========================================================
//                    以下定義函式
//========================================================


int Isoperator(char ch) //判斷是否為運算子,分別將運算子和數字進入不同的棧
{
	switch (ch)
	{
	case '+':
	case '-':
	case '*':
	case '/':
	case '(':
	case ')':
	case '#':
		return 1;
	default:
		return 0;
	}
}

int Operate(int a, char op, int b) //運算操作
{
	int result;
	switch(op)
	{
	case '+':
		result=a+b;
		break;
	case '-':
		result=a-b;
		break;
	case '*':
		result=a*b;
		break;
	case '/':
		result=a/b;
		break;
	}
	return result;
}

char Precede(char ch1, char ch2) //運算子優先順序的比較
 {
   char p;
   switch(ch1)
   {
     case '+':
     case '-':
		 if (ch2=='+'||ch2=='-'||ch2==')'||ch2=='#')
                p = '>';                 //ch1運算子的優先順序小於ch2運算子
		      else
                p = '<';
			  break;

     case '*':
     case '/':
		 if (ch2 == '(')
                p = '<';
		      else
                p = '>';
			  break;

     case '(':
		 if (ch2 == ')')
				p = '=';
		      else if (ch2 == '#')
			  {
				printf(" 表示式錯誤!運算子不匹配!\n") ;
				exit(0);
			  }
			  else
				p = '<';
			  break ;

	 case ')':
		 if (ch2 == '(')
			  {
				printf(" 表示式錯誤!運算子不匹配!\n") ;
				exit(0);
			  }
		      else
		    	p = '>';
			  break ;

     case '#':
		 if (ch2 == ')')
              {
				 printf(" 表示式錯誤!運算子不匹配!\n") ;
				 exit(0);
			  }
		      else if (ch2 == '#')
				p = '=';
			  else
				p='<';
			  break;
   }
   return p;
  }

//========================================================
//                    以下是求值過程
//========================================================
int EvaluateExpression()               //參考書p53演算法3.4
 {
   int a, b, temp, answer;
   char ch,op,e;
   char *str;
   int  j = 0;
   SqStackn OPND;  //OPND為運算數字棧
   SqStack OPTR;   //OPTR為運算子棧
   InitStack(OPTR);
   Push(OPTR,'#');  //,所以此棧底是'#',因為運算子棧以'#'作為結束標誌
   InitStackn(OPND);

  // printf("\n\n按任意鍵開始求解:\n\n");
  // ch=getch();
   printf("\n請輸入表示式並以'#'結束:\n");
   str =(char*)malloc(50*sizeof(char));
   gets(str);
   ch=str[j];  //ch是字元型的,而e是整型的整數
   j++;

   GetTop(OPTR,e);  //e為棧頂元素返回值

   while (ch!='#' || e!='#')
   {
	   if (!Isoperator(ch))   //遇到數字,轉換成十進位制並計算
	 {
		 temp=ch-'0';  //將字元轉換為十進位制數
		  ch=str[j];
		  j++;
		  while(!Isoperator(ch))
		  {
			  temp=temp*10 + ch-'0';  //將逐個讀入運算數的各位轉化為十進位制數
			  ch=str[j];
			  j++;
		  }
		  Pushn(OPND,temp);
	 }

	   else if (Isoperator(ch))  //判斷是否是運算子,不是運算子則進棧


		 switch (Precede(e,ch))
       {
         case '<' : Push(OPTR,ch);  // 棧頂元素優先權低
			        ch = str[j++];
					printf("\n\n 運算子棧為:\n");  //輸出棧,顯示棧的變化
					StackTraverse(OPTR);
					printf("\n 運算數棧為:\n");
					StackTraversen(OPND);
					break;
		 case '=' : Pop(OPTR,op);  // 脫括號並接收下一字元
			        ch = str[j++] ;
					printf("\n\n 運算子棧為:\n");
					StackTraverse(OPTR);
					printf("\n 數棧為:\n");
					StackTraversen(OPND);
					break;
		 case '>' : Pop(OPTR,op);       //彈出最上面兩個,並運算,把結果進棧
			        Popn(OPND,b);
					Popn(OPND,a);
					Pushn(OPND,Operate(a,op,b));
					printf("\n\n 運算子棧為:\n");
					StackTraverse(OPTR);
					printf("\n 數棧為:\n");
					StackTraversen(OPND);
       }
       else
	   {
         printf("您的輸入有問題,請檢查重新輸入!");
		 exit(0);
	   }

	   GetTop(OPTR,e);   //取出運算子棧最上面元素是否是'#'

   }  //while
   GetTopn(OPND,answer);             //已輸出。數字棧最上面即是最終結果
   return answer;
}


//========================================================
//                      執行部分
//========================================================
void ShowMenu()
{
	printf("\n\n");
	printf(" 表示式求值系統\n");
}
void Quit();
void Manage()
{
	int answer;
//	ShowMenu();
	answer=EvaluateExpression();
	printf("\n\n表示式結果是:  %d\n",answer);
	Quit();
}
void Quit()
{
	char ch;
    printf("   本次運算結束。\n");
    printf("   繼續本系統嗎?\n\n");
	printf(" 繼續運算請按Y/y  ");
	printf("\n 退出程式請按N/n  ");
	printf(" \n___________________________________________________________________\n");

	ch=getch();
	ch=toupper(ch);  //將ch字元轉換成大寫字母

	if(ch == 'N')
	{
		printf("\n\n 系統退出。\n");
		exit(0);
	}
	Manage();
}

int main()
{
	ShowMenu();
    Manage();
	return 0;
}