C语言二进制文件写入异常:G.bin无结果记录排查求助
问题:G.bin文件无内容输出的原因及修复方案
我无法理解为何G.bin文件中没有结果记录,任务要求是将输入行中0之前或之后的部分写入第二个文件,需写入总和更大的那部分。相关代码、键盘输入数据及G.bin预期数据如下:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> int main() { FILE* fa; errno_t err = fopen_s(&fa, "F.bin", "wb"); if (err != 0) { printf("Error opening file F.bin\n"); return 1; } printf("Enter numbers:\n"); int sum_before = 0; int sum_after = 0; int num; int zero_encountered = 0; char input[256]; fgets(input, sizeof(input), stdin); size_t input_length = strlen(input); if (input[input_length - 1] == '\n') { input[input_length - 1] = '\0'; // Видалити символ нового рядка } fwrite(input, sizeof(char), strlen(input), fa); fclose(fa); char* token; char* nextToken = NULL; token = strtok_s(input, " ", &nextToken); while (token != NULL) { num = atoi(token); if (num == 0) { zero_encountered = 1; } if (!zero_encountered) { sum_before += num; } else { sum_after += num; } token = strtok_s(NULL, " ", &nextToken); } FILE* fb; err = fopen_s(&fb, "G.bin", "wb"); if (err != 0) { printf("Error opening file G.bin\n"); return 1; } if (sum_before > sum_after) { size_t part_length = strlen(input) - strlen(nextToken) - 1; // Обчислюємо довжину першої частини fwrite(input, sizeof(char), part_length, fb); } else { fwrite(nextToken, sizeof(char), strlen(nextToken), fb); } fclose(fb); printf("Результат успішно записано у файл G.bin\n"); return 0; }
键盘输入数据:
12 45 78 0 312 545 899
G.bin预期数据:
312 545 899
错误原因分析
问题核心出在对strtok_s的后续使用逻辑上:
strtok_s在循环处理完所有token后,nextToken会指向字符串末尾的'\0',此时strlen(nextToken)为0,导致写入G.bin的字节数为0,文件为空。strtok_s分割时会将原字符串中的空格替换为'\0',循环结束后nextToken已经丢失了0之后内容的起始位置,无法通过它获取目标内容。- 计算0之前部分长度的公式
strlen(input) - strlen(nextToken) -1在循环结束后完全失效,无法得到正确的长度值。
修复方案
需要在遍历token时记录关键位置,同时避免原输入字符串被破坏。修改后的代码如下:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> int main() { FILE* fa; errno_t err = fopen_s(&fa, "F.bin", "wb"); if (err != 0) { printf("Error opening file F.bin\n"); return 1; } printf("Enter numbers:\n"); int sum_before = 0; int sum_after = 0; int num; int zero_encountered = 0; char input[256]; fgets(input, sizeof(input), stdin); size_t input_length = strlen(input); if (input[input_length - 1] == '\n') { input[input_length - 1] = '\0'; // 去除换行符 } // 保存输入副本,避免strtok_s修改原字符串影响后续截取 char input_copy[256]; strcpy(input_copy, input); fwrite(input, sizeof(char), strlen(input), fa); fclose(fa); char* token; char* nextToken = NULL; char* after_zero_start = NULL; // 记录0之后内容的起始位置 token = strtok_s(input_copy, " ", &nextToken); while (token != NULL) { num = atoi(token); if (num == 0) { zero_encountered = 1; // 记录0之后第一个token的起始位置 after_zero_start = nextToken; } if (!zero_encountered) { sum_before += num; } else { sum_after += num; } token = strtok_s(NULL, " ", &nextToken); } FILE* fb; err = fopen_s(&fb, "G.bin", "wb"); if (err != 0) { printf("Error opening file G.bin\n"); return 1; } if (sum_before > sum_after) { // 找到0在原输入中的位置,计算0之前内容的长度 char* zero_pos = strstr(input, " 0 "); if (zero_pos == NULL) { zero_pos = strstr(input, "0 "); // 处理0在开头的情况 if (zero_pos == NULL) zero_pos = strstr(input, " 0"); // 处理0在结尾的情况 } if (zero_pos != NULL) { size_t part_length = zero_pos - input; fwrite(input, sizeof(char), part_length, fb); } } else { // 写入0之后的内容 if (after_zero_start != NULL && strlen(after_zero_start) > 0) { fwrite(after_zero_start, sizeof(char), strlen(after_zero_start), fb); } } fclose(fb); printf("Результат успішно записано у файл G.bin\n"); return 0; }
关键修改说明
- 保存输入副本:用
input_copy执行strtok_s分割,保留原输入字符串的完整性,方便后续截取原始内容。 - 记录0之后的起始位置:在遇到0时,将
nextToken(即0之后第一个token的起始地址)存入after_zero_start,确保能直接定位到目标内容。 - 正确截取0之前的内容:通过
strstr在原输入中查找0的位置,计算从开头到该位置的长度,避免依赖失效的nextToken。 - 边界情况处理:考虑0在开头、结尾等特殊场景,防止截取逻辑出错。
内容的提问来源于stack exchange,提问作者Артем Педенко
相关产品推荐
相关产品推荐

