1. 程式人生 > >動手敲程式碼——棧(經典問題練習)

動手敲程式碼——棧(經典問題練習)

/*用棧實現計算器*/ 
/*經典的用來練習棧的題目,需要藉助逆波蘭表示式*/

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

#define MAXSIZE 64
#define OK 1
#define ERROR 0

typedef struct
{
    int data[MAXSIZE];
    int top;
}stacknode;

/*建立一個順序棧*/
stacknode * sqstack_create(void)
{
    stacknode * p;

    p = (stacknode *)malloc(sizeof
(*p)); assert(p); //分配空間後加上斷言是個好習慣 p->top = -1; return p; } /*入棧操作*/ int sqstack_push(int n, stacknode * p) { if(p->top == (MAXSIZE - 1)) //棧滿 { return ERROR; } p->data[++p->top] = n; return OK; } /*出棧操作*/ int sqstack_pop(int *dest, stacknode * p) { if
(p->top == -1) //棧空 { return ERROR; } *dest = p->data[p->top--]; return OK; } /*獲取棧頂值*/ int sqstack_top(int *dest, stacknode *p) //const修飾指標*p,p指向的內容不可改變 { if(p->top == -1) //棧空 { return ERROR; } *dest = p->data[p->top]; return
OK; } /*列印棧中內容*/ int sqstack_print(stacknode *p) { int n = p->top; if(n == -1) //棧空 { return ERROR; } while(n) { printf(" %d ",p->data[n--]); } printf(" %d ",p->data[n]); printf("\n"); } /*判斷棧是否為空*/ int sqstack_is_empty(stacknode *p) { return (p->top == -1); } /*優先順序判斷函式*/ int get_priority(int ope) { switch (ope) { case '+': case '-':return 1; case '*': case '/':return 2; case '(':return 0; default:return ERROR; } } /*提取兩個數和一個操作符進行計算,得到的結果再壓棧*/ void compute(stacknode *pnum,int ope) { int num1,num2; int result; sqstack_pop(&num1,pnum); sqstack_pop(&num2,pnum); switch (ope) { case '+': result = num1 + num2; case '-': result = num1 - num2; case '*': result = num1 * num2; case '/': result = num1 / num2; } sqstack_push(result,pnum); } /*進行優先順序計算*/ void deal_ope(stacknode *pnum,stacknode *pope,int ope) { int old_ope; if(sqstack_is_empty(pope)||ope == '(') //當空棧或符號為( 時,將符號壓棧後返回 { sqstack_push(ope,pope); return; } sqstack_top(&old_ope,pope); //得到棧頂元素 if(get_priority(ope)>get_priority(old_ope)) //比較優先順序,入參的符號優先順序大於棧頂元素時, 將符號壓棧後返回 { sqstack_push(ope,pope); return; } while(get_priority(ope)<=get_priority(old_ope)) { sqstack_pop(&old_ope,pope); compute(pnum,old_ope); //以棧頂符號計算 後壓棧 if(sqstack_is_empty(pope)) { break; } sqstack_top(&old_ope,pope); } sqstack_push(ope,pope); //將新的操作符入棧 } //處理括號 ,進行括號裡的高優先順序計算,之後將計算結果壓入數字棧,並且將括號丟棄 void deal_bracket(stacknode *pnum,stacknode *pope) { int old_ope; sqstack_top(&old_ope,pope); //得到符號棧棧頂元素 while(old_ope != '(') { sqstack_pop(&old_ope,pope); //符號棧出棧 compute(pnum,old_ope); //計算後將結果壓入數字棧 sqstack_top(&old_ope,pope); //得到棧頂元素,進行下一次迴圈 } sqstack_pop(&old_ope,pope); //將( 出棧丟去 } int main() { /*str為表示式陣列*/ char str[MAXSIZE]; printf("請輸入你要計算的表示式:\n"); gets(str); int i = 0; int value = 0; //數字的值 int flag = 0; int old_ope; stacknode *pnum,*pope; // 定義兩個指向棧結構體的指標 pnum = sqstack_create(); // 建立存放數字的棧 pope = sqstack_create(); // 建立存放運算子號的棧 /* 表示式字串解析函式,然後將高優先順序的符號/(*)進行計算重新入棧 退出while大家的優先順序都一樣+-*/ while (str[i] != '\0') { //獲取輸入的數字 if (str[i] >= '0' && str[i] <= '9')//num { value = value * 10 + str[i] - '0'; flag = 1; } else//ope { if (flag) { //flag = 1說明value裡面儲存了數字,將其入棧 sqstack_push (value, pnum); //num標誌清零,value存放數字的變數清零 flag = 0; value = 0; } if(str[i] == ')') { //如果是右括號,則 deal_bracket(pnum,pope); } else//+-*/(等情況 { deal_ope(pnum,pope,str[i]); } } i++; } //如果flag = 1.說明value裡面還有數值,將其入棧 if (flag) { sqstack_push(value,pnum); } //然後將符號與數字依次出棧計算。數字出棧計算完成之後回再次在compute中入棧 while (!sqstack_is_empty(pope)) { sqstack_pop(&old_ope,pope); compute(pnum,old_ope); } //取出數字棧最後剩下的數字,就是最後的答案 sqstack_pop(&value,pnum); //列印結果 printf("%s = %d\n",str,value); return 0; }