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); }
问题原因
- 节点内存分配错误:
curr = malloc(sizeof(struct node*))仅分配了指针大小的内存(通常4或8字节),但NODE结构体的实际大小远大于指针,导致内存越界,后续操作会覆盖节点的line指针或其他字段,引发未定义行为。 - 字符串内存分配错误:
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
相关产品推荐
相关产品推荐

