这是用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;
}