1. 程式人生 > >棧之計算表示式值

棧之計算表示式值

演算法思想:

  1. 規定運算子的優先順序表
  2. 設定兩個棧,運算數棧,運算子棧。
  3. 輸入一個表示式,自左向右掃描,進行如下處理:若遇到運算數則進棧,若遇到運算子,則與運算子棧中的棧頂元素進行優先順序比較。1.如果當前運算子優先順序大於棧頂元素的優先順序,則當前運算子進棧。2.如果當前運算子的優先順序小於等於棧頂元素的優先順序,則運算子棧退棧一次,運算數棧退棧兩次,得到運算數a和運算數b和運算子op,執行運算後將得到的結果壓進運算數棧。

    先是兩個標頭檔案:
    NumLinkStack.h

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

typedef struct  Node1
{
    int
data; struct Node1 *next; }NumNode, *NumStack; int NumInitStack(NumStack *L) { (*L) = (NumNode *)malloc(sizeof(NumNode)); if (!(*L)) { return 0; } else { (*L)->next = NULL; return 1; } } int NumPush(NumStack L,int x) { NumNode *temp; temp = (NumNode *)
malloc(sizeof(NumNode)); if (!temp) { return 0; } temp->data = x; temp->next = L->next; L->next = temp; return 1; } int NumPop(NumStack L, int *x) { NumNode *temp; temp = L->next; if (temp==NULL) { return 0; } *x = temp->data; L->next
= temp->next; free(temp); return 1; } int NumGetTop(NumStack L) { if (L->next==NULL) { return 0; } else { return L->next->data; } }

OperaLinkStack.h

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

typedef struct  Node2
{
    char data;
    struct  Node2 *next;
}OperaNode, *OperaStack;

int OperaInitStack(OperaStack *L)
{
    (*L) = (OperaNode *)malloc(sizeof(OperaNode));
    if (!(*L))
    {
        return 0;
    }
    else
    {
        (*L)->next = NULL;
        return 1;
    }
}

int OperaPush(OperaStack L, char x)
{
    OperaNode *temp;
    temp = (OperaNode *)malloc(sizeof(OperaNode));
    if (!temp)
    {
        return 0;
    }

    temp->data = x;
    temp->next = L->next;
    L->next = temp;
    return 1;
}

int OperaPop(OperaStack L, char *x)
{
    OperaNode *temp;
    temp = L->next;

    if (temp == NULL)
    {
        return 0;
    }
    *x = temp->data;
    L->next = temp->next;
    free(temp);
    return 1;
}

char OperaGetTop(OperaStack L)
{
    if (L->next==NULL)
    {
        return 0;
    }
    else
    {
        return L->next->data;    
    }
}

主函式:

#include "NumLinkStack.h"
#include "OperaLinkStack.h"
#include <math.h>
#include <string.h>

int ExpEvaluation(NumStack N, OperaStack L);//計算函式

int Judege(char ch);//判斷是否為運算子

char Compare(char ch, char ch2);//判斷運算子的優先順序

int Execute(int a, char op, int b);//運算

int main(void)
{
    NumStack N;
    OperaStack L;
    NumInitStack(&N);
    OperaInitStack(&L);

    printf("%d",ExpEvaluation(N, L));
    getchar();
    getchar();

    return 0;
}

int ExpEvaluation(NumStack N, OperaStack L)
{
    char express[100];
    int i = 0;
    int k = 0;
    int j = 0;
    int num2 = 0;
    char e;
    int a, b;
    char op;
    OperaPush(L, '=');

    printf("Please input an expresion (Ending with =)\n");
    scanf("%s",express);

    while (express[i] != '='|| OperaGetTop(L) != '=')
    {
        if (express[i] >= '0'&&express[i] <= '9')
        {
            k++;
            if (k<=j)//判斷此時為幾位數,如果j大於k時,表明前面的為運算子,num2從個位開始相加,故num2不用歸零了
            {
                num2 = express[i] - 48;
                i++;
            }
            if (k>j)
            {
                num2 = num2 * 10 + (express[i] - 48);
                k = j = 0;
                i++;
            }
            if (!Judege(express[i]))//如果後面的數還是運算數的話,k++
            {
                k++;
            }
            if (k==j)//表明後面的為運算子了,將前面的數字壓棧
            {
                NumPush(N, num2);
            }
        }
        else if (Judege(express[i]))
        {
            switch (Compare(express[i], OperaGetTop(L)))
            {
            case '<':
                OperaPush(L, express[i++]);
                if (express[i] != '('&&express[i] != ')')//當運算子為括號時,不進行j++操作例23+(56*5)
                     j++;
                break;

            case '=':
                OperaPop(L, &e);//脫括號,並接受下一個字元
                i++;
                break;

            case '>':
                OperaPop(L, &op);
                NumPop(N, &b);
                NumPop(N, &a);
                NumPush(N, Execute(a, op, b));//注意此處運算結束後,i不加一
                break;
            }
        }
    }        
     return NumGetTop(N);
}

int Judege(char ch)
{
    char ptr[8] = { '+', '-', '*', '/', '(', ')', '=' };
    int i;
    for (i = 0; i < 7; i++)
    {
        if (ch == ptr[i])
            return 1;
    }
    return 0;
}

char Compare(char a, char b)
{
    int i, j;
    char Table[8][8] =
    {
        { ' ', '+', '-', '*', '/', '(', ')', '=' },
        { '+', '>', '>', '<', '<', '<', '>', '>' },
        { '-', '>', '>', '<', '<', '<', '>', '>' },
        { '*', '>', '>', '>', '>', '<', '>', '>' },
        { '/', '>', '>', '>', '>', '<', '>', '>' },
        { '(', '<', '<', '<', '<', '<', '=', ' ' },
        { ')', '>', '>', '>', '>', ' ', '>', '>' },
        { '=', '<', '<', '<', '<', '<', ' ', '=' }
    };  //優先順序表格
    for (i = 0; i < 8; i++)
    if (Table[0][i] == a)  //縱座標尋找
        break;
    for (j = 0; j < 8; j++)  //橫座標尋找
    if (Table[j][0] == b)
        break;
    return Table[j][i];
}

int Execute(int a, char op, int b)
{
    switch (op)
    {
    case '+':return a + b;
    case '-':return a - b;
    case '*':return a * b;
    case '/':return a / b;
    }
}