要求:给定该目录下的txt文件,读入后,按照每个单词的词典顺序和数量依次输出
example:
Do not take to heart every thing you hear.
Do not spend all that you have.
Do not sleep as long as you want;
那么你要输出:
all 1
as 2
do 3
every 1
have 1
hear 1
heart 1
long 1
not 3
sleep 1
spend 1
take 1
that 1
thing 1
to 1
want 1
you 3
参考:(12条消息) 词频统计(数组或链表实现)_K3V2的博客-CSDN博客
(12条消息) BUAA词频统计(数组或链表实现)_star-399的博客-CSDN博客
(12条消息) C语言快排函数qsort()_f_zyj的博客-CSDN博客_c语言快排函数
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<ctype.h>
#include<string.h>
#include<stdlib.h>//qsort
#include<search.h>//qsort
#define Word_MaxLength 100
#define WordArrLength 1000
struct Word //Word类保存两个信息,方便输出
{
char word[Word_MaxLength]; //用来储存单词
int count; //用来储存单词出现的次数
}finalArr[WordArrLength]; //Word类的数组
//cmp函数作为qsort函数的形参,负责对比相邻两节点的word大小
int cmp(const void* p1, const void* p2)
{
struct Word* a = (struct Word*)p1; struct Word* b = (struct Word*)p2;
return strcmp(a->word, b->word);
}
int main()
{
FILE* fp;
char Tempwords[Word_MaxLength]; //用来保存从文件中读到的单词
int i = 0, j = 0;
int existNum = 0;//existNum的存在代表已保存的单词数
int flag = 0; //用来判断是拷贝Tempword还是将已存在的单词数量加一
char Forlower; //将读到的字符转换成小写
//判断能否正常打开txt文件
if ((fp = fopen("article.txt", "rb")) == NULL)
{
printf("Fail to open!\n");
}
while (!feof(fp))
{
Forlower = tolower(fgetc(fp));
if (isalpha(Forlower)) //无论字母大小写,都调用tolower函数
{
Tempwords[i] = Forlower; //i可以记录当前单词的长度,当遇到空格也就是当前单词记录完成后
i++; //记得将i重置成0,方便下一个单词的长度记录
}
else//不是字母,则需要考虑Tempwords的查重和插入操作
{
Tempwords[i] = '\0';
for (j = 0; j <= existNum; j++)
{
if (strcmp(finalArr[j].word, Tempwords) == 0)//从已保存的existNum个单词中遍历查重
{
//查到Tempwords已经存在,就数量加一
finalArr[j].count++;
flag = 1; //flag=0允许拷贝临时单词
break;
}
}
//遍历后发现Tempwords是新单词,存入finalArr中
if (flag == 0)
{
finalArr[existNum].count=1; //将该单词的数量从0改为1
strcpy(finalArr[existNum].word, Tempwords); //拷贝存入
existNum++; //已存在的单词数加一
}
flag = 0, i = 0;
}
}
//已经通过遍历文件保存了所有单词,接下来给单词按词典顺序排序
//用到stdlib.h和search.h库中的函数qsort
qsort(finalArr, existNum, sizeof(finalArr[0]), cmp);
//排序完成,按要求输出
for (int t = 0; t < existNum; t++)
{
printf("%s %d\n", finalArr[t].word, finalArr[t].count);
}
return 0;
}
在代码完成过程中,遇到了以下问题:
1.如果直接判断
isalpha(tolower(fgetc(fp)))
会发现最后输出为乱码,不知道是什么原因,还是得预先把从文件中读到的字符通过tolower函数存在ForLower(char型字符)中,然后在判断是否为字母以及进行下一步判断。
2.如果不把flag和i在加入新单词之后重置,那么单词不会被区分开来,无法正确输出。
3.可以通过strcmp函数逐个对比已保存的单词,然后判断是否需要交换单次顺序(for+冒泡),但感觉还是很繁琐,于是学习到了头文件<stdlib.h>中的qsort函数(在查的时候还要求加上<search.h>头文件,但是我发现不加好像也问题不大)。这是C语言中的快排函数,不管是整型、浮点型还是结构体中的成员都可以快速访问并排序,相当方便!!