Что касается строк в printf - PullRequest
0 голосов
/ 16 мая 2018

Из этого поста https://stackoverflow.com/a/22059317/5859944

FILE *fileptr;
char *buffer;
long filelen;

fileptr = fopen("myfile.txt", "rb");  // Open the file in binary mode
fseek(fileptr, 0, SEEK_END);          // Jump to the end of the file
filelen = ftell(fileptr);             // Get the current byte offset 
                                         in the file
rewind(fileptr);                      // Jump back to the beginning of 
                                         the file

buffer = (char *)malloc((filelen+1)*sizeof(char)); // Enough memory 
                                                      for file + \0
fread(buffer, filelen, 1, fileptr); // Read in the entire file
fclose(fileptr); // Close the file

Вы читаете файл как байтовый массив.

Как ясно, что это не что иное, как строка. Можно добавить

buffer[filelen] = '\0';

и

printf("%s" , buffer);

должен печатать содержимое файла как строку. И это происходит в простых текстовых файлах, но не в двоичных.

Для двоичных файлов нужно написать функцию следующим образом:

void traverse(char *string ,size_t size){
  for(size_t i=0;i<size;i++)
    printf("%c",string[i]);
}

и печатайте каждый символ по одному. Что ставит тарабарщину на экран.

  • Почему printf не рассматривает buffer как строку символов в двоичных файлах?
  • Почему printf в функции traverse ставит тарабарщину вместо символов?

Что касается второго пункта, то я знаю, что это может быть связано с signed char, но даже если строка хранится как unsigned char, результаты остаются прежними.

Ответы [ 2 ]

0 голосов
/ 16 мая 2018

Почему printf не рассматривает буфер как символьную строку в случае двоичных файлов?

printf("%s",buffer) предполагает , что buffer содержит строку C. Проблема в том, что это не то, что на самом деле содержит buffer. Ваш buffer фактически содержит байты из двоичного файла.

Строка C заканчивается первым нулевым байтом (a.k.a., '\ 0', a.k.a., ASCII NUL), и произвольный нетекстовый файл (a.k.a., "двоичный файл") может содержать ноль байтов в любом месте внутри себя. Формат printf "% s" остановится, как только увидит первый нулевой байт.

Почему printf в функции traverse ставит тарабарщину вместо символов?

Этот "бред" составляет символов. Но символы ничего не значат, потому что файл, который вы пытаетесь интерпретировать как последовательность символов, не должен интерпретироваться таким образом.

Текстовый файл - это последовательность байтов, которые должны отображаться в соответствии с некоторой кодировкой символов и которые обычно предназначены для передачи некоторого вида человекочитаемой информации. Произвольный «двоичный» файл, вероятно, содержит последовательность байтов, которые не должны представлять читаемый человеком текст. Они представляют собой нечто другое, что понимает какая-то компьютерная программа.

printf "%s" пытается отобразить эти байты в соответствии с какой-либо системой кодировки символов (часто либо UTF-8 или US-ASCII ), но (а) он не всегда сможет это сделать, и (б) даже когда он способен сделать это, последовательность символов ничего не будет значить.

0 голосов
/ 16 мая 2018

Первая проблема заключается в том, что вы смешиваете цель чтения файла.Чтобы прочитать двоичные данные из файла и впоследствии распечатать эти двоичные данные, вы всегда должны использовать unsigned char и unsigned char* для хранения данных, считанных из двоичного файла .

Это связано с тем, что для точного отображения этих данных необходимо использовать флаг типа "%u" в строках формата до printf.Только некоторые символы могут быть напечатаны в соответствии с ASCII, а это означает, что если вы захотите увидеть все двоичные данные в вашем файле, вы не сможете увидеть некоторые из них напечатанными, если используете флаг "%c".

Двоичная версия вашей функции будет выглядеть следующим образом:

void traverse(unsigned char *string ,size_t size){
  for(size_t i=0;i<size;i++)
    printf("%u",string[i]);
}

Вторая проблема:

должна печатать содержимое файла как если бы это была строка,И это происходит в простых текстовых файлах, но не в двоичных.

Это не так.При использовании флага "%s" печатаются символы, как если бы они были печатными символами, он завершается, когда достигает нулевого символа \0.Вы не можете эффективно использовать %s для печати двоичных данных.

...