Несоответствие с inttypes.h, fscanf(), fprintf()

У меня есть некоторые проблемы с inttypes, проиллюстрированные здесь этим крошечным примером кода:

#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>


void print_byte(uint8_t b)
{
    printf("%d%d%d%d%d%d%d%d\n",
        !!(b & 128), !!(b & 64), !!(b & 32), !!(b & 16),
        !!(b & 8), !!(b & 4), !!(b & 2), !!(b & 1));
}

int main()
{
    FILE *f;
    uint8_t bs = 8;
    uint16_t bw = 100, bh = 200;
    f = fopen("out", "w+");

    print_byte(bs);
    printf("%"PRIu8" %"PRIu16" %"PRIu16"\n", bs, bw, bh);
    fprintf(f, "%"PRIu8"%"PRIu16"%"PRIu16, bs, bw, bh);
    fclose(f);

    f = fopen("out", "r");

    fscanf(f, "%"SCNu8"%"SCNu16"%"SCNu16, &bs, &bw, &bh);   
    printf("%"PRIu8" %"PRIu16" %"PRIu16"\n", bs, bw, bh);
    print_byte(bs);
    fclose(f);

    return 0;
}

Дает мне

gcc -o test test.c && ./test
00001000
8 100 200
104 100 200
01101000

Если я изменю SCNu8 в SCNo8 в fscanf я получаю то, что должен получить:

00001000
8 100 200
8 100 200
00001000

В чем проблема? Я не понимаю, почему он не работает для первого кода, но работает, когда я интерпретирую этот байт как восьмеричное значение.

1 ответ

Решение

Проблема заключается в том, что значения в вашем текстовом файле в конечном итоге объединяются, например так:

8100200

Вот почему вы не можете прочитать данные обратно правильно: fscanf не знает, где заканчивается первый номер и начинается следующий номер.

Вводить пробелы в fprintf формат строки исправляет эту проблему:

fprintf(f, "%"PRIu8" %"PRIu16" %"PRIu16, bs, bw, bh);

[fscanf is] предполагается прочитать 1 байтовое значение, а затем два 2 байта

fscanf читает текст, а не байты. Если вы хотите записать байты, используйте библиотечные функции для двоичного вывода и ввода, т.е. fwrite а также fread:

// Writing in binary
f = fopen("out.bin", "wb");
fwrite(&bs, sizeof(bs), 1, f);
fwrite(&bw, sizeof(bw), 1, f);
fwrite(&bh, sizeof(bh), 1, f);
fclose(f);
// Reading in binary
f = fopen("out.bin", "rb");
fread(&bs, sizeof(bs), 1, f);
fread(&bw, sizeof(bw), 1, f);
fread(&bh, sizeof(bh), 1, f);
Другие вопросы по тегам