描述:
文学研究人员需要统计某篇英文小说中某些形容词的出现次数和位置。试写一个实现这一目标的文字统计系统,称为"文学研究助手"。
基本要求:
英文小说存于文本文件中。待统计的词汇集合要一次输入完毕,即统计工作必需在程序的一次运行后就全部完成。程序的输出结果是每个词出现次数和出现位置所在行的行号,格式自行设计。
KMP算法模块:
void kmp_next(const string pattern, int patternLen, int *next) {
int i = 0, j = -1;
next[i] = j; // default next[0] = -1
while (i < patternLen) {
while (j >= 0 && pattern[i] != pattern[j]) { //比较常见的next数组构建;
j = next[j];
}
i++;
j++;
next[i] = j;
}
//for(int index = 0; index < patternLen; ++index) printf("next指针:%d \n", n ext[index]);//可以测试一下next数组是否正确;
return;
}
int kmp_search(const string text, int textLen, const string pattern, int patternLen,int pos) {
int i = pos-1, j = 0;
// 建立一个next数组,并且声明,不然可以会程序不报错,但就是没输出;
int next[patternLen + 1];
memset(next, 0x00, sizeof(next));
// int idx = 0;
// memset(matchIndex, 0x00, sizeof(matchIndex));
kmp_next(pattern, patternLen, next);
while (i < textLen) {
while (j >= 0 && text[i] != pattern[j]) { //这和课本上的差不多KMP算法;
j = next[j];
}
i++;
j++;
// a match is found
// if (j == patternLen) {
// printf("found substring at index:" + (i - patternLen));
// j = next[j];
// }
if (j == patternLen) {
printf("found substring at index:%d\n", (i - patternLen));
//j = next[j];
//matchIndex[idx++] = i - patternLen;
return (i - patternLen);
}
}
return -1;
}
全部代码展示:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef char string[1000]; //为了能够改变大小写问题,相当于c++里的string;
int length(string a){
int i=0;
while(a[i]){ //构造一个计算string长度的函数 (相当与string.size());
i++;
}
return i;
}
void kmp_next(const string pattern, int patternLen, int *next) {
int i = 0, j = -1;
next[i] = j; // default next[0] = -1
while (i < patternLen) {
while (j >= 0 && pattern[i] != pattern[j]) { //比较常见的next数组构建;
j = next[j];
}
i++;
j++;
next[i] = j;
}
//for(int index = 0; index < patternLen; ++index) printf("next指针:%d \n", next[index]);//可以测试一下next数组是否正确;
return;
}
int kmp_search(const string text, int textLen, const string pattern, int patternLen,int pos) {
int i = pos-1, j = 0;
// 建立一个next数组,并且声明,不然可以会程序不报错,但就是没输出;
int next[patternLen + 1];
memset(next, 0x00, sizeof(next));
// int idx = 0;
// memset(matchIndex, 0x00, sizeof(matchIndex));
kmp_next(pattern, patternLen, next);
while (i < textLen) {
while (j >= 0 && text[i] != pattern[j]) { //这和课本上的差不多KMP算法;
j = next[j];
}
i++;
j++;
// a match is found
// if (j == patternLen) {
// printf("found substring at index:" + (i - patternLen));
// j = next[j];
// }
if (j == patternLen) {
printf("found substring at index:%d\n", (i - patternLen));
//j = next[j];
//matchIndex[idx++] = i - patternLen;
return (i - patternLen);
}
}
return -1;
}
void find(char name[],string keys){
string text;
int text_length;
int line=1; //行
int findkmp; // 记录这一行的第几个;
int count=0; //计数 (一共有多少个单词)
FILE *fp;
fp=fopen(name,"r");
if(fp==NULL){
printf("文件打开失败");
exit(0);//return 一样的;
}
int key_length=length(keys);
while(!feof(fp)){
fgets(text,1000,fp);
text_length=length(text);
for(int i=0;i<text_length;i++){
if(text[i]>='A'&&text[i]<='Z'){ //转化单词的大小写,把大写转化,以免遗漏;
text[i]='a'+text[i]-'A';
}
}
findkmp=kmp_search(text,text_length,keys,key_length,1); //开始的位置是第一个;
if(findkmp==-1){
continue;
}else{
count++;
printf("row=%d,col=%d",line,findkmp);
}
while(findkmp!=-1){
findkmp=kmp_search(text,text_length,keys,key_length,findkmp+2); //找到后,每次从findkmp+1开始;因为上面函数会有findkmp=findkmp-1;
if(findkmp!=-1){
count++;
printf("row=%d,col=%d",line,findkmp);//这些可以自己去美化;
}
}
line++;
}
fclose(fp);
if(count){
printf("%s一共有%d",keys,count);
}else{
printf("没有找到该单词");
}
return;
}
void jiemian(){
printf("1.查询单词\n"); //界面设计就不太麻烦,想美观可以自己去找;
printf("0.退出\n");
}
int main(){
/*int ret=0;
string pattern;
string text;
scanf("%s",text);
scanf("%s",pattern);
int n=length(pattern);
int n1=length(text);
for(int i=0;i<n1;i++){
if(text[i]>='A'&&text[i]<='Z'){
text[i]='a'+text[i]-'A';
}
}
//kmp_next(pattern,n,next);
ret=kmp_search(text,n1,pattern,n,4);
printf("%d",ret);*/
printf("输入文件名\n");
char name[20];
gets(name);
while(1){
jiemian();
int shuru;
scanf("%d",&shuru);
if(shuru==1){
printf("请输入要查询的单词\n");
string keys;
scanf("%s",keys);
find(name,keys); //注意这个输入的文件名,最好查询的文件在同一个文件夹里,直接输入名字加后缀如:
//英语短篇小说.txt;
printf("\n");
}
if(shuru==0){
break;
}
}
return 0;
}
运行案例: