2016-02-13 4 views
1

У меня возникли некоторые проблемы с inttypes, проиллюстрированные здесь этот крошечный образец кода:Несогласованность с inttypes.h, fscanf(), fprintf()

#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 

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

00001000 
8 100 200 
8 100 200 
00001000 

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

+0

Эта проблема также возникает, если я использую '«% HHU% ху% ху»' везде. – user3618511

+0

Функции 'scan'ner являются сложными животными. Вы хотите проверить результат, который они возвращают. – alk

+0

Также сбросьте три тестовые переменные до 0 перед чтением и получите просвещенные ... ;-) – alk

ответ

5

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

8100200 

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

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

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

[fscanf это] предполагается прочитать значение 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); 
+0

Я действительно не понимаю вас здесь. Зачем нужен разделитель? Он должен был прочитать значение в 1 байт, а затем два 2 байта. – user3618511

+0

@ user3618511: Что бы вы ожидали, что код будет читаться с помощью 'bs = 1; bw = 2; bh = 3'? – alk

+0

Ну, что я написал: 1 2 и 3. – user3618511