up 2楼的太编译了首先是优先级,要自己定义,比如+-是1,*/是2,等等,根据需要恩,从左到右判断每个字符,还是说你的例子比如读到了344,这时又读到“+”,那么344跟+分别存好,接着读4545,又读到*,*的优先级比+的高,所以再存,继续读234,又读了*,这时*(刚来的)的优先级不高于*(前一个),所以开始计算最近存的两个数,也就是4545*234。依次类推。实际上是两个软件栈,一般用数组实现。一个是算符,一个是数。当读来的算符的优先级高于栈顶的优先级(位于栈顶的就是上次读来的)时,入栈,数字不判断,直接入数字的栈。当读来的算符的优先级不高于栈顶的优先级时,数字栈顶的两个数字弹出,用算符栈栈顶的算符计算,计算结果再入数字栈,刚才计算过的两个数字就不再入了。所以,上面的例子,第一次计算过乘法后,数字栈是344,4545*234的值,算符栈是+,*(这个*是原式233后面的那个),然后继续读字符,判断。在编译原理里这个计算过程叫规约,里面还有好多技巧,比如除数与被除数要互换,如何处理“(”和“)”,还有一个在编译里叫做“acc”的标记,等等。我说的也越来越乱了,在找本《编译技术》的书看看吧。
问题就在怎么判断优先级?如果是 ++*-*+/-***+的顺序如何自动的
判断优先级,
1 1 +//后缀,运算符在两个数后面后缀表达式的求值比较简单,扫描一遍即可完成。它需要使用一个栈,假定用S表示,其元素类型应为操作数的类型,假定为浮点型float,用此栈存储后缀表达式中的操作数、计算过程中的中间结果以及最后结果。假定一个后缀算术表达式以字符’@’作为结束符,并且以一个字符串的方式提供。后缀表达式求值算法的基本思路是:把包含后缀算术表达式的字符串定义为一个输入字符串流对象,每次从中读入一个字符(空格作为数据之间的分隔符,不会被作为字符读入)时,若它是运算符,则表明它的两个操作数已经在栈S中,其中栈顶元素为运算符的后一个操作数,栈顶元素的下一个元素为运算符的前一个操作数,把它们弹出后进行相应运算即可,然后把运算结果再压入栈S中;否则,读入的字符必为操作数的最高位数字,应把它重新送回输入流中,然后把下一个数据作为浮点数输入,并把它压入到栈S中。依次扫描每一个字符(对于浮点数只需扫描它的最高位并一次输入整个浮点数)并进行上述处理,直到遇到结束符’@’为止,表明后缀表达式计算完毕,最终结果保存在栈中,并且栈中仅存这一个值,把它弹出返回即可。具体算法描述为: float Compute(char* str) //计算由str字符串所表示的后缀表达式的值, //表达式要以'@'字符结束。 { Stack S; //用S栈存储操作数和中间计算结果 InitStack(S); //初始化栈 istrstream ins(str); //把str定义为输入字符串流对象ins char ch; //用于输入字符 float x; //用于输入浮点数 ins>>ch; //从ins流对象(即str字符串)中顺序读入一个字符 while(ch!='@') { //扫描每一个字符并进行相应处理 switch(ch) { case '+': x=Pop(S)+Pop(S); break; case '-': x=Pop(S); // Pop(S)弹出减数 x=Pop(S)-x; //Pop(S)弹出的是被减数 break; case '*': x=Pop(S)*Pop(S); break; case '/': x=Pop(S); // Pop(S)弹出除数 if(x!=0.0) x=Pop(S)/x; //Pop(S)弹出的是被除数 else { //除数为0时终止运行 cerr<<"Divide by 0!"<<endl; exit(1); } break; default: //读入的必为一个浮点数的最高位数字 ins.putback(ch); //把它重新回送到输入流中 ins>>x; //从字符串输入流中读入一个浮点数 } Push(S,x); //把读入的一个浮点数或进行相应运算 //的结果压入到S栈中 ins>>ch; //输入下一个字符,以便进行下一轮循环处理 } if(!StackEmpty(S)) { //若栈中仅有一个元素,则它是后缀表达式的值,否则为出错 x=Pop(S); if(StackEmpty(S)) return x; else { cerr<<"expression error!"<<endl; exit(1); } } else { //若最后栈为空,则终止运行 cerr<<"Stack is empty!"<<endl; exit(1); } }
2楼的太编译了首先是优先级,要自己定义,比如+-是1,*/是2,等等,根据需要恩,从左到右判断每个字符,还是说你的例子比如读到了344,这时又读到“+”,那么344跟+分别存好,接着读4545,又读到*,*的优先级比+的高,所以再存,继续读234,又读了*,这时*(刚来的)的优先级不高于*(前一个),所以开始计算最近存的两个数,也就是4545*234。依次类推。实际上是两个软件栈,一般用数组实现。一个是算符,一个是数。当读来的算符的优先级高于栈顶的优先级(位于栈顶的就是上次读来的)时,入栈,数字不判断,直接入数字的栈。当读来的算符的优先级不高于栈顶的优先级时,数字栈顶的两个数字弹出,用算符栈栈顶的算符计算,计算结果再入数字栈,刚才计算过的两个数字就不再入了。所以,上面的例子,第一次计算过乘法后,数字栈是344,4545*234的值,算符栈是+,*(这个*是原式233后面的那个),然后继续读字符,判断。在编译原理里这个计算过程叫规约,里面还有好多技巧,比如除数与被除数要互换,如何处理“(”和“)”,还有一个在编译里叫做“acc”的标记,等等。我说的也越来越乱了,在找本《编译技术》的书看看吧。