সি ++ হেক্স স্ট্রিংকে স্বাক্ষরিত পূর্ণসংখ্যায় রূপান্তর করুন


135

আমি একটি হেক্স স্ট্রিং সি ++ এ 32 বিট স্বাক্ষরিত পূর্ণসংখ্যায় রূপান্তর করতে চাই।

সুতরাং, উদাহরণস্বরূপ, আমার কাছে হেক্স স্ট্রিং "fffefffe" রয়েছে। এর বাইনারি উপস্থাপনা 111111111111111111111111111111111110. এর স্বাক্ষরিত পূর্ণসংখ্যা উপস্থাপনাটি হ'ল: -65538।

আমি এই রূপান্তরটি কীভাবে সি ++ এ করব? এটি অ-নেতিবাচক সংখ্যার জন্যও কাজ করা দরকার। উদাহরণস্বরূপ, হেক্স স্ট্রিং "0000000A", যা বাইনারিতে 000000000000000000000000000000101010, এবং দশমিক 10 টি।


2
বিঃদ্রঃ. আপনি কেবল সেই সিস্টেমগুলির জন্য -65538 পাবেন যেখানে মাপের (শেষ) == 4
মার্টিন ইয়র্ক

3
@ মার্টিন ইয়র্ক, তিনি উল্লেখ করেননি int। "32 বিট স্বাক্ষরিত পূর্ণসংখ্যা" ইন্টিওয়ে_ট বা __int32 ইত্যাদি হতে পারে
কিরিল ভি লিয়াদভিনস্কি

উত্তর:


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

নতুন সি ++ 11 স্ট্যান্ডার্ডে, কয়েকটি নতুন ইউটিলিটি ফাংশন রয়েছে যা আপনি ব্যবহার করতে পারেন! বিশেষত, "স্ট্রিং টু নাম্বার" ফাংশনগুলির একটি পরিবার রয়েছে ( http://en.cppreferences.com/w/cpp/string/basic_string/stol এবং http://en.cppreferences.com/w/cpp/string/ বেসিক_স্ট্রিং / স্টুল )। এগুলি সি এর স্ট্রিংয়ের সাথে সংখ্যার রূপান্তর ফাংশনগুলির চারপাশে মূলত পাতলা মোড়ক রয়েছে তবে কীভাবে কীভাবে ডিল করতে হয় তা জানেনstd::string

সুতরাং, নতুন কোডের সহজ উত্তরটি সম্ভবত এটির মতো দেখাবে:

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

বিঃদ্রঃ: নীচে আমার মূল উত্তরটি দেওয়া হয়েছে, যা সম্পাদনা হিসাবে সম্পূর্ণ উত্তর নয়। কার্যক্ষম সমাধানের জন্য, কোডটি :-) রেখার উপরে চাপুন stick

এটি প্রদর্শিত হয় যেহেতু 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 এর পূর্ণসংখ্যার মানটি দিয়ে শেষ করি
ক্লেটন

@ জেমনিং ২ কে, হ্যাঁ, এটি অদ্ভুত যে হেক্স স্ট্রিংগুলিতে (এমনকি 0x উপসর্গ দিয়েও) উভয়ই উত্সাহিত করা এবং আমার লেজিকাল_কাস্ট বার্ফ যদি আমি স্ট্রিং :: হেক্স না রাখি।
ইভান তেরান

1
@ স্টিভওয়িলকিনসন: " EDIT " দিয়ে শুরু করে অনুচ্ছেদটি পড়ুন । এটি আপনাকে কীভাবে ব্যবহার করতে হবে তা ব্যাখ্যা করেstd::hex
ইভান তেরান

1
এর জন্য কোনও ত্রুটি না ঘটেছে তা নিশ্চিত করে stringstreamপরীক্ষা ss.good() && ss.eof()করা উচিত ।
atoMerz

1
এই "stoul" সংরক্ষণ করুন আমার যুক্তিবিজ্ঞান
vincenzopalazzo

60

এমন একটি পদ্ধতির জন্য যা উভয় সি এবং সি ++ নিয়ে কাজ করে আপনি স্ট্যান্ডার্ড লাইব্রেরি ফাংশন স্ট্র্টল () ব্যবহার করে বিবেচনা করতে পারেন।

#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+ overflowStrtol ব্যবহার করার সময় থাকবে । সঙ্গে strtoulথাকবে কোন ওভারফ্লো এবং ফিরে মান রূপান্তরিত হবে longসঠিক ফলাফল (-65538) উত্পাদন করতে। তাই আপনার উত্তর প্রায় ডান :)
কিরিল ভি 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

@ এফএমইউকে: কারণ 0xFFFFFFFFF একটি স্বাক্ষরিত পূর্ণসংখ্যা ওভারফ্লো, যা অপরিজ্ঞাত আচরণ।
বিলি ওনিল

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

strtolপরিবর্তিত stringকরতে 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 () ফাংশনটি কেবল স্টেড :: স্ট্রিংকে কনস্ট চরে রূপান্তরিত করে।

সুতরাং আপনার কাছে যদি কনস্টের চর * প্রস্তুত থাকে তবে কেবল সেই পরিবর্তনশীল নামটি সরাসরি ব্যবহার করে এগিয়ে যান, নীচে দেখানো হয়েছে [আমি আরও বৃহত্তর হেক্স সংখ্যার জন্য স্বাক্ষরযুক্ত দীর্ঘ ভেরিয়েবলের ব্যবহারও দেখিয়ে চলেছি। স্ট্রিংয়ের পরিবর্তে কনস্ট চর * রাখার ক্ষেত্রে এটি বিভ্রান্ত করবেন না:

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

আমার আজ একই সমস্যা ছিল, আমি কীভাবে এটি সমাধান করেছি তা আমি এখানে লেক্সিকাল_কাস্ট <> রাখতে পারি

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 দ্বারা বিভাজ্য হতে হবে

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.