首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >六转储输出与xxd输出

六转储输出与xxd输出
EN

Stack Overflow用户
提问于 2014-10-10 14:01:39
回答 1查看 3.6K关注 0票数 0

我正在尝试创建一个像xxd这样的十六进制,但是有一些不同之处我正在试图解决。目前,该程序每行处理10个字符,如在xxd中最右边列vs16中看到的那样。它也只显示每列一个八进制,而不是两个八进制对。

xxd

代码语言:javascript
复制
 0000000: 2369 6e63 6c75 6465 203c 7374 6469 6f2e  #include <stdio.

我的输出

代码语言:javascript
复制
 0:  23 69 6E 63 6C 75 64 65 20 3C  #include <     

编辑:

为了补充一些澄清,我试图实现两件事。1)我希望这个程序输出与xxd完全相同的。为此,它需要输出32个十六进制数(8x列为4)。2)我还希望程序在4行的列中列出十六进制数,类似于xxd。

我试着将下面源代码中的"10“编辑成类似于"12”的内容,但是它会在输出中产生错误,它似乎是一个幻数

来源:

代码语言:javascript
复制
 #include <stdio.h>    
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
 #include <ctype.h>

 #define BYTE_OFFSET_INIT 8
 #define CHAR_OFFSET_INT  39
 #define LINE_LENGTH 50

 static void print_e(int e, char *program, char *file)
 {
   fprintf(stderr, "%s: %s: %s\n", program, file, strerror(e));
 }
 static void print_line(char *line)
 {
   int i;  
 /* sprintf leaves terminators mid-line, so clear them out so we can print the full line */
   for (i = BYTE_OFFSET_INIT; i < CHAR_OFFSET_INT; i++)
     if (line[i] == '\0')
       line[i] = ' ';
   printf("%s\n", line);
 }

 int main(int argc, char *argv[])
 {
   char line[LINE_LENGTH + 1];

   int ch;
   int character = 0;
   int line_offset = 0;
   int byte_offset = BYTE_OFFSET_INIT, char_offset = CHAR_OFFSET_INT;

   if (argc != 2) {
     fprintf(stderr, "Usage: %s [file]\n", argv[0]);
     exit(EXIT_FAILURE);
   }
   FILE *fp = fopen(argv[1], "rb");
   if (!fp) {
     print_e(errno, argv[0], argv[1]);
     exit(EXIT_FAILURE);
   }

   printf("Offset              Bytes              Characters\n");
   printf("------  -----------------------------  ----------\n");

   while ((ch = fgetc(fp)) != EOF) {
     if (character == 0) {
       sprintf(line, "%6d  ", line_offset);
       line_offset += 10;
     }
     sprintf(line + byte_offset, "%02X ", ch);
     sprintf(line + char_offset, "%c", isprint(ch) ? ch : '.');
     character++;
     char_offset++;
     byte_offset += 3;

     if (character == 10) {
       print_line(line);
       character = 0;
       char_offset = CHAR_OFFSET_INT;
       byte_offset = BYTE_OFFSET_INIT;
     }
   }
   if (ferror(fp)) {
     print_e(errno, argv[0], argv[1]);
     exit(EXIT_FAILURE);
   }

   if (character > 0)
     print_line(line);

   if (fclose(fp) == EOF) {
     print_e(errno, argv[0], argv[1]);
     exit(EXIT_FAILURE);
   }
   return 0;
 }
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-10-11 23:57:41

虽然一次扫描一个字节并以正确的位置将其写入输出字符串是可能的,但这是不必要的。一次读取DISPLAY_LENGTH字节和两次循环读取字节数要容易得多;首先输出十六进制表示,然后再输出ASCII字符。唯一(次要的)警告是在文件末尾要做什么;但是由于fread返回字符的数量,所以您可以在必要的时间内继续计数和输出空格,以填充十六进制行。

这将导致下面的程序。DISPLAY_LENGTH是每一行显示的总字节数,GROUP_BYTES是每个十六进制组中的单个字节数(将其设置为1将显示一个“常规”的十六进制输出,2将按您的xxd示例进行分组,更高的值也可以使用)。

我有一些乐趣,找出魔术公式,以正确地居中文本Bytes和计算多少破折号显示为分隔符。其余的都很简单。

我不知道xxd输出是什么样子,除了您的一行示例外,所以我使用stat提前读出文件的长度(增加了一个机会显示“不是文件”的错误--例如,用一个文件夹),并显示正确的破折号和空格来排列行计数器。我将这个值设置为最小值6,所以文本Offset总是有空间的。

如果您的编译器不是现代编译器,它可能会抱怨%zu格式字符串。如果是这样的话,请使用%lu;您还可能需要将所有出现的size_t更改为unsigned long

代码语言:javascript
复制
#include <stdio.h>    
#include <stdlib.h>
#include <sys/stat.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>

#define DISPLAY_LENGTH  21
#define GROUP_BYTES     2

static void print_e(int e, char *program, char *file)
{
    fprintf(stderr, "%s: %s: %s\n", program, file, strerror(e));
}

int main(int argc, char *argv[])
{
    size_t i;
    struct stat fs;
    int n_digit;
    unsigned char read_buf[DISPLAY_LENGTH];
    size_t bytes_read, cpos = 0;

    if (argc != 2)
    {
        fprintf(stderr, "Usage: %s [file]\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    FILE *fp = fopen(argv[1], "rb");
    if (!fp)
    {
        print_e (errno, argv[0], argv[1]);
        exit(EXIT_FAILURE);
    }

    if (stat(argv[1], &fs) == -1)
    {
        print_e (errno, argv[0], argv[1]);
        exit(EXIT_FAILURE);
    }

    if ((fs.st_mode & S_IFMT) != S_IFREG)   /* regular file */
    {
        fprintf(stderr, "Not a regular file: %s\n", argv[1]);
        exit(EXIT_FAILURE);
    }

    n_digit = 0;
    while (fs.st_size > 0)
    {
        fs.st_size /= 10;
        n_digit++;
    }
    if (n_digit < 6)
        n_digit = 6;

    printf("%*s  ", n_digit, "Offset");
    printf("%*s%-*s", ((2*DISPLAY_LENGTH+(DISPLAY_LENGTH+GROUP_BYTES-1)/GROUP_BYTES)+2)/2, "Bytes", ((2*DISPLAY_LENGTH+(DISPLAY_LENGTH+GROUP_BYTES-1)/GROUP_BYTES)+2-5)/2, "");
    printf ("  Characters\n");
    for (i=0; i<n_digit; i++)
        printf ("-");

    printf("  ");

    for (i=1; i<2*DISPLAY_LENGTH+(DISPLAY_LENGTH+GROUP_BYTES-1)/GROUP_BYTES; i++)
        printf ("-");
    printf ("  ");

    for (i=0; i<DISPLAY_LENGTH; i++)
        printf ("-");
    printf ("\n");

    while ( (bytes_read = fread (read_buf, 1, DISPLAY_LENGTH, fp)))
    {
        printf ("%*zu ", n_digit, cpos);

        for (i=0; i<bytes_read; i++)
        {
            if (!(i % GROUP_BYTES))
                printf (" ");
            printf ("%02X", read_buf[i]);
        }
        while (i < DISPLAY_LENGTH)
        {
            if (!(i % GROUP_BYTES))
                printf (" ");
            printf ("  ");
            i++;
        }

        printf ("  ");

        for (i=0; i<bytes_read; i++)
            printf ("%c", isprint(read_buf[i]) ? read_buf[i] : '.');

        printf ("\n");

        cpos += bytes_read;
    }
    if (ferror(fp))
    {
        print_e (errno, argv[0], argv[1]);
        exit(EXIT_FAILURE);
    }

    if (fclose(fp))
    {
        print_e (errno, argv[0], argv[1]);
        exit(EXIT_FAILURE);
    }
    return 0;
}

示例输出,显示自己编译的可执行文件,显示长度为21,每2个字节分组:

代码语言:javascript
复制
Offset                        Bytes                           Characters
------  ----------------------------------------------------  ---------------------
     0  CFFA EDFE 0700 0001 0300 0080 0200 0000 0D00 0000 70  ....................p
    21  0600 0085 0020 0000 0000 0019 0000 0048 0000 005F 5F  ..... .........H...__
    42  5041 4745 5A45 524F 0000 0000 0000 0000 0000 0000 00  PAGEZERO.............
... (673 very similar lines omitted) ...
 14196  7075 7473 005F 7374 6174 2449 4E4F 4445 3634 005F 73  puts._stat$INODE64._s
 14217  7472 6572 726F 7200 6479 6C64 5F73 7475 625F 6269 6E  trerror.dyld_stub_bin
 14238  6465 7200 0000                                        der...
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26301273

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档