void CAnalyzeDlg::MakeTree() { HTREEITEM hRoot = m_pTree->m_tree.InsertItem(CString(m_g.GetStart())); CString temp; HTREEITEM hItem = hRoot; stack <HTREEITEM> s; s.push(hItem); while (!TreeStack.empty()) { temp = m_g.GetPrecept(TreeStack.top()).GetRight().c_str(); hItem = s.top(); s.pop(); TreeStack.pop(); for(int i = 0; i < temp.GetLength(); i++) { HTREEITEM hItem2; hItem2 = m_pTree->m_tree.InsertItem(CString(temp.GetAt(i)), hItem); if(m_g.IsInVn(temp.GetAt(i))) { s.push(hItem2); } } m_pTree->m_tree.Expand(hItem, TVE_EXPAND); } assert(s.empty()); assert(TreeStack.empty()); }代码解释
时间: 2023-07-14 18:12:24 浏览: 42
这段代码是一个函数,函数名为MakeTree(),它的作用是构建一棵树并将其显示在界面上。具体来说,它使用了一个栈和一个循环来遍历语法分析栈(TreeStack),将其中的终结符和非终结符插入到树中。该函数的主要步骤如下:
1. 首先,创建了一个根节点(hRoot),节点名称为文法的起始符号(m_g.GetStart())。
2. 接着,将根节点入栈(s.push(hItem))。
3. 进入循环,只要语法分析栈不为空,就继续循环。
4. 从语法分析栈中取出一个元素(TreeStack.top()),并获取其右部(m_g.GetPrecept(TreeStack.top()).GetRight())。
5. 取出栈顶节点(hItem),将其出栈(s.pop()),并将语法分析栈的栈顶元素出栈(TreeStack.pop())。
6. 遍历右部字符串中的字符,依次将终结符和非终结符插入到树中。如果遇到了非终结符,则将其对应的节点入栈(s.push(hItem2)),以备后续处理。
7. 最后,将当前节点展开(m_pTree->m_tree.Expand(hItem, TVE_EXPAND))。
8. 循环结束后,用 assert() 函数来检查栈和语法分析栈是否已经为空。
该函数的目的是为了将语法分析栈中的内容可视化,方便用户查看和理解语法分析的过程。
相关问题
class CAnalyzeDlg : public CResizingDialog { // Construction public: CString GetStepInfo(int iStep, const vector <int> & Status, const vector <char> & Symbol, CString sInput, Pair Action, int Goto); CAnalyzeDlg(CWnd* pParent = NULL); // standard constructor ~CAnalyzeDlg(); void SetGrammar(const Grammar & g); // Dialog Data //{{AFX_DATA(CAnalyzeDlg) enum { IDD = IDD_DIALOG2 }; CEdit m_edit1; CExplorer1 m_web; CString m_input; //}}AFX_DATA // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CAnalyzeDlg) protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //}}AFX_VIRTUAL // Implementation protected: Grammar m_g; CTreeDlg * m_pTree; string m_strTempFilename; // Generated message map functions //{{AFX_MSG(CAnalyzeDlg) virtual void OnOK(); virtual void OnCancel(); afx_msg void OnButton1(); virtual BOOL OnInitDialog(); afx_msg void OnButton2(); afx_msg void OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized); //}}AFX_MSG DECLARE_MESSAGE_MAP() private: void MakeTree(); stack <int> TreeStack; };代码详细介绍
这是一个 MFC 对话框类 CAnalyzeDlg,继承自 CResizingDialog。其中包含了以下成员函数:
- GetStepInfo:根据当前分析步骤的状态、符号、输入、动作以及 Goto 表信息,构造一个分析步骤的信息字符串。
- SetGrammar:设置语法规则。
- OnOK、OnCancel:处理对话框的 OK 和 Cancel 按钮消息。
- OnInitDialog:初始化对话框。
- OnButton1、OnButton2:处理对话框中的两个按钮消息。
- OnActivate:处理对话框激活消息。
此外,该类还包含了以下成员变量:
- m_g:语法规则。
- m_pTree:指向语法分析树对话框的指针。
- m_strTempFilename:临时文件名。
- TreeStack:用于构造语法分析树的栈。
#include <bits/stdc++.h> using namespace std; #define MAXSIZE 1001 int tot; struct Node{ string data; int lchild; int rchild; int fchild; }node[MAXSIZE]; int stack_num[MAXSIZE];//下标数组 int stack_op[MAXSIZE];//运算符数组 int top_num; int top_op; int op_rank[255]; int makenode(string x){ tot++; node[tot].data=x; node[tot].lchild=0; node[tot].rchild=0; node[tot].fchild=0; return tot; }//叶子节点的构造 int maketree(int a,int b,char c){ tot++; node[tot].data=c; node[tot].lchild=a; node[tot].rchild=b; node[tot].fchild=0; node[a].fchild=tot; node[b].fchild=tot; return tot; }//叶子结点构造树 void print_tree(int x){ if(x==0) return; print_tree(node[x].lchild); print_tree(node[x].rchild); cout<<node[x].data<<' '; }//后序遍历 void push_num(int num){ top_num++; stack_num[top_num]=num; } int pop_num(){ return stack_num[top_num--]; } void push_op(char c){ top_op++; stack_op[top_op]=c; } char pop_op(){ return stack_op[top_op--]; } void solve(){ char c=pop_op(); while(c!='('){ int b=pop_num(); int a=pop_num(); push_num(maketree(a,b,c)); c=pop_op(); } } void judge_op(char c){ if(op_rank[c]>op_rank[stack_op[top_op]]||top_op==0){ push_op(c); return; } char x=pop_op(); int b=pop_num(); int a=pop_num(); push_num(maketree(a,b,x)); judge_op(c); } void clearstack(){ while(top_op!=0){ char c=pop_op(); int b=pop_num(); int a=pop_num(); push_num(maketree(a,b,c)); } } int main(){ op_rank['(']=1; op_rank['+']=2; op_rank['-']=2; op_rank['*']=3; op_rank['/']=3; op_rank[')']=4; string s; getline(cin,s); s=s+'@'; tot=0; string s_num; for(int i=0;i<s.size();i++){ switch(s[i]){ case '@': if(s_num!="") push_num(makenode(s_num)); clearstack(); break; case'(': push_op('('); solve(); break; case '+': case '-': case '*': case '/': if(s_num!="") push_num(makenode(s_num)); s_num=""; judge_op(s[i]); break; default: s_num+=s[i]; break; } } print_tree(pop_num()); return 0; }修改此代码使能输出结果
您好,我看出来这是一个表达式求值的代码,但是现在的代码只输出了表达式的后序遍历结果,并没有进行求值。如果您想让程序输出表达式的结果,可以按照以下步骤进行修改:
1. 在节点结构体中添加一个值域,用来存储节点的计算结果:
```c++
struct Node{
string data;
int lchild;
int rchild;
int fchild;
int value; // 添加一个值域,用来存储节点的计算结果
}node[MAXSIZE];
```
2. 修改 `makenode()` 函数,在创建一个数字节点时,将该节点的值域初始化为该数字的值:
```c++
int makenode(string x){
tot++;
node[tot].data=x;
node[tot].lchild=0;
node[tot].rchild=0;
node[tot].fchild=0;
if(isdigit(x[0])){ // 如果是数字节点,则将值域初始化为该数字的值
node[tot].value=stoi(x);
}
return tot;
}
```
3. 修改 `solve()` 函数,在计算完一个操作符节点的值之后,将该节点的计算结果存储到其值域中:
```c++
void solve(){
char c=pop_op();
while(c!='('){
int b=pop_num();
int a=pop_num();
int res;
switch(c){ // 根据操作符计算两个子树的值
case '+': res=node[a].value+node[b].value; break;
case '-': res=node[a].value-node[b].value; break;
case '*': res=node[a].value*node[b].value; break;
case '/': res=node[a].value/node[b].value; break;
}
push_num(maketree(a,b,c)); // 创建一个新的操作符节点,并将其值域设置为该节点的计算结果
node[tot].value=res;
c=pop_op();
}
}
```
4. 最后,在 `main()` 函数中,输出根节点的值域即可:
```c++
cout << node[pop_num()].value << endl;
```
完整代码如下: