1. 程式人生 > >用棧實現簡易計算器

用棧實現簡易計算器

近期學習的棧中就數計算器最難了!!!

字尾表示式的特點就是計算機運算非常方便,需要用到棧;計算機處理過程只需要順序讀入,如果遇到數字,則放入棧中,如果是運算子,則將兩個棧中數字取出進行運算;
比如1+2的字尾表示式為12+;
而棧可以把一般的中綴表示式變成字尾表示式,並且計算字尾表示式得出結果,因此此應用在計算器中非常常用。
把中綴表示式轉換成字尾表示式需要循幾個規則:
(1)如果讀入運算元,則直接放入輸出字串。
(2)如果讀入一般運算子如+-*/,則放入堆疊,但是放入堆疊之前必須要檢查棧頂,並確定棧頂運算子的優先順序比放入的運算子的優先順序低;如果放入的優先順序較低,則需要將棧頂的運算子放入輸出字串。
(3)如果讀入(,因為左括號優先順序最高,因此放入棧中,但是注意,當左括號放入棧中後,則優先順序最低。
(4)如果讀入),則將棧中運算子取出放入輸出字串,直到取出(為止,注意:()不輸出到輸出字串。
(5)順序讀完表示式,如果棧中還有操作符,則彈出,並放入輸出字串。
計算字尾表示式需要遵循以下幾個規則:
(1)如果是運算元,則放入棧中。
(2)如果是操作符,則取出棧中兩個運算元,進行運算後,將結果放入棧中。
(3)直到最後棧中只有一個元素,此元素就是計算結果。

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

#define OK    100001
#define ERROR 100002
struct node
{
    int data;
    struct node *next;
};

typedef struct node Node;

struct stack
{
    Node *top;
    int count;
};

typedef struct stack Stack;


int InitStack(Stack *S)
{
    S->top = NULL;
    S->
count = 0; return OK; } int EmptyStack(Stack *S) { return (S->count == 0) ? OK : ERROR; } int Push(Stack *S, int e) { Node *p = (Node *)malloc(sizeof(Node)); if (NULL == p) { return ERROR; } p->data = e; p->next = S->top; S->top = p; S->
count++; return OK; } int GetTop(Stack *S) { if (NULL == S->top) { return ERROR; } return (S->top->data); } int Priority(char s) { switch(s) { case '(': return 3; case '*': case '/': return 2; case '+': case '-': return 1; default : return 0; } } int Pop(Stack *S) { int e; if (NULL == S->top) { return ERROR; } Node *p = S->top; e = p->data; S->top = p->next; free(p); S->count--; return e; }
int main()
{
    char str[100] = {0};
    int i = 0, tmp = 0, j;
    Stack num, opt;

    if (InitStack(&num) != OK || InitStack(&opt) != OK)
    {
        printf("Init Failure!\n");
        exit(1);
    }

    printf("Please input operator :\n");
    scanf("%s",&str);

    while (str[i] != '\0' || EmptyStack(&opt) != OK)
    {
        if (str[i] >= '0' && str[i] <= '9')
        {
            tmp = tmp * 10 + str[i] - '0';
            i++;

            if (str[i] < '0' || str[i] >'9')
            {
                Push(&num, tmp);
                tmp = 0;
            }
        }

        else
        {
            if (EmptyStack(&opt) == OK || (GetTop(&opt) == '(' && str[i] != ')') || 
                Priority(str[i]) > Priority(GetTop(&opt)))
            {
                Push(&opt, str[i]);
                i++;
                continue;
            }

            if (GetTop(&opt) == '(' && str[i] == ')')
            {
                Pop(&opt);
                i++;
                continue;
            }

            if ((str[i] == '\0' && EmptyStack(&opt) != OK) || str[i] == ')' && GetTop(&opt) != '(' ||
                Priority(str[i]) <= Priority(GetTop(&opt)))
            {
                switch(Pop(&opt))
                {
                    case '+':
                        Push(&num, Pop(&num) + Pop(&num));
                        break;
                    case '-':
                        j = Pop(&num);
                        Push(&num, Pop(&num) - j);
                        break;
                    case '*':
                        Push(&num, Pop(&num) * Pop(&num));
                        break;
                    case '/':
                        j = Pop(&num);
                        Push(&num, Pop(&num) / j);
                        break;
                }

                continue;
            }
        }
    }

    printf("%d\n",Pop(&num));
    return 0;
}