C++逆波兰式的实现代码

合集下载

C++逆波兰式的实现代码

C++逆波兰式的实现代码

- 1 - #include"iostream.h"#include<stdlib.h>#include<stdio.h>#include<math.h>#define max 100char ex[max]; /*存储后缀表达式*/void trans(){ /*将算术表达式转化为后缀表达式*/char str[max]; /*存储原算术表达式*/char stack[max]; /*作为栈使用*/char ch;int sum,i,j,t,top=0;printf("*****************************************\n");printf("*输入一个求值的表达式,以#结束。

*\n");printf("******************************************\n");printf("算数表达式:");i=0; /*获取用户输入的表达式*/do{i++;cin>>str[i];/*此步我用的是C++ C 语言的话在后面 之所以用这个有一点区别 都*/ //scanf("%c",&str[i]);}while(str[i]!='#' && i!=max);sum=i;t=1;i=1;ch=str[i];i++;//while(ch!='#'){switch(ch){case '(': /*判定为左括号*/top++;stack[top]=ch;break;case ')': /*判定为右括号*/while(stack[top]!='('){ex[t]=stack[top];top--;t++;}top--;break;case '+': /*判定为加减号*/case '-':while(top!=0&&stack[top]!='('){ex[t]=stack[top];top--;t++;}top++;stack[top]=ch;break;- 2 - case '*': /*判定为乘除号*/case '/':while(stack[top]=='*'||stack[top]=='/'){ex[t]=stack[top];top--;t++;}top++;stack[top]=ch;break;case ' ':break;default:while(ch>='0'&&ch<='9'){ /*判定为数字*/ex[t]=ch;t++;ch=str[i];i++;}i--;ex[t]=' ';t++;}ch=str[i];i++;}while(top!=0){ex[t]=stack[top];t++;top--;}ex[t]=' ';printf("\n\t 原来表达式:");for(j=1;j<sum;j++)printf("%c",str[j]);printf("\n\t 逆波兰式:",ex);for(j=1;j<t;j++)printf("%c",ex[j]);}void compvalue(){ /*计算后缀表达式的值*/float stack[max],d; /*作为栈使用*/char ch;int t=1,top=0; /*t 为ex 下标,top 为stack 下标*/ch=ex[t];t++;while(ch!=' '){switch(ch){case '+':stack[top-1]=stack[top-1]+stack[top];top--;break;case '-':stack[top-1]=stack[top-1]-stack[top];top--;break;case '*':stack[top-1]=stack[top-1]*stack[top];top--;break;case '/':if(stack[top]!=0) stack[top-1]=stack[top-1]/stack[top];else{printf("\n\t除零错误!\n");exit(0); /*异常退出*/}top--;break;default:d=0;while(ch>='0'&&ch<='9'){d=10*d+ch-'0'; /*将数字字符转化为对应的数值*/ch=ex[t];t++;}top++;stack[top]=d;}ch=ex[t];t++;}printf("\n\t计算结果:%g\n",stack[top]);}void main(){trans();compvalue();}- 3 -。

后缀表达式的实现(逆波兰表达式)

后缀表达式的实现(逆波兰表达式)

课程名称:编译原理实验项目:后缀表达式的实现姓名:专业:班级:学号:计算机科学与技术学院20 年月日实验名称:消去C程序中的注释一、实验目的1、为了更好的配合《编译原理》有关词法分析章节的教学。

2、加深和巩固学生对于词法分析的了解和掌握。

3、使学生通过本实验能够初步的了解和掌握程序词法分析的整个过程。

4、提高学生的上机和编程过程中处理具体问题的能力。

二、实验要求设计、编制并调制一个程序,将中缀表达式改写为后缀表达式。

掌握中间语言的转换方法。

功能可以包括:1.后缀表达式求值后缀表达式也叫逆波兰表达式,其求值过程可以用到栈来辅助存储。

假定待求值的后缀表达式为:6 5 2 3 + 8 * + 3 + *,则其求值过程如下:1)遍历表达式,遇到的数字首先放入栈中,此时栈如下所示:2)接着读到“+”,则弹出3和2,执行3+2,计算结果等于5,并将5压入到栈中。

3)读到8,将其直接放入栈中。

4)读到“*”,弹出8和5,执行8*5,并将结果40压入栈中。

而后过程类似,读到“+”,将40和5弹出,将40+5的结果45压入栈...以此类推。

最后求的值288。

2.中缀表达式转后缀表达式规则:中缀表达式a + b*c + (d * e + f) * g,其转换成后缀表达式则为a b c * + d e * f + g * +。

转换过程需要用到栈,具体过程如下:1)如果遇到操作数,我们就直接将其输出。

2)如果遇到操作符,则我们将其放入到栈中,遇到左括号时我们也将其放入栈中。

3)如果遇到一个右括号,则将栈元素弹出,将弹出的操作符输出直到遇到左括号为止。

注意,左括号只弹出并不输出。

4)如果遇到任何其他的操作符,如(“+”,“*”,“(”)等,从栈中弹出元素直到遇到发现更低优先级的元素(或者栈为空)为止。

弹出完这些元素后,才将遇到的操作符压入到栈中。

有一点需要注意,只有在遇到" ) "的情况下我们才弹出" ( ",其他情况我们都不会弹出" ( "。

逆波兰式(后缀表达式)的计算

逆波兰式(后缀表达式)的计算

逆波兰式(后缀表达式)的计算输⼊:后缀表达式(可带浮点数)输出:double型的计算结果代码:#include <stdio.h>#include <stdlib.h>#include <malloc.h>#define ElemType double#define Stack_Init_Size 100#define Increase_Size 10#define MaxBuffer 10typedef struct sqStack{ElemType *top;ElemType *base;int initSize;}sqStack;typedef struct sqStack *LinkStack;//初始化void InitStack( sqStack *s ){s->base = (LinkStack)malloc(Stack_Init_Size * sizeof(ElemType));if(!s->base){printf("存储空间分配失败······\n");return;}s->top = s->base;s->initSize = Stack_Init_Size;}//进栈void Push(sqStack *s,ElemType e){if(s->top - s->base >= s->initSize - 1){s->base = (LinkStack)realloc(s->base,(s->initSize + Increase_Size) * sizeof(ElemType));//第⼀个s->base是增加后的存储空间块的地址,第⼆个是增加空间之前的存储空间块地址,后⾯是增加过的存储空间块的⼤⼩ if(!s->base){printf("增加存储空间失败······\n");return;}s->initSize = Increase_Size + Stack_Init_Size;}*(s->top) = e;(s->top)++;}//出栈void Pop(sqStack *s,ElemType *e){if(s->top == s->base){printf("栈已空,⽆法进⾏出栈操作······\n");return;}s->top--;*e = *s->top;}//求栈的长度int StackLen(sqStack s){return (s.top - s.base);}//逆波兰计算器:输⼊逆波兰式(后缀表达式)输出结果int main(){int i = 0,j,len;double m,n,t;char c;struct sqStack s;char str[MaxBuffer];InitStack(&s);printf("请输⼊您要计算的后缀表达式,按Enter键结束(两个不同的字符之间⽤空格隔开):\n");scanf("%c",&c);while(c != '\n'){while( (c >= '0'&&c <= '9') || c == '.'){str[i] = c;i++;// str[i] = '\0';if(i >= 10){printf("\n输⼊的数字过⼤导致出错\n"); return -1;}scanf("%c",&c);if( c == ' '){t = atof(str);// printf("\nt is %f\n",t);Push(&s,t);i = 0;for(j = 0;j < MaxBuffer;j++){str[j] = '\0';}break;}}switch( c ){case '+':Pop(&s,&m);Pop(&s,&n);Push(&s,n+m);break;case '-':Pop(&s,&m);Pop(&s,&n);Push(&s,n-m);break;case '*':Pop(&s,&m);Pop(&s,&n);Push(&s,n*m);break;case '/':Pop(&s,&m);Pop(&s,&n);if( m == 0){printf("\n除数为0,出错\n");return -1;}else{Push(&s,n/m);break;}}scanf("%c",&c);}Pop(&s,&t);printf("\n最终的计算结果为:%f \n",t);return 0;}。

c#实现逆波兰式

c#实现逆波兰式

c#实现逆波兰式运⽤⼤众例⼦:所谓的逆波兰表⽰法(Reverse Polish notation,RPN,或逆波兰记法),是⼀种数学表达式⽅式,在逆波兰记法中,所有操作符置于操作数的后⾯,因此也被称为后缀表⽰法。

逆波兰记法不需要括号来标识操作符的优先级。

(摘⾃维基)我们平时长写的数学公式被称为中缀表达式,即:(a+b)*c,⽤逆波兰式为ab+c*,再如:(a+b)*c-(a+b)/e,逆波兰式为ab+c*ab+e/-,⾸先理解下转化成逆波兰式的⼏个步骤:算法实现(选⾃百度):⾸先需要分配2个栈,⼀个作为临时存储运算符的栈S1(含⼀个结束符号),⼀个作为输⼊逆波兰式的栈S2(空栈),S1栈可先放⼊优先级最低的运算符#,注意,中缀式应以此最低优先级的运算符结束。

可指定其他字符,不⼀定⾮#不可。

从中缀式的左端开始取字符,逐序进⾏如下步骤:(1)若取出的字符是,则分析出完整的运算数,该操作数直接送⼊S2栈(2)若取出的字符是,则将该运算符与S1栈栈顶元素⽐较,如果该⼤于S1栈栈顶运算符优先级,则将该运算符进S1栈,否则,将S1栈的栈顶运算符弹出,送⼊S2栈中,直⾄S1栈栈顶运算符低于(不包括等于)该运算符优先级,最后将该运算符送⼊S1栈。

(3)若取出的字符是“(”,则直接送⼊S1栈顶。

(4)若取出的字符是“)”,则将距离S1栈栈顶最近的“(”之间的运算符,逐个,依次送⼊S2栈,此时抛弃“(”。

(5)重复上⾯的1~4步,直⾄处理完所有的输⼊字符(6)若取出的字符是“#”,则将S1栈内所有运算符(不包括“#”),逐个出栈,依次送⼊S2栈。

最后出来的S2需要逆序处理下,便是逆波兰表达式了。

看着定义,然后粗略了实现了下⾯的代码:主⽅法:static void Main(string[] args){while (true){Console.WriteLine("输⼊计算公式:");//输⼊公式string formula = Console.ReadLine();//定义临时计算符栈Stack<string> opStack = new Stack<string>();opStack.Push("#");Stack<string> numStack = new Stack<string>();for (int i = 0; i < formula.Length;){int opNum = GetOperationLevel(formula[i].ToString());if (opNum == 0){int index = GetCompleteValue(formula.Substring(i, formula.Length - i));numStack.Push(formula.Substring(i, index));i = (i + index);}//为操作数,获取完整else{if (formula[i] == '('){opStack.Push(formula[i].ToString());}else if (formula[i] == ')'){MoveOperator(opStack, numStack);}else{if (opStack.Peek() == "("){opStack.Push(formula[i].ToString());}else{JudgeOperator(opStack, numStack, formula[i].ToString());}}i++;}}if (opStack.Count != 0){while (opStack.Count != 0 && opStack.Peek() != "#"){numStack.Push(opStack.Pop());}}StringBuilder strBuild = new StringBuilder();foreach (string s in numStack){strBuild.Insert(0,s);}Console.WriteLine(strBuild.ToString());}}获取运算符等级:///<summary>///获取运算符等级///</summary>///<param name="c">当前字符</param>///<returns></returns>private static int GetOperationLevel(string c){switch (c){case"+": return1;case"-": return1;case"*": return2;case"/": return2;case"#": return -1;case"(": return -1;case")": return -1;default: return0;}}获取完整操作数///<summary>///获取完整数值///</summary>///<param name="formula">公式</param>///<returns></returns>private static int GetCompleteValue(string formula){int index = formula.Length;for (int i = 0; i < formula.Length; i++){int num = GetOperationLevel(formula[i].ToString());if (num != 0){index = i;break;}}return index;}移动运算符:///<summary>///移动运算符///</summary>///<param name="opStack"></param>///<param name="numStack"></param>private static void MoveOperator(Stack<string> opStack, Stack<string> numStack) {string s = opStack.Pop();if (s == "("){return;}else{numStack.Push(s);MoveOperator(opStack, numStack);return;}}判断运算符:///<summary>///判断运算符///</summary>///<param name="opStack"></param>///<param name="numStack"></param>///<param name="x"></param>private static void JudgeOperator(Stack<string> opStack, Stack<string> numStack, string x){int xNum = GetOperationLevel(x);int opNum = GetOperationLevel(opStack.Peek());if (xNum > opNum || numStack.Peek() == "("){opStack.Push(x);return;}else{string opStr = opStack.Pop();numStack.Push(opStr);JudgeOperator(opStack, numStack, x);return;}}代码运⾏效果:接下来就是计算公式的值,思路是新建⼀个栈R⽤来放结果,依次取出表达式的栈F,1.如果取出的值为操作数,则放⼊栈R,2.如果取出的值为运算符,则取出栈R顶的两个,进⾏运算,运算结果在存放⼊栈R 最后R顶的元素,即为计算的值下⾯为代码,⽬前只做了+,-,*,///numStack为逆波兰表达式Stack<string> rpnFormula = new Stack<string>();foreach (string s in numStack){rpnFormula.Push(s);}Console.WriteLine(CalcRPNFormula(rpnFormula));=private static string CalcRPNFormula(Stack<string> rpnFormula){Stack<string> resultStack = new Stack<string>();foreach (string s in rpnFormula){int num = GetOperationLevel(s);if (num == 0){resultStack.Push(s);}else{CalcResult(resultStack,s);}}return resultStack.Pop();}private static void CalcResult(Stack<string> resultStack, string operatorStr){if (resultStack.Count >= 2){double num2 = Convert.ToDouble(resultStack.Pop());double num1 = Convert.ToDouble(resultStack.Pop());if (operatorStr == "+"){resultStack.Push(Convert.ToString(num1 + num2));}else if (operatorStr == "-"){resultStack.Push(Convert.ToString(num1 - num2));}else if (operatorStr == "*"){resultStack.Push(Convert.ToString(num1 * num2));}else if (operatorStr == "/"){resultStack.Push(Convert.ToString(num1 / num2));}}}因为适应⾃⼰的项⽬,需要做到⽀持“”^”,"arctan", "sqrt", "sin", "cos", "tan", "arcsin", "arccos"的计算⽅式,在查看上⾯⽣成的逆波兰式的时候,发现^会后置,其他的都是前置,然后就投机取巧了以下,遇到^取前两位,遇到其他特殊符号,则取后⼀位,所以增加了以下内容,测试了下例⼦:2^3+sqrt(9)+sin(45)+1 通过之前的代码转换为后缀表达式为23^sqrt9+sin45+1+(正确应为23^9sqrt+45sin+1+),然后根据上述的进⾏计算,加了这⼏个特许计算后,可能与原来的后缀表达式有点背道⽽驰,没有对特殊字符进⾏后置处理,但⽬前为了先实现计算,所以投机取巧了下,后期会进⾏修改///<summary>///特殊字符///</summary>private static List<string> m_SpecialOp = new List<string>() { "arctan", "sqrt", "sin", "cos", "tan", "arcsin", "arccos" };///<summary>///获取运算符等级///</summary>///<param name="c">当前字符</param>///<returns></returns>private static int GetOperationLevel(string c){//sin(cos(tan(arcsin(arccos(arctan(switch (c){case"+": return1;case"-": return1;case"*": return2;case"/": return2;case"^": return2;case"arctan": return10;case"sqrt": return10;case"sin": return10;case"cos": return10;case"tan": return10;case"arcsin": return10;case"arccos": return10;case"#": return -1;case"(": return -1;case")": return -1;default: return0;}}///<summary>///计算逆波兰式///</summary>///<param name="rpnFormula"></param>///<returns></returns>private static string CalcRPNFormula(Stack<string> rpnFormula){Stack<string> resultStack = new Stack<string>();while (rpnFormula.Count > 0){string rpnStr = rpnFormula.Pop();int num = GetOperationLevel(rpnStr);if (num == 0){resultStack.Push(rpnStr);}else if (num == 10){SpecialCalc(resultStack, rpnStr, rpnFormula.Pop());}else{CalcResult(resultStack, rpnStr);}}return resultStack.Pop();}///<summary>///特殊计算///</summary>///<param name="resultStack"></param>///<param name="operatorStr"></param>///<param name="calcValue"></param>private static void SpecialCalc(Stack<string> resultStack, string operatorStr, string calcValue) {if (m_SpecialOp.Contains(operatorStr)){double num = Convert.ToDouble(calcValue);if (operatorStr == "sqrt"){resultStack.Push(Math.Sqrt(num).ToString("#0.000"));}else if (operatorStr == "sin"){resultStack.Push(Math.Sin(num).ToString("#0.000"));}else if (operatorStr == "cos"){resultStack.Push(Math.Cos(num).ToString("#0.000"));}else if (operatorStr == "tan"){resultStack.Push(Math.Tan(num).ToString("#0.000"));}else if (operatorStr == "arcsin"){resultStack.Push(Math.Asin(num).ToString("#0.000"));}else if (operatorStr == "arccos"){resultStack.Push(Math.Acos(num).ToString("#0.000"));}else if (operatorStr == "arctan"){resultStack.Push(Math.Atan(num).ToString("#0.000"));}}}///<summary>///计算结果///</summary>///<param name="resultStack"></param>///<param name="operatorStr"></param>private static void CalcResult(Stack<string> resultStack, string operatorStr){if (resultStack.Count >= 2){double num2 = Convert.ToDouble(resultStack.Pop());double num1 = Convert.ToDouble(resultStack.Pop());if (operatorStr == "+"){resultStack.Push(Convert.ToString(num1 + num2));}else if (operatorStr == "-"){resultStack.Push(Convert.ToString(num1 - num2));}else if (operatorStr == "*"){resultStack.Push(Convert.ToString(num1 * num2));}else if (operatorStr == "/"){resultStack.Push(Convert.ToString(num1 / num2));}else if (operatorStr == "^"){resultStack.Push(Math.Pow(num1, num2).ToString());}}}。

逆波兰表达式求值(实验报告及C源码)

逆波兰表达式求值(实验报告及C源码)

逆波兰表达式求值一、需求分析1、从键盘中输入一个后缀表达式,该表示包括加减乘除等操作符,以及正整数作为操作数等。

2、用堆栈来实现3、测试数据输入:2 3 * 1 – #输出:2 3 * 1 -- =5二、概要设计抽象数据类型需要一个浮点数栈来存储还没有计算的浮点数或者运算的结果。

ADT Stack数据成员:int size; int top; //分别用于存储栈大小、栈顶位置float *listArray;//存储浮点型数字的数组成员函数:bool push(float it);bool pop(float& it);bool isEmpty(); //判断栈为空bool isOne();//判断栈是否只有一个元素算法的基本思想1. 逐一扫描字符串,用ascii码进行判断,如果该字符是数字,则利用x=x*10+str[i]-48将数据由字符类型转换为浮点型数据;2. 如果字符是‘.’,则将‘.’转化为小数点,并将‘.’后的数据转化为小数部分;3. 遇到空格前是数据的,将x押入栈;4. 如果该字符是’+’,’-’,’*’或’/’,判断栈里的元素是否少于两个个,如果少于两个,报错;如果大于等于两个,就弹出两个数据,并进行相应的计算;程序的流程输入字符串,程序对字符串依次扫描。

扫描一位,处理一位。

扫描完成后,判断栈里是不是只有一个数据,若是,得到正确结果;若不是,则表达式出错。

三、详细设计物理数据类型用浮点数类型的栈存储运算中要用的数据,需要入栈、出栈,故设计如下的浮点类型的栈:class Stack{private:int size;int top;float *listArray;public:Stack(int sz=20);~Stack();bool push(float it);//入栈bool pop(float& it);//出栈bool isEmpty();//判断栈是否为空bool isOne(); //判断栈里是否只有且仅有一个元素};成员函数的函数体Stack::Stack(int sz) //栈构造函数{size=sz;top=0;listArray=new float[size]; }bool Stack::push(float it) {if(top==size)return false;listArray[top++]=it;return true;}bool Stack::pop(float& it) {if(top==0)return false;it=listArray[--top];return true;}bool Stack::isEmpty() //判断站是否为空{if(top==0)return true;return false;}bool Stack::isOne(){if(top==1)return true;return false;}Stack::~Stack(){delete listArray;}算法的具体步骤用switch语句实现1. 逐一扫描字符串,用ascii码进行判断,如果该字符是数字,则利用x=x*10+str[i]-48将数据由字符类型转换为浮点型数据;2. 如果字符是‘.’,则将‘.’转化为小数点,并将‘.’后的数据转化为小数部分;3. 遇到空格前是数据的,将x押入栈;4. 如果该字符是’+’,’-’,’*’或’/’,判断栈里的元素是否少于两个个,如果少于两个,报错;如果大于等于两个,就弹出两个数据,并进行相应的计算;算法的时空分析因为入栈、出栈的时间复杂度均为Θ(1),所以时间的复杂度主要取决于字符串的长度,空间也同样取决于字符串长度。

C语言实现逆波兰式实例

C语言实现逆波兰式实例

C语⾔实现逆波兰式实例复制代码代码如下:#include<stdio.h>#include<string.h>typedef struct{char s[20][20];int top;}SQ;void copystr(char *a,char *b){int i=0;do{b[i]=a[i];i++;}while(a[i]!='\0');b[i]='\0';}void voidSQ(SQ *s){s->top=-1;}int ifempty(SQ *s){return(s->top==-1);}void push(SQ *S,char *c){if(S->top==19)printf("over flow\n");else{S->top++;copystr(c,S->s[S->top]);}}char *pop(SQ *S){if(ifempty(S)){printf("over flow!\n");return(NULL);}elsereturn(S->s[S->top--]);}int judge(char *c){if(c[1]=='\0')switch(c[0]){case '+':return(3);case '-':return(3);case '*':return(2);case '/':return(2);default:return(1);}elsereturn(1);}void write(char *a,char *b,char *c){strcat(a,c);strcat(a,b);}int seek(char *c,int start){int signal=1;for(start=start++;c[start]!='\0'&&signal!=0;start++) {if(c[start]==')')signal--;else if(c[start]=='(')signal++;}if(signal==0)return(start-1);else{printf("输⼊⽆效式⼦\n");return(-1);}}void FB(SQ *A,SQ *B){for(;!ifempty(A);){push(B,A->s[A->top]);pop(A);}}char *rewrite(char *A){SQ front;SQ back;int i,j,k,flag=0;char *result;char mid[20];voidSQ(&front);voidSQ(&back);for(i=0;A[i]!='\0';){if(A[i]=='('){j=seek(A,i);for(k=i+1;k<j;k++){mid[k-i-1]=A[k];}mid[j-i-1]='\0';copystr(rewrite(mid),mid);push(&back,mid);i=j+1;}else if(A[i]!='(')mid[0]=A[i];mid[1]='\0';push(&back,mid);i++;}}FB(&back,&front);for(;front.top>=2;){flag=0;for(i=0;i<=front.top;i++){if(judge(front.s[i])==2){flag=1;break;}}if(flag==1){for(;front.top>=2;){if(judge(front.s[front.top])==1&&judge(front.s[front.top-1])==2&&judge(front.s[front.top-2])==1) {write(front.s[front.top],front.s[front.top-1],front.s[front.top-2]);push(&back,front.s[front.top]);pop(&front);pop(&front);pop(&front);}else{push(&back,front.s[front.top]);pop(&front);}}FB(&front,&back);FB(&back,&front);}else{for(;front.top>=2;){if(judge(front.s[front.top])==1&&judge(front.s[front.top-1])==3&&judge(front.s[front.top-2])==1) {write(front.s[front.top],front.s[front.top-1],front.s[front.top-2]);push(&back,front.s[front.top]);pop(&front);pop(&front);pop(&front);}else{push(&back,front.s[front.top]);pop(&front);}}FB(&front,&back);FB(&back,&front);}result=front.s[front.top];return(result);}typedef struct{char c[20];int top;}sq; int execute(char a,char b,char c) {switch(a){case('+'):return((c-48)+(b-48)); case('-'):return((c-48)-(b-48));case('*'):return((c-48)*(b-48));case('/'):return((c-48)/(b-48));}}void voidsq(sq *s){s->top=-1;}int ifsqempty(sq *s){return(s->top==-1);}void pushsq(sq *s,char x){if(s->top==19)printf("over flow!\n");else{s->top=s->top+1;s->c[s->top]=x;}}void popsq(sq *s){if(ifsqempty(s))printf("over flow!\n");elses->top--;}int just(char c){switch(c){case ('+'):return(0);case ('-'):return(0);case ('*'):return(0);case ('/'):return(0);default:return(1);}}void restread(sq *a,sq *b){for(;!ifsqempty(a);){pushsq(b,a->c[a->top]);popsq(a);}}int calculate(char *c){sq rest,read;int i,re;voidsq(&rest);voidsq(&read);for(i=0;c[i]!='\0';i++)pushsq(&read,c[i]);for(;read.top>=2;){for(;read.top>=2;){if(just(read.c[read.top])==0&&just(read.c[read.top-1])==1&&just(read.c[read.top-2]) ==1) {re=execute(read.c[read.top],read.c[read.top-1],read.c[read.top-2]);pushsq(&rest,re+48);popsq(&read);popsq(&read);popsq(&read);}else{pushsq(&rest,read.c[read.top]);popsq(&read);}}restread(&read,&rest);restread(&rest,&read);}return(read.c[0]-48);}void main(){char re[20];char a[20];printf("请输⼊算式:\n");scanf("%s",a);copystr(rewrite(a),re);printf("逆波兰式:\n%s\n",re);printf("求值结果:\n%d\n",calculate(re));}。

C语言之逆波兰表达式完整代码(附算法)

C语言课程设计之逆波兰表达式//逆波兰表达式(后缀表达式)reverse polish notation//程序实现的功能是将中缀表达式转变为后缀表达式,再求出其值//主要运用的知识点有:isdigit函数,pow函数,system("cls")函数,堆栈,格式的强制转换#include<stdio.h>#include<ctype.h>#include<stdlib.h>#include<math.h>void shift( char notation[]); //中缀表达式转换为后缀表达式的转换函数float calculate(float a[][2],int k); //计算后缀表达式int judge(char notation[]); //判断输入的中缀表达式是否符合要求int grade(char a); //返回运算符的等级void display(float a[][2],int k); //在屏幕上显示后缀表达式//主函数void main(){char notation [100];char choice;do{printf("请输入正确的中缀表达式:\n");printf("例如:2*3+4/3-(2+1)\n");scanf("%s",&notation);if(judge(notation)){shift(notation);}elseprintf("你的表达式有错误,请仔细检查!\n");fflush(stdin);printf("\n你是否需要继续计算(是输入Y/y,否输入其他任意键)\n");scanf("%c",&choice);getchar();system("cls");}while(choice=='Y'||choice=='y');printf("\n程序结束,谢谢使用!\n");}//判定函数int judge(char notation[]){int i,m,num=1,p1=0,p2=0;for(i=0;notation[i]!='\0';i++) //排除表达式外的字符{if(notation[i]!='('&&notation[i]!=')'&&notation[i]!='+'&&notation[i]!='-'&&notation[i]!='*'&&notation[i]!='/'&&!isdigit(notation[i])&&notation[i]!='.') {num=0;return num;}}if(notation[0]=='*'||notation[0]=='/'||notation[0]==')'||notation[0]=='.') //排除第一个字符为*,/,),.{num=0;return num;}for(i=0;notation[i]!='\0';i++) //排除'+','-','*','/','.'之间的连续出现以及'+','-','*','/','.'后面直接加')'{if(notation[i]!='('&&notation[i]!=')'&&!isdigit(notation[i])){if(notation[i+1]!='('&&!isdigit(notation[i+1])){num=0;return num;}}if(notation[i]=='('&&(notation[i+1]==')'||notation[i+1]=='.'||notation[i+1]=='*'||notation[i+ 1]=='/')){ //排除'('和')','.','*','/'一起连用num=0;return num;}if(notation[i]==')'&&(notation[i+1]=='('||notation[i+1]=='.'))//排除')'和'(','.'一起连用{num=0;return num;}}for(i=0;notation[i]!='\0';i++) //小数位不得超过4位{if(notation[i]=='.'&&notation[i+1]!='\0'&&notation[i+2]!='\0'&&notation[i+3]!='\0'&&notation[i+4]!='\0'&&notation[i+5]!='\0'){if(isdigit(notation[i+1])&&isdigit(notation[i+2])&&isdigit(notation[i+3])&&isdigit(notation[i+ 4])&&isdigit(notation[i+5])){num=0;return num;}}}for(i=0;notation[i]!='\0';i++) //排除一个小数中有两个小数点的情况{if(notation[i]=='.'){i++;while(isdigit(notation[i])){i++;}if(notation[i]=='.'){num=0;return 0;}}}for(i=0;notation[i]!='\0';i++) //排除')'后面不可以直接跟数字以及'('前面不可以加数字{if(notation[i]==')'&&isdigit(notation[i+1])){num=0;return num;}if(isdigit(notation[i])&&notation[i+1]=='(' ){num=0;return num;}}for(i=0;notation[i]!='\0';i++) //约束数字的位数一共最多为七位{if(isdigit(notation[i])){m=0; //用来计数,数字的位数为7while(isdigit(notation[i])||notation[i]=='.'){i++;m++;if(notation[i]=='.'){m--;}}if(m>7){num=0;return num;}}}for(i=0;notation[i]!='\0';i++) //'('与')'需要配对存在{if(notation[i]=='(')p1++;if(notation[i]==')')p2++;if(p1!=p2){num=0;return num;}}return num;}//转换函数void shift( char notation[]){char s1[100];s1[0]='#';float s2[100][2]; //第一维放后缀表达式的元素,第二维表示小数点的位数以及是否是运算符int i=0,j=1,k=0,t=0;float sum,num1=0,num2=0; //num1为存储整数位num2为存储小数位while(notation[i]!='\0'){if(i==0&&notation[i]=='+') //第一位为正号的情况{if(isdigit(notation[++i])){num1=0; //整数部分while(isdigit(notation[i])){num1=num1*10+(notation[i]-'0'); //notation[i]-'0'可以将字符转换为整数0~9i++;}num2=0; //小数部分t=0;if(notation[i]=='.'){i++;while(isdigit(notation[i])){num2=float (num2+pow(0.1,++t)*(notation[i]-'0'));i++;}}s2[k++][0]=float(num1+num2);s2[k-1][1]=float(t);}}if(i==0&&notation[i]=='-') //第一位为负号的情况,代码与正号类似{if(isdigit(notation[++i])){num1=0;while(isdigit(notation[i])){num1=(-1)*num1*10+(-1)*(notation[i]-'0');i++;}num2=0;t=0;if(notation[i]=='.'){i++;while(isdigit(notation[i])){num2=float(num2+(-1)*pow(0.1,++t)*(notation[i]-'0'));i++;}}s2[k++][0]=float(num1+num2);s2[k-1][1]=float(t);}}if(isdigit(notation[i])) //当前字符为数字的情况与为正号的情况一样{num1=0;while(isdigit(notation[i])){num1=num1*10+(notation[i]-'0');i++;}num2=0;t=0;if(notation[i]=='.'){i++;while(isdigit(notation[i])){num2=float(num2+pow(0.1,++t)*(notation[i]-'0'));i++;}}s2[k++][0]=float(num1+num2);s2[k-1][1]=float(t);}if(notation[i]=='+'||notation[i]=='-'||notation[i]=='*'||notation[i]=='/'){ //当前的字符为操作符时,如果s1的站定为'('则将字符直接送入s1if(s1[j-1]=='('){s1[j++]=notation[i++];}}if(notation[i]=='+'||notation[i]=='-'||notation[i]=='*'||notation[i]=='/'){ //当前字符为操作符时的普通的情况if(grade(notation[i])>grade(s1[j-1])){s1[j++]=notation[i++];}else{s2[k++][0]=s1[--j];s2[k-1][1]=-1;s1[j++]=notation[i++];}}if(notation[i]=='(') //当前字符为'('的情况{s1[j++]=notation[i++];if(notation[i]=='+') //'('后跟正号的情况{if(isdigit(notation[++i])){num1=0;while(isdigit(notation[i])){num1=num1*10+(notation[i]-'0');i++;}num2=0;t=0;if(notation[i]=='.'){i++;while(isdigit(notation[i])){num2=float(num2+pow(0.1,++t)*(notation[i]-'0'));i++;}}s2[k++][0]=float(num1+num2);s2[k-1][1]=float(t);}}if(notation[i]=='-') //'('后跟负号的情况{if(isdigit(notation[++i])){num1=0;while(isdigit(notation[i])){num1=float((-1)*num1*10+(-1)*(notation[i]-'0'));i++;}num2=0;t=0;if(notation[i]=='.'){i++;while(isdigit(notation[i])){num2=float(num2+(-1)*pow(0.1,++t)*(notation[i]-'0'));i++;}}s2[k++][0]=float(num1+num2);s2[k-1][1]=float(t);}}}if(notation[i]==')') //当前字符为')'的情况{while(s1[--j]!='('){s2[k++][0]=s1[j];s2[k-1][1]=-1;}i++;}}while(j>0&&s1[--j]!='#') //依次将s1中的除了'#'外的所有操作符出栈,相当于最后的扫尾工作{s2[k++][0]=s1[j];s2[k-1][1]=-1;}printf("\n后缀表达式(逆波兰表达式):\n");display(s2,k-1);printf("\n表达式的值为:\n");sum=calculate(s2,k-1);printf("%7.4f",sum);}//计算函数float calculate(float a[][2],int k){int i,t=0,j=k;float b[100][2],c[100];for(i=k;i>=0;i--){b[i][0]=a[k-i][0];b[i][1]=a[k-i][1];}i=k;while(j>=0){if(b[i][1]!=-1){c[t]=float (b[i][0]);j--;i--;t++;}if(b[i][1]==-1) //每当遇到一个运算符则将栈最上面的两个数出栈进行运算,然后再入栈{if(int(b[i][0])=='+'){c[t-2]=float (c[t-2]+c[t-1]);}if(int(b[i][0])=='-'){c[t-2]=float (c[t-2]-c[t-1]);}if(int(b[i][0])=='*'){c[t-2]=float (c[t-2]*c[t-1]);}if(int(b[i][0])=='/'){c[t-2]= float (c[t-2]/c[t-1]);}j--;i--;t--;}}return c[0]; //运算到最后,栈中的元素即为结果}//等级函数int grade(char a) //按照运算符的优先级{if(a=='#')return 0;if(a=='(')return 1;if(a=='-'||a=='+')return 2;if(a=='*'||a=='/')return 3;if(a==')')return 4;elsereturn 5;}//显示函数void display(float a[][2],int k){int i;for(i=0;i<=k;i++){if(a[i][1]==0)printf(" %d",int(a[i][0]));if(a[i][1]==1)printf(" %7.1f",a[i][0]);if(a[i][1]==2)printf(" %7.2f",a[i][0]);if(a[i][1]==3)printf(" %7.3f",a[i][0]);if(a[i][1]==4)printf(" %7.4f",a[i][0]);if(a[i][1]==-1)printf(" %c",int (a[i][0]));}}算法实现一个表达式E的后缀形式可以如下定义:(1)如果E是一个变量或常量,则E的后缀式是E本身。

c语言实现逆波兰表达式!

if(a[i] >= '0' && a[i] <= '9'){ double f = getSum(&i); operNum[top++] = f;
}else if(a[i] == ' '){ i++;
}else if(a[i] == '+'){ x1 = operNum[--top]; x2 = operNum[--top]; operNum[top++] = x1 + x2; i++;
博客园 用户登录 代码改变世界 密码登录 短信登录 忘记登录用户名 忘记密码 记住我 登录 第三方登录/注册 没有账户, 立即注册
c语 言 实 现 逆 波 兰 表 达 式 !
C语言实现逆波兰表达式 (栈的应用 )
#include<iostream> #include<cstdio> using namespace std; const int MAXSIZE = 110; char a[MAXSIZE]; double operNum[MAXSIZE]; ​ double getSum(int* i){//地址传递,可以在边求值时边改变i的原值。如若是值传递,会导致值的重复算
}else if(a[i] == '-'){ x1 = operNum[--top]; x2 = operNum[--top]; operNum[top++] = x2 - x1; i++;
}else if(a[i] == '*'){ x1 = operNum[--top]; x2 = operNum[--top]; operNum[top++] = x1 * x2; i++;

对逆波兰式计算的程序设计

数据结构作业报告逆波兰式的计算一题目内容逆波兰式也叫后缀表达式(将运算符写在操作数之后)如:我们平时写a+b,这是中缀表达式,写成后缀表达式就是:ab+(a+b)*c-(a+b)/e的后缀表达式为:(a+b)*c-(a+b)/e→((a+b)*c)((a+b)/e)-→((a+b)c*)((a+b)e/)-→(ab+c*)(ab+e/)-→ab+c*ab+e/-计算给出的逆波兰式(假设条件:逆波兰表达式由单字母变量和双目四则运算符构成,以’#‘作为结束标志)。

二题目分析逆波兰式即后缀表达式,运算符置于两个操作数之后。

运算实应从前往后依次读出两个运算数,与这两个运算数之后的运算符进行计算,然后再从前往后提取两个操作数,再从之后提取对应的运算符,直到计算完毕。

这与栈的功能相一致,建立一个栈结构,将表达式的各个字符依次读取,若是数字则放入栈中,,若是操作符则从栈中提取两个数字进行运算,将运算结果加入到栈中,直至运算完毕。

三程序描述首先定义相关数值,建立栈结构的数据类型typedef struct{SElemType *base;SElemType *top;int stacksize;}SqStack;之后是各个对栈的操作函数Status InitStack(SqStack &S){S.base=(SElemType*)malloc(STACK_INIT_SIZE*sizeof(SElem Type));if(!S.base)exit(OVERFLOW);S.top=S.base;S.stacksize=STACK_INIT_SIZE;return OK;}//建立空栈Status Push(SqStack &S,SElemType e){if(S.top-S.base>=S.stacksize){S.base=(SElemType*)malloc(S.base,(S.stacksize+STACKINCREME NT)*sizeof(SElemTYpe));if(!S.base)exit(OVERFLOW);S.top=S.base+S.stacksize;S.stacksize+=STACKINCREMENT;}*S.top++=e;return OK;}//将栈顶元素输出到元素e之中Status Pop(SqStack &S,SElemType e) {if(S.top==S.base)return ERROR;e=*--S.top;return OK;}//将元素e加入到栈之中程序最重要的操作函数如下(进行计算操作):char CalVal_InverPoland(char Buffer[]){Stack Opnd;InitStack(Opnd);int i=0;char c;ElemType e1,e2;while(Buffer[i]!='#'){if(!IsOperator(Buffer[i])){Push(Opnd,Buffer[i]);}else{Pop(Opnd,e2);Pop(Opnd,e1);c=Cal(e1,Buffer[i],e2);Push(Opnd,c);}i++;}return c;}while循环中是对表达式各字符的判断和计算过程,如果是数字则加入栈中,是操作符则从栈中提取两数据进行计算,之后将计算结果加入到栈中,直至遇到表达式结束标志’#’则结束运算,栈中数字则为计算结果。

(编译原理)逆波兰式算法的源代码

(编译原理)逆波兰式算法的源代码一.实验目的1.深入理解算符优先分析法2.掌握FirstVt和LastVt集合的求法有算符优先关系表的求法3.掌握利用算符优先分析法完成中缀表达式到逆波兰式的转化二.实验内容及要求将非后缀式用来表示的算术表达式转换为用逆波兰式来表示的算术表达式,并计算用逆波兰式来表示的算术表达式的值。

程序输入/输出示例:输出的格式如下:(1)(2)输入一以#结束的中缀表达式(包括+—*/()数字#)(3)(4)逆波兰式备注:(1)在生成的逆波兰式中如果两个数相连则用&分隔,如28和68,中间用&分隔;串。

注意:1.表达式中允许使用运算符(+-*/)、分割符(括号)、数字,结束符#;2.如果遇到错误的表达式,应输出错误提示信息(该信息越详细越好);3.对学有余力的同学,测试用的表达式事先放在文本文件中,一行存放一个表达式,同时以分号分割。

同时将预期的输出结果写在另一个文本文件中,以便和输出进行对照;三.实验过程1、逆波兰式定义将运算对象写在前面,而把运算符号写在后面。

用这种表示法表示的表达式也称做后缀式。

逆波兰式的特点在于运算对象顺序不变,运算符号位置反映运算顺序。

采用逆波兰式可以很好的表示简单算术表达式,其优点在于易于计算机处理表达式。

2、产生逆波兰式的前提中缀算术表达式3、逆波兰式生成的实验设计思想及算法(1)首先构造一个运算符栈,此运算符在栈内遵循越往栈顶优先级越高的原则。

(2)读入一个用中缀表示的简单算术表达式,为方便起见,设该简单算术表达式的右端多加上了优先级最低的特殊符号“#”。

(3)从左至右扫描该算术表达式,从第一个字符开始判断,如果该字符是数字,则分析到该数字串的结束并将该数字串直接输出。

(4)如果不是数字,该字符则是运算符,此时需比较优先关系。

做法如下:将该字符与运算符栈顶的运算符的优先关系相比较。

如果,该字符优先关系高于此运算符栈顶的运算符,则将该运算符入栈。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
#include"iostream.h" #include<stdlib.h> #include<stdio.h> #include<math.h> #define max 100
char ex[max];
/*存储后缀表达式*/
void trans()
{
/*将算术表达式转化为后缀表达式*/
char str[max];
/*存储原算术表达式*/
char stack[max]; /*作为栈使用*/
char ch;
int sum,i,j,t,top=0;
printf("*****************************************\n");
printf("*输入一个求值的表达式,以#结束。*\n");
while(stack[top]!='(')
{
ex[t]=stack[top];top--;t++;
}
top--;
break;
case '+': /*判定为加减号*/
case '-':
while(top!=0&&stack[top]!='(')
{
ex[t]=stack[top];top--;t++;
case '+':
stack[top-1]=stack[top-1]+stack[top];
top--;
break;
case '-':
stack[top-1]=stack[top-1]-stack[top];
top--;
break;
-2-
case '*':
stack[top-1]=stack[top-1]*stack[top]; top--; break; case '/': if(stack[top]!=0) stack[top-1]=stack[top-1]/stack[top]; else{
void main(){ trans(); compvalue();
}
-3-
void compvalue(){ /*计算后缀表达式的值*/
float stack[max],d; /*作为栈使用*/
char ch;
int t=1,top=0; /*t 为 ex 下标,top 为 stack 下标*/
ch=ex[t];t++;
while(ch!=' '){
switch(ch){
}
top++;stack[top]=ch;
-1-
break;
case '*': /*判定为乘除号*/ case '/':
while(stack[top]=='*'||stack[top]=='/') {
ex[t]=stack[top];top--;t++; } top++;stack[top]=ch; break; case ' ':break; default: while(ch>='0'&&ch<='9') { /*判定为数字*/
printf("******************************************\n");

printf("算数表达式:");
i=0; /*获取用户输入的表达式*/
do
{
i++;
cin>>str[i];
/*此步我用的是 C++ C 语言的话在后面 之所以用这个有一点区别 都*/
//scanf("%c",&str[i]);
printf("\n\t 除零错误!\n"); exit(0); /*异常退出*/ } top--; break; default: d=0; while(ch>='0'&&ch<='9'){
d=10*d+ch-'0'; /*将数字字符转化为对应的数值*/ ch=ex[t];t++; } top++; stack[top]=d; } ch=ex[t];t++; } printf("\n\t 计算结果:%g\n",stack[top]); }
ex[t]=ch;t++; ch=str[i];i++; } i--; ex[t]=' ';t++; } ch=str[i];i++; } while(top!=0) { ex[t]=stack[top];t++;top--; } ex[t]=' '; printf("\n\t 原来表达式:"); for(j=1;j<sum;j++) printf("%c",str[j]); printf("\n\t 逆波兰式:",ex); for(j=1;j<t;j++) printf("%c",ex[j]); }
}while(str[i]!='#' && i!=max);
sum=i;
t=1;i=1;
ch=str[i];i++;
//
while(ch!='#'){
switch(ch)
{
case '(': /*判定为左括号*/
top++;stack[top]=ch;
break;
case ')': /*判定为右括号*/
相关文档
最新文档