You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言文本词频统计出错求助:重复统计单词问题排查

大小写不敏感单词计数程序的错误分析与修复

需求与现状

  • 需求:统计文本文件中每个单词的出现次数,大小写不敏感(如"immenso"和"IMMENSO"视为同一单词)
  • 输入文本:
    Mi illumino di immenso
    Illumino di immenso
    Di immenso
    IMMENSO
    
  • 预期输出:
    immenso 4
    di 3
    illumino 2
    Mi 1
    
  • 当前错误输出:
    Mi 1
    illumino 2
    di 3
    immenso 4
    Illumino 1
    di 2
    immenso 3
    Di 1
    immenso 2
    IMMENSO 1
    

问题原因分析

原代码的核心逻辑存在三处关键错误:

  1. 遍历判断逻辑混乱:读取新单词后,遍历已存储单词时,只要遇到一个不匹配的条目就直接将新单词添加到数组末尾,完全忽略后续可能存在的匹配项,导致同一单词被重复添加。
  2. 未统一大小写基准:直接存储原始单词,仅靠stricmp做比较,既无法保证输出形式统一,也容易因遍历逻辑错误导致重复统计。
  3. 无条件递增计数:每次循环后都执行n++,即使找到匹配项也会新增无效条目,进一步加剧重复统计问题。

解决方法与修正代码

修复要点

  • 将所有读取到的单词转换为统一大小写(如全小写),作为存储和比较的基准,彻底解决大小写不敏感问题。
  • 遍历已存储单词时,先用标记位记录是否找到匹配项,遍历结束后再决定是计数加1还是新增条目。
  • 仅在新增单词条目时递增n,避免无效计数。
  • 可选:添加排序逻辑,让输出顺序与预期一致。

修正后的代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define N 100

typedef struct words {
    int iteration;
    char word[N];
} word_s;

// 将字符串转换为全小写
void to_lower(char *str) {
    while (*str) {
        *str = tolower((unsigned char)*str);
        str++;
    }
}

int main() {
    FILE *file = fopen("file", "r");
    if (file == NULL) {
        printf("Error opening file\n");
        exit(1);
    }

    word_s v[N];
    int n = 0; // 已存储的单词数量
    char str[N];

    while (fscanf(file, "%s", str) != EOF) {
        to_lower(str); // 统一转换为全小写
        int found = 0;

        // 遍历查找匹配的单词
        for (int i = 0; i < n; i++) {
            if (strcmp(v[i].word, str) == 0) {
                v[i].iteration++;
                found = 1;
                break; // 找到后立即退出循环,避免无效遍历
            }
        }

        // 未找到匹配项则新增条目
        if (!found) {
            strcpy(v[n].word, str);
            v[n].iteration = 1;
            n++;
        }
    }

    // 按出现次数降序排序,匹配预期输出顺序
    for (int i = 0; i < n - 1; i++) {
        for (int j = i + 1; j < n; j++) {
            if (v[i].iteration < v[j].iteration) {
                word_s temp = v[i];
                v[i] = v[j];
                v[j] = temp;
            }
        }
    }

    // 输出统计结果
    for (int i = 0; i < n; i++) {
        printf("%s %d\n", v[i].word, v[i].iteration);
    }

    fclose(file);
    return 0;
}

代码说明

  1. to_lower函数:统一单词的大小写形式,从根源上避免大小写差异导致的重复统计。
  2. 匹配检查逻辑:用found标记位确保只有遍历完所有已存储单词后,才决定是否新增条目,彻底解决重复添加问题。
  3. 排序逻辑:通过冒泡排序按出现次数降序排列结果,与预期输出顺序一致(不需要可删除该部分)。
  4. 资源释放:添加fclose(file)避免文件资源泄漏。

内容的提问来源于stack exchange,提问作者Severjan Lici

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 12:07:48