C语言程序选项3仅首次运行正常,再次执行显示空值求助
问题分析与解决方案
你遇到的问题核心在于文件指针的生命周期管理和链表的重复初始化问题,具体原因和修复方案如下:
问题根源拆解
文件仅打开一次,关闭后未重新初始化
在main开头你打开了文件,但第一次执行选项3时调用fclose(arq)关闭了文件。后续再次选择选项3时,arq已经是无效的关闭状态,fgets无法读取任何内容,自然生成空链表。链表未在每次执行前重置
第一次执行选项3后,liberar(filmes)释放了链表内存,但main中的filmes指针是值传递,不会被置为NULL,再次执行时会变成野指针,导致插入逻辑异常。
修复后的代码修改要点
1. 每次进入选项3时重新打开文件
把文件的打开/关闭逻辑移到选项3的分支内部,确保每次执行都能获取有效文件指针:
case 3: printf("\n Voce gostaria de listar em ordem alfabetica ou alfabetica reversa (0/1) :"); int op; scanf("%d",&op); if(op!=0 && op!=1) { printf("\n Voce precisa digita o numero 1 ou 0 apenas!\n"); break; // 新增break,避免进入无效switch分支 } // 每次执行选项3时重新打开文件 arq = fopen("asd.txt", "r"); if (arq == NULL) { printf("Ocorreu um erro ao abrir o arquivo!"); break; } filmes = NULL; // 重置链表头指针,避免野指针 switch(op){ case 0: while (fgets(linha, sizeof linha, arq)) { char *p = strtok(linha, ","); if(p != NULL) { // 新增空值判断,避免传入NULL filmes = InsertOrd(filmes, p); } } fclose(arq); escrever(film,filmes); liberar(&filmes); // 修改调用方式 break; case 1: while (fgets(linha, sizeof linha, arq)) { char *p1 = strtok(linha, ","); if(p1 != NULL) { // 新增空值判断 filmes = InsertDec(filmes, p1); } } fclose(arq); escrever(film,filmes); liberar(&filmes); // 修改调用方式 break; } break;
2. 优化liberar函数,彻底清除野指针
原函数无法修改main中的filmes指针,改为传递指针的指针,释放后将原指针置为NULL:
void liberar(struct Lista **filmes) { struct Lista *current = *filmes; while (current != NULL) { struct Lista *next = current->next; free(current->data); free(current); current = next; } *filmes = NULL; // 将原指针置为NULL,避免野指针 }
3. 移除冗余的链表释放代码
main函数末尾的链表释放逻辑是多余的,因为每次选项3执行后已经调用liberar完成内存释放,可以直接删除这部分代码。
额外注意点
- 你注释里提到
strdup在栈上分配内存是错误的,它实际是在堆上分配,所以你用free释放的操作是正确的。 - 处理文件行时增加
strtok空值判断,避免文件出现空行或异常格式时导致程序崩溃。
内容的提问来源于stack exchange,提问作者Maurício Z.B
相关产品推荐
相关产品推荐

