利用双栈实现基本计算器功能:
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
#define STACK_SIZE_FIRST 100
#define STACK_SIZE_INCREASE 20
struct Expression{
char sign;
struct Expression *next;
};
typedef struct{
char *top;
char *bottom;
int stack_size;
}Stack;
struct Expression *GetExp();
int StackCreate(Stack *s);
int PUSH(Stack *s, char c);
int POP(Stack *s, char c);
char GetTop(Stack *s);
int Calculate(struct Expression *exp);
int Count(char num1, char sign, char num2);
int IsOpOrNum(char c);
char JudgeLevel(char c1, char c2);
void PrintResult(struct Expression *exp,int result);
int IsExpresiion(struct Expression *exp);
int main() {
struct Expression *head;
int Result = 0;
int temp = 0;
char select;
while(temp == 0) {
head = GetExp();
if(IsExpresiion(head) == 0 || head == NULL) {
printf("error!please re-enter");
getch();
system("cls");
} else {
Result = Calculate(head);
PrintResult(head,Result);
printf("whether to continue to calculate??y??n\n");
select = getch();
if(select == 'n' || select == 'N')
temp = 1;
else
system("cls");
}
}
system("pause");
return 0;
}
struct Expression *GetExp() {
printf("\tthe bracketed arithmetic expression evaluation\n");
printf("please enter an arithmetic expression that needs to be calculated:('='to the end)\n");
char c;
int number = 0;
struct Expression *head = NULL,*p1,*p2,*first = NULL;
head = (struct Expression *)malloc(sizeof(struct Expression));
while((c = getchar()) != '\n') {
if(c != '?') {
p1 = (struct Expression *)malloc(sizeof(struct Expression));
if(c == '=')
c = '#';
p1->sign = c;
if(first == NULL)
first = p1;
else
p2->next = p1;
p2 = p1;
number++;
}
}
if(p2->sign != '#') {
p1 = (struct Expression *)malloc(sizeof(struct Expression));
p1->sign = '#';
p2->next = p1;
p2 = p1;
number++;
}
head->next = first;
head->sign = number + '0';
if(head->next != NULL)
p2->next = NULL;
return head;
}
int StackCreate(Stack *s) {
s->bottom = (char *)malloc(STACK_SIZE_FIRST * sizeof(char));
if (s->bottom == NULL) {
printf("stack initialization failed!\n");
exit(0);
} else {
s->top = s->bottom;
s->stack_size = STACK_SIZE_FIRST;
}
return 1;
}
int PUSH(Stack *s, char c) {
if(s->top - s->bottom >= STACK_SIZE_FIRST) {
s->bottom = (char *)realloc(s->bottom,(STACK_SIZE_FIRST+STACK_SIZE_INCREASE) * sizeof(char));
if(s->bottom == NULL) {
printf("increase stack space failed!\n");
exit(0);
}
s->stack_size = s->stack_size + STACK_SIZE_INCREASE;
}
*(s->top) = c;
s->top ++;
return 1;
}
int POP(Stack *s, char c) {
if(s->top == s->bottom) {
printf("stack is empty!stack failure!\n");
exit(0);
} else {
c = *(s->top);
s->top --;
}
return 1;
}
char GetTop(Stack *s) {
char c;
if(s->top == s->bottom)
printf("stack is empty,unable to get the top element of the stack!\n");
else {
c = * (s->top - 1);
}
return c;
}
int Calculate(struct Expression *exp) {
exp = exp->next;
char OpSign ='?';
char NumSign1='?',NumSign2= '?';
char result;
char temp = '?';
Stack s_operator, s_number;
StackCreate(&s_operator);
StackCreate(&s_number);
PUSH(&s_operator,'#');
printf("\nthe calculation procedure is as follows:\n");
while(exp->sign != '#' || GetTop(&s_operator) != '#') {
if(IsOpOrNum(exp->sign) == 0) {
PUSH(&s_number,exp->sign);
exp = exp->next;
} else if(IsOpOrNum(exp->sign) == 1) {
OpSign = GetTop(&s_operator);
switch(JudgeLevel(OpSign,exp->sign)) {
case '<':PUSH(&s_operator,exp->sign);
exp = exp->next;
break;
case '=':POP(&s_operator,OpSign);
exp = exp->next;
break;
case '>':POP(&s_operator,OpSign);
NumSign1 = GetTop(&s_number);
POP(&s_number,temp);
NumSign2 = GetTop(&s_number);
POP(&s_number,temp);
result = Count(NumSign2,OpSign,NumSign1);
PUSH(&s_number,result);
break;
default: break;
}
}
}
result = GetTop(&s_number);
return result - '0';
}
char JudgeLevel(char c1, char c2) {
switch(c1) {
case '+':switch(c2) {
case '*':
case '/':
case '(':
return '<';
break;
default: return '>';
break;
}
break;
case '-':switch(c2) {
case '*':
case '/':
case '(':
return '<';
break;
default: return '>';
break;
}
break;
case '*':switch(c2) {
case '(':return '<';
break;
default: return '>';
break;
}
break;
case '/':switch(c2) {
case '(':return '<';
break;
default: return '>';
break;
}
break;
case '(':switch(c2) {
case ')':return '=';
break;
default: return '<';
break;
}
break;
case ')':switch(c2) {
case '+':return '>';
break;
default: return '>';
break;
}
break;
case '#':switch(c2) {
case '#':return '=';
break;
default: return '<';
break;
}
break;
default:return '<';
break;
}
}
int Count(char num1, char sign, char num2) {
int a=0,b=0;
a = num1 - '0';
b = num2 - '0';
int result = 0;
switch(sign) {
case '+':result = a+b;
break;
case '-':result = a-b;
break;
case '*':result = a*b;
break;
case '/':result = a/b;
break;
default: break;
}
printf("%d %c %d = %d\n",a,sign,b,result);
return result + '0';
}
int IsOpOrNum(char c) {
switch(c) {
case '+':
case '-':
case '*':
case '/':
case '(':
case ')':
case '#':
return 1;
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
return 0;
break;
default: return -1;
break;
}
}
void PrintResult(struct Expression *exp,int result) {
printf("\nthe final calculation results are:\n");
exp = exp->next;
while(exp != NULL) {
if( exp->sign == '#')
exp->sign = '=';
printf(" %c",exp->sign);
exp = exp->next;
}
printf(" %d\n",result);
}
int IsExpresiion(struct Expression *exp) {
int parameter = 1;
int i=0,j=0;
if(exp->sign - '0' < 4)
parameter = 0;
exp = exp->next;
while((parameter == 1) && (exp != NULL)) {
switch(IsOpOrNum(exp->sign)) {
case 0:exp = exp->next;
if(IsOpOrNum(exp->sign) != 1 || exp->sign == '(')
parameter = 0;
break;
case 1:switch(exp->sign) {
case ')':i++;
exp = exp->next;
if(IsOpOrNum(exp->sign) != 1)
parameter = 0;
if(IsOpOrNum(exp->sign) == 1)
if(exp->sign == '(') {
printf("11111\n");
parameter = 0;
}
break;
case '+':
case '-':
case '*':
exp = exp->next;
if(exp->sign == '(')
parameter = 1;
else if(IsOpOrNum(exp->sign) == 0)
parameter = 1;
else
parameter = 0;
break;
case '/':
exp = exp->next;
if(exp->sign == '(')
parameter = 1;
else if(IsOpOrNum(exp->sign) == 0) {
if(exp->sign == '0') {
printf("cannot divide into 0\n");
parameter = 0;
}
}
else
parameter = 0;
break;
case '(':
j++;
exp = exp->next;
if(IsOpOrNum(exp->sign) != 0)
if(exp->sign != '(')
parameter = 0;
break;
case '#':
if(exp->next != NULL)
parameter = 0;
exp = exp->next;
break;
}
break;
case -1:
parameter = 0;
break;
}
}
if(i != j)
parameter = 0;
return parameter;
}