C语言sscanf读取文本转二进制文件时字符串拼接问题求助
问题排查与解决
你的问题核心是缓冲区溢出导致字符串未正确终止,进而出现Codigo与Descripcion字段拼接的现象,主要和结构体字符数组长度、sscanf的使用方式有关,具体排查和修复步骤如下:
1. 核心原因分析
- 若结构体中存储Codigo的字符数组长度刚好等于输入数字串的长度,会没有空间存放C字符串必需的终止符
'\0',输出时会继续读取相邻内存(即Descripcion的起始部分),造成拼接假象。 - 直接使用
%s作为sscanf格式符时,若输入字符串长度超过数组容量,会触发缓冲区溢出,覆盖相邻字段的内存数据。
2. 具体修复步骤
步骤1:修正结构体字符数组长度
确保存储字符串的数组至少比最长输入长度多1,预留终止符位置。比如示例中Codigo是15位数字,数组长度设为16:
typedef struct { char Codigo[16]; // 15位数字 + '\0' float Precio; int Stock; char Descripcion[20]; // 最多19个字符 + '\0' } Producto;
步骤2:限制sscanf的读取长度
在格式符中添加数字限制读取的字符数,避免缓冲区溢出。格式符中的数字需等于对应数组长度减1:
// 读取时限制每个字符串的最大长度 int ret = sscanf(line, "%15s %f %d %19s", prod.Codigo, &prod.Precio, &prod.Stock, prod.Descripcion);
步骤3:验证字段读取完整性
检查sscanf的返回值,确保4个字段都被正确读取,避免因格式错误导致的异常:
if (ret != 4) { fprintf(stderr, "读取行失败: %s", line); continue; }
3. 完整修正示例代码
#include <stdio.h> #include <stdlib.h> typedef struct { char Codigo[16]; float Precio; int Stock; char Descripcion[20]; } Producto; int main() { FILE *txt_file = fopen("datos.txt", "r"); FILE *bin_file = fopen("datos.bin", "wb"); if (!txt_file || !bin_file) { perror("打开文件失败"); return 1; } char line[100]; Producto prod; while (fgets(line, sizeof(line), txt_file)) { int ret = sscanf(line, "%15s %f %d %19s", prod.Codigo, &prod.Precio, &prod.Stock, prod.Descripcion); if (ret != 4) { fprintf(stderr, "无效行: %s", line); continue; } fwrite(&prod, sizeof(Producto), 1, bin_file); } fclose(txt_file); fclose(bin_file); // 验证二进制文件内容 bin_file = fopen("datos.bin", "rb"); while (fread(&prod, sizeof(Producto), 1, bin_file)) { printf("Codigo: %s | Precio: %.1f | Stock: %d | Descripcion: %s\n", prod.Codigo, prod.Precio, prod.Stock, prod.Descripcion); } fclose(bin_file); return 0; }
内容的提问来源于stack exchange,提问作者Matti Garzia
相关产品推荐
相关产品推荐

