如何使用C语言在指定结构体格式的DAT文件中搜索目标名称
判断指定DAT文件中是否存在目标名称的实现方法
每条记录固定占用32字节,在x86-64架构下对应如下C结构体定义:
typedef struct record { unsigned suncents; // 4字节,存储金额(单位:分) unsigned char name_len; // 1字节,存储名称的有效长度 char name[27]; // 27字节,存储名称**不包含终止符**,需通过name_len获取有效长度 } record;
数据文件由0条或多条连续记录组成,无固定排序规则。以提供的sample.dat为例,用hexdump -C sample.dat可查看内容:
$ hexdump -C sample.dat 00000000 86 07 00 00 0e 44 65 6e 6e 69 73 20 52 69 74 63 |.....Dennis Ritc| 00000010 68 69 65 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d |hie-------------| 00000020 22 01 00 00 0a 41 72 63 68 69 6d 65 64 65 73 2d |"....Archimedes-| 00000030 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d |----------------| 00000040 00 28 6b ee 0b 41 6c 61 6e 20 54 75 72 69 6e 67 |.(k..Alan Turing| 00000050 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d |----------------| 00000060
注:每行显示16字节,两行(32字节)对应一条完整记录。
核心实现思路
- 校验文件有效性:先获取文件总字节数,若无法被32整除,说明文件损坏,直接判定目标名称不存在
- 逐记录匹配:
- 每次从文件读取32字节到
record结构体 - 先对比目标名称长度与当前记录的
name_len,长度不一致直接跳过 - 长度一致时,用
memcmp安全对比目标名称与记录name字段的前name_len个字节 - 找到匹配记录立即返回存在;遍历完所有记录未匹配则返回不存在
- 每次从文件读取32字节到
C语言示例代码
#include <stdio.h> #include <stdlib.h> #include <string.h> #include "records.h" // 检查文件中是否存在指定名称,存在返回1,不存在返回0 int has_name(const char *filename, const char *target_name) { FILE *fp = fopen(filename, "rb"); if (!fp) { perror("Failed to open file"); return 0; } // 获取文件大小 fseek(fp, 0, SEEK_END); long file_size = ftell(fp); fseek(fp, 0, SEEK_SET); // 校验文件大小是否符合记录格式 if (file_size % sizeof(record) != 0) { fclose(fp); return 0; } size_t record_count = file_size / sizeof(record); record rec; size_t target_len = strlen(target_name); for (size_t i = 0; i < record_count; i++) { if (fread(&rec, sizeof(record), 1, fp) != 1) { break; } // 长度不匹配直接跳过 if (rec.name_len != target_len) { continue; } // 内存对比,避免无终止符字符串的安全问题 if (memcmp(target_name, rec.name, target_len) == 0) { fclose(fp); return 1; } } fclose(fp); return 0; } // 测试入口 int main(int argc, char *argv[]) { if (argc != 3) { fprintf(stderr, "Usage: %s <dat_file> <target_name>\n", argv[0]); return 1; } int result = has_name(argv[1], argv[2]); printf("Name '%s' %s in the file.\n", argv[2], result ? "exists" : "does NOT exist"); return 0; }
关键注意事项
- 禁止使用strcmp:记录的
name字段无终止符,直接用strcmp会读取内存中多余数据,引发未定义行为,必须用memcmp结合name_len - 二进制模式打开:Windows系统下必须用
"rb"模式打开,避免换行符转换破坏二进制记录结构 - 异常处理:需处理文件打开失败、读取中断、文件格式损坏等场景,避免程序崩溃
- 字节序无关:本次匹配逻辑不涉及
suncents字段,无需处理x86-64的小端序问题;若后续处理金额字段则需注意
内容的提问来源于stack exchange,提问作者Catherine LU
相关产品推荐
相关产品推荐

