DFA的编程实现含源代码实验报告剖析Word格式.docx
《DFA的编程实现含源代码实验报告剖析Word格式.docx》由会员分享,可在线阅读,更多相关《DFA的编程实现含源代码实验报告剖析Word格式.docx(17页珍藏版)》请在冰豆网上搜索。
能将保存在内存变量中的DFA写入DFA文件,也能将DFA文件读入内存中。
(思考:
对稀疏DFA(转换表中为空的地方较多)或用“或”表达转换的DFA(如下的测试用例三),如何改进DFA转换表的表达。
)
(3)DFA的正确性检查:
检查所有集合的元素的唯一性。
检查“开始状态”是否唯一,并是否包含在“状态集”中。
检查“接受状态集”是否为空,并是否包含在“状态集”中。
检查“状态转换表”是否满足DFA的要求。
检查“状态转换表”并非填满时的处理是否得当…
(4)DFA的语言集列表显示:
输入待显示的字符串的最大长度N,输出以上定义的DFA的语言集中长度≤N的所有规则字符串。
(提示:
注意算法中while循环的次数)
(5)DFA的规则字符串判定:
输入(或用字符集随机生成)一个字符串,模拟DFA识别字符串的过程判定该字符串是否是规则字符串(属于DFA的语言集)。
测试用例:
DFA
(一)
DFA
(二)
DFA(三)
实验要求:
按照《编译原理及实践》参考书第二章中描述的“while循环+双层case选择”的算法编程实现一般的DFA。
要求能通过以上三个测试用例的测试。
完成内容中
(1)(5)部分,可得C。
完成内容中
(1)
(2)(5)部分,可得B。
完成内容中
(1)
(2)(4)(5)部分,可得A。
完成全部内容,可得奖励。
判定算法概要:
准备:
开始状态s0,接受状态集F,状态转换表T(s,c),sÎ
S,cÎ
S
c=getchar();
s=开始状态s0;
while(c!
=EOF)//输入未结束则循环…
{
s=T(s,c);
if(s==NULL)
error();
}
if(sÎ
接受状态集F)
accept();
else
error();
通用DFA存储格式的建议:
(用以上的第三个测试DFA为例)
3//字符集中的字符个数(以下两行也可合并成一行)
/*o//以空格分隔的字符集。
O代表任意非/和*的字符
5//状态个数(以下两行也可合并成一行)
12345//状态编号。
若约定总是用从1开始的连续数字表示,则此行可省略
1//开始状态的编号。
若约定为1,则此行可省略
1//结束状态个数。
5//结束状态的编号
2-1-1//状态1的所有出去的转换。
按字符集中的字符顺序给出。
-1表示出错状态
-13-1
343
543
-1-1-1
实验报告:
同时上交纸质报告与电子版报告。
纸质报告以实验分析、实验中遇到的问题及解决方法、实验测试(含屏幕截图)、实验心得等为主,不得大量引用源程序(引用源程序总行数不得超过100行)。
电子版报告以源程序、测试用例、输出文件等为主,包括纸质报告的电子版,须确保提并的源程序能编译运行,否则不要上交。
电子版请发送到****************,邮件标题请写明学号、姓名与实验编号,形如:
<
实验一>
<
学号>
姓名>
。
不得抄袭实验报告与源程序,否则后果自负!
提高内容:
(1)图形化的用户界面;
(2)任意DFA的状态转换图、状态转换表的图形绘制;
附实验报告源码
实验一DFA的编程实现
实验分析:
DFA的初始化
一个DFA的基本信息状态集、字符集、开始状态、结束状态集、状态转换表;
在程序中状态集、字符集、开始状态、结束状态集都用string类型来表示,即可不用考虑用户输入内容的长度。
但缺点是字符集只能是字符而不可以是字符串。
状态转换表:
为三个字符的字符串,第一个为当前状态,第二个为输入字符,第三个为下一状态。
用vector容器存放转换函数的内容
字符串判断
初始化一个DFA,后可以通过一下算法判断一个字符串是否符合该DFA。
开始状态s0,接受状态集F,状态转换表T(s,c),sS,c
if(s接受状态集F)
error();
在实际编写代码中的体现为
voididentify()//判断字符串
{
cout<
"
请输入字符串"
endl;
stringstr;
cin>
>
str;
inti=0;
charpresent=StartStates;
while(i<
str.length())
{
present=move(present,str[i]);
//move函数即去遍历转换表,返回下个状态
if(present=='
N'
)//N即为move返回错误的状态,
{
break;
}
i++;
}
if(FinalStates.find(present)!
=FinalStates.npos)//如果返回的状态用find函数属于最终状态集则表示识别
cout<
该自动机识别此字符串"
else
该自动机不识别此字符串"
}
对DFA的存储与读写
将DNF的信息写入文件中,
第一行:
字符集;
第二行:
状态集;
第三行:
开始状态;
第四行:
结束状态集;
以下行写入状态转换表
按照既定的规定读取文件
中的数据将其赋值,然后
初始化DFA即可;
DFA的语言集列表显示:
这一个模块应该是这个实验中比较难的一部分了。
我并没有使用while循环的这个做法。
而是用函数递归,通过所有字符集的路径去遍历整个DFA。
最后将符合条件的字符串输出;
voidTraversal(charpresent,intN,stringstrass="
)//遍历DFA的语言集列表
if(present=='
||N<
0)//若路径已经大于N或者当前状态错误,停止递归
return;
N--;
=FinalStates.npos)
该自动机识别字符串:
strass<
for(inti=0;
i<
Alphabet.length();
i++)
stringtemp;
temp=strass;
strass+=Alphabet[i];
Traversal(move(present,Alphabet[i]),N,strass);
strass=temp;
递归终止条件的判断。
当N--时,N小于0,或者遍历到无路可走是便终止
遇到的问题:
对于递归的终止条件写得不够明确。
递归前对字符串赋值strass赋值,递归后应该还原,这一点没有想到。
调试了很久。
总结,对递归的具体编写还是不熟悉。
目前的代码,字符集和状态只能是一个字符,若要优化可以用vector<
string>
容器存储即可;
实验用例:
实验结果:
判断字符串:
显示小于N的语言集:
读取DFA文件:
实验总结:
在这次实验中,学习对一般的DFA的表达方法与编程实现方法。
对课本提供的算法有了更深刻的认识。
在编写和调试代码的过程中对自身的编程能力也有了很大的提高。
对自动机和其识别语言有了更透彻的理解。
在动手编程之前一定要好好明确实验的理论准备和思路的理清,能帮助我们在实验过程中少走更多的弯路。
总之在这次实验中收获很多,提高了动手能力和分析问题的能力。
源代码:
//构造一个DFA
#include<
iostream>
vector>
fstream>
usingnamespacestd;
classTransitionTable
public:
charpresent;
//当前状态
charnext;
//下一状态
charinput;
//输入字符
TransitionTable(charP,charI,charD)
present=P;
next=D;
input=I;
};
classDFA
DFA()
1、手动输入,2、读取txt文件"
intselect;
select;
if(select==1)
inti();
if(select==2)
read();
stringStates;
//状态集
charStartStates;
//开始状态
stringFinalStates;
//结束状态集
stringAlphabet;
//字符集
vector<
TransitionTable>
Trans;
//转换函数
voidinti()//初始化自动机
请输入有限状态集S:
States;
请输入字符集A:
Alphabet;
请输入转换函数MOVE--格式为:
当前状态-输入字符-下一状态:
(输入#结束输入)"
intj=0;
while(true)
charinput[4];
cin>
input;
if(strcmp(input,"
#"
)==0)
TransitionTableTemp(input[0],input[1],input[2]);
Trans.push_back(Temp);
请输入开始状态集S0:
StartStates;
请输入结束状态集F:
FinalStates;
voididentify()//识别字符串
请输入字符串:
)//N即为move返回错误的状态,
;
charmove(charP,charI)//move转换函数
Trans.size();
if(Trans[i].present==P&
&
Trans[i].input==I)
returnTrans[i].next;
return'
voidread()//从txt文件中读取DNF的信息
chartemp[10];
fstreamff("
DNF.txt"
ios:
:
in);
ff.getline(temp,10);
Alphabet=temp;
States=temp;
StartStates=temp[0];
FinalStates=temp[0];
while(!
ff.eof())
ff.getline(temp,10);
TransitionTableTemp(temp[0],temp[1],temp[2]);
/*将DNF的信息写入文件中,
第一行:
第二行:
第三行:
第四行:
以下行写入状态转换表*/
voidwrite()
out);
ff<
Alphabet<
States<
StartStates<
FinalStates<
ff<
Trans[i].present<
Trans[i].input<
Trans[i].next<
ff.close();
voidTraversal(charpresent,intN,stringstrass="
)//遍历DFA的语言集列表显示
0)
elseif(FinalStates.find(present)==FinalStates.npos&
N<
return;
intmain()
DFAexample;
example.identify();
intN;
cout<
请输入N"
cin>
N;
example.Traversal(example.StartStates,N);
example.write();
system("
pause"
);
return0;
/*测试用例
输入状态转换表
0a1
0b2
1b2
2a1
1a3
2b3
3a3
3b3
#
2b5
5b5
3b4
5a6
6b4
4a6
6a3
4b5
*/