华南农业大学SCAU 1109综合性实验

在当前目录中存在文件名为"case1.in"(其中case后为数字1,不是字母l,写错提交后会判错)的文本文件,
其内容为一篇英文文章(以EOF作为结束标志)。现要求读取该文本文件内容,统计文章中每个单词出现的次数,
并输出出现次数最多的前5个单词及其出现次数(按出现次数由多到少的顺序输出,次数相同时按字典顺序输出,
不足5个单词时,按序输出全部单词)。程序中注意如下细节:
(1)	空格、标点符号与回车符起到分隔单词的作用。
(2)	文章一行的末尾可能有连字符,出现连字符时,该行最末的字符串与下行最先出现的字符串构一个单词;
(3)	名词缩写算一个单词;
(4)	数字不算单词;
(5)	单词不区分大小写;
(6)	输出时单词全使用小写;


#include "stdio.h"
#include "math.h"
#include "string.h"
#include "stdlib.h"

_______________________

main()
{
         _______________________
}

输入格式

文件case1.in中一篇英文文章,包含多段文字,单词数不超过10000,每个单词不超过20个字符


 

输出格式

按题意输出答案

输入样例

(如case1.in内容如下) 
I am a student. My school is SCAU. It is a beau-
tiful university. I like it.

输出样例

a 2
i 2
is 2
it 2
am 1

定义一个结构体 WordCount 来存储每个单词及其出现的次数

typedef struct
{
    char word[21];
    int count;
} WordCount;

单词统计

add_word 函数:用于添加一个新的单词或者增加已有单词的计数。它会遍历 words 数组,检查该单词是否已经存在。如果存在,则增加其计数;如果不存在且数组还有空间,则将该单词添加到数组中并将计数初始化为 1

void add_word(const char *word)
{
    for(int i=0; i<word_count; i++)
    {
        if(strcmp(words[i].word,word)==0)
        {
            words[i].count++;
            return;
        }
    }
    if(word_count<10000)
    {
        strcpy(words[word_count].word,word);
        words[word_count].count=1;
        word_count++;
    }
}

process_line 函数:用于处理一行文本,提取其中的单词并调用 add_word 函数进行统计。它会遍历行中的每个字符,将连续的字母和数字组合成一个单词,遇到非字母数字字符时将当前单词添加到统计中。

void process_line(const char *line) {
    char word[21] = {0};
    int pos = 0;
    int has_alpha = 0;
    for (int i = 0; line[i]; i++) {
        char c = line[i];
        if (isalnum(c)) {
            if (pos < 20) {
                word[pos++] = tolower(c);
                if (isalpha(c)) {
                    has_alpha = 1;
                }
            }
        } else {
            if (pos > 0 && has_alpha) {
                word[pos] = '\0';
                add_word(word);
                pos = 0;
                has_alpha = 0;
            }
            pos = 0;
            has_alpha = 0;
        }
    }
    if (pos > 0 && has_alpha) {
        word[pos] = '\0';
        add_word(word);
    }
}

在 main 函数中,打开指定的文件 case1.in,逐行读取文件内容。对于每行内容,先去除换行符,然后将其拼接起来。如果行末是连字符 -,则将连字符去除并继续拼接下一行;否则,调用 process_line 函数处理当前拼接的内容,并清空缓冲区

FILE *fp = fopen("case1.in", "r");
if(!fp)
{
    perror("Failed to open file");
    return 1;
}
char buffer[10000] = {0};
char line[10000];
while (fgets(line, sizeof(line), fp))
{
    line[strcspn(line,"\n")]='\0';
    strcat(buffer,line);
    size_t len = strlen(buffer);
    if (len > 0&& buffer[len - 1]=='-')
    {
        buffer[len-1] ='\0';
    }
    else
    {
        process_line(buffer);
        buffer[0] = '\0';
    }
}
if (strlen(buffer)>0)
{
    process_line(buffer);
}
fclose(fp);

使用 qsort 函数对 words 数组进行排序,排序规则是先按照出现次数从高到低排序,如果出现次数相同,则按照字典序排序。最后输出出现次数最多的前 5 个单词及其出现次数

qsort(words, word_count, sizeof(WordCount), compare);
int output_num=word_count<5?word_count:5;
for (int i=0; i<output_num; i++)
{
    printf("%s %d\n",words[i].word,words[i].count);
}

完整代码

#include "stdio.h"
#include "math.h"
#include "string.h"
#include "stdlib.h"


//-------------该行开始是填空的内容--------------
typedef struct
{
    char word[21];
    int count;
} WordCount;
WordCount words[10000];
int word_count=0;
void add_word(const char *word)
{
    for(int i=0; i<word_count; i++)
    {
        if(strcmp(words[i].word,word)==0)
        {
            words[i].count++;
            return;
        }
    }
    if(word_count<10000)
    {
        strcpy(words[word_count].word,word);
        words[word_count].count=1;
        word_count++;
    }
}
int compare(const void *a,const void *b)
{
    const WordCount *wa=(const WordCount *)a;
    const WordCount *wb=(const WordCount *)b;
    if(wb->count!=wa->count)
    {
        return wb->count-wa->count;
    }
    else
    {
        return strcmp(wa->word,wb->word);
    }
}
void process_line(const char *line) {
    char word[21] = {0};
    int pos = 0;
    int has_alpha = 0;
    for (int i = 0; line[i]; i++) {
        char c = line[i];
        if (isalnum(c)) {
            if (pos < 20) {
                word[pos++] = tolower(c);
                if (isalpha(c)) {
                    has_alpha = 1;
                }
            }
        } else {
            if (pos > 0 && has_alpha) {
                word[pos] = '\0';
                add_word(word);
                pos = 0;
                has_alpha = 0;
            }
            pos = 0;
            has_alpha = 0;
        }
    }
    if (pos > 0 && has_alpha) {
        word[pos] = '\0';
        add_word(word);
    }
}

//-------------该行之上是填空的内容--------------


main()
{
         
//-------------该行开始是填空的内容--------------
    FILE *fp = fopen("case1.in", "r");
    if(!fp)
    {
        perror("Failed to open file");
        return 1;
    }
    char buffer[10000] = {0};
    char line[10000];
    while (fgets(line, sizeof(line), fp))
    {
        line[strcspn(line,"\n")]='\0';
        strcat(buffer,line);
        size_t len = strlen(buffer);
        if (len > 0&& buffer[len - 1]=='-')
        {
            buffer[len-1] ='\0';
        }
        else
        {
            process_line(buffer);
            buffer[0] = '\0';
        }
    }
    if (strlen(buffer)>0)
    {
        process_line(buffer);
    }
    fclose(fp);
    qsort(words, word_count, sizeof(WordCount), compare);
    int output_num=word_count<5?word_count:5;
    for (int i=0; i<output_num; i++)
    {
        printf("%s %d\n",words[i].word,words[i].count);
    }
    return 0;
//-------------该行之上是填空的内容--------------

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值