状态机
原来起点是1,终点是ERROR
有回车干扰,且消除 ‘\n'代码在希冀里不识别
fsacnf 读取回车时会替换为 ’\0'
fgets 读取回车时会‘\'n
#include <stdio.h>
#include <string.h>
#define FINAL 5
#define ERROR 6
//提示,可使用如下二维数组存储DFA。
//一个状态对应一行;一个输入符号(digit/other)对应一列。
//每看到输入字符串中一个符号,就以当且状态为行号,
//看到的符号为列号查询下个状态作为当前状态。
int integerDFA[][3] = {
// 符号,下个状态
{0, 0, 0},
{0, 2, ERROR}, // 状态1
{0, 3, FINAL}, // 状态2
{0, 4, FINAL}, // 状态3
{0, FINAL, FINAL}, // 状态4
{0, ERROR, ERROR}, // 状态5
{0, 0, 0} // 状态6
};
int statu; // 当前状态
int old_sta; // 上一个状态
FILE* fp;
FILE* fa2;
int lenth = 10000;
char* str = new char[1200]; // 循环读取文件,分200字节读取
char** cmd = new char*[lenth]; // 词元存储
int cnt = 0; // 分割词元个数
int isnum(char* p) {
if (*p >= '0' && *p <= '9') {
return 1;
}
return 0;
}
// 分割成单词
void splitv2(char *str) {
char* p = str;
int num = 0;
// 分割词语
// 按空格分割字符
while (*p != '\0') {
// printf("%c\n", *p);
if (*p == ' ' || *p == '\n') {
if (num != 0) {
cnt++;
num = 0;
}
} else {
cmd[cnt][num] = *p;
num++;
}
p++;
}
// 如果临时存储区字符不为0,说明还有分割字符,此时
// 恰好是最后一行时,或者到一行末尾了
if (*p == '\0') {
if (num != 0) {
cnt++;
num = 0;
}
}
}
//void check(char* str) {
int check(char* str) {
int checknum;
checknum = 2;
char*p = str;
// 进入字符探测,允许跳转状态
statu = 1;
old_sta = statu;
// 字符 '\0'也是比较对象,对应于状态机的非字符直接到结束状态。只有一个非字符就是结束符才能输出正确
do {
if (isnum(p) == 0) {
checknum = 2;
} else {
checknum = 1;
}
old_sta = statu;
statu = integerDFA[statu][checknum];
p++;
} while (*p != '\0');
// 此时 *p=='\0', 所以必然是2
// if (isnum(p) == 0) {
// checknum = 2;
// } else {
// checknum = 1;
// }
// old_sta = statu;
// statu = integerDFA[statu][checknum];
printf("%d\n", statu);
if (statu >= 2 && statu <= 4) { // 对结果检测,不需要 '\0' 继续探测
printf("true\n");
return 1;
} else if (statu == FINAL) { // 读取四个字符后,不读取'\0' 就进入FINAL状态
printf("true\n");
return 1;
} else if (statu == ERROR) {
printf("false\n");
return 0;
} else if (statu == 0) { // 连续出错字符
printf("false\n");
return 0;
}
return 0;
}
void init_cmd() {
for (int i = 0; i < lenth; i++) {
cmd[i] = new char[200];
}
// 分词存储先清空杂乱数据
for (int i = 0; i < lenth; i++) {
for (int j = 0; j < 200; j++) {
cmd[i][j] = '\0';
}
}
}
int main() {
fp = fopen("input.txt", "r");
fa2 = fopen("output.txt", "w");
init_cmd();
// 分割词语
// while (fgets(str, 200, fp) != NULL) {
// 利用scanf 读取吸收回车,而希冀里不能执行 '\n'的比较
while (fscanf(fp,"%s",str)!=EOF) {
// 处理回车,有些回车读取会影响代码结果
if (str[0] == '\n' && strlen(str) == 1) {
// printf("发现回车\n");
continue;
} else if (str[strlen(str) - 1 ] == '\n') {
// 发现文末回车
// printf("发现文末回车\n");
str[strlen(str) - 1 ] = '\0';
}
// 剥离成函数使用
splitv2(str);
}
// 对每个单词进行检查
// 这样解决不知道什么时候根据状态进行结束的问题。字符连续,没有字符了就根据状态给结论。
for (int i = 0; i < cnt; i++) {
printf("%s-----\n", cmd[i]);
// fprintf(fa2,"--%s--\n",cmd[i]);
if (check(cmd[i]) == 1) {
fprintf(fa2, "true");
} else {
fprintf(fa2, "false\n");
// fprintf(fa2,"%d\n",statu);
}
}
fclose(fa2);
fclose(fp);
return 0;
}