C ++ हस्ताक्षरित पूर्णांक में हेक्स स्ट्रिंग परिवर्तित करें


135

मैं सी + + में 32 बिट हस्ताक्षरित पूर्णांक के लिए एक हेक्स स्ट्रिंग परिवर्तित करना चाहता हूं।

इसलिए, उदाहरण के लिए, मेरे पास हेक्स स्ट्रिंग "फ़िफ़्फ़फे" है। इसका द्विआधारी प्रतिनिधित्व 11111111111111111111111111111111110 है। इस पर हस्ताक्षर किए गए पूर्णांक का प्रतिनिधित्व है: -65538।

मैं इस रूपांतरण को C ++ में कैसे करूं? इसके लिए गैर-नकारात्मक संख्याओं के लिए भी काम करना होगा। उदाहरण के लिए, हेक्स स्ट्रिंग "0000000A", जो बाइनरी में 00000000000000000000000000001010 और दशमलव में 10 है।


2
ध्यान दें। आपको केवल -65538 सिस्टम के लिए मिलेगा, जहां sizeof (int) == 4
मार्टिन

3
@ मर्टिन यॉर्क, उन्होंने उल्लेख नहीं किया int। "32 बिट हस्ताक्षरित पूर्णांक" int32_t या __int32 आदि हो सकता है
Kirill V. Lyadvinsky

जवाबों:


230

उपयोग 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 / स्टूल )। ये अनिवार्य रूप से संख्या रूपांतरण कार्यों के लिए C के स्ट्रिंग के आसपास पतले रैपर हैं, लेकिन जानते हैं कि कैसे निपटेंstd::string

तो, नए कोड के लिए सबसे सरल उत्तर शायद इस तरह दिखेगा:

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

नोट: नीचे मेरा मूल उत्तर है, जो जैसा कहता है संपादित करें पूर्ण उत्तर नहीं है। एक कार्यात्मक समाधान के लिए, कोड के ऊपर कोड :-)।

ऐसा प्रतीत होता है कि चूंकि lexical_cast<>स्ट्रीम रूपांतरण शब्दार्थ है। अफसोस की बात है कि धाराएँ "0x" अंकन को नहीं समझती हैं। इसलिए, boost::lexical_castमेरे और मेरे दोनों हाथ एक-एक करके हेक्स स्ट्रिंग्स से अच्छी तरह से नहीं जुड़े। उपरोक्त समाधान जो मैन्युअल रूप से इनपुट स्ट्रीम को हेक्स पर सेट करता है वह इसे ठीक से संभाल लेगा।

बूस्ट के पास ऐसा करने के लिए कुछ सामान है, जिसमें कुछ अच्छी त्रुटि जाँच क्षमता भी है। आप इसे इस तरह से उपयोग कर सकते हैं:

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

यदि आप बूस्ट का उपयोग करने का मन नहीं करते हैं, तो यहां लेक्सिकल कास्ट का एक हल्का संस्करण है, जिसमें कोई त्रुटि नहीं है:

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"); 

1
जब मैं इस पद्धति का उपयोग करता हूं, तो मैं 152144602 के पूर्णांक मान के साथ समाप्त होता हूं
क्लेटन

@ jmanning2k, हाँ, यह अजीब है कि दोनों को बढ़ावा देने और हेक्स स्ट्रिंग्स (पर भी 0x उपसर्ग के साथ) पर मेरे lexical_cast barf अगर मैं std :: hex को स्ट्रिंग में नहीं डालता हूं।
इवान टेरान

1
@SteveWilkinson: " EDIT " से शुरू होने वाले पैराग्राफ को पढ़ें । यह बताता है कि आपको कैसे उपयोग करने की आवश्यकता हैstd::hex
इवान टेरान

1
के लिए stringstreamरों एक जांच होनी चाहिए ss.good() && ss.eof()सुनिश्चित करें कि कोई त्रुटियां हुईं बनाने के लिए।
atoMerz

1
यह "स्टूल" मेरे तर्क को बचाए
vincenzopalazzo

60

C और C ++ दोनों के साथ काम करने वाली विधि के लिए, आप मानक लाइब्रेरी फ़ंक्शन स्ट्रटोल () का उपयोग करने पर विचार कर सकते हैं।

#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;
    }
}

2
आपको उपयोग strtoulनहीं करना चाहिए strtol+ overflowस्ट्रेटोल का उपयोग करते समय होगा । के साथ strtoulकोई अतिप्रवाह नहीं होगा और लौटाया गया मान longसही परिणाम (-65538) का उत्पादन करने के लिए परिवर्तित हो जाएगा । तो आपका जवाब लगभग सही है :)
Kirill V. Lyadvinsky

8
+1। क्योंकि स्ट्रैस्टोल (या स्ट्रैटोल) स्ट्रिंगस्ट्रीम का उपयोग करने से तेज है।
किरिल वी। लयाडविंस्की

27

एंडी बुकानन, जहां तक ​​सी ++ से चिपके रहने की बात है, मुझे आपका साथ पसंद है, लेकिन मेरे पास कुछ तरीके हैं:

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");

इस तरह से आपको इंट टाइप प्रति इम्प्लांट की जरूरत नहीं है।


1
मैंने वह कदम भी उठाया होगा, लेकिन मुझे लगता है कि मुझे कोण कोष्ठक के प्रसार को सीमित करना पसंद है। इस मामले के लिए मुझे लगा कि "डुप्लीकेट कोड नहीं" नियम को तोड़ना उचित था। :-)
एंडी जे बुकानन

दुर्भाग्यपूर्ण है कि यह आवश्यक है, लेकिन अच्छी तरह से किया जाता है। मेरे व्यक्तिगत एसटीएल / बूस्ट एक्सटेंशन / फिक्स हेडर में जोड़ा गया। धन्यवाद!
टिम सिलवेस्टर

दुर्भाग्य से यह केवल अहस्ताक्षरित रूपांतरण के लिए काम करता है। तो आप 0xFFFFFFFF को -1 में नहीं बदल सकते।
fmuecke

@fmuecke: ऐसा इसलिए है क्योंकि 0xFFFFFFFF एक हस्ताक्षरित पूर्णांक अतिप्रवाह है, जो अपरिभाषित व्यवहार है।
बिली ओनेल

15

इसके साथ काम करने का उदाहरण 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;
    }
}

strtolstringकरने के लिए धर्मान्तरित long। मेरे कंप्यूटर पर numeric_limits<long>::max()देता है 0x7fffffff। जाहिर है कि 0xfffefffeइससे बड़ा है 0x7fffffff। इसलिए वांछित मूल्य के बजाय strtolरिटर्न MAX_LONGstrtoulधर्मान्तरित 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कंसोल में ऊपर दिए गए कोड ।


9

यहाँ एक सरल और काम करने की विधि मुझे कहीं और मिली:

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

कृपया ध्यान दें कि मान प्राप्त करने के लिए आप अहस्ताक्षरित लंबे पूर्णांक / लंबे पूर्णांक का उपयोग करना पसंद कर सकते हैं। एक और नोट, c_str () फ़ंक्शन बस std :: string को 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);

यह पूरी तरह से ठीक काम करता है (बशर्ते आप अपनी आवश्यकता के अनुसार उपयुक्त डेटा प्रकारों का उपयोग करें)।


6

मुझे आज भी यही समस्या थी, यहाँ मैंने इसे कैसे हल किया ताकि मैं 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...

(इस पृष्ठ मिला जब मैं एक कम बेकार रास्ते के लिए देख रहा था :-)

चीयर्स, ए।


1
कोड में तुच्छ संकलन त्रुटि है - आउटलेव परिभाषित नहीं किया जाना चाहिए (आउटवैल्यू होना चाहिए)।
गैबी डावर

3

यह मेरे लिए काम किया:

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 

0

इसे इस्तेमाल करे। यह समाधान थोड़ा जोखिम भरा है। कोई जाँच नहीं है। स्ट्रिंग में केवल हेक्स मान होना चाहिए और स्ट्रिंग की लंबाई वापसी प्रकार के आकार से मेल खाना चाहिए। लेकिन अतिरिक्त हेडर की कोई आवश्यकता नहीं है।

char hextob(char ch)
{
    if (ch >= '0' && ch <= '9') return ch - '0';
    if (ch >= 'A' && ch <= 'F') return ch - 'A' + 10;
    if (ch >= 'a' && ch <= 'f') return ch - 'a' + 10;
    return 0;
}
template<typename T>
T hextot(char* hex)
{
    T value = 0;
    for (size_t i = 0; i < sizeof(T)*2; ++i)
        value |= hextob(hex[i]) << (8*sizeof(T)-4*(i+1));
    return value;
};

उपयोग:

int main()
{
    char str[4] = {'f','f','f','f'};
    std::cout << hextot<int16_t>(str)  << "\n";
}

नोट: स्ट्रिंग की लंबाई 2 से विभाज्य होनी चाहिए

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.