C++ で整数を16進文字列に変換するにはどうすればよいですか?
私はそれを行ういくつかの方法を見つけることができますが、それらは主にCをターゲットにしているように見えます。C++でネイティブに行う方法はないようです。ただし、これは非常に単純な問題です。 int
があり、後で印刷するために16進数文字列に変換します。
<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進数に戻る)です。
発生する可能性のある問題の1つは、これを表すために必要な正確な桁数を生成するという事実です。 setfill
およびsetw
を使用して、問題を回避できます。
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();
}
軽くて速くするために、文字列を直接埋めることをお勧めします。
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;
}
std::stringstream
を使用して整数を文字列に変換し、その特別なマニピュレーターを使用してベースを設定します。そのような例:
std::stringstream sstream;
sstream << std::hex << my_integer;
std::string result = sstream.str();
16進数として印刷するだけです:
int i = /* ... */;
std::cout << std::hex << i;
以下を試すことができます。それは働いています...
#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;
}
この質問は古いですが、誰もboost::format
に言及していないのには驚いています:
cout << (boost::format("%x") % 1234).str(); // output is: 4d2
int num = 30;
std::cout << std::hex << num << endl; // This should give you hexa- decimal of 30
以下のリンカーンのコメントのおかげで、私はこの答えを変えました。
次の答えは、コンパイル時に8ビット整数を適切に処理します。ただし、C++ 17が必要です。 C++ 17をお持ちでない場合は、何か他のことを行う必要があります(たとえば、この関数のオーバーロード、uint8_tと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の呼び出しを追加しました。これは、std::uint8_t
に8ビット整数型(たとえば、std::stringstream
値が渡される)がcharとして扱われ、希望する結果が得られないためです。このような整数をstd::to_string
に渡すと、それらが正しく処理され、他の大きな整数型を使用するときに問題が発生することはありません。もちろん、これらの場合、std :: to_string呼び出しは不要なので、わずかなパフォーマンスの低下が生じる可能性があります。
注:これを元の回答のコメントに追加するだけでしたが、コメントする担当者がいません。
参考のためのコード:
#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;
}
ios::fmtflags
の多く/ほとんどがstd::stringstream
では機能しないが、Kornelが以前に投稿したテンプレートのアイデアのように、次のように機能し、比較的きれいであることがわかった人には:
#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);
私のソリューションを見てください、[1] 私は自分のプロジェクトからそのままコピーしたので、ドイツ語のAPIドキュメントが含まれています。私の目標は、実際のニーズに合わせて柔軟性と安全性を組み合わせることです。[2]
0x
prefixが追加されました:呼び出し側が決定する場合があります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");
私の解決策。整数型のみが許可されます。
更新 2番目のパラメーターにオプションのプレフィックス0xを設定できます。
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