简单的利用c++实现 文本文件单词的检索和计数(KMP算法)
主要功能:检索输出某个单词某个单词出现在文本中的行号、在改行中出现的次数以及位置。
核心代码设计:
//设计初始类
class Word
{
public:
Word(){text[0]='\0';}
int Getlength()const;
void PlaceVocabulary();
char text[MaxStrSize];
};
Getlength()为求取text的字符串长度
PlanceVocaBulary()为可使用用户在程序过程中输入字符
1.求取失效函数算法设计
求失效函数的作用是用于KMP算法过程中需要的变量。
它的算法过程如下代码所示:
void GetFailure(const Word &pat,int f[])
{
int j=0,k=-1;
f[0]=-1;
while(j<pat.Getlength()-1)
if(k==-1||pat.text[k]==pat.text[j])
f[++j]=++k;
else
k=f[k];
}
2.KMP算法设计
int KMP_find(Word ob,Word pat,int p=0)//p是用于下次匹配的开始检索位置
{
int *f=new int[pat.Getlength()];
GetFailure(pat,f);
int i=p,j=0;
while(i<ob.Getlength()&&j<pat.Getlength()&&pat.Getlength()-j<=ob.Getlength()-i)
{
if(j==-1||pat.text[j]==ob.text[i])
{
i++;
j++;
}
else
j=f[j];
}
delete []f;
if(j<pat.Getlength())
return -1;
else
return i-j;
}
3.统计单词出现次数功能设计
void WordCount()
{
Word ob,pat;
char filename[10];
ifstream infile;
int i=0,j,k;
cout<<"Place input flie name:";
cin>>filename;
cout<<"Place input vocabulary:";
cin>>pat.text;
infile.open(filename);
while(infile)
{
infile.getline(ob.text,MaxStrSize);
k=0;
while(k<ob.Getlength()-1)
{
j=KMP_find(ob,pat,k);
if(j<0) break;
else
{
i++;
k=j+ob.Getlength();
}
}
}
infile.close();
cout<<pat.text<<endl;
cout<<"在文本文件:"<<filename<<" "<<"总共出现"<<i<<"次"<<endl;
}
4.检索单词功能设计
void WordRetrieval()
{
Word ob,pat;
char filename[20];
int i,j,k,l=0,m;
int wz[20];
ifstream infile;
cout<<"Place text file name:";
cin>>filename;
cout<<"Place you need retrieval:";
cin>>pat.text;
infile.open(filename);
while(infile)
{
infile.getline(ob.text,MaxStrSize);
l++;k=0;i=0;
while(k<ob.Getlength()-1)
{
j=KMP_find(ob,pat,k);
if(j<0) break;
else
{
i++;
wz[i]=j;
k=j+ob.Getlength();
}
}
if(i>0)
{
cout<<"所在行:"<<l<<" 出现次数:"<<i;
cout<<"在该行出现的位置分别是:";
for(m=1;m<=i;m++) cout<<wz[m]+1;
cout<<endl;
}
}
infile.close();
}
关于界面设计的一些函数在这暂且不提,完整代码在文章末尾
2.实现界面:
附录 完整代码(文件下载在末尾)
#include<fstream>
#include<iostream>
#include<stdio.h>
#define MaxStrSize 100
using namespace std;
class Word
{
public:
Word(){text[0]='\0';}
int Getlength()const;
void PlaceVocabulary();
char text[MaxStrSize];
};
void GetFailure(const Word &pat,int f[])
{
int j=0,k=-1;
f[0]=-1;
while(j<pat.Getlength()-1)
if(k==-1||pat.text[k]==pat.text[j])
f[++j]=++k;
else
k=f[k];
}
int KMP_find(Word ob,Word pat,int p=0)//p是用于下次匹配的开始检索位置
{
int *f=new int[pat.Getlength()];
GetFailure(pat,f);
int i=p,j=0;
while(i<ob.Getlength()&&j<pat.Getlength()&&pat.Getlength()-j<=ob.Getlength()-i)
{
if(j==-1||pat.text[j]==ob.text[i])
{
i++;
j++;
}
else
j=f[j];
}
delete []f;
if(j<pat.Getlength())
return -1;
else
return i-j;
}
void WordCount()
{
Word ob,pat;
char filename[10];
ifstream infile;
int i=0,j,k;
cout<<"Place input flie name:";
cin>>filename;
cout<<"Place input vocabulary:";
cin>>pat.text;
infile.open(filename);
while(infile)
{
infile.getline(ob.text,MaxStrSize);
k=0;
while(k<ob.Getlength()-1)
{
j=KMP_find(ob,pat,k);
if(j<0) break;
else
{
i++;
k=j+ob.Getlength();
}
}
}
infile.close();
cout<<pat.text<<endl;
cout<<"在文本文件:"<<filename<<" "<<"总共出现"<<i<<"次"<<endl;
}
void WordRetrieval()
{
Word ob,pat;
char filename[20];
int i,j,k,l=0,m;
int wz[20];
ifstream infile;
cout<<"Place text file name:";
cin>>filename;
cout<<"Place you need retrieval:";
cin>>pat.text;
infile.open(filename);
while(infile)
{
infile.getline(ob.text,MaxStrSize);
l++;k=0;i=0;
while(k<ob.Getlength()-1)
{
j=KMP_find(ob,pat,k);
if(j<0) break;
else
{
i++;
wz[i]=j;
k=j+ob.Getlength();
}
}
if(i>0)
{
cout<<"所在行:"<<l<<" 出现次数:"<<i;
cout<<"在该行出现的位置分别是:";
for(m=1;m<=i;m++) cout<<wz[m]+1;
cout<<endl;
}
}
infile.close();
}
void Word::PlaceVocabulary()
{
cout<<"Place input text:"<<endl;
cin>>text;
}
int Word::Getlength() const
{
int i;
i=0;
while(text[i]!='\0')
{
i++;
}
return i;
}
void Menu()
{
cout<<"======================================="<<endl;
cout<<"文本文件单词的检索和计数系统"<<endl;
cout<<"======================================="<<endl;
cout<<"1.建立文本文件"<<endl;
cout<<"2.统计单词出现次数"<<endl;
cout<<"3.检索单词"<<endl;
cout<<"4.退出"<<endl;
cout<<"请输入你的选择<1,2,3,4>:";
}
void CreateText()
{
Word Text,end;
char TextName[100];
end.text[0]='/';
end.text[1]='e';
end.text[2]='n';
end.text[3]='d';
end.text[4]='\0';
cout<<"请输入文件名:";
cin>>TextName;
ofstream outfile(TextName,ios::out);
if(!outfile)
{
cerr<<"open error!"<<endl;
}
cout<<"请输入文本内容:(写完后用/end结束输入)"<<endl;
while(KMP_find(Text,end)==-1)
{
cin>>Text.text;
if(KMP_find(Text,end)==-1)
for(int i=0;i<Text.Getlength();i++) outfile<<Text.text[i];
outfile<<'\n';
}
outfile.close();
cout<<"Text create success"<<endl;
}
int main()
{
int i,j=1;
do{
Menu();
cin>>i;
switch(i)
{
case 1: CreateText();break;
case 2: WordCount();break;
case 3: WordRetrieval();break;
case 4: j=0;break;
default: cout<<"Place error"<<endl;
}
}while(j);
return 0;
}