C语言(NetBeans)结构体二进制文件读写功能失效求助
我来帮你排查下这个二进制文件读写的问题,看了你的代码后,发现几个关键错误导致了现在的异常:
1. 保存函数写入了错误的数据结构
在saveBinaryCliente函数里,你当前用的是:
res = fwrite(aux, sizeof(CLIENTE), 1, fp);
但aux是ELEMENTO*类型,指向的是包含VEICULO、CLIENTE、ALUGADO和链表指针的整个节点,而你实际需要保存的只是其中的CLIENTE部分。这种错误的写入会把无关的结构体内容和内存地址都写到文件里,导致读取时完全解析错误,出现全0的情况。
正确的写法应该是写入aux->info_cliente:
res = fwrite(&aux->info_cliente, sizeof(CLIENTE), 1, fp);
2. 保存函数的计数逻辑错误
你现在用res变量记录写入结果,但它在循环里会被每次覆盖,最后打印的Saved %i register clientes!只会显示最后一次写入的结果,而不是总条数。应该单独用一个计数器累加成功写入的数量:
int count = 0; for(aux=iniLista; aux!=NULL; aux=aux->seguinte){ res = fwrite(&aux->info_cliente, sizeof(CLIENTE), 1, fp); if(res == 1) count++; } printf("Saved %i register clientes!\n", count);
3. 读取函数用feof判断循环的坑
while (!feof(fp))的写法很容易导致多读一次无效数据——因为feof是在尝试读取失败后才会设置标志位,循环会多执行一次,可能插入空数据。正确的做法是直接判断fread的返回值:
while (fread(&aux, sizeof(CLIENTE), 1, fp) == 1){ inserirCliente(iniLista, aux); }
另外你传入&(*iniLista)有点多余,直接传iniLista就行,它已经是二级指针了。
4. 未插入客户时的空文件处理
当链表为空时,saveBinaryCliente的循环不会执行,但wb模式会创建一个空文件。如果不想生成空文件,可以在保存前先判断链表是否为空:
if(iniLista == NULL){ fclose(fp); printf("No clientes to save!\n"); return 0; }
修正后的完整函数
保存函数
int saveBinaryCliente(ELEMENTO *iniLista){ ELEMENTO *aux = NULL; FILE *fp = NULL; int res=0; int count = 0; fp = fopen("clientes.dat", "wb"); if(fp == NULL){ printf("Erro ao abrir o ficheiro clientes!\n"); return -1; } if(iniLista == NULL){ fclose(fp); printf("No clientes to save!\n"); return 0; } for(aux=iniLista; aux!=NULL; aux=aux->seguinte){ res = fwrite(&aux->info_cliente, sizeof(CLIENTE), 1, fp); if(res == 1){ count++; } } fclose(fp); printf("Saved %i register clientes!\n", count); return 0; }
读取函数
int readDataCliente(ELEMENTO **iniLista){ CLIENTE aux; FILE *fp = NULL; fp = fopen("clientes.dat", "rb"); if(fp == NULL){ printf("Error reading file clientes!\n"); return -1; } while (fread(&aux, sizeof(CLIENTE), 1, fp) == 1){ inserirCliente(iniLista, aux); } fclose(fp); return 0; }
这些修正后,写入的就是纯净的CLIENTE结构体数据,读取时能正确解析,不会再出现全0或无效数据的问题,计数也会准确显示保存的客户数量。
内容的提问来源于stack exchange,提问作者Nuno Oliveira
相关产品推荐
相关产品推荐

