2009-10-12 13 views
6

Dada una cadena de valores hexadecimales es decir p. "0011223344" por lo que es 0x00, 0x11, etc.matriz Hex a char en C

¿Cómo agrego estos valores a una matriz de caracteres?

equivale a decir:

char array[4] = { 0x00, 0x11 ... }; 

Respuesta

-3

En primer lugar, su pregunta no es muy precisa. ¿Es la cadena un buffer std::string o char? ¿Configurado en tiempo de compilación?

La memoria dinámica es casi seguro su respuesta.

char* arr = (char*)malloc(numberOfValues); 

Luego, puede recorrer la entrada y asignarla a la matriz.

+1

No es una cadena estándar :: esta es C y solo hay un tipo de cadena. –

+2

@Paul: ¿qué considera que es útil acerca de su respuesta? La pregunta es sobre "cómo recorrer la entrada y asignarla a una matriz" ... la cual deja cuidadosamente como ejercicio para el lector. –

+1

@jon: (1) C & C++ a veces se confunden, (2) Dejo las tareas como ejercicios para el solicitante, típicamente, y (3) esperaba * respuestas del OP para poder dar un mejor respuesta, pero hizo un "preguntar y correr". –

16

No puede incluir 5 bytes de datos en una matriz de 4 bytes; eso conduce a desbordamientos de búfer.

Si usted tiene los dígitos hexadecimales en una cadena, puede utilizar sscanf() y un bucle:

#include <stdio.h> 
#include <ctype.h> 

int main() 
{ 
    const char *src = "0011223344"; 
    char buffer[5]; 
    char *dst = buffer; 
    char *end = buffer + sizeof(buffer); 
    unsigned int u; 

    while (dst < end && sscanf(src, "%2x", &u) == 1) 
    { 
     *dst++ = u; 
     src += 2; 
    } 

    for (dst = buffer; dst < end; dst++) 
     printf("%d: %c (%d, 0x%02x)\n", dst - buffer, 
       (isprint(*dst) ? *dst : '.'), *dst, *dst); 

    return(0); 
} 

Tenga en cuenta que la impresión de la cadena que comienza con un cero bytes requiere atención; la mayoría de las operaciones terminan en el primer byte nulo. Tenga en cuenta que este código no anuló la terminación del búfer; no está claro si la terminación nula es deseable, y no hay suficiente espacio en el búfer que declare para agregar un terminal nulo (pero que se soluciona fácilmente). Existe una posibilidad decente de que si el código se empaquetó como una subrutina, tendría que devolver la longitud de la cadena convertida (aunque también podría argumentarse que es la longitud de la cadena fuente dividida entre dos).

+2

¡Esta respuesta me salvó las HORAS! de trabajo. Funciona muy bien para Arduino, simplemente omita la sección printf – frazras

3

Si la cadena es correcta y no hay necesidad de mantener su contenido y luego lo haría de esta manera:

#define hex(c) ((*(c)>='a')?*(c)-'a'+10:(*(c)>='A')?*(c)-'A'+10:*(c)-'0') 

void hex2char(char *to){ 
    for(char *from=to; *from; from+=2) *to++=hex(from)*16+hex(from+1); 
    *to=0; 
} 

EDIT 1: lo siento, no recuerdo para calcular con las letras AF (AF)

EDIT 2: i trató de escribir un código más pedante:

#include <string.h> 

int xdigit(char digit){ 
    int val; 
     if('0' <= digit && digit <= '9') val = digit -'0'; 
    else if('a' <= digit && digit <= 'f') val = digit -'a'+10; 
    else if('A' <= digit && digit <= 'F') val = digit -'A'+10; 
    else         val = -1; 
    return val; 
} 

int xstr2str(char *buf, unsigned bufsize, const char *in){ 
    if(!in) return -1; // missing input string 

    unsigned inlen=strlen(in); 
    if(inlen%2 != 0) return -2; // hex string must even sized 

    for(unsigned i=0; i<inlen; i++) 
    if(xdigit(in[i])<0) return -3; // bad character in hex string 

    if(!buf || bufsize<inlen/2+1) return -4; // no buffer or too small 

    for(unsigned i=0,j=0; i<inlen; i+=2,j++) 
    buf[j] = xdigit(in[i])*16 + xdigit(in[i+1]); 

    buf[inlen/2] = '\0'; 
    return inlen/2+1; 
}

Pruebas:

#include <stdio.h> 

char buf[100] = "test"; 

void test(char *buf, const char *s){ 
    printf("%3i=xstr2str(\"%s\", 100, \"%s\")\n", xstr2str(buf, 100, s), buf, s); 
} 

int main(){ 
    test(buf,  (char*)0 ); 
    test(buf,  "123"  ); 
    test(buf,  "3x"  ); 
    test((char*)0, ""  ); 
    test(buf,  ""  ); 
    test(buf,  "3C3e" ); 
    test(buf,  "3c31323e"); 

    strcpy(buf, "616263" ); test(buf, buf); 
}

Resultado:

-1=xstr2str("test", 100, "(null)") 
-2=xstr2str("test", 100, "123") 
-3=xstr2str("test", 100, "3x") 
-4=xstr2str("(null)", 100, "") 
    1=xstr2str("", 100, "") 
    3=xstr2str("", 100, "3C3e") 
    5=xstr2str("", 100, "3c31323e") 
    4=xstr2str("abc", 100, "abc") 
+0

Esto supone que puedes modificar la cadena, y hace la traducción in situ, y null termina la cadena convertida. Dado que el primer byte es nulo, es probable que deba devolver el número de caracteres convertidos. –

+0

Usted es cierto, pero la pregunta no formula los requisitos, por lo que este código es lo suficientemente bueno ;-) – sambowry

+0

Es posible que desee considerar el apoyo de dígitos hexadecimales por encima de 9, también.Si la única cadena requerida para trabajar es la dada en la pregunta, entonces obviamente la respuesta más concisa es 'char array [] = {0, 17, 34, 51, 68};'. Pero creo que cuando el interlocutor dijo "es decir", en realidad quiso decir "p. Ej." –

0

Fatalfloor ...

Hay un par de maneras de hacer esto ... en primer lugar, se puede utilizar memcpy() para copiar la imagen misma en la matriz de caracteres.

También puede usar técnicas de cambio de bits y enmascaramiento de bits. Supongo que esto es lo que debes hacer ya que suena como un problema de tarea.

Por último, puede utilizar un direccionamiento de fantasía para copiar la ubicación de la memoria que necesita.

Todos estos métodos se detallan aquí:

Store an int in a char array?

+0

¿Le gustaría aclarar cómo se puede usar memcpy()? –

3

me gustaría hacer algo como esto;

// Convert from ascii hex representation to binary 
// Examples; 
// "00" -> 0 
// "2a" -> 42 
// "ff" -> 255 
// Case insensitive, 2 characters of input required, no error checking 
int hex2bin(const char *s) 
{ 
    int ret=0; 
    int i; 
    for(i=0; i<2; i++) 
    { 
     char c = *s++; 
     int n=0; 
     if('0'<=c && c<='9') 
      n = c-'0'; 
     else if('a'<=c && c<='f') 
      n = 10 + c-'a'; 
     else if('A'<=c && c<='F') 
      n = 10 + c-'A'; 
     ret = n + ret*16; 
    } 
    return ret; 
} 

int main() 
{ 
    const char *in = "0011223344"; 
    char out[5]; 
    int i; 

    // Hex to binary conversion loop. For example; 
    // If in="0011223344" set out[] to {0x00,0x11,0x22,0x33,0x44} 
    for(i=0; i<5; i++) 
    { 
     out[i] = hex2bin(in); 
     in += 2; 
    } 
    return 0; 
} 
0

Dale una mejor manera:

Hex cadena de valor numérico, es decir, str [] = "0011223344" a valorar 0x0011223344, utilice

value = strtoul(string, NULL, 16); // or strtoull() 

hecho. si es necesario eliminar el comienzo de 0x00, ver abajo.

aunque para plataformas LITTLE_ENDIAN, más: valor Hex a char array, valor 0x11223344 a char matriz [N] = {0x00, 0x11, ...}

unsigned long *hex = (unsigned long*)arr; 
*hex = htonl(value); 
// you'd like to remove any beginning 0x00 
char *zero = arr; 
while (0x00 == *zero) { zero++; } 
if (zero > arr) memmove(zero, arr, sizeof(arr) - (zero - arr)); 

hecho. Notas: Para convertir cadenas largas en 64 bits en un sistema de 32 bits, debe usar unsigned long long en lugar de unsigned long, y htonl no es suficiente, hágalo usted mismo como se indica a continuación porque podría no hay htonll, htonq o hton64 etc:

#if __KERNEL__ 
    /* Linux Kernel space */ 
    #if defined(__LITTLE_ENDIAN_BITFIELD) 
     #define hton64(x) __swab64(x) 
    #else 
     #define hton64(x) (x) 
    #endif 
#elif defined(__GNUC__) 
    /* GNU, user space */ 
    #if __BYTE_ORDER == __LITTLE_ENDIAN 
     #define hton64(x) __bswap_64(x) 
    #else 
     #define hton64(x) (x) 
    #endif 
#elif 
     ... 
#endif 

#define ntoh64(x) hton64(x) 

ver http://effocore.googlecode.com/svn/trunk/devel/effo/codebase/builtin/include/impl/sys/bswap.h

+0

longitud máxima de cadena hexada admitida: 16 bytes/caracteres cuando el carácter inicial no es '0'. – Test

0
{ 
    char szVal[] = "268484927472"; 
    char szOutput[30]; 

    size_t nLen = strlen(szVal); 
    // Make sure it is even. 
    if ((nLen % 2) == 1) 
    { 
     printf("Error string must be even number of digits %s", szVal); 
    } 

    // Process each set of characters as a single character. 
    nLen >>= 1; 
    for (size_t idx = 0; idx < nLen; idx++) 
    { 
     char acTmp[3]; 
     sscanf(szVal + (idx << 1), "%2s", acTmp); 
     szOutput[idx] = (char)strtol(acTmp, NULL, 16); 
    } 
} 
0

que estaba buscando lo mismo y después de leer mucho, finalmente creé esta función. Pensó que podría ayudar, alguien

// in = "63 09 58 81" 
void hexatoascii(char *in, char* out, int len){ 
    char buf[5000]; 
    int i,j=0; 
    char * data[5000]; 
    printf("\n size %d", strlen(in)); 
    for (i = 0; i < strlen(in); i+=2) 
    { 
     data[j] = (char*)malloc(8); 
     if (in[i] == ' '){ 
      i++; 
     } 
     else if(in[i + 1] == ' '){ 
      i++; 
     } 
     printf("\n %c%c", in[i],in[i+1]); 
     sprintf(data[j], "%c%c", in[i], in[i+1]); 
     j++; 
    } 

    for (i = 0; i < j-1; i++){ 
     int tmp; 
     printf("\n data %s", data[i]); 
     sscanf(data[i], "%2x", &tmp); 
     out[i] = tmp; 
    } 
    //printf("\n ascii value of hexa %s", out); 
} 
0

Digamos que se trata de una plataforma ascii little-endian. Tal vez el OP significa "arreglo de char" en lugar de "cadena" .. Trabajamos con pares de carbón y el bit de enmascaramiento .. nota shiftyness de x16 ..

/* not my original work, on stacko somewhere ? */ 

for (i=0;i < 4;i++) { 

    char a = string[2 * i]; 
    char b = string[2 * i + 1]; 

    array[i] = (((encode(a) * 16) & 0xF0) + (encode(b) & 0x0F)); 
} 

y codificar la función() se define. ..

unsigned char encode(char x) {  /* Function to encode a hex character */ 
/**************************************************************************** 
* these offsets should all be decimal ..x validated for hex..    * 
****************************************************************************/ 
    if (x >= '0' && x <= '9')   /* 0-9 is offset by hex 30 */ 
     return (x - 0x30); 
    else if (x >= 'a' && x <= 'f') /* a-f offset by hex 57 */ 
     return(x - 0x57); 
    else if (x >= 'A' && x <= 'F') /* A-F offset by hex 37 */ 
     return(x - 0x37); 
} 

Este enfoque flota en otros lugares, no es mi trabajo original, pero es viejo. No me gustan los puristas porque no es portátil, pero la extensión sería trivial.