[英]Hexdump text and binary files in C
I am writing a code in C performing hexdump in both text and binary files. 我正在用C语言编写文本和二进制文件中的十六进制转储代码。 My output in text files are correct but when I tried performing hexdump in a binary file, I got garbages.
我在文本文件中的输出是正确的,但是当我尝试在二进制文件中执行hexdump时,出现了垃圾。 I would like to ask for your help if which part of my code is wrong and how should I correct my mistakes.
如果我的代码的哪一部分是错误的,我该如何纠正我的错误,我想向您寻求帮助。 Thanks.
谢谢。
#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);
}
You have a couple of errors in logic. 您在逻辑上有两个错误。 First as specified in the comment, all characters are equally important within a binary file.
首先,如注释中所指定,二进制文件中的所有字符都同等重要。 There is no need (and you shouldn't) test
if(buff[i] >= 33 && buff[i] <= 255 || buff[i] != 00)
for your binary output. 不需要(也不应该
if(buff[i] >= 33 && buff[i] <= 255 || buff[i] != 00)
对二进制输出测试if(buff[i] >= 33 && buff[i] <= 255 || buff[i] != 00)
。
The proper declarations for main
are int main (void)
and int main (int argc, char **argv)
(which you will see written with the equivalent char *argv[]
). main
的正确声明是int main (void)
和int main (int argc, char **argv)
(您将看到使用等效的char *argv[]
编写)。 See: C11 Standard §5.1.2.2.1 Program startup p1 (draft n1570) . 请参阅: C11标准§5.1.2.2.1程序启动p1(草稿n1570) 。 See also: See What should main() return in C and C++?
另请参见: 请参见main()在C和C ++中应该返回什么?
Next with your binary output, you are attempting to print an unsigned value with %02x
, but your are passing a signed character. 接下来是二进制输出,您尝试使用
%02x
打印无符号值,但是您正在传递带符号的字符。 If the char
value is negative, you are trying to output the sign-extended value with outputs the full width of the unsigned value ( 02x
will pad the field to 2 characters, but does not prevent more than two characters from printing). 如果
char
值为负,则您尝试输出带符号扩展值,并输出无符号值的完整宽度( 02x
会将字段填充为2个字符,但不会阻止打印两个以上的字符)。 You have a couple of options, first use the hh
length modifier to limit the type to 1-byte, and second simply cast the value to (unsigned char)
, eg 您有两种选择,首先使用
hh
length修饰符将类型限制为1个字节,然后仅将值(unsigned char)
为(unsigned char)
,例如
printf("%02hhx ", (unsigned char)buff[i]);
You logic is also a bit cumbersome. 您的逻辑也有点麻烦。 You should use
if ... else if ... else
to handle your binary cases. 您应该使用
if ... else if ... else
来处理二进制情况。 Further, you are outputting two spaces when either i >= read || buff[i] == 0
此外,当
i >= read || buff[i] == 0
时,您将输出两个空格。 i >= read || buff[i] == 0
, so you may as well combine the test. i >= read || buff[i] == 0
,所以您最好将测试结合起来。
A short rewrite could look something like the following (which will read from the file given as the 1st argument -- or from stdin
if no argument is given) 简短的重写可能类似于以下内容(它将从作为第一个参数给出的文件中读取-如果没有给出参数,则将从
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);
}
(note: if your compiler does not support the hh
prefix, the cast itself will suffice) (注意:如果您的编译器不支持
hh
前缀,则强制转换本身就足够了)
Look things over and let me know if you have further questions. 仔细检查一下,如果您还有其他问题,请告诉我。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.