使用链表读取打印文件内容时出现无限输出乱码问题求助
问题分析与修复
你的代码出现「打印第一个单词后无限输出随机符号」的核心原因是结构体内存分配错误,另外还有几个次要问题需要修正:
核心错误:结构体内存分配不足
在创建节点时,你写了:
tmp=malloc(sizeof(node*));
这里分配的是node*指针的大小(通常为4或8字节),但node结构体包含一个char*和一个node*成员,实际需要分配整个结构体的内存空间。正确写法应该是:
tmp=malloc(sizeof(node));
内存分配不足会导致tmp->next的内存区域未被正确初始化,变成野指针,遍历链表时无法正常终止,进而出现无限循环和随机垃圾值。
其他需要修正的问题
- 冗余的函数参数:
createlist函数的FILE *file参数完全没用,函数内部自己打开了文件,main里传入的是未初始化的指针,直接删掉这个参数即可。 - 未关闭文件:打开文件后没有调用
fclose,会导致资源泄漏。 - 内存泄漏:程序结束前没有释放链表节点和字符串的内存,长期运行会浪费系统资源,建议添加销毁链表的函数。
- 读取逻辑可选调整:
fscanf("%s", buffer)是按单个单词读取(空格/换行作为分隔符),如果你的需求是读取整行内容,应该改用fgets。
修复后的完整代码
#include <stdio.h> #include <stdlib.h> #include <string.h> #define N 100 typedef struct node { char *str; struct node* next; } node; node *createlist() { node *tmp=NULL; node *head=NULL; node* p=NULL; char buffer[N+3]; FILE *file=fopen("file","r"); if(file==NULL) { printf("Error opening file\n"); exit(1); } // 如果要读取整行,替换下面的fscanf为fgets: // while(fgets(buffer, N+3, file) != NULL) while(fscanf(file,"%s",buffer)!=EOF) { // 修复:分配结构体大小而非指针大小 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"); exit(2); } tmp->next=NULL; strcpy(tmp->str,buffer); if(head==NULL) { head=tmp; } else { p=head; while(p->next !=NULL) { p=p->next; } p->next=tmp; } } fclose(file); // 关闭文件 return head; } void printfile(node *head) { node* tmp=head; while(tmp != NULL) { printf("%s ",tmp->str); tmp=tmp->next; } printf("\n"); } // 添加销毁链表的函数,避免内存泄漏 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(); printfile(head); freelist(head); // 释放内存 return 0; }
额外说明
如果你的需求是读取文件的每一行(而不是每个单词),把createlist里的fscanf替换为fgets即可,同时可以去掉换行符:
while(fgets(buffer, N+3, file) != NULL) { // 去掉换行符 buffer[strcspn(buffer, "\n")] = '\0'; // 后续节点创建代码不变 }
内容的提问来源于stack exchange,提问作者Severjan Lici
相关产品推荐
相关产品推荐

