文本文件单词的检索与计数.docx
- 文档编号:4363827
- 上传时间:2022-11-30
- 格式:DOCX
- 页数:15
- 大小:117.40KB
文本文件单词的检索与计数.docx
《文本文件单词的检索与计数.docx》由会员分享,可在线阅读,更多相关《文本文件单词的检索与计数.docx(15页珍藏版)》请在冰豆网上搜索。
文本文件单词的检索与计数
程序设计课程设计
报告
学院:
软件学院
专业班级:
软件班
学号:
姓名:
指导教师:
时间:
2012年6月29日
文本文件单词的检索与计数
专业:
软件工程班级:
1.1【问题描述】
串是非数值处理中的主要对象,如在信息检索、文本编辑、符号处理等许多领域,得到越来越广泛的应用。
在高级语言中也引入了串数据类型概念,并且串变量与其他变量(如整型、实型等)一样,可以进行各种运算。
然而,在各种不同类型的应用中,所处理的串有不同的特点,要想有效地实现串的处理,就必须熟悉串的存储结构及其基本运算。
本课程设计的目的就是熟悉串类型的实现方法和文本模式匹配方法,熟悉如何利用模式匹配算法实现一般的文本处理技术。
本课程设计分两步:
首先,设计出串定位算法(即模式匹配算法)及其实现;然后,再利用串定位算法设计文本文件的检索及单词的计数等操作。
1.2【设计需求及分析】
1.2.1串模式匹配算法的设计要求
在串的基本操作中,在主串中查找模式串的模式匹配算法——即求子串位置的函数Index(S,T),是文本处理中最常用、最重要的操作之一。
所谓子串的定位就是求子串在主串中首次出现的位置,又称为模式匹配或串匹配。
模式匹配的算法很多,在这里只要求用最简单的朴素模式匹配算法。
该算法的基本思路是将给定子串与主串从第一个字符开始比较,找到首次与子串完全匹配的子串为止,并记住该位置。
但为了实现统计子串出现的个数,不仅需要从主串的第一个字符位置开始比较,而且需要从主串的任一给定位置检索匹配字符串,所以,首先要给出两个算法:
1.标准的朴素模式匹配算法
2.给定位置的匹配算法
1.2.2文本文件单词的检索与计数的设计要求
要求编程建立一个文本文件,每个单词不包含空格且不跨行,单词由字符序列构成且区分大小写;统计给定单词在文本文件中出现的总次数;检索输出某个单词出现在文本中的行号、在该行中出现的次数以及位置。
该设计要求可分为三个部分实现:
其一,建立文本文件,文件名由用户用键盘输入;其二,给定单词的计数,输入一个不含空格的单词,统计输出该单词在文本中的出现次数;其三,检索给定单词,输入一个单词,检索并输出该单词所在的行号、该行中出现的次数以及在该行中的相应位置。
1.建立文本文件
2.给定单词的计数
3.检索单词出现在文本文件中的行号、次数及其位置
4.主控菜单程序的结构
3【设计功能的实现】(用C或C++语言描述)
详细设计
朴素模式匹配算法
该算法的基本思想是:
设有三个指针——i,j,k,用i指示主串S每次开始比较的位置;指针j,k分别指示主串S和模式串T中当前正在等待比较的字符位置;一开始从主串S的第一个字符(i=0;j=1)和模式T的第一个字符(k=0)比较,若相等,则继续逐个比较后续字符(j++,k++)。
否则从主串的下一个字符(i++)起再重新和模式串(j=0)的字符开始比较。
依此类推,直到模式T中的所有字符都比较完,而且一直相等,则称匹配成功,并返回位置i;否则返回-1,表示匹配失败。
顺序串的模式匹配算法如下:
intindex(SStringS,SStringT)
{//求子串T在主串S中首次出现的位置
inti,j,k,m,n;
m=T.length;//模式串长度赋m
n=S.length;//目标串长度赋n
for(i=0;i<=n-m;i++)
{
j=0;k=i;//目标串起始位置i送入k
while(j<=m&&s.ch[k]==t.ch[j])
{k++;j++;}//继续下一个字符的比较
if(j==m)//若相等,则说明找到匹配的子串,返回匹配位置i,
//否则从下一个位置重新开始比较
returni;
}//endfor
return-1;
}//endIndex
给定位置的串匹配算法
该算法要求从串S1(为顺序存储结构)中第k个字符起,求出首次与字符串S2相同的子串的起始位置。
该算法与上面介绍的模式匹配算法类似,只不过上述算法的要求是从主串的第一个字符开始,该算法是上述算法的另一种思路:
从第k个元素开始扫描S1,当其元素值与S2的第一个元素的值相同时,判定它们之后的元素值是否依次相同,直到S2结束为止。
若都相同,则返回当前位置值;否则继续上述过程,直至S1扫描完为止,其实现算法如下:
IntPartPosition(SStringS1,SStringS2,intk)
{
inti,j;
i=k-1;//扫描s1的下标,因为c中数组下标是从0开始,串中序号相差1
j=0;//扫描s2的开始下标
while(i if(s1.ch[i]==s2.ch[j]) {i++;j++;//继续使下标移向下一个字符位置} else {i=i-j+1;j=0; //使i下标回溯到原位置的下一个位置,使j指向s2的第一个字符,再重新比较} if(j>=s2.length) returni-s2.length;//表示s1中存在s2,返回其起始位置 else return-1;//表示s1中不存在s2,返回-1 }//函数结束 说明: 以上两个算法可统一为一个算法,即在子串定位算法Index(S,T)的参数中增加一个起始位置参数即可。 建立文本文件 建立文件的实现思路是: (1)定义一个串变量; (2)定义文本文件; (3)输入文件名,打开该文件; (4)循环读入文本行,写入文本文件,其过程如下: While( 不是文件输入结束){ 读入一文本行至串变量; 串变量写入文件; 输入是否结束输入标志; } (5)关闭文件。 给定单词的计数 该功能需要用到前一节中设计的模式匹配算法,逐行扫描文本文件。 匹配一个,计数器加1,直到整个文件扫描结束;然后输出单词出现的次数。 其实现过程如下: (1)输入要检索的文本文件名,打开相应的文件; (2)输入要检索统计的单词; (3)循环读文本文件,读入一行,将其送入定义好的串中,并求该串的实际长度,调用串匹配函数进行计数。 具体描述如下: While(不是文件结束){ 读入一行并到串中; 求出串长度; 模式匹配函数计数; } (4)关闭文件,输出统计结果。 检索单词出现在文本文件中的行号、次数及其位置 这个设计要求与上一个类似,但要相对复杂一些。 其实现过程描述如下: (1)输入要检索的文本文件名,打开相应的文件; (2)输入要检索统计的单词; (3)行计数器置初值0; (4)while(不是文件结束){ 读入一行到指定串中; 求出串长度; 行单词计数器置0; 调用模式匹配函数匹配单词定位、该行匹配单词计数; 行号计数器加1; If(行单词计数器! =0) 输出行号、该行有匹配单词的个数以及相应的位置; } 运行主控程序 主控菜单程序的结构要求内容如下: (1)头文件包含; (2)菜单选项包括: 1.建立文件 2.单词计数 3.单词定位 4.退出程序 (3)选择1——4执行相应的操作,其他字符为非法。 程序代码: #include #include #include #defineLIST_INIT_SIZE500/*线性表存储空间的初始分配量*/ #defineLISTINCREMENT10/*线性表存储空间的分配增量*/ #defineFILE_NAME_LEN20/*文件名长度*/ #defineWORD_LEN20/*单词长度*/ #defineMaxStrSize256 #definellength110/*规定一行有110个字节*/ typedefstruct{ charch[MaxStr];/*ch是一个可容纳256个字符的字符数组*/ intlength; }string;/*定义顺序串类型*/ typedefstruct{ charword[WORD];/*存储单词,不超过20个字符*/ intcount;/*单词出现的次数*/ }elem_type; typedefstruct{ elem_type*elem;/*存储空间基址*/ intlength;/*当前长度*/ intlistsize;/*当前分配的存储容量*/ }sqlist; voidsqlist_init(sqlist*sq,elem_type*et){ sq->elem=et; sq->length=0; } voidsqlist_add(sqlist*sq,elem_type*et,char*word) { inti; intj; for(i=0;i { /*当前单词与加入的单词相同,直接统计,不做插入*/ if(strcmp(et[i].word,word)==0) { et[i].count++; return; } if(strcmp(et[i].word,word)>0) { break; } } if(sq->length==LIST_INIT_SIZE) { printf("空间不足,单词[%s]插入失败\n",word); return; } for(j=sq->length;j>i;j--) { memcpy(et+j,et+j-1,sizeof(elem_type)); } sq->length++; strcpy(et[i].word,word); et[i].count=1; } intsqlist_count(sqlist*sq,elem_type*et) { inti; intj=0; for(i=0;i j=j+et[i].count; returnj; } voidcreat_text_file() { elem_typew; sqlists; charfile_name[FILE_NAME_LEN+1],yn; FILE*fp; printf("输入要建立的文件名: "); scanf("%s",file_name); fp=fopen(file_name,"w"); yn='n';/*输入结束标志初值*/ while(yn=='n'||yn=='N') { printf("请输入一行文本: "); gets(w.word); gets(w.word); s.length=strlen(w.word); fwrite(&w,s.length,1,fp); fprintf(fp,"%c",10);/*是输入换行*/ printf("结束输入吗? yorn: ");yn=getchar(); } fclose(fp);/*关闭文件*/ printf("建立文件结束! \n"); } voidsubstrsum() { charfile_name[FILE_NAME_LEN+1]; charword[WORD_LEN+1]; FILE*fp; inti; intj,q=0; intw,x,y=0; elem_typeet[LIST_INIT_SIZE]; sqlistsq; sqlist_init(&sq,et); printf("请输入文件名: "); scanf("%s",file_name); fp=fopen(file_name,"r"); if(fp==NULL){ printf("打开文件失败! \n"); return; } while(fscanf(fp,"%s",word)! =EOF){ sqlist_add(&sq,et,word); } fclose(fp); printf(">>>>>>>>>>>>>>>>单词<<<>>>>个数<<<<<<<<<<<\n"); for(i=0;i { x=strlen(et[i].word); for(w=x-1;w>=0;w--) if(et[i].word[w]<65||(et[i].word[w]>90&&et[i].word[w]<97)||et[i].word[w]>122) { et[i].word[w]=''; } for(w=0;w if(et[i].word[w]=='') y++; if(y==x) { et[i].count=0; y=0; } elsey=0; if(et[i].count! =0) printf("%20s%10d\n",et[i].word,et[i].count); elseq++; } j=sqlist_count(&sq,et); printf("\n>>>>>>>>>>>>>>>>>>%s的单词总数为%d个\n",file_name,j); printf("\n>>>>>>>>>>>>>>>>>>%s的非单词个数为%d种\n",file_name,q); printf("\n"); } intpartposition(strings1,strings2,intk) {inti,j; i=k-1; /*扫描s1的下标,因为c中数组下标是从0开始,串中序号相差1*/ j=0;/*扫描s2的开始下标*/ while(i {if(s1.ch[i]==s2.ch[j]) {i++;j++;/*继续使下标移向下一个字符位置*/ } else { i=i-j+1;j=0; }} if(j>=s2.length) returni-s2.length; else return-1;/*表示s1中不存在s2,返回-1*/ /*表示s1中存在s2,返回其起始位置*/ }/*函数结束*/ voidsubstrcount() { FILE*fp; strings,t;/*定义两个串变量*/ charfname[10]; inti=0,j,k; printf("输入文本文件名: "); scanf("%s",fname); fp=fopen(fname,"r"); printf("输入要统计计数的单词: "); scanf("%s",t.ch); t.length=strlen(t.ch); while(! feof(fp)){ memset(s.ch,'\0',110); fgets(s.ch,110,fp); s.length=strlen(s.ch); k=0;/*初始化开始检索位置*/ while(k { j=partposition(s,t,k);/*调用串匹配函数*/ if(j<0)break; else{ i++;/*单词计数器加1*/ k=j+t.length;/*继续下一字串的检索*/ } } } printf("\n单词%s在文本文件%s中共出现%d次\n",t.ch,fname,i); }/*统计单词出现的个数*/ voidsubstrint() { FILE*fp; strings,t;/*定义两个串变量*/ charfname[10]; inti,j,k,l,m; intwz[20];/*存放一行中字串匹配的多个位置*/ printf("输入文本文件名: "); scanf("%s",fname); fp=fopen(fname,"r"); printf("输入要检索的单词: "); scanf("%s",t.ch); t.length=strlen(t.ch); l=0;/*行计数器置0*/ while(! feof(fp)) {/*扫描整个文本文件*/ memset(s.ch,'\0',110); fgets(s.ch,110,fp); s.length=strlen(s.ch); l++;/*行计数器自增1*/ k=0;/*初始化开始检索位置*/ i=0;/*初始化单词计数器*/ while(k { j=partposition(s,t,k);/*调用串匹配函数*/ if(j<0)break; else { i++;/*单词计数器加1*/ wz[i]=j;/*记录匹配单词位置*/ k=j+t.length;/*继续下一字串检索*/ } } if(i>0) { printf("行号: %d,次数: %d,位置分别为: ",l,i); for(m=1;m<=i;m++) printf("第%4d个字符",wz[m]+1); } printf("\n"); } printf("\n本软件自定义110个字节为一行\n\n"); }/*检索单词出现在文本文件中的行号、次数及其位置*/ voidsubstrio() { voidsubstrcount(),substrint(); chart; while (1) { printf("===============================================\n"); printf("||文本文件单词字串的定位统计及定位||\n"); printf("||================================||\n"); printf("||a.单词出现次数||\n"); printf("||||\n"); printf("||||\n"); printf("||b.单词出现位置||\n"); printf("||||\n"); printf("====================================\n"); printf("请输入: \n"); scanf("%c",&t); switch(t){ case'a': substrcount();break; case'b': substrint();break; default: return; } } } intmain() { voidcreat_text_file(),substrsum(),substrio(); intxz; intt=1; while(t){ system("graftabl936");/*在Win-TC中可以显示汉字*/ printf("*************************************\n"); printf("**文本文件的检索、字串的统计及定位**\n"); printf("*************************************\n"); printf("**1.建立文本文档**\n"); printf("**2.文本单词汇总**\n"); printf("**3.单词定位**\n"); printf("**4.退出**\n"); printf("请选择: "); scanf("%d",&xz); switch(xz){ case1: creat_text_file();break; case2: substrsum();break; case3: substrio();break; case4: return0; default: printf("选择错误,重新选\n"); } } }
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 文本文件 单词 检索 计数