如何在C ++中构建一个支持转换回已经访问过的状态的NFA?

时间:2016-02-21 22:45:48

标签: c++ nfa

我正在尝试使用以下格式的文本文件构建NFA

state   1   start
state   2
state   3   accept
transition  1   0   2
transition  1   1   3
transition  2   0   1
transition  2   0   3

其中州是: 州[州#] [开始或接受] [开始或接受] 转换是:转换[状态转换自] [符号] [状态转换为]

只要没有从一个状态转换回同一个状态,我就可以让程序工作。 (例如:将转换1 0 1添加到上面的文件中不起作用)。我已经坚持了几个小时,我想我必须尝试实现一种方法来跟踪配置,以使其工作,以确保相同的配置不会尝试多次,但我无法得到它。 我正在考虑为Configurations创建一个struct,并以某种方式将其实现到evaluateInput()函数中,但我仍然坚持如何去做。

这是我的代码:

#include <iostream>
#include <string>
#include <sstream>
#include <fstream>
#include <stdlib.h>
#include <vector>

using namespace std;

string num, currentState, tranState;
char symbol;

struct Transition;

struct State{
    bool startS = false;
    bool acceptS = false;
    string sym;
    vector<Transition> transitions;//transition between states
};

struct Transition{
    string symb;
    State to;
    State from;
    bool eval = false;
};

struct NFA{
    vector<State> NFAStates;
    State start;
};

void evaluateInput(string in, NFA F)
{
    vector<State> currStates;
    vector<State> numAccept;

    for(int n = 0; n < F.NFAStates.size(); n++)
    {
        if(F.NFAStates[n].startS)
        {
            currStates.push_back(F.NFAStates[n]);
        }
    }
    for(int i = 0; i < in.length(); i++)
    {
        vector<State> next;
        for(int j = 0; j < currStates.size(); j++)
        {
            int tranSize = currStates[j].transitions.size();
            for(int k = 0; k < tranSize; k++)
            {
                if((currStates[j].transitions[k].eval == false) && (in.at(i) == currStates[j].transitions[k].symb))
                {
                    currStates[j].transitions[k].eval = true;
                    for(int m = 0; m < F.NFAStates.size(); m++)
                    {
                        if(F.NFAStates[m].sym == currStates[j].transitions[k].to.sym)
                        {
                            next.push_back(F.NFAStates[m]);
                            if(F.NFAStates[m].acceptS)
                            {
                                numAccept.push_back(F.NFAStates[m]);
                            }
                        }
                    }
                }
            }
            currStates = next;
        }
    }

    if(numAccept.size() > 0)
    {
        cout << "Accept!" << endl;
    }
}

int main(int argc, char* argv[])
{
    char* fileName;
    string stringInput;
    if(argc > 1)
    {
        fileName = argv[1];
        stringInput = argv[2];
        //cout << stringInput << endl;
    }

    ifstream file(fileName);

    if(file.is_open())
    {
        NFA FA;
        string line;
        while(getline(file, line)){
            //cout << "1: " << line << endl;
            string ST;

            stringstream ss(line);
            getline(ss, ST, '\t');

            if(ST == "state")
            {
                State S;
                string SoA1;
                string SoA2;
                getline(ss, num, '\t');
                getline(ss, SoA1, '\t');
                getline(ss, SoA2);

                int num_i = stoi(num);
                S.sym = num_i;
                if((SoA1 == "start") || (SoA2 == "start"))
                {
                    S.startS = true;
                }

                if((SoA1 == "accept") || (SoA2 == "accept"))
                {
                    S.acceptS = true;
                }

                FA.NFAStates.push_back(S);
                if(S.startS == true){
                    FA.start = S;
                }
            }else if(ST == "transition")
            {
                Transition T;
                string symbol1;
                getline(ss, currentState, '\t');
                getline(ss, symbol, '\t');
                getline(ss, tranState);

                symbol = symbol1[0];
                int currentState_i = stoi(currentState);
                int tranState_i = stoi(tranState);
                T.symb = symbol;

                for(int j = 0; j < FA.NFAStates.size(); j++)
                {
                    if(FA.NFAStates[j].sym == tranState)
                    {
                        T.to = FA.NFAStates[j];
                    }
                }

                for(int i = 0; i < FA.NFAStates.size(); i++)
                {
                    if(FA.NFAStates[i].sym == currentState)
                    {
                        T.from = FA.NFAStates[i];
                        FA.NFAStates[i].transitions.push_back(T);
                    }
                }
            }
        }
        evaluateInput(stringInput, FA);
    }
}

感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

您的代码没有多大意义,因为当您尝试构建状态机表示时,有许多(不完整的)状态对象副本由copy-ctor创建。

每个State对象都包含Transition个对象的向量,而每个Transition对象又包含两个State个对象,from和{{1} },它将是您恰好正在解析转换行的点处创建的to个对象的副本(因此将包含已经解析的转换,但不包含那些尚未解析的转换)。

如果您更改State对象以使用TransitionState *直接引用所涉及的State &对象,而不是复制它们,那将更有意义

然后,当你尝试评估NFA时,你再次复制状态,这意味着你很容易在向量中多次获得相同的状态。使用State替代这些更有意义。同样,在std::set<State *>对象中,您宁愿使用NFA以便更容易按名称查找状态(并避免在向量上调用std::map<std::string, State>时使所有指针无效)