C 中的 Hexdump 文本和二进制文件

Hexdump text and binary files in C

我正在用 C 编写代码,在文本和二进制文件中执行 hexdump。我在文本文件中的输出是正确的,但是当我尝试在二进制文件中执行 hexdump 时,我得到了垃圾。如果我的代码哪一部分错误,我应该如何纠正我的错误,我想请求你的帮助。谢谢

#include <stdio.h>
#define OFFSET 16

main(int argc, char const *argv[]) 
{
    FILE *fp;
    char buff[OFFSET];
    int read;
    int address = 0;
    int i;

    if (argc != 2){
        exit(0);
    }

    fp = fopen(argv[1], "rb");

    while ((read = fread(buff, 1, sizeof buff, fp)) > 0){
        printf("%08x ", address);
        address += OFFSET;

        //print hex values 
        for (i = 0; i < OFFSET; i++){

            if(i >= read){
                buff[i] = 0;
            }
            if(buff[i] >= 33 && buff[i] <= 255 || buff[i] != 00){
                printf("%02x ", buff[i]);
            }
            if(buff[i] == 00){
                printf("   ");
            }
        }

        //print ascii values
        for (i = 0; i < OFFSET; i++) {
            printf("%c", (buff[i] >= 33 && buff[i] <= 255 ? buff[i] : ' '));
        }
        printf("\n");
    }

    fclose(fp);
}

你有几个逻辑错误。首先如评论中所述,所有字符在二进制文件中都同等重要。没有必要(也不应该)为二进制输出测试 if(buff[i] >= 33 && buff[i] <= 255 || buff[i] != 00)

main 的正确声明是 int main (void)int main (int argc, char **argv)(您会看到用等价的 char *argv[] 写的)。参见:C11 Standard §5.1.2.2.1 Program startup p1 (draft n1570). See also: See What should main() return in C and C++?

接下来您的二进制输出,您试图用 %02x 打印一个 unsigned 值,但是您正在传递一个 signed[=44] =] 字符。如果 char 值为负,则您尝试输出 符号扩展 值,输出无符号值的全宽(02x 将填充该字段到 2 个字符,但不会阻止打印两个以上的字符)。您有几个选择,首先使用 hh 长度修饰符将类型限制为 1 字节,然后简单地将值转换为 (unsigned char),例如

            printf("%02hhx ", (unsigned char)buff[i]);

你逻辑也有点繁琐。您应该使用 if ... else if ... else 来处理您的二进制案例。另外,你在i >= read || buff[i] == 0时输出两个空格,所以你不妨结合测试。

简短的重写可能类似于以下内容(它将从作为第一个参数给出的文件中读取——如果没有给出参数,则从 stdin 中读取)

#include <stdio.h>

#define OFFSET 16

int main (int argc, char const *argv[]) 
{
    char buff[OFFSET] = "";
    int read, address = 0, i;
    FILE *fp = argc > 1 ? fopen (argv[1], "rb") : stdin;

    if (!fp) {
        perror ("fopen");
        return 1;
    }

    while ((read = fread(buff, 1, sizeof buff, fp)) > 0) {
        printf("%08x ", address);
        address += OFFSET;

        for (i = 0; i < OFFSET; i++)    /* print hex values */
            if (i >= read || buff[i] == 0)
                printf("   ");
            else
                printf("%02hhx ", (unsigned char)buff[i]);

        fputs ("| ", stdout); /* optional separator before ASCII */

        for (i = 0; i < OFFSET; i++)    /* print ascii values */
            printf("%c", (buff[i] >= ' ' && buff[i] <= '~' ? buff[i] : ' '));
        putchar ('\n'); /* use putchar to output single character */
    }

    if (fp != stdin)
        fclose (fp);
}

(注意:如果您的编译器不支持 hh 前缀,则转换本身就足够了)

检查一下,如果您还有其他问题,请告诉我。