编译原理DFA地生成与字符串地识别.docx
- 文档编号:18862028
- 上传时间:2023-04-24
- 格式:DOCX
- 页数:15
- 大小:51.97KB
编译原理DFA地生成与字符串地识别.docx
《编译原理DFA地生成与字符串地识别.docx》由会员分享,可在线阅读,更多相关《编译原理DFA地生成与字符串地识别.docx(15页珍藏版)》请在冰豆网上搜索。
编译原理DFA地生成与字符串地识别
实验报告
实验项目列表
序号
实验项目名称
成绩
01
DFA的生成与字符串的识别
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
总评成绩:
教员签字:
一、实验名称
DFA的生成与字符串的识别
二、实验目的
1.掌握正规文法与FA之间的转换;
2.掌握通过DFA识别字符串的具体操作过程。
三、实验容和要求
程序A
(1)输入输出
输入:
正规文法
输出:
FA
(2)具体功能
本程序的具体功能包括以下两项:
1)输入正规文法,并构造其等价的FA;
2)对构造出的FA进行判断:
是NFA晒是DFA。
程序B
(1)输入输出
输入:
DFA,字符串
输出:
字符串的DFA识别过程(状态转换轨迹)及错误信息或成功识别信息。
(2)具体功能
本程序的具体功能包括以下4项:
1)输入DFA;
2)输入一个字符串;
3)对输入的字符串用DFA进行识别,并输出识别的过程(DFA状态转换轨迹);
4)若DFA成功识别(输入串结束时到达某终态),则给出成功识别的信息。
若字符串不能为DFA所识别(在某状态下遇某输入符不能进行正常的状态转换),则给出错误信息并结束程序的运行。
四、实验环境
1.硬件环境:
PC机
2.软件环境:
Windows操作系统,VC++集成开发环境
五、算法设计思想
对于程序A,首先考虑的是正规文法的存储。
根据情况可以将左右部分开存储,也可采用结构体的方式,将一个文法存储在一个结构体节点里。
本程序采用了前者。
将每个正规文法的左部存储在x[]字符组里,右部的终结符存储在y[]中。
在用户输入了正规文法之后,分别考虑两种情况:
1.右部只有一个终结符;2.右部有一个终结符和一个非终结符。
根据两种情况分别对文法做如下存储:
情况一在z[]里存入默认的终态‘Z’;情况二在z[]里存储右部的非终结符。
然后,为了使结果一目了然,设计者采用简易表格输出了对应FA的初态,终态,状态集,字母表等主要信息。
在最后将文法的格式转化成状态矩阵的格式,并输出相应表格。
最后,对输入文法本身进行了判断:
若存在某一产生式左部和右部终结符均相同,但右部非终结符不同的情况,则输入文法所对应的FA为NFA;反之,若不存在这样的情况则为DFA。
对于程序B,根据需要采用了结构体的存储方式。
DAF[].A用于存储当前状态,DAF[].B用于存储输入符,DAF[].C用于存储后继状态。
变量start用于存储当前状态量,outstr[]存储已识别通过的状态。
开始识别时,读入一个字符,采用顺序查找的方法找到与当前状态和输入符均符合的结点,将此时的DAF[].C赋值给start,并存入输出字串outstr[]。
然后循环。
若某次查找无法找到对应的后继状态,报错。
当查找到终态时,若此时字串也读取完毕则识别成功,若不然则继续。
若字串读取完毕而未到终态,报错。
六、主要问题与解决方法
问题一:
对于程序A,当输出状态集和字母表时会出现重复的元素,因此重新使用了字符数组xx[],yy[],zz[]来重新存储需要输出的元素,使输出的字符不重复。
问题二:
对于表格的制作与输出,采用了光标控制的方法。
运用gotoxy函数解决了按行和按字符位从左到右的输入局限性,能灵活的控制输入的位置,界面更加友好。
七、实验结果
按照实验的要求,程序A实现了正规文法到有穷自动机的转换,输出的FA信息较为详细,表格化的输出方式能够让用户清晰的得到自己需要的信息。
最后能够准确给出有穷自动机类型的判断,且整个用户界面友好美观。
程序B实现了输入DFA的存储以及字符串的识别功能,并能够给出识别的状态转换轨迹。
程序使用方法较为简便。
以下是程序的用户运行界面截图:
程序A运行界面:
程序B运行界面:
八、体会、质疑、建议
本次实验帮助编写者巩固了关于状态集、初态、终态字母表等基本术语的概念,对实验者熟练掌握正规文法与FA的相互转换、词法分析的基本流程等课堂知识起到了很好的实践作用。
对于整个程序的编写也锻炼了程序编写者将算法思想转化为程序代码的能力。
本次实验是编译原理课程的第一次实验。
课程本身是具有一定难度的,实验的过程使得实验者对课堂上一些晦涩难懂的知识点得到了更好的理解,并且锻炼了编程能力,积累了一定的实践经验,希望编译原理课程能够安排更多的实验课程。
九、源代码
程序A代码:
#include
#include
#include
#include
#include
#defineM10
voidgotoxy(intx,inty){
COORDcoord;
coord.X=x;
coord.Y=y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),coord);
}
voidprint()//简易画线代码,呵呵,画行直线
{
inti,j;
for(i=0;i<10;i++)
printf("─");
printf("┬");
for(i=0;i<25;i++)
printf("─");
putchar(10);
for(i=0;i<10;i++)
printf("");
printf("│");
putchar(10);
for(j=0;j<3;j++)//画5行直线
{for(i=0;i<10;i++)
printf("─");
printf("┼");
for(i=0;i<25;i++)
printf("─");
putchar(10);
for(i=0;i<10;i++)
printf("");
printf("│");
putchar(10);
}
for(i=0;i<10;i++)
printf("─");
printf("┴");
for(i=0;i<25;i++)
printf("─");
putchar(10);
}
voidprint2(intx)//简易画线代码,呵呵,画行直线
{
inti,j;
for(i=0;i<12;i++)
printf("─");
printf("┬");
for(i=0;i<12;i++)
printf("─");
printf("┬");
for(i=0;i<13;i++)
printf("─");
putchar(10);
for(i=0;i<12;i++)
printf("");
printf("│");
for(i=0;i<12;i++)
printf("");
printf("│");
putchar(10);
for(j=0;j {for(i=0;i<12;i++) printf("─"); printf("┼"); for(i=0;i<12;i++) printf("─"); printf("┼"); for(i=0;i<13;i++) printf("─"); putchar(10); for(i=0;i<12;i++) printf(""); printf("│"); for(i=0;i<12;i++) printf(""); printf("│"); putchar(10); } for(i=0;i<12;i++) printf("─"); printf("┴"); for(i=0;i<12;i++) printf("─"); printf("┴"); for(i=0;i<13;i++) printf("─"); putchar(10); } voidmain() { inti=0,j=0,sign=0,n=0,cnt=0; charstr[M],endget,x[M],y[M],z[M],xx[M],yy[M],zz[M]; printf("请输入正规文法: \n"); do { cin>>str; if(strlen(str)==3)/*输入产生式为S_a型*/ { x[i]=str[0]; y[i]=str[2]; z[i++]='Z'; } elseif(strlen(str)==4)/*输入产生式为S_aB型*/ { x[i]=str[0]; y[i]=str[2]; z[i++]=str[3]; } elseprintf("输入错误,再见! \n"),exit(0); for(j=0;j<4;j++)str[j]=NULL; n=i; printf("是否结束输入? (Y/N): "); cin>>endget; gotoxy(0,n+1); printf(""); gotoxy(0,n+1); }while(endget! ='Y'); printf("\n\n对应的FA: \n"); print();/*制表函数*/ gotoxy(0,n+5); printf("状态集Q"); gotoxy(22,n+5); for(i=0;i { { for(j=0;j if(x[i]==xx[j])break; } if(j==cnt)xx[cnt++]=x[i]; } for(i=0;i printf("%c",xx[i]); printf("Z\n\n字母表∑"); gotoxy(22,n+7); cnt=0; for(i=0;i { { for(j=0;j if(y[i]==yy[j])break; } if(j==cnt)yy[cnt++]=y[i]; } for(i=0;i printf("%c",yy[i]); putchar(10); putchar(10); printf("初态q0"); gotoxy(22,n+9); printf("%c",x[0]); putchar(10); putchar(10); printf("终态Z"); gotoxy(22,n+11); printf("Z"); putchar(10); putchar(10); printf("状态转换矩阵\n"); print2(n);/*制表函数*/ gotoxy(8,n+15); printf("现态"); gotoxy(35,n+15); printf("输入符"); gotoxy(60,n+15); printf("后继态"); for(i=0;i { gotoxy(2,n+17+i*2); printf("%c",x[i]); gotoxy(27,n+17+i*2); printf("%c",y[i]); gotoxy(52,n+17+i*2); printf("%c",z[i]); } putchar(10); putchar(10); for(i=0;i { for(j=i+1;j if(x[i]==x[j]&&y[i]==y[j]&&z[i]! =z[j]) sign=1; } if(sign==1)printf("该FA是NFA。 \n"); elseprintf("该FA是DFA。 \n"); } 程序B代码: #include #include #include #include #include #defineM30//DFA最多的delta函数个数 #defineN40//能识别的最大字符串长度 typedefstructs { charA; charB; charC; }node; voidgotoxy(intx,inty){ COORDcoord; coord.X=x; coord.Y=y; SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),coord); } voidmain() { intt,len,i=0,j=0,z=0,m=0; charstart,endget,str[N],outstr[N]; nodeDFA[M]; printf("请输入DFA,字符间用空格分隔: \n"); do { cin>>DFA[i].A; cin>>DFA[i].B; cin>>DFA[i].C; i++; printf("是否结束输入? (Y/N): "); cin>>endget; gotoxy(0,i+1); printf(""); gotoxy(0,i+1); }while(endget! ='Y'); cnt=i; printf("请输入须识别的字符串: \n"); cin>>str; outstr[m++]=start=DFA[0].A; len=strlen(str); for(i=0;i<=len;i++) { if(start==DFA[cnt-1].C&&i==len) { printf("识别成功! \n"); printf("状态转换轨迹为: \n"); for(z=0;z printf("%c",outstr[z]); putchar(10); break; } for(j=0;j { if(DFA[j].A==start&&DFA[j].B==str[i]) break; } if(j==cnt)printf("识别错误,再见! \n"),exit(0); elseoutstr[m++]=start=DFA[j].C; } if(i! =len)printf("识别错误,再见! \n"); }
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 编译 原理 DFA 生成 字符串 识别