【问题标题】:Reading file in hex gives wrong output (skips some hex values)以十六进制读取文件会给出错误的输出(跳过一些十六进制值)
【发布时间】:2016-02-28 17:12:01
【问题描述】:

我正在尝试从 Chip8 版本的 Pong 中读取/打印十六进制指令(可以下载 here)。
这是我用来读取 ROM 的代码:

//Open ROM
string dir = "Test/PONG";
ifstream inf(dir.c_str(), ios::binary);

unsigned char input;
for(int i = 0; inf >> input; i++) {
    //Each loop prints 1 bytes
    //New line every 16 bytes and print line number
    if(i%16 == 0) {
        cout << endl;
        cout << setw(7) << setfill('0') << i << " ";
    }
    //2 extra spaces after 8 bytes
    else if(i%8 == 0)
        cout << "  ";
    cout << hex << setw(2) << setfill('0') << (int)input << " ";
}
cout << endl;

这是输出的一部分:

0000000 6a 02 6b 6c 3f 6d a2 ea   da b6 dc d6 6e 00 22 d4  
0000010 66 03 68 02 60 60 f0 15   f0 07 30 00 12 1a c7 17  
0000020 77 08 69 ff a2 f0 d6 71   a2 ea da b6 dc d6 60 01  

...

这是我在终端中运行命令“hexdump -C PONG”得到的我认为正确的输出:

00000000  6a 02 6b 0c 6c 3f 6d 0c  a2 ea da b6 dc d6 6e 00  
00000010  22 d4 66 03 68 02 60 60  f0 15 f0 07 30 00 12 1a  
00000020  c7 17 77 08 69 ff a2 f0  d6 71 a2 ea da b6 dc d6  

...

在十六进制值的第一行,您可以在终端中看到两次值“0c”,但代码的输出会跳过打印“0c”。我不确定为什么我的代码会跳过“0c”。我是否不正确地阅读文件?命令“hexdump”是否提供了错误的输出?我可以改变我阅读文件的方式吗?

编辑:使用 inf.get(input) 能够读取 '0c' 但它也会以不同的方式输出一些十六进制值。
例如:

6a 02 6b 0c 6c 3f 6d 0c ffffffa2 ffffffea ffffffda ffffffb6 ffffffdc ffffffd6 6e 00 22 ffffffd4 66 03 68 02 60 60 fffffff0

编辑2:打印'f',因为一些十六进制值被读取为负数。 所以我做了一个 if 语句来检查输入是否为负数,如果它是负数,我将它乘以 -1,然后打印十六进制值。

编辑 3:我决定使用字符串流仅打印出负十六进制值的最后 2 个字符:

stringstream convert;
if((int)input < 0) {
     convert << hex << (int)input;
     cout << convert.str().substr(6,8) << " ";
     convert.str("");
}

编辑 4:十六进制 '0c' 表示转义序列 '\f',因此在打印时被忽略。使用 inf.get(input) 而不是 inf &gt;&gt; input 将字符作为未格式化的字符存储到输入中(我认为)。但是get() 函数不能将unsigned char 作为参数。所以我必须将输入转换为char&amp;
总之,我不得不将inf &gt;&gt; input 更改为inf.get((char&amp;)input)

来源:http://www.cplusplus.com/reference/istream/istream/get/

【问题讨论】:

  • 也许字符 0c 是换页的 ASCII 这一事实与您的输出有关
  • 我也是这么想的,但是“08”代表退格,但是当从文件中读取“08”时,它仍然显示正确的输出。尽管在这种情况下您可能仍然是对的,但我问:如何强制打印“0c”?来源:en.wikipedia.org/wiki/…
  • 你试过用 inf.get(input) 代替吗?
  • 现在它似乎正在工作,虽然现在输出看起来像这样:6a 02 6b 0c 6c 3f 6d 0c ffffffa2 ffffffea ffffffda。它在一些十六进制值前添加了 6 'f'。
  • 当您在 8 个字节后添加额外的空间时,似乎发生了一些事情。您是否以与发布的内容不同的方式编辑了该程序?

标签: c++ file-io hex emulation hexdump


【解决方案1】:

您使用(signed) int 作为变量。当signed int 为负数并以十六进制打印时,其前面将有一个或多个F 数字。

我强烈建议您使用 unsigned int 作为您的值。

【讨论】:

  • 当我将其设为无符号时,我收到以下错误:没有匹配函数调用 'std::basic_ifstream::get(unsigned char&)' 我不太确定如何修复它。编辑:我读错了你的答案,我以为你想让我输入一个无符号字符。但是,将输入输入 unsigned int 会给我一个类似的错误。
【解决方案2】:

Operator>> 从输入流中读取格式化数据(在您的情况下为 char),因此值为 12(十六进制中的 0c)的 char 被视为 ASCII 换页符并被忽略(将被视为 32 或 0x20 的值空间 )。 Char 也是有符号值,a2 的十六进制值(十进制 162)将存储为负值。将该值提升为 int 将保留符号,并且由于互补,当打印为无符号时,您将获得 ffff。

坚持

unsigned char input;

然后读取值使用

inf.get(static_cast<char>(input))

打印

cout << hex << setw(2) << setfill('0') << static_cast<unsigned int>(input) << " ";

【讨论】:

  • 我尝试将输入转换为无符号整数,但仍在打印“f”。
  • 我认为问题可能是某些十六进制值被读取(或存储)为负数。我使用字符串流做了一个临时解决方案,只打印最后 2 个字符。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-01-26
  • 1970-01-01
  • 2020-10-25
  • 1970-01-01
  • 2012-03-13
  • 2018-07-26
  • 2013-07-07
相关资源
最近更新 更多