DFA的编程实现(含源代码、实验报告)

时间:2024.3.31

实验一(一)程序设计语言及其编译器实现概览(2小时)

实验目的:学习一门简单的程序设计语言的定义及其编译器实现

实验任务:针对一门简单的程序设计语言,阅读其定义文档,初步了解其编译器的源代码。

实验内容:

(1)选择一门语言:TINY或其它语言也可(需自备其编译器的源代码)。

(2)阅读其定义文档,了解语言定义的方法,包括:词法、语法、语义、运行时环境、目标机器、目标语言等内容。

(3)了解其编译器源代码。

· 对TINY语言编译器,其源代码由多个文件组成,请弄清楚每个文件的作用是什么。详情请见《编译原理及实践》第1.7节。请做一个C++工程文件(Win32 Console Application, tiny.dsp),把它们组织起来,然后编译成可执行文件(tiny.exe),即为TINY语言编译器。然后用它编译TINY语言示例源代码(sample.tny)。看看编译生成的目标文件(sample.tm)是怎样的。要运行目标程序,还需要一个虚拟机,名为TM机。TM机是以软件形式存在的,其源代码为tm.c,需要编译生成可执行文件tm.exe。然后将目标程序作为TM机的输入运行TM机即可得到所期待的结果。要求读懂main.c、globals.h、util.h、scan.h和util.c、scan.c等文件,三人一组进行讨论,给每一行加上注释,总结你们各自对程序的理解和阅读程序的收获,每组提交1份加了注释的文件和心得。有能力的同学可加上tm.c。

实验一(二)DFA的编程实现(2小时)

实验目的:通过本次实验,加深对DFA及其识别的语言的理解,学习对一般的DFA的表达方法与编程实现方法。

实验任务:编写一个C语言程序,模拟实现DFA识别字符串的过程。

实验内容:(1)DFA的输入;(2)DFA的存储与读写;(3)DFA的正确性检查;(4)DFA的语言集列表显示;(5)DFA的规则字符串判定;

内容说明:

(1)DFA的输入:

分别输入DFA的“字符集”、“状态集”、“开始状态”、“接受状态集”、“状态转换表”等内容,并保存在设定的变量中。

(2)DFA的存储与读写:

将上述DFA的五元组保存在一个文本文件中,扩展名指定为.dfa。请自行设计DFA文件的存储格式,并说明其含义。能将保存在内存变量中的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();

c = getchar();

}

if (s Î 接受状态集F)

    accept ();

else

    error ();

通用DFA存储格式的建议:(用以上的第三个测试DFA为例)

3 // 字符集中的字符个数 (以下两行也可合并成一行)

/ * o // 以空格分隔的字符集。O代表任意非/和*的字符

5 // 状态个数 (以下两行也可合并成一行)

1 2 3 4 5 // 状态编号。若约定总是用从1开始的连续数字表示,则此行可省略

1 // 开始状态的编号。若约定为1,则此行可省略

1 // 结束状态个数。若约定为1,则此行可省略

5 // 结束状态的编号

2 -1 -1 // 状态1的所有出去的转换。按字符集中的字符顺序给出。-1表示出错状态

-1 3 -1

3 4 3

5 4 3

-1 -1 -1

实验报告:

同时上交纸质报告与电子版报告。纸质报告以实验分析、实验中遇到的问题及解决方法、实验测试(含屏幕截图)、实验心得等为主,不得大量引用源程序(引用源程序总行数不得超过100行)。电子版报告以源程序、测试用例、输出文件等为主,包括纸质报告的电子版,须确保提并的源程序能编译运行,否则不要上交。电子版请发送到248133074@qq.com,邮件标题请写明学号、姓名与实验编号,形如:<实验一> <学号> <姓名>。不得抄袭实验报告与源程序,否则后果自负!

提高内容:

(1)图形化的用户界面;

(2)任意DFA的状态转换图、状态转换表的图形绘制;

附实验报告源码

实验一DFA的编程实现

实验目的:

通过本次实验,加深对DFA及其识别的语言的理解,学习对一般的DFA的表达方法与编程实现方法。

实验任务:

编写一个C语言程序,模拟实现DFA识别字符串的过程。

实验内容:

(1)DFA的输入;(2)DFA的存储与读写;(3)DFA的正确性检查;(4)DFA的语言集列表显示;(5)DFA的规则字符串判定;

实验分析:

DFA的初始化

一个DFA的基本信息 状态集、字符集、开始状态、结束状态集、状态转换表;

在程序中状态集、字符集、开始状态、结束状态集都用string类型来表示,即可不用考虑用户输入内容的长度。但缺点是字符集只能是字符而不可以是字符串。

状态转换表:为三个字符的字符串,第一个为当前状态,第二个为输入字符,第三个为下一状态。 用vector容器存放转换函数的内容

 

字符串判断

初始化一个DFA,后可以通过一下算法判断一个字符串是否符合该DFA。

判定算法概要:

准备:开始状态s0, 接受状态集F, 状态转换表T(s, c), sÎS, cÎS

c = getchar();

s = 开始状态s0;

while ( c != EOF ) // 输入未结束则循环…

{

s = T(s, c);

if (s == NULL)

    error();

c = getchar();

}

if (s Î 接受状态集F)

    accept ();

else

error ();

在实际编写代码中的体现为

void identify() //判断字符串

   {

      cout<<"请输入字符串"<<endl;

      string str;

      cin>>str;

      int i=0;

      char present=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<<"该自动机识别此字符串"<<endl;

      else

         cout<<"该自动机不识别此字符串"<<endl;

   }

 

DFA的存储与读写

将DNF的信息写入文件中,

第一行:字符集;

第二行:状态集;

第三行:开始状态;

第四行:结束状态集;

以下行写入状态转换表

按照既定的规定读取文件

中的数据将其赋值,然后

初始化DFA即可;

DFA的语言集列表显示:

这一个模块应该是这个实验中比较难的一部分了。我并没有使用while循环的这个做法。而是用函数递归,通过所有字符集的路径去遍历整个DFA。最后将符合条件的字符串输出;

void Traversal(char present, int N,string strass="")//遍历DFA的语言集列表

   {

      if(present=='N'||N<0)//若路径已经大于N或者当前状态错误,停止递归

         return;

      N--;

      if(FinalStates.find(present)!=FinalStates.npos)

      {

         cout<<"该自动机识别字符串:"<<strass<<endl;

      }

      for(int i=0;i<Alphabet.length();i++)

      {

         string temp;

         temp=strass;

         strass+=Alphabet[i]; 

         Traversal(move(present,Alphabet[i]),N,strass);

         strass=temp;

      }

   }

递归终止条件的判断。

N-- 时, N小于0,或者遍历到无路可走是便终止

遇到的问题:

对于递归的终止条件写得不够明确。 递归前对字符串赋值strass赋值,递归后应该还原,这一点没有想到。调试了很久。 总结,对递归的具体编写 还是不熟悉。

目前的代码,字符集和状态只能是一个字符,若要优化可以用vector<string>容器存储即可;

实验用例:

实验结果:

DFA的初始化

判断字符串:

显示小于N的语言集:

读取DFA文件:

实验总结:

在这次实验中,学习对一般的DFA的表达方法与编程实现方法。对课本提供的算法有了更深刻的认识。在编写和调试代码的过程中对自身的编程能力也有了很大的提高。对自动机和其识别语言有了更透彻的理解。在动手编程之前一定要好好明确实验的理论准备和思路的理清,能帮助我们在实验过程中少走更多的弯路。总之在这次实验中收获很多,提高了动手能力和分析问题的能力。

源代码:

//构造一个DFA

#include<iostream>

#include<string>

#include<vector>

#include<fstream>

using namespace std;

class TransitionTable

{

public:

       char present;   //当前状态

       char next;              //下一状态

       char input;             //输入字符

       TransitionTable(char P,char I,char D)

       {

              present=P;

              next=D;

              input=I;

       }

};

class DFA

{

public:

       DFA()

       {

              cout<<"1、手动输入,2、读取txt文件"<<endl;

              int select;

              cin>>select;

              if(select==1)

                     inti();

              if(select==2)

                     read();

       }

       string States;   //状态集

       char StartStates;     //开始状态

       string FinalStates;   //结束状态集

       string Alphabet;      //字符集

       vector<TransitionTable> Trans; //转换函数

       void inti()       //初始化自动机

       {

              cout<<"请输入有限状态集S:"<<endl;

              cin>>States;

              cout<<"请输入字符集A:"<<endl;

              cin>>Alphabet;

              cout<<"请输入转换函数MOVE --格式为:当前状态-输入字符-下一状态:(输入#结束输入)"<<endl;

              int j=0;

             

              while(true)

              {

                     char input[4];

                     cin>>input;

                     if(strcmp(input,"#")==0)

                            break;

                     TransitionTable Temp(input[0],input[1],input[2]);

                     Trans.push_back(Temp);

              }

      

              cout<<"请输入开始状态集S0:"<<endl;

              cin>>StartStates;

              cout<<"请输入结束状态集F:"<<endl;

              cin>>FinalStates;

       }

       void identify() //识别字符串

       {

               

              cout<<"请输入字符串:"<<endl;

              string str;

              cin>>str;

              int i=0;

              char present=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<<"该自动机识别此字符串"<<endl;

              else

                     cout<<"该自动机不识别此字符串"<<endl;;

       }

       char move(char P,char I)       //move 转换函数

       {

              for(int i=0;i<Trans.size();i++)

              {

                     if(Trans[i].present==P&&Trans[i].input==I)

                            return Trans[i].next;

              }

              return 'N';

       }

       void read()     //从txt文件中读取DNF的信息

       {

              char temp[10];

              fstream ff("DNF.txt",ios::in);

              ff.getline(temp,10);

              Alphabet=temp;

              ff.getline(temp,10);

              States=temp;

              ff.getline(temp,10);

              StartStates=temp[0];

              ff.getline(temp,10);

              FinalStates=temp[0];

              while(!ff.eof())

              {

                     ff.getline(temp,10);

                     TransitionTable Temp(temp[0],temp[1],temp[2]);

                     Trans.push_back(Temp);

              }

       }

      

       /*将DNF的信息写入文件中,

       第一行:字符集;

       第二行:状态集;

       第三行:开始状态;

       第四行:结束状态集;

       以下行写入状态转换表*/

       void write()

       {

              fstream ff("DNF.txt",ios::out);     

              ff<<Alphabet<<endl;

              ff<<States<<endl;

              ff<<StartStates<<endl;

              ff<<FinalStates<<endl;

              for(int i=0;i<Trans.size();i++)

                     ff<<Trans[i].present<<Trans[i].input<<Trans[i].next<<endl;

              ff.close();

       }

      

       void Traversal(char present, int N,string strass="")      //遍历 DFA的语言集列表显示

       {

             

              if(present=='N'||N<0)

                     return;

              N--;

              if(FinalStates.find(present)!=FinalStates.npos)

              {

                     cout<<"该自动机识别字符串:"<<strass<<endl;

              }

              else if(FinalStates.find(present)==FinalStates.npos&&N<0)

                     return ;

              for(int i=0;i<Alphabet.length();i++)

              {

                     string temp;

                     temp=strass;

                     strass+=Alphabet[i];     

                     Traversal(move(present,Alphabet[i]),N,strass);

                     strass=temp;

              }

       }

};

int main()

  {

       DFA example;

       example.identify();

       int N;

       cout<<"请输入N"<<endl;

       cin>>N;

       example.Traversal(example.StartStates,N);

       example.write();

       system("pause");

       return 0;

}

/*测试用例

输入状态转换表

0a1

0b2

1b2

2a1

1a3

2b3

3a3

3b3

#

0a1

0b2

2a1

1b2

1a3

2b5

3a3

5b5

3b4

5a6

6b4

4a6

6a3

4b5

*/

更多相关推荐:
C++程序设计实验报告

C++程序设计实验报告学号:姓名:班级:指导老师:实验一、字符和格式的输出实验一,实验目的1、重点把握各种内部数据类型、数值和逻辑运算,各种表达式、函数声明、定义和调用。2、掌握过程控制编程方法,正确编制多重循…

程序设计实验报告模板

C语言程序设计实验报告1实验目的(1)掌握函数的定义方法、调用方法、参数说明以及返回值;(2)掌握实参与形参的对应关系,以及参数之间的值传递的方式;(3)掌握函数的嵌套调用及递归调用的设计方法;(4)在编程过程…

算法与编程实验报告

算法与编程实验报告班级10083412姓名储飞学号10081235指导老师朱芳第一题一题目一题目统计字母的使用频率二目的与要求1目的通过编写程序统计字母的使用频率培养学生综合利用C语言进行程序设计的能力熟悉字符...

C语言程序设计实验报告8

C语言程序设计实验报告八专业计算机科学与技术班级卓越工程师班日期20xx年12月16日实验组别第一组成绩第八次实验指针实验指导教师李开学生姓名邱金源学号U20xx14493实验名称指针实验一实验目的12345熟...

Windows编程实验报告

Windows编程实验报告1GDI图形程序设计姓名专业学号框架窗口程序和20xx3241Windows编程实验报告1Windows编程实验一GDI图形程序设计框架窗口程序和一实验目的1熟悉在VisualC60I...

算法与编程实验报告

算法与编程实验实验报告第一题一题目统计字母的使用频率二目的与要求1目的通过编写程序统计字母的使用频率培养学生综合利用C语言进行程序设计的能力熟悉字符串的操作方法加强函数的运用提高软件系统分析能力和程序文档建立归...

网络编程实验报告

网络编程实验报告指导老师姓名学号班级实验题目网络文件传输实验目的了解网络文件传输的方法了解FTP协议基础学习使用WinSock实现网络文件的传输了解点对点P2P网络文件传输的方法学习使用WinSock实现P2P...

C程序设计实验报告

C语言程序设计实验报告学号不告诉你哦班级信管一班姓名你猜猜哈哈一实验题目一编程实验猜数问题输入两个整数并求这两个整数的和输入所猜的结果如果输入数比正确的结果要大提示猜大了如果输入数比正确的结果要小提示猜小了当猜...

程序设计实验报告

兰州商学院陇桥学院工学系课程设计报告设计题目迷宫与栈问题系别工学系专业方向年级班学生姓名学生学号指导教师目录一系统开发的背景1二系统分析与设计1一系统的分析1二系统的具体分析设计2三系统的功能要求2一系统模块结...

程序设计实践 实验报告

程序设计基础课程设计通讯录管理系统院系计算机学院班级信息工程1班姓名方穗城学号20xx13064003合作者丁丹妮李晓艳指导教师刘艳军20xx年5月3日方穗城20xx信息工程1班通讯录管理系统目录摘要11研究背...

c++程序设计实验报告

实验要求对大纲中列出的四个实验要求1以面向对象的程序设计思想编程2熟悉面向对象程序设计语言VC编程环境3在计算机上快速完成程序编写调试运行分别写出实验报告三页以上要求详尽描述根据实验内容要求自己设计的上机编程源...

简单程序设计实验报告(模版)

深圳大学实验报告课程名称实验项目名称学院计算机与软件学院班级实验时间实验报告提交时间教务处制2342教师批改学生实验报告时间应在学生提交实验报告时间后10日内5

编程实验报告(38篇)