cancellare un array di caratteri c


104

Ho pensato che impostando il primo elemento su un null sarebbe stato cancellato l'intero contenuto di un array di caratteri.

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

Tuttavia, questo imposta solo il primo elemento su null.

o

my_custom_data[0] = 0; 

piuttosto che usare memset, ho pensato che i 2 esempi sopra dovrebbero cancellare tutti i dati.


1
Jared, perché hai impostato il tag c ++? ha parlato di "C" e non ha aggiunto alcun tag relativo a C ++.
Johannes Schaub - litb

1
Ciò si applica ugualmente bene agli array di caratteri in C ++, anche se non ha specificato.
Adam Hawes

4
Ho rimosso il tag C ++ per evitare ciò che abbiamo già visto con persone che offrono soluzioni specifiche per C ++
Alnitak

Risposte:


113

Dipende da come si desidera visualizzare l'array. Se stai visualizzando l'array come una serie di caratteri, l'unico modo per cancellare i dati è toccare ogni voce. memsetè probabilmente il modo più efficace per ottenere questo risultato.

D'altra parte, se si sceglie di visualizzarlo come una stringa con terminazione null C / C ++, l'impostazione del primo byte su 0 cancellerà effettivamente la stringa.


4
La parola chiave nella risposta è "efficace". Solo il primo elemento è impostato su 0 e il resto ha ancora valori indefiniti, ma se si tratta l'array come una stringa con terminazione null e il primo elemento è null, la stringa è considerata vuota.
Arnold Spence

in effetti, questa è la risposta, gente.
Johannes Schaub - litb

@caparcode, esattamente. Ecco perché è molto importante capire come viene utilizzato l'array.
JaredPar

Sì, è quello che avrei dovuto dire nel mio primo post. Il carattere è una stringa terminata. quindi entrambi faranno quel trucco. char [0] = "\ 0"; o char [0] = 0. Non sono sicuro, ma ho sentito che usare "\ 0" è meglio per usare stringhe con terminazione null.
ant2009

@robUK, sì hai ragione. Tecnicamente "\ 0" è uguale a 0 (in ascii) ma dovresti usare "\ 0" perché rende chiara la tua intenzione
Mark Testa

70

Un array in C è solo una posizione di memoria, quindi l' my_custom_data[0] = '\0';assegnazione imposta semplicemente il primo elemento a zero e lascia gli altri elementi intatti.

Se vuoi cancellare tutti gli elementi dell'array, dovrai visitare ogni elemento. Questo è ciò che memsetserve:

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

Questo è generalmente il modo più veloce per occuparsene. Se puoi usare C ++, considera invece std :: fill:

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

1
Credo che la seconda versione dovrebbe essere: std :: fill (arr, arr + sizeof (arr) / sizeof (arr [0]), 0);
David Rodríguez - dribeas

Chiarimento: non usare sizeof con fill perché avrai problemi in seguito con array di int, long, double o cosa hai.
Zan Lynx

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

Zan Lynx, questo è un comportamento indefinito. non puoi fare & arr [arr_len]. ma devi fare std :: fill (arr, arr + sizeof arr, 0); o se hai la lunghezza da qualche parte std :: fill (arr, arr + arr_len, 0); assumendo una matrice di caratteri
Johannes Schaub - litb

È valido solo in C. sebbene la domanda fosse chiaramente mirata a C (un altro ragazzo ha aggiunto un tag C ++, non ho idea del perché), lo std :: fill mostra l'affinità C ++ :)
Johannes Schaub - litb

25

Perché pensi che l'impostazione di un singolo elemento cancelli l'intero array? In C, soprattutto, accade poco senza che il programmatore lo programmi esplicitamente. Se imposti il ​​primo elemento su zero (o qualsiasi valore), hai fatto esattamente questo e nient'altro.

Durante l'inizializzazione è possibile impostare un array su zero:

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

Altrimenti, non conosco altra tecnica oltre al memset o qualcosa di simile.


Immagino che questo dipenda dal compilatore che usi
cocoafan

1
@cocoafan: No, non dipende dal compilatore. Fa parte della specifica del linguaggio. Qualsiasi compilatore che si comporta in modo diverso non segue il linguaggio C.
abelenky

Non lo sapevo, grazie. Non sono riuscito a trovare alcuna risorsa in cui leggere questo caso speciale. Sarebbe bello averlo come segnalibro.
cocoafan

1
Si chiama inizializzazione parziale. Non ho la specifica C99, ma qui ci sono due fonti: bit.ly/enBC2m "Non è necessario inizializzare tutti gli elementi in un array. Se un array è parzialmente inizializzato, gli elementi che non sono inizializzati ricevono il valore 0 di il tipo appropriato. " bit.ly/f9asHH "Se ci sono meno inizializzatori rispetto agli elementi nell'array, gli elementi rimanenti vengono automaticamente inizializzati a 0"
abelenky

Questo non si applica a un array che è già stato dichiarato e assegnato valori, vero?
skinnedKnuckles

10

Uso:

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

O:

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

1
La seconda opzione ( memset(my_custom_data, 0, strlen(my_custom_data));) verrà cancellata solo al primo '\ 0', che potrebbe essere oltre la fine della matrice. Questo può, o non può, andare bene.
brewmanz

9

Prova il codice seguente:

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

2
Cordiali saluti: rientra il codice di 4 spazi o selezionalo e premi il pulsante "codice", che assomiglia a due righe di binario.
meagar

Ottima soluzione se non vuoi includere string.h per memset ().
Akash Agarwal


6

Pls trova di seguito dove ho spiegato con i dati nella matrice dopo il caso 1 e il caso 2.

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

Caso 1:

sc_ArrData[0] = '\0';

Risultato:

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

Caso 2:

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

Risultato:

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

Sebbene l'impostazione del primo argomento su NULL risolva il problema, è consigliabile utilizzare memset


4

No. Tutto quello che stai facendo è impostare il primo valore su "\ 0" o 0.

Se stai lavorando con stringhe con terminazione nulla, nel primo esempio otterrai un comportamento che imita ciò che ti aspetti, tuttavia la memoria è ancora impostata.

Se vuoi cancellare la memoria senza usare memset, usa un ciclo for.


Dico di no al ciclo for. Cerca di non scrivere le tue funzioni di libreria "migliorate" (e di solito no). In effetti, memset e memcpy sono piuttosto speciali e spesso vengono inseriti nel codice macchina personalizzato per la CPU in base a ciò che si conosce sull'allineamento e la lunghezza dei dati.
Zan Lynx

@Zan l'OP non vuole usare memset (forse è incorporato e non lo ha disponibile). Ma sì, memset di solito è altamente ottimale e probabilmente più veloce di un ciclo for.
Adam Hawes

È vero, tuttavia non voleva usare memset, quindi ho suggerito un ciclo for.
Alan


2

Scrivere un carattere nullo sul primo carattere fa proprio questo. Se lo consideri come una stringa, il codice che obbedisce al carattere di terminazione null lo tratterà come una stringa nulla, ma non è la stessa cosa che cancellare i dati. Se vuoi effettivamente cancellare i dati dovrai usare memset.



1

Ho pensato che impostando il primo elemento su un null sarebbe stato cancellato l'intero contenuto di un array di caratteri.

Non è corretto come hai scoperto

Tuttavia, questo imposta solo il primo elemento su null.

Esattamente!

È necessario utilizzare memset per cancellare tutti i dati, non è sufficiente impostare una delle voci su null.

Tuttavia, se impostare un elemento dell'array su null significa qualcosa di speciale (ad esempio quando si utilizza una stringa di terminazione null in) potrebbe essere sufficiente impostare il primo elemento su null. In questo modo qualsiasi utente dell'array capirà che è vuoto anche se l'array include ancora i vecchi caratteri in memoria


Non utilizzare "memset" over leggibilità: stackoverflow.com/questions/453432/...
Johann Gerell

1

imposta il primo elemento su NULL. la stampa dell'array di caratteri non ti restituirà nulla.



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

1
Questo non è AZZERANTE, sta solo impostando il primo carattere su ""! Penso che volessi scrivere * input = '\ 0'
stviper

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.