我正在尝试使用以下格式的文本文件构建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);
}
}
感谢您的帮助。
答案 0 :(得分:0)
您的代码没有多大意义,因为当您尝试构建状态机表示时,有许多(不完整的)状态对象副本由copy-ctor创建。
每个State
对象都包含Transition
个对象的向量,而每个Transition
对象又包含两个State
个对象,from
和{{1} },它将是您恰好正在解析转换行的点处创建的to
个对象的副本(因此将包含已经解析的转换,但不包含那些尚未解析的转换)。
如果您更改State
对象以使用Transition
或State *
直接引用所涉及的State &
对象,而不是复制它们,那将更有意义
然后,当你尝试评估NFA时,你再次复制状态,这意味着你很容易在向量中多次获得相同的状态。使用State
替代这些更有意义。同样,在std::set<State *>
对象中,您宁愿使用NFA
以便更容易按名称查找状态(并避免在向量上调用std::map<std::string, State>
时使所有指针无效)