如何在C语言固定长度随机访问文件中避免写入垃圾值
解决固定长度记录文件的垃圾值问题
核心思路
要在保持90字节固定记录长度的同时避免垃圾值,关键是提前清空结构体的内存空间,让未被输入内容填充的位置变为可预知的可控值(比如'\0'或空格),这样写入文件的内容不会出现随机垃圾字节,同时保留随机访问的特性。
具体实现方案
方案1:初始化整个结构体为0
在定义结构体变量后,用memset将整个结构体的内存填充为0。所有未被输入覆盖的字符数组位置都会是'\0',写入文件后无垃圾值,且读取时puts等函数能正常识别字符串结束。
修改后的代码示例:
#include <stdio.h> #include <string.h> // 引入memset所需头文件 #define size 30 struct Record{ char account[size]; char name[size]; char address[size]; }; int main() { FILE *ptr = NULL; ptr = fopen("testfile.txt", "w"); if (ptr == NULL) { printf("Could not open file."); return 1; // 出错直接退出,避免后续无效执行 } else { struct Record client; // 初始化整个结构体内存为0 memset(&client, 0, sizeof(struct Record)); // 替换gets为fgets,避免缓冲区溢出(gets已被C标准废弃) printf("Enter account number: "); fgets(client.account, size, stdin); // 去掉fgets读取的换行符 client.account[strcspn(client.account, "\n")] = '\0'; printf("Enter name: "); fgets(client.name, size, stdin); client.name[strcspn(client.name, "\n")] = '\0'; printf("Enter address: "); fgets(client.address, size, stdin); client.address[strcspn(client.address, "\n")] = '\0'; // 保持固定长度写入,确保随机访问特性 fwrite(&client, sizeof(struct Record), 1, ptr); fclose(ptr); ptr = fopen("testfile.txt", "r"); if (ptr == NULL) { printf("Could not open file for reading."); return 1; } struct Record read_client; memset(&read_client, 0, sizeof(struct Record)); // 读取前初始化,避免内存垃圾 fseek(ptr, 0, SEEK_SET); fread(&read_client, sizeof(struct Record), 1, ptr); puts(read_client.account); puts(read_client.name); puts(read_client.address); fclose(ptr); } puts("Done!"); return 0; }
方案2:用空格填充未使用位置
如果希望文件内容更直观可读(未使用位置显示空格而非'\0'),可以在输入后将字符数组中字符串结束符后的位置填充为空格。
示例代码片段(以account字段为例):
printf("Enter account number: "); fgets(client.account, size, stdin); client.account[strcspn(client.account, "\n")] = '\0'; // 填充空格到数组末尾 int len = strlen(client.account); for(int i = len; i < size - 1; i++){ client.account[i] = ' '; } client.account[size - 1] = '\0'; // 确保字符串结束符(可选,按需设置)
关键注意点
- 禁用
gets:该函数无缓冲区长度限制,易导致缓冲区溢出,已被C11标准废弃,改用fgets更安全。 - 保持固定写入单位:写入时必须使用
sizeof(struct Record)作为写入长度,确保每条记录都是90字节,保证fseek可通过记录索引 * sizeof(struct Record)准确定位。 - 读取前初始化结构体:避免读取到内存中残留的垃圾值,保证读取数据的准确性。
内容的提问来源于stack exchange,提问作者M.Jafar
相关产品推荐
相关产品推荐

