簡體   English   中英

我將如何在 C++ 中創建一個十六進制轉儲實用程序?

[英]How would I create a hex dump utility in C++?

基本上,我需要使用 C++ 編寫一個十六進制轉儲實用程序。 它看起來像這樣

使用 Visual Studio 的 Word 文檔的十六進制轉儲的一部分

(使用 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;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM