Comment convertir une chaîne de valeurs hexadécimales en chaîne?

Dites que j’ai une chaîne comme:

ssortingng hex = "48656c6c6f"; 

Où tous les deux caractères correspondent à la représentation hexadécimale de leur ASCII, valeur, par exemple:

 0x48 0x65 0x6c 0x6c 0x6f = "Hello" 

Alors, comment puis-je obtenir "hello" partir de "48656c6c6f" sans avoir à créer une table de recherche ASCII? atoi() ne fonctionnera évidemment pas ici.

 int len = hex.length(); std::ssortingng newSsortingng; for(int i=0; i< len; i+=2) { string byte = hex.substr(i,2); char chr = (char) (int)strtol(byte.c_str(), null, 16); newString.push_back(chr); } 

Les chiffres hexadécimaux sont très faciles à convertir en binary:

 // C++98 guarantees that '0', '1', ... '9' are consecutive. // It only guarantees that 'a' ... 'f' and 'A' ... 'F' are // in increasing order, but the only two alternative encodings // of the basic source character set that are still used by // anyone today (ASCII and EBCDIC) make them consecutive. unsigned char hexval(unsigned char c) { if ('0' <= c && c <= '9') return c - '0'; else if ('a' <= c && c <= 'f') return c - 'a' + 10; else if ('A' <= c && c <= 'F') return c - 'A' + 10; else abort(); } 

Donc, faire toute la chaîne ressemble à ceci:

 void hex2ascii(const ssortingng& in, ssortingng& out) { out.clear(); out.reserve(in.length() / 2); for (ssortingng::const_iterator p = in.begin(); p != in.end(); p++) { unsigned char c = hexval(*p); p++; if (p == in.end()) break; // incomplete last digit - should report error c = (c << 4) + hexval(*p); // + takes precedence over << out.push_back(c); } } 

Vous pouvez raisonnablement demander pourquoi on le ferait de cette façon quand il y a strtol , et son utilisation consum beaucoup moins de code (comme dans la réponse de James Curran). Eh bien, cette approche est plus lente en ordre décimal complet , car elle copie chaque bloc de deux octets (en allouant éventuellement de la mémoire de tas), puis appelle une routine de conversion de texte en nombre qui ne peut pas être écrite aussi efficacement que le code spécialisé ci-dessus. L'approche de Christian (en utilisant issortingngstream) est cinq fois plus lente que cela . Voici un graphique de référence - vous pouvez faire la différence même avec un minuscule bloc de données à décoder, et il devient flagrant à mesure que les différences s'agrandissent. (Notez que les deux axes sont sur une échelle de journal.)

Benchmark de comparaison

Est-ce l'optimisation prématurée? Sûrement pas. C'est le genre d'opération qui est insérée dans une routine de bibliothèque, oubliée, puis appelée des milliers de fois par seconde. Il faut crier. J'ai travaillé sur un projet il y a quelques années qui utilisait énormément les sums de contrôle SHA1 en interne. Nous avons enregistré des accélérations de 10 à 20% sur les opérations courantes en les stockant sous forme d'octets bruts au lieu d'hex, en les convertissant uniquement lorsque nous devions les montrer au utilisateur - et c’est avec les fonctions de conversion déjà réglées à mort. On peut honnêtement préférer la brièveté à la performance ici, en fonction de la tâche la plus importante, mais si oui, pourquoi croyez-vous en C ++?

De plus, d’un sharepoint vue pédagogique, je pense qu’il est utile de montrer des exemples codés à la main pour ce type de problème; cela en dit plus sur ce que l'ordinateur doit faire.

Je ne peux pas commenter, mais la solution de zwol a un bug:

 c = c << 4 + hexval(*p); 

est correctement

 c = (c << 4) + hexval(*p); 

comme l'opérateur de décalage a une priorité inférieure à celle d'append

 std::ssortingng str("48656c6c6f"); std::ssortingng res; res.reserve(str.size() / 2); for (int i = 0; i < str.size(); i += 2) { std::istringstream iss(str.substr(i, 2)); int temp; iss >> std::hex >> temp; res += static_cast(temp); } std::cout << res; 

strtol devrait faire le travail si vous ajoutez 0x à chaque paire de chiffres hexadécimaux.