一目标的文字统计系统,称为“文学研究助手”。
设计要求:
1. 英文小说存于一个文本文件中。
2. 待统计的词汇集合要一次输入完毕。
3. 程序的输出结果是每个词的出现次数和出现位置所在行的行号,格式
自行设计。
源代码
#include<iostream>
#include<cstdlib>
#include<fstream>
using namespace std;
char *FileRead(char ch[]) //读文件函数
{
char *c = (char *)calloc(2000, sizeof(char)); //calloc分配出来的内存,返回值也是void * 但是分配的内存是被清空过的,更安全
int i = 0;
ifstream in(ch);
if (!in) { cout << "不能打开文件" << ch << endl; return 0; }
in >> noskipws; //读文件不跳过空格
while (!in.eof()) //eof 判断是否读到文件尾
{
in >> c[i++];
}
in.close();
return c;
}
void GetNext(char t[], int next[])
{// 求模式串T的next函数值并存入数组next
int j = 0, k = -1;
int n = strlen(t);
next[j] = -1;
while (j<n)
{
if (k == -1 || t[j] == t[k])
{
j++; k++; next[j] = k;
}
else k = next[k];
}
}
int IndexKMP(char s[], char t[], int next[])
{// 利用模式串T的next函数求T在主串S中第pos个字符之后的位置的KMP算法。
// 其中,T非空,1≤pos≤StrLength(S)
int i, j;
i =0; j = 0;
int count = 0; //计数器
int m = strlen(s), n = strlen(t);
while (i<m && j<n) //
{
if (j == -1 || s[i] == t[j])
{
i++; j++;
} // 继续比较后继字符
else j = next[j];// 模式串向右移动
if (j >= n)
{
count++;
cout << "单词第"<<count<<"次出现在" << (i - j + 1) / 84 + 1 << "行,第" << (i - j + 1) << "个字符开始" << endl;
j = 0; //J必须重新赋值为零,
}// 匹配成功
}
return count;
}
void ShowMenu()
{
cout << "********************************************" << endl;
cout << "****** 文 学 研 究 助 手 ******" << endl;
cout << "****** 0.安全退出系统 ******" << endl;
cout << "****** 1.文件读入小说 ******" << endl;
cout << "****** 2.输出小说文本 ******" << endl;
cout << "****** 3.查询小说关键字 ******" << endl;
cout << "\n\t\n\t\t请选择:";
}
int main()
{
char index[10] = { 0 }, novel_path[10] = { 0 }; //赋初值为零,分配内存时初始化为零,
char *ch;
int *next, index_length, n, x = 100;
cout << "\t\t\t登陆文学研究助手...\n\n\n"<< endl;
while (x != 0)
{
system("pause");
system("cls"); //清屏
ShowMenu();
cin >> x;
switch (x)
{
case 0:
exit(0);
break;
case 1:
cout << "请输入小说文件路径:";
cin >> novel_path;
ch = FileRead(novel_path);
cout << "文件读入成功!" << endl;
break;
case 2:
cout << ch << endl;
break;
case 3:
{
cout << ch << endl;
cout << "请输入要查询的单词:";
getchar();
cin.get(index, 20);
index_length = strlen(index);
next = new int[index_length];
GetNext(index, next);
n = IndexKMP(ch, index, next);
cout << index << "在小说中总共出现" << n << "次" << endl;
}
break;
default:
break;
}
}
system("pause");
return 0;
}