문제

C ++의 16 진 문자열을 32 비트 서명 정수로 변환하고 싶습니다.

예를 들어, 16 진 문자열 "fffefffe"가 있습니다. 이것의 이진 표현은 11111111111111111111111111111110입니다.

C ++ 에서이 변환은 어떻게하나요? 이것은 또한 음이 아닌 숫자에 대해서도 작동해야합니다. 예를 들어, 바이너리에서 0000000000000000000000000000001010 인 HEX 문자열 "0000000A", 10 진수로 10입니다.

도움이 되었습니까?

해결책

사용 std::stringstream

unsigned int x;   
std::stringstream ss;
ss << std::hex << "fffefffe";
ss >> x;

다음 예제가 생성됩니다 -65538 그 결과 :

#include <sstream>
#include <iostream>

int main() {
    unsigned int x;   
    std::stringstream ss;
    ss << std::hex << "fffefffe";
    ss >> x;
    // output it as a signed type
    std::cout << static_cast<int>(x) << std::endl;
}

새로운 C ++ 11 표준에는 몇 가지 새로운 유틸리티 기능이 있습니다. 구체적으로, "문자열 대 번호"함수가 있습니다 (http://en.cppreference.com/w/cpp/string/basic_string/stol 그리고 http://en.cppreference.com/w/cpp/string/basic_string/stoul). 이것들은 본질적으로 C의 문자열 주위의 숫자 전환 기능이지만, 처리하는 방법을 알고 있습니다. std::string

따라서 최신 코드에 대한 가장 간단한 답변은 다음과 같습니다.

std::string s = "0xfffefffe";
unsigned int x = std::stoul(s, nullptr, 16);

노트: 아래는 나의 원래 대답이며, 편집이 말한 것처럼 완전한 답변은 아닙니다. 기능 솔루션의 경우 라인 위의 코드를 사용하십시오 .-).

그 이후로 보입니다 lexical_cast<> 스트림 변환 의미론을 갖도록 정의됩니다. 안타깝게도 스트림은 "0x"표기법을 이해하지 못합니다. 그래서 둘 다 boost::lexical_cast 그리고 내 손을 굴린 사람은 16 진수를 잘 다루지 않습니다. 입력 스트림을 16 진로 수동으로 설정하는 위의 솔루션은 잘 처리합니다.

부스트에는 몇 가지가 있습니다 이를 위해서도 좋은 오류 확인 기능도 있습니다. 다음과 같이 사용할 수 있습니다.

try {
    unsigned int x = lexical_cast<int>("0x0badc0de");
} catch(bad_lexical_cast &) {
    // whatever you want to do...
}

Boost를 사용하고 싶지 않다면 여기에 오류 확인이없는 어휘 캐스트의 라이트 버전이 있습니다.

template<typename T2, typename T1>
inline T2 lexical_cast(const T1 &in) {
    T2 out;
    std::stringstream ss;
    ss << in;
    ss >> out;
    return out;
}

다음과 같이 사용할 수 있습니다.

// though this needs the 0x prefix so it knows it is hex
unsigned int x = lexical_cast<unsigned int>("0xdeadbeef"); 

다른 팁

C 및 C ++ 모두에서 작동하는 메소드의 경우 표준 라이브러리 함수 strtol ()을 사용하는 것을 고려할 수 있습니다.

#include <cstdlib>
#include <iostream>
using namespace std;

int main() {
    string s = "abcd";
    char * p;
    long n = strtol( s.c_str(), & p, 16 );
    if ( * p != 0 ) { //my bad edit was here
        cout << "not a number" << endl;
    }
    else {
        cout << n << endl;
    }
}

Andy Buchanan, C ++가 고집하는 한, 나는 당신을 좋아했지만 몇 가지 개조가 있습니다.

template <typename ElemT>
struct HexTo {
    ElemT value;
    operator ElemT() const {return value;}
    friend std::istream& operator>>(std::istream& in, HexTo& out) {
        in >> std::hex >> out.value;
        return in;
    }
};

좋아요

uint32_t value = boost::lexical_cast<HexTo<uint32_t> >("0x2a");

그렇게하면 int 유형 당 하나의 명립이 필요하지 않습니다.

작업 예제 strtoul 될거야:

#include <cstdlib>
#include <iostream>
using namespace std;

int main() { 
    string s = "fffefffe";
    char * p;
    long n = strtoul( s.c_str(), & p, 16 ); 
    if ( * p != 0 ) {  
        cout << "not a number" << endl;
    }    else {  
        cout << n << endl;
    }
}

strtol 변환 string 에게 long. 내 컴퓨터에 numeric_limits<long>::max() 주어진 0x7fffffff. 분명히 0xfffefffe 보다 큽니다 0x7fffffff. 그래서 strtol 보고 MAX_LONG 원하는 가치 대신. strtoul 변환 string 에게 unsigned long 그렇기 때문에이 경우 오버플로가 없습니다.

확인, strtol 변환 전에 입력 문자열을 32 비트 서명 정수가 아닌 것으로 간주하고 있습니다. 재미있는 샘플 strtol:

#include <cstdlib>
#include <iostream>
using namespace std;

int main() { 
    string s = "-0x10002";
    char * p;
    long n = strtol( s.c_str(), & p, 16 ); 
    if ( * p != 0 ) {  
        cout << "not a number" << endl;
    }    else {  
        cout << n << endl;
    }
}

위의 코드는 인쇄합니다 -65538 콘솔에서.

다른 곳에서 찾은 간단하고 작업 방법은 다음과 같습니다.

string hexString = "7FF";
int hexNumber;
sscanf(hexString.c_str(), "%x", &hexNumber);

서명되지 않은 긴 정수/긴 정수를 사용하여 값을받을 수 있습니다. 또 다른 참고로, c_str () 함수는 std :: 문자열을 const char*로 변환합니다.

따라서 const char*가 준비되어 있다면 아래에 표시된 것처럼 변수 이름을 직접 사용하는 것으로 진행하십시오. 문자열 대신 const char*가있는 경우와 혼동하지 마십시오.] :

const char *hexString = "7FFEA5"; //Just to show the conversion of a bigger hex number
unsigned long hexNumber; //In case your hex number is going to be sufficiently big.
sscanf(hexString, "%x", &hexNumber);

이것은 완벽하게 작동합니다 (필요에 따라 적절한 데이터 유형을 사용하는 경우).

오늘도 같은 문제가 있었는데, 여기에 내가 어떻게 해결했는지 lexical_cast <>를 유지할 수 있습니다.

typedef unsigned int    uint32;
typedef signed int      int32;

class uint32_from_hex   // For use with boost::lexical_cast
{
    uint32 value;
public:
    operator uint32() const { return value; }
    friend std::istream& operator>>( std::istream& in, uint32_from_hex& outValue )
    {
        in >> std::hex >> outValue.value;
    }
};

class int32_from_hex   // For use with boost::lexical_cast
{
    uint32 value;
public:
    operator int32() const { return static_cast<int32>( value ); }
    friend std::istream& operator>>( std::istream& in, int32_from_hex& outValue )
    {
        in >> std::hex >> outvalue.value;
    }
};

uint32 material0 = lexical_cast<uint32_from_hex>( "0x4ad" );
uint32 material1 = lexical_cast<uint32_from_hex>( "4ad" );
uint32 material2 = lexical_cast<uint32>( "1197" );

int32 materialX = lexical_cast<int32_from_hex>( "0xfffefffe" );
int32 materialY = lexical_cast<int32_from_hex>( "fffefffe" );
// etc...

(이 페이지를 찾았습니다.

건배, A.

이것은 나를 위해 효과가있었습니다.

string string_test = "80123456";
unsigned long x;
signed long val;

std::stringstream ss;
ss << std::hex << string_test;
ss >> x;
// ss >> val;  // if I try this val = 0
val = (signed long)x;  // However, if I cast the unsigned result I get val = 0x80123456 

또 다른 방법

using namespace System;

template <typename NUM>
NUM hexstr2num(String^ h)
{
    NUM v=0;
    String^ k=L"0123456789ABCDEF";
    short l=h->Length;
    char off;
    h=h->ToUpper();

    if(h->Substring(0,1)!=L"H")
        {if(h->Substring(0,2)==L"0X") off=2;}
    else
        {off=1;}

    if(!off) throw;

    char dx=0;
    for(int i=l;i>off;i--)
        {
            if((dx=k->IndexOf(h->Substring(i-1,1)))>=0)
                {v+=dx<<((l-i)<<2);}
            else
                {throw;}
        }
    return v;
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top