2012-06-13 10 views
5

Necesito buscar en un trozo de memoria una cadena de caracteres, pero varias de estas cadenas tienen cada carácter nulo separado, como este:
"I. .am. a. .string "
con todos los '.' s son caracteres nulos. Mi problema proviene de poner esto en la memoria. He intentado varias maneras, por ejemplo:Manipulación de cadenas C con múltiples caracteres nulos en la memoria

char* str2; 
str2 = (char*)malloc(sizeof(char)*40); 
memcpy((void*)str2, "123\0567\09abc", 12);  

pondrá lo siguiente en la memoria que los puntos str2 a: 123.7.9abc..
Algo así como
str2 = "123456789\0abcde\054321";
tendrá str2 que apunta a un bloque de memoria que las apariencias como 123456789.abcde,321, donde el '.' es un personaje nulo, y el ',' es una coma real.

Así que insertar claramente caracteres nulos en cadenas de caracteres no funciona tan fácilmente como pensé, como insertar un carácter de nueva línea. Encontré dificultades similares para probar esto con la biblioteca de cadenas también. Que podía hacer asignaciones separadas, algo así como:

char* str;  
str = (char*)malloc(sizeof(char)*40); 
strcpy(str, "123"); 
strcpy(str+4, "abc"); 
strcpy(str+8, "ABC"); 

Pero eso no es ciertamente preferible, y creo que el problema radica en mi entendimiento de cómo las cadenas de c-estilo se almacenan en la memoria. Claramente, "abc \ 0123" no entra realmente en la memoria como 61 62 63 00 31 32 33 (en hexadecimal). ¿Cómo se almacena y cómo puedo almacenar lo que necesito?

(también me disculpo por no haber configurado el código en bloques, esta es la primera vez que publico una pregunta, y de alguna manera "cuatro espacios" es más difícil de lo que puedo manejar aparentemente. Gracias, Luchian. Veo más nuevas líneas fueron necesarios.)

+0

Utilice el botón {} por encima de la ventana de edición, o Ctrl-K, para crear bloques de código. –

Respuesta

6

Si cada char contiene un nulo, es casi seguro que realmente tenga cadenas codificadas en UTF-16. Procese en consecuencia y sus problemas desaparecerán.

Suponiendo que está en Windows, donde UTF-16 es común, debería utilizar wchar_t* en lugar de char* para contener tales cadenas. Y utilizaría funciones de procesamiento de cadenas de caracteres anchas para operar con dichos datos. Por ejemplo, use wcscpy en lugar de strcpy y así sucesivamente.

+0

Esto definitivamente resolvió mi problema práctico y me permite implementar la búsqueda fácilmente. Esta es la primera vez que he programado en Windows, y no había encontrado caracteres anchos antes, así que cuando miro los volcados binarios nunca se me ocurrió. Y seguí pensando en lo extraño que era anular la terminación de cada personaje ... = P Refp a continuación también me ayudó a descubrir qué estaba causando el problema que estaba teniendo hacerlo a la vieja usanza. – Fulluphigh

2

En primer lugar, cada segundo carácter que es un NULL es una clara característica de una cadena ancha, una cadena compuesta por caracteres de dos bytes, realmente una matriz de unsigned short s. Dependiendo de su compilador y configuraciones, es mejor que use el tipo de datos wchar_t en lugar de char y wcsxxx() familia de funciones en lugar de strxxx().

En Windows, las cadenas de 2 bytes (UTF-16, técnicamente) es el formato de cadena nativo del sistema operativo, por lo que están por todas partes.

Dicho esto, las funciones strxxx() asumen que la cadena tiene terminación nula. Así que planifique en consecuencia. Algunas veces memxxx() vendrá al rescate.

"abc \ 0123" no entra en la memoria de la forma esperada porque \ 012 está siendo interpretado por el compilador como una única secuencia de escape octal: el carácter con el código octal 12 (que es 0a hex). Para evitar, utilice uno de los siguientes literales:

"abc\000123" 
"abc\x00123" 
"abc\0""123" 

El fragmento donde se genera una cadena a partir de trozos es sobre todo correcto.Es sólo que prefiero usar

strcpy(str+strlen(str)+1, "123"); 

que garantiza que el siguiente fragmento se escribirá más allá del carácter nulo de la porción anterior.

+2

\ 054 está siendo interpretado por el compilador como una única secuencia de escape octal. Octal 54 es hex 2c. Para crear una cadena verdadera con un nulo incorporado, utilice el siguiente literal: "abcde \ 00054321" o "abcde \ 0" "54321", o "abcde \ x0054321". El analizador de secuencia de escape se está igualando codiciosamente, obviamente. Se adhieren a los literales de cadena que no permiten una interpretación ambigua. –

+0

@Roddy: la edición lleva tiempo :) –

0

estoy un poco confundido por su pregunta. Pero déjame adivinar qué está pasando. Usted está mirando una cadena wchat_t de 16 bits y no una cadena c normal. wchar obtener caracteres ascii puede parecer nulo separado entre letras, pero en realidad esto es normal.

simple (wchar_t *) XXX donde XXX es un puntero a esa región de memoria y operaciones wchar_t de búsqueda como wcscpy etc ... en cuanto a los nulos entre cadenas, este puede ser un método conocido para pasar múltiples construcciones de cadena. Simplemente puede iterar después de leer cada cadena hasta que normalmente encuentre 2 nulos consecutivos.

esperanza he respondido a su pregunta. ¡Buena suerte!

3

\0 es la secuencia de arranque de un carácter de escape en octetos, que no es sólo un "carácter nulo " (a pesar de que el uso de su propio dará lugar a uno).


La forma más sencilla de definir una cadena que contiene una nulo carácter seguido de algo que también podría ser entendido como una parte de un characer escapado en el octeto (por ejemplo, "\ 012" ) es dividirlo usando esta función por debajo de C:

char const * p = "123456789" "\0" "abcde" "\0" "54321"; 

1. "\ 012" se traducirá en el carácter con el valor hexadecimal equivalente de 0x0A, no tres caracteres; 0x00, '1' y '2'.

+0

Excelente respuesta. La respuesta de David anterior funciona perfectamente para lo que necesito hacer, pero aún no sabía qué estaba causando este comportamiento. No sabía que los octetos fueran algo de lo que pudieras escapar de esta manera. Gracias, excelente respuesta. No tengo suficientes representantes para votar, pero sí. – Fulluphigh

+0

@Joshua Es una buena idea familiarizarse con la sintaxis básica de su lenguaje de programación. Aquí hay una referencia útil para C: http://ieng9.ucsd.edu/~cs30x/Std.C/syntax.html –

Cuestiones relacionadas