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.

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

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

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

Warum nicht verwenden memset()? So geht das.

Wenn Sie das erste Element festlegen, bleibt der Rest des Speichers unberührt, aber str-Funktionen behandeln die Daten als leer.

John Fricker
quelle
1
Verwenden Sie Memset nicht über Lesbarkeit: stackoverflow.com/questions/453432/…
Johann Gerell
1
und was ist deine Antwort dann?
mkb
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

Akaanthan Ccoder
quelle
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.

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

Sie sollten memset verwenden. Das Festlegen nur des ersten Elements funktioniert nicht. Sie müssen alle Elemente festlegen. Wenn nicht, wie können Sie nur das erste Element auf 0 setzen?

Michael
quelle
Memset sollte nicht über Lesbarkeit verwendet werden: stackoverflow.com/questions/453432/…
Johann Gerell
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.

Tvanfosson
quelle
2

Normalerweise mag ich das einfach so:

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

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


quelle
1

Wie wäre es mit folgendem:

bzero(my_custom_data,40);
Codeconnundrum
quelle
-3
void clearArray (char *input[]){
    *input = ' '; 
}
Wolf
quelle
1
Dies ist nicht CLEARING, sondern setzt nur das erste Zeichen auf ''! Ich denke du wolltest schreiben * input = '\ 0'
stviper
-4

Versuche Folgendes:

strcpy(my_custom_data,"");
Greg Grady
quelle