web-dev-qa-db-ja.com

C ++ 16進文字列を符号付き整数に変換します

C++で16進文字列を32ビット符号付き整数に変換したい。

したがって、たとえば、16進数の文字列「fffefffe」があります。これのバイナリ表現は11111111111111101111111111111110です。これの符号付き整数表現は-65538です。

C++でこの変換を行うにはどうすればよいですか?これは、負でない数でも機能する必要があります。たとえば、16進文字列「0000000A」は、バイナリで00000000000000000000000000001010、10進数で10です。

119
Clayton

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進数に設定する上記のソリューションは、それをうまく処理します。

Boostにはいくつかの機能があります これを行うには、Niceのエラーチェック機能がいくつかあります。次のように使用できます。

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"); 
204
Evan Teran

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;
    }
}
56
anon

アンディ・ブキャナン、C++にこだわる限り、私はあなたのものが好きでしたが、私はいくつかのMODを持っています:

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型ごとに1つの実装を必要としません。

26
Mike Lundy

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は、stringlongに変換します。私のコンピューターではnumeric_limits<long>::max()0x7fffffffを与えます。明らかに、0xfffefffe0x7fffffffより大きいです。したがって、strtolは、必要な値の代わりにMAX_LONGを返します。 strtoulstringunsigned 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を出力します。

15

ここに私が他の場所で見つけたシンプルで実用的な方法があります:

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

値を受け取るために、符号なし長整数/長整数の使用を好むかもしれないことに注意してください。もう1つの注意点として、c_str()関数はstd :: stringをconst char *に変換するだけです。

したがって、const char *の準備ができている場合は、以下に示すように、その変数名を直接使用してください[大きな16進数での符号なしlong変数の使用方法も示しています。文字列の代わりに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);

これはまったく問題なく機能します(必要に応じて適切なデータ型を使用する場合)。

8
AamodG

今日も同じ問題がありましたが、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。

6
Andy J Buchanan

これは私のために働いた:

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 
3
mike