You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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的后续使用逻辑上:

  1. strtok_s在循环处理完所有token后,nextToken会指向字符串末尾的'\0',此时strlen(nextToken)为0,导致写入G.bin的字节数为0,文件为空。
  2. strtok_s分割时会将原字符串中的空格替换为'\0',循环结束后nextToken已经丢失了0之后内容的起始位置,无法通过它获取目标内容。
  3. 计算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;
}

关键修改说明

  1. 保存输入副本:用input_copy执行strtok_s分割,保留原输入字符串的完整性,方便后续截取原始内容。
  2. 记录0之后的起始位置:在遇到0时,将nextToken(即0之后第一个token的起始地址)存入after_zero_start,确保能直接定位到目标内容。
  3. 正确截取0之前的内容:通过strstr在原输入中查找0的位置,计算从开头到该位置的长度,避免依赖失效的nextToken。
  4. 边界情况处理:考虑0在开头、结尾等特殊场景,防止截取逻辑出错。

内容的提问来源于stack exchange,提问作者Артем Педенко

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 15:36:59