文本文件单词统计(C语言)
本人目前还是一位在校大学生,写文章的目的是为了记录一下当前所学,与其他爱好者或从业者相互学习交流。文本文件单词统计这个题目是学校的一次课程设计中的一道,在编写时也是参考了很多资料,借鉴了一些别人的想法,如有冒犯我会及时删除。同样,我的编写成果肯定会存在一些不足之处,也请读者多多包涵。 这个题目的具体信息如下: 1、问题描述 编写一个文本文件单词统计的程序,包括建立文件、单词统计、单词查询、单词定位的功能。
2、基本要求 程序应先询问用户的 ID号(ID 号包括两个大写字母和4 位数字),例如:请输入用户 ID 号:AB1234 ,程序应对输入的 ID 号验证,符合 ID 号要求的格式(检验ID并不是主要要求,大家可自行忽略),然后程序提示四种选择: (1) 建立文件 (2) 单词统计 (3) 单词查询及定位 (4) 退出 注意: i) 文件至少包含50个英文单词(一定出现重复的单词,且一定包含数字) ii) 文档不规范,单词之间可能不只有一个空格,并且有加引号的一些单词“jiaozi” 加引号的单词算单词,但数字不算单词 iii) 逐行扫描文本文件,计算文档中单词总数,及各个单词出现的频次,并且按照单词首字母abcd…… 的顺序排列,显示并生成soft.txt文件 iv) 查询任意给出的单词是否存在,如果不存在,在屏幕上输出“查无此词!”;如果存在,显示单词出现的总次数,并且详细列出其出现的位置。 例如: 请您输入待查询的词:of 单词 of 共出现了2次; 第1次出现在第1行,第5个位置; 第2次出现在第3行,第1个位置。 请您输入待查询的词:
3、问题分析 解决如下问题: 1.检测用户ID格式是否正确,要求(1)用户ID位数为6;(2)前两位为大写英文字母,后四位是数字; 2.可创建文本文件并可输入内容; 3.对文本文件中的单词数进行统计,要求:(1)输出时将单词按照字典顺序排序;(2)数字不算入总数;(3)引号内的单词也算入总数; 4.实现单词定位,要求(1)输出单词出现的详细位置;(2)输出该单词出现的次数
1.4、功能实现 i.检验用户ID:用户从键盘中输入一个字符串。程序将接受的字符串赋值到一个字符数组,遍历数组中的元素判断格式是否正确。
ii.建立文本文件:(1)定义一个串变量;(2)定义文本文件;(3)输入文件名,打开该文件;(4)循环读入文本行,写入文本文件,其过程如下: While(不是文件输入结束){ 读入一文本行至串变量; 串变量写入文件; 输入是否结束输入标志;} (5)关闭文件。
iii.朴素匹配算法:该算法是整个单词检索程序的核心。对于主串的每一个字符作为子串的开头,与要匹配的字符串进行匹配,对主串做最大的循环,每个字符开头都做子串长度的小循环,直到匹配成功或者全部遍历完成为止。更具体地说:设有三个指针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,表示匹配失败。(可能讲述地不清楚,读者可再查询其他资料进行学习)
iv. 单词统计: 单词总个数统计:在下文提到的单词出现频率统计的过程结束之后,将每个单词出现的次数相加就是单词的总个数。
单词之间有多个空格。在进行判断时,若空格之后仍然是空格,则多个空格作为一个空格进行处理。
单词出现频率统计:逐行扫描文本,将不同的单词放在一个字符数组中。在扫描过程中,每遇到一个与已保存在数组中的某一个单词相同的单词的时候,该单词的计数加1。
按字典顺序排序:将数组中的每个元素(即单词)采用冒泡法排序,最后输出详细的单词出现频率。
v.单词查询:遍历保存单词的字符数组,将要查询的单词与数组元素挨个比对。若不存在,则显示“查无此词”。
vi.单词定位:确定要检索的文本文件,确定要检索的单词,逐行扫描文本,将所要查询的单词与文本比对,若相同则立即输出行数和相应位置。
源代码如下:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<time.h>
typedef struct{
char str[50];
int cnt;
}Str;
int vcount(char* p){
FILE *fp;
char temp[50];
char tmp[50];
Str words[200];
int num=0,count=0;
int i,j,neww=1;
int m,n;
if((fp=fopen(p,"r"))==NULL){
printf("找不到文件\n");
return -1;
}
loop: while(fscanf(fp,"%s",tmp)!=EOF){
neww=1;
for(i=0;i<50;i++){
if(tmp[i]>='0'&&tmp[i]<='9'){
goto loop;
}
}
for(i=0;i<50;i++){
if(tmp[i]=='$'||tmp[i]==','||tmp[i]=='.')
tmp[i]='\0';
}
for(i=0; i<num; i++){
if (strcmp(tmp, words[i].str)==0 ){
neww=0;
words[i].cnt++;
}
}
if (neww){
for (j=0; tmp[j]!='\0'; j++) {
words[num].str[j] = tmp[j];
}
words[num].str[j] = '\0';
words[num++].cnt = 1;
}
}
for(m=0;m<num-1;m++){
for(n=0;n<num-1;n++){
if(strcmp(words[n].str,words[n+1].str)<0)
{
strcpy(temp,words[n].str);
strcpy(words[n].str,words[n+1].str);
strcpy(words[n+1].str,temp);
}
}
}
for(m=0;m<num;m++){
count += words[m].cnt;
}
printf("一共%d个不同的单词,每个单词出现次数如下:\n",num);
for (i=num-1; i>=0; i--) {
printf("%-10s %2d\n", words[i].str, words[i].cnt);
}
printf("单词个数为(包含重复出现)%d\n",count);
fclose(fp);
}
int Index(char* p){
int j=0,i=0;
char S[1000],T[50];
char ch1,ch2;
FILE *fp;
if((fp=fopen(p,"r"))==NULL){
printf("找不到文件\n");
return -1;
}
ch1=fgetc(fp);
while(ch1!='$'){
S[i]=ch1;
i++;
ch1=fgetc(fp);
}
S[i]='$';
printf("请输入你要搜索的单词:\n");
scanf("%s",T);
ch2=T[0];
while(ch2!='\0'){
j++;
ch2=T[j];
}
int row=1,col=1;
int m=0,n=0,q=1;
int num=0;
int left=0;
while(m<i){
if(S[m]=='"'){
m=m+1;
left=1;
}
if(S[m]==T[n]){
m++;
n++;
}
else{
m=m-n+1;
n=0;
};
if(n==j&&S[m+1]!=' '){
num++;
if(row==1){
col=m-n+1;
printf("第%d次出现的位置位于第%d行第%d列\n",num,row,col);
}
else{
col=m-n-q;
printf("第%d次出现的位置位于第%d行第%d列\n",num,row,col);
}
}
if(S[m]==' '||(S[m]=='"' &&left==1)){
col++;
left=0;
while(S[m]==' '||S[m]=='"')
m=m+1;
}
if(S[m]=='\n'){
row++;
q=m;
};
if(S[m]=='$'){
printf("所选单词出现的次数是%d\n",num);
return num;
}
}
}
void createfile(char* p){
FILE *fp;
char ch;
fp=fopen(p,"w+");
ch=getchar();
printf("请输入单词:(请以$符号结束)\n");
while(ch!='$')
{
ch=getchar();
fputc(ch,fp);
}
fclose(fp);
}
int checkID(char s[],int x) {
int i = 0,y = x;
char t[6];
if(strlen(s)!=6){
printf("您输入的格式不正确(位数不是6位),请重新输入!\n");
return 1;
}
for(i=0;i<y;i++){
t[i] = s[i];
}
for(i=0;i<y;i++){
if(i<2){
if(t[i]>='A'&&t[i]<='Z') ;
else {
printf("您输入的格式不正确(前两位不是大写英文字母),请重新输入!\n");
return 1;
break;
}
}
if(i>=2){
if(t[i]>='0'&&t[i]<='9') ;
else {
printf("您输入的格式不正确(后四位中包含非数字字符),请重新输入!\n",i+1);
return 1;
break;
}
}
}
}
int main(){
int j = 1,l = 0;
int count=-1,c=-1;
char filename[255],afilename[255];
char *p;
char ID[6];
char quit;
while(j==1){
printf("请输入您的ID!(前两位为大写字母,后四位为整数)\n");
scanf("%s",ID);
j = checkID(ID,sizeof(ID));
if(j==0){
printf("输入正确!");
}
}
while(true){
printf("请选择您想要进行的操作(请输入操作前对应的数字)\n 1.建立文件\n 2.单词查询及定位\n 3.单词统计\n 4.退出\n");
scanf("%d",&l);
fflush(stdin);
if(l!=1&&l!=2&&l!=3&&l!=4){
printf("您的输入有误,请重新输入!");
}
if(l==1){
printf("请输入所要创建的文件名(包括扩展名)");
scanf("%[^\n]",filename);
p=filename;
createfile(p);
printf("文件创建成功!");
}
if(l==2){
while(count==-1){
printf("请输入文件名(包括扩展名)");
scanf("%[^\n]",afilename);
fflush(stdin);
p=afilename;
count=Index(p);
if(count==0){
printf("查无此词!");
}
if(count==-1){
printf("文件名有误,请重新进入查询!\n");
break;
}
}
}
if(l==3){
while(c==-1){
printf("请输入文件名(包括扩展名)");
scanf("%[^\n]",afilename);
fflush(stdin);
p=afilename;
c=vcount(p);
if(c==-1){
printf("文件名有误,请重新进入查询!\n");
break;
}
}
}
if(l==4){
printf("您已退出该程序!");
break;
}
}
}
部分运行结果截图:
|