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#实现逆波兰式运⽤⼤众例⼦:所谓的逆波兰表⽰法(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源码)

逆波兰表达式求值一、需求分析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语⾔实现逆波兰式实例复制代码代码如下:#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",¬ation);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]!='('&¬ation[i]!=')'&¬ation[i]!='+'&¬ation[i]!='-'&¬ation[i]!='*'&¬ation[i]!='/'&&!isdigit(notation[i])&¬ation[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]!='('&¬ation[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]=='.'&¬ation[i+1]!='\0'&¬ation[i+2]!='\0'&¬ation[i+3]!='\0'&¬ation[i+4]!='\0'&¬ation[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])&¬ation[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&¬ation[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&¬ation[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语言实现逆波兰表达式!

}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)如果不是数字,该字符则是运算符,此时需比较优先关系。
做法如下:将该字符与运算符栈顶的运算符的优先关系相比较。
如果,该字符优先关系高于此运算符栈顶的运算符,则将该运算符入栈。
中缀表达式转换成逆波兰式数据结构c语言

中缀表达式转换成逆波兰式数据结构c语言在计算机科学领域,中缀表达式和逆波兰式是两种常见的数学表达方式。
中缀表达式是我们日常生活中最为熟悉的数学表达方式,通常是由运算符和操作数构成的代数表达式,比如:(3 + 4) * 5。
而逆波兰式则是将操作符置于操作数之后的一种数学表达方式,比如:“3 4 + 5 *”。
在本文中,我们将深入探讨中缀表达式如何转换成逆波兰式,并结合数据结构和C语言编程,来实现这一转换过程。
通过这样的方式,我们不仅能够更深入地理解中缀表达式和逆波兰式的本质及其在计算机科学领域中的重要性,同时也能够加深对数据结构和C语言编程的理解。
1. 中缀表达式和逆波兰式的概念让我们简单回顾一下中缀表达式和逆波兰式的概念。
在中缀表达式中,操作符位于操作数之间,例如:3 + 4 * 5。
而逆波兰式则采用后缀表达方式,操作符位于操作数之后,例如:3 4 5 * +。
2. 数据结构的选择在将中缀表达式转换成逆波兰式的过程中,我们需要选择合适的数据结构来存储中间结果和最终结果。
在这里,我们选择使用栈这一数据结构。
栈是一种后进先出的数据结构,非常适合处理中缀表达式转换成逆波兰式的过程。
3. 中缀表达式转换成逆波兰式的算法接下来,我们将介绍中缀表达式转换成逆波兰式的算法。
该算法主要通过遍历中缀表达式,并使用栈来处理操作符的优先级和操作数的顺序。
具体的转换过程可以分为以下几个步骤: 1. 从左至右遍历中缀表达式的每个元素 2. 如果是操作数,则直接输出 3. 如果是左括号,则将其压入栈中 4. 如果是操作符,则比较其与栈顶操作符的优先级,如果栈顶操作符优先级较高,则将栈顶操作符弹出并输出,直到栈为空或者遇到了左括号 5. 如果是右括号,则将栈中左括号之前的所有操作符全部弹出并输出 6. 遍历完毕后,将栈中剩余的所有操作符依次弹出并输出4. C语言实现中缀表达式转换成逆波兰式在C语言中,我们可以使用数组来模拟栈的操作。
c++逆波兰表达式递归

C++逆波兰表达式递归逆波兰表达式,也叫后缀表达式,是一种比较常用的表达式表示方法。
逆波兰表达式将操作符放在操作数的后面,因此不需要考虑运算符的优先级和括号的问题。
例如,正常的中缀表达式"1+2*3"在逆波兰表达式中就可以表示为"1 2 3 * +"。
在这篇文章中,我们将会介绍如何用递归的方式来实现C++逆波兰表达式的计算。
1.递归函数我们首先需要定义一个递归函数来计算逆波兰表达式。
这个递归函数需要接受一个字符串(逆波兰表达式)作为参数,并返回一个整数(表达式的计算结果)。
递归函数的整体框架如下:int evaluate(string expression) {// 在这里实现递归函数}我们需要在函数中实现递归计算逆波兰表达式的功能。
2.处理长度为1的表达式递归函数的第一步是检查表达式的长度。
如果表达式的长度为1,则表明该表达式是操作数,可以直接返回该值。
我们可以通过下面的代码来实现这一步:if (expression.length() == 1) {return stoi(expression); // 将字符串转换为整数}在这里,我们使用了stoi函数将一个字符串转换为整数。
由于表达式的长度为1,我们可以将该字符串作为整数直接返回。
3.处理长度大于1的表达式如果表达式的长度大于1,那么该表达式一定是一个操作符和两个操作数的组合,此时我们需要找到该操作符,并对两个操作数进行计算。
我们可以通过下面的代码来找到操作符:char op = expression.back(); // 找到操作符expression.pop_back(); // 删掉操作符在这里,我们使用了back()函数来获取字符串的最后一个字符,也就是操作符。
同时,我们使用了pop_back()函数来删掉该操作符,这样原来的字符串中就只剩下操作数了。
接下来,我们需要找到这两个操作数。
找到操作数的方法与找到操作符的方法类似。
逆波兰(加、减、乘、除、括号)表达式原理及C++代码实现

逆波兰(加、减、乘、除、括号)表达式原理及C++代码实现当我们输⼊⼀个数学表达式,是中缀表达式,我们⾸先转换为后缀表达式(逆波兰表达式),然后再进⾏求值。
代码思路:(1)⾸先对输⼊的中缀表达式合法性进⾏判断,bool isStringLegal(const char* str); 函数实现。
(2)然后把中缀表达式转换为后缀表达式。
(3)根据后缀表达式求出结果,double getTheResult(vector<string> &vec);函数实现。
注意:表达式的运算符可以输⼊加、减、乘、除、括号,输⼊的数据为整形数据,计算结果为double型数据。
1 #include <iostream>2 #include <math.h>3 #include <map>4 #include <vector>5 #include <string.h>6 #include <memory>7 #include <string>8 #include <stdio.h>9 #include <stack>10 #include <stdlib.h>1112using namespace std;1314#define MAX_STRING_LENGTH 1001516/* 解析当前的整形数据,并把整形数据转换为string型 */17string analyData(const char* str, int &i);1819/* 根据逆波兰表达式求表达式的值 */20double getTheResult(vector<string> &vec);2122/* 判断该字符是否是 + - * / ( ) */23bool isCalChar(const char ch);2425/* 判断输⼊的中缀表达式是否合法 */26bool isStringLegal(const char* str);27282930/* 解析当前的整形数据,并把整形数据转换为string型 */31string analyData(const char* str, int &i)32 {33int temp = i++;34while(str[i] >= '0' && str[i] <= '9' && str[i] != '\0')35 {36 i++;37 }3839string s(str+temp,str+i);4041return s;42 }4344/* 根据逆波兰表达式求表达式的值 */45double getTheResult(vector<string> &vec)46 {47 vector<string>::iterator it;48 stack<double> sta;4950string strTemp;51double d = 0, d1 = 0, d2 = 0;5253for(it = vec.begin(); it != vec.end(); it++)54 {55 strTemp = (*it);5657if(strTemp == "+")58 {59 d1 = sta.top();60 sta.pop();6162 d2 = sta.top();63 sta.pop();6465 d = d1 + d2;66 sta.push(d);67 }68else if(strTemp == "-")69 {70 d1 = sta.top();71 sta.pop();7273 d2 = sta.top();74 sta.pop();7576 d = d2 - d1;77 sta.push(d);78 }79else if(strTemp == "*")80 {81 d1 = sta.top();82 sta.pop();8384 d2 = sta.top();85 sta.pop();8687 d = d2 * d1;88 sta.push(d);89 }90else if(strTemp == "/")91 {92 d1 = sta.top();93 sta.pop();9495 d2 = sta.top();96 sta.pop();9798 d = d2 / d1;99 sta.push(d);100 }101else102 {103const char *p = strTemp.c_str();104 d = atoi(p);105 sta.push(d);106 }107 }108return sta.top();109 }110111/* 判断该字符是否是 + - * / ( ) */112bool isCalChar(const char ch)113 {114if(ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '(' || ch == ')') 115 {116return true;117 }118119return false;120 }121/* 判断输⼊的中缀表达式是否合法 */122bool isStringLegal(const char* str)123 {124/* 判断是否是空串 */125if(NULL == str)126 {127return false;128 }129130int len = strlen(str);131int i = 0;132int flag = 0;133134/* 字符串的开头和末尾是否是数字 */135if(str[0] > '9' || str[0] < '0' || str[len-1] > '9' || str[len-1] < '0')136 {137return false;138 }139140141for(i = 0; str[i] != '\0'; i++)142 {143/* 是否有除了加减乘除括号之外的字符 */144if(isCalChar(str[i]) == false)145 {146return false;147 }148149/* 判断是否有两个连续的符号 */150if(i < len-1 && isCalChar(str[i]) == true)151 {152if(isCalChar(str[i+1]) == true)153 {154return false;155 }156157 }158159/* 判断括号是否成对 */160if(str[i] == '(')161 {162 flag++;163 }164else if(str[i] == ')')165 {166 flag--;167 }168169/* 判断是否出现 )( 这样的情况 */170if(flag < 0)171 {172return false;173 }174 }175176/* 判断括号是否匹配 */177if(flag != 0)178 {179return false;180 }181182return true;183 }184185int main(void)186 {187char str[MAX_STRING_LENGTH] = {0};188int i = 0;189string data;190191/* 存放运算符表达式的栈 */192 stack<char> oper_char;193194/* 存放后缀表达式 */195 vector<string> post_str;196197/* 输⼊中缀的表达式 */198 gets(str);199200/* 判断输⼊的中缀表达式是否合法 */201if(isStringLegal(str) != true)202 {203 cout << "This expression is not legal." << endl; 204 }205else206 {207/* 将中缀表达式转换为后缀表达式 */208for(i = 0; str[i] != '\0'; i++)209 {210/* 如果该字符为数字,解析该数字,并压⼊栈 */ 211if(str[i] >= '0' && str[i] <= '9')212 {213 data = analyData(str,i);214 post_str.push_back(data);215 i--;216 }217else if(str[i] == '(')218 {219 oper_char.push(str[i]);220 }221else if(str[i] == ')')222 {223char chtemp[2] = {0};224225 chtemp[0] = oper_char.top();226227while(chtemp[0] != '(')228 {229string strtemp(chtemp);230 post_str.push_back(strtemp);231 oper_char.pop();232233 chtemp[0] = oper_char.top();234 }235 oper_char.pop();236 }237else if(str[i] == '+' || str[i] == '-')238 {239char chtemp[2] = {0};240241/* 全部出栈,但是碰到 '('就要停⽌出栈 */242while(oper_char.size() != 0)243 {244 chtemp[0] = oper_char.top();245if(chtemp[0] == '(')246 {247break;248 }249250 oper_char.pop();251252string strtemp(chtemp);253 post_str.push_back(strtemp);254 }255256/*将当前的表达式符号⼊栈*/257 oper_char.push(str[i]);258 }259else if(str[i] == '*' || str[i] == '/')260 {261char chtemp[2] = {0};262while(oper_char.size() != 0)263 {264 chtemp[0] = oper_char.top();265if(chtemp[0] == '(' || chtemp[0] == '+' || chtemp[0] == '-') 266 {267break;268 }269else270 {271 oper_char.pop();272273string strtemp(chtemp);274 post_str.push_back(strtemp);275 }276 }277278/*将当前的表达式符号⼊栈*/279 oper_char.push(str[i]);280 }281 }282283/* 存放表达式的栈可能还有数据 */284while(!oper_char.empty())285 {286char chtemp[2] = {0};287 chtemp[0] = oper_char.top();288 oper_char.pop();289290string strtemp(chtemp);291 post_str.push_back(strtemp);292 }293294/* 把逆波兰表达式求值 */295 cout << getTheResult(post_str) << endl;296 }297298return0;299 }。
(编译原理)逆波兰式算法地源代码

一.实验目的1.深入理解算符优先分析法2.掌握FirstVt和LastVt集合的求法有算符优先关系表的求法3.掌握利用算符优先分析法完成中缀表达式到逆波兰式的转化二.实验内容及要求将非后缀式用来表示的算术表达式转换为用逆波兰式来表示的算术表达式,并计算用逆波兰式来表示的算术表达式的值。
程序输入/输出示例:输出的格式如下:(1)(2)输入一以#结束的中缀表达式(包括+—*/()数字#)(3)(4)逆波兰式备注:(1)在生成的逆波兰式中如果两个数相连则用&分隔,如28和68,中间用&分隔;注意:1.表达式中允许使用运算符(+-*/)、分割符(括号)、数字,结束符#;2.如果遇到错误的表达式,应输出错误提示信息(该信息越详细越好);3.对学有余力的同学,测试用的表达式事先放在文本文件中,一行存放一个表达式,同时以分号分割。
同时将预期的输出结果写在另一个文本文件中,以便和输出进行对照;三.实验过程1、逆波兰式定义将运算对象写在前面,而把运算符号写在后面。
用这种表示法表示的表达式也称做后缀式。
逆波兰式的特点在于运算对象顺序不变,运算符号位置反映运算顺序。
采用逆波兰式可以很好的表示简单算术表达式,其优点在于易于计算机处理表达式。
2、产生逆波兰式的前提中缀算术表达式3、逆波兰式生成的实验设计思想及算法(1)首先构造一个运算符栈,此运算符在栈内遵循越往栈顶优先级越高的原则。
(2)读入一个用中缀表示的简单算术表达式,为方便起见,设该简单算术表达式的右端多加上了优先级最低的特殊符号“#”。
(3)从左至右扫描该算术表达式,从第一个字符开始判断,如果该字符是数字,则分析到该数字串的结束并将该数字串直接输出。
(4)如果不是数字,该字符则是运算符,此时需比较优先关系。
做法如下:将该字符与运算符栈顶的运算符的优先关系相比较。
如果,该字符优先关系高于此运算符栈顶的运算符,则将该运算符入栈。
倘若不是的话,则将此运算符栈顶的运算符从栈中弹出,将该字符入栈。
C++栈实现逆波兰式的应用

C++栈实现逆波兰式的应⽤⽬录⼀.定义⼆.逆波兰式的意义三.逆波兰式的实现1.⽅法2.代码实现⼀.定义逆波兰式,⼜称后缀表达式,指的是操作符在其所控制的操作数后⾯的表达式。
举个例⼦,1 + 2 * 3 - 4这个表达式是我们熟悉的中缀表达式,那么其所对应的后缀表达式为:1 2 3 * + 4 -。
再来个复杂的例⼦:1 * (2 + 3) / 5 - 4 / 2其对应的后缀表达式为:1 2 3 + * 5 / 4 2 / -(其中括号由于只是提升表达式优先级的作⽤,因此不放⼊后缀表达式中)。
⼆.逆波兰式的意义为什么要将看似简单的中缀表达式转换为复杂的逆波兰式,原因就在于这个简单是相对我们⼈类的思维结构来说的,对计算机⽽⾔中序表达式是⾮常复杂的结构。
相对的,逆波兰式在计算机看来却是⽐较简单易懂的结构。
因为计算机普遍采⽤的内存结构是栈式结构,它执⾏先进后出的顺序。
三.逆波兰式的实现1.⽅法(1)中缀表达式转化为后缀表达式对于给出的中缀表达式,如何将其转化为后缀表达式呢?第⼀,若遇到操作数则直接输出/存储。
第⼆,遇到操作符,若此时栈为空或者操作符优先级⾼于栈顶,则⼊栈。
第三,若操作符的优先级低于或者等于栈顶,则出栈直⾄栈空或者优先级低于该操作符。
第四,遇到'(',其后的所有操作符(直⾄遇到')')按上述操作⼊栈或出栈;当遇到')‘时,将'('顶上的所有操作符出栈。
(2)由后缀表达式计算结果第⼀,遇到操作数则⼊栈。
第⼆,遇到操作符则将栈顶的两个操作数出栈,其中第⼀个数为右操作数,第⼆个数为左操作数。
第三,计算结果并将计算的结果⼊栈。
第四,最后栈顶的结果即为所计算的结果。
2.代码实现#include <iostream>#include <string>#include <stack>#include <vector>using namespace std;string trans(string& s){string operand;stack<char> Operator;int flag = 0;//记录括号优先级for (const auto& e : s){if (e == '('){Operator.push(e);flag = 1;continue;}if (e == ')'){flag = 0;while (Operator.top() != '('){operand.push_back(Operator.top());Operator.pop();}Operator.pop();continue;}//操作符if (e == '+' || e == '-' || e == '*' || e == '/'){if (flag == 1){if (Operator.top() == '('){Operator.push(e);}else if ((e == '*' || e == '/') && (Operator.top() == '+' || Operator.top() == '-')){Operator.push(e);}else//操作符的优先级低于或等于栈顶操作符则出栈,直⾄遇到'('{while (Operator.top() != '('){operand.push_back(Operator.top());Operator.pop();}Operator.push(e);}}else if (Operator.empty())//栈空就⼊栈{Operator.push(e);}//操作符的优先级⾼于栈顶操作符,⼊栈else if ((e == '*' || e == '/') && (Operator.top() == '+' || Operator.top() == '-')){Operator.push(e);}else//操作符的优先级低于或等于栈顶操作符则出栈,直⾄栈空或者优先级⾼于栈顶操作符 {while (!Operator.empty()){operand.push_back(Operator.top());Operator.pop();}Operator.push(e);}}//操作数else{operand.push_back(e);}}while (!Operator.empty()){operand.push_back(Operator.top());Operator.pop();}return operand;}int evalRPN(const string& s){stack<char> operand;int left = 0, right = 0;for (const auto& e : s){if (e == '+' || e == '-' || e == '*' || e == '/'){switch (e){case '+':right = operand.top();operand.pop();left = operand.top();operand.pop();operand.push(left + right);break;case '-':right = operand.top();operand.pop();left = operand.top();operand.pop();operand.push(left - right);break;case '*':right = operand.top();operand.pop();left = operand.top();operand.pop();operand.push(left * right);break;case '/':right = operand.top();operand.pop();left = operand.top();operand.pop();operand.push(left / right);break;}}else//操作数{operand.push(e - '0');}}return operand.top();}int RPN(const string& str){//1.中缀表达式转化为后缀表达式string s(str);s = trans(s);//2.后缀表达式计算答案return evalRPN(s);}int main(){string s("1*(2*3+5)/5-4/2");int ret = RPN(s);cout << "ret:" << ret << endl;return 0;}结果:到此这篇关于C++栈实现逆波兰式的应⽤的⽂章就介绍到这了,更多相关C++ 逆波兰式内容请搜索以前的⽂章或继续浏览下⾯的相关⽂章希望⼤家以后多多⽀持!。
逆波兰转换C语言(带注释)

#include <stdio.h>#include <malloc.h>struct stack{char letter;struct stack *next;};int rank(char a); ////////判断运算符优先级函数void push(char a,struct stack*s);char pop(struct stack *s);void main(){char element;int i=0,j=0;struct stack *s;s=(struct stack*)malloc(sizeof(struct stack)); ////////创建一个运算符栈s->next=NULL;push('@',s); ////////给栈一个起始值while(s->next->letter!='#') ////////以‘#’作为输出的结尾{element=getchar();if(element!='#') ////////当输入不为结尾标志时{if((element>'a'&& element<'z') || (element>'A' && element<'Z')) ////////若输入为字母,则直接输出printf("%c",element);else if(rank(element)>rank(s->next->letter))push(element,s);////////若不为字母,则判断该运算符的优先级else{while(rank(element)<=rank(s->next->letter) && s->next->letter!='@') ///////输入运算符的优先级高于栈顶运算符的优先级,进栈{printf("%c",pop(s));///////若优先级不高于栈顶运算符,则将栈顶弹出,并输出,}///////直到栈顶运算符的优先级严格小于输入运算符的优先级push(element,s);///////或者已经到达栈底,之后将该输入的运算符进栈}}else push(element,s);////////若为输入结尾标志符,直接进栈,跳出while循环}while(s->next->letter!='@')////////将栈中的剩余的运算符全部弹出,并依次输出‘#’和‘@’不输出{if(s->next->letter!='#')printf("%c",pop(s));elseelement=pop(s);}}void push(char a,struct stack*s){struct stack* temp;temp=(struct stack*)malloc(sizeof(struct stack));temp->letter=a;temp->next=s->next;s->next=temp;}char pop(struct stack *s){struct stack* temp;char a;a=s->next->letter;temp=s->next;s->next=s->next->next;free(temp);return a;}int rank(char a){if(a=='+'||a=='-')return 1;else if(a=='*'||a=='/')return 2;elsereturn 4;}。
C#.NET逆波兰算法求解普通算式(支持自定义运算符)

先来一个例子:using System;using System.Collections.Generic;using RPN;namespace CSharp_Console{class Program{public static void Main(string[] args){var rpn = new ReversePolishNotation();rpn.AddOperation(new Power('^', "乘方", 5));rpn.AddOperation(new E('e', "科学记数法", 5));var expression = "3^6 +78*345+3-345/3e(-2)*(-9+3-5*7)";try{Console.WriteLine(rpn.RpnExpression(expression));Console.WriteLine(rpn.Calculate(expression));}catch (Exception ex){Console.WriteLine(ex.Message);}Console.ReadKey();}}//以下是定义拓展运算符,例子仅供参考class E:ReversePolishNotation.Operator{public E(char symbol, string name, int pri) : base(symbol, name, pri) { }public override double Calc(double op1, double op2){return op1 * Math.Pow(10, op2);}}class Power:ReversePolishNotation.Operator{public Power(char symbol, string name, int pri) : base(symbol, name, pri) { }public override double Calc(double op1, double op2){return Math.Pow(op1, op2);}}}实现源代码:using System;using System.Collections.Generic;namespace RPN{/// <summary>/// 逆波兰表示法(后缀表示法)/// <remarks>该类支持扩展运算符,你可以通过继承ReversePolishNotation.Operator来自定义自己的运算符,并通过ReversePolishNotation.AddOperation方法将实例化的运算符对象加入逆波兰表示法中。
c#逆波兰式实现计算器

c#逆波兰式实现计算器语⽂不好,不太会组织语⾔,希望不要太在意。
如题,先简要介绍⼀下什么是逆波兰式通常我们在写数学公式的时候就是a+b+c这样,这种表达式称为中缀表达式,逆波兰式⼜称为后缀表达式,例如a+b 后缀表达式就为ab+⽽把中缀表达式转为逆波兰式也是很容易的,以下算法摘⾃百度百科简要说⼀下栈,栈是⼀种先进后出的对象集合,可以把栈理解为⼀个桶,先进后出 Stack Peek()是取出但是不剔除做⽐较的时候⽤,Pop()是出栈,Push()⼊栈⾸先需要分配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栈便为逆波兰式输出结果。
不过S2应做⼀下逆序处理。
便可以按照逆波兰式的计算⽅法计算了!把⼀个表达式转为逆波兰式⽐如 (a+b)*c 逆波兰式为ab+c*a为数字,⼊栈,b为数字,⼊栈,“+”,为运算符 a b出栈,计算a+b 然后将结果⼊栈,c⼊栈,"*"为运算符,a+b的结果出栈,c出栈,运算* 将结果再⼊栈运算完毕,栈⾥的结果就是我们想要的了代码实现(有点乱)判断元素是不是为数字static bool IsNumber(string s){return Regex.IsMatch(s, @"\d+");}判断元素是否为运算符(+-*/)static bool IsSiZe(string s){string ts = "+-*/";return ts.IndexOf(s) > -1;}判断优先级static int Level(string s){int i = 0;switch (s){case",":i = 0;break;case"(":case")":case"#":i = 1;break;case"+":case"-":i = 2;break;case"*":case"/":i = 3;break;}return i;}计算private static void Calc(Stack<string> numStack, Stack<string> operStack){int rightnum = int.Parse(numStack.Pop());int leftnum = int.Parse(numStack.Pop());string oper = operStack.Pop();switch (oper){case"+":numStack.Push((leftnum + rightnum).ToString());break;case"-":numStack.Push((leftnum - rightnum).ToString());break;case"*":numStack.Push((leftnum * rightnum).ToString());break;case"/":numStack.Push((leftnum / rightnum).ToString());break;}}总体实现代码static void ToNiBoLan(string exp){operStack.Push("#"); //进栈便于⽐较string token = "";for (int i = 0; i < exp.Length; i++){if (IsNumber(exp[i].ToString())) //如果是数字{token += exp[i].ToString();}else if (exp[i].ToString() == "(") //左括号直接进栈{operStack.Push(exp[i].ToString());if (IsNumber(token))numStack.Push(token);token = "";}else if (IsSiZe(exp[i].ToString())){if (IsNumber(token))numStack.Push(token);token = "";int item = Level(exp[i].ToString()).CompareTo(Level(operStack.Peek())); //⽐较运算符优先级 if (item > 0) //如果优先级⾼于栈顶,运算符进栈{operStack.Push(exp[i].ToString());}else //如果运算符⼩于或等于栈顶进⾏计算并将运算符进栈{Calc(numStack, operStack);operStack.Push(exp[i].ToString());}}else if (exp[i].ToString() == ")") //如果遇到右括号依次遍历进⾏计算直⾄遇到左括号{if (IsNumber(token))numStack.Push(token);token = "";while (operStack.Peek() != "("){Calc(numStack, operStack);}token = numStack.Pop(); //拿出数字便于进⾏下⼀次计算operStack.Pop(); //符合条件的左括号出栈}else //遍历结束{if (IsNumber(token))numStack.Push(token);token = "";while (numStack.Count > 1){Calc(numStack, operStack);}}}} 调⽤string s = Console.ReadLine()+"#"; //为了便于⽐较,在表达式结尾加上"#" ToNiBoLan(s);Console.WriteLine(numStack.Pop()); 总体代码如此。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
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 ')': /*判定为右括号*/