webentwicklung-frage-antwort-db.com.de

Ganzzahl bis Hex-Zeichenfolge in C ++

Wie konvertiere ich eine ganze Zahl in eine hexadezimale Zeichenfolge in C++ ?

Ich kann einige Wege finden, dies zu tun, aber sie scheinen hauptsächlich auf C ausgerichtet zu sein. Es scheint keinen nativen Weg zu geben, dies in C++ zu tun. Es ist jedoch ein ziemlich einfaches Problem. Ich habe eine int, die ich zum späteren Drucken in eine Hex-Zeichenfolge konvertieren möchte.

105
kryptobs2000

Verwenden Sie <iomanip> 'S std::hex . Wenn Sie drucken, senden Sie es einfach an std::cout. Wenn nicht, verwenden Sie std::stringstream

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

Sie können dem ersten <<<< "0x" Voranstellen oder was auch immer Sie möchten.

Andere interessante Manipulationen sind std::oct (Oktal) und std::dec (Zurück zur Dezimalzahl).

Ein Problem, auf das Sie stoßen können, ist die Tatsache, dass dies die genaue Anzahl von Ziffern ergibt, die zur Darstellung erforderlich sind. Sie können setfill und setw verwenden, um das Problem zu umgehen:

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

Zum Schluss würde ich eine solche Funktion vorschlagen:

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

Um es leichter und schneller zu machen, empfehle ich das direkte Füllen einer Saite.

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

Verwenden std::stringstream, um Ganzzahlen in Strings umzuwandeln, und seine speziellen Manipulatoren, um die Basis zu setzen. Zum Beispiel so:

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

Gib es einfach als Hexadezimalzahl aus:

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

Sie können Folgendes versuchen. Es funktioniert...

#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;
}
8
Mahmut EFE

Diese Frage ist alt, aber ich bin überrascht, warum niemand boost::format Erwähnt hat:

cout << (boost::format("%x") % 1234).str();  // output is: 4d2
4
s4eed
int num = 30;
std::cout << std::hex << num << endl; // This should give you hexa- decimal of 30
4
Mahesh

Dank Lincolns Kommentar unten habe ich diese Antwort geändert.

In der folgenden Antwort werden 8-Bit-Ints zur Kompilierungszeit ordnungsgemäß verarbeitet. Es erfordert jedoch C++ 17. Wenn Sie nicht über C++ 17 verfügen, müssen Sie etwas anderes tun (z. B. Überladungen dieser Funktion bereitstellen, eine für uint8_t und eine für int8_t, oder etwas anderes als "if constexpr" verwenden, möglicherweise 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();
}

rsprüngliche Antwort, die 8-Bit-Ints nicht richtig behandelt, wie ich dachte:

Die Antwort von Kornel Kisielewicz ist großartig. Ein geringfügiger Zusatz hilft jedoch dabei, Fälle zu erfassen, in denen Sie diese Funktion mit Vorlagenargumenten aufrufen, die keinen Sinn ergeben (z. B. float) oder die zu unübersichtlichen Compilerfehlern führen (z. B. benutzerdefinierter Typ).

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

Ich habe dies bearbeitet, um einen Aufruf von std :: to_string hinzuzufügen, da 8-Bit-Integer-Typen (z. B. std::uint8_t Werte übergeben) an std::stringstream werden als Zeichen behandelt, wodurch Sie nicht das gewünschte Ergebnis erhalten. Übergabe solcher ganzen Zahlen an std::to_string behandelt sie korrekt und schadet nicht, wenn andere, größere Integer-Typen verwendet werden. Natürlich kann es in diesen Fällen zu leichten Leistungseinbußen kommen, da der Aufruf std :: to_string nicht erforderlich ist.

Hinweis: Ich hätte dies nur in einem Kommentar zur ursprünglichen Antwort hinzugefügt, aber ich habe nicht den Repräsentanten, um zu kommentieren.

4
Loss Mentality

Code für Ihre Referenz:

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

Für diejenigen von Ihnen, die herausgefunden haben, dass viele/die meisten der ios::fmtflags arbeite nicht mit std::stringstream doch wie die vorlagenidee, die kornel vor langer zeit gepostet hat, funktioniert folgendes und ist relativ sauber:

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

Schauen Sie sich doch mal meine Lösung an,[1] dass ich wörtlich aus meinem projekt kopiert habe, damit dort ein deutsches API doc enthalten ist. Mein Ziel war es, Flexibilität und Sicherheit mit meinen tatsächlichen Bedürfnissen zu verbinden:[2]

  • no 0x Präfix hinzugefügt: Anrufer können entscheiden
  • automatischer Breitenabzug : weniger Tippen
  • explizites Steuerelement für die Breite : Verbreiterung zum Formatieren, (verlustfreie) Verkleinerung, um Platz zu sparen
  • fähig für den Umgang mit long long
  • beschränkt auf Integraltypen : Vermeiden Sie Überraschungen durch stille Konvertierungen
  • leichtigkeit des Verständnisses
  • keine fest programmierte Grenze
#include <string>
#include <sstream>
#include <iomanip>

/// Vertextet einen Ganzzahlwert val im Hexadezimalformat.
/// Auf die Minimal-Breite width wird mit führenden Nullen aufgefüllt;
/// falls nicht angegeben, wird diese Breite aus dem Typ des Arguments
/// abgeleitet. Funktion geeignet von char bis long long.
/// Zeiger, Fließkommazahlen u.ä. werden nicht unterstützt, ihre
/// Übergabe führt 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] basierend auf der Antwort von Kornel Kisielewicz
[2] Übersetzt in die Sprache von CppTest lautet das so:

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

Meine Lösung. Es sind nur ganzzahlige Typen zulässig.

pdate. Sie können das optionale Präfix 0x im zweiten Parameter einstellen.

definition.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 Convert::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 <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;
}

Ergebnisse:
0xfe
0xfe
0xfffffffe
0xfffffffffffffffe

zB
zB fffffffe
fffffffffffffffe

1
Joma

Ich mache:

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

Schauen Sie sich ALSO Antwort von iFreilicht und die benötigte Template-Header-Datei hier an Gist !

1
CarpeDiemKopi