HOWTO · C++
Convierte la cadena en hexadecimal en C++
Este artículo introduce cómo convertir una cadena a un valor hexadecimal en C++
En esta página
Convertir un std::string a hexadecimal en C++ significa producir una representación de texto de los bytes de la cadena: cada char se convierte en un valor de dos dígitos en base 16, de modo que "Hello" se convierte en 48656c6c6f. Necesitas esto para depurar datos binarios, generar sumas de comprobación o huellas digitales y proporcionar datos a protocolos que esperan cargas útiles codificadas en hexadecimal.
Este artículo muestra cómo imprimir la salida hexadecimal directamente, cómo construir un std::string hexadecimal reutilizable, cómo mantener cada byte en dos dígitos y cómo se relaciona el resultado con la codificación de texto; después compara los enfoques para que puedas elegir el adecuado.
Convertir una cadena a bytes hexadecimales
El enfoque más directo recorre la entrada un byte cada vez y escribe cada valor en std::cout en base 16. El manipulador de flujo std::hex cambia la salida de enteros a hexadecimal, y std::setw(2) con std::setfill('0') mantiene cada byte en dos dígitos. Iterar con unsigned char mantiene cada byte en el intervalo 0–255, de modo que los bytes por encima de 0x7f se formatean correctamente incluso en plataformas donde el char simple tiene signo. Ejecuta este ejemplo:
El ejemplo se conserva en inglés byte por byte; muestra cómo la entrada "Hello" se imprime como 48656c6c6f.
El código y las etiquetas o salidas visibles de esta sección se mantienen en inglés.
#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 permanece activo hasta que lo cambies, así que configúralo una vez antes del bucle. std::setw(2) solo se aplica al siguiente valor insertado, por eso va dentro del bucle, mientras que std::setfill('0') persiste. Imprimir en std::cout funciona bien para una inspección rápida, pero el texto convertido desaparece en cuanto se desplaza fuera de la pantalla; la siguiente sección lo conserva.
Construir y almacenar una cadena hexadecimal
Cuando necesites el texto convertido más adelante —para devolverlo desde una función, añadirlo a un mensaje de registro o escribirlo en un archivo—, acumúlalo en un std::stringstream en lugar de std::cout. Se aplican los mismos manipuladores de formato, y str() produce un std::string que contiene el resultado:
El ejemplo se conserva en inglés byte por byte; su salida muestra las etiquetas string: y hexval: sin traducir, junto al texto de entrada y su valor hexadecimal.
El código y las etiquetas o salidas visibles de esta sección se mantienen en inglés.
#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
Como toHex devuelve un std::string, quien llama decide qué hacer con él: imprimirlo, almacenarlo o pasarlo a un flujo de archivo. El ejemplo solo imprime el valor; escribirlo en un archivo es un paso aparte mediante std::ofstream, que acepta el mismo texto hexadecimal.
Formatear cada byte con dos dígitos hexadecimales
Un byte contiene un valor de 0 a 255 —de 0x00 a 0xff—, por lo que dos dígitos siempre bastan. Sin relleno, los valores por debajo de 0x10 se imprimen como un solo dígito, lo que vuelve ambigua la salida: el par de bytes 0x01, 0x0a y el byte único 0x1a producirían ambos 1a. std::setw(2) establece el ancho mínimo de campo y std::setfill('0') proporciona el carácter de relleno:
El ejemplo se conserva en inglés byte por byte; usa una entrada que contiene un byte intermedio 0x0a para mostrar por qué el relleno evita la ambigüedad.
El código y las etiquetas o salidas visibles de esta sección se mantienen en inglés.
#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
El byte del medio es 0x0a y aun así se imprime como dos dígitos. Quita std::setw y std::setfill y la misma entrada se imprime como 41a42, donde ya no se puede saber dónde termina un byte y empieza el siguiente. Mantén std::setw dentro del bucle —se restablece después de cada valor formateado—, mientras que std::setfill solo necesita configurarse una vez.
Comprender los valores de byte y la codificación de texto
Todos los ejemplos hasta ahora convierten bytes, no caracteres. std::string almacena una secuencia de char, y el bucle formatea el valor numérico de cada uno. Para una entrada ASCII esta distinción es invisible —H es el byte único 0x48—, pero importa para otros textos. En UTF-8, é (punto de código U+00E9) se almacena como los dos bytes 0xc3 0xa9, por lo que el mismo bucle produce c3a9 en lugar de e9:
El ejemplo se conserva en inglés byte por byte; el comentario del código permanece en inglés y la salida muestra c3a9, correspondiente a los bytes UTF-8 de é.
#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
Por tanto, las funciones de este artículo describen los bytes codificados de lo que contenga la cadena. Si necesitas puntos de código hexadecimales en su lugar, decodifica primero el texto y formatea los valores decodificados. El manejo de bytes sin signo importa por la misma razón: donde el char simple tiene signo, un byte como 0xc3 se convierte en un valor por debajo de cero y sale por el flujo como ffffffc3. Iterar con unsigned char —o pasar por él en la conversión antes de static_cast<int>— mantiene el valor en 0xc3.
Elegir un enfoque de conversión
Usa el bucle directo de std::cout cuando solo necesites inspeccionar los datos una vez. Devuelve un std::string construido con std::stringstream cuando el resultado deba sobrevivir a la llamada: es la opción de propósito general más legible y mantiene el formato de std::hex, std::setw y std::setfill en un solo lugar.
Una tercera opción divide cada byte en sus dos mitades de 4 bits (nibbles) y asigna cada una mediante una tabla de búsqueda:
El ejemplo se conserva en inglés byte por byte; convierte la entrada literal "World" y muestra su representación hexadecimal.
El código y las etiquetas o salidas visibles de esta sección se mantienen en inglés.
#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 versión con tabla de búsqueda siempre emite exactamente dos dígitos por byte y no aplica formato mediante flujos, lo que algunas bases de código prefieren por coherencia. Si es más rápida depende de tu implementación de la biblioteca estándar, así que mide con tus propios datos si eso importa. Elijas el enfoque que elijas, el resultado describe bytes: para texto ASCII se lee como un par por carácter, y para UTF-8 o datos binarios se lee como un par por byte codificado.