Я пытаюсь создать программу C, которая открывает файл и печатает его байт за байтом, используя формат Hexabyte (% 02x) для каждого байта.
Результат должен быть примерно таким:
$ ./hexabyte file
43
3d
67
...
Я знаю, что хочу использовать для этого fread, но не уверен, почему это решение не работает:
#include<stdlib.h>
#include<stdio.h>
#include<errno.h>
#include<string.h>
int args_test(int args, char path[]){
if (args < 1){
fprintf(stderr, "Usage: %s path\n", path);
exit(EXIT_SUCCESS);
}
if (args < 2){
fprintf(stderr, "Usage: %s path\n", path);
exit(EXIT_SUCCESS);
}
if (args > 2){
fprintf(stderr, "Usage: %s path\n", path);
exit(EXIT_SUCCESS);
}
return 0;
}
int open_file(char path[]){
FILE *fp;
fp = fopen(path, "r");
char buffer[1000];
if (!fp){
fprintf(stderr, "%s\n", strerror(errno));
return EXIT_FAILURE;
}
fseek(fp, 0, SEEK_END);
int len = ftell(fp);
//Why does it not reach this loop?
while (fread(buffer, strlen(path), 1, fp) == 1){
printf("%02x hexabytes\n", len);
}
fclose(fp);
exit(EXIT_SUCCESS);
}
int main(int args, char* argv[]){
if (args < 2 || args > 2){
args_test(args, argv[0]);
}
args_test(args, argv[1]);
open_file(argv[1]);
exit(EXIT_SUCCESS);
}
Кажется, что он никогда не достигает моего цикла while, и поэтому никогда ничего не печатает
Хаха спасибо. Конечно :)
Не рекомендуется выходить из функции, используйте вместо этого возврат
Если вы используете свою функцию, например, библиотека, и она внезапно перестает работать, потому что произошла ошибка, и вы выполняете exit(1), это не ожидаемое поведение. Конечно, это нормально для таких небольших примеров, но это недопустимо для большой (r) кодовой базы.
Отладчик - ваш друг. А за документацию: любой учебник C. Вы не можете научиться программированию, копируя / вставляя фрагменты. Программа - это не лоскутное одеяло.
@hellow: exit в порядке, если вы хотеть для выхода. Речь не о рекомендациях, а о различных функциях.





Вам нужно сбросить указатель файла на начало файла:
fseek(fp, 0, SEEK_SET);
Это помогло. Теперь он не выводит никаких значений, так что мне тоже придется разобраться в этом. Думал, что он должен работать, когда он вошел в цикл. Хм.
@kthonenice, потому что вы печатаете printf("%02x hexabytes\n", len);, а не фактический буфер, который вы читаете
Да, но если я попытаюсь добавить буфер вместо len, мне нужно будет изменить формат с% 02x?
Возьмите, пожалуйста, учебник. Этот сайт предназначен для вопросов специфический о проблемах специфический, а не для обучения. Вы не научитесь C, задавая единичные вопросы, вам нужны основы.
Вы стремитесь к концу файла, поэтому fread нечего будет читать. Вам нужно вернуться к началу.
fread также просят прочитать длину пути, что кажется неправильным, так как ваш цикл настроен для 1 байта за раз.
fseek(fp, 0, SEEK_END); // Seeks to end of file
int len = ftell(fp);
// Nothing to read, at end
while (fread(buffer, strlen(path), 1, fp) == 1){
printf("%02x hexabytes\n", len);
}
Просто снова найдите ftell.
fseek(fp, 0, SEEK_END); // Seeks to end of file
int len = ftell(fp);
fseek(fp, 0, SEEK_SET); // Go to start again
// Read from start, 1 byte at a time
char byte;
while (fread(&byte, 1, 1, fp) == 1){
printf("%02X\n", (int)byte);
}
Вы также можете читать 1000 байт за раз (как ваш buffer), но тогда вам понадобится второй цикл, или вы можете прочитать весь файл, но вам нужно динамически выделить буфер (buffer = malloc(len);).
Спасибо за разъяснения. Теперь я вижу, что мой файл уже был в конце. Интересно, как работает ваш байт char. В примере, который я искал, указан размер, как и в случае с моим начальным буфером, но вы делаете что-то другое, как я вижу. Не совсем уверен, как ваш fread работает по сравнению с моим, но похоже, что ваша реализация работает так, как я предполагал, моя должна!
Цикл читает по одному байту за раз, чтение больших объемов за один раз часто используется для повышения производительности, но тогда для этого вам все равно понадобится 1 printf на байт или для форматирования строки другими способами.
Просто нужно найти базовый синтаксис, чтобы убедиться, что я все понимаю. Но спасибо, что сообщили мне, где я напортачил! Очень признателен!
Даже если вы исправите проблему с fseek, у вас останутся другие проблемы:
while (fread(buffer, strlen(path), 1, fp) == 1){
printf("%02x hexabytes\n", len);
}
Обратите внимание, что вы не читаете по одному байту за раз; вы читаете байты кусками размера strlen(path) за раз.
Вы также не печатаете только что прочитанные байты; вы печатаете длина файла. Предполагая, что размер вашего файла составляет, скажем, 65536 байт, вы получите результат
10000 hexabytes
10000 hexabytes
10000 hexabytes
...
65536 / strlen(path) раза. Не думаю, что ты этого хочешь.
Я думаю, что вы собираетесь сделать что-то в этом роде:
unsigned char buffer[1000]; // for arbitrary bytes, unsigned char works better.
int bytes_read = 0;
while ( (bytes_read = fread( buffer, 1, sizeof buffer, fp )) != EOF )
{
for( int b = 0; b < bytes_read; b++ )
{
printf( "%02hhx\n", buffer[b] ); // %x expects unsigned *int*, use the
} // hh modifier to specify unsigned char
}
Выражение
bytes_read = fread( buffer, 1, sizeof buffer, fp )
считывает до sizeof buffer (в данном случае 1000) байтов из fp и сохраняет фактически прочитанное число в bytes_read. Если мы не попали в EOF, то печатаем содержимое buffer.
if (args < 2 || args > 2)==if (args != 2);)