基本上,我需要使用 C++ 编写一个十六进制转储实用程序。它看起来像这样
(使用 Visual Studio 的 Word 文档的十六进制转储的一部分)
我想提示用户输入文件名,然后显示十六进制值以及翻译后的 ASCII 字符。我在处理二进制文件方面还是新手,所以如果你能保持简单,那将不胜感激。
基本上,我需要使用 C++ 编写一个十六进制转储实用程序。它看起来像这样
(使用 Visual Studio 的 Word 文档的十六进制转储的一部分)
我想提示用户输入文件名,然后显示十六进制值以及翻译后的 ASCII 字符。我在处理二进制文件方面还是新手,所以如果你能保持简单,那将不胜感激。
对于你的这种问题,我通常不会这样做....但是敲出这样的东西并不需要太多,也许你可以从中吸取教训。这是一个简单的程序,它只是从标准输入和输出中读取,格式与您展示的大致相同。在这里试试。
代码
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
unsigned long address = 0;
cout << hex << setfill('0');
while( cin.good() )
{
int nread;
char buf[16];
for( nread = 0; nread < 16 && cin.get(buf[nread]); nread++ );
if( nread == 0 ) break;
// Show the address
cout << setw(8) << address;
// Show the hex codes
for( int i = 0; i < 16; i++ )
{
if( i % 8 == 0 ) cout << ' ';
if( i < nread )
cout << ' ' << setw(2) << (unsigned int)(unsigned char)buf[i];
else
cout << " ";
}
// Show printable characters
cout << " ";
for( int i = 0; i < nread; i++)
{
if( buf[i] < 32 ) cout << '.';
else cout << buf[i];
}
cout << "\n";
address += 16;
}
return 0;
}
输入
Hello there, this is a test binary file.
What do you think?
.
输出
00000000 48 65 6c 6c 6f 20 74 68 65 72 65 2c 20 74 68 69 Hello there, thi
00000010 73 20 69 73 20 61 20 74 65 73 74 20 62 69 6e 61 s is a test bina
00000020 72 79 20 66 69 6c 65 2e 0a 57 68 61 74 20 64 6f ry file..What do
00000030 20 79 6f 75 20 74 68 69 6e 6b 3f 0a 0a 2e you think?...
#include <iostream>
#include <vector>
#include <iomanip>
#include <numeric>
template<typename byte_type = std::uint8_t, typename container_type = std::vector<std::vector<byte_type>>>
container_type arrange_bytes(const byte_type* buffer, const std::size_t size, const std::size_t w = 16) {
return std::accumulate(buffer, buffer + size, container_type{{}}, [w](auto& acc, const byte_type byte) {
if(acc.back().size() >= w) {
acc.push_back({});
}
acc.back().push_back(byte);
return acc;
});
}
std::string init_text_row(const int offset) {
std::ostringstream ost{};
ost << std::hex << std::setfill('0') << std::setw(8) << offset;
return ost.str();
}
template<typename byte_type = std::uint8_t>
std::string format_row(const std::vector<byte_type>& bytes, const int offset) {
auto init = init_text_row(offset);
return std::accumulate(bytes.begin(), bytes.end(), init, [](auto& acc, const auto& byte) {
std::ostringstream ost{};
ost << ' ' << std::hex << std::setfill('0') << static_cast<unsigned>(byte);
return acc + ost.str();
});
}
template<typename byte_type = std::uint8_t, typename container_type = std::vector<std::vector<byte_type>>>
std::string format_bytes(const container_type& bytes) {
struct memory {
std::string data = {};
int offset = 0;
};
return std::accumulate(bytes.begin(), bytes.end(), memory{}, [](auto& acc, const auto& row) {
acc.data += format_row(row, acc.offset) + '\n';
acc.offset += row.size();
return acc;
}).data;
}
template<typename byte_type = std::uint8_t>
std::string hexdump(const byte_type* buffer, std::size_t size) {
return format_bytes(arrange_bytes(buffer, size));
}
#include <cstring>
int main() {
const auto* message = "Hello, world! I am Simon the Sourcerer and I am a mighty pirate!";
const auto len = std::strlen(message);
std::cout << hexdump(message, len) << std::endl;
return 0;
}