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

基于链表实现文本词频统计的C语言代码问题求助

问题描述

需求:读取文本文件,不区分大小写统计每个单词的出现次数(如tall、TALL、tAlL视为同一单词),需用链表实现。现有代码基于链表实现时出现重复单词统计错误,具体情况如下:

  • 实现思路:用大小为100的char buffer[N]逐词读取文件,检查单词是否已存在于链表中:存在则计数+1,不存在则添加新节点并将计数设为1。
  • 测试文本内容:
Mi illumino di immenso
Illumino di immenso
Di immenso
IMMENSO
  • 当前错误输出:
Mi->1
illumino->2
di->3
immenso->3
immenso->13435072
  • 期望输出(不要求排序):
immenso 4
di 3
illumino 2
Mi 1
代码问题排查

原代码存在以下核心错误:

  1. 链表遍历遗漏最后一个节点:原代码while(p->next != NULL)的循环条件,导致遍历到链表最后一个节点时直接退出,无法检查该节点的单词是否匹配,这是重复单词出现的主要原因。
  2. 节点instance未初始化:创建新节点tmp时仅分配内存,未给instance赋值,导致未初始化节点出现垃圾数值(如输出中的13435072)。
  3. 匹配成功后未释放冗余内存:每次循环一开始就为tmp分配内存,若找到已有单词,新分配的节点未被释放,造成内存泄漏。
  4. 新增节点逻辑错误:原代码在新增节点时错误修改p->instance,应给新节点tmp->instance赋值为1,再将tmp挂载到链表末尾。
  5. 文件打开逻辑冗余:createlist函数接收FILE*参数但内部重新打开固定文件名的文件,且main函数传入的file是未初始化指针,逻辑混乱。
修复后的完整代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 100

typedef struct node
{
    char *str;
    int instance;
    struct node* next;
} node;

node *createlist(const char *filename)
{
    node *tmp = NULL;
    node *head = NULL;
    node* p = NULL;
    char buffer[N+3];
    int found;

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

    while(fscanf(file, "%s", buffer) != EOF)
    {
        found = 0;
        // 先遍历链表检查单词是否存在
        p = head;
        while(p != NULL)
        {
            if(strcasecmp(p->str, buffer) == 0)
            {
                p->instance++;
                found = 1;
                break;
            }
            p = p->next;
        }

        if(found == 1)
        {
            continue; // 存在则跳过创建新节点
        }

        // 不存在则创建新节点
        tmp = malloc(sizeof(node));
        if(tmp == NULL)
        {
            printf("Allocation error\n");
            exit(1);
        }
        tmp->str = malloc((strlen(buffer)+1)*sizeof(char));
        if(tmp->str == NULL)
        {
            printf("Allocation error\n");
            free(tmp); // 释放已分配的节点内存
            exit(2);
        }
        strcpy(tmp->str, buffer);
        tmp->instance = 1; // 初始化计数为1
        tmp->next = NULL;

        // 将新节点添加到链表末尾
        if(head == NULL)
        {
            head = tmp;
        }
        else
        {
            p = head;
            while(p->next != NULL)
            {
                p = p->next;
            }
            p->next = tmp;
        }
    }

    fclose(file);
    return head;
}

void printlist(node *head)
{
    node* tmp = head;
    while(tmp != NULL)
    {
        printf("%s -> %d\n", tmp->str, tmp->instance);
        tmp = tmp->next;
    }
}

// 新增:释放链表内存,避免泄漏
void freelist(node *head)
{
    node *tmp;
    while(head != NULL)
    {
        tmp = head;
        head = head->next;
        free(tmp->str);
        free(tmp);
    }
}

int main()
{
    node *head = NULL;

    head = createlist("file");
    printlist(head);
    freelist(head); // 释放内存

    return 0;
}
修复说明
  • 调整遍历逻辑:改为while(p != NULL),确保所有节点都被检查到。
  • 调整节点创建时机:先检查链表,确认不存在后再创建新节点,避免不必要的内存分配。
  • 初始化instance:新节点创建时明确设置tmp->instance = 1。
  • 修复文件打开逻辑:createlist接收文件名参数,由内部打开并关闭文件,避免指针混乱。
  • 新增内存释放函数:避免程序退出时的内存泄漏。

内容的提问来源于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.24 21:37:43