四则运算 C++ 栈实现
2018-01-05 12:34
246 查看
源代码来自http://blog.csdn.net/lub0807/article/details/37884417
注释是自己加上去的,关于中缀表达式转后缀表达式,可以看一下我的这篇文章:
http://blog.csdn.net/include_heqile/article/details/79036631
注释是自己加上去的,关于中缀表达式转后缀表达式,可以看一下我的这篇文章:
http://blog.csdn.net/include_heqile/article/details/79036631
#include <STDIO.H> #include <STDLIB.H> #define MAX_EXP 100 //表达式最大长度 #define MAX_INT 10 //整数最大位数 #define NO_RESULT -99999 //计算异常的返回值 enum node_type{ NUM, OP }; struct node{ int number; char operation; enum node_type type; struct node *next; }; struct stack{ struct node *top; int length; }; typedef struct node Node; typedef struct stack Stack; int GetResult(const char []); void StringToMidExp(const char [], Stack *); int TenPow(int); void MidExpToBackExp(Stack *, Stack *); int BackExpToResult(Stack *); void ShowStack(const Stack *); void ShowNode(const Node *); void InitStack(Stack *); void Push(Stack *, Node *); void Pop(Stack *, Node *); void ClearStack(Stack *); void Reverse(Stack *, Stack *); int main(void) { char expression[MAX_EXP]; int result; printf("输入四则运算表达式:\n"); scanf("%s", expression); result = GetResult(expression); if (result == NO_RESULT) { printf("表达式有误,计算失败。\n"); } else { printf("计算结果是:%d\n", result); } return 0; } //根据表达式的字符串计算结果 int GetResult(const char exp[]) { Stack middleExp, backExp; Stack *pm, *pb; pm = &middleExp; pb = &backExp; InitStack(pm); InitStack(pb); StringToMidExp(exp, pm); printf("中缀表达式:"); ShowStack(pm); MidExpToBackExp(pm, pb);//后缀表达式存储在pb栈中 printf("后缀表达式:"); ShowStack(pb); return BackExpToResult(pb); } //字符串转换成中缀表达式 //栈ps最后存储的就是原输入的中缀表达式形式 void StringToMidExp(const char exp[], Stack *ps) { //num数组用来记录数字的字符在相应位置上的值,以便后期还原成数值形式 int num[MAX_INT]; int k, n, count, temp; Stack m_stack; Stack *pm; Node *q; k = 0; count = 0; pm = &m_stack; InitStack(pm); while (exp[k] != '\0')//持续循环,直到字符串处理完毕 { //只要是数字就进行以下处理 if (exp[k] >= '0' && exp[k] <= '9') //数字0到9 { //48是'0'的ASCII码值 num[count] = exp[k] - 48; //num数组记录整数的每一位 count++; //count记录整数的位数 } //能够进入这条分支的,就是运算符 else if ((exp[k] >= 40 && exp[k] <= 43) || exp[k] == 45 || exp[k] == 47) //运算符 { //将该运算符之前的字符形式的数字转换成与之对应的数值型 if (count > 0) { n = 0; temp = 0; //经过该while循环,字符串形式的数字就被转换成了数值型 while (n < count) { /** 这里的TenPow是自己定义的一个函数TenPow(n)就是10的n次方 很明显,在nun数组中索引越小的数字位数越高 具体关系就是: 位数 = count-n-1 (n就是num数组中的索引) */ temp += num * TenPow(count - n -1); //每一位乘以10的某次方 n++; } //申请一个Node大小的内存空间,并用Node型指针q指向该地址 //给q的数据域和数据类型域赋值 q = (Node *)malloc(sizeof(Node)); q->type = NUM; q->number = temp; //将q压进pm栈 Push(pm, q); } //为了下一波数字字符串的录入做准备,需要把count重置为0 count = 0; //位数清零 //运算符前面的数字进栈了,接下来就该运算符进栈了 q = (Node *)malloc(sizeof(Node)); //和上面数字进栈的方式相同,先赋值,然后压栈 q->type = OP; q->operation = exp[k]; Push(pm, q); } k++; } //既然输入的是一个算数式,那么末尾一定是一个数字 //由于没有运算符了,while循环中的else if语句就不会触发,最后一个数字就不会被转换 //因此需要在循环结束之后处理最后一个数字 if (count > 0) //把最后一个数字转换出来 { n = 0; temp = 0; while (n < count) { temp += num * TenPow(count - n -1); n++; } q = (Node *)malloc(sizeof(Node)); q->type = NUM; q->number = temp; Push(pm, q); } //颠倒次序之后,在出栈的时候就是按照中缀表达式的从左至右的次序输出的 //从始至终,pm都只是一个局部变量,最后的中缀表达式是保存在ps中的 Reverse(pm, ps); //颠倒一下次序 } //计算10的n次方 int TenPow(int n) { if (n == 0) { return 1; } else { int i, k; i = 0; k = 1; while (i < n) { k *= 10; i++; } return k; } } //中缀表达式转换成后缀表达式 //有关中缀表达式转换成后缀表达式的详细内容,可以参考我的这篇博客: //http://blog.csdn.net/include_heqile/article/details/79036631 void MidExpToBackExp(Stack *pm, Stack *pb) { Stack tempStack, oprStack; Stack *pt, *pr; Node *q, *r; pt = &tempStack; //临时存储后缀表达式 pr = &oprStack; //用来决定运算符的顺序 InitStack(pt); InitStack(pr); //这个while循环就是中缀表达式转换为后缀表达式的处理过程 //每一次循环,都会从中缀表达式的栈中读取出一个元素 while (pm->top) { q = (Node *)malloc(sizeof(Node)); Pop(pm, q); //如果读到的是数字,直接进栈(最终的栈,就是用来存储后缀表达式的栈) if (q->type == NUM) { Push(pt, q); } else { if (q->operation == '+' || q->operation == '-') { //因为对于+和-运算符来说, //只有 ( 操作符的优先级比他们低 //这时才会停止弹栈,然后他自己再进栈 while (pr->top && pr->top->operation != '(') { //弹栈,将弹出的操作符入后缀表达式栈 r = (Node *)malloc(sizeof(Node)); Pop(pr, r); Push(pt, r); } //弹栈停止,自己进后缀表达式栈 Push(pr, q); } else if (q->operation == '*' || q->operation == '/') { //对于* / 运算符来讲,左括号 ( + - 的优先级都是比他低的 while (pr->top && pr->top->operation != '(' && pr->top->operation != '+' && pr->top->operation != '-') { r = (Node *)malloc(sizeof(Node)); Pop(pr, r); Push(pt, r); } Push(pr, q); } //左括号是不会进入后缀表达式栈的 else if (q->operation == '(') { Push(pr, q); } else//这个就是q->operation == ')' 的情况 { while (pr->top) { //一直弹栈,直到碰到左括号 if (pr->top->operation == '(') { r = (Node *)malloc(sizeof(Node)); Pop(pr, r); free(r); break; } r = (Node *)malloc(sizeof(Node)); Pop(pr, r); Push(pt, r); } free(q); } } } while (pr->top) //栈内剩余运算符全部出栈 { r = (Node *)malloc(sizeof(Node)); Pop(pr, r); Push(pt, r); } Reverse(pt, pb); //颠倒一下次序 } //根据后缀表达式计算结果 int BackExpToResult(Stack *ps) { if (!ps->top) //空栈说明表达式有误 { return NO_RESULT; } Stack tempStack; Stack *pt; Node *q; int num_left, num_right, result; pt = &tempStack; InitStack(pt); while (ps->top) { if (ps->top->type == NUM) { q = (Node *)malloc(sizeof(Node)); Pop(ps, q); Push(pt, q); } else { q = (Node *)malloc(sizeof(Node)); Pop(pt, q); num_right = q->number; free(q); if (!pt->top) //pt栈内没有第2个数了,说明表达式有误 { return NO_RESULT; } q = (Node *)malloc(sizeof(Node)); Pop(pt, q); num_left = q->number; free(q); q = (Node *)malloc(sizeof(Node)); Pop(ps, q); switch(q->operation) { case '+': result = num_left + num_right; break; case '-': result = num_left - num_right; break; case '*': result = num_left * num_right; break; case '/': result = num_left / num_right; break; } free(q); q = (Node *)malloc(sizeof(Node)); q->type = NUM; q->number = result; Push(pt, q); } } q = (Node *)malloc(sizeof(Node)); Pop(pt, q); result = q->number; free(q); if (pt->top) //pt栈内还有数字,说明表达式有误 { return NO_RESULT; } else { return result; } } //显示栈中元素 void ShowStack(const Stack *ps) { if (ps->top) { Node *p = ps->top; while (p->next) { ShowNode(p); printf(" "); p = p->next; } ShowNode(p); printf("\n"); } else { printf("无\n"); } } //显示一个节点元素 void ShowNode(const Node *p) { if (p->type == NUM) { printf("%d", p->number); } else { printf("%c", p->operation); } } //初始化栈 void InitStack(Stack *ps) { ps->length = 0; ps->top = NULL; } //节点入栈 void Push(Stack *ps, Node *pn) { pn->next = ps->top; ps->top = pn; ps->length++; } //节点出栈 void Pop(Stack *ps, Node *pn) { if (ps->top) { Node *q = ps->top; pn->next = NULL; pn->number = q->number; pn->operation = q->operation; pn->type = q->type; ps->top = q->next; free(q); ps->length--; } else { pn = NULL; } } //清空栈 void ClearStack(Stack *ps) { Node *q; while (ps->top) { q = ps->top; ps->top = q->next; free(q); ps->length--; } } //反转栈中元素的次序 void Reverse(Stack *ps1, Stack *ps2) { if (ps1->top) { Node *q; ClearStack(ps2);//先把ps2清空,之后将ps1中的元素依次出栈,然后在压到ps2中即可 while (ps1->top) { //临时变量,用来暂时存储出栈的元素 q = (Node *)malloc(sizeof(Node)); Pop(ps1, q); Push(ps2, q); } } else { ps2->top = NULL; ps2->length = 0; } }
相关文章推荐
- 初探利用C++的STL实现数学四则运算计算结果
- 四则运算的C++实现
- 用c++简单实现四则运算
- 使用简单工厂模式实现四则运算 C++
- 分别用C++和JavaScript 实现四则运算表达式求值
- c++实现重载分数的四则运算
- 用栈实现四则运算表达式(c++)
- C++实现计算器(四则混合运算)
- 四则运算之C++实现篇
- 工厂方法模式实现四则运算 C++
- c++通过栈和递归函数实现简单四则运算以及括号的的计算器
- 支持多位数,括号,四则运算,的计算器算法c++实现
- 实数四则运算表达式的计算,C++ 实现
- C++实现支持浮点(x.x)的四则运算(带括号)
- C++ 通过main()函数输入参数,实现简单的四则运算
- 四则运算的实现(C++)重做
- 再探利用C++的STL和堆栈编程思想实现数学四则运算计算结果
- C++实现 vector 的四则运算
- C++实现能四则运算计算器
- 实现两个数相加不用四则运算