代码模仿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()。

这次百度了一下,看了一下大致的原因的种类:

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++;
    }

 

当前缺陷:由于文件中数据和读取文件的方式问题,不能读入两位数的状态,在(二)中改进。

posted @ 2017-12-06 13:24  qynx  阅读(413)  评论(0编辑  收藏  举报