Definieren einer Zeichenfolge ohne Null-Endzeichen (\0) am Ende

Lesezeit: 7 Minuten

Benutzeravatar von Ravi Gupta
Ravi Gupta

Welche verschiedenen Möglichkeiten gibt es in C/C++, um eine Zeichenfolge ohne nullbeendendes Zeichen (\0) am Ende zu definieren?

BEARBEITEN: Ich interessiere mich nur für Zeichen-Arrays und nicht für STL-Strings.

  • C/C++ ?? […..]

    – Prasun Saurav

    30. September 2010 um 6:33 Uhr

  • Das ist nicht ein String in C. In C ist ein String als ein Zeichenarray definiert, das durch das NUL-Zeichen abgeschlossen wird. Was Sie fragen, ist nur ein Zeichenarray.

    – paxdiablo

    30. September 2010 um 6:38 Uhr

  • Es scheint, dass viele Leute nur die gleiche Antwort wiederholen: Verwenden Sie std::string.

    – Alexander Rafferty

    30. September 2010 um 6:42 Uhr

  • std::string ist seit C++11 nullterminiert: de.cppreference.com/w/cpp/string/basic_string/data

    – Michael

    23. Februar 2018 um 19:26 Uhr

Benutzeravatar von kriss
kriss

Typisch wie ein anderer Poster schrieb:

char s[6] = {'s', 't', 'r', 'i', 'n', 'g'};

oder wenn Ihr aktueller C-Zeichensatz ASCII ist, was normalerweise zutrifft (heute nicht viel EBCDIC)

char s[6] = {115, 116, 114, 105, 110, 107};

Es gibt auch einen weitgehend ignorierten Weg, der nur in C (nicht C++) funktioniert.

char s[6] = "string";

Wenn die Arraygröße zu klein ist, um die abschließende 0 aufzunehmen (aber groß genug, um alle anderen Zeichen der konstanten Zeichenfolge aufzunehmen), wird die abschließende Null nicht kopiert, aber es ist immer noch gültiges C (aber ungültiges C++).

Natürlich geht das auch zur Laufzeit:

char s[6];
s[0] = 's';
s[1] = 't';
s[2] = 'r';
s[3] = 'i';
s[4] = 'n';
s[5] = 'g';

oder (gleiche Bemerkung zum ASCII-Zeichensatz wie oben)

char s[6];
s[0] = 115;
s[1] = 116;
s[2] = 114;
s[3] = 105;
s[4] = 110;
s[5] = 103;

Oder verwenden Sie memcopy (oder memmove oder bcopy, aber in diesem Fall hat dies keinen Vorteil).

memcpy(c, "string", 6);

oder strncpy

strncpy(c, "string", 6);

Was verstanden werden sollte ist, dass es so etwas wie einen String in C nicht gibt (in C++ gibt es String-Objekte, aber das ist eine ganz andere Geschichte). Sogenannte Strings sind nur Char-Arrays. Und schon der Name char ist irreführend, es ist kein char sondern nur eine Art numerischer Typ. Wir hätten es wahrscheinlich stattdessen Byte nennen können, aber in den alten Zeiten gab es seltsame Hardware, die 9-Bit-Register oder ähnliches verwendete, und Byte impliziert 8 Bit.

Da char sehr oft zum Speichern eines Zeichencodes verwendet wird, dachten C-Designer an einen einfacheren Weg, als eine Zahl in einem char zu speichern. Sie könnten einen Buchstaben zwischen einfache Anführungszeichen setzen und der Compiler würde verstehen, dass er diesen Zeichencode im char speichern muss.

Was ich meine ist (zum Beispiel), dass Sie es nicht tun müssen

char c="\0";

Um einen Code 0 in einem Zeichen zu speichern, tun Sie einfach:

char c = 0;

Da wir sehr oft mit einer Menge Zeichen variabler Länge arbeiten müssen, haben C-Designer auch eine Konvention für “Strings” gewählt. Setzen Sie einfach einen Code 0, wo der Text enden soll. Übrigens gibt es einen Namen für diese Art der String-Darstellung “nullterminierter String” und wenn Sie die beiden Buchstaben sz am Anfang eines Variablennamens sehen, bedeutet dies normalerweise, dass der Inhalt ein nullterminierter String ist.

“C sz strings” ist überhaupt kein Typ, nur ein Array von Zeichen, so normal wie beispielsweise ein Array von int, aber String-Manipulationsfunktionen (strcmp, strcpy, strcat, printf und viele viele andere) verstehen und verwenden die 0 Beendigungskonvention. Das bedeutet auch, dass Sie, wenn Sie ein char-Array haben, das nicht nullterminiert ist, keine dieser Funktionen aufrufen sollten, da dies wahrscheinlich etwas falsch macht (oder Sie müssen besonders vorsichtig sein und Funktionen mit a verwenden n Buchstaben in ihrem Namen wie streng).

Das größte Problem bei dieser Konvention ist, dass sie in vielen Fällen ineffizient ist. Ein typisches Beispiel: Sie möchten etwas an das Ende einer 0-terminierten Zeichenfolge setzen. Wenn Sie die Größe beibehalten hätten, könnten Sie einfach am Ende der Zeichenfolge springen, mit der sz-Konvention müssen Sie sie Zeichen für Zeichen überprüfen. Andere Probleme treten beim Umgang mit verschlüsseltem Unicode oder dergleichen auf. Aber zu der Zeit, als C erstellt wurde, war diese Konvention sehr einfach und erfüllte ihre Aufgabe perfekt.

Heutzutage sind die Buchstaben zwischen doppelten Anführungszeichen wie “String” keine einfachen Zeichenfelder wie früher, sondern const char *. Das bedeutet, dass das, worauf der Zeiger zeigt, eine Konstante ist, die nicht geändert werden sollte (wenn Sie sie ändern möchten, müssen Sie sie zuerst kopieren), und das ist eine gute Sache, weil es hilft, viele Programmierfehler zur Kompilierzeit zu erkennen.

  • +1, aber um pingelig zu sein, der Typ eines Zeichenfolgenliterals (dh "hi") ist nicht const char*sondern eher const char[3] wo 3 ist die Anzahl der Zeichen + 1 für die abschließende 0. Sie kann a direkt zugewiesen werden const char* da Arrays in Zeiger auf das erste Element zerfallen, aber dieser einfache Test zeigt den Unterschied: assert( sizeof(const char*) != sizeof("Hi there!") )

    – David Rodríguez – Dribeas

    30. September 2010 um 8:12 Uhr

  • @ David Rodríguez – dribeas: Ja, Sie haben Recht, aber ich glaube, meine Antwort ist bereits komplex genug, ohne Details zu Unterschieden zwischen Array-Typen und Zeigern hinzuzufügen. Für diejenigen, die sich für das Thema interessieren, habe ich versucht, es in dieser Antwort zu erklären: stackoverflow.com/questions/3613302/…

    – kriss

    30. September 2010 um 9:26 Uhr


Seths Benutzeravatar
Seth

Die abschließende Null dient dazu, den String abzuschließen. Ohne sie benötigen Sie eine andere Methode, um die Länge zu bestimmen.

Sie können eine vordefinierte Länge verwenden:

char s[6] = {'s','t','r','i','n','g'};

Sie können Zeichenfolgen im Pascal-Stil emulieren:

unsigned char s[7] = {6, 's','t','r','i','n','g'};

Sie können verwenden std::string (in C++). (da Sie nicht an std::string interessiert sind).

Vorzugsweise würden Sie eine bereits vorhandene Technologie verwenden, die Unicode verarbeitet oder zumindest die Zeichenfolgencodierung versteht (dh wchar.h).

Und ein Kommentar: Wenn Sie dies in ein Programm einfügen, das auf einem tatsächlichen Computer ausgeführt werden soll, sollten Sie erwägen, Ihre eigene “Zeichenfolge” zu definieren. Dies ermutigt Ihren Compiler zum Barfen, wenn Sie jemals versehentlich versuchen, es an eine Funktion zu übergeben, die einen String im C-Stil erwartet.

typedef struct {
    char[10] characters;
} ThisIsNotACString;

  • +1 für die bisher vollständigste Antwort, Hauptsache, es fehlt eine Diskussion darüber char s[3] = "abc";

    – Toni Delroy

    30. September 2010 um 7:01 Uhr

  • Wenn Sie so weit gehen, Ihren eigenen Strukturtyp zu definieren, hat es keinen Vorteil, length mit chars zu verwechseln, um Pascal-Strings zu emulieren. Es wäre viel sauberer, ein separates Feld für len zu haben. Es würde das zugrunde liegende Speicherlayout überhaupt nicht ändern, aber eine mögliche Verwirrung vermeiden.

    – kriss

    27. Juli 2017 um 9:44 Uhr

Benutzeravatar von Prasoon Saurav
Prasun Saurav

C++ std::strings sind nicht NUL-terminiert.

PS: NULL ist ein Makro1. NUL ist \0. Mischen Sie sie nicht.

1: C.2.2.3 Makro NULL

Das Makro NULL, definiert in einem von <clocale>, <cstddef>, <cstdio>, <cstdlib>, <cstring>,
<ctime>oder <cwchar>ist in dieser Internationalen Norm (18.1) eine implementierungsdefinierte C++-Nullzeigerkonstante.

  • NULL und NUL sind beide nur eine schicke Art, 0 zu sagen.

    – Alexander Rafferty

    30. September 2010 um 6:50 Uhr

  • Ich wünschte, ich könnte eine weitere +1 für diese NULL-Klarstellung mit Fußnote geben.

    – JoshD

    30. September 2010 um 6:55 Uhr

  • @Alexander Rafferty: NUL ist der Name des Nullzeichens ‘\0’, während NULL ein Nullzeiger ist. In C ist es normalerweise definiert als (void*)0während es in C++ nur ist 0. Beachten Sie, dass der Unterschied der Typ ist, nicht der Wert.

    – David Rodríguez – Dribeas

    30. September 2010 um 8:14 Uhr

  • Seit c++11 sind std::string nullterminiert.

    – Chaoran

    1. November 2018 um 1:58 Uhr

In C++ können Sie die Schnur Klasse und beschäftigen Sie sich überhaupt nicht mit dem Nullzeichen.

Nur der Vollständigkeit halber und festnageln Sie dies vollständig.

vector<char>

Benutzeravatar von JoshD
JoshD

Verwenden Sie std::string.

Es gibt Dutzende anderer Möglichkeiten, Strings zu speichern, aber die Verwendung einer Bibliothek ist oft besser, als eine eigene zu erstellen. Ich bin sicher, wir könnten uns alle viele verrückte Möglichkeiten einfallen lassen, Strings ohne Null-Terminatoren zu erstellen :).

Benutzeravatar von shuttle87
Shuttle87

In C wird es im Allgemeinen keine einfachere Lösung geben. Sie könnten möglicherweise tun, was Pascal getan hat, und die Länge der Zeichenfolge in das erste Zeichen einfügen, aber dies ist ein bisschen mühsam und begrenzt Ihre Zeichenfolgenlänge auf die Größe der Ganzzahl, die in den Platz des ersten Zeichens passt. In C++ würde ich definitiv die Klasse std::string verwenden, auf die zugegriffen werden kann

#include <string>

Da es sich um eine häufig verwendete Bibliothek handelt, ist dies mit ziemlicher Sicherheit zuverlässiger als das Rollen Ihrer eigenen Saitenklasse.

1387270cookie-checkDefinieren einer Zeichenfolge ohne Null-Endzeichen (\0) am Ende

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy