用棧實現簡易計算器
阿新 • • 發佈:2019-01-10
近期學習的棧中就數計算器最難了!!!
字尾表示式的特點就是計算機運算非常方便,需要用到棧;計算機處理過程只需要順序讀入,如果遇到數字,則放入棧中,如果是運算子,則將兩個棧中數字取出進行運算;
比如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;
}