要求说明:

(1)从键盘接收算术表达式,以“#”表示接收结束;
(2)输出算术表达式的值;
(3)操作数仅限于非负整数,操作符只能是+、-、*、/、^、(、)
(4)可以判断表达式的合法性(如括号的匹配)

写作业时遇到的一道题目,觉得比较麻烦,估计以后会有人遇到相同的问题,就写了篇博客记录下来。

主要思路:

(1)先将表达式转化成后缀表达式
(2)逐个读取后缀表达式,计算结果

转化成后缀表达式:

(1)设立操作符栈。
(2)设表达式的结束符为“#”,预设操作符栈的栈底为“#”。
(3)若当前字符是操作数,则直接发送给后缀式。
(4)若当前字符为操作符且优先级大于栈顶操作符,则人栈,否则退出栈顶操作符发送给后缀式。
(5)若当前字符是结束符,则自栈顶至栈底依次将栈中所有操作符发送给后缀式。
(6)“(”对它之前后的操作符起隔离作用,则若当前操作符为“(”时人栈。
(7)“)”可视为自相应左括号开始表达式的结束符,则从栈顶起,依次退出栈顶操作
符发送给后缀式直至栈顶字符为“("止。“(”不发送到后缀式。

转化成后缀表达式函数代码:

/*SeqStack *L操作符栈,char *str1读取的表达式,char *str2返回的后缀表达式*/
void Conversion(SeqStack *S,char *str1,char *str2)
{int i=0;char *p=str1,e;//预设操作符栈的栈底为“#”Push(S,'#');while (*p!='\0'){//若当前字符不是操作符是操作数,则直接发送给后缀式。if (!Isoperator(*p)){str2[i++]=*p;}else{if (*p=='(')Push(S,*p);else if (*p==')'){while(GetTop(S)!='('){Pop(S,&e);str2[i++]=e;}Pop(S,&e);  /*pop掉前括号*/}else if (*p=='#'){while (!IsEmpty(S)){Pop(S,&e);str2[i++]=e;}}else if (Compare(*p,GetTop(S))){Push(S,*p);}else if (!Compare(*p,GetTop(S))){Pop(S,&e);str2[i++]=e;continue;  /*continue应该要加*/}}p++;}str2[i-1]='\0';  /*#号也存进去了,所以用'\0'覆盖掉*/
}

完整计算表达式代码:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <conio.h>
#define TRUE 1
#define FALSE 0
#define Stack_Size 50char ops[8]= {'+','-','*','/','(',')','^','#'}; /*运算符数组*/
int priority[8] = {1,1,2,2,0,0,3,-1};typedef struct
{char elem[Stack_Size];int top;
} SeqStack;    /*运算符栈的定义*/typedef struct
{int elem[Stack_Size];int top;
} nSeqStack;  /* 运算数栈的定义*/void InitStack(SeqStack *S)   /*初始化运算符栈*/
{S->top =-1;
}void InitStackn(nSeqStack *S)   /*初始化运算数栈*/
{S->top =-1;
}int IsEmpty(SeqStack *S)    /*判断栈S为空栈时返回值为真,反之为假*/
{return(S->top==-1?TRUE:FALSE);
}int IsEmptyn(nSeqStack *S)    /*判断栈S为空栈时返回值为真,反之为假*/
{return(S->top==-1?TRUE:FALSE);
}/*判栈满*/
int IsFull(SeqStack *S)     /*判断栈S为满栈时返回值为真,反之为假*/
{return(S->top==Stack_Size-1?TRUE:FALSE);
}int IsFulln(nSeqStack *S)      /*判断栈S为满栈时返回值为真,反之为假*/
{return(S->top==Stack_Size-1?TRUE:FALSE);
}int Push(SeqStack *S, char x)   /*运算符栈入栈函数*/
{if (S->top==Stack_Size-1){printf("Stack is full!\n");return FALSE;}else{S->top++;S->elem[S->top]=x;return TRUE;}
}int Pushn(nSeqStack *S, int x)   /*运算数栈入栈函数*/
{if (S->top==Stack_Size-1){printf("Stack is full!\n");return FALSE;}else{S->top++;S->elem[S->top]=x;return TRUE;}
}int Pop(SeqStack *S, char *x)    /*运算符栈出栈函数*/
{if (S->top==-1){printf("运算符栈空!\n");return FALSE;}else{*x=S->elem[S->top];S->top--;return TRUE;}
}int Popn(nSeqStack *S, int *x)    /*运算数栈出栈函数*/
{if (S->top==-1){printf("运算数栈空!\n");return FALSE;}else{*x=S->elem[S->top];S->top--;return TRUE;}
}char GetTop(SeqStack *S)    /*运算符栈取栈顶元素函数*/
{if (S->top ==-1){printf("运算符栈为空!\n");return FALSE;}else{return (S->elem[S->top]);}
}int GetTopn(nSeqStack *S)    /*运算数栈取栈顶元素函数*/
{if (S->top ==-1){printf("运算符栈为空!\n");return FALSE;}else{return (S->elem[S->top]);}
}int Isoperator(char ch)        /*判断输入字符是否为运算符函数,是返回TRUE,不是返回FALSE*/
{int i;for (i=0; i<8; i++){if(ch==ops[i])return TRUE;}return FALSE;
}int Compare(char c1,char c2)
{int m,n;/*赋值c1对应的n*/if (c1=='+' || c1=='-')m=1;else if (c1=='*' || c1=='/')m=2;else if (c1=='(' || c1==')')m=0;else if (c1=='^')m=3;else if (c1=='#')m=-1;/*赋值c2对应的n*/if (c2=='+' || c2=='-')n=1;else if (c2=='*' || c2=='/')n=2;else if (c2=='(' || c2==')')n=0;else if (c2=='^')n=3;else if (c2=='#')n=-1;return m>n;
}/*SeqStack *L操作符栈,char *str1读取的表达式,char *str2返回的后缀表达式*/
void Conversion(SeqStack *S,char *str1,char *str2)
{int i=0;char *p=str1,e;//预设操作符栈的栈底为“#”Push(S,'#');while (*p!='\0'){//若当前字符不是操作符是操作数,则直接发送给后缀式。if (!Isoperator(*p)){str2[i++]=*p;}else{if (*p=='(')Push(S,*p);else if (*p==')'){while(GetTop(S)!='('){Pop(S,&e);str2[i++]=e;}Pop(S,&e);  /*pop掉前括号*/}else if (*p=='#'){while (!IsEmpty(S)){Pop(S,&e);str2[i++]=e;}}else if (Compare(*p,GetTop(S))){Push(S,*p);}else if (!Compare(*p,GetTop(S))){Pop(S,&e);str2[i++]=e;continue;  /*continue应该要加*/}}p++;}str2[i-1]='\0';  /*#号也存进去了,所以用'\0'覆盖掉*/
}int Calc(char *str)
{nSeqStack *n,nn;n=&nn;int i;int x,y,result;char *p=str;InitStackn(n);while (*p!='\0'){if (!Isoperator(*p)){Pushn(n,*p-'0');}else{Popn(n,&x);Popn(n,&y);switch (*p){case '+':result=y+x;break;case '-':result=y-x;break;case '*':result=y*x;break;case '/':result=y/x;   /*假设都能整除*/break;case '^':result=y;for (i=1;i<x;i++){result=result*y;}break;default:printf("error\n");break;}Pushn(n,result);}p++;}return result;
}int main()
{/**整体步骤*(1)表达式转化成后缀表达式*(2)表达式逐个读取进行计算*/char str1[100],str2[100];scanf("%s",str1);SeqStack *s,ss;s=&ss;InitStack(s);Conversion(s,str1,str2);printf("后缀表达式:%s\n",str2);int result = Calc(str2);printf("表达式结果:%d\n",result);return 0;
}

附:

利用后缀表达式求解,只需要从左向右依次扫描表达式,
(1)遇到操作数人栈,
(2)遇到操作符.则做出栈两次,获得两个操作数,
后出栈的操作数为第一个操作对象,对它们进行计算,
计算结果作为下次运算的操作数入栈。
重复上述操作,直到后缀表达式读取结束,既可完成表达式的计算。

[基础算法]通过后缀表达式实现表达式的计算相关推荐

  1. python前缀表达式求值_python数据结构与算法 11 后缀表达式求值

    从本节开始,删除原版的英文,直接发译后的文稿. 后缀表达式求值 栈的最一个应用例子,计算一个后缀表达式的值.这个例子中仍然用栈的数据结构.不过,当扫描表达式的时候,这次是操作数压栈等待,不是转换算法中 ...

  2. 有趣的数据结构算法10——后缀表达式(PRN)介绍及利用栈计算后缀表达式的结果

    有趣的数据结构算法10--后缀表达式(PRN)介绍及利用栈计算后缀表达式的结果 解题思路 实现代码 GITHUB下载连接 在前一天已经利用栈完成2进制到8进制的转换.但是栈的应用方面还有很多,本次我将 ...

  3. java后缀表达式_表达式计算 java 后缀表达式

    题目: 问题描述 输入一个只包含加减乖除和括号的合法表达式,求表达式的值.其中除表示整除. 输入格式 输入一行,包含一个表达式. 输出格式 输出这个表达式的值. 样例输入 1-2+3*(4-5) 样例 ...

  4. 六十四、前缀,后缀,中缀表达式转化求值问题

    @Author:Runsen 编程的本质来源于算法,而算法的本质来源于数学,编程只不过将数学题进行代码化. ---- Runsen 算法,一门既不容易入门,也不容易精通的学问. 上次介绍如何利用栈实现 ...

  5. 255.0.0.0子网掩码相应的cidr前缀表示法是?_六十四、前缀,后缀,中缀表达式转化求值问题...

    「@Author:Runsen」 ❝ 编程的本质来源于算法,而算法的本质来源于数学,编程只不过将数学题进行代码化. 「---- Runsen」 ❞ 算法,一门既不容易入门,也不容易精通的学问. 上次介 ...

  6. 设计一个算法,将一般算术表达式转化为逆波兰表达式,并求逆波兰表达式的值

    栈的设计与使用 实验内容 设计一个算法,将一般算术表达式转化为逆波兰表达式,并求逆波兰表达的值 解题思路 (1)一般算术表达(中缀表达),如#3×(4+2)/2-5#,#为表达式界定符,逆波兰表达式( ...

  7. 白话Spring(基础篇)---AOP(execution表达式)

    [一知半解,就是给自己挖坑] 作为AOP的最后一节内容,我们来简单总结一下切面表达式上见的书写方法.下面的那内容有参考其他博文,在此先对开源博客的各位大神表示感谢! ----------------- ...

  8. 零起点学算法07——复杂一点的表达式计算

    零起点学算法07--复杂一点的表达式计算 Description 下面你来计算一个复杂一点的计算表达式 Input 没有输入 Output 输出表达式的值,保留2位小数 题目分析:根号要用sqrt来算 ...

  9. el表达式 java_java基础学习:JavaWeb之EL表达式

    其他更多java基础文章: java基础学习(目录) 一.EL表达式 EL 全名为Expression Language.JSP中可以使用EL表达式,EL表达式是用"${}"括起来 ...

最新文章

  1. TensorRT-8量化分析
  2. 未来的数据中心(三)
  3. 直接调用android原生接口实现点击直接拨打电话功能
  4. C语言文件操作(三)读取指定路径txt文件,并输出文件内容
  5. python学习-类(global、nonlocal、继承、多态)
  6. nginx subrequest演示示例程序
  7. bigdecimal除法保留4位小数_小猿圈分享-MySQL保留几位小数的4种方法
  8. centos 安装jdk_新Jenkins实践-第2章 JENKINS SERVER的安装部署方式
  9. pyinstaller 打包exe可执行文件
  10. Spring消息之STOMP
  11. SQL Server实现列转行
  12. 什么是变量?变量的本质是什么?变量的生命周期和作用域
  13. [实战] Android 发短信 - SMS
  14. 《MacTalk 跨越边界》一一1.1 40岁了,还有没有路走?
  15. filezilla提示 local: unable to open
  16. 【Godot】通过属性检查器显示对应节点的脚本属性
  17. 安卓9.0刷linux,Android 9.0 内核编译实战(以一加6为例)
  18. 基于MATLAB的全局多项式插值法(趋势面法)与逆距离加权(IDW)法插值与结果分析
  19. 网格员计算机考试基础知识,网格员考题_请问下网格员考试的内容题目是什么要复习什么_淘题吧...
  20. WIN7 iTunes无法识别iPhone,重装系统解决

热门文章

  1. 老生常谈,正确使用memset
  2. linux 怎么配置apache,在Linux下配置Apache Web服务
  3. python精要(81)-collections容器类型(1)-统计相同的值
  4. python精要(65)-类(2)-构造函数
  5. go语言基础到提高(10)- 包及方法
  6. 【Python】可视化配色方案自由啦 (Python版)
  7. 【NLP】中文BERT上分新技巧,多粒度信息来帮忙
  8. 探秘AI开发「神器」ModelArts,解读IoT 智能设备,华为云教你玩转 AI开发!
  9. Attention 扫盲:注意力机制及其 PyTorch 应用实现
  10. 给大家介绍一下:网易云信新晋音视频质量诊断专家