Geheel getal naar hexadecimale tekenreeks in C++

Hoe converteer ik een geheel getal naar een hexadecimale tekenreeks in C++?

Ik kan een aantal manieren vinden om het te doen, maar ze lijken meestal gericht op C. Het lijkt erop dat er geen native manier is om het in C++ te doen. Het is echter een vrij eenvoudig probleem; Ik heb een intdie ik wil converteren naar een hexadecimale tekenreeks voor later afdrukken.


Antwoord 1, autoriteit 100%

Gebruik <iomanip>‘s std::hex. Als je print, stuur het dan naar std::cout, zo niet, gebruik dan std::stringstream

std::stringstream stream;
stream << std::hex << your_int;
std::string result( stream.str() );

U kunt de eerste <<voorafgaan met << "0x"of wat je maar wilt als je wilt.

Andere interessante manips zijn std::oct(octal) en std::dec(terug naar decimaal).

Een probleem dat u kunt tegenkomen, is het feit dat dit het exacte aantal cijfers oplevert dat nodig is om het weer te geven. U kunt setfillen setwgebruiken om het probleem te omzeilen:

stream << std::setfill ('0') << std::setw(sizeof(your_type)*2) 
       << std::hex << your_int;

Dus tot slot zou ik een dergelijke functie willen voorstellen:

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

Antwoord 2, autoriteit 18%

Om het lichter en sneller te maken, raad ik aan om directe vulling van een string te gebruiken.

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

Antwoord 3, autoriteit 10%

Gebruik std::stringstreamom gehele getallen om te zetten in strings en zijn speciale manipulatoren om de basis in te stellen. Bijvoorbeeld zo:

std::stringstream sstream;
sstream << std::hex << my_integer;
std::string result = sstream.str();

Antwoord 4, autoriteit 7%

Druk het gewoon af als een hexadecimaal getal:

int i = /* ... */;
std::cout << std::hex << i;

Antwoord 5, autoriteit 3%

Je kunt het volgende proberen. Het werkt…

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

Antwoord 6, autoriteit 3%

Deze vraag is oud, maar het verbaast me waarom niemand boost::format:

noemde

cout << (boost::format("%x") % 1234).str();  // output is: 4d2

Antwoord 7, autoriteit 2%

Dankzij de onderstaande opmerking van Lincoln heb ik dit antwoord gewijzigd.

Het volgende antwoord verwerkt 8-bits ints correct tijdens het compileren. Het vereist echter wel C++17. Als je C++17 niet hebt, moet je iets anders doen (bijv. overbelasting van deze functie voorzien, één voor uint8_t en één voor int8_t, of iets anders gebruiken dan “if constexpr”, misschien 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();
}

Oorspronkelijk antwoord dat 8-bits ints niet correct verwerkt, zoals ik dacht:

Het antwoord van Kornel Kisielewicz is geweldig. Maar een kleine toevoeging helpt bij het opsporen van gevallen waarin u deze functie aanroept met sjabloonargumenten die niet kloppen (bijv. float) of die zouden resulteren in rommelige compilerfouten (bijv. door de gebruiker gedefinieerd type).

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

Ik heb dit bewerkt om een ​​aanroep toe te voegen aan std::to_string omdat 8-bits integer-types (bijv. std::uint8_twaarden doorgegeven) aan std::stringstreamworden behandeld als char, wat u niet het gewenste resultaat geeft. Het doorgeven van dergelijke gehele getallen aan std::to_stringhandelt ze correct af en doet geen pijn bij het gebruik van andere, grotere typen gehele getallen. Natuurlijk kunt u in deze gevallen mogelijk een kleine prestatie-hit krijgen, aangezien de std::to_string-aanroep niet nodig is.

Opmerking: ik zou dit gewoon in een opmerking aan het oorspronkelijke antwoord hebben toegevoegd, maar ik heb niet de vertegenwoordiger om te reageren.


Antwoord 8, autoriteit 2%

int num = 30;
std::cout << std::hex << num << endl; // This should give you hexa- decimal of 30

Antwoord 9

Ik wel:

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

Bekijk het SOantwoord van iFreilicht en het vereiste sjabloon header-bestand van hier GIST!


Antwoord 10

Kijk maar eens naar mijn oplossing,[1]die ik letterlijk heb gekopieerd van mijn project, dus er is een Duits API-document bijgevoegd. Mijn doel was om flexibiliteit en veiligheid te combineren met mijn werkelijke behoeften:[2]

  • geen 0xprefixtoegevoegd: beller mag beslissen
  • automatische breedte-aftrek: minder typen
  • expliciete breedtecontrole: verbreden voor opmaak, (verliesloos) verkleinen om ruimte te besparen
  • geschikt voor long long
  • beperkt tot integrale typen: voorkom verrassingen door stille conversies
  • gemakkelijk te begrijpen
  • geen hardgecodeerde limiet
#include <string>
#include <sstream>
#include <iomanip>
/// Vertextet einen Ganzzahlwert val im Hexadezimalformat.
/// Auf die Minimal-Breite width wird mit fuhrenden Nullen aufgefullt;
/// falls nicht angegeben, wird diese Breite aus dem Typ des Arguments
/// abgeleitet. Funktion geeignet von char bis long long.
/// Zeiger, Flie?kommazahlen u.a. werden nicht unterstutzt, ihre
/// Ubergabe fuhrt 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]gebaseerd op het antwoord van Kornel Kisielewicz
[2]Vertaald in de taal van CppTest, is dit hoe het luidt:

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

Antwoord 11

Mijn oplossing. Alleen integrale typen zijn toegestaan.

U kunt testen/uitvoeren op https://replit.com/@JomaCorpFX/ToHex

Update.U kunt een optioneel voorvoegsel 0x instellen in de tweede parameter.

definitie.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 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 <iostream>
#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;
}

Resultaten:

0xfe
0xfe
0xfffffffe
0xfffffffffffffffe
fe
fe
fffffffe
fffffffffffffffe

output


Antwoord 12

Voor degenen onder jullie die erachter kwamen dat veel/de meeste van de ios::fmtflagsniet werken met std::stringstreammaar toch het sjabloonidee dat Kornel lang geleden gepost, het volgende werkt en is relatief schoon:

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

Antwoord 13

Code voor uw referentie:

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

Antwoord 14

Ik zou graag een antwoord willen toevoegen om te genieten van de schoonheid van C++-taal. Het aanpassingsvermogen om op hoog en laag niveau te werken. Veel plezier met programmeren.

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

Voorbeelden:

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"

Antwoord 15

voor vast aantal cijfers, bijvoorbeeld 2:

   static const char* digits = "0123456789ABCDEF";//dec 2 hex digits positional map
    char value_hex[3];//2 digits + terminator
    value_hex[0] = digits[(int_value >> 4) & 0x0F]; //move of 4 bit, that is an HEX digit, and take 4 lower. for higher digits use multiple of 4
    value_hex[1] = digits[int_value & 0x0F]; //no need to move the lower digit
    value_hex[2] = '\0'; //terminator

u kunt ook een for cycle-variant schrijven om variabele cijfers te verwerken

voordelen:

  • snelheid: het is een minimale bit-bewerking, zonder externe functie-aanroepen
  • geheugen: het gebruikt een lokale string, geen toewijzing buiten het functiestapelframe, geen vrij geheugen nodig. Hoe dan ook, indien nodig kunt u een veld of een globaal gebruiken om de waarde_ex naar het stapelframe te laten blijven

Antwoord 16

Sinds C++20, met std::format, zou je kunnen doen:

std::format("{:#x}", your_int);    // 0x2a
std::format("{:#010x}", your_int); // 0x0000002a

Demo


Antwoord 17

#include <iostream> 
#include <sstream>  
int main()
{
unsigned int i = 4967295; // random number
std::string str1, str2;
unsigned int u1, u2;
std::stringstream ss;

Void pointer gebruiken:

// 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 toevoegen:

// 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();

Uitgangen:

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

Antwoord 18

_itoa_s

char buf[_MAX_U64TOSTR_BASE2_COUNT];
_itoa_s(10, buf, _countof(buf), 16);
printf("%s\n", buf);    // a

swprintf_s

uint8_t x = 10;
wchar_t buf[_MAX_ITOSTR_BASE16_COUNT];
swprintf_s(buf, L"%02X", x);

Antwoord 19

char_to_hex geeft een string van twee karakters terug

const char HEX_MAP[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
char replace(unsigned char c)
{
    return HEX_MAP[c & 0x0f];
}
std::string char_to_hex(unsigned char c)
{
    std::string hex;
    // First four bytes
    char left = (c >> 4);
    // Second four bytes
    char right = (c & 0x0f);
    hex += replace(left);
    hex += replace(right);
    return hex;
} 

Antwoord 20

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 (adres)
6946500 (adres tot december)
0x69fec4 (adres tot december, uitvoer in hex)


ging hier instinctief mee om…
int adres = (int)&var;

heb dit ergens anders gezien…
niet-ondertekend lang adres = reinterpret_cast(&var);

reactie vertelde me dat dit correct is…
int adres = (int)&var;

over goed gedekt gesproken
lichtheid, waar ben je? ze krijgen te veel likes!

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Other episodes