计算理论导引实验 NFA转DFA
nfa转化为dfa例题详解

确定有限自动机(NFA )到确定有限自动机(DFA )的转化是正则表达式和有限自动机等形式化语言理论中的一个重要概念。
这个过程涉及将非确定性自动机转化为等价的确定性自动机。
下面是一个简单的例子,演示如何将一个NFA 转化为DFA 。
示例 NFA:考虑一个NFA ,它接受所有包含子串 "01" 的二进制字符串。
NFA 状态转移图:NFA 状态转移规则:1. q0→0q12. q1→1q23. q2→1,εq34. q3→1,εq35. q3→0,εq0NFA 状态图解释:•q0 是起始状态。
•q2 是接受状态。
•从 q0 开始,读入 "0" 到达 q1,再读入 "1" 到达 q2,形成 "01" 子串。
•从 q2 通过 "1" 和 ε 达到 q3,表示可以在 "01" 后面追加 "1"。
•q3 可以通过 "1" 和 ε 一直回到自身,表示可以在 "01" 后面追加任意数量的 "1"。
• q3 还可以通过 "0" 和 ε 返回到 q0,表示可以在任意位置重新开始 "01" 的匹配。
NFA到DFA转换:下面是将上述NFA转化为DFA的步骤:1.构建子集构造法的初始状态:初始状态是 NFA 的起始状态的ε-闭包。
在这个例子中,初始状态为 {q0, q3}。
2.状态扩展:对于每个状态集合,找出它的ε-闭包,并对每个可能的输入符号应用状态转移规则,形成新的状态集合。
–对于输入 "0":•从 {q0, q3} 中的 q0 通过 "0" 可以到达 q1,形成 {q1}。
–对于输入 "1":•从 {q0, q3} 中的 q0 通过 "1" 可以到达 q2,形成 {q2}。
编译原理实验NFA确定化为DFA

实用文档2016.11.02不确定有穷状态自动机的确定化目录一、实验名称 (2)二、实验目的 (2)三、实验原理 (2)1、NFA定义 (2)2、DFA的定义 (2)3、closure函数 (2)4、move函数 (3)四、实验思路 (3)1、输入 (3)2、closure算法 (3)3、move算法 (3)4、构造子集 (4)5、输出 (4)五、实验小结 (4)1、输入存储问题 (4)2、closure算法问题 (4)3、输出问题 (5)六、附件 (5)1、源代码 (5)2、运行结果截图 (7)一、实验名称不确定有穷状态自动机的确定化二、实验目的输入:非确定有穷状态自动机NFA输出:确定化的有穷状态自动机DFA三、实验原理1、NFA定义一个不确定的有穷自动机M是一个五元组,M=(K,E,f,S,Z)其中a.K是一个有穷集,它的每个元素称为一个状态;b.E是一个有穷字母表,它的每个元素称为一个输入符号;c.f是一个从K×E*到K的子集的映像,即:K*E*->2k,其中2k表示K的幂集;d.S包含于K,是一个非空初态集;e.Z包含于K,是一个终态集。
2、DFA的定义一个确定的有穷自动机M是一个五元组,M=(K,E,f,S,Z)其中a.K是一个有穷集,它的每个元素称为一个状态;b.E是一个有穷字母表,它的每个元素称为一个输入符号;c.f是转换函数,是K×E->K上的映像,即,如f(ki,a)=kj(ki∈K,kj∈K)就意味着,当前状态为ki,输入字符为a时,将转换到下一状态kj,我们把kj称作ki的一个后继状态;d.S∈K,是唯一的一个初态;e.Z包含于K,是一个终态集,终态也称可接受状态或结束状态。
3、closure函数状态集合I的ε—闭包,表示为ε—closure(I),定义为一状态集,是状态集I中的任何状态S经任意条ε弧而能到达的状态的集合。
4、move函数状态集合I的a弧转换,表示为move(I,a),定义为状态集合J,其中J是所有那些从I中的某一状态经过一条a弧而到达的状态的全体。
NFA到DFA的确定化及最小化

for(n=0;n<y;n++)
{
if(d[n].find(t[NODE.find(d[i][j])].jihe[k])<d[n].length()||t[NODE.find(d[i][j])].jihe[k].length()==0)
{
if(t[NODE.find(d[i][j])].jihe[k].length()==0)
he.jihe[m]+=b[j].last[0];
}
//输出
void outputfa(int len,int h,chan *t)
{
int i,j,m;
cout<<" I ";
for(i=0;i<len;i++)
cout<<'I'<<CHANGE[i]<<" ";
cout<<endl<<"-------------------------"<<endl;
t[h++].ltab=t[i].jihe[j];
}
}
cout<<endl<<"状态转换矩阵如下:"<<endl;
outputfa(len,h,t); //输出状态转换矩阵
//状态重新命名
string *d=new string[h];
NODE.erase();
cout<<endl<<"重命名:"<<endl;
NFA转化为DFA的确定化及最小化
编译原理实验NFA确定化为DFA

编译原理实验NFA确定化为DFA编译原理中的NFA(Non-deterministic Finite Automaton,非确定性有限自动机)是一种能够识别正则语言的形式化模型。
它的设计简单,但效率较低。
为了提高识别效率,需要将NFA转化为DFA(Deterministic Finite Automaton,确定性有限自动机)。
本文将介绍NFA确定化为DFA的一般方法,并以一个具体例子来说明该过程。
首先,我们来了解一下NFA和DFA的差异。
NFA可以有多个转移路径,每个输入符号可以对应多个状态转移,而DFA每个输入符号只能对应唯一的状态转移。
这使得NFA在识别过程中具有非确定性,无法确定下一个状态。
而DFA则能够准确地根据当前状态和输入符号确定下一个状态。
NFA确定化为DFA的一般方法如下:1.创建DFA的初始状态。
该状态对应NFA的起始状态以及从起始状态经过ε(空)转移可以到达的所有状态。
2.对DFA的每个状态进行如下处理:a)对当前状态的每个输入符号进行处理。
b)根据当前状态和输入符号,确定下一个状态。
如果有多个状态,需要将它们合并为一个DFA状态。
c)重复上述步骤,直到处理完所有输入符号。
3.对于合并的DFA状态,需要重复执行第2步的处理过程,直到没有新的合并状态产生为止。
4.最终得到的DFA包含的状态即为NFA确定化的结果。
下面以一个具体的例子来说明NFA确定化为DFA的过程。
考虑以下NFA:(状态)(输入符号)(转移状态)1a,ε1,22a33b44a5首先,创建DFA的初始状态,根据NFA的起始状态和通过ε转移可以到达的状态。
在该例子中,起始状态为1,通过ε转移可以到达状态1和2、因此,初始状态为{1,2}。
接下来,对初始状态{1,2}进行处理。
对于输入符号a,根据NFA的状态转移表可以得到DFA的下一个状态为{1,2,3},因为NFA的状态1通过a和ε可以到达状态3、对于输入符号b,当前状态没有转移。
NFA如何转换成等价的DFA

NFA如何转换成等价的DFANFA(Non-deterministic Finite Automaton)和DFA (Deterministic Finite Automaton)都是有限自动机,它们在计算理论中起着重要的作用。
NFA允许在一个状态下有多个转移选项,而DFA则要求在给定输入下只有一个确定的转移选项。
本文将从NFA转换为DFA的角度进行讨论。
首先,让我们回顾一下NFA的定义。
NFA由以下五个元素组成:1.一个有限的状态集合Q。
2.一个有限的输入字母表Σ。
3.一个状态转移函数δ:QxΣ->P(Q),其中P(Q)表示Q的幂集,即所有可能子集的集合。
4.一个初始状态q0∈Q。
5.一个接受状态集合F⊆Q。
NFA接受一个输入字符串的条件是,通过状态转移函数从初始状态q0开始,能够读取字符串中的每个符号并转移到一个接受状态。
要将NFA转换为DFA,我们可以使用子集构造法。
该方法的核心思想是,DFA的每个状态对应于NFA的一个状态集合。
转换函数用于计算DFA 中的其中一状态通过一些输入符号转移到的状态。
接受状态集合由NFA中的状态集合中有至少一个接受状态的状态组成。
下面是将NFA转换为DFA的具体步骤:1.创建一个新DFA,其中初始状态是NFA的初始状态集合。
将其添加到DFA状态集合中。
2.对于每个DFA状态集合,对每个输入符号执行以下步骤:-使用NFA状态集合中的状态和输入符号计算出新的状态集合。
这可以通过查找NFA状态集合中每个状态在给定输入下能够到达的状态来完成。
-如果新的状态集合不在DFA状态集合中,将其添加到DFA状态集合中。
-添加一个转移函数,使得在给定输入下从当前DFA状态集合转移到新的状态集合。
3.标记任何DFA状态集合,其包含来自NFA接受状态集合的状态作为接受状态。
通过执行上述步骤,可以将NFA转换为等价的DFA。
这个DFA可以接受与原来的NFA相同的输入字符串。
NFA到DFA的转换可以进一步帮助我们理解自动机的功能,并且可以扩展到其他计算理论中的问题。
编译原理NFA转DFA

编译原理NFA转DFA实验⼀:利⽤⼦集法构造DFA⼀.实验⽬的掌握将⾮确定有限⾃动机确定化的⽅法和过程。
⼆.实验要求、内容及步骤实验要求:1.输⼊⼀个NFA,输出⼀个接受同⼀正规集的DFA;2.采⽤C++语⾔,实现该算法;3.编制测试程序;4.调试程序。
实验步骤:1.输⼊⼀个NFA关系图;2.通过⼀个转换算法将NFA转换为DFA;3.显⽰DFA关系图。
三.实验设备计算机、Windows 操作系统、Visual C++ 程序集成环境。
四.实验原理1.NFA-DFA转换原理:从NFA的矩阵表⽰中可以看出,表项通常是⼀状态的集合,⽽在DFA的矩阵表⽰中,表项是⼀个状态,NFA到相应的DFA的构造的基本思路是:DFA的每⼀个状态对应NFA的⼀组状态。
DFA使⽤它的状态去记录在NFA读⼊⼀个输⼊符号后可能到达的所有状态。
输⼊:⼀个NFA N输出:⼀个接受同样语⾔的DFA D⽅法:为D构造转换表Dtran,DFA的每个状态是NFA的状态集。
D的状态集合⽤Dstates表⽰。
D的开始状态为ε-closure(s0),s0是N的开始状态。
使⽤下列算法构造D的状态集合Dstates和转换表Dtran。
如果D的某个状态是⾄少包含⼀个N的接受状态的NFA状态集,那么它是D的⼀个接受状态。
2.⼦集构造法:初始时, ε-closure(S0) 是Dstates中唯⼀的状态且未被标记;while Dstates中存在⼀个未标记的状态T do begin标记T;for 每个输⼊符号a do beginU := ε-closure ( move (T, a) );if U 没在Dstates中then3.ε-closure的计算:将T中所有状态压⼊栈stack;将ε-closure (T) 初始化为T;while stack不空 do begin将栈顶元素t弹出栈;for 每个这样的状态u:从t到u有⼀条标记为ε的边do if u不在ε-closure ( T )中 do begin 将u 添加到ε-closure ( T );将u压⼊栈stack中 endend五.程序设计1.总体设计2.⼦程序设计识别模块读⼊字符识别模块识别标识符识别分界符、运算符识别常数输出六.程序中的结构说明1.结构体Symbolrecord 结构体结构体成员名成员属性Symbol[10] ⽤于存储关键字编码名 id⽤于存储关键字对应的编码读取字符字母识别标识符数字识别数字/识别注释打印并结束FTentrytype结构体结构体成员名成员属性idname[10] ⽤于存储识别后标识符名address ⽤于存储标识符的地址type ⽤于存储标识符的类型digittype结构体结构体成员名成员属性num ⽤于存储识别后的数字address ⽤于存储标识符数字的地址tokentype结构体结构体成员名成员属性id ⽤于存储被识别的类型名entry ⽤于存储标识符的地址idname[10] ⽤于存储被识别的标识符名2.符号编码表符号编码表符号名代码符号名代码Begin 0 } 14End 1 ( 15If 2 ) 16 Then 3 < 17 Else 4 <= 18for 5 = 19do 6 != 20while 7 > 21+ 8 >= 22- 9 := 23* 10 ‘’24/ 11 Id 25; 12 Const 26{ 133.重要函数介绍tokentype recogid(char ch)//识别标识符算法tokentype handlecom(char ch) //handlecom函数,识别注释函数void sort(char ch) //sort函数,读取⽂件内容,并根据读⼊内容调⽤不同的识别函数void scanner()//scanner函数,打开⽂件七.函数代码#include#include#include#include;-----------------------定义单词编码表的数据结构-------------------- struct symbolrecord { char symbol[10];int id;} ;;-------------------------定义符号表的数据结构---------------------- struct entrytype{ char idname[10];int address;int type;};;-------------------------定义常数表的数据结构---------------------- struct digittype{ int num;int address;};;---------------------------Token字的数据结构----------------------- struct tokentype{ int id;int entry;char idname[10];};FILE *fp; //源⽂件指针struct digittype d[10]; //定义常数表,个数指针struct entrytype a[40];int k=0,t=0;;---------------------------单词编码表初始化------------------------ struct symbolrecord s[26]= { "Begin",0,"End",1,"while",7, "+",8,"-",9,"*",10,"/",11,";",12,"{",13,"}",14,"(",15,")",16,"<",17,"<=",18, "=",19,"!=",20, ">",21,">=",22, ":=",23, " ",24,"const",26 };;---------------------------识别标识符算法-------------------------- tokentype recogid(char ch) { tokentype tokenid;FILE *fs;int flag,fflag;char word[10]={0};int i,j;i=0;while(isalpha(ch)||isdigit(ch)){ word[i]=ch;ch=fgetc(fp);i=i+1;}ungetc(ch,fp);word[i]='\0';for(j=0;j<=8;j++){ flag=strcmp(word, s[j].symbol);if(flag==0) //是关键字{ tokenid.id=j;tokenid.entry=-1;break;{ fflag=strcmp(a[j].idname,word);if(fflag==0) //在符号表中可以找到{ tokenid.id=25;tokenid.entry=a[j].address;break;} }if(fflag!=0){ fs=fopen("symbol.txt","a"); //符号表中不存在的标识符 strcpy(a[k].idname, word); a[k].address=k;a[k].type=25;tokenid.id=25;tokenid.entry=k;for(j=0;j<9;j++)fprintf(fs,"%c",word[j]);fprintf(fs,"%c",'\t');fprintf(fs,"%d",a[k].address);fprintf(fs,"%c",'\t');fprintf(fs,"%d",a[k].type);fprintf(fs,"%c",'\n');fclose(fs);k=k+1;} }strcpy(tokenid.idname, word);//⾃⾏添加的return tokenid;};-----------------------------识别数字函数-------------------------- tokentype recogdig(char ch) { int flag;int i=0,j;int num=0;tokentype tokenid;while(isdigit(ch)){ num=(ch-48)+num*10;if(d[j].num==num){ flag=1;tokenid.id=26;tokenid.entry=d[j].address;break;}if(flag!=1){ d[t].num=num;d[t].address=t;tokenid.id=26;tokenid.entry=t;t=t+1;}sprintf(tokenid.idname, "%d", num);//int>>charreturn tokenid;};------------------------识别算符和界符函数------------------------- tokentype recogdel(char ch) { tokentype tokenid;switch(ch){ case'{':{ tokenid.id=13;strcpy(tokenid.idname, "{");//⾃⾏添加的}break;case'}':{ tokenid.id=14;strcpy(tokenid.idname, "}");}break;case';':{ tokenid.id=12;strcpy(tokenid.idname, ";");}break;case'=':{ tokenid.id=19;strcpy(tokenid.idname, "=");}break;case':':ch=fgetc(fp);if(ch=='=') tokenid.id=23; break;case'!':strcpy(tokenid.idname, "!="); } break; case'<':{ch=fgetc(fp);if(ch=='='){ tokenid.id=18;strcpy(tokenid.idname, "<=");}else{ tokenid.id=17;strcpy(tokenid.idname, "<"); ungetc(ch,fp);}}; break;case'>':ch=fgetc(fp);if(ch=='='){tokenid.id=22;strcpy(tokenid.idname, ">=");}else { tokenid.id=21;strcpy(tokenid.idname, ">"); ungetc(ch,fp);}; break;case'+':{ tokenid.id=8;strcpy(tokenid.idname, "+");}break;case'*':{ tokenid.id=10;strcpy(tokenid.idname, "*");}break;case'(':{ tokenid.id=15;strcpy(tokenid.idname, "(");}break;strcpy(tokenid.idname, ")");}break;}tokenid.entry=-1;return tokenid;};---------------------------handlecom函数--------------------------- tokentype handlecom(char ch) { tokentype tokenid;char ch1;int flag=0;if(ch!='*' ){ tokenid.id=25;tokenid.entry=-1;}else{ while(flag==0){ ch1=ch;ch=fgetc(fp);if((ch1='*')&&(ch='/'))flag=1;}}return tokenid;};---------------------------sort函数---------------------------- void sort(char ch){struct tokentype tokenword;FILE * fq = fopen("tokenfile.txt","a");if(isalpha(ch))tokenword=recogid(ch); //字母else if(isdigit(ch))tokenword=recogdig(ch); //数字else if(ch=='/')tokenword=recogdel(ch);printf("%s\t%d\t%d\n",tokenword.idname,tokenword.id,tokenword.entry) ; fprintf(fq,"%d",tokenword.id);fprintf(fq,"%c",'\t');fprintf(fq,"%d",tokenword.entry);fprintf(fq,"%c",'\n');fclose(fq);};--------------------------scanner函数---------------------------- void scanner() { char ch;fp=fopen("source.txt","r");ch=getc(fp);while(ch!=EOF){ if(!isspace(ch)){ sort(ch);}ch=fgetc(fp);}fclose(fp);};------------------------------主函数------------------------------ int main(){ int i;printf("输出token字如下:\n");printf("idname\ttype\taddress\n");scanner();printf("************************************\n");printf("输出符号表如下:\n");printf("%s\t%s\t%s\n","idname","address","type");for(i=0;i<=k-1;i++)printf("%s\t%d\t%d\n",a[i].idname,a[i].address,a[i].type);printf("************************************\n"); printf("输出常数表如下:\n"); printf("%s\t%s\n","num","address");for(i=0;i<=t-1;i++)printf("%d\t%d\n",d[i].num,d[i].address);}⼋.程序测试Source源⽂件程序截图main(){If a!=35end;do whileend;36}九.实验⼩结⼦集构造法的基本思想是构造得到的DFA的每个状态对应于NFA的⼀个状态集合。
NFA转化为DFA编译原理实验报告

编译原理实验报告实验名称正则表达式与有限自动机院系信息工程学院班级计算机科学与技术1班学号 2013550336 姓名朱义一、实验目的通过本次实验,加深对正则表达式,NFA,DFA及其识别的语言的理解二、实验题目编程实现NFA确定化为NFA的过程三、算法思想1.一个自动机是一个五元组,分别是<状态集,符号集,f函数,起始状态,终止状态>2.使用子集法的步骤是:1)将起始状态求闭包,得到S0。
2)从0开始直到totss对每个子集求各个字符所能到达的新子集将其加入tot+1子集中。
3)检查tot+1子集是否与之前的子集重合或者为空,如果重合或为空则子集不增加.4)记录新的状态转换函数。
3. 根据NFA转化为DFA的过程一步步模拟进行操作。
四、数据结构介绍程序里将NFA五元组分别储存在以下数据结构里初态集储存在 int数组 sta_statu[maxs]里 maxs为元素的最大数终态集储存在 int数组 end_statu[maxs]里字符集储存在 char数组 cha[maxs]里状态储存为0~n-1(n个状态情况)状态转换函数储存于结构 stuct statu里struct Edge{ //转化边char cost; //消耗int dest; //指向的终点};struct statu{Edge node[50]; // 终点int cnt;//边的数量statu(){cnt=0;for(int i=0;i<50;i++){node[i].cost=’#';node[i].dest=0;}}}sta[50];//起点五、具体实现使用子集法实现:函数接口解释:void creat_subset(void); 构造子集函数Ins(int a,int ss) 用深搜(dfs)求状态ss的闭包,并将闭包里的所有元素加入到子集closure[a]里。
void ins_subset(int a,int ss,char target)求状态ss通过字符target所能到达的所有状态,并将这些状态加入到子集closure[a]里。
编译原理 NFA转DFA

实验一:利用子集法构造DFA一.实验目的掌握将非确定有限自动机确定化的方法和过程。
二.实验要求、内容及步骤实验要求:1.输入一个NFA,输出一个接受同一正规集的DFA;2.采用C++语言,实现该算法;3.编制测试程序;4.调试程序。
实验步骤:1.输入一个NFA关系图;2.通过一个转换算法将NFA转换为DFA;3.显示DFA关系图。
三.实验设备计算机、Windows 操作系统、Visual C++ 程序集成环境。
四.实验原理1.NFA-DFA转换原理:从NFA的矩阵表示中可以看出,表项通常是一状态的集合,而在DFA的矩阵表示中,表项是一个状态,NFA到相应的DFA的构造的基本思路是:DFA的每一个状态对应NFA的一组状态。
DFA使用它的状态去记录在NFA读入一个输入符号后可能到达的所有状态。
输入:一个NFA N输出:一个接受同样语言的DFA D方法:为D构造转换表Dtran,DFA的每个状态是NFA的状态集。
D的状态集合用Dstates表示。
D的开始状态为ε-closure(s0),s0是N的开始状态。
使用下列算法构造D的状态集合Dstates和转换表Dtran。
如果D的某个状态是至少包含一个N的接受状态的NFA状态集,那么它是D的一个接受状态。
2.子集构造法:初始时, ε-closure(S0) 是Dstates中唯一的状态且未被标记;while Dstates中存在一个未标记的状态T do begin标记T;for 每个输入符号a do beginU := ε-closure ( move (T, a) );if U 没在Dstates中then将U作为一个未被标记的状态添加到 Dstates.Dtran [ T, a ] := Uendend3.ε-closure的计算:将T中所有状态压入栈stack;将ε-closure (T) 初始化为T;while stack不空 do begin将栈顶元素t弹出栈;for 每个这样的状态u:从t到u有一条标记为ε的边do if u不在ε-closure ( T )中 do begin将u 添加到ε-closure ( T );将u压入栈stack中 endend五.程序设计1.总体设计2.子程序设计识别模块读入字符识别模块识别标识符识别分界符、运算符识别常数输出六.程序中的结构说明1.结构体Symbolrecord 结构体结构体成员名 成员属性Symbol[10] 用于存储关键字编码名 id用于存储关键字对应的编码读取字符字母识别标识符数字识别数字/识别注释打印并结束FTFTFTentrytype结构体结构体成员名成员属性idname[10] 用于存储识别后标识符名address 用于存储标识符的地址type 用于存储标识符的类型digittype结构体结构体成员名成员属性num 用于存储识别后的数字address 用于存储标识符数字的地址tokentype结构体结构体成员名成员属性id 用于存储被识别的类型名entry 用于存储标识符的地址idname[10] 用于存储被识别的标识符名2.符号编码表符号编码表符号名代码符号名代码Begin 0 } 14End 1 ( 15If 2 ) 16 Then 3 < 17 Else 4 <= 18for 5 = 19do 6 != 20while 7 > 21+ 8 >= 22- 9 := 23* 10 ‘’24/ 11 Id 25; 12 Const 26{ 133.重要函数介绍tokentype recogid(char ch)//识别标识符算法tokentype recogdig(char ch) ///识别数字函数tokentype recogdel(char ch) //识别算符和界符函数tokentype handlecom(char ch) //handlecom函数,识别注释函数void sort(char ch) //sort函数,读取文件内容,并根据读入内容调用不同的识别函数void scanner()//scanner函数,打开文件七.函数代码#include <stdio.h>#include <string.h>#include <ctype.h>#include <stdlib.h>;-----------------------定义单词编码表的数据结构-------------------- struct symbolrecord{ char symbol[10];int id;} ;;-------------------------定义符号表的数据结构---------------------- struct entrytype{ char idname[10];int address;int type;};;-------------------------定义常数表的数据结构---------------------- struct digittype{ int num;int address;};;---------------------------Token字的数据结构----------------------- struct tokentype{ int id;int entry;char idname[10];};FILE *fp; //源文件指针struct digittype d[10]; //定义常数表,个数指针struct entrytype a[40];int k=0,t=0;;---------------------------单词编码表初始化------------------------ struct symbolrecord s[26]={ "Begin",0,"End",1,"If",2,"Then",3, "Else",4, "for",5, "do",6,"while",7, "+",8,"-",9,"*",10,"/",11,";",12,"{",13,"}",14,"(",15,")",16,"<",17,"<=",18, "=",19,"!=",20, ">",21,">=",22, ":=",23, " ",24,"const",26 };;---------------------------识别标识符算法-------------------------- tokentype recogid(char ch){ tokentype tokenid;FILE *fs;int flag,fflag;char word[10]={0};int i,j;i=0;while(isalpha(ch)||isdigit(ch)){ word[i]=ch;ch=fgetc(fp);i=i+1;}ungetc(ch,fp);word[i]='\0';for(j=0;j<=8;j++){ flag=strcmp(word, s[j].symbol);if(flag==0) //是关键字{ tokenid.id=j;tokenid.entry=-1;break;} }if(flag!=0){ for(j=0;j<=k;j++){ fflag=strcmp(a[j].idname,word);if(fflag==0) //在符号表中可以找到{ tokenid.id=25;tokenid.entry=a[j].address;break;} }if(fflag!=0){ fs=fopen("symbol.txt","a"); //符号表中不存在的标识符 strcpy(a[k].idname, word);a[k].address=k;a[k].type=25;tokenid.id=25;tokenid.entry=k;for(j=0;j<9;j++)fprintf(fs,"%c",word[j]);fprintf(fs,"%c",'\t');fprintf(fs,"%d",a[k].address);fprintf(fs,"%c",'\t');fprintf(fs,"%d",a[k].type);fprintf(fs,"%c",'\n');fclose(fs);k=k+1;} }strcpy(tokenid.idname, word);//自行添加的return tokenid;};-----------------------------识别数字函数-------------------------- tokentype recogdig(char ch){ int flag;int i=0,j;int num=0;tokentype tokenid;while(isdigit(ch)){ num=(ch-48)+num*10;ch=fgetc(fp);i=i+1;}for(j=0;j<=t;j++)if(d[j].num==num){ flag=1;tokenid.id=26;tokenid.entry=d[j].address;break;}if(flag!=1){ d[t].num=num;d[t].address=t;tokenid.id=26;tokenid.entry=t;t=t+1;}sprintf(tokenid.idname, "%d", num);//int>>charreturn tokenid;};------------------------识别算符和界符函数------------------------- tokentype recogdel(char ch){ tokentype tokenid;switch(ch){ case'{':{ tokenid.id=13;strcpy(tokenid.idname, "{");//自行添加的}break;case'}':{ tokenid.id=14;strcpy(tokenid.idname, "}");}break;case';':{ tokenid.id=12;strcpy(tokenid.idname, ";");}break;case'=':{ tokenid.id=19;strcpy(tokenid.idname, "=");}break;case':':ch=fgetc(fp);if(ch=='=') tokenid.id=23; break;case'!':{ ch=fgetc(fp);if(ch=='=') tokenid.id=20;strcpy(tokenid.idname, "!="); } break;case'<':{ch=fgetc(fp);if(ch=='='){ tokenid.id=18;strcpy(tokenid.idname, "<=");}else{ tokenid.id=17;strcpy(tokenid.idname, "<");ungetc(ch,fp);}}; break;case'>':ch=fgetc(fp);if(ch=='='){tokenid.id=22;strcpy(tokenid.idname, ">=");}else { tokenid.id=21;strcpy(tokenid.idname, ">");ungetc(ch,fp);}; break;case'+':{ tokenid.id=8;strcpy(tokenid.idname, "+");}break;case'*':{ tokenid.id=10;strcpy(tokenid.idname, "*");}break;case'(':{ tokenid.id=15;strcpy(tokenid.idname, "(");}break;case')':{ tokenid.id=16;strcpy(tokenid.idname, ")");}break;}tokenid.entry=-1;return tokenid;};---------------------------handlecom函数--------------------------- tokentype handlecom(char ch){ tokentype tokenid;char ch1;int flag=0;if(ch!='*' ){ tokenid.id=25;tokenid.entry=-1;}else{ while(flag==0){ ch1=ch;ch=fgetc(fp);if((ch1='*')&&(ch='/'))flag=1;}}return tokenid;};---------------------------sort函数---------------------------- void sort(char ch){struct tokentype tokenword;FILE * fq = fopen("tokenfile.txt","a");if(isalpha(ch))tokenword=recogid(ch); //字母else if(isdigit(ch))tokenword=recogdig(ch); //数字else if(ch=='/')tokenword=handlecom(ch);elsetokenword=recogdel(ch);printf("%s\t%d\t%d\n",tokenword.idname,tokenword.id,tokenword.entry) ;fprintf(fq,"%d",tokenword.id);fprintf(fq,"%c",'\t');fprintf(fq,"%d",tokenword.entry);fprintf(fq,"%c",'\n');fclose(fq);};--------------------------scanner函数---------------------------- void scanner(){ char ch;fp=fopen("source.txt","r");ch=getc(fp);while(ch!=EOF){ if(!isspace(ch)){ sort(ch);}ch=fgetc(fp);}fclose(fp);};------------------------------主函数------------------------------ int main(){ int i;printf("输出token字如下:\n");printf("idname\ttype\taddress\n");scanner();printf("************************************\n");printf("输出符号表如下:\n");printf("%s\t%s\t%s\n","idname","address","type");for(i=0;i<=k-1;i++)printf("%s\t%d\t%d\n",a[i].idname,a[i].address,a[i].type);printf("************************************\n"); printf("输出常数表如下:\n");printf("%s\t%s\n","num","address");for(i=0;i<=t-1;i++)printf("%d\t%d\n",d[i].num,d[i].address);printf("\n\n");system("pause");}八.程序测试Source源文件程序截图main(){If a!=35end;do whileend;36}九.实验小结子集构造法的基本思想是构造得到的DFA的每个状态对应于NFA的一个状态集合。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
HUNAN UNIVERSITY
计算理论导引实验报告
题目:NFA转换为DFA 学生姓名:
学生学号:
专业班级:计算机科学与技术
上课老师:
实验日期:
一、实验目的 (2)
二、实验方法.......................................................................................... 错误!未定义书签。
三、实验代码.......................................................................................... 错误!未定义书签。
四、测试数据以及运行结果 (5)
一、实验目的
•将一个给定的NFA转换为一个完全等价的DFA。
二、实验方法
编写一个算法/程序,将一个给定的NFA转换为一个完全等价的DFA 三、实验代码
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
int ans[65536];
int one[65536];
int zero[65536];
int lft[65536];
int rgt[65536];
int change[65536];
bool vis[65536];
bool ac[65536];
int cnt, n, q, f;
void init()
{
}
int getlow(int p)
{
return p&(-p);
}
int getloc(int p)
{
int x = 1;
if(p == 1)
return 0;
int i = 0;
while(++i)
{
x <<= 1;
if(p == x)
return i;
}
return 0;
}
int mege(int a, int b)
{
while(b)
{
int x = getlow(b);
if(!(a&x))
a ^= x;
b ^= x;
}
return a;
}
void dfs(int p)
{
ans[cnt] = p;
int lsum = 0, rsum = 0;
while(p)
{
int x = getlow(p);
int y = getloc(x);
lsum = mege(lsum, zero[y]);
rsum = mege(rsum, one[y]);
p ^= x;
}
lft[cnt] = lsum;
rgt[cnt] = rsum;
cnt++;
if(!vis[lsum])
vis[lsum] = 1, dfs(lsum);
if(!vis[rsum])
vis[rsum] = 1, dfs(rsum);
}
int main()
{
init();
int t;
scanf("%d", &t);
while(t--)
{
scanf("%d%d%d", &n, &q, &f);
for(int i = 0; i < n; i++)
scanf("%d", &zero[i]);
for(int i = 0; i < n; i++)
scanf("%d", &one[i]);
cnt = 0;
memset(vis, 0, sizeof(vis));
memset(ac, 0, sizeof(ac));
vis[q] = 1;
dfs(q);
int sum = 0;
for(int i = 0; i < cnt; i++)
if(ans[i]&f)
ac[i] = 1, sum++;
for(int i = 0; i < cnt; i++)
change[ans[i]] = i;
printf("%d %d %d\n", cnt, sum, 0);
for(int i = 0, j = 0; i < cnt; i++)
{
if(ac[i])
{
if(j)
printf(" ");
printf("%d", i);
j++;
}
}
printf("\n");
for(int i = 0; i < cnt; i++)
{
if(i)
printf(" ");
printf("%d", change[lft[i]]);
}
printf("\n");
for(int i = 0; i < cnt; i++)
{
if(i)
printf(" ");
printf("%d", change[rgt[i]]);
}
printf("\n");
}
return 0;
}
四、测试数据以及运行结果
给出NFA,测试正确结果不唯一:
1
4 1 8
1 4 0 8
7 8 8 8
结论:NFA转换成DFA成功,该程序能实现NFA到DFA的转换。