Enthält std :: string einen Nullterminator?

87

Enthält die folgende Zeichenfolge den Nullterminator '\ 0'?

std::string temp = "hello whats up";

Vielen Dank! :) :)

Herr
quelle
1
Derzeit steht die akzeptierte Antwort von @jahhaj im Widerspruch zur Antwort von user529758, dessen Antwort wohl aktueller ist. Beim Durchlesen habe ich den Kommentar von Jesse Good übersprungen, daher ist dies hier, um seine Bedeutung hervorzuheben.
Jonathan Komar

Antworten:

98

Nein, aber wenn Sie sagen, dass temp.c_str()ein Nullterminator in der Rückgabe dieser Methode enthalten ist.

Es ist auch erwähnenswert, dass Sie wie jedes andere Zeichen ein Nullzeichen in eine Zeichenfolge einfügen können.

string s("hello");
cout << s.size() << ' ';
s[1] = '\0';
cout << s.size() << '\n';

druckt

5 5

und nicht 5 1wie zu erwarten, wenn Nullzeichen eine besondere Bedeutung für Zeichenfolgen haben.

jahhaj
quelle
5
Wenn Sie temp.c_str()das Nullzeichen aufrufen , wird es eingeschlossen. Wenn Sie es wirklich in der Zeichenfolge benötigen, fügen Sie es einfach wie jedes andere Zeichen hinzu. temp.push_back('\0'). Jetzt temp.c_str()gehören zwei Nullzeichen.
Jahhaj
1
@dupdupdup, wie in einigen Antworten erwähnt, sollten Sie, wenn Sie eine nullterminierte Zeichenfolge benötigen, eine s.c_str () für das konstruierte Objekt aufrufen. Es wird ein Zeiger auf ein Zeichenarray zurückgegeben, das am Ende garantiert '\ 0' hat.
Maksim Skurydzin
@Rico, Jahhaj Wie man dann den String beendet. Zum Beispiel - Ich habe meiner Zeichenfolge einige Zeichen als str [i] hinzugefügt. Jetzt kann ich es nicht mit cout drucken.
Bhavuk Mathur
Um Ihren Punkt zu ergänzen: Da der Operator << so überladen ist, druckt cout << s zwar die vollständige Zeichenfolge char für char, aber wenn Sie c_str () nehmen und auf operator << setzen, wird bis zum gedruckt null char. Das folgende Programm verlässt diesen Punkt. {string s ("SampleString"); cout << s.size () << "\ t" << s << endl; s [3] = '\ 0'; cout << "\ n \ n Nach Null \ n \ n" << s.size () << "\ t" << s << endl; cout << "\ n \ n Nehmen von c_str \ n \ n" << s.size () << "\ t" << s.c_str () << endl; }
Fooo
70

Nicht in C ++ 03, und es wird nicht einmal vor C ++ 11 garantiert, dass in einem C ++ std :: string im Speicher fortlaufend ist. Nur C-Strings (char-Arrays, die zum Speichern von Strings vorgesehen sind) hatten den Null-Terminator.

In C ++ 11 und höher mystring.c_str()ist äquivalent zu mystring.data()äquivalent zu &mystring[0]und mystring[mystring.size()]ist garantiert '\0'.

Quuxpluson
quelle
4
Mit C ++ 11 ist jetzt garantiert, dass Zeichenfolgen im Speicher zusammenhängend sind.
Zneak
@zneak danke! Aktualisiert. Aber ich bezweifle, dass es zumindest vernünftigerweise C ++ 11-Compilant-Compiler gibt ... sogar GCC hat die Unterstützung dafür gebrochen.
4
@ H2CO3: C ++ 11 beiseite, dies wurde in adressiert DR 530 in 2005 . Die überwiegende Mehrheit der Standardbibliotheksimplementierungen hat Zeichenfolgendaten mindestens genauso lange im zusammenhängenden Speicher gespeichert.
ildjarn
3
Danke @ildjarn, genau das habe ich gesucht. Ein Grund für den Umzug war, dass niemand im Ausschuss von einer STL-Implementierung wusste, bei der kein kontinuierlicher Speicher verwendet wurde.
Zneak
7
@ H2CO3: Ehrlich gesagt, wenn dich das beleidigt, brauchst du dickere Haut.
ildjarn
8

Dies hängt von Ihrer Definition von "enthalten" hier ab. Im

std::string temp = "hello whats up";

Es gibt einige Dinge zu beachten:

  • temp.size()gibt die Anzahl der Zeichen vom ersten hbis zum letzten zurück p(beide inklusive)
  • Aber zur gleichen Zeit temp.c_str()oder temp.data()wird mit einem nullTerminator zurückkehren
  • Oder mit anderen Worten int(temp[temp.size()])wird Null sein

Ich weiß, ich ähnlich klingen hier , um einige der Antworten , aber ich möchte darauf hinweisen , dass sizeder std::stringin C++wird separat gehalten und es ist nicht wie in Cdem Sie das Zählen halten , wenn Sie die erste finden nullTerminator.

Um hinzuzufügen, wäre die Geschichte ein wenig anders, wenn Ihre string literalenthält eingebettet \0. In diesem Fall std::stringstoppt die Konstruktion des ersten nullZeichens wie folgt:

std::string s1 = "ab\0\0cd";   // s1 contains "ab",       using string literal
std::string s2{"ab\0\0cd", 6}; // s2 contains "ab\0\0cd", using different ctr
std::string s3 = "ab\0\0cd"s;  // s3 contains "ab\0\0cd", using ""s operator

Verweise:

aniliitb10
quelle
2

Ja, wenn Sie aufrufen temp.c_str(), wird eine nullterminierte C-Zeichenfolge zurückgegeben.

Die tatsächlich im Objekt gespeicherten Daten sind tempmöglicherweise nicht nullterminiert, aber es spielt keine Rolle und sollte für den Programmierer keine Rolle spielen, denn wenn der Programmierer dies wünscht const char*, würde er c_str()das Objekt aufrufen , das garantiert null zurückgibt -terminierte Zeichenfolge.

Nawaz
quelle
1
Der Nullterminator (falls vorhanden) wird auch nicht in die Rückgabe von einbezogen temp.size().
Jahhaj
1

Mit C ++ - Zeichenfolgen müssen Sie sich darüber keine Gedanken machen, und dies hängt möglicherweise von der Implementierung ab.

Mit erhalten temp.c_str()Sie eine C-Darstellung der Zeichenfolge, die definitiv das \0Zeichen enthält. Abgesehen davon sehe ich nicht wirklich, wie nützlich es für eine C ++ - Zeichenfolge wäre

Naps62
quelle
1

std::stringintern zählt die Anzahl der Zeichen. Intern funktioniert es mit dieser Zählung. Wie andere gesagt haben, wenn Sie die Zeichenfolge für die Anzeige benötigen oder aus welchem ​​Grund auch immer, können Sie ihre c_str()Methode verwenden, die Ihnen die Zeichenfolge mit dem Nullterminator am Ende gibt.

Übermensch
quelle
Können Sie einige Referenzen für diese Anweisung geben, "std :: string zählt intern die Anzahl der Zeichen. Intern funktioniert es mit dieser Anzahl"
rimalonfire