本篇适用于ZZU的编译原理课程实验二——自动机实验:NFA转DFA并最小化,包含了实验代码和实验报告的内容,读者可根据需要参考完成自己的程序设计。
如果是ZZU的学弟学妹看到这篇,那么恭喜你,你来对地方啦!
如果需要相关文档资料的话,我也已经上传,免费下载:「编译原理实验二代码+实验报告(ZZU)」
不要忘了点赞👍和收藏💌支持一下哦!
源代码
先给出实验的源代码
#include <iostream>
#include <fstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
#include <sstream>
using namespace std;
// NFA类定义
struct NFA {
set<int> states; // 状态集合
set<int> alphabet; // 字母表
map<pair<int,int>, set<int>> transitions; // 转移函数 F(fromState, symbol)={toStates}
int start_state{
}; // 初始状态
set<int> accept_states; // 接受状态集合
};
// DFA类定义
struct DFA {
set<int> states; // 状态集合
set<int> alphabet; // 字母表
map<pair<int,int>, int> transitions; // 转移函数
int start_state{
}; // 初始状态
set<int> accept_states; // 接受状态集合
};
// 从文件读取NFA
NFA readNFAFromFile(const string& filename) {
NFA nfa;
ifstream file(filename);
string line;
// 读取状态集合
getline(file, line);
istringstream iss(line); // 将一行数据转换成一个输入流,随后可以像处理文件或标准输入一样从`iss`中提取数据
int state;
while (iss >> state) {
// 从转换好后的每一行输入中,逐个读取整数作为状态`state`
nfa.states.insert(state);
}
// 读取字母表
getline(file, line);
iss.clear(); // 重置流状态
iss.str(line); // 读取新的一行作为流
int symbol; // 输入的标志字母
while (iss >> symbol) {
nfa.alphabet.insert(symbol);
}
// 读取转移规则数量
int trans_count;
file >> trans_count;
// 读取转移规则
for (int i = 0; i < trans_count; i++) {
int from_state, now_symbol; // 当前状态,转换字母
file >> from_state >> now_symbol; // 从文件中读取
set<int> to_states_set; // 目标状态集合
int to_state; // 目标状态
// 读取目标状态,添加到到目标状态集合
while (file.get() != '\n' && file >> to_state) {
to_states_set.insert(to_state);
}
nfa.transitions[{
from_state, now_symbol}] = to_states_set; // 转移函数 F(fromState, symbol)={toState}
}
// 读取初始状态和接受状态
file >> nfa.start_state;
int accept_state;
file >> accept_state;
nfa.accept_states.insert(accept_state);
return nfa;
}
// 获取ε-闭包集合
set<int> getEpsilonClosure(const NFA& nfa, const set<int>& states) {
set<int> closure = states;
// 队列进行存储状态集合states
queue<int> q;
for (int state : states) {
q.push(state);
}
while (!q.empty()) {
// 从前往后弹出状态
int current = q.fr