borrar una matriz de caracteres c


104

Pensé que al establecer el primer elemento en un valor nulo se borraría todo el contenido de una matriz de caracteres.

char my_custom_data[40] = "Hello!";
my_custom_data[0] = '\0';

Sin embargo, esto solo establece el primer elemento en nulo.

o

my_custom_data[0] = 0; 

en lugar de usar memset, pensé que los 2 ejemplos anteriores deberían borrar todos los datos.


1
Jared, ¿por qué estableciste la etiqueta c ++? habló sobre "C" y no agregó etiquetas relacionadas con C ++.
Johannes Schaub - litb

1
Esto se aplica igualmente bien a las matrices de caracteres en C ++, aunque no lo especificó.
Adam Hawes

4
Eliminé la etiqueta C ++ para evitar lo que ya hemos visto con personas que ofrecen soluciones específicas de C ++
Alnitak

Respuestas:


113

Depende de cómo desee ver la matriz. Si está viendo la matriz como una serie de caracteres, entonces la única forma de borrar los datos es tocar cada entrada. memsetes probablemente la forma más eficaz de lograrlo.

Por otro lado, si elige ver esto como una cadena C / C ++ terminada en nulo, establecer el primer byte en 0 borrará efectivamente la cadena.


4
La palabra clave en la respuesta es "efectivamente". Solo el primer elemento comienza a establecerse en 0 y el resto todavía tiene valores indefinidos, pero si está tratando la matriz como una cadena terminada en nulo y el primer elemento es nulo, entonces la cadena se considera vacía.
Arnold Spence

de hecho, esta es la respuesta, amigos.
Johannes Schaub - litb

@caparcode, exactamente. Por eso es muy importante comprender cómo se utiliza la matriz.
JaredPar

Sí, eso es lo que debería haber dicho en mi primera publicación. El char es una cadena terminada. así que estos harán ese truco. char [0] = '\ 0'; o char [0] = 0. No estoy seguro, pero escuché que usar '\ 0' es mejor para usar cadenas terminadas en nulo.
ant2009

@robUK, sí, tienes razón. Técnicamente, '\ 0' es igual a 0 (en ascii) pero debes usar '\ 0' porque deja clara tu intención
Mark Testa

70

Una matriz en C es solo una ubicación de memoria, por lo que, de hecho, su my_custom_data[0] = '\0';asignación simplemente establece el primer elemento en cero y deja los otros elementos intactos.

Si desea borrar todos los elementos de la matriz, deberá visitar cada elemento. Para eso memsetsirve:

memset(&arr[0], 0, sizeof(arr));

Por lo general, esta es la forma más rápida de solucionar este problema. Si puede usar C ++, considere std :: fill en su lugar:

char *begin = &arr;
char *end = begin + sizeof(arr);
std::fill(begin, end, 0);

1
Creo que la segunda versión debería ser: std :: fill (arr, arr + sizeof (arr) / sizeof (arr [0]), 0);
David Rodríguez - dribeas

Aclaración: no use sizeof con fill porque tendrá problemas más adelante con matrices de int, long, double o lo que sea.
Zan Lynx

Prefiero: std :: fill (& arr [0], & arr [arr_len], 0);
Zan Lynx

Zan Lynx, ese es un comportamiento indefinido. no puedes hacer & arr [arr_len]. pero tienes que hacer std :: fill (arr, arr + sizeof arr, 0); o si tiene la longitud en algún lugar std :: fill (arr, arr + arr_len, 0); asumiendo una variedad de char
Johannes Schaub - litb

Es válido solo en C. aunque la pregunta estaba claramente dirigida a C (otro tipo agregó una etiqueta de C ++, no tengo ni idea de por qué), el std :: fill muestra afinidad de C ++ :)
Johannes Schaub - litb

25

¿Por qué pensaría que establecer un solo elemento borraría toda la matriz? En C, especialmente, pocas cosas pasan sin que el programador lo programe explícitamente. Si establece el primer elemento en cero (o cualquier valor), entonces ha hecho exactamente eso, y nada más.

Al inicializar, puede establecer una matriz en cero:

char mcd[40] = {0}; /* sets the whole array */

De lo contrario, no conozco ninguna otra técnica que no sea memset, o algo similar.


Supongo que esto depende del compilador que uses
cocoafan

1
@cocoafan: No, no depende del compilador. Es parte de la especificación del lenguaje. Cualquier compilador que se comporte de manera diferente no sigue el lenguaje C.
abelenky

No lo sabía, gracias. No pude encontrar ningún recurso donde pueda leer este caso especial. Sería bueno tenerlo como marcador.
cocoafan

1
Se llama inicialización parcial. No tengo la especificación C99, pero aquí hay dos fuentes: bit.ly/enBC2m "No es necesario inicializar todos los elementos de una matriz. Si una matriz se inicializa parcialmente, los elementos que no se inicializan reciben el valor 0 de el tipo apropiado ". bit.ly/f9asHH "Si hay menos inicializadores que elementos en la matriz, los elementos restantes se inicializan automáticamente a 0"
abelenky

Esto no se aplica a una matriz que ya ha sido declarada y con valores asignados, ¿verdad?
skinnedKnuckles

10

Utilizar:

memset(my_custom_data, 0, sizeof(my_custom_data));

O:

memset(my_custom_data, 0, strlen(my_custom_data));

1
La segunda opción ( memset(my_custom_data, 0, strlen(my_custom_data));) solo se borrará hasta el primer '\ 0', que podría estar más allá del final de la matriz. Esto puede estar bien o no.
brewmanz

9

Prueba el siguiente código:

void clean(char *var) {
    int i = 0;
    while(var[i] != '\0') {
        var[i] = '\0';
        i++;
    }
}

2
FYI: sangra el código con 4 espacios o selecciónalo y presiona el botón 'código', que parece dos líneas de binario.
meagar

Excelente solución si no desea incluir string.h para memset ().
Akash Agarwal


6

Por favor, encuentre a continuación donde he explicado con datos en la matriz después del caso 1 y el caso 2.

char sc_ArrData[ 100 ];
strcpy(sc_ArrData,"Hai" );

Caso 1:

sc_ArrData[0] = '\0';

Resultado:

-   "sc_ArrData"
[0] 0 ''
[1] 97 'a'
[2] 105 'i'
[3] 0 ''

Caso 2:

memset(&sc_ArrData[0], 0, sizeof(sc_ArrData));

Resultado:

-   "sc_ArrData"
[0] 0 ''
[1] 0 ''
[2] 0 ''
[3] 0 ''

Aunque configurar el primer argumento en NULL hará el truco, es aconsejable usar memset


4

No Todo lo que está haciendo es establecer el primer valor en '\ 0' o 0.

Si está trabajando con cadenas terminadas en nulo, en el primer ejemplo, obtendrá un comportamiento que imita lo que espera, sin embargo, la memoria todavía está configurada.

Si desea borrar la memoria sin usar memset, use un bucle for.


Digo no en el bucle for. Trate de no escribir sus propias funciones de biblioteca "mejoradas" (y generalmente no). De hecho, memset y memcpy son bastante especiales y a menudo se incluyen en el código de máquina personalizado para la CPU en función de lo que se conoce sobre la alineación y la longitud de los datos.
Zan Lynx

@Zan the OP no quiere usar Memset (tal vez esté incrustado y no lo tenga disponible). Pero sí, memset suele ser muy óptimo y probablemente más rápido que un bucle for.
Adam Hawes

Es cierto, sin embargo, no quería usar memset, así que sugerí un bucle for.
Alan


2

Escribir un carácter nulo en el primer carácter hace precisamente eso. Si lo trata como una cadena, el código que obedece al carácter de terminación nula lo tratará como una cadena nula, pero eso no es lo mismo que borrar los datos. Si realmente desea borrar los datos, deberá usar memset.



1

Pensé que al establecer el primer elemento en un valor nulo se borraría todo el contenido de una matriz de caracteres.

Eso no es correcto como descubriste

Sin embargo, esto solo establece el primer elemento en nulo.

¡Exactamente!

Necesita usar memset para borrar todos los datos, no es suficiente establecer una de las entradas como nula.

Sin embargo, si establecer un elemento de la matriz en nulo significa algo especial (por ejemplo, cuando se usa una cadena de terminación nula en), podría ser suficiente establecer el primer elemento en nulo. De esa manera, cualquier usuario de la matriz entenderá que está vacía aunque la matriz todavía incluya los caracteres antiguos en la memoria.


No use "memset" sobre la legibilidad: stackoverflow.com/questions/453432/…
Johann Gerell

1

establezca el primer elemento en NULL. imprimir la matriz de caracteres no le devolverá nada.



-3
void clearArray (char *input[]){
    *input = ' '; 
}

1
¡Esto no es BORRAR, simplemente establece el primer carácter en ''! Creo que querías escribir * input = '\ 0'
stviper

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.