撰文/周翔
本人开源代码页:http://blog.csdn.net/hifrog/category/131301.aspx
功能:用户输入一个字符串,判断这个字符串是否是后缀表达式,并把它转化为前缀表达式,并显示。
原理:利用S属性文法的制导翻译生成语法树节点,其中该语法树为二叉树。非叶节点保存运算符,叶节点保存数字或变量。制导翻译公式请参考《编译原理》(高等教育出版社,陈意云著,2003年版)一书。笔者使用的产生式
加减二元运算的产生式:E->TE+|TE-|T
乘除二元运算的产生式:T->FT*|FT/|F
变量、数字、二元表达式的产生式:F->E|i
为了避免从左向右推导产生的歧意,笔者采用了从右向左推导。
其它特点:
1.程序能自动判断为什么不是后缀表达式;
2.代码长度不超过100行。
代码:
//*============= 代码: 周翔 ===============*//
#include<string>
#include<iostream>
#include<csetjmp>
using namespace std;
static string expr;
static int pos;
static jmp_buf errjb;
struct BiTree
{
string data;
BiTree* lchild;
BiTree* rchild;
};
BiTree* T_MulDiv();
BiTree* F_ExpNum();
//E->TE+|TE-|T
BiTree* E_AddSub()
{
if(expr[pos]=='+'||expr[pos]=='-')
{
BiTree* ret=new BiTree;
ret->data=expr[pos--];
ret->rchild=E_AddSub();
ret->lchild=T_MulDiv();
return ret;
}
return T_MulDiv();
}
//T->FT*|FT/|F
BiTree* T_MulDiv()
{
if(expr[pos]=='*'||expr[pos]=='/')
{
BiTree* ret=new BiTree;
ret->data=expr[pos--];
ret->rchild=T_MulDiv();
ret->lchild=F_ExpNum();
return ret;
}
return F_ExpNum();
}
//F->E|i
BiTree* F_ExpNum()
{
BiTree* ret=new BiTree;
ret->data="";
if(isalnum(expr[pos]))
{
ret->data=expr[pos--];
ret->lchild=ret->rchild=0;
return ret;
}
if(pos<0)
{
cout<<"出错!未预期的结尾!"<<endl;
longjmp(errjb,1);
}
if(expr[pos]=='+'||expr[pos]=='-'||expr[pos]=='*'||expr[pos]=='/')
{
return E_AddSub();
}
cout<<"出错!非法字符!"<<endl;
longjmp(errjb,1);
}
void PreVisit(BiTree* BT)
{
if(BT)
{
cout<<BT->data;
PreVisit(BT->lchild);
PreVisit(BT->rchild);
}
}
int main()
{
bool quit=false;
do{
if(setjmp(errjb)==0)
{
cout<<"请输入一个表达式(按'Q'或'q'退出):"<<endl;
cin>>expr;
if(expr[0]=='Q'||expr[0]=='q')
quit=true;
else
{
pos=expr.length()-1;
BiTree* Root=E_AddSub();
if((int)expr[pos]>0)
{
cout<<"出错!冗余的字符!"<<endl;
longjmp(errjb,1);
}
cout<<"该后缀表达式的前缀表达式如下:"<<endl;
PreVisit(Root);
cout<<endl;
}
}
else
{
cout<<"您输入的字符串不是后缀表达式!"<<endl;
}
}while(!quit);
return 0;
}
分享到:
相关推荐
在源代码中,`trans` 函数用于将前缀表达式转换为后缀表达式,而求后缀表达式的值的函数尚未给出。通常,求后缀表达式值的函数会遍历后缀表达式,每遇到一个数字就压入操作数栈,每遇到一个运算符就从栈中取出相应的...
这个文件可能包括了处理输入表达式、构建运算符栈、将前缀表达式转化为后缀表达式、以及输出后缀表达式到屏幕的功能。对于C或C++语言,我们可以创建一个主函数,调用这些功能,接收用户输入,然后通过YACC生成的解析...
项目中的"expression"文件很可能包含了C++源代码,实现了上述其中一种或多种求值方法。代码可能包括了表达式的解析、符号表管理(用于存储变量及其对应的值)、运算符优先级判断等功能。同时,为了处理复杂情况,...
总的来说,实现“字符串数学表达试解析执行的C++源代码”需要理解编译原理中的解析概念,掌握C++编程技巧,以及深入理解数学表达式的计算规则。这样的项目不仅有助于提升编程能力,也是对计算机科学基础理论的实践...
源代码通常包括了表达式转换、解析和计算的模块。 在课程设计中,你可能会被要求完成以下任务: - 设计并实现表达式树的数据结构。 - 编写算法将中缀表达式转换为后缀表达式。 - 实现一个计算器程序,能接收后缀...
2. **前缀、中缀和后缀表达式**:在处理表达式时,可以转换为不同的表示形式,如前缀( polish notation)、中缀(infix notation)和后缀(postfix notation,也称为逆波兰表示法)。其中,后缀表达式对于计算非常...
- 前缀表达式(如`-a+b`)和后缀表达式(如`a b +`)常用于表达式求值,因为它们消除了括号的需要,简化了解析。 - 中缀表达式(如`a + b`)是人常用的写法,但在计算机处理时需要转换为前缀或后缀形式,因为它们...
标题中的“控制台表达式计算程序,C++源代码”表明这是一个使用C++编程语言编写的程序,它的主要功能是在控制台环境下解析和计算数学表达式。这种类型的程序通常涉及词法分析、语法分析和计算过程,是编译原理和算法...
前缀和后缀表达式不需要括号,因为运算符的位置决定了优先级,而中缀表达式是我们常见的有括号的运算顺序。在本例中,可能使用了中缀表达式转换为二叉树的方法,再通过遍历这棵树来计算表达式的值。 二叉树表达式求...
在这个环境中,你需要理解编译器的工作原理,如何组织源代码文件,以及如何使用调试工具来测试和优化你的程序。 5. **扩展到浮点数** - **数据类型**:在C++中,我们可以使用`double`数据类型来处理浮点数,确保...
前缀表达式是运算符在操作数前面(如“*+234”),后缀表达式是运算符在操作数后面(如“23*4+”)。这两种表示法可以方便地进行计算,因为它们天然地反映了运算的顺序。 4. **表达式求值**:在前缀或后缀表达式的...
为了从前缀表达式转化为后缀表达式,我们需要遵循以下步骤: 1. 读取前缀表达式的每个字符。 2. 如果字符是操作数,将其添加到后缀表达式中。 3. 如果字符是运算符,根据其优先级将其添加到后缀表达式中。在前缀...
中缀表达式是我们常见的运算符在操作数之间的表达方式,如 "2 + 3 * 4",而波兰式(也称为前缀表达式)和后缀表达式(也称为逆波兰式)则是两种不同的表示方法,它们有助于简化表达式的求值过程,特别是对于编译器和...
这通常涉及到前缀、后缀(逆波兰)表示法或者中缀表达式到后缀表达式的转换。后缀表示法在计算中特别方便,因为它可以使用堆栈数据结构来实现。理解堆栈的工作原理,包括`push`、`pop`和`peek`操作,是实现这种算法...
在计算机科学中,有两种主要的求值策略:前缀表达式(也叫波兰表示法)、中缀表达式(我们常见的运算符在操作数之间的形式)和后缀表达式(也叫逆波兰表示法)。在本演示中,可能使用了其中的一种或多种来实现表达式...
在本压缩包中,"46道题目源代码整合"提供了46个C++编程问题的解决方案,涵盖了计算概论、程序设计以及数据结构与算法等多个领域,对于学习和提升C++编程能力具有很高的参考价值。 【计算概论】 计算概论是计算机...
实现表达式求值有多种方法,如中缀表达式(常见的加减乘除运算符在数字之间)、后缀表达式(也称逆波兰表示法,运算符位于操作数之后)和前缀表达式(运算符位于操作数之前)。其中,后缀表达式通常与堆栈配合使用,...
2. **前缀/后缀表达式(逆波兰表示法)**:为了计算复杂的表达式,程序可能会使用前缀或后缀表示法,因为它们在计算时不需要额外的括号。前缀表示法将操作符放在操作数前面,而后缀表示法则将操作符放在操作数后面。...
这通常需要使用栈这种数据结构来处理运算符的优先级,例如后缀表达式(逆波兰表示法)或中缀表达式的转换与求值。 3. **魔方阵(Magic Square)**:魔方阵是一种特殊的矩阵,其行、列、对角线上的数字之和都相等。...
逆波兰算法,也称为后缀表达式或逆波兰表示法,是一种无括号的数学表达式表示方法。在该表示法中,运算符位于其操作数之后,这使得表达式的计算可以通过栈数据结构来简化。它常用于编译器设计、解析器构建以及计算机...