web-dev-qa-db-ja.com

バイトを16進数として印刷するにはどうすればよいですか?

C#ではString.Formatメソッドを使用できることを知っています。しかし、これをC++でどのように行うのですか?バイトを16進数に変換できる関数はありますか?? 8バイトの長さのデータを16進数に変換するだけで、どうすればよいですか?

28
Danny

さて、一度に1バイト(符号なしchar)を配列に変換できます

char buffer [17];
buffer[16] = 0;
for(j = 0; j < 8; j++)
    sprintf(&buffer[2*j], "%02X", data[j]);
30
bentech

C関数ではなくC++ストリームを使用する場合は、次の操作を実行できます。

int ar[] = { 20, 30, 40, 50, 60, 70, 80, 90 };
const int siz_ar = sizeof(ar) / sizeof(int);

for (int i = 0; i < siz_ar; ++i)
    cout << ar[i] << " ";
cout << endl;

for (int i = 0; i < siz_ar; ++i)
    cout << hex << setfill('0') << setw(2) << ar[i] << " ";
cout << endl;

とても簡単です。

出力:

20 30 40 50 60 70 80 90
14 1e 28 32 3c 46 50 5a 
57
Component 10

C:

static void print_buf(const char *title, const unsigned char *buf, size_t buf_len)
{
    size_t i = 0;
    fprintf(stdout, "%s\n", title);
    for(i = 0; i < buf_len; ++i)
    fprintf(stdout, "%02X%s", buf[i],
             ( i + 1 ) % 16 == 0 ? "\r\n" : " " );

}

C++:

void print_bytes(std::ostream& out, const char *title, const unsigned char *data, size_t dataLen, bool format = true) {
    out << title << std::endl;
    out << std::setfill('0');
    for(size_t i = 0; i < dataLen; ++i) {
        out << std::hex << std::setw(2) << (int)data[i];
        if (format) {
            out << (((i + 1) % 16 == 0) ? "\n" : " ");
        }
    }
    out << std::endl;
}
14
user1763487

最新のC++での任意の構造の印刷

これまでのすべての回答は、整数の配列の印刷方法のみを示していますが、サイズがわかっていれば、任意の構造を印刷することもできます。次の例では、このような構造を作成し、バイトを介してポインターを繰り返し、出力に出力します。

#include <iostream>
#include <iomanip>
#include <cstring>

using std::cout;
using std::endl;
using std::hex;
using std::setfill;
using std::setw;

using u64 = unsigned long long;
using u16 = unsigned short;
using f64 = double;

struct Header {
    u16 version;
    u16 msgSize;
};

struct Example {
    Header header;
    u64 someId;
    u64 anotherId;
    bool isFoo;
    bool isBar;
    f64 floatingPointValue;
};

int main () {
    Example example;
    // fill with zeros so padding regions don't contain garbage
    memset(&example, 0, sizeof(Example));
    example.header.version = 5;
    example.header.msgSize = sizeof(Example) - sizeof(Header);
    example.someId = 0x1234;
    example.anotherId = 0x5678;
    example.isFoo = true;
    example.isBar = true;
    example.floatingPointValue = 1.1;

    cout << hex << setfill('0');  // needs to be set only once
    auto *ptr = reinterpret_cast<unsigned char *>(&example);
    for (int i = 0; i < sizeof(Example); i++, ptr++) {
        if (i % sizeof(u64) == 0) {
            cout << endl;
        }
        cout << setw(2) << static_cast<unsigned>(*ptr) << " ";
    }

    return 0;
}

出力は次のとおりです。

05 00 24 00 00 00 00 00 
34 12 00 00 00 00 00 00 
78 56 00 00 00 00 00 00 
01 01 00 00 00 00 00 00 
9a 99 99 99 99 99 f1 3f

この例では memory alignment workingも示しています。 versionが2バイトを占める(05 00)、その後にさらに2バイトのmsgSizeが続きます(24 00)、4バイトのパディング、その後にsomeId34 12 00 00 00 00 00 00)およびanotherId78 56 00 00 00 00 00 00)。次に、isFooが1バイト(01)およびisBar、別のバイト(01)、6バイトのパディングが続き、最後にダブルフィールドfloatingPointValueのIEEE 754標準表現で終わります。

また、すべての値は リトルエンディアン (最下位バイトが最初に来る)として表されることに注意してください。これは、Intelプラットフォームでコンパイルおよび実行されているためです。

4
Lucio Paiva

これはNibble to Hexメソッドの修正バージョンです

void hexArrayToStr(unsigned char* info, unsigned int infoLength, char **buffer) {
    const char* pszNibbleToHex = {"0123456789ABCDEF"};
    int nNibble, i;
    if (infoLength > 0) {
        if (info != NULL) {
            *buffer = (char *) malloc((infoLength * 2) + 1);
            buffer[0][(infoLength * 2)] = 0;
            for (i = 0; i < infoLength; i++) {
                nNibble = info[i] >> 4;
                buffer[0][2 * i] = pszNibbleToHex[nNibble];
                nNibble = info[i] & 0x0F;
                buffer[0][2 * i + 1] = pszNibbleToHex[nNibble];
            }
        } else {
            *buffer = NULL;
        }
    } else {
        *buffer = NULL;
    }
}
3
Mohamed Saad

私はより良い方法を知りません:

unsigned char byData[xxx]; 

int nLength = sizeof(byData) * 2;
char *pBuffer = new char[nLength + 1];
pBuffer[nLength] = 0;
for (int i = 0; i < sizeof(byData); i++)
{
    sprintf(pBuffer[2 * i], "%02X", byData[i]);
}

Nibble to Hexメソッドを使用して速度を上げることができます

unsigned char byData[xxx];

const char szNibbleToHex = { "0123456789ABCDEF" };

int nLength = sizeof(byData) * 2;
char *pBuffer = new char[nLength + 1];
pBuffer[nLength] = 0;
for (int i = 0; i < sizeof(byData); i++)
{
    // divide by 16
    int nNibble = byData[i] >> 4;
    pBuffer[2 * i]  = pszNibbleToHex[nNibble];

    nNibble = byData[i] & 0x0F;
    pBuffer[2 * i + 1]  = pszNibbleToHex[nNibble];

}
2
Rick Murtagh

C++ストリームを使用し、後で状態を復元する

これは バイトを16進数として印刷するにはどうすればよいですか のバリエーションですが、

main.cpp

#include <iomanip>
#include <iostream>

int main() {
    int array[] = {0, 0x8, 0x10, 0x18};
    constexpr size_t size = sizeof(array) / sizeof(array[0]);

    // Sanity check decimal print.
    for (size_t i = 0; i < size; ++i)
        std::cout << array[i] << " ";
    std::cout << std::endl;

    // Hex print and restore default afterwards.
    std::ios cout_state(nullptr);
    cout_state.copyfmt(std::cout);
    std::cout << std::hex << std::setfill('0') << std::setw(2);
    for (size_t i = 0; i < size; ++i)
        std::cout << array[i] << " ";
    std::cout << std::endl;
    std::cout.copyfmt(cout_state);

    // Check that cout state was restored.
    for (size_t i = 0; i < size; ++i)
        std::cout << array[i] << " ";
    std::cout << std::endl;
}

コンパイルして実行します:

g++ -o main.out -std=c++11 main.cpp
./main.out

出力:

0 8 16 24 
00 8 10 18 
0 8 16 24

Ubuntu 16.04、GCC 6.4.0でテスト済み。