如何将Linked List保存到文件?链表写入文件无限循环致文件过大
链表保存到文件时无限写入的问题修复
问题描述
无法将链表(liste chainée)保存到文件中,程序会持续写入直到文件大小达到1.4GB。确认问题出在保存函数,因为链表填充过程正常。
原程序代码
#include <stdio.h> #include <stdlib.h> #include <string.h> /***valeur d'un capteur d'humidite***/ typedef struct { int heure; int minute; }Date; typedef struct//valeur d'une cellule/noeud { char id[10]; char id_capt[10]; Date date_hr; int val_hum;//float ou int }valeurs_hum; typedef struct//liste chainee { valeurs_hum capt; struct Element* suivant; }Element; typedef struct Liste Liste; struct Liste { Element *premier; }; /************************************************/ Liste *initialisation() { Liste *liste = malloc(sizeof(*liste)); Element *nouveau = malloc(sizeof(*nouveau));//element->nouveau if (liste == NULL || nouveau == NULL) { exit(EXIT_FAILURE); } printf("Donner id = "); fflush(stdin); scanf("%s",nouveau->capt.id); if( strlen(nouveau->capt.id)==0)//peut etre ajouter au premier nouveau=NULL; else { printf("Donner id du capteur = "); fflush(stdin); scanf("%s",nouveau->capt.id_capt); printf("Donner date de prendre valeur d'humidite\n"); printf("heure = "); scanf("%d",&nouveau->capt.date_hr.heure); printf("minite = "); scanf("%d",&nouveau->capt.date_hr.minute); //valeur du capteur aleatoire nouveau->capt.val_hum = rand() % 100 + 1; nouveau->suivant = NULL; liste->premier = nouveau; return liste; } } /********************************************/ void insertion(Liste *liste) { /* Création du nouvel élément */ Element *nouveau = malloc(sizeof(*nouveau)); if (liste == NULL || nouveau == NULL) { exit(EXIT_FAILURE); } printf("Donner id = "); fflush(stdin); scanf("%s",nouveau->capt.id); if( strlen(nouveau->capt.id)==0) nouveau=NULL; else { printf("Donner id du capteur = "); fflush(stdin); scanf("%s",nouveau->capt.id_capt); printf("Donner date de prendre valeur d'humidite\n"); printf("heure = "); scanf("%d",&nouveau->capt.date_hr.heure); printf("minite = "); scanf("%d",&nouveau->capt.date_hr.minute); //valeur du capteur aleatoire nouveau->capt.val_hum = rand() % 100 + 1; /* Insertion de l'élément au début de la liste */ nouveau->suivant = liste->premier; liste->premier = nouveau; } } /*******************************************/ void afficherListe(Liste *liste) { if (liste == NULL) { exit(EXIT_FAILURE); } Element *nouveau = liste->premier;//nouveau->courant while (nouveau != NULL) { printf("\n id : %s", nouveau->capt.id); printf("\n id du capteur : %s", nouveau->capt.id_capt); printf("\n date de prendre valeur d'humidite = %d:%d",nouveau->capt.date_hr.heure,nouveau->capt.date_hr.minute); printf("\n valeur du capteur :%d", nouveau->capt.val_hum); nouveau = nouveau->suivant; } printf("\n"); } /*************************************************/ void Sauvegarder(Liste *liste, FILE* pf) { int i; Element *courant = liste->premier; while(courant!=NULL) fprintf(pf,"\n%s : %s : %d:%d : %d \n", courant->capt.id, courant->capt.id_capt, courant->capt.date_hr.heure,courant->capt.date_hr.minute,courant->capt.val_hum); courant=courant->suivant; } /************************************************/ int main(void) { char* nomfich; FILE * pf; int i,nbr_capt; Liste *l; Liste *l1; nomfich=(char*)malloc(sizeof(char)); printf("\n Donnez le nom du fichier à créer :"); gets(nomfich); /*--------------------------------------------*/ /*------------------Ecriture dans le fichier----------------*/ pf = fopen(nomfich, "a+"); //do{ l=initialisation(); printf("donner nbre capt = "); scanf("%d",&nbr_capt); for(i=0;i<nbr_capt;i++) insertion(l); /*if( l==NULL) break; else*/ Sauvegarder(l, pf); //}while(1); fclose(pf); return 0; }
核心错误分析
你锁定的Sauvegarder函数确实是问题根源:
while(courant!=NULL) fprintf(pf,"\n%s : %s : %d:%d : %d \n", courant->capt.id, courant->capt.id_capt, courant->capt.date_hr.heure,courant->capt.date_hr.minute,courant->capt.val_hum); courant=courant->suivant;
C语言中,while循环若未用大括号{}包裹,只会执行紧跟其后的第一行代码。这里fprintf被反复执行,但courant=courant->suivant;不在循环体内,导致courant指针永远指向链表首节点,形成死循环,持续向文件写入相同内容,直到文件体积异常庞大。
修复方案
给while循环添加大括号,让指针移动语句进入循环体:
void Sauvegarder(Liste *liste, FILE* pf) { Element *courant = liste->premier; while(courant!=NULL) { fprintf(pf,"\n%s : %s : %d:%d : %d \n", courant->capt.id, courant->capt.id_capt, courant->capt.date_hr.heure,courant->capt.date_hr.minute,courant->capt.val_hum); courant=courant->suivant; } }
其他潜在问题修复
程序还有几个可能引发崩溃或异常的问题,建议一并修复:
- 文件名内存分配不足:
nomfich=(char*)malloc(sizeof(char));仅分配1字节,完全无法存储文件名,会导致内存越界。改为分配足够空间:char* nomfich = malloc(256 * sizeof(char)); // 分配256字节存储文件名 gets函数不安全:gets会引发缓冲区溢出,改用fgets并处理换行符:fgets(nomfich, 256, stdin); nomfich[strcspn(nomfich, "\n")] = '\0'; // 去除fgets读取的换行符initialisation函数返回漏洞:输入空id时,未释放已分配内存且无返回值,会导致未定义行为:Liste *initialisation() { Liste *liste = malloc(sizeof(*liste)); Element *nouveau = malloc(sizeof(*nouveau)); if (liste == NULL || nouveau == NULL) { exit(EXIT_FAILURE); } printf("Donner id = "); fflush(stdin); scanf("%s",nouveau->capt.id); if( strlen(nouveau->capt.id)==0) { free(nouveau); // 释放已分配内存 free(liste); return NULL; } else { // 原有初始化逻辑... return liste; } }insertion函数内存泄漏:输入空id时,未释放已分配的nouveau内存:void insertion(Liste *liste) { Element *nouveau = malloc(sizeof(*nouveau)); if (liste == NULL || nouveau == NULL) { exit(EXIT_FAILURE); } printf("Donner id = "); fflush(stdin); scanf("%s",nouveau->capt.id); if( strlen(nouveau->capt.id)==0) { free(nouveau); // 释放内存 return; } else { // 原有插入逻辑... } }
内容的提问来源于stack exchange,提问作者skander
相关产品推荐
相关产品推荐

