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

C语言打印链表时字符串出现垃圾值问题求助

链表节点字符串读取后显示垃圾值问题分析与修复

问题概述

从文本文件读取数据填充如下NODE结构体链表时,初始化节点阶段打印字符串正常,但调用printList()函数时,line字段始终显示垃圾值。

typedef struct node {
    int data;
    char* line;
    struct node* next;
} NODE;

运行示例

./a.out linkedlisttext.txt

data in readFile(): 4
string in readFile():  Hello world
address in readFile(): 0x1326067a0


data in readFile(): 28
string in readFile():  What is up world???
address in readFile(): 0x1326067c0


data in readFile(): 2124
string in readFile():  your mother
address in readFile(): 0x1326067e0


data in readFile(): 85
string in readFile():  more data
address in readFile(): 0x132606800


data in readFile(): 9421
string in readFile():  just a little more data
address in readFile(): 0x132606820


data in readFile(): 992
string in readFile():  are we almost there?
address in readFile(): 0x132606840


data in readFile(): 301
string in readFile():  we did it!
address in readFile(): 0x132606860

DATA:    4 | STRING �g`2
address in printList(): 0x1326067a0
DATA:   28 | STRING �g`2
address in printList(): 0x1326067c0
DATA: 2124 | STRING �g`2
address in printList(): 0x1326067e0
DATA:   85 | STRING h`2
address in printList(): 0x132606800
DATA: 9421 | STRING 0h`2
address in printList(): 0x132606820
DATA:  992 | STRING Ph`2
address in printList(): 0x132606840
DATA:  301 | STRING 
address in printList(): 0x132606860

输入文件内容(linkedlisttext.txt)

4, Hello world
28, What is up world???
2124, your mother
85, more data
9421, just a little more data
992, are we almost there?
301, we did it!

完整错误代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct node {
    int data;
    char* line;
    struct node* next;
} NODE;


struct node* readFile(FILE* fp, NODE* root) {
    char line[100];
    char* token;
    NODE* curr;
    NODE* prev;

    while(fgets(line, 100, fp) != NULL) {   
        curr = malloc(sizeof(struct node*));
        token = strtok(line, ",");
        curr->data = atoi(token);
        printf("\ndata in readFile(): %d\n", curr->data);
        token = strtok(NULL, "");
        curr->line = (char*) malloc(sizeof(token)  + 1);
        strcpy(curr->line, token);
        printf("string in readFile(): %s", curr->line);
        printf("address in readFile(): %p\n\n", curr->line);
        curr->next = NULL;  
        if(root == NULL) {
            root = curr;
        } else {
            NODE* travel = root;
            while(travel->next != NULL) {
                travel = travel->next;
            }
            travel->next = curr;
        }
    }
    return root;    
}

void printList(NODE* root) {
    struct node* temp = root;
    while(temp->next != NULL) {
        printf("DATA: %4d | STRING %s\n", temp->data, temp->line);
        printf("address in printList(): %p\n", temp->line);
        temp = temp->next;
    }
    printf("DATA: %4d | STRING %s\n", temp->data, temp->line);
    printf("address in printList(): %p\n", temp->line);
}

int main(int argc, char** argv) {
    FILE* fp = fopen(argv[1], "r");
    NODE* root = NULL;  
    if(fp == NULL) {
        return 0;
    }   
    root = readFile(fp, root);
    printList(root);
}

问题原因

  1. 节点内存分配错误:curr = malloc(sizeof(struct node*))仅分配了指针大小的内存(通常4或8字节),但NODE结构体的实际大小远大于指针,导致内存越界,后续操作会覆盖节点的line指针或其他字段,引发未定义行为。
  2. 字符串内存分配错误:curr->line = (char*) malloc(sizeof(token) + 1)中,sizeof(token)是指针的大小,不是字符串的实际长度。分配的内存空间不足以存储完整字符串,导致strcpy操作越界,破坏内存中的其他数据。

修复方案

  • 将节点内存分配改为malloc(sizeof(struct node)),确保分配足够空间存储整个结构体。
  • 将字符串内存分配改为malloc(strlen(token) + 1),根据字符串实际长度分配空间,加1是为了存储终止符\0。
  • 可选优化:在链表插入时维护尾节点,避免每次遍历整个链表提升效率。

修复后的代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct node {
    int data;
    char* line;
    struct node* next;
} NODE;


struct node* readFile(FILE* fp, NODE* root) {
    char line[100];
    char* token;
    NODE* curr;
    NODE* tail = NULL; // 维护尾节点优化插入

    while(fgets(line, 100, fp) != NULL) {   
        // 修复节点内存分配
        curr = malloc(sizeof(struct node));
        if (!curr) { // 增加内存分配失败检查
            perror("malloc failed");
            exit(EXIT_FAILURE);
        }
        token = strtok(line, ",");
        curr->data = atoi(token);
        printf("\ndata in readFile(): %d\n", curr->data);
        token = strtok(NULL, "");
        // 修复字符串内存分配
        curr->line = malloc(strlen(token) + 1);
        if (!curr->line) { // 增加内存分配失败检查
            perror("malloc failed");
            free(curr);
            exit(EXIT_FAILURE);
        }
        strcpy(curr->line, token);
        printf("string in readFile(): %s", curr->line);
        printf("address in readFile(): %p\n\n", curr->line);
        curr->next = NULL;  
        if(root == NULL) {
            root = curr;
            tail = curr;
        } else {
            // 尾节点直接插入,无需遍历
            tail->next = curr;
            tail = curr;
        }
    }
    return root;    
}

void printList(NODE* root) {
    struct node* temp = root;
    while(temp != NULL) { // 简化循环条件
        printf("DATA: %4d | STRING %s", temp->data, temp->line);
        printf("address in printList(): %p\n", temp->line);
        temp = temp->next;
    }
}

int main(int argc, char** argv) {
    if (argc < 2) { // 增加参数检查
        fprintf(stderr, "Usage: %s <filename>\n", argv[0]);
        return EXIT_FAILURE;
    }
    FILE* fp = fopen(argv[1], "r");
    NODE* root = NULL;  
    if(fp == NULL) {
        perror("fopen failed");
        return EXIT_FAILURE;
    }   
    root = readFile(fp, root);
    printList(root);
    // 可选:添加链表内存释放逻辑,避免内存泄漏
    fclose(fp);
    return EXIT_SUCCESS;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 10:57:36