缓冲区满时用fprintf写入字符与整数异常,求解决方案
我来帮你拆解下这个问题——你现在碰到的是混合字符和整数写入ASCII文件时内容为空且仅一行的问题,先理清楚原代码里的逻辑漏洞,再给你可行的修正方案。
背景回顾
你原本有一个310字节的缓冲区,满负载时写入ASCII文件。纯字符写入的逻辑是正常的:能生成10行、每行31字节的内容(此时buffUsed=10,buffSize=10,actSize=30),对应的代码如下:
if(buffUsed == buffSize) { retOpen = createASCIIFile(); x = 1; for(i =0 ;i<(buffUsed*(actSize+1));i++) { if(i==(x*31)) { fprintf(fPtr,"\n"); x++; } fprintf(fPtr,"%c",buffer[i]); } }
但当缓冲区同时包含字符和整数时,修改后的代码执行后文件内容为空且仅一行,有问题的代码如下:
if(buffUsed == buffSize) { retOpen = createASCIIFile(); x = 1; for(i =0 ;i<(buffUsed*(actSize+1));i++) { for(i =i ;i<(buffUsed*(actSize+1));i++) { if(i==x*(actSize+1)) { fprintf(fPtr,"\n"); x++; } for(j=i+((buffUsed-1)*(actSize+1)); j<19+((buffUsed-1)*(actSize+1));j++) { fprintf(fPtr,"%c",buffer[j]); } for(k=j;k<23+((buffUsed-1)*(actSize+1));k++) { fprintf(fPtr,"%d",buffer[k]); } for(l=k;l<(actSize+1)+((buffUsed-1)*(actSize+1));l++) { fprintf(fPtr,"%d",buffer[l]); } i=l-1; } } retOpen = closeFile(); fileRename(); }
问题根源分析
- 循环变量被恶意覆盖:外层
for循环的i被内层for(i=i;...)直接重写,导致外层循环逻辑完全混乱,大概率跳过了所有有效写入步骤。 - 缓冲区索引计算错误:比如
j=i+((buffUsed-1)*(actSize+1))这个偏移量是9*31=279,直接跳到缓冲区末尾附近,访问的是无效内存区域,写入内容自然异常。 - 整数处理逻辑错误:原代码用
%d输出单个字节的buffer[k],这会把字节的ASCII值当成整数输出(比如字符'A'(0x41)会输出"65"),如果你的需求是把二进制整数转换成数字字符串,这个逻辑完全不对。 - 缺乏文件打开检查:如果
createASCIIFile()失败,fPtr为NULL,写入操作会静默失败,直接生成空文件。
修正后的解决方案
假设你的每行数据结构是:前19字节为字符,接下来4字节为一个32位整数,最后8字节为其他整数(按原代码循环范围推导),以下是修正后的代码:
#include <stdint.h> // 用于固定宽度整数类型 if(buffUsed == buffSize) { retOpen = createASCIIFile(); // 必须检查文件是否成功打开,避免空文件 if (!retOpen || fPtr == NULL) { // 这里可以加错误日志或处理逻辑 return; } int totalLines = buffUsed; // 总共10行 int lineByteCount = actSize + 1; // 每行31字节 for(int lineIdx = 0; lineIdx < totalLines; lineIdx++) { int lineStart = lineIdx * lineByteCount; // 当前行的起始索引 // 1. 写入前19个字符 for(int j = lineStart; j < lineStart + 19; j++) { fprintf(fPtr, "%c", buffer[j]); } // 2. 读取并写入接下来4字节的32位整数(假设小端存储) int32_t targetInt = *(int32_t*)(buffer + lineStart + 19); fprintf(fPtr, "%d", targetInt); // 如果需要固定宽度对齐,可以用 %8d 这样的格式化符 // 3. 写入最后8字节的内容:如果是单个字节转整数输出 for(int l = lineStart + 23; l < lineStart + lineByteCount; l++) { uint8_t byteVal = buffer[l]; fprintf(fPtr, "%d", byteVal); // 若需要分隔符,可改为 fprintf(fPtr, "%d ", byteVal); } // 4. 每行结束换行 fprintf(fPtr, "\n"); } retOpen = closeFile(); fileRename(); }
关键修复点说明
- 重构循环逻辑:去掉嵌套覆盖
i的错误,改用按行遍历的方式,每行计算起始索引,逻辑清晰且不会出现变量冲突。 - 正确处理整数转换:通过指针转换读取整个二进制整数(比如
int32_t),而不是逐个字节输出ASCII值,符合“写入整数”的需求。 - 增加错误检查:确保文件打开成功后再执行写入,避免空文件问题。
- 明确缓冲区边界:所有索引计算都基于当前行的起始位置,不会越界访问无效内存。
额外注意事项
- 如果你的整数是大端存储或64位类型,需要调整指针类型(比如
int64_t)或手动处理字节序。 - 若要让整数输出更规范(比如固定宽度、补零),可以调整
fprintf的格式化符(比如%08d表示8位宽度补零)。
内容的提问来源于stack exchange,提问作者user8540390
相关产品推荐
相关产品推荐

