- 实验名称
与正规文法等价的FA的生成程序
- 实验目的
1.掌握根据正规文法转化为FA的原理;
2.实现FA的生成程序。
- 实验内容和要求
- 输入正规文法,并构造其等价的有穷自动机(FA)。
- 对构造出的FA进行判断——是不确定的有穷自动机(NFA)还是确定的有穷自动机(DFA)。
- 实验环境
VS 2022
- 算法设计思想
构造一个fa[][]结构体表,结点内放置一个string类字符串,供存储后继态。接收终结符和非终结符集,都用string接收,fa表行对应一个非终结符,列对应一个终结符,
由于正规文法必定由三个或两个字符输入组成(无后继的文法用#号填充),则用三个char类型字符接收,然后做分析,利用第一个非终结符找到行,利用第二个终结符找到列,然后将第三个字符存入fa表对应的行列中,如果第三个字符为#号,则手动存入Z字符。判断NFA或DFA,在分析存状态的同时,查看string.size()字符长度,如果超过1,则存在多个后继态,判断出FA为NFA。
- 主要问题与解决方法
- 如何在最后判断FA为NFA或DFA。利用一个标记judge,如算法思想中说的,如果查找过程中,发现当前存的字符串大小超过1,则存在多个后继态,即为NFA,此时judge置为1,默认为0,待fa表全输出后,做一个判断if(judge),然后输出NFA或DFA。
- #号如何处理。判断,若第三个字符为#号时,则往该结点字符串存入‘Z’字符。‘Z’表示终态。
- 实验结果
- 体会、质疑、建议
代码中的奥妙,其乐无穷!!!
- 源代码
#include<iostream>
#include<string>
#include<iomanip>
#define N 100
using namespace std;
void creat();
int main()
{ /************************************主函数实现部分,通过while实现即时多次使用程序**************************/
creat();
while (1) {
/***********************************简单的用户交互设计******************************************************/
int choice;
cout << "1.Try new FA./2.Exit" << endl;
cout<< "Press:";
cin >> choice;
if (choice == 1)creat();
else return 0;
}
}
void creat()
{ /************************************初始化,创建FA表和VN,VT集*********************************************/
struct { //定义结构体,结点内存放一个string字符串,方便处理
string state;
}fa[N][N];
string VN; //存储非终结符
string VT; //存储终结符
int sum, judge=0; //sum为FA文法个数,judge用来判断DFA或NFA
char vn, vt, z; //用三个char字符来接受每一条文法
/************************************开始读取VN,VT,sum***************************************************/
cout << "Please input the VN word:" << endl;
cin >> VN;
cout << "Please input the VT word:" << endl;
cin >> VT;
cout << "Please input the amount of the FA rules:" << endl;
cin >> sum;
cout << "Please input the FA rule:" << endl;
/************************************开始读取文法,同时做处理**********************************************/
for (int s = 0;s < sum;s++) {
cin >> vn >> vt >> z;
if (z != '#')fa[VN.find(vn)][VT.find(vt)].state.push_back(z);//若z不为#号,往fa表中字符串存放入z
else fa[VN.find(vn)][VT.find(vt)].state.push_back('Z'); //若z为#号,则fa表中直接手动存入终态'Z'
if (fa[VN.find(vn)][VT.find(vt)].state.size() >1)judge = 1; //若字符串长度.size()不小于2,则表示,该状态集存在两个以上终态,因此judge置为1
}
/************************************FA文法表输出**********************************************************/
cout << "The FA table is as followed:" << endl << " ";
for (auto i : VT)cout << right << setw(5) << i;//先将第一行终结符按格式输出
cout << endl;
for (int i = 0;i < VN.size();i++) { //逐行输出FA表
cout << VN.at(i); //输出每行首位非终结符
for (int j = 0;j < VT.size();j++)cout << right << setw(5) << fa[i][j].state;//依次输出FA表内每行状态集
cout << endl;
}
/************************************FA文法表判断**********************************************************/
if (judge)cout << "The FA is NFA." << endl;
else cout << "The FA is DFA." << endl;
}
/*案例数据1 NFA
SAB
ab
8
SaA
SbB
Sa#
AaB
AbA
BaS
BbA
Bb#
案例数据2 DFA
SAB
ab
6
SaA
SbB
AaA
AbB
BbA
Ba#
*/