1. 程式人生 > >用c語言做一個棧,完成逆波蘭表示式

用c語言做一個棧,完成逆波蘭表示式

先用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());

    

}

/*

 

 

 */