Löschen eines char-Arrays c


104

Ich dachte, wenn Sie das erste Element auf null setzen, wird der gesamte Inhalt eines char-Arrays gelöscht.

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

Dies setzt jedoch nur das erste Element auf null.

oder

my_custom_data[0] = 0; 

Anstatt zu verwenden memset, dachte ich, dass die 2 obigen Beispiele alle Daten löschen sollten.


1
Jared, warum hast du das c ++ - Tag gesetzt? Er sprach über "C" und fügte keine C ++ - Tags hinzu.
Johannes Schaub - litb

1
Dies gilt ebenso gut für Zeichenarrays in C ++, obwohl er dies nicht angegeben hat.
Adam Hawes

4
Ich habe das C ++ - Tag entfernt, um zu vermeiden, was wir bereits bei Leuten gesehen haben, die C ++ - spezifische Lösungen anbieten
Alnitak

Antworten:


113

Dies hängt davon ab, wie Sie das Array anzeigen möchten. Wenn Sie das Array als eine Reihe von Zeichen anzeigen, können Sie die Daten nur löschen, indem Sie jeden Eintrag berühren. memsetist wahrscheinlich der effektivste Weg, um dies zu erreichen.

Wenn Sie dies jedoch als nullterminierte C / C ++ - Zeichenfolge anzeigen, wird die Zeichenfolge durch Löschen des ersten Bytes auf 0 effektiv gelöscht.


4
Das Schlüsselwort in der Antwort lautet "effektiv". Nur das erste Element wird auf 0 gesetzt und der Rest hat noch undefinierte Werte. Wenn Sie das Array jedoch als nullterminierte Zeichenfolge behandeln und das erste Element null ist, wird die Zeichenfolge als leer betrachtet.
Arnold Spence

in der Tat ist dies die Antwort Leute.
Johannes Schaub - litb

@caparcode genau. Deshalb ist es sehr wichtig zu verstehen, wie das Array verwendet wird.
JaredPar

Ja, das hätte ich in meinem ersten Beitrag sagen sollen. Das Zeichen ist eine terminierte Zeichenfolge. Also werden diese beiden diesen Trick machen. char [0] = '\ 0'; oder char [0] = 0. Ich bin nicht sicher, aber ich habe gehört, dass die Verwendung von '\ 0' besser für die Verwendung von nullterminierten Zeichenfolgen ist.
Ant2009

@robUK, ja du bist richtig. Technisch gesehen ist '\ 0' gleich 0 (in ASCII), aber Sie sollten '\ 0' verwenden, da dies Ihre Absicht klar macht
Mark Testa

70

Ein Array in C ist nur ein Speicherort. In der Tat setzt Ihre my_custom_data[0] = '\0';Zuweisung das erste Element einfach auf Null und lässt die anderen Elemente intakt.

Wenn Sie alle Elemente des Arrays löschen möchten, müssen Sie jedes Element besuchen. Dafür ist da memset:

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

Dies ist im Allgemeinen der schnellste Weg, dies zu erledigen. Wenn Sie C ++ verwenden können, ziehen Sie stattdessen std :: fill in Betracht:

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

1
Ich glaube, die zweite Version sollte sein: std :: fill (arr, arr + sizeof (arr) / sizeof (arr [0]), 0);
David Rodríguez - Dribeas

Klarstellung: Verwenden Sie sizeof nicht mit fill, da Sie später Probleme mit Arrays von int, long, double oder was haben Sie haben.
Zan Lynx

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

Zan Lynx, das ist undefiniertes Verhalten. Sie können & arr [arr_len] nicht tun. aber du musst std :: fill machen (arr, arr + sizeof arr, 0); oder wenn Sie die Länge irgendwo haben std :: fill (arr, arr + arr_len, 0); Annahme einer Reihe von char
Johannes Schaub - litb

Es ist nur in C gültig. Obwohl die Frage eindeutig auf C abzielte (ein anderer Typ hat ein C ++ - Tag hinzugefügt, ich habe keine Ahnung warum), zeigt die std :: fill die C ++ - Affinität :)
Johannes Schaub - litb

25

Warum sollte das Setzen eines einzelnen Elements das gesamte Array löschen? Insbesondere in C passiert nie etwas, ohne dass der Programmierer es explizit programmiert. Wenn Sie das erste Element auf Null (oder einen beliebigen Wert) setzen, haben Sie genau das getan und nichts weiter.

Bei der Initialisierung können Sie ein Array auf Null setzen:

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

Ansonsten kenne ich keine andere Technik als Memset oder ähnliches.


Ich denke, das hängt von dem Compiler ab, den Sie verwenden
Cocoafan

1
@cocoafan: Nein, es ist nicht vom Compiler abhängig. Es ist Teil der Sprachspezifikation. Jeder Compiler, der sich anders verhält, folgt nicht der C-Sprache.
Abelenky

Das wusste ich nicht, danke. Ich konnte keine Ressource finden, in der ich diesen Sonderfall lesen kann. Wäre schön, es als Lesezeichen zu haben.
Cocoafan

1
Dies wird als Teilinitialisierung bezeichnet. Ich habe die C99-Spezifikation nicht, aber hier sind zwei Quellen: bit.ly/enBC2m "Sie müssen nicht alle Elemente in einem Array initialisieren. Wenn ein Array teilweise initialisiert wird, erhalten nicht initialisierte Elemente den Wert 0 von der entsprechende Typ. " bit.ly/f9asHH "Wenn das Array weniger Initialisierer als Elemente enthält, werden die verbleibenden Elemente automatisch auf 0 initialisiert"
abelenky

Dies gilt nicht für ein Array, das bereits deklariert und mit Werten versehen wurde, oder?
SkinnedKnuckles

10

Verwenden:

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

Oder:

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

1
Die zweite Option ( memset(my_custom_data, 0, strlen(my_custom_data));) wird nur bis zum ersten '\ 0' gelöscht, das möglicherweise über das Ende des Arrays hinausgeht. Dies kann in Ordnung sein oder auch nicht.
Brewmanz

9

Versuchen Sie den folgenden Code:

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

2
FYI - Code um 4 Leerzeichen einrücken oder auswählen und auf die Schaltfläche 'Code' klicken, die wie zwei Binärzeilen aussieht.
Meagar

Hervorragende Lösung, wenn Sie string.h für memset () nicht einschließen möchten.
Akash Agarwal


6

Bitte finden Sie unten, wo ich mit Daten im Array nach Fall 1 und Fall 2 erklärt habe.

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

Fall 1:

sc_ArrData[0] = '\0';

Ergebnis:

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

Fall 2:

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

Ergebnis:

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

Obwohl das Setzen des ersten Arguments auf NULL ausreicht, ist die Verwendung von memset ratsam


4

Nee. Sie setzen lediglich den ersten Wert auf '\ 0' oder 0.

Wenn Sie mit nullterminierten Zeichenfolgen arbeiten, erhalten Sie im ersten Beispiel ein Verhalten, das Ihren Erwartungen entspricht, der Speicher ist jedoch weiterhin festgelegt.

Wenn Sie den Speicher ohne Verwendung von memset löschen möchten, verwenden Sie eine for-Schleife.


Ich sage nein in der for-Schleife. Versuchen Sie, keine eigenen "verbesserten" (und normalerweise nicht) Bibliotheksfunktionen zu schreiben. Tatsächlich sind memset und memcpy eher speziell und werden häufig in benutzerdefinierten Maschinencode für die CPU eingefügt, basierend auf dem, was über Datenausrichtung und -länge bekannt ist.
Zan Lynx

@Zan das OP möchte kein Memset verwenden (vielleicht ist er eingebettet und hat es nicht verfügbar). Aber ja, Memset ist normalerweise sehr optimal und wahrscheinlich schneller als eine for-Schleife.
Adam Hawes

Es stimmt, aber er wollte kein Memset verwenden, also schlug ich eine for-Schleife vor.
Alan


2

Das Schreiben eines Nullzeichens in das erste Zeichen bewirkt genau das. Wenn Sie es als Zeichenfolge behandeln, wird es durch Code, der dem Nullterminierungszeichen folgt, als Nullzeichenfolge behandelt. Dies entspricht jedoch nicht dem Löschen der Daten. Wenn Sie die Daten tatsächlich löschen möchten, müssen Sie memset verwenden.



1

Ich dachte, wenn Sie das erste Element auf null setzen, wird der gesamte Inhalt eines char-Arrays gelöscht.

Das ist nicht richtig, wie Sie entdeckt haben

Dies setzt jedoch nur das erste Element auf null.

Genau!

Sie müssen memset verwenden, um alle Daten zu löschen. Es reicht nicht aus, einen der Einträge auf null zu setzen.

Wenn das Setzen eines Elements des Arrays auf null jedoch etwas Besonderes bedeutet (z. B. bei Verwendung einer nullterminierenden Zeichenfolge in), kann es ausreichend sein, das erste Element auf null zu setzen. Auf diese Weise wird jeder Benutzer des Arrays verstehen, dass es leer ist, obwohl das Array noch die alten Zeichen im Speicher enthält


Verwenden Sie "memset" nicht über der Lesbarkeit: stackoverflow.com/questions/453432/…
Johann Gerell

1

Setzen Sie das erste Element auf NULL. Wenn Sie das char-Array drucken, erhalten Sie nichts zurück.



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

1
Dies ist nicht CLEARING, sondern setzt nur das erste Zeichen auf ''! Ich denke du wolltest schreiben * input = '\ 0'
stviper

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.