最新数学表达式计算(c语言实现)演示教学
- 格式:doc
- 大小:281.00 KB
- 文档页数:15
一、设计思想计算算术表达式可以用两种方法实现:1.中缀转后缀算法此算法分两步实现:先将算术表达式转换为后缀表达式,然后对后缀表达式进行计算.具体实现方法如下:(1)中缀转后缀需要建一个操作符栈op和一个字符数组exp,op栈存放操作符,字符数组用来存放转换以后的后缀表达式。
首先,得到用户输入的中缀表达式,将其存入str数组中。
对str数组逐个扫描,如果是数字或小数点,则直接存入exp数组中,当扫描完数值后,在后面加一个#作为分隔符。
如果是操作符,并且栈为空直接入栈,如果栈不为空,与栈顶操作符比较优先等级,若比栈顶优先级高,入栈;如果比栈顶优先级低或相等,出栈将其操作符存到exp数组中,直到栈顶元素优先等级低于扫描的操作符,则此操作符入栈;如果是左括号,直接入栈,如果是右括号,出栈存入exp数组,直到遇到左括号,左括号丢掉。
然后继续扫描下一个字符,直到遇到str中的结束符号\0,扫描结束。
结束后看op栈是否为空,若不为空,继续出栈存入exp数组中,直到栈为空.到此在exp数组最后加结束字符\0。
我们就得到了后缀表达式。
(2)后缀表达式计算此时需要一个数值栈od来存放数值。
对exp数组进行逐个扫描,当遇到数字或小数点时,截取数值子串将其转换成double类型的小数,存入od栈中。
当遇到操作符,从栈中取出两个数,进行计算后再放入栈中。
继续扫描,知道扫描结束,此时值栈中的数值就是计算的结果,取出返回计算结果。
2。
两个栈实现算法此算法需要两个栈,一个值栈od,一个操作符栈op。
将用户输入的数学表达式存入str数组中,对其数组进行逐个扫描。
当遇到数字或小数点,截取数值子串,将其转换成double类型的数值存入od栈中;当遇到左括号,直接入op栈;遇到右括号,op栈出栈,再从值栈od中取出两个数值,计算将其结果存入值栈中,一直进行此操作,直到操作符栈栈顶为左括号,将左括号丢掉。
如果遇到操作符,若op栈为空,直接入栈;若栈不为空,与栈顶元素比较优先等级,若比栈顶操作符优先等级高,直接入op栈,如果低于或等于栈顶优先等级,op栈出栈,再从值栈中取出两个数值,计算将其结果存入值栈中,一直进行此操作,直到栈顶优先等级低于扫描的操作符等级,将此操作符入op 栈。
C#算术表达式求值(后缀法),看这⼀篇就够了⼀、种类介绍算术表达式有三种:前缀表达式、中缀表达式和后缀表达式。
⼀般⽤的是中缀,⽐如1+1,前后缀就是把操作符移到前⾯和后⾯,下⾯简单介绍⼀下这三种表达式。
1、前缀表⽰法前缀表⽰法⼜叫波兰表⽰法,他的操作符置于操作数的前⾯(例:+ 1 2),是波兰数学家扬·武卡谢维奇1920年代引⼊的,⽤于简化命题逻辑。
因为我们⼀般认为操作符是在操作数中间的,所以在⽇常⽣活中⽤的不多,但在计算机科学领域占有⼀席之地。
⼀般的表⽰法对计算机来说处理很⿇烦,每个符号都要考虑优先级,还有括号这种会打乱优先级的存在,将使计算机花费⼤量的资源进⾏解析。
⽽前缀表⽰法没有优先级的概念,他是按顺序处理的。
举个例⼦:9-2*3这个式⼦,计算机需要先分析优先级,先乘后减,找到2*3,再进⾏减操作;化成前缀表⽰法就是:- 9 * 2 3,计算机可以依次读取,操作符作⽤于后⼀个操作数,遇到减就是让9减去后⾯的数,⽽跟着9的是乘,也就是说让9减去乘的结果,这对计算机来说很简单,按顺序来就⾏了。
2、中缀表⽰法这也就是我们⼀般的表⽰法,他的操作符置于操作数的中间(例:1 + 2),前⾯也说过这种⽅法不容易被计算机解析,但他符合⼈们的普遍⽤法,许多编程语⾔也就⽤这种⽅法了。
在中缀表⽰法中括号是必须有的,要不然运算顺序会乱掉。
3、后缀表⽰法后缀表⽰法⼜叫逆波兰表⽰法,他的操作符置于操作数的后⾯(例:1 2 +),他和前缀表⽰法都对计算机⽐较友好,但他很容易⽤堆栈解析,所以在计算机中⽤的很多。
他的解释过程⼀般是:操作数⼊栈;遇到操作符时,操作数出栈,求值,将结果⼊栈;当⼀遍后,栈顶就是表达式的值。
因此逆波兰表达式的求值使⽤堆栈结构很容易实现,且能很快求值。
注意:逆波兰记法并不是简单的波兰表达式的反转。
因为对于不满⾜交换律的操作符,它的操作数写法仍然是常规顺序,如,波兰记法/ 6 3的逆波兰记法是6 3 /⽽不是3 6 /;数字的数位写法也是常规顺序。
一、设计思想第一种算法:将中缀表达式转为后缀表达式,然后通过后缀表达式计算出算术表达式的结果。
核心思想:第一步:中缀变后缀。
首先,我们做出一个统一的Node结构体,结构体内部包含四个属性,分别是操作符的字符‘op’,char类型;操作符的优先级‘level’,int 类型;数字的浮点数数值‘od’,float类型;Node的标识符,int类型。
然后,定义一个Node结构体类型的数组*listNode,这里的*listNode用的是全局变量,为了方便在得到后缀表达式后,不需再传递给计算的方法。
定义一个存放操作符的栈,遍历用户输入的算术表达式(不考虑错误情况),在遍历的过程中如果遇到数字,直接将数字存放在*listNode里面;如果遇到了操作符,则判断操作符栈目前是不是为空,如果为空,直接将遇到的操作符放入操作符栈中,如果操作符栈不为空,那么观察操作符栈中栈顶的操作符,然后再次判断当前遇到的操作符的优先级是不是比栈顶的操作符的优先级高,如果是,那么将当前的操作符入操作符栈;如果不是,那么将操作符栈的栈顶操作符取出,追加到*listNode中,然后继续观察栈顶操作符,直到当前的操作符的优先级比栈顶操作符的优先级高或者操作符栈为空时,将当前操作符入操作符栈。
如果遇到了左括号,那么定义其优先级为最低,然后直接将左括号入操作符栈。
如果遇到了右括号,那么开始从操作符栈中取出操作符追加到*listNode中,直到遇到了与之对应的左括号,然后将左括号和右括号一起销毁。
当遍历完成了算术表达式之后,这时判断操作符栈是否为空,如果不为空,那么从操作符栈中依次取出栈顶操作符追加到*listNode中,直到操作符栈为空,那么就代表我们将中缀表达式转变成为了后缀表达式。
第二步:通过得到的后缀表达式,计算算术表达式。
首先,定义一个数字栈用来存放数值。
然后,遍历*listNode中的每一个Node,如果Node是一个数字,那么就将数字入数字栈,如果Node是一个操作符,那么就从数字栈中依次取出栈顶的两个数字,然后根据操作符计算这两个数字,将得到的结果再次入数字栈,直到遍历*listNode完成,最终数字栈中会只剩下一个Node,那就是我们计算出算术表达式的结果,将结果返回给main 函数用来输出。
一、设计思想两种算法首先都要建立两个栈,一个是存放操作数的数栈OdStack,一个是存放运算符的符栈OpStack。
数栈采用double型的用来存放浮点数,符栈采用char型的用来存放运算符,由于考虑到运算符有优先级的问题,所以事先做了一个Type用来存储运算符的优先级。
栈建立好了之后做栈的相关操作,初始化栈,入栈,出栈,看栈顶。
其中入栈要判满,出栈和看栈顶要判空。
中缀转后缀再计算的算法。
此算法的基本思路是先将中缀表达式转换成后缀表达式,之后再利用后缀表达式的算法对表达式进行计算。
首先,用一个char数组将中缀表达式读入,对数组中的每一个元素进行处理,区分哪些是数,哪些是运算符。
如果是数元素(或小数点元素),则依次存入用来存储后缀表达式的char数组,直到一个整合数存完之后用空格将其与后面的元素分开。
如果是运算符元素,则根据当前运算符的优先级和栈里面的运算符的优先级进行处理。
如果栈内元素的优先级小于当前元素的优先级或者栈内为空,则将当前运算符入栈;如果栈内元素的优先级大于等于当前元素的,则依次将出栈元素存入后缀表达式,并用空格将其与后面的元素分开,直到栈内元素的优先级小或者栈内为空。
对于左括号来说,无条件进栈,并只在有右括号出现的时候才有可能出栈。
对于右括号来说,无条件让栈内元素出栈,直到左括号出栈。
依次将每个元素进行处理直到中缀表达式索引完毕。
至此,已经实现了将中缀表达式转换成了后缀表达式,在数组的最后加上结束符以便下一步的调用。
第二步,读出后缀表达式并进行计算。
如果索引到空格则将索引标志后推1位。
之后要先对char型的数字元素进行整合,从后缀表达式中依次取出数字元素(连同小数点)存入一个新的char型数组,直到一整个数取完后通过atof函数将char型转换成浮点型存入数栈,并将新数组初始化用来存储下一个数。
如果是索引到运算符,则在数栈中出栈两个数字与当前运算符进行运算,先出栈的数字放在运算符后面,后出栈的数字放在运算符的前面,将运算以后的结果再次存入数栈。
C语⾔简单计算器原理——表达式求值(采⽤逆波兰表达式和栈
结合)
表达式的求解的关键是将其转换成逆波兰表达式(即后缀表达式,如1+2*3它的逆波兰表达式为123*+),在后缀表达式中已经考虑了运算符的优先级,
没有括号,只有操作数和运算符。
算术表达式转换成后缀表达式⽅法如下:
依次从键盘输⼊表达式的字符ch,对于每个ch:
(1)若ch为数字则直接将其放⼊后缀数组exp中并以#号标记数值串结束。
(2)若ch为"(",则直接将其压⼊字符栈op中。
(3)若ch为")",则将栈中"("以前的字符依次全部删除并将其放⼊后缀数组exp中,然后再将字符ch放⼊字符栈op中。
(4)若ch为"+"."-",则将栈中"("以前的运算符依次全部删除并将其放⼊后缀数组exp中,然后再将ch放⼊op栈中。
(5)若ch为"*"."/",则将栈顶连续的"*"."/"删除,并放⼊后缀数组exp中,然后将ch放⼊op栈中。
(6)若字符串str扫描完毕,则将栈中所有运算符删除并放⼊后缀数组exp,最后在后缀数组exp中便可得到后缀表达式。
在对后缀表达式求值时要⽤到⼀个数值栈st,在后缀数组exp中从头开始扫描,若是数字则将其放⼊数值栈中,
若遇到字符就进⾏两次退栈,并将运算结果再放⼊栈中,如此重复下去,最后当后缀数组扫描完后数值栈st的栈顶元素便是所要求的表达式的值。
x的绝对值c语言表达式 -回复C语言是一门广泛使用的编程语言,其灵活性和高效性使其成为开发者们首选工具之一。
在C语言中,我们可以通过表达式来实现各种功能和运算。
本文将以表达式"[x的绝对值c 语言表达式]"为主题,逐步解析如何在C语言中实现计算绝对值的功能。
绝对值是一个数与0之间的距离,无论数是正数还是负数,其绝对值永远是正数。
在数学中,绝对值表示为一个数前面加上一个垂直的竖线。
在C语言中,我们可以使用条件表达式来计算绝对值。
首先,我们需要理解条件运算符(?:)。
条件运算符是C语言中用于根据条件的真假返回不同值的一种表达式。
条件运算符的一般语法如下:condition ? expression1 : expression2;其中,condition表示一个条件表达式,expression1和expression2表示在条件为真或假时分别返回的值。
接下来,我们可以使用条件表达式来计算绝对值。
假设x是一个整数变量,我们可以编写如下的C语言表达式来计算x的绝对值:x >= 0 ? x : -x;这个表达式的意思是,如果x大于等于0,则返回x的值,否则返回-x的值。
通过这个表达式,我们可以实现计算任意整数的绝对值。
现在,让我们来解释这个表达式的工作原理。
当x大于等于0时,条件表达式x >= 0的结果为真,因此整个表达式的返回值为x。
而当x小于0时,条件表达式x >= 0的结果为假,整个表达式的返回值为-x。
这样我们就可以获取到x的绝对值。
通过使用条件表达式,我们可以在不使用if语句的情况下计算绝对值。
这在一些简单的计算中非常方便,可以简化代码的编写和阅读。
但需要注意的是,在复杂的情况下,尽管条件表达式可以实现绝对值的计算,但仍然建议使用if语句来提高可读性和程序的可维护性。
下面,我们将通过一个示例来演示如何使用上述的C语言表达式来计算绝对值。
c#include <stdio.h>int main() {int x;printf("请输入一个整数:");scanf("d", &x);int abs_value = x >= 0 ? x : -x;printf("绝对值为:d\n",abs_value);return 0;}在这个示例中,我们首先定义一个整型变量x,并通过用户输入来获取其值。
#include <stdio.h>#include <stdlib.h>typedef struct opLnode{char op;opLnode *next;}opLnode,*opLinkList;void OpInitStack(opLinkList &L) //运算符生成栈{L=(opLinkList)malloc(sizeof(opLnode));L->next=NULL;}void OpPush(opLinkList &L,char x) //运算符入栈{opLinkList p;p=(opLinkList)malloc(sizeof(opLnode));p->op=x;p->next=L->next;L->next=p;}char OpPop(opLinkList &L,char x) //栈顶运算符元素出栈{opLinkList p;p=(opLinkList)malloc(sizeof(opLnode));p=L->next;x=p->op;L->next=p->next;free(p);return x;}char OpGetTop(opLinkList L,char x) //读栈顶运算符元素{L=L->next;x=L->op;return x;}typedef struct Lnode{int i;Lnode *next;}Lnode,*LinkList;void InitStack(LinkList &L) //数值生成栈{L=(LinkList)malloc(sizeof(Lnode));L->next=NULL;}void Push(LinkList &L,int x) //数值入栈{LinkList p;p=(LinkList)malloc(sizeof(Lnode));p->i=x;p->next=L->next;L->next=p;}int Pop(LinkList &L,int x) //栈顶数值元素出栈{LinkList p;p=(LinkList)malloc(sizeof(Lnode));p=L->next;x=p->i;L->next=p->next;free(p);return x;}int GetTop(LinkList L,int x) //读栈顶数值元素{L=L->next;x=L->i;return x;}int GetNumber(char ch) //字符转化为数字{return (ch-48);int JudgeOp(char a) //判断输入是否为运算符{switch (a){case'+':case'-':case'*':case'/':case'(':case')':case'=':return 1;break;default:return 0;break;}}int JudgeNum(char a) //判断输入是否为为数字{switch(a){case'0':case'1':case'2':case'3':case'4':case'5':case'6':case'7':case'8':case'9':return 1;break;default:return 0;break;}}char Precede(char a,char b) //比较两运算符的“大小”switch (a){case'+':case'-':{if('*'==b||'/'==b||'('==b){return '<';}else{return '>';}break;}case'*':case'/':{if('('==b){return '<';}else{return '>';}break;}case'(':{if(')'==b){return '=';}else{return '<';}break;}case')':{return '>';break;}case'=':{if('='==b){return '=';}else{return '<';}break;}default:break;}}int Operate(int a,char op,int b) //运算{int c;switch (op){case '+':{c=a+b;break;}case '-':{c=a-b;break;}case '*':{c=a*b;break;}case '/':{c=a/b;break;}default:break;}return c;}int main(){printf("本程序只能计算整型数据,小数部分自动舍弃。
一、设计思想计算算术表达式可以用两种方法实现:1.中缀转后缀算法此算法分两步实现:先将算术表达式转换为后缀表达式,然后对后缀表达式进行计算。
具体实现方法如下:(1)中缀转后缀需要建一个操作符栈op和一个字符数组exp,op栈存放操作符,字符数组用来存放转换以后的后缀表达式。
首先,得到用户输入的中缀表达式,将其存入str数组中。
对str数组逐个扫描,如果是数字或小数点,则直接存入exp数组中,当扫描完数值后,在后面加一个#作为分隔符。
如果是操作符,并且栈为空直接入栈,如果栈不为空,与栈顶操作符比较优先等级,若比栈顶优先级高,入栈;如果比栈顶优先级低或相等,出栈将其操作符存到exp数组中,直到栈顶元素优先等级低于扫描的操作符,则此操作符入栈;如果是左括号,直接入栈,如果是右括号,出栈存入exp数组,直到遇到左括号,左括号丢掉。
然后继续扫描下一个字符,直到遇到str中的结束符号\0,扫描结束。
结束后看op栈是否为空,若不为空,继续出栈存入exp数组中,直到栈为空。
到此在exp数组最后加结束字符\0。
我们就得到了后缀表达式。
(2)后缀表达式计算此时需要一个数值栈od来存放数值。
对exp数组进行逐个扫描,当遇到数字或小数点时,截取数值子串将其转换成double类型的小数,存入od栈中。
当遇到操作符,从栈中取出两个数,进行计算后再放入栈中。
继续扫描,知道扫描结束,此时值栈中的数值就是计算的结果,取出返回计算结果。
2.两个栈实现算法此算法需要两个栈,一个值栈od,一个操作符栈op。
将用户输入的数学表达式存入str数组中,对其数组进行逐个扫描。
当遇到数字或小数点,截取数值子串,将其转换成double类型的数值存入od栈中;当遇到左括号,直接入op栈;遇到右括号,op栈出栈,再从值栈od中取出两个数值,计算将其结果存入值栈中,一直进行此操作,直到操作符栈栈顶为左括号,将左括号丢掉。
如果遇到操作符,若op栈为空,直接入栈;若栈不为空,与栈顶元素比较优先等级,若比栈顶操作符优先等级高,直接入op栈,如果低于或等于栈顶优先等级,op栈出栈,再从值栈中取出两个数值,计算将其结果存入值栈中,一直进行此操作,直到栈顶优先等级低于扫描的操作符等级,将此操作符入op栈。
继续扫描直到遇到str中的结束字符\0,扫描结束。
此时看操作符栈是否为空,若不为空,出栈,再从值栈中取出两个数值进行计算,将其结果存入值栈,一直进行此操作,直到操作符栈为空。
此时把值栈中的数值取出,即为所得的最终计算结果。
二、算法流程图第一种算法:中缀转后缀算法其主函数流程图为:返回计算结果图1 主函数算法流程图中缀转后缀算法流程图如下:放入exp数组中图2 中缀转后缀算法流程图计算后缀表达式流程图如下:图3 后缀表达式计算流程图第二种算法:两个栈算法其主函数流程图为:返回计算结果图4 主函数算法流程图直接计算数学表达式流程图如下:图5 直接计算表达式流程图三、源代码下面给出的是用中缀转后缀算法实现的程序的源代码:#include<stdio.h>#include<string.h>#include<math.h>#include<stdlib.h>#define MAXSIZE 100 //定义宏,数组最大长度为100//函数实现中缀转后缀,将存储数学表达式的数组str传参进来,exp存储后缀表达式void trans(char str[],char exp[]){struct{char data[MAXSIZE];//用来存放操作符int top;//数组下标}op;//用结构体创建操作符栈char ch;int i=0,j=0,tempi=0;op.top=-1;//给操作符栈初始化,令下标为-1while(ch!='\0'){ch=str[i]; //取str数组的第i个元素赋值给chif((ch>='0'&& ch<='9') || ch=='.')//对数值操作{tempi=i;//若ch为数字或小数点,将其下标值赋给临时下标tempi//依次向后扫描str数组,若一直为数字,跳入while循环while((ch>='0' && ch<= '9') || ch == '.'){tempi++;exp[j]=ch;//将数字存入exp数组中j++;ch=str[tempi];//取str数组中下标为tempi的元素赋给ch}exp[j]='#';j++;//用#做分隔符,将数值分隔开i=tempi;//跳出循环,将此时的tempi赋给i,继续向后扫描}//对操作符操作else if(ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch=='%' || ch == '(' || ch == ')'){int level(char op);//声明level函数if(ch=='(')//如果为(,直接进栈{op.top++;op.data[op.top]=ch;//进栈操作}else if(ch==')'){//如果为),一直出栈直到遇到(while(level(op.data[op.top])!=-1)//若栈顶元素不为(,进入while循环{exp[j]=op.data[op.top];//操作符出栈,存入exp数组中op.top--;j++;if(op.top==-1)break;//如果栈为空,跳出循环}op.top--;//左括号pop出来}else if(op.top==-1)//如果栈为空,直接进栈{op.top++;op.data[op.top]=ch;//进栈操作}//如果所扫描的操作符优先等级比栈顶元素高,直接进栈else if(level(ch)>level(op.data[op.top])){op.top++;op.data[op.top]=ch;//进栈操作}else{//如果所扫描的操作符优先等级没有栈顶元素高,//一直出栈直到比栈顶元素优先级高while(level(ch)<=level(op.data[op.top])){exp[j]=op.data[op.top];//出栈存入exp数组中op.top--;j++;if(op.top==-1)break;//如果栈为空,跳出循环}op.top++;op.data[op.top]=ch;//比栈顶元素优先级高,入栈}i++;//str下标加1,向后扫描}}while(op.top!=-1)//扫描结束后如果操作符栈不为空,出栈直至为空{exp[j]=op.data[op.top];//出栈存入exp数组中op.top--;j++;}exp[j]='\0';//赋\0结束exp字符数组}int level(char op)//判断操作符优先等级{if(op == '+' || op == '-')//若为+、-,等级为1return 1;else if(op == '*' || op == '/' || op == '%')return 2; //若为*、/、%,等级为2else if(op == '(')return -1 ; //若为(,等级为-1elsereturn -3; //其他等级为-3;}double calvalue(double od1,double od2,char tempop)//计算{switch(tempop){case '+':return od1 + od2; //计算加法case '-':return od1 - od2;//计算减法case '*':return od1 * od2;//计算乘法case '/':return od1 / od2;//计算除法case '%':return fmod(od1,od2);//求余}return 0;}double calculate(char exp[])//计算后缀表达式{struct //用结构体创建值栈{double data[MAXSIZE]; //存储数值int top;}od;double d; //声明d变量存储数值double od1,od2; //存储值栈依次pop出来的操作数char ch;char tempch[20]; //声明临时数组存储子串int j=0,t;int length=strlen(exp);//计算exp数组的长度od.top=-1; //初始化值栈,令下标为-1while(j<length){ch=exp[j];//提取exp中第j个元素if(ch!='+' && ch!='-' && ch!= '*' && ch!='/' && ch!='%'){//如果为数字或小数点t=0;while((ch>='0' && ch<='9') ||ch=='.'){tempch[t]=ch;t++;//依次存放到临时数组中j++;ch=exp[j];}tempch[t]='\0';//结束tempch数组d=atof(tempch);//将子串转化成double类型的数od.top++;od.data[od.top]=d;//入值栈}else //若为操作符,从值栈中pop出两个数计算{od2=od.data[od.top];od.top--;//先出栈的赋给od2od1=od.data[od.top]; //后出栈的赋给od1od.data[od.top]=calvalue(od1,od2,ch); //计算出结果后再入栈}j++;}return od.data[od.top];//将结束后值栈中的数pop出来,即为计算结果}main(){char str[MAXSIZE],exps[MAXSIZE]; //定义两个数组printf("请输入算术表达式:\n");gets(str); //从控制台输入算数表达式printf("表达式为:%s\n",str);trans(str,exps); //调用trans函数,得到后缀表达式printf("后缀表达式:%s\n",exps);printf("结果为:%lf\n", calculate(exps)); //调用calculate函数,计算结果}下面给出的是用两个栈算法实现的程序的源代码:#include<stdio.h>#include<string.h>#include<math.h>#include<stdlib.h>#define MAXSIZE 100 //定义宏,数组最大长度为100double calculate(char str[]){struct //用结构体创建操作符栈{char data[MAXSIZE];//用来存放操作符}op;struct //用结构体创建值栈{double data[MAXSIZE];//用来存放操作数int top;}od;char ch;char tempch[20];//声明临时数组存储子串int j=0,t;double d;double od1,od2;//存储值栈依次pop出来的操作数char tempop;int length=strlen(str);//计算str数组的长度op.top=-1;//初始化操作符栈,令下标为-1od.top=-1;//初始化值栈while(j<length){ch=str[j];if((ch>='0' && ch<='9') ||ch=='.')//若为数值或小数点{d=0;t=0;while((ch>='0' && ch<='9') ||ch=='.')//截取子串{tempch[t]=ch;t++;//赋值给临时数组j++;ch=str[j];}tempch[t]='\0';d=atof(tempch);//将子串转化成double类型的数od.top++;od.data[od.top]=d;//入值栈}//对操作符操作else if(ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch=='%' || ch == '(' || ch == ')') {if(ch=='(')//如果为(,直接进栈{op.top++;op.data[op.top]=ch;//进栈操作}else if(ch==')')//如果为),一直出栈直到遇到({int level(char op);//声明level函数while(level(op.data[op.top])!=-1)//若栈顶元素不为(,进入while循环{//声明calvalue函数double calvalue(double od1,double od2,char tempop);od2=od.data[od.top];od.top--;od1=od.data[od.top];tempop=op.data[op.top];op.top--;od.data[od.top]=calvalue(od1,od2,tempop);//计算出结果后入值栈if(op.top==-1)break;//如果操作符栈为空,跳出循环}op.top--;//左括号pop出来}else if(op.top==-1)//如果栈为空,直接进栈{op.top++;op.data[op.top]=ch;//进栈操作}//如果所扫描的操作符优先等级比栈顶元素高,直接进栈else if(level(ch)>level(op.data[op.top])){op.top++;op.data[op.top]=ch;//进栈操作}else{//如果所扫描的操作符优先等级没有栈顶元素高,//一直出栈直到比栈顶元素优先级高while(level(ch)<=level(op.data[op.top])){od2=od.data[od.top];od.top--;od1=od.data[od.top];tempop=op.data[op.top];op.top--;od.data[od.top]=calvalue(od1,od2,tempop);//计算结果后入值栈if(op.top==-1)break;//如果栈为空,跳出循环}op.top++;op.data[op.top]=ch;//比栈顶元素优先级高,入操作符栈}j++;//str下标加1,向后扫描}}while(op.top!=-1)//扫描结束后如果操作符栈不为空,出栈直至为空{od2=od.data[od.top];od.top--;od1=od.data[od.top];tempop=op.data[op.top];op.top--;od.data[od.top]=calvalue(od1,od2,tempop);//计算结果后入值栈}return od.data[od.top];//将结束后值栈中的数pop出来,即为计算结果}int level(char op)//判断操作符优先等级{if(op == '+' || op == '-')//若为+、-,等级为1return 1;else if(op == '*' || op == '/' || op == '%')return 2; //若为*、/、%,等级为2else if(op == '(')return -1 ; //若为(,等级为-1elsereturn -3; //其他等级为-3;}double calvalue(double od1,double od2,char tempop)//计算{switch(tempop){case '+':return od1 + od2;//计算加法case '-':return od1 - od2;//计算减法case '*':return od1 * od2;//计算乘法case '/':return od1 / od2;//计算除法case '%':return fmod(od1,od2);//求余}return 0;}void main(){char str[MAXSIZE];//定义str数组存放数学表达式printf("输入算术表达式:\n");gets(str); //从控制台输入算数表达式printf("结果是:%lf\n",calculate(str));//调用calculate函数,计算结果}四、运行结果图6 中缀转后缀算法运行结果图7 两个栈算法运行结果五、遇到的问题及解决编程的前期工作很重要,需要明确的理清思路,而编写运行的过程中更是会出现很多问题,有因粗心造成的拼写错误,有语法错误,也有逻辑错误。