用c語言做一個棧,完成逆波蘭表示式
阿新 • • 發佈:2019-01-23
先用c語言,實現了一個棧結構,在用棧完成逆波蘭表示式。 包含中綴表示式 -》 字尾表示式, 用棧完成計算。
// main.m // 逆波蘭表示式 // // Created by 郭朝順 on 2018/5/10星期四. // Copyright © 2018年 樂樂. All rights reserved. // #import <Foundation/Foundation.h> #include <stdio.h> #include <stdlib.h> typedef struct Node { double data; struct Stack * next; } Node; typedef struct Stack { Node * data; int count; } Stack; Stack * s ; // 生成棧 void initStack() { s = (Stack *)malloc(sizeof(Stack)); s->count = 0; s->data = NULL; } // 入棧,push void push(double data) { printf("%f 即將被入棧\n",data); Node * n = malloc(sizeof(Node)); n->data = data; n->next = s->data; s->data = n; s->count ++; } // 出棧,pop double pop() { if(s->data == NULL) { printf("已經是空棧了\n"); return CGFLOAT_MAX; } Node * n = s->data; double r = n->data; printf("資料 %f 即將出棧\n",n->data); s->data=n->next; free(n); s->count--; return r; } // 清空棧 void clearStack() { while (s->data != NULL) { pop(); } } // 獲取棧頂元素 double topItem() { if (s->data==NULL) { printf("此棧為空棧\n"); return CGFLOAT_MAX; } printf("此棧中元素數量為 %d 個,棧頂為 %f\n",s->count,s->data->data); return s->data->data; } // 把字串轉成double,沒有做錯誤檢測,比如使用者輸入 12.35.5 5abc.64,就會出錯。 double charToDouble(char * num) { double a = 0.0; // 把一個字串轉成浮點型數字,記錄小數點後的位數,忽略小數點轉成整數, // 然後用這個整數 除以小數點後的位數,即可得到浮點數 int havePoint = 0; //這個數中是否有小數點 int j=0; // 記錄小數點後面有幾位的 for(int i=0; num[i]!='\0'; i++) { if(num[i]=='.') { havePoint = 1; continue; } if(havePoint==1) { j++; } a = a * 10 + num[i] - '0'; } while(j>0) { a = a/10; j--; } printf("字串%s 轉成 浮點數 %f\n",num,a); return a; } int main() { initStack(); // char * str = "3*4/2*3"; char str[100] ; printf("輸入一串表示式\n"); // 鍵盤要換成英文輸入,不然無法輸入。哭... gets(str); // 記錄逆波蘭表示式的結果, // 結構是 【0或1】 【對應值】,由於加減乘除 都是char型別,char -> int -> double,所以用double儲存。 // 0 表示是數字型別, 1 表示後面的是符號型別 , // 40 = ( 41 = ) 42 = * 43 = + 45 = - 47 = / // double niBoLan[100]={0.0}; int niI = 0; // 逆波蘭表示式的下標 char num[100] = "\0"; // 把字串匯出數字使用, int j = 0;//記錄這個數字char的長度,比如 12.3 就會記錄為4 for(int i=0; str[i]!='\0'; ) { // 區分出是數字還是符號 if ((str[i]<='9'&&str[i]>='0') || str[i]=='.') { // 把數字轉換出來 while ((str[i]<='9'&&str[i]>='0') || str[i]=='.') { char a = str[i]; num[j]=a; j++; num[j]='\0'; i++; } double b = charToDouble(num); num[99] ="\0"; j=0; niBoLan[niI] = 0; niI ++; niBoLan[niI] = b; niI ++; } else { char a = str[i]; switch (a) { case '+': case '-': while(topItem()=='*'||topItem()=='/'||topItem()=='+'||topItem()=='-'){ niBoLan[niI] = 1; niI ++; niBoLan[niI] = pop(); niI++; } push(a); break; case '*': case '/': while(topItem()=='*'||topItem()=='/'){ niBoLan[niI] = 1; niI ++; niBoLan[niI] = pop(); niI++; } push(a); break; case '(': push(a); break; case ')': while(topItem()!='('){ niBoLan[niI] = 1; niI ++; niBoLan[niI] = pop(); niI++; } pop(); // 需要把 ( 彈出 break; } i++; } } // 棧中剩餘的符號彈出 while (s->data != NULL) { niBoLan[niI] = 1; niI ++; niBoLan[niI] = pop(); niI++; } for(int i = 0;i<niI;i++) { printf("%f ",niBoLan[i]); } printf("\n逆波蘭轉換完畢,檢查一下\n"); clearStack(); printf("\n清空棧結構,開始計算結果\n"); double num1; double num2; for(int i = 0;i<niI;i+=2) { // 判斷標誌位, 0 是數字, 1 是符號。 int isChar = niBoLan[i]; if(isChar == 0 ) { // 數字直接入棧 push(niBoLan[i+1]); } else { char a = niBoLan[i+1]; switch (a) { case '+': push( pop() + pop() ); break; case '-': num1 = pop(); num2 = pop(); push( num2 - num1 ); break; case '*': push( pop() * pop() ); break; case '/': num1 = pop(); num2 = pop(); push( num2 / num1 ); break; } } } printf("\n計算結果 %f\n",pop()); } /* */