[`原文网址](https://blog.csdn.net/qq_24451605/article/details/50075467)
课程设计选这个题,然后找到了上述文章。拿去vs一跑发现不少错误。主要是指针越界的错误。 故稍作修改,起码能跑。还添加了一些注释,方便像我一样的混子看懂 删除了化简和dfs函数,因为没啥用。。。。 下面是输入:  说实话,这个输入不是很方便,明明可以一次输入R->Sa|a,非要自找麻烦输入两次。 不说了,上代码! ``
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <vector>
#include <queue>
#include <cctype>
#include <map>
#include <set>
#define MAX 500
using namespace std;
class WF
{
public:
string left;
set<string> right;
WF(const string& temp)
{
left = temp;
right.clear();
}
void print()
{
printf("%s->", left.c_str());
set<string>::iterator it = right.begin();
printf("%s", it->c_str());
it++;
for (; it != right.end(); it++)
printf("|%s", it->c_str());
puts("");
}
void insert(const string& temp)
{
right.insert(temp);
}
};
map<string, int> VN_dic;
vector<WF> VN_set;
string start;
bool used[MAX];
void remove1()
{
for (int i = 0; i < VN_set.size(); i++)
for (int j = 0; j < i; j++)
{
vector<string> cont;
set<string>& right1 = VN_set[i].right;
set<string>& right2 = VN_set[j].right;
char ch = VN_set[j].left[0];
set<string>::iterator it1 = right1.begin();
set<string>::iterator it2;
for (; it1 != right1.end(); it1++)
if (it1->at(0) == ch)
for (it2 = right2.begin(); it2 != right2.end(); it2++)
cont.push_back(*it2 + it1->substr(1));
int nn = right1.size();
while (nn--)
{
if (right1.begin()->at(0) == ch)
right1.erase(right1.begin());
else
{
cont.push_back(*right1.begin());
right1.erase(right1.begin());
}
}
for (int i = 0; i < cont.size(); i++)
right1.insert(cont[i]);
}
}
void remove2()
{
for (int i = 0; i < VN_set.size(); i++)
{
char ch = VN_set[i].left[0];
set<string>& temp = VN_set[i].right;
set<string>::iterator it = temp.begin();
string tt = VN_set[i].left.substr(0, 1) + "\'";
bool flag = true;
for (; it != temp.end(); it++)
if (it->at(0) == ch)
{
VN_set.push_back(WF(tt));
VN_dic[tt] = VN_set.size();
flag = false;
break;
}
set<string>& tempp = VN_set[i].right;
int x = VN_dic[tt] - 1;
if (flag) continue;
vector<string> cont;
set<string>& ss = VN_set[x].right;
ss.insert("~");
while (!tempp.empty())
{
if (tempp.begin()->at(0)==ch)
ss.insert(tempp.begin()->substr(1) + tt);
else
{
cont.push_back(tempp.begin()->substr(0) + tt);
}
tempp.erase(tempp.begin());
}
puts("");
for (int i = 0; i < cont.size(); i++)
{
tempp.insert(cont[i]);
}
}
}
void print()
{
cout << "**********消除左递归后的结果********" << endl;
for (int i = 0; i < VN_set.size(); i++)
VN_set[i].print();
puts("");
}
int main()
{
char buf[MAX];
int n;
VN_dic.clear();
VN_set.clear();
start = "S";
cout << "请输入文法G[S]的产生式数量:";
cin >> n;
while (n--)
{
cin >> buf;
int len = strlen(buf), i;
for (i = 0; i < len; i++)
if (buf[i] == '-')
{
buf[i] = 0;
break;
}
string temp = buf;
if (!VN_dic[temp])
{
VN_set.push_back(WF(temp));
VN_dic[temp] = VN_set.size();
}
int x = VN_dic[temp] - 1;
int j = 3; string tempp;
while (buf[j] != '\0') {
string buf(1, buf[j]);
tempp = tempp + buf;
j++;
}
temp = tempp;
VN_set[x].insert(temp);
}
cout << endl << "完整的G文法:" << endl;
for (int i = 0; i < VN_set.size(); i++)
VN_set[i].print();
remove1();
remove2();
print();
return 0;
}
|