web-dev-qa-db-fra.com

C ++ convertir une chaîne en hexadécimal et vice versa

Quel est le meilleur moyen de convertir une chaîne en hexadécimal et vice versa en C++?

Exemple:

  • Une chaîne comme "Hello World" au format hexadécimal: 48656C6C6F20576F726C64
  • Et de l'hexagone 48656C6C6F20576F726C64 en chaîne: "Hello World"
56
Sebtm

Une chaîne du type "Hello World" au format hexadécimal: 48656C6C6F20576F726C64.

Ah, voila:

#include <string>

std::string string_to_hex(const std::string& input)
{
    static const char* const lut = "0123456789ABCDEF";
    size_t len = input.length();

    std::string output;
    output.reserve(2 * len);
    for (size_t i = 0; i < len; ++i)
    {
        const unsigned char c = input[i];
        output.Push_back(lut[c >> 4]);
        output.Push_back(lut[c & 15]);
    }
    return output;
}

#include <algorithm>
#include <stdexcept>

std::string hex_to_string(const std::string& input)
{
    static const char* const lut = "0123456789ABCDEF";
    size_t len = input.length();
    if (len & 1) throw std::invalid_argument("odd length");

    std::string output;
    output.reserve(len / 2);
    for (size_t i = 0; i < len; i += 2)
    {
        char a = input[i];
        const char* p = std::lower_bound(lut, lut + 16, a);
        if (*p != a) throw std::invalid_argument("not a hex digit");

        char b = input[i + 1];
        const char* q = std::lower_bound(lut, lut + 16, b);
        if (*q != b) throw std::invalid_argument("not a hex digit");

        output.Push_back(((p - lut) << 4) | (q - lut));
    }
    return output;
}

(Cela suppose qu'un caractère a 8 bits, donc ce n'est pas très portable, mais vous pouvez le prendre à partir d'ici.)

74
fredoverflow
string ToHex(const string& s, bool upper_case /* = true */)
{
    ostringstream ret;

    for (string::size_type i = 0; i < s.length(); ++i)
        ret << std::hex << std::setfill('0') << std::setw(2) << (upper_case ? std::uppercase : std::nouppercase) << (int)s[i];

    return ret.str();
}

int FromHex(const string &s) { return strtoul(s.c_str(), NULL, 16); }
27
Krevan

Vous pouvez essayer ça. Ça marche...

#include <algorithm>
#include <sstream>
#include <iostream>
#include <iterator>
#include <iomanip>

namespace {
   const std::string test="hello world";
}

int main() {
   std::ostringstream result;
   result << std::setw(2) << std::setfill('0') << std::hex << std::uppercase;
   std::copy(test.begin(), test.end(), std::ostream_iterator<unsigned int>(result, " "));
   std::cout << test << ":" << result.str() << std::endl;
}
10
Mahmut EFE

Utiliser des tables de recherche et autres fonctionne, mais c’est exagéré, voici quelques façons très simples de transformer une chaîne en caractères hexadécimaux et d’en retourner en caractères hexadécimaux:

#include <stdexcept>
#include <sstream>
#include <iomanip>
#include <string>
#include <cstdint>

std::string string_to_hex(const std::string& in) {
    std::stringstream ss;

    ss << std::hex << std::setfill('0');
    for (size_t i = 0; in.length() > i; ++i) {
        ss << std::setw(2) << static_cast<unsigned int>(static_cast<unsigned char>(in[i]));
    }

    return ss.str(); 
}

std::string hex_to_string(const std::string& in) {
    std::string output;

    if ((in.length() % 2) != 0) {
        throw std::runtime_error("String is not valid length ...");
    }

    size_t cnt = in.length() / 2;

    for (size_t i = 0; cnt > i; ++i) {
        uint32_t s = 0;
        std::stringstream ss;
        ss << std::hex << in.substr(i * 2, 2);
        ss >> s;

        output.Push_back(static_cast<unsigned char>(s));
    }

    return output;
}
9
X-Istence

Exemple le plus simple utilisant la bibliothèque standard.

#include <iostream>
using namespace std;

int main()
{
  char c = 'n';
  cout << "HEX " << hex << (int)c << endl;  // output in hexadecimal
  cout << "ASC" << c << endl; // output in ascii
  return 0;
}

Pour vérifier la sortie, codepad renvoie: 6e

et un en ligne outil de conversion ascii-à-hexadécimal donne également 6e. Donc ça marche.

Vous pouvez aussi faire ceci:

template<class T> std::string toHexString(const T& value, int width) {
    std::ostringstream oss;
    oss << hex;
    if (width > 0) {
        oss << setw(width) << setfill('0');
    }
    oss << value;
    return oss.str();
}
8
user195488

Je pense qu'il existe une solution beaucoup plus simple et élégante. Certaines des méthodes susmentionnées peuvent même renvoyer des exceptions non gérées dans certains cas. Voici un code infaillible (comme dans jamais ne se trompe) et très rapide. Essayez-le et comparez les résultats en termes de rapidité et de compacité:

#include <string>

// Convert string of chars to its representative string of hex numbers
void stream2hex(const std::string str, std::string& hexstr, bool capital = false)
{
    hexstr.resize(str.size() * 2);
    const size_t a = capital ? 'A' - 1 : 'a' - 1;

    for (size_t i = 0, c = str[0] & 0xFF; i < hexstr.size(); c = str[i / 2] & 0xFF)
    {
        hexstr[i++] = c > 0x9F ? (c / 16 - 9) | a : c / 16 | '0';
        hexstr[i++] = (c & 0xF) > 9 ? (c % 16 - 9) | a : c % 16 | '0';
    }
}

// Convert string of hex numbers to its equivalent char-stream
void hex2stream(const std::string hexstr, std::string& str)
{
    str.resize((hexstr.size() + 1) / 2);

    for (size_t i = 0, j = 0; i < str.size(); i++, j++)
    {
        str[i] = (hexstr[j] & '@' ? hexstr[j] + 9 : hexstr[j]) << 4, j++;
        str[i] |= (hexstr[j] & '@' ? hexstr[j] + 9 : hexstr[j]) & 0xF;
    }
}

Testez le code :

#include <iostream>
int main()
{
    std::string s = "Hello World!";
    std::cout << "original string: " << s << '\n';
    stream2hex(s, s);
    std::cout << "hex format: " << s << '\n';
    hex2stream(s, s);
    std::cout << "original one: " << s << '\n';
}

et le résultat est:

original string: Hello World!
hex format: 48656C6C6F20576F726C6421
original one: Hello World!
7
polfosol ఠ_ఠ

C'est un peu plus rapide:

static const char* s_hexTable[256] = 
{
    "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0a", "0b", "0c", "0d", "0e", "0f", "10", "11",
    "12", "13", "14", "15", "16", "17", "18", "19", "1a", "1b", "1c", "1d", "1e", "1f", "20", "21", "22", "23",
    "24", "25", "26", "27", "28", "29", "2a", "2b", "2c", "2d", "2e", "2f", "30", "31", "32", "33", "34", "35",
    "36", "37", "38", "39", "3a", "3b", "3c", "3d", "3e", "3f", "40", "41", "42", "43", "44", "45", "46", "47",
    "48", "49", "4a", "4b", "4c", "4d", "4e", "4f", "50", "51", "52", "53", "54", "55", "56", "57", "58", "59",
    "5a", "5b", "5c", "5d", "5e", "5f", "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6a", "6b",
    "6c", "6d", "6e", "6f", "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7a", "7b", "7c", "7d",
    "7e", "7f", "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8a", "8b", "8c", "8d", "8e", "8f",
    "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9a", "9b", "9c", "9d", "9e", "9f", "a0", "a1",
    "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "aa", "ab", "ac", "ad", "ae", "af", "b0", "b1", "b2", "b3",
    "b4", "b5", "b6", "b7", "b8", "b9", "ba", "bb", "bc", "bd", "be", "bf", "c0", "c1", "c2", "c3", "c4", "c5",
    "c6", "c7", "c8", "c9", "ca", "cb", "cc", "cd", "ce", "cf", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
    "d8", "d9", "da", "db", "dc", "dd", "de", "df", "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9",
    "ea", "eb", "ec", "ed", "ee", "ef", "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "fa", "fb",
    "fc", "fd", "fe", "ff"
};

// Convert binary data sequence [beginIt, endIt) to hexadecimal string
void dataToHexString(const uint8_t*const beginIt, const uint8_t*const endIt, string& str)
{
    str.clear();
    str.reserve((endIt - beginIt) * 2);
    for(const uint8_t* it(beginIt); it != endIt; ++it)
    {
        str += s_hexTable[*it];
    }
}
6
Erik Hvatum

Depuis C++ 17, il y a aussi std :: from_chars . La fonction suivante prend une chaîne de caractères hexadécimaux et renvoie un vecteur de T:

#include <charconv>

template<typename T>
std::vector<T> hexstr_to_vec(const std::string& str, unsigned char chars_per_num = 2)
{
  std::vector<T> out(str.size() / chars_per_num, 0);

  T value;
  for (int i = 0; i < str.size() / chars_per_num; i++) {
    std::from_chars<T>(
      str.data() + (i * chars_per_num),
      str.data() + (i * chars_per_num) + chars_per_num,
      value,
      16
    );
    out[i] = value;
  }

  return out;
}
4
Nico

Cela convertira Hello World en 48656c6c6f20576f726c64 et print le.

#include <iostream>
#include <cstring>

using namespace std;

int main()
{
    char hello[20]="Hello World";

    for(unsigned int i=0; i<strlen(hello); i++)
        cout << hex << (int) hello[i];
    return 0;
}
2
Dilushan

Ceci convertira "Hello World" en "48656c6c6f6f20576f726c64" et stockera cette valeur hexadécimale dans str1 et convertira également "48656c6c6f20576f726c64" en "Hello World".

#include <iostream>
#include<sstream>

using namespace std;
int hexCharToInt(char);
string hexToString(string);
int main()
{
    std::string str;
    std::stringstream str1;

    str="Hello World";
    for(int i=0;i<str.length();i++){
        str1 << std::hex << (int)str.at(i);
    }
    std::cout << str1.str() <<"\n";
    string test = "48656c6c6f20576f726c64";
    std::cout << hexToString(test) <<"\n";
    return 0;
}
string hexToString(string str){
    std::stringstream HexString;
    for(int i=0;i<str.length();i++){
        char a = str.at(i++);
        char b = str.at(i);
        int x = hexCharToInt(a);
        int y = hexCharToInt(b);
        HexString << (char)((16*x)+y);
    }
    return HexString.str();
}

int hexCharToInt(char a){
    if(a>='0' && a<='9')
        return(a-48);
    else if(a>='A' && a<='Z')
        return(a-55);
    else
        return(a-87);
}
1
Anshul Jain

Pourquoi personne n'a utilisé sprintf?

#include <string>
#include <stdio.h>

static const std::string str = "hello world!";

int main()
{
  //copy the data from the string to a char array
  char *strarr = new char[str.size()+1];
  strarr[str.size()+1] = 0; //set the null terminator
  memcpy(strarr, str.c_str(),str.size()); //memory copy to the char array

  printf(strarr);
  printf("\n\nHEX: ");

  //now print the data
  for(int i = 0; i < str.size()+1; i++)
  {
    char x = strarr[i];
    sprintf("%x ", reinterpret_cast<const char*>(x));
  }

  //DO NOT FORGET TO DELETE
  delete(strarr);

  return 0;
}
0
Alexander Frankland

Voici une autre solution, largement inspirée de celle de @fredoverflow.

/**
 * Return hexadecimal representation of the input binary sequence
 */
std::string hexitize(const std::vector<char>& input, const char* const digits = "0123456789ABCDEF")
{
    std::ostringstream output;

    for (unsigned char gap = 0, beg = input[gap]; gap < input.length(); beg = input[++gap])
        output << digits[beg >> 4] << digits[beg & 15];

    return output.str();
}

Longueur était le paramètre requis dans le prévu

0
psychoslave