C ++での16進数文字列への整数


127

C ++で整数を16進文字列に変換するにはどうすればよいですか?

私はそれを行う方法をいくつか見つけることができますが、それらは主にCをターゲットにしているようです。C++でそれを行うネイティブな方法はないようです。ただし、これはかなり単純な問題です。私が持っているint私は、後で印刷するために16進数文字列に変換したいのですがどれを。

回答:


225

使用<iomanip>std::hex。印刷する場合は、に送信してください。送信しstd::coutない場合は、std::stringstream

std::stringstream stream;
stream << std::hex << your_int;
std::string result( stream.str() );

最初を付加することができます<<<< "0x"、またはあなたが望むならば何でもあなたが好きです。

関心のある他のマニピュレータはstd::oct(8進数)とstd::dec(10進数に戻る)です。

あなたが遭遇するかもしれない一つの問題は、これがそれを表すのに必要な正確な桁数を生み出すという事実です。あなたはこれを使用setfillsetwて問題を回避することができます:

stream << std::setfill ('0') << std::setw(sizeof(your_type)*2) 
       << std::hex << your_int;

最後に、私はそのような関数を提案します:

template< typename T >
std::string int_to_hex( T i )
{
  std::stringstream stream;
  stream << "0x" 
         << std::setfill ('0') << std::setw(sizeof(T)*2) 
         << std::hex << i;
  return stream.str();
}

7
@MSalters-まったく逆です。intタイプに関する提案をテストしてください;)
Kornel Kisielewicz

2
@LexFridman、必要に応じて16進数を正確に出力します。タイプがuint8_tである場合、なぜ8桁を出力するのですか?
Kornel Kisielewicz

15
警告:charは常にcharとして脅かされるため、これは1バイトでは機能しません
ov7a

5
#include <sstream>も必要です
David Gausmann、2018

2
私は複数のint型をフォーマットしていた場合、と思われるstd::setwのに対し、ニーズは、すべてのint型のためのストリームに出力するstd::hexstd::setfillstd::uppercase、...一度だけ出力ストリームに送信する必要があります。これは矛盾していますか?
wcochran

39

軽くて速くするには、文字列を直接埋めることをお勧めします。

template <typename I> std::string n2hexstr(I w, size_t hex_len = sizeof(I)<<1) {
    static const char* digits = "0123456789ABCDEF";
    std::string rc(hex_len,'0');
    for (size_t i=0, j=(hex_len-1)*4 ; i<hex_len; ++i,j-=4)
        rc[i] = digits[(w>>j) & 0x0f];
    return rc;
}

これはどのタイプでも機能しますか?double、float、uint8_tも意味しますか?
SR

@SRこれは、整数型ではなくdoublefloat(およびポインタではない)で機能します
Wolf

... CとC ++の非常に実用的な(しかし有効な)混合です。速度についてはわかりません... 私の好みでは、少し密度が高くなっています。
ウルフ

素晴らしい回答ありがとうございます。これを行うために「ただ」ストリームライブラリを取り込むことは、このような無駄なことのようです。
DeveloperChris

1
これはに印刷さ0000FFFF0xFFFFます。0xFFFF出力として持つことを好みます。
DrumM

24

std::stringstream整数を文字列に変換し、その特別なマニピュレータをベースを設定するために使用します。例えばそのように:

std::stringstream sstream;
sstream << std::hex << my_integer;
std::string result = sstream.str();

14

16進数として出力するだけです。

int i = /* ... */;
std::cout << std::hex << i;

8
私はを使用しますstd::cout<<std::hex<<i<<std::dec;。そうしないと、後でストリーミングされる整数はすべて16進数になります。stringstreamストリームは使用後に破棄されますが、cout永遠に存続するため、使用する他の回答についてはこれを行う必要はありません。
Mark Lakata

8

以下を試すことができます。それは働いています...

#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
using namespace std;

template <class T>
string to_string(T t, ios_base & (*f)(ios_base&))
{
  ostringstream oss;
  oss << f << t;
  return oss.str();
}

int main ()
{
  cout<<to_string<long>(123456, hex)<<endl;
  system("PAUSE");
  return 0;
}

1
良い答えですが、C ++ 11のto_string名前空間の一部であることに注意してくださいstd
Alex

@Alexはい、結局のところ2014年です...すぐにC ++ 14への対応を開始する必要があることを禁じます。
アレックス

7

この質問は古いですが、なぜ誰も言及しなかったのには驚いていboost::formatます:

cout << (boost::format("%x") % 1234).str();  // output is: 4d2

4
int num = 30;
std::cout << std::hex << num << endl; // This should give you hexa- decimal of 30

4

以下のリンカーンのコメントのおかげで、私はこの答えを変更しました。

次の回答は、コンパイル時に8ビット整数を適切に処理します。ただし、C ++ 17が必要です。C ++ 17がない場合は、何か他のことを行う必要があります(たとえば、この関数のオーバーロードを1つはuint8_tに、もう1つはint8_tに提供するか、「if constexpr」以外の何かを使用します。おそらくenable_if)。

template< typename T >
std::string int_to_hex( T i )
{
    // Ensure this function is called with a template parameter that makes sense. Note: static_assert is only available in C++11 and higher.
    static_assert(std::is_integral<T>::value, "Template argument 'T' must be a fundamental integer type (e.g. int, short, etc..).");

    std::stringstream stream;
    stream << "0x" << std::setfill ('0') << std::setw(sizeof(T)*2) << std::hex;

    // If T is an 8-bit integer type (e.g. uint8_t or int8_t) it will be 
    // treated as an ASCII code, giving the wrong result. So we use C++17's
    // "if constexpr" to have the compiler decides at compile-time if it's 
    // converting an 8-bit int or not.
    if constexpr (std::is_same_v<std::uint8_t, T>)
    {        
        // Unsigned 8-bit unsigned int type. Cast to int (thanks Lincoln) to 
        // avoid ASCII code interpretation of the int. The number of hex digits 
        // in the  returned string will still be two, which is correct for 8 bits, 
        // because of the 'sizeof(T)' above.
        stream << static_cast<int>(i);
    }        
    else if (std::is_same_v<std::int8_t, T>)
    {
        // For 8-bit signed int, same as above, except we must first cast to unsigned 
        // int, because values above 127d (0x7f) in the int will cause further issues.
        // if we cast directly to int.
        stream << static_cast<int>(static_cast<uint8_t>(i));
    }
    else
    {
        // No cast needed for ints wider than 8 bits.
        stream << i;
    }

    return stream.str();
}

私が思ったように8ビット整数を正しく処理しない元の答え:

Kornel Kisielewiczの答えは素晴らしい。しかし、少し追加するだけで、意味のないテンプレート引数(例:float)を使用してこの関数を呼び出す場合や、面倒なコンパイラエラー(例:ユーザー定義型)が発生する場合を見つけることができます。

template< typename T >
std::string int_to_hex( T i )
{
  // Ensure this function is called with a template parameter that makes sense. Note: static_assert is only available in C++11 and higher.
  static_assert(std::is_integral<T>::value, "Template argument 'T' must be a fundamental integer type (e.g. int, short, etc..).");

  std::stringstream stream;
  stream << "0x" 
         << std::setfill ('0') << std::setw(sizeof(T)*2) 
         << std::hex << i;

         // Optional: replace above line with this to handle 8-bit integers.
         // << std::hex << std::to_string(i);

  return stream.str();
}

これを編集してstd :: to_stringへの呼び出しを追加しました。8ビット整数型(std::uint8_t渡される値など)std::stringstreamはcharとして扱われるため、期待どおりの結果が得られないためです。そのような整数を渡すstd::to_stringそれらを正しく処理し、他のより大きな整数型を使用しても問題はありません。もちろん、std :: to_stringの呼び出しが不要なため、これらのケースではパフォーマンスがわずかに低下する可能性があります。

注:元の回答のコメントにこれを追加しただけですが、コメントする担当者がいません。


私のテストでは、std :: to_string(i)はstd :: uint8_t整数を16進数として出力しません。これは、uint8_t型とint8_t型の両方に大きな条件にキャストする必要があるため、これらには別々の条件が必要になる可能性があると思います。
リンカーン

1
@リンカーンあなたは正しいです。to_stringが8ビットの整数を処理するようになった当時(今から数か月前)に何をしていたのかわかりません。当時使用していたと思われるコンパイラーのバージョンに戻ってもう一度確認しましたが、to_stringは私が言ったように機能しませんでした。だから誰が知っていますか?とにかく、これをキャッチしてくれてありがとう-私は正しく動作するはずのものの答えを編集しました。
喪失の

1
これはまだ予期せず機能しますchar(これは、両方uint8_tとは異なりint8_t、ほとんどの実装では(それぞれunsigned char、およびsigned char)です)。
ルスラン

@ruslanはい、boolおよびワイドchar型もすべてstd :: is_integralに一致し、アサートに失敗しません。しかし、charはstd。ごとに保証された一意の型であり、ワイドchar型と同様に、必要に応じてそれらすべてを処理できます(例外はun / signed charであり、これはあらゆる幅のun / signed整数型と一致しますaバイトは現在のマシン(通常はint8)にあるため、同じ幅のintにも一致させる場合はフィルターできません)。:あなたはstatic_assertに複数の用語を追加することによって、文字、ワイド文字、boolsを拒否することができる... && !std::is_same_v<char, T> && !std::is_same_v<bool, T>...など
損失の考え方を

2

Kornelが以前に投稿したテンプレートのアイデアのように、多くの/ほとんどがまだios::fmtflags機能しstd::stringstreamないことに気付いた方は、次のように動作し、比較的クリーンです。

#include <iomanip>
#include <sstream>


template< typename T >
std::string hexify(T i)
{
    std::stringbuf buf;
    std::ostream os(&buf);


    os << "0x" << std::setfill('0') << std::setw(sizeof(T) * 2)
       << std::hex << i;

    return buf.str().c_str();
}


int someNumber = 314159265;
std::string hexified = hexify< int >(someNumber);

9
単にbuf.str()を返すべきではありませんか?
ruipacheco 2016年

2

私がやります:

int hex = 10;      
std::string hexstring = stringFormat("%X", hex);  

見てくださいSOをここからiFreilichtと必要なテンプレートのヘッダー・ファイルからの回答をGIST


2

プロジェクトから逐語的にコピーした私のソリューション[1]を見てください。ドイツ語のAPIドキュメントが含まれています。私の目標は、実際のニーズに合わせて柔軟性と安全性を組み合わせることでした:[2]

  • 0x接頭辞が追加されていません:発信者が決定できます
  • 自動幅控除:タイピングを減らす
  • 明示的な幅の制御:書式設定の拡大、スペースを節約するための(可逆)縮小
  • 対処することができる long long
  • 整数型に制限:サイレント変換による驚きを回避
  • 理解しやすさ
  • ハードコードされた制限なし
#include <string>
#include <sstream>
#include <iomanip>

/// Vertextet einen Ganzzahlwert val im Hexadezimalformat.
/// Auf die Minimal-Breite width wird mit führenden Nullen aufgefüllt;
/// falls nicht angegeben, wird diese Breite aus dem Typ des Arguments
/// abgeleitet. Funktion geeignet von char bis long long.
/// Zeiger, Fließkommazahlen u.ä. werden nicht unterstützt, ihre
/// Übergabe führt zu einem (beabsichtigten!) Compilerfehler.
/// Grundlagen aus: http://stackoverflow.com/a/5100745/2932052
template <typename T>
inline std::string int_to_hex(T val, size_t width=sizeof(T)*2)
{
    std::stringstream ss;
    ss << std::setfill('0') << std::setw(width) << std::hex << (val|0);
    return ss.str();
}

[1] Kornel Kisielewicz の回答に基づく
[2] CppTestの言語に翻訳すると、次のようになります。

TEST_ASSERT(int_to_hex(char(0x12)) == "12");
TEST_ASSERT(int_to_hex(short(0x1234)) == "1234");
TEST_ASSERT(int_to_hex(long(0x12345678)) == "12345678");
TEST_ASSERT(int_to_hex((long long)(0x123456789abcdef0)) == "123456789abcdef0");
TEST_ASSERT(int_to_hex(0x123, 1) == "123");
TEST_ASSERT(int_to_hex(0x123, 8) == "00000123");
// with deduction test as suggested by Lightness Races in Orbit:
TEST_ASSERT(int_to_hex(short(0x12)) == "0012"); 

1
たとえば、幅の控除をTEST_ASSERT(int_to_hex(short(0x12)) == "0012");
自慢

2

参照用のコード:

#include <iomanip>
#include <sstream>
...
string intToHexString(int intValue) {

    string hexStr;

    /// integer value to hex-string
    std::stringstream sstream;
    sstream << "0x"
            << std::setfill ('0') << std::setw(2)
    << std::hex << (int)intValue;

    hexStr= sstream.str();
    sstream.clear();    //clears out the stream-string

    return hexStr;
}

4
これは実際に既存の回答に追加されるわけではありません。明示的clearsstreamそれをしても意味がありません(関数が次の行に戻ったときに破棄されます)。名前を付けることをhexStr完全に回避することができ、同じ効果を得ることができます。4行のコードを1行に減らします。return sstream.str();clear
ShadowRanger 2016

1
フォーラムの目的が物事と使い方を理解することである場合。冗長であることは、ラインを保存することよりも、明確な画像を提供するためにはるかに優れています。質問は最適化されたコードではなく、回答はそのような変換を処理するモジュール方式の方法を提供しようとします。@ShadowRanger
Parasrish

1
の目的はsstream.clear();何ですか?sstreamオブジェクトは、自動的にスコープの終わりに破壊されるので、return sstream.str();それを行うだろう。
ウルフ

sstream.clearストリームがスコープの終了で終了する前に、コンテンツをクリアします(failおよびeofフラグをクリアでクリアするため)。実際、ストリーム変数の存続期間とともにスコープが終了すると、sstream.str値によって返されるために使用できます。[参照:cplusplus.com/reference/ios/ios/clear/]
パラリッシュ

2

私の解決策。整数型のみが許可されています。

更新。オプションのプレフィックス0xを2番目のパラメーターに設定できます。

definition.h

#include  <iomanip>
#include <sstream>

template <class T, class T2 = typename std::enable_if<std::is_integral<T>::value>::type>
static std::string ToHex(const T & data, bool addPrefix = true);



template<class T, class>
inline std::string Convert::ToHex(const T & data, bool addPrefix)
{
    std::stringstream sstream;
    sstream << std::hex;
    std::string ret;
    if (typeid(T) == typeid(char) || typeid(T) == typeid(unsigned char) || sizeof(T)==1)
    {
        sstream << static_cast<int>(data);
        ret = sstream.str();
        if (ret.length() > 2)
        {
            ret = ret.substr(ret.length() - 2, 2);
        }
    }
    else
    {
        sstream << data;
        ret = sstream.str();
    }
    return (addPrefix ? u8"0x" : u8"") + ret;
}

main.cpp

#include <definition.h>
int main()
{
    std::cout << ToHex<unsigned char>(254) << std::endl;
    std::cout << ToHex<char>(-2) << std::endl;
    std::cout << ToHex<int>(-2) << std::endl;
    std::cout << ToHex<long long>(-2) << std::endl;

    std::cout<< std::endl;
    std::cout << ToHex<unsigned char>(254, false) << std::endl;
    std::cout << ToHex<char>(-2, false) << std::endl;
    std::cout << ToHex<int>(-2, false) << std::endl;
    std::cout << ToHex<long long>(-2, false) << std::endl;
    return 0;
}

結果:
0xfe
0xfe
0xfffffffe
0xfffffffffffffffe

fe
fe fffffffe
fffffffffffffffe


1

C ++言語の美しさを楽しむための回答を追加したいと思います。高レベルと低レベルで動作するためのその適応性。幸せなプログラミング。

public:template <class T,class U> U* Int2Hex(T lnumber, U* buffer)
{
    const char* ref = "0123456789ABCDEF";
    T hNibbles = (lnumber >> 4);

    unsigned char* b_lNibbles = (unsigned char*)&lnumber;
    unsigned char* b_hNibbles = (unsigned char*)&hNibbles;

    U* pointer = buffer + (sizeof(lnumber) << 1);

    *pointer = 0;
    do {
        *--pointer = ref[(*b_lNibbles++) & 0xF];
        *--pointer = ref[(*b_hNibbles++) & 0xF];
    } while (pointer > buffer);

    return buffer;
}

例:

char buffer[100] = { 0 };
Int2Hex(305419896ULL, buffer);//returns "0000000012345678"
Int2Hex(305419896UL, buffer);//returns "12345678"
Int2Hex((short)65533, buffer);//returns "FFFD"
Int2Hex((char)18, buffer);//returns "12"

wchar_t buffer[100] = { 0 };
Int2Hex(305419896ULL, buffer);//returns L"0000000012345678"
Int2Hex(305419896UL, buffer);//returns L"12345678"
Int2Hex((short)65533, buffer);//returns L"FFFD"
Int2Hex((char)18, buffer);//returns L"12"

これは、他の回答では見られないいくつかの手法を使用しています。答えを編集して、それがどのようにそしてなぜ機能するかについてのいくつかの説明を含めることができますか?
Jason Aller

0
#include <iostream> 
#include <sstream>  

int main()
{
unsigned int i = 4967295; // random number
std::string str1, str2;
unsigned int u1, u2;

std::stringstream ss;

voidポインターの使用:

// INT to HEX
ss << (void*)i;       // <- FULL hex address using void pointer
ss >> str1;          //     giving address value of one given in decimals.
ss.clear();         // <- Clear bits
// HEX to INT
ss << std::hex << str1;   // <- Capitals doesn't matter so no need to do extra here
ss >> u1;
ss.clear();

0xの追加:

// INT to HEX with 0x
ss << "0x" << (void*)i;   // <- Same as above but adding 0x to beginning
ss >> str2;
ss.clear();
// HEX to INT with 0x
ss << std::hex << str2;   // <- 0x is also understood so need to do extra here
ss >> u2;
ss.clear();

出力:

std::cout << str1 << std::endl; // 004BCB7F
std::cout << u1 << std::endl;   // 4967295
std::cout << std::endl;
std::cout << str2 << std::endl; // 0x004BCB7F
std::cout << u2 << std::endl;   // 4967295


return 0;
}

-1
int var = 20;
cout <<                          &var << endl;
cout <<                     (int)&var << endl;
cout << std::hex << "0x" << (int)&var << endl << std::dec; // output in hex, reset back to dec

0x69fec4(アドレス)
6946500(アドレスからdec)
0x69fec4(アドレスからdec、16進数で出力)


本能的にこれを行った...
int address =(int)&var;

別の場所でこれを見た...
unsigned long address = reinterpret_cast(&var);

コメントはこれが正しいと私に言った...
int address =(int)&var;

よく覆われた 明度といえば、どこにいますか?彼らはあまりにも多くの高評価を得ています!


この質問はすでに十分にカバーされています。あなたの答えはすでに投稿されたものに何を追加しますか?そして、アドレスはそれとどのように関係していますか?
オービットのライトネスレース

@LightnessRacesinOrbit閉まっていませんか?コメントした最後の3人に言った?これは、私が探していたもののポイントに近づきます。それは他の誰かを助けるかもしれません。そして、アドレスはそれとどう関係しているのですか?10進数で住所を読み取るのは誰ですか?それは実際の例です。
水たまり

ほぼ9年前に既に投稿された同じ回答を投稿することは有用であるとは見なされず、この方程式へのポインターの導入は不意に思いついたようです-OPはポインターについて尋ねません。さらに、いや、それはないだろうunsigned longけどstd::intptr_t
オービットのライトネスレース

intptr_t = int ... uintptr_t = unsigned int ...メモリアドレスは現在署名されていますか?そしてintはyaにどれだけのメモリを与えますか?
2018

あなたは要点を逃しています。アンはintptr_t、ビルドプラットフォーム上の任意のポインタを格納することができます。それは[必ずしも]には当てはまりませんunsigned int。そして、再び、これのどれも問題に関連していません。私からこれ以上の返信がありません
軌道上での明度レース
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.