压缩文法使用的前提:在文法中无U::=U的情况,在本例中未进行该项的判别,需要人工识别该类规则
在写压缩代码前本来想借鉴网上的代码,但是代码运行实在是太差了,还是自己写吧。由于写的那几天在准备PAT考试,所以就使用了以前未使用的vector来进行代码的书写,使用了push_back以及erase方法,但在使用erase方法时出现了一些纰漏导致检查了好几天的程序,以为是算法逻辑错了。
代码如下:
#include<bits/stdc++.h>
using namespace std;
//保存左右部的字符串和标记
struct STR{
string s;
int flag[100];
};
//判断终结符和非终结符
int Norterminal(char c)
{
if(c>='A'&&c<='Z')
return 1;
else if(c!=':'&&c!='='&&c!='<'&&c!='>'&&c!=' ')
return 0;
else
return -1;
}
int main()
{
int num;
cin>>num;//输入文法规则的个数
std::vector<string> strN;//保存文法规则
string gram;//文法规则
string start;//开始符
STR strL[100];//左部规则的个数
STR strR[100];//右部规则的个数
string left;
//保存输入规则
for(int i=0;i<num;i++)
{
cin>>gram;
strN.push_back(gram);
}
//得到所有的输入规则的左部和右部
for(unsigned i=0;i<strN.size();i++)
{
strL[i].s=strN[i][0];
strL[i].flag[i]=0;
//cout<<strN[i].length()<<endl;
int len=strN[i].length();
//得到右部
strR[i].s=strN[i].substr(4,len-1);
for(int i=0;i<len;i++)
{
strR[i].flag[i]=0;
}
}
/*判断条件1*/
//起始符加标记
strL[0].flag[0]=1;
for(int i=0;i<strN.size();i++)
{
for(int j=0;j<strR[i].s.length();j++)
{
if(strL[i].flag[0]==1)
{
if(Norterminal(strR[i].s[j]))
{
strR[i].flag[j]=1;
//cout<<strR[i].s[j]<<endl;
for(int k=0;k<strN.size();k++)
{
if(strL[k].s[0]==strR[i].s[j])
{
strL[k].flag[0]=1;
cout<<strL[k].s<<endl;
}
}
}
}
}
}
//删除不满足条件一的结果
cout<<"循环条件一后的结果:"<<endl;
for(int i=0;i<strN.size();i++)
{
if(strL[i].flag[0]==1)
{
cout<<strN[i]<<endl;
}
else
{
strN.erase(strN.begin()+i);
}
}
//条件二的初始化
for(unsigned i=0;i<strN.size();i++)
{
strL[i].flag[0]=0;
for(int j=0;j<strN[i].size();j++)
{
strR[i].flag[j]=0;
}
}
strL[0].flag[0]=1;
for(int i=0;i<strN.size();i++)
{
if(Norterminal(strR[i].s[0])==0&&strR[i].s.length()==1)
{
strL[i].flag[0]=1;
}
}
//判断条件二
for(int i=0;i<strN.size();i++)
{
if(strL[i].flag[0]==1)
{
for(int j=0;j<strN.size();j++)
{
for(int k=0;k<strN[j].length();k++)
{
if(strL[i].s[0]==strR[j].s[k])
{
strR[j].flag[k]=1;
strL[j].flag[0]=1;
}
}
}
}
}
cout<<"循环条件二后的结果:"<<endl;
//删除不满足条件二的结果
for(int i=0;i<strN.size();i++)
{
if(strL[i].flag[0]==1)
{
cout<<strN[i]<<endl;
}
}
}