如何修复count_words()函数以生成正确词频的单词链表?
C语言词频统计链表问题排查与修复
核心问题根源
你的问题集中在两个关键点:
- 单词内存复用导致内容覆盖:你大概率使用了同一个局部字符缓冲区读取所有单词,直接将缓冲区地址赋值给链表节点的
word指针。所有节点的word会指向同一块内存,后续读取的单词会覆盖之前的内容,函数返回后局部缓冲区被释放,最终word指针变成野指针(表现为空)。 - 链表节点插入逻辑错误:全局变量
word_counts最终仅存1个节点、count为6,说明你没有正确创建并链入新节点,而是一直在修改同一个节点的count值,新节点从未被添加到链表中。
具体修复步骤
1. 为每个单词独立分配内存
不要直接把缓冲区地址赋值给节点的word,必须为每个单词单独分配内存并复制内容:
// 错误写法:直接复用缓冲区指针 node->word = word; // 正确写法1:使用strdup(POSIX标准,Windows可用_strdup) node->word = strdup(word); if (node->word == NULL) { perror("strdup failed"); exit(EXIT_FAILURE); } // 正确写法2:手动malloc+strcpy(兼容所有环境) node->word = malloc(strlen(word) + 1); if (node->word == NULL) { perror("malloc failed"); exit(EXIT_FAILURE); } strcpy(node->word, word);
2. 修复链表节点插入逻辑
确保找到重复单词时累加count,未找到时创建新节点并链入链表:
// 示例:从全局链表word_counts中查找单词 WordCount *current = word_counts; while (current != NULL) { if (strcmp(current->word, word) == 0) { current->count++; return; // 找到重复,直接返回 } current = current->next; } // 未找到,创建新节点并头插 WordCount *new_node = malloc(sizeof(WordCount)); if (new_node == NULL) { perror("malloc failed"); exit(EXIT_FAILURE); } new_node->word = strdup(word); new_node->count = 1; new_node->next = word_counts; // 新节点指向原链表头 word_counts = new_node; // 更新链表头为新节点
如果你的函数是通过指针参数操作链表(如void count_words(WordCount **wclist, FILE *fp)),则更新链表头时要写*wclist = new_node,确保传入的指针指向正确更新。
3. 验证全局变量初始化
确保全局变量word_counts初始化为NULL,避免野指针导致的异常:
WordCount *word_counts = NULL;
4. 内存泄漏防护(可选但推荐)
程序结束前遍历链表,释放每个节点的内存:
void free_wordcount(WordCount *head) { WordCount *temp; while (head != NULL) { temp = head; head = head->next; free(temp->word); free(temp); } }
总结
按照上述步骤修复后,每个节点的word会指向独立的内存块,不会被后续单词覆盖;新节点也会正确链入链表,词频统计结果就能符合预期。
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

