文学研究助手课程设计报告
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
文学研究助手课程设计报告书1 问题描述
文学研究人员需要统计某篇英文小说中某些形容词的出现次数和位置。实现这一目标的文字统计系统,称为“文学研究助手”。其中,英文小说存于一个文本文件中。待统计的词汇集合要一次输入完毕,即统计工作必须在程序的一次运行之后就全部完成。程序的输出结果是每个词的出现次数和出现位置所在行的行号,格式自行设计。
2 注意事项
1 文本串为非空,以文件的形式存放,统计匹配的词集非空,文件名和词集均由用户输入。
2 单词是字母构成的序列,并且区分大小写,且中间不应有空格。
3 为了操作的简便,单词在原文本中不出现换行的情况。
4 计算机终端输出的格式是:单词,次数,行号,同一行出现两次,只输出第一次的。
3 设计
3.1 存储结构设计
1 char articles[MAXSIZE] (定义一个全局数组,用于从文件中读取字符依次放入此字符串中。以便进行此后的操作)。
2 struct HString
{
char* words;
int length;
int* next;
int count;
int j;
};(定义此结构体类型,其中words指针用来指代存储输入检测单词的空间的头指针,length用来表示该检测单词的长度,count用来存储每个单词的出现次数,j用来表示从该单词的零位置开始检测,为下面的KMP算法提供方便)。
3 void wenjianfuzhi(char articles[])
{
FILE *p,*q;
char ch;
int i=0;
p=fopen("dage.txt","w");
if(p==NULL)
{
exit(-1);
}
while(scanf("%c",&ch)!=EOF)
putc(ch,p);
fclose(p);
q=fopen("dage.txt","r");
if(q==NULL)
{
exit(-1);
}
while((ch=getc(q))!=EOF)
{
articles[i]=ch;
i++;
}
fclose(q);
system("pause");
}(本函数之中,首先以写的方式打开一个叫做“dage.txt”的文本文件,让后依次向其中输入数据,让后再以读的方式,将文件中的内容给全局数组,本段程序中是将原来的文章,存入事先开辟的一个文件“dage.txt”中来).
3.2 算法设计(流程图)
本次实验,为了使程序的效率更高,使用了串模式匹配的KMP算法,该算法的核心思想是:每当一趟匹配过程中出现字符比较不等时,不需要回测指针,而是利用已经得到的“部分匹配”的结果将模式向右滑动尽可能远的一段距离后,继续进行比较。
算法流程图如下:
3.3 测试用例设计
3.3.1 测试当所查单词在文章中不存在时
输入文章:yi ge ren de shi hou .bu shi bu xiang ni .yi ge ren de shi hou .zhi shi pa xiang ni
输入检测单词:wo
3.3.2 测试一个单词并且该单词在文章中时
输入文章:yi ge ren de shi hou .bu shi bu xiang ni .yi ge ren de shi hou .zhi shi pa xiang ni
输入检测单词:shi
3.3.3 测试多个单词
输入文章:yi ge ren de shi hou .bu shi bu xiang ni .yi ge ren de shi hou .zhi shi pa xiang ni
输入检测单词:yi ren shi
3.3.4 循环检测多次
输入文章:yi ge ren de shi hou .bu shi bu xiang ni .yi ge ren de shi hou .zhi shi pa xiang ni
输入检测
单词:ren
输入继续研究:1
输入文章:wo ai ni.wo de jia .wo de jia .wo de tian tang
输入检测单词:wo de
4 调试报告
本次试验中,很多地方都经过调试而达到了优化的效果,本来此次试验是以数组来模拟一个文件,来存储最初的文章,后来考虑到实验的真实性,可操作性以及灵活性,我将数组改成了对文件的操作,虽然会复杂很多,但是对自己的编
程能力的提高有很大的好处,在编写文件的时候,起初运行的时候老是屏幕一闪而过,没有结果,后来经过断点调试,发现,原来在判断文件是否打开成功的if 语句出现问题,正确的语句应该是:i f(p==NULL){exit(-1);},可是原来判定条件写成了!P,这导致了老是会执行exit(-1),这条语句,最终导致出错。
第二,在进行格式控制的过程中,发现‘*‘号的长度老是会超过屏幕的长度,为了取得一个视觉的效果,经过多次尝试,不断改变‘*’的个数,最终将界面设计的符合审美要求,还有在进行多次研究的时候,忽视了我们定义的数组是全局数组,它的作用范围是程序运行的整个区间,所以在进行第二次研究的时候,我们向文件中输入文章,然后传给全局数组,发现输出的全局数组的内容,与我们期望的不相符合,但是有时当我们文件的内容很多时,又能够正常输出,为了解释这一令人困惑的问题,我设置断点进行排查,最终发现原来是存储结构的定义出现了问题,当文件的内容很小的时候,输入的内容不足以覆盖原来数组中的所有的内容,所以会出现失败,当文章的内容很大的时候,输入的覆盖了数组中的所有的内容,于是让我们从外界看起来好像是对的,但是错误还是真实存在的,为了避免这样的事,我在主函数开始的时候,就首先让全局数组全赋值为NULL,经过本次的修改,发现达到了程序的预期效果。
其次,在整个程序修改完之后,运行程序的时候,发现虽然编译的时候没有报错,但是程序运行还是屏幕一闪而过,找了很多原因后,还是没有解决,后来上网查询,终于发现Visual studio和Visual C++ 不太一样,让Visual studio有运行结果可看,可以再程序的结尾加上system(“pause“),这样在程序运行时会出现这样一句话:”请按任意键继续“,最终修改后发现可以看见程序运行的结果了。
还有,为了更加人性化的需求,和更加贴近事实的效果,和为了研究人员使用的方便性,我在程序的最后使用了GOTO语句,进行了跳转,并且为了使用户界面更加清晰,用了system(“cls“),将原有的屏幕上的内容都清理完,从而方便了用户进行第二次操作,而不用没研究一次都要打开程序一次,节约了时间。虽然理论上来讲GOTO不应该使用,因为他会使程序的可读性变差,但是,适当的时侯,使用一重GOTO语句,可以使程序的效率提高,并且会使程序变得一目了然,所以必要的时候,我想GOTO语句还是可以使用的。