ขอบคุณความคิดเห็นของลินคอล์นด้านล่างฉันได้เปลี่ยนคำตอบนี้
คำตอบต่อไปนี้จัดการ ints 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();
}
คำตอบเดิมที่จัดการ int 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
จะถือว่าเป็นถ่านซึ่งไม่ได้ให้ผลลัพธ์ที่คุณต้องการ การส่งจำนวนเต็มดังกล่าวเพื่อstd::to_string
จัดการกับพวกมันอย่างถูกต้องและไม่ทำร้ายสิ่งต่าง ๆ เมื่อใช้จำนวนเต็มชนิดอื่นที่ใหญ่กว่า แน่นอนว่าคุณอาจได้รับผลกระทบด้านประสิทธิภาพเล็กน้อยในกรณีเหล่านี้เนื่องจากไม่จำเป็นต้องใช้การเรียก std :: to_string
หมายเหตุ: ฉันเพิ่งจะเพิ่มสิ่งนี้ในความคิดเห็นในคำตอบเดิม แต่ฉันไม่มีตัวแทนที่จะแสดงความคิดเห็น
int
ประเภท;)