代码模仿DFA(-)
文件内容如下:
*/| 12345 1 5 -1 2 -1 3 -1 -1 4 -1 3 4 5 3
在读取文件时需要检查是否有重复符号输入:
期初代码如下:
#include<vector> vector<char>signal; ifstream in; in.open("shu.txt"); string line; getline(in,line); for(inr i=0;i<line.length();i++){ signal.push_back(line[i]); for(j=0;j<signal.size();j++){ if(signal.at(j)==line[i]) { cout<<"error()"<<endl; return 0; } } }
检查的那一部分不管是用at方法遍历,还是用iterator遍历,都是在编译时不报错,运行时报错。
vector iterators incompatible
abort()
解决方法:在读取完后,再进行遍历
思考原因:访问非法内存。
读取文件方式:
先以getline() 读入一行数据
注意getline实现
int getline_(char s[],int lim){ int c,i; i=0; while((c=getchar())!=EOF&&c!='\n'&&i<lim-1) s[i++]=c; s[i]='\0'; return i; }//这里虽然少了一个输入流的参数,但原理是一样的
在把数据缓冲传入指定的字符串时,其会在s的头部开始写数据,并在数据的末尾加'\0',也就是改变了字符串原来的长度,
即getline后,我们传入的字符串与输入的字符串一致。
当到达要输入状态表时,输入中有空格,如果先用getline读入一行,再以空格为分隔符分别把字符串转为整数,较为复杂
直接用 >> 读入整数。
至此,读入数据完毕。
2017-12-06
算法部分:
(1)要求输出长度小于等于N的可能读取的字符串
最初部分代码:
for (int j = 0; j < end_state.size(); j++) { /*if (node.size() == 1&&node.front()==end_state.at(j)) { cout << path.at(0); }*/ /*if(node.size()>=1) cout << node.at(node.size() - 1)<< endl;*/ else if ((node.at(node.size() - 1) == end_state.at(j))) //起初有错误 { //cout << path.at(path.size() - 1) << endl; for (int k = 0; k < path.size(); k++) cout << path.at(k); cout << endl; //从给出的测试样例中看,终止状态仍有出去的边,所以这里不能结束 //应继续探查当前状态周围的结点 } }
结果又报错上述的错误 abort() has been called()。
这次百度了一下,看了一下大致的原因的种类:
本次原因是当node为空时,node.size()-1访问非法内存
修改如下:
for (int j = 0; j < end_state.size(); j++) { if (node.size() == 1&&node.front()==end_state.at(j)) { cout << path.at(0); } /*if(node.size()>=1) cout << node.at(node.size() - 1)<< endl;*/ else if (node.size()>=1&&(node.at(node.size() - 1) == end_state.at(j))) //起初有错误 { //cout << path.at(path.size() - 1) << endl; for (int k = 0; k < path.size(); k++) cout << path.at(k); cout << endl; //从给出的测试样例中看,终止状态仍有出去的边,所以这里不能结束 //应继续探查当前状态周围的结点 } }
最终搜索代码(用深度优先搜索实现,这里要注意递归调用函数后,回退状态与符号)
void show_result(int n,int state_num) { //深度优先遍历 //if (state_num == start_state) node.push_back(state_num); //加入当前状态到状态结点 if (path.size() > n) //如果路径中的符号多于n,结束 return; else { for (int j = 0; j < end_state.size(); j++) { if (node.size() == 1&&node.front()==end_state.at(j)) { cout << path.at(0); } /*if(node.size()>=1) cout << node.at(node.size() - 1)<< endl;*/ else if (node.size()>=1&&(node.at(node.size() - 1) == end_state.at(j))) //起初有错误 { //cout << path.at(path.size() - 1) << endl; for (int k = 0; k < path.size(); k++) cout << path.at(k); cout << endl; //从给出的测试样例中看,终止状态仍有出去的边,所以这里不能结束 //应继续探查当前状态周围的结点 } } } for (int i = 0; i < signal.size(); i++) { if (table[state_num][i] != -1) { path.push_back(signal.at(i)); //加入两个状态之间的符号 show_result(n,table[state_num][i]); path.pop_back(); node.pop_back(); } } }
(2)检查串能否被识别
int check(vector<int>validate) { int state_num = start_state; for (int i = 0; i < validate.size(); i++) { if (table[state_num][validate.at(i)] == -1) { cout << "error()"; return 0; } else { //cout << "状态走向"<<" "<<state_num<<validate.at(i)<<" "<<table[state_num][i] << endl; state_num = table[state_num][validate.at(i)]; } } for (int i = 0; i < end_state.size(); i++) { if (i >= end_state.size()) { cout << "error()chang"; return 0; } if (state_num == end_state.at(i)) { cout << "accept()" << endl; return 1; } } }
写代码的时候如果数组变量很多,最好用纸列一下,不然容易忘记。
也可以在旁边写注释,提醒自己本部分的功能,再与所写代码比较,看是否代码有错误的地方。
读取数据部分代码:
ifstream in; in.open("shu.txt"); string line; getline(in, line); for (int i = 0; i < line.length(); i++) {//读入符号集 signal.push_back(line[i]); } for (int i = 0; i < signal.size(); i++) { //检查重复符号 for (int j = i + 1; j < signal.size(); j++) { if (signal.at(i) == signal.at(j)) { cout << "error() with repeated signal" << endl; system("pause"); return 0; } } } getline(in, line);//getline从存储字符串的0号位存入字符,并在存的末尾加'\0',读入状态集 for (int i = 0; i < line.length(); i++) { state.push_back(line[i] - '0'); } getline(in, line); if (line.length() > 1) { cout << "error() !开始状态不唯一" << endl; system("pause"); return 0; } start_state = line[0] - '0'; getline(in, line); for (int i = 0; i < line.length(); i++) { //读入结束状态集 end_state.push_back(line[i]-'0'); } for (int i = 0; i < end_state.size(); i++) { //结束状态是否在状态集中 for (int j = 0; j < state.size(); j++) { if (end_state.at(i) == state.at(j)) break; if (j == state.size()) { cout << "error(无此结束状态) " << endl; system("pause"); return 0; } } } int num=0; while (!in.eof()) {//读入状态转换表 for (int j = 0; j < signal.size(); j++) { in >> table[state.at(num)][j]; cout<< table[state.at(num)][j]<<" "; } cout << endl; num++; }
当前缺陷:由于文件中数据和读取文件的方式问题,不能读入两位数的状态,在(二)中改进。