如何用文件读取的数字创建链表?fgets能否生成完整链表?
问题分析与修正方案
首先明确:你的当前代码既不会生成完整链表,也不会正确填充第一个节点,存在多个关键问题,下面逐一拆解并给出修正方案:
核心问题点
fgets使用完全错误:seq1是Nodo*类型的链表节点指针,fgets是用于读取字符串到字符数组的函数,直接将节点指针传给fgets会导致内存越界、类型不匹配,完全无法正确读取数字。- 仅创建了单个节点:你只
malloc了一个seq1和seq2节点,循环中没有动态创建新节点的逻辑,根本无法构建多节点的链表。 feof循环条件错误:用!feof(f1)作为循环条件会导致最后一次读取失败后仍进入循环,引发错误。- 参数冗余且被覆盖:函数参数中的
f1、f2被函数内的fopen重新赋值,完全没有利用传入的参数,属于无效设计。 - 未完成数字转换:文件中是数字文本,需要用
atoi或sscanf将读取的字符串转为int,存入节点的dato字段。
修正后的代码示例
以下是能正确从文件读取数字并构建链表的代码:
#include <stdio.h> #include <stdlib.h> #include <string.h> // 提前定义类型,避免函数声明报错 typedef FILE* fp; typedef struct Nd { int dato; struct Nd* next; } Nodo; typedef Nodo* lista; // 辅助函数:创建新节点 lista creaNodo(int num) { lista nuovo = (lista)malloc(sizeof(Nodo)); if (nuovo == NULL) { printf("Errore allocazione memoria\n"); exit(1); } nuovo->dato = num; nuovo->next = NULL; return nuovo; } // 辅助函数:尾插节点到链表 void aggiungiInCoda(lista* testa, lista nuovo) { if (*testa == NULL) { *testa = nuovo; return; } lista corrente = *testa; while (corrente->next != NULL) { corrente = corrente->next; } corrente->next = nuovo; } int Sequenza() { lista seq1 = NULL, seq2 = NULL; fp f1, f2; char buffer[256]; // 用字符数组存读取的每行字符串 int num; f1 = fopen("sequenza1.txt", "r"); f2 = fopen("sequenza2.txt", "r"); if (f1 == NULL || f2 == NULL) { printf("Errore nell'apertura di uno dei due file\n"); return 0; } // 读取第一个文件构建链表seq1 while (fgets(buffer, sizeof(buffer), f1) != NULL) { // 去除换行符 buffer[strcspn(buffer, "\n")] = '\0'; num = atoi(buffer); // 转成int lista nuovo = creaNodo(num); aggiungiInCoda(&seq1, nuovo); } // 读取第二个文件构建链表seq2 while (fgets(buffer, sizeof(buffer), f2) != NULL) { buffer[strcspn(buffer, "\n")] = '\0'; num = atoi(buffer); lista nuovo = creaNodo(num); aggiungiInCoda(&seq2, nuovo); } // 示例:打印seq1验证结果 printf("Sequenza 1: "); lista corrente = seq1; while (corrente != NULL) { printf("%d ", corrente->dato); corrente = corrente->next; } printf("\n"); // 记得用完链表后释放内存(可自行补充释放逻辑) fclose(f1); fclose(f2); return 1; } // 主函数测试 int main() { Sequenza(); return 0; }
关键修正说明
- 用字符数组接收文件内容:先用
fgets读取每行字符串到buffer,再转换为int类型,避免类型错误。 - 动态创建节点:每读取一个数字就调用
creaNodo创建新节点,完美解决未知节点数量的问题。 - 尾插法构建链表:通过
aggiungiInCoda函数将新节点添加到链表尾部,保证链表的连续性。 - 正确的循环条件:用
fgets != NULL判断是否读取结束,避免feof的陷阱。 - 内存安全:创建节点时检查
malloc是否成功,后续可添加链表内存释放逻辑,避免内存泄漏。
内容的提问来源于stack exchange,提问作者Tania
相关产品推荐
相关产品推荐

