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.

ant2009
fuente
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.

JaredPar
fuente
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);
John Feminella
fuente
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.

abelenky
fuente
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));
Jake1164
fuente
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++;
    }
}
Cristian Altamirano
fuente
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
7

¿Por qué no usar memset()? Así es como se hace.

La configuración del primer elemento deja intacto el resto de la memoria, pero las funciones str tratarán los datos como vacíos.

John Fricker
fuente
1
No use memset sobre la legibilidad: stackoverflow.com/questions/453432/…
Johann Gerell
1
y cual es tu respuesta entonces?
mkb
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

Codificador Akaanthan
fuente
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.

Alan
fuente
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
3

Deberías usar memset. Establecer solo el primer elemento no funcionará, debe establecer todos los elementos; si no es así, ¿cómo podría establecer solo el primer elemento en 0?

Miguel
fuente
memset no debe usarse en exceso de legibilidad: stackoverflow.com/questions/453432/…
Johann Gerell
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.

tvanfosson
fuente
2

Normalmente me gusta esto:

memset(bufferar, '\0', sizeof(bufferar));
Jevgenij Kononov
fuente
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.

hhafez
fuente
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.


fuente
1

¿Qué tal lo siguiente?

bzero(my_custom_data,40);
codeconnundrum
fuente
-3
void clearArray (char *input[]){
    *input = ' '; 
}
lobo
fuente
1
¡Esto no es BORRAR, simplemente establece el primer carácter en ''! Creo que querías escribir * input = '\ 0'
stviper
-4

Intente lo siguiente:

strcpy(my_custom_data,"");
Greg Grady
fuente