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로 위협되기 때문에 단일 바이트에서는 작동하지 않습니다.
ov7a

5
또한 #include <sstream>
David Gausmann이

2
나는 여러의 int를 포맷하고 있다면, 보인다 std::setw반면 필요가 모든 인터넷 용 스트림에 출력 std::hex, std::setfill, std::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 ++의 매우 실용적인 (그러나 유효한) 혼합, 속도에 대해 잘 모르겠습니다. 제 취향으로 는 약간 조밀합니다.
Wolf

감사합니다, 훌륭한 답변입니다. 이를 위해 '그냥'스트림 라이브러리를 가져 오는 것은 그렇게 낭비 인 것 같습니다.
DeveloperChris

1
이 인쇄 0000FFFF를 위해 0xFFFF. 나는 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 19.01.09

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
멋진 대답은,하지만 조심 to_string네임 스페이스의 일부인 stdC ++ 11
알렉스

@Alex 네, 결국 2014 년입니다 ... 천국은 금방 우리가 곧 C ++ 14를 다루어야 할 것입니다.
Alex

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

아래 Lincoln의 의견 덕분에이 답변을 변경했습니다.

다음 답변은 컴파일 타임에 8 비트 int를 올바르게 처리합니다. 그러나 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();
}

8 비트 정수 유형 (예 : std::uint8_t전달 된 값) std::stringstream이 문자로 처리되어 원하는 결과를 제공하지 않기 때문에 std :: to_string에 대한 호출을 추가하기 위해 이것을 편집했습니다 . 이러한 정수를std::to_string 하여 올바르게 처리하고 다른 더 큰 정수 유형을 사용할 때 문제가 발생하지 않습니다. 물론 std :: to_string 호출이 필요하지 않기 때문에 이러한 경우 약간의 성능 저하가 발생할 수 있습니다.

참고 : 원래 답변에 대한 댓글에 이것을 추가했지만 댓글을 달 담당자가 없습니다.


내 테스트에서 std :: to_string (i)은 std :: uint8_t 정수를 16 진수로 인쇄하지 않습니다. uint8_t 및 int8_t 유형 모두에 대해 별도의 조건이 있어야 할 수 있다고 생각합니다. 더 큰 정수로 캐스팅해야하기 때문입니다.
Lincoln

1
@ 링컨 당신이 맞아요. 나는 to_string이 8 비트 정수를 처리하도록 만든 당시 (지금 몇 달 전) 내가 무엇을했는지 모르겠다. 나는 그 당시에 사용하고 있다고 생각하는 컴파일러 버전으로 돌아가서 다시 확인했지만 to_string은 내가 말한대로 작동하지 않았습니다. 그래서 누가 압니까? 어쨌든, 이것을 잡아 주셔서 감사합니다-올바르게 작동하는 것에 대한 답변을 편집했습니다.
Loss Mentality

1
이것은 여전히 ​​예상치 않게 작동합니다 char(이는 대부분의 구현 uint8_t과 구별됩니다 int8_t(각각 unsigned charsigned char)).
Ruslan

@ruslan 예, bool 및 wide char 유형도 모두 std :: is_integral과 일치하며 어설 션에 실패하지 않습니다. 그러나 char는 표준에 따라 보장 된 고유 유형이므로 와이드 char 유형과 마찬가지로 원하는 경우 모든 유형을 처리 할 수 ​​있습니다 (예외는 un / signed char, 너비 a의 un / signed 정수 유형과 일치 함). byte는 현재 컴퓨터 (일반적으로 int8)에 있으므로 동일한 너비의 int도 일치시키려는 경우 필터링 할 수 없습니다. static_assert에 더 많은 용어를 추가하여 char, wide chars, bools를 거부 할 수 있습니다. ... && !std::is_same_v<char, T> && !std::is_same_v<bool, T>기타 ...
Loss Mentality

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

2

나는한다:

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

iFreilicht의 SO 답변과 여기 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");
궤도의 Lightness Races

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
이것은 실제로 기존 답변에 추가되지 않으며 명시 적 clear으로 sstream(함수가 다음 줄에서 반환 될 때 파괴 될 것임) 명시 적으로 의미가 없습니다. 이름을 hexStr완전히 피하고 ing return sstream.str();없이도 clear동일한 효과를 얻을 수 있으므로 코드 4 줄을 1 줄로 줄일 수 있습니다.
ShadowRanger

1
포럼의 목적이 사물과 사용법을 이해하는 것입니다. 자세한 내용은 줄을 절약하는 것보다 명확한 그림을 제공하는 것이 훨씬 낫습니다. 질문은 최적화 된 코드에 관한 것이 아니었고 답변은 이러한 변환을 처리하는 모듈 방식 방법을 제공하려고합니다. @ShadowRanger
parasrish

1
의 목적은 sstream.clear();무엇입니까? sstream객체는 자동으로 범위의 끝에서 파괴되기 때문에 return sstream.str();그것을 할 것입니다.
Wolf

sstream.clear스트림이 범위 종료로 끝나기 전에 콘텐츠를 지 웁니다 (clear로 실패 및 eof 플래그를 지 웁니다). 실제로 범위가 죽을 때 스트림 변수의 수명과 함께 sstream.str값으로 반환하는 데 사용할 수 있습니다. [참조 : cplusplus.com/reference/ios/ios/clear/]
parasrish

2

내 솔루션. 정수 유형 만 허용됩니다.

최신 정보. 두 번째 매개 변수에서 선택적 접두사 0x를 설정할 수 있습니다.

정의 .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;

무효 포인터 사용 :

// 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 (address to dec)
0x69fec4 (address to dec, output in hex)


본능적으로 이것과 함께 갔다 ...
int address = (int) & var;

이것을 다른 곳에서 보았다 ...
unsigned long address = reinterpret_cast (& var);

댓글은 이것이 맞다고 말했습니다 ...
int address = (int) & var;

잘 덮힌 가벼움에 대해 말하자면 , 당신은 어디에 있습니까? 좋아요가 너무 많아요!


이 질문은 이미 잘 다루어졌습니다. 귀하의 답변은 이미 게시 된 항목에 무엇을 추가합니까? 그리고 주소는 그것과 무슨 관련이 있습니까?
궤도의 가벼운 경주

@LightnessRacesinOrbit 그것이 닫히지 않았습니까? 댓글을 남긴 마지막 3 명에게 그렇게 말 했나요? 이것은 내가 찾던 것에 대해 더 많은 것을 얻습니다. 다른 사람을 도울 수 있습니다. 그리고 주소는 그것과 무슨 관련이 있습니까? 누가 십진수로 주소를 읽는가? 실제 예입니다.
Puddle

거의 9 년 전에 이미 게시 된 동일한 답변을 게시하는 것은 유용하지 않은 것으로 간주되며,이 방정식에 대한 포인터의 도입은 갑자기 나타난 것처럼 보입니다. OP는 포인터에 대해 묻지 않습니다. 또한, 아니, 수 없습니다 것입니다 unsigned longstd::intptr_t.
궤도의 가벼운 경주

intptr_t = int ... uintptr_t = unsigned int ... 메모리 주소가 이제 서명 되었습니까? 그리고 int가 얼마나 많은 메모리를 제공합니까?
Puddle

당신은 요점을 놓치고 있습니다. 는 intptr_t빌드 플랫폼에 어떤 포인터를 저장할 수있다; 그것은 [필연적으로] 사실이 아닙니다 unsigned int. 그리고 다시 말하지만, 이것 중 어느 것도 질문과 관련이 없습니다. 더 이상 내에서 응답이 없습니다
밝기 경주 궤도에
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.