( отредактировано для соответствия hexdump -Cv
выводу)
В тех же строках и продолжая мой комментарий, если вы читаете из входного файла 16-байтовые блоки, вы можете вывести адрес и ваши шестнадцатеричные байты, а затем добавьте разделитель и затем l oop отдельно снова через байты, чтобы обеспечить значения ASCII в качестве правого столбца. Ниже программа принимает имя файла для чтения в качестве первого аргумента (или оно читает из stdin
по умолчанию, если аргумент не указан).
Если указано имя файла, вы также можете указать второй параметр, который обеспечивает символ, который будет использоваться вместо непечатаемых символов в выходных данных ASCII (на самом деле вы должны реализовать getopt
для обработки аргументов - но при желании вы должны это сделать).
Быстрая реализация может быть :
#include <stdio.h>
#define OFFSET 16 /* bytes to display per-line of output */
int main (int argc, char const *argv[])
{
char buff[OFFSET] = "",
sep = argc > 2 ? *argv[2] : '.'; /* default non-print char ',' */
int bytes, /* (add getopt to handle opts) */
address = 0,
i;
/* read from filename provided as 1st argument (stdin by default) */
FILE *fp = argc > 1 ? fopen (argv[1], "rb") : stdin;
if (!fp) { /* validate file open for reading */
perror ("fopen");
return 1;
}
/* read OFFSET number of bytes at a time */
while ((bytes = fread(buff, 1, sizeof buff, fp)) > 0) {
/* print address */
printf("%0*x ", OFFSET / 2, address);
address += OFFSET;
/* print hex values */
for (i = 0; i < OFFSET; i++) {
if (i && i % (OFFSET / 2) == 0) /* additional space between bytes */
putchar (' ');
if (i >= bytes) /* final line where i >= bytes */
fputs (" ", stdout);
else /* output zero-padded hex-byte */
printf("%02hhx ", (unsigned char)buff[i]);
}
fputs (" |", stdout); /* add separator */
/* print ascii values - putchar() outputs a single char */
for (i = 0; i < bytes; i++)
putchar (buff[i] >= ' ' && buff[i] <= '~' ? buff[i] : sep);
puts ("|"); /* add closing '|' and \n */
}
printf("%0*x\n", OFFSET / 2, address); /* output final address */
if (fp != stdin) /* close file if not stdin */
fclose (fp);
}
Пример использования / вывода
$ ./bin/hexdump dat/animals.bin.dat
00000000 01 00 41 62 69 67 61 69 6c 00 00 00 04 00 00 00 |..Abigail.......|
00000010 74 01 00 00 74 01 43 61 70 72 69 63 6f 72 6e 69 |t...t.Capricorni|
00000020 73 20 73 75 6d 61 74 72 61 65 6e 73 69 73 00 00 |s sumatraensis..|
00000030 5c 3f 1b 00 5c 4f 1b 00 5c 53 08 00 02 00 75 6e |\?..\O..\S....un|
00000040 6b 6e 6f 77 6e 00 00 00 04 00 00 00 74 01 00 00 |known.......t...|
...
00000370 73 00 73 69 73 00 00 00 5c 3f 1b 00 5c 4f 1b 00 |s.sis...\?..\O..|
00000380 5c 58 01 00 |\X..|
00000384
С пробелом, предоставленным в качестве второго аргумента в качестве непечатаемого символа для вывода ASCII:
$ ./bin/hexdump dat/animals.bin.dat ' '
00000000 01 00 41 62 69 67 61 69 6c 00 00 00 04 00 00 00 | Abigail |
00000010 74 01 00 00 74 01 43 61 70 72 69 63 6f 72 6e 69 |t t Capricorni|
00000020 73 20 73 75 6d 61 74 72 61 65 6e 73 69 73 00 00 |s sumatraensis |
00000030 5c 3f 1b 00 5c 4f 1b 00 5c 53 08 00 02 00 75 6e |\? \O \S un|
00000040 6b 6e 6f 77 6e 00 00 00 04 00 00 00 74 01 00 00 |known t |
...
00000370 73 00 73 69 73 00 00 00 5c 3f 1b 00 5c 4f 1b 00 |s sis \? \O |
00000380 5c 58 01 00 |\X |
00000384
Сравнение с hexdump -Cv
:
$ hexdump -Cv dat/animals.bin.dat
00000000 01 00 41 62 69 67 61 69 6c 00 00 00 04 00 00 00 |..Abigail.......|
00000010 74 01 00 00 74 01 43 61 70 72 69 63 6f 72 6e 69 |t...t.Capricorni|
00000020 73 20 73 75 6d 61 74 72 61 65 6e 73 69 73 00 00 |s sumatraensis..|
00000030 5c 3f 1b 00 5c 4f 1b 00 5c 53 08 00 02 00 75 6e |\?..\O..\S....un|
00000040 6b 6e 6f 77 6e 00 00 00 04 00 00 00 74 01 00 00 |known.......t...|
...
00000370 73 00 73 69 73 00 00 00 5c 3f 1b 00 5c 4f 1b 00 |s.sis...\?..\O..|
00000380 5c 58 01 00 |\X..|
00000384
Дайте мне знать, если у вас есть дополнительные вопросы.