資料結構第二次作業(表示式求值【棧模擬】)
實驗題目:棧的應用-算術表示式求值
實驗目的 :
1.掌握棧的定義及實現;
2.掌握利用棧求解算術表示式的方法。
實驗內容:
通過修改完善教材中的演算法3.4,利用棧來實現算術表示式求值的演算法。對演算法3.4中呼叫的幾個函式要給出其實現過程:
(1) 函式In(c):判斷c是否為運算子;
(2) 函式Precede(t1,t2):判斷運算子t1和t2的優先順序;
(3) 函式Operate(a,theta,b):對a和b進行二元運算theta。
程式執行時,輸入合法的算術表示式(中間值及最終結果要在0~9之間,可以包括加減乘除和括號),便可輸出相應的計算結果。如下圖:
實驗提示 :(僅供參考,每個函式的具體實現可以有多種方法,希望有創新)
1. 將棧的定義和實現單獨儲存在標頭檔案“stack.h”中,然後在表示式求值的源程式中包含此標頭檔案(即#include“stack.h”)。
2.表示式求值源程式的具體實現
(1) 主函式如下:
void main()
{
Printf(“請輸入算術表示式,並以#結束.\n”);
Printf(“the result of expression is:%d\n”,EvaluateExpression());
}
(2) 函式EvaluateExpression的實現見演算法3.22
(3)
Status In(SElemType c)//應在前面有定義typedef char SElemType;
{ // 判斷c是否為運算子
switch(c)
{
case'+':return TRUE;
……//補充完整
default:return FALSE;
}
}
(4) 函式Precede(t1,t2)的實現可以採用以下形式:
SElemType Precede(SElemType t1,SElemType t2)
{ //根據教材表3.1,判斷兩個運算子的優先關係
SElemType f;
switch(t2)
{
case '+':
case '-':if(t1=='('||t1=='#')
f='<';
else
f='>';
break;
……//補充完整
}
return f;
}
(5) 函式Operate(a,theta,b)的實現可以採用以下方式:
SElemType Operate(SElemType a,SElemType theta,SElemType b)
{
SElemType c;
a=a-48;
b=b-48;
switch(theta)
{
case'+':c=a+b+48;
break;
……//補充完整
}
return c;
}
選做內容:進一步改進,使表示式的中間值及最終結果不侷限於0~9之間的個位數。(如果完成要在實驗報告中註明),如下圖:
實驗要求 :
(1) 程式要新增適當的註釋,程式的書寫要採用縮排格式。
(2) 程式要具在一定的健壯性,即當輸入資料非法時, 程式也能適當地做出反應。
(3) 程式要做到介面友好,在程式執行時使用者可以根據相應的提示資訊進行操作。
(4) 根據實驗報告模板詳細書寫實驗報告,在實驗報告中給出表示式求值演算法的流程圖。
#include<stdio.h>
#include<string.h>
#include<malloc.h>
#include<stdlib.h>
#include<stack>
#include<iostream>
#define OK 1
#define ERROR 0
#define OVERFLOW -2
#define MAXSIZE 100
using namespace std;
int In(char ch) // 判斷輸入字元是否為運算子
{
if(ch=='+') return OK;
if(ch=='-') return OK;
if(ch=='*') return OK;
if(ch=='/') return OK;
if(ch=='(') return OK;
if(ch==')') return OK;
if(ch=='#') return OVERFLOW;
return ERROR;
}
char Precede(char a,char b) // 比較符號 a與符號 b的優先順序.如 a 優於 b,則返回 ' > ',否則返回 ' < ' 或 ' = '
{
if(b=='+')
{
if(a=='('||a=='#') return '<';
return '>';
}
if(b=='-')
{
if(a=='('||a=='#') return '<';
return '>';
}
if(b=='*')
{
if(a=='*'||a=='/'||a==')') return '>';
return '<';
}
if(b=='/')
{
if(a=='*'||a=='/'||a==')') return '>';
return '<';
}
if(b=='(') return '<';
if(b==')')
{
if(a=='(') return '=';
return '>';
}
if(b=='#')
{
if(a=='#') return '=';
return '>';
}
}
double Operate(double a,char theta,double b) // 把 a、b進行二元運算
{
if(theta=='+') return a+b;
if(theta=='-') return a-b;
if(theta=='*') return a*b;
if(theta=='/') return a/b;
}
double EvaluateExpression() // 計算過程
{
char str[10010];
stack<double> OPND;
stack<char> OPTR;
scanf("%s",str);
OPTR.push('#');
double a,b,shu=0;
int flag=0;
char theta;
for(int i=0;str[i];i++)
{
if(In(str[i])==0)
{
shu=shu*10+str[i]-'0';
flag=1;
}
else
{
if(flag)
{
OPND.push(shu);
shu=0;
flag=0;
}
switch(Precede(OPTR.top(),str[i]))
{
case '<':
OPTR.push(str[i]);
break;
case '>':
theta=OPTR.top(); OPTR.pop();
b=OPND.top(); OPND.pop();
a=OPND.top(); OPND.pop();
OPND.push(Operate(a,theta,b));
i--; // 這裡是因為判斷的該符號 str[i] 還沒有入棧,故需要回去判斷一下
break;
case '=':
OPTR.pop();
break;
}
}
}
return OPND.top();
}
int main()
{
printf("\n************************************************************************\n\n");
puts("溫馨提醒:\n");
puts(" 為了方便,請您在輸入表示式的結尾加一個符號 '#',以判斷您的輸入完成");
puts("\n 如若忘了輸入結束字元 '#',結果可能有誤");
printf("\n************************************************************************\n\n");
puts("\n請輸入您想要計算的表示式:\n");
printf("\n計算結果為:%.2lf\n",EvaluateExpression());
puts("\n\n\n\n謝謝您的使用,請按任意鍵退出");
system("pause");
return 0;
}