計算表達式的值--順序棧(數據結構第二次實驗)


實驗題目:棧的應用-算術表達式求值                      

實驗環境:    Visual C++ 6.0                    

實驗目的 :

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) 函數In(c)的實現可以采用以下方式:

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) 根據實驗報告模板詳細書寫實驗報告,在實驗報告中給出 表達式求值算法的流程圖 。

(5) 上傳源程序到Sakai網絡教學平台。順序表的源程序保存為 calculator.cpp。

#include<stdio.h> 
#include<malloc.h>
#include<stdlib.h>
#include<string.h>
#define OVERFLOW -2
#define MAXSIZE 100
#define OK 1 
#define ERROR 0
#define TRUE 1
#define FALSE 0
#include<iostream>
using namespace std;

typedef int Status;
typedef char SElemType;

//--------順序棧的存儲結構------
typedef struct 
{
    SElemType *base;    //棧底指針 
    SElemType *top;    //棧頂指針 
    int stacksize;     //占可用的最大容量 
}SqStack; 


Status InitStack (SqStack &S)
{//構造一個空棧 
    S.base=new SElemType[MAXSIZE];   //為順序棧動態分配一個最大容量為MAXSIZE的數組空間 
    if (!S.base) exit(OVERFLOW);    //動態分配失敗
    S.top=S.base;     //top初始為base,空棧 
    S.stacksize=MAXSIZE;   //stacksize置為棧的最大容量MAXSIZE 
    return OK;
    
}

Status Push(SqStack &S,SElemType e) 
{//插入元素e為新的棧頂元素
    if(S.top-S.base==S.stacksize)   return ERROR;   //棧滿 
    *S.top++=e;    //元素e壓入棧頂,棧頂指針加1 
    return OK;
    
}

Status Pop(SqStack &S,SElemType &e)
{//刪除s的棧頂元素,用e返回其    
    if (S.top==S.base)  return ERROR;  //棧頂 
    e=*--S.top;   // 棧頂指針減1,將棧頂元素為e 
    return OK;
    
} 

SElemType GetTop(SqStack S) 
{//返回S的棧頂元素,不修改棧頂指針、
    if(S.top!=S.base)   //棧非空
        return *(S.top-1);   //返回棧頂元素的值,棧頂指針不變 
    
}


Status In(SElemType c)
{
    switch(c)          //判斷讀入的字符是哪一種運算符, 
    {
        case '+':
            return TRUE;
            break; 
        case '-':
            return TRUE;
            break;
        case '*':
            return TRUE;
            break;
        case '/':
            return TRUE;
            break;
        case '(':
            return TRUE;
            break;
        case ')':
            return TRUE;
            break;
        case '#':
            return TRUE;
            break;
        default:
            return FALSE;
            
    }
}

SElemType Precede(SElemType t1,SElemType t2)
{
    SElemType f;       
    switch(t2)     //判斷運算符棧的棧頂元素和讀入的運算符之間誰的優先級更高,並返回結果 
    {
        case '+':
            if (t1=='('||t1=='#')
                f='<';
            else
                f='>';
            break;
            
        case '-':
            if (t1=='('||t1=='#')
                f='<';
            else
                f='>';
            break;
            
        case '*':
            if (t1=='+'||t1=='-'||t1=='('||t1=='#')
                f='<';
            else
                f='>';
            break;
            
        case '/':
            if (t1=='+'||t1=='-'||t1=='('||t1=='#')
                f='<';
            else
                f='>';
            break;
                
        case '(':
            if (t1=='+'||t1=='-'||t1=='('||t1=='#'||t1=='*'||t1=='/')
                f='<';
            break;
            
        case ')':
            if (t1=='+'||t1=='-'||t1=='*'||t1=='/'||t1==')')
                f='>';
            else if (t1=='(')
                f='=';
            break;
            
        case '#':
            if (t1=='#')
                f='=';
            else
                f='>';
            break;    
        default:
            cout<<"輸入超出范圍。。。";
        
    }
    return f;
}


SElemType Operate(SElemType a,SElemType theta,SElemType b)
{    
    SElemType c;
    a=a-'0';      //因為a,b均為字符型,所以轉化成int型 
    b=b-'0';
    switch(theta)
    {
        case '+':
            c=a+b+'0';break;        //再將計算的結果轉化為字符型 
        case '-':
            c=a-b+'0';break;
        case '*':
            c=a*b+'0';break;
        case '/':
            c=a/b+'0';break;        
    }
    return c;   //返回計算結果 
}

char EvaluateExpression()
{//算數表達式求值的算符優先算法,設OPTR和 OPND分別為運算符棧和操作數棧
    SqStack OPND,OPTR;
    char ch,theta,a,b,c,x,w;
    InitStack(OPND);  //初始化OPND棧 
    InitStack(OPTR);  //初始化OPTR棧 
    Push(OPTR,'#');   //將表達式起始符“#”OPTR棧 
    cin>>ch;
    while (ch!='#'||GetTop(OPTR)!='#')    //表達式沒有掃描完畢或者OPTR的棧頂元素不為“#” 
    {
        if (!In(ch))     //判斷ch是不是運算符,不是則壓入OPND棧 
            {
                Push(OPND,ch);
                cin>>ch;
            }
        else
            switch(Precede(GetTop(OPTR),ch))   // 比較OPTR的棧頂元素和ch的優先級 
            {
                case '<':
                    Push(OPTR,ch);        //當前字符ch壓入OPTR棧 ,讀入下一個字符ch 
                    cin>>ch;
                    break;
                case '>':
                    Pop(OPTR,theta);    //彈出OPTR棧頂的運算符 
                    Pop(OPND,b);        //彈出OPND棧頂的運算數, 
                    Pop(OPND,a);        //彈出OPND棧頂的運算數,
                    Push(OPND,Operate(a,theta,b));     //將運算結果壓入OPND棧 
                    break;
                case '=':               //OPTR的棧頂元素是“(”且ch是“)”
                    Pop(OPTR,x);        //彈出OPTR棧頂的"(",
                    cin>>ch;            //讀入下一個字符ch 
                    break;
                
            }
    }
    return GetTop(OPND);              //OPND棧頂元素即為表達式求值結果 
    
}
int main()
{
    char w;
    cout<<"請輸入算數表達式,並以#結束\n";
    w=EvaluateExpression();    //將運算結果賦值給w 
    w=w-48;         //將字符轉換成數字 
    printf("The result of expression is %d\n",w); 
                   
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM