这是用2个栈实现一个小计算器功能,包含的运算符有:+ , - , * , / , ( , ) ,可谓“功能强大”!
(这次可是很用心的加了很多注释的,好吧,是我之前的程序都没用心加)
1、calculatestack.h
#ifndef __CALCULATESTACK_H__ #define __CALCULATESTACK_H__ #define TRUE 1 #define FALSE 0 #define PUSH 1 #define JISUAN 0 #define SIZE 50 typedef struct _num { int num[SIZE]; // 栈数组 int top; // 栈顶元素下标 }Num; typedef struct _opt { char opt[SIZE]; int top; }Opt; // 置空栈 int InitStack_Opt (Opt *S); int InitStack_Num (Num *S); // 判断输入类型,数字返T,字符返F int judge_type (char ch); // 进栈 int Push_NUM (Num *s, int x); int Push_Opt (Opt *s, char ch); // 出栈 int Pop_Num (Num *s, int *x); int Pop_Opt (Opt *s, char *ch); // 判断运算符是否进行计算 int judge_op (Opt *s, char ch); // 计算 int Jisuan (Num *s_num, Opt *s_opt); #endif // __CALCULATESTACK_H__2、calculatestack.c
#include "calculateStack.h" // 置空栈 int InitStack_Num (Num *S) { if (S == NULL) { errno = ERROR; return FALSE; } S->top = -1; return TRUE; } int InitStack_Opt (Opt *S) { if (S == NULL) { errno = ERROR; return FALSE; } S->top = -1; return TRUE; } // 判断输入类型 int judge_type (char ch) { if (ch >= '0' && ch <= '9') return TRUE; // 数字返TRUE else return FALSE; // 字符返FALSE } // 进栈 int Push_Num (Num *s, int x) { // 判断是否满栈 if (s->top == SIZE -1) { errno = FULL_STACK; return FALSE; } else { s->num[++s->top] = x; return TRUE; } } int Push_Opt (Opt *s, char ch) { // 判断是否满栈 if (s->top == SIZE -1) { errno = FULL_STACK; return FALSE; } else { s->opt[++s->top] = ch; return TRUE; } } // 出栈 int Pop_Num (Num *s, int *x) { // 判断是否空栈 if (s->top == -1) { errno = EMPTY_STACK; return FALSE; } *x = s->num[s->top--]; // x用来保存出栈的数字 return TRUE; } int Pop_Opt (Opt *s, char *ch) { // 判断是否空栈 if (s->top == -1) { errno = EMPTY_STACK; return FALSE; } *ch = s->opt[s->top--]; // ch用来保存出栈的字符 return TRUE; } // 先计算再入栈 int Jisuan (Num *s_num, Opt *s_opt) { // 判断数字栈中是否还有2个数据 if (s_num->top == 0) { errno = ERROR; myError("s_num->top == 0"); return FALSE; } // 判断字符栈中是否还有1个数据 if (s_opt->top == -1) { errno = EMPTY_STACK; myError("s_opt->top == -1"); return FALSE; } int num1, num2, num3; Pop_Num (s_num, &num1); Pop_Num (s_num, &num2); // 取出数据 char ch; Pop_Opt (s_opt, &ch); // 取出字符 if (ch == '+') num3 = num2 + num1; else if (ch == '-') num3 = num2 - num1; else if (ch == '*') num3 = num2 * num1; else if (ch == '/') { if (num1 == 0) { printf ("分母为0,错误\n"); return FALSE; } else num3 = num2 / num1; } Push_Num (s_num, num3); // 将计算结果入数字栈 return TRUE; } // 判断运算符是否进行计算 int judge_op (Opt *s, char ch) { // 栈空或传入的字符为'('则直接进栈 if (s->top == -1 || ch == '(') { return PUSH; } else { switch (s->opt[s->top]) { case '+': case '-': if (ch == '+' || ch == '-') // 栈顶为'+','-'时 return JISUAN; // 加减需计算 else return PUSH; // 其他全进栈 break; case '*': case '/': return JISUAN; // 栈顶为'*','/'时全部进计算 break; case '(': return PUSH; // 栈顶为'(' 全部进栈 break; } } } 3、main.c #include <stdio.h> #include <stdlib.h> #include "calculateStack.h" int main() { Num s_num; Opt s_opt; if (InitStack_Num(&s_num) == FALSE) { printf ("errno:%d\n", errno); char * a = myStrError(errno); printf ("a: %s\n", a); } if (InitStack_Opt(&s_opt) == FALSE) { printf ("errno:%d\n", errno); char * a = myStrError(errno); printf ("a: %s\n", a); } char a[SIZE]; // 临时存放用来转化为数字的字符串 char str[SIZE]; printf ("请输入算式:"); scanf ("%s",str); getchar(); int i = 0; while (str[i] != '\0') { // 判断输入的是否为数字 if (judge_type (str[i]) == TRUE) { int j = 0; while (judge_type (str[i]) == TRUE) // 判断接下来的字符是否为数字 { a[j++] = str[i]; i++; } a[j] = '\0'; i--; Push_Num (&s_num, atoi(a)); // 数字进栈 } else { if (str[i] == ')') // 如果进来的字符是')'则计算至'(' { while (s_opt.opt[s_opt.top] != '(') { Jisuan(&s_num, &s_opt); } char ch1[SIZE] = {0}; Pop_Opt (&s_opt, ch1); // 左括号出栈 } // 判断进栈还是计算 else if (judge_op (&s_opt, str[i]) == PUSH) { Push_Opt (&s_opt, str[i]); } else { Jisuan (&s_num, &s_opt); // 计算上一个字符 Push_Opt (&s_opt, str[i]); // 此字符进栈 } } i++; } while (s_opt.top != -1) // 将栈中存放的字符全部计算掉 { Jisuan (&s_num, &s_opt); } if (s_num.top != 0) // 若数字栈中不是存放了一个结果则输入有误 { printf ("输入格式错误!\n"); } else { printf ("答案是:%d\n",s_num.num[s_num.top]); } return 0; }