C ++で整数を16進文字列に変換するにはどうすればよいですか?
私はそれを行う方法をいくつか見つけることができますが、それらは主にCをターゲットにしているようです。C++でそれを行うネイティブな方法はないようです。ただし、これはかなり単純な問題です。私が持っているint
私は、後で印刷するために16進数文字列に変換したいのですがどれを。
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進数に戻る)です。
あなたが遭遇するかもしれない一つの問題は、これがそれを表すのに必要な正確な桁数を生み出すという事実です。あなたはこれを使用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();
}
std::setw
のに対し、ニーズは、すべてのint型のためのストリームに出力するstd::hex
、std::setfill
、std::uppercase
、...一度だけ出力ストリームに送信する必要があります。これは矛盾していますか?
軽くて速くするには、文字列を直接埋めることをお勧めします。
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
(およびポインタではない)で機能します
0000FFFF
れ0xFFFF
ます。0xFFFF
出力として持つことを好みます。
16進数として出力するだけです。
int i = /* ... */;
std::cout << std::hex << i;
std::cout<<std::hex<<i<<std::dec;
。そうしないと、後でストリーミングされる整数はすべて16進数になります。stringstream
ストリームは使用後に破棄されますが、cout
永遠に存続するため、使用する他の回答についてはこれを行う必要はありません。
以下を試すことができます。それは働いています...
#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;
}
to_string
名前空間の一部であることに注意してくださいstd
以下のリンカーンのコメントのおかげで、私はこの答えを変更しました。
次の回答は、コンパイル時に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の呼び出しが不要なため、これらのケースではパフォーマンスがわずかに低下する可能性があります。
注:元の回答のコメントにこれを追加しただけですが、コメントする担当者がいません。
char
(これは、両方uint8_t
とは異なりint8_t
、ほとんどの実装では(それぞれunsigned char
、およびsigned char
)です)。
... && !std::is_same_v<char, T> && !std::is_same_v<bool, T>
...など
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);
私がやります:
int hex = 10;
std::string hexstring = stringFormat("%X", hex);
プロジェクトから逐語的にコピーした私のソリューション[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");
TEST_ASSERT(int_to_hex(short(0x12)) == "0012");
参照用のコード:
#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;
}
clear
にsstream
それをしても意味がありません(関数が次の行に戻ったときに破棄されます)。名前を付けることをhexStr
完全に回避することができ、同じ効果を得ることができます。4行のコードを1行に減らします。return sstream.str();
clear
sstream.clear();
何ですか?sstream
オブジェクトは、自動的にスコープの終わりに破壊されるので、return sstream.str();
それを行うだろう。
sstream.clear
ストリームがスコープの終了で終了する前に、コンテンツをクリアします(failおよびeofフラグをクリアでクリアするため)。実際、ストリーム変数の存続期間とともにスコープが終了すると、sstream.str
値によって返されるために使用できます。[参照:cplusplus.com/reference/ios/ios/clear/]
私の解決策。整数型のみが許可されています。
更新。オプションのプレフィックス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
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"
#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;
}
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;
unsigned long
けどstd::intptr_t
。
intptr_t
、ビルドプラットフォーム上の任意のポインタを格納することができます。それは[必ずしも]には当てはまりませんunsigned int
。そして、再び、これのどれも問題に関連していません。私からこれ以上の返信がありません
int
タイプに関する提案をテストしてください;)