1. DFA状态转换图
该C++程序是基于以下特定DFA编写的简单词法分析器,如需更改其他DFA,下文讲解释需要改动的地方。
2. 问题描述
输入格式:
输入一个字符串。
输出格式:
若字符串正确,输出单词串。如果有错误,输出错误的类型。
输入样例1:
bacbacdabbaccb
输出样例1:
bacb
acdab
baccb
字符串共被划分为3个词
输入样例2:
abaxab
输出样例2:
ab
a
字符串中第4个字符x是一个非法字符
输入样例3:
abaaba
输出样例3:
ab
a
字符串中第4个字符a发生了错误
输入样例4:
aba
输出样例4:
ab
a
最后一个词不完整
3.问题分析
我们都知道“程序” = “数据结构”+“算法”,所以第一个要解决的问题便是DFA和字符串的存储问题。其中最值得思考的是DFA的存储问题。 字符串看似好处理,但是也隐藏很大的问题。比如,应该用c++的string数据类型,还是应该使用char数组来存储呢?在字符串输入的时候,如何防止空格和回车进入缓冲区呢? 鉴于我们接下来要对每个字符进行分析,所以我采用char数组的方式存储字符串。 而DFA我是用状态转移矩阵来存储,只需要一个二维数组便可以解决。 下图是草稿思路过程(草稿嘛,乱一点很正常)和流程图。
4. 流程图
5.代码
#include <bits/stdc++.h>
using namespace std;
const int DFA[4][4] = {
{1, 0, -1, -1},
{-1, 3, 1, 2},
{1, -1, -1, -1},
{-1, -1, -1, -1},
};
const int START_STATE = 0;
const int END_STATE = 3;
const char ALPHABET[4] = {'a', 'b', 'c', 'd'};
const char ERROR_TYPE[3][100] = {"\n字符串中第%d个字符%c是一个非法字符", "\n字符串中第%d个字符%c发生了错误", "\n最后一个词不完整"};
int main() {
char str[101];
cin >> str;
int lineNum = 0;
int wordCnt = 0;
int strCnt = strlen(str);
int index = 0;
int errorType = -1;
int currentState = 0;
while (strCnt--) {
if (str[index] == 'a') {
int state = DFA[lineNum][0];
if (state != -1) {
lineNum = state;
currentState = lineNum;
cout << str[index];
} else {
errorType = 1;
break;
}
}else if(str[index] == 'b'){
int state = DFA[lineNum][1];
if (state != -1) {
lineNum = state;
currentState = lineNum;
cout << str[index];
} else {
errorType = 1;
break;
}
}else if(str[index] == 'c'){
int state = DFA[lineNum][2];
if (state != -1) {
lineNum = state;
currentState = lineNum;
cout << str[index];
} else {
errorType = 1;
break;
}
}else if(str[index] == 'd'){
int state = DFA[lineNum][3];
if (state != -1) {
lineNum = state;
currentState = lineNum;
cout << str[index];
} else {
errorType = 1;
break;
}
}else{
errorType = 0;
break;
}
if(currentState == 3){
lineNum = 0;
wordCnt++;
putchar(10);
}
index++;
}
strCnt++;
if(strCnt == 0 && currentState != 3){
errorType = 2;
}
switch (errorType) {
case 0:
printf(ERROR_TYPE[errorType],(index+1),str[index]);
break;
case 1:
printf(ERROR_TYPE[errorType],(index+1),str[index]);
break;
case 2:
printf(ERROR_TYPE[errorType]);
break;
default:
printf("字符串共被划分为%d个词",wordCnt);
break;
}
return 0;
}
Mot de l’auteur(作者的话):
因为一些历史遗留问题(就是懒),前期分析问题的时候预先设定的一些变量,没有使用到,后面写完也懒得删了哈哈哈~
关于更换DFA:你只需要修改状态转移函数(const int DFA[4][4])便可以,我已经提升作用域到全局变量了,在程序的开头就能看见。
Au revoir à tous!
|