HOWTO · C++
Converti stringa in esadecimale in C++
Questo articolo introduce come convertire una stringa in un valore esadecimale in C++
In questa pagina
Convertire una std::string in esadecimale in C++ significa produrre una rappresentazione testuale dei byte della stringa: ogni char diventa un valore in base 16 a due cifre, quindi "Hello" diventa 48656c6c6f. Questa conversione serve per eseguire il debug di dati binari, generare checksum o fingerprint e alimentare protocolli che prevedono payload codificati in esadecimale.
Questo articolo mostra come stampare direttamente l’output esadecimale, come costruire una std::string esadecimale riutilizzabile, come mantenere ogni byte su due cifre e in che modo il risultato si collega alla codifica del testo; infine confronta gli approcci per aiutarti a scegliere quello più adatto.
Convertire una stringa in byte esadecimali
L’approccio più diretto scorre l’input un byte alla volta e scrive ogni valore su std::cout in base 16. Il manipolatore di flusso std::hex imposta la stampa degli interi in esadecimale, mentre std::setw(2) con std::setfill('0') mantiene ogni byte su due cifre. Iterare con unsigned char mantiene ogni byte nell’intervallo 0–255, quindi i byte sopra 0x7f vengono formattati correttamente anche sulle piattaforme in cui un semplice char è con segno. Esegui questo esempio:
Il codice e le etichette o gli output visibili in questa sezione restano in inglese.
#include <iomanip>
#include <iostream>
#include <string>
int main() {
std::string input = "Hello";
std::cout << std::hex << std::setfill('0');
for (unsigned char c : input) {
std::cout << std::setw(2) << static_cast<int>(c);
}
std::cout << '\n';
}
48656c6c6f
std::hex resta attivo finché non viene modificato, quindi va impostato una sola volta prima del ciclo. std::setw(2) si applica solo al prossimo valore inserito, motivo per cui si trova dentro il ciclo, mentre std::setfill('0') persiste. Stampare su std::cout è adatto a un controllo rapido, ma il testo convertito non è più disponibile dopo essere stato visualizzato; la sezione successiva mostra come conservarlo.
Costruire e memorizzare una stringa esadecimale
Quando il testo convertito serve più tardi — per restituirlo da una funzione, aggiungerlo a un messaggio di log o scriverlo in un file — accumulalo in un std::stringstream invece di inviarlo a std::cout. Valgono gli stessi manipolatori di formattazione e str() produce una std::string che contiene il risultato:
Il codice e le etichette o gli output visibili in questa sezione restano in inglese.
#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>
std::string toHex(const std::string& input) {
std::stringstream ss;
ss << std::hex << std::setfill('0');
for (unsigned char c : input) {
ss << std::setw(2) << static_cast<int>(c);
}
return ss.str();
}
int main() {
std::string text = "C++ Programming";
std::string hexText = toHex(text);
std::cout << "string: " << text << '\n';
std::cout << "hexval: " << hexText << '\n';
}
string: C++ Programming
hexval: 432b2b2050726f6772616d6d696e67
Poiché toHex restituisce una std::string, è il chiamante a decidere cosa farne: stamparla, conservarla o passarla a uno stream di file. L’esempio stampa soltanto il valore — le etichette string: e hexval: nell’output restano in inglese e mostrano il testo di input seguito dalla sua forma esadecimale — mentre la scrittura in un file è un passaggio separato tramite std::ofstream, che accetta lo stesso testo esadecimale.
Formattare ogni byte con due cifre esadecimali
Un byte contiene un valore da 0 a 255 — da 0x00 a 0xff — quindi due cifre sono sempre sufficienti. Senza riempimento, i valori inferiori a 0x10 vengono stampati con una sola cifra e l’output diventa ambiguo: la coppia di byte 0x01, 0x0a e il singolo byte 0x1a produrrebbero entrambi 1a. std::setw(2) imposta la larghezza minima del campo e std::setfill('0') fornisce il carattere di riempimento:
Il codice e le etichette o gli output visibili in questa sezione restano in inglese.
#include <iomanip>
#include <iostream>
#include <string>
int main() {
std::string input = "A\nB";
std::cout << std::hex << std::setfill('0');
for (unsigned char c : input) {
std::cout << std::setw(2) << static_cast<int>(c);
}
std::cout << '\n';
}
410a42
Il byte centrale è 0x0a e viene comunque stampato con due cifre. Se rimuovi std::setw e std::setfill, lo stesso input produce 41a42, dove non si capisce più dove finisca un byte e dove inizi il successivo. Mantieni std::setw dentro il ciclo — viene reimpostato dopo ogni valore formattato — mentre std::setfill va impostato una sola volta.
Comprendere i valori dei byte e la codifica del testo
Ogni esempio visto finora converte byte, non caratteri. std::string memorizza una sequenza di char e il ciclo formatta il valore numerico di ciascuno. Con un input ASCII questa distinzione è invisibile — H è il singolo byte 0x48 — ma conta per altro testo. In UTF-8, é (punto di codice U+00E9) è memorizzato come i due byte 0xc3 0xa9, quindi lo stesso ciclo produce c3a9 invece di e9:
Il codice e le etichette o gli output visibili in questa sezione restano in inglese.
#include <iomanip>
#include <iostream>
#include <string>
int main() {
std::string input = "\xc3\xa9"; // UTF-8 bytes for U+00E9
std::cout << std::hex << std::setfill('0');
for (unsigned char c : input) {
std::cout << std::setw(2) << static_cast<int>(c);
}
std::cout << '\n';
}
c3a9
Le funzioni di questo articolo descrivono quindi i byte codificati di ciò che la stringa contiene; il commento nel codice resta in inglese e indica che la stringa contiene i byte UTF-8 del punto di codice U+00E9. Se invece ti servono i punti di codice in esadecimale, decodifica prima il testo e formatta i valori decodificati. La gestione dei byte senza segno conta per lo stesso motivo: dove un semplice char è con segno, un byte come 0xc3 viene convertito in un valore minore di zero e inviato allo stream come ffffffc3. Iterando con unsigned char — oppure convertendo prima il valore in unsigned char e poi con static_cast<int> — il valore resta 0xc3.
Scegliere un approccio di conversione
Usa il ciclo diretto su std::cout quando devi solo ispezionare i dati una volta. Restituisci una std::string costruita con std::stringstream quando il risultato deve sopravvivere alla chiamata: è l’opzione generale più leggibile e mantiene in un unico punto la formattazione con std::hex, std::setw e std::setfill.
Una terza opzione divide ogni byte nelle sue due metà da 4 bit (nibble) e mappa ciascuna metà tramite una tabella di lookup:
Il codice e le etichette o gli output visibili in questa sezione restano in inglese.
#include <iostream>
#include <string>
std::string toHexLookup(const std::string& input) {
static const char digits[] = "0123456789abcdef";
std::string result;
result.reserve(input.size() * 2);
for (unsigned char c : input) {
result += digits[c >> 4];
result += digits[c & 0x0f];
}
return result;
}
int main() {
std::cout << toHexLookup("World") << '\n';
}
576f726c64
La versione con lookup emette sempre esattamente due cifre per byte e non esegue alcuna formattazione tramite stream, una caratteristica che alcune codebase preferiscono per coerenza. La sua eventuale maggiore velocità dipende dall’implementazione della libreria standard, quindi misura sui tuoi dati se è rilevante. Qualunque approccio tu scelga, il risultato descrive byte: per il testo ASCII si legge come una coppia per carattere, mentre per UTF-8 o dati binari si legge come una coppia per byte codificato.