Std :: string contiene un terminatore nullo?


90

La stringa sottostante conterrà il terminatore nullo "\ 0"?

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

Grazie! :)



1
Allo stato attuale, la risposta accettata da @jahhaj è in conflitto con la risposta dell'utente529758, la cui risposta è probabilmente più aggiornata. Mentre leggevo, ho saltato il commento di Jesse Good, quindi questo è qui per sottolineare la sua importanza.
Jonathan Komar

Risposte:


100

No, ma se dici che temp.c_str()un terminatore nullo sarà incluso nel ritorno da questo metodo.

Vale anche la pena dire che puoi includere un carattere null in una stringa proprio come qualsiasi altro carattere.

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

stampe

5 5

e non 5 1come ci si potrebbe aspettare se i caratteri nulli avessero un significato speciale per le stringhe.


5
Se chiami temp.c_str()il carattere nullo verrà incluso. Se ne hai davvero bisogno nella stringa aggiungilo come qualsiasi altro carattere. temp.push_back('\0'). Ora temp.c_str()includerà due caratteri nulli.
jahhaj

1
@dupdupdup, come hanno menzionato alcune delle risposte, se hai bisogno di una stringa con terminazione null dovresti chiamare s.c_str () sull'oggetto costruito. Restituirà un puntatore alla matrice di caratteri che è garantito per avere "\ 0" alla fine.
Maksim Skurydzin

@Rico, Jahhaj Come terminare la stringa allora. Ad esempio: ho aggiunto alcuni caratteri alla mia stringa come str [i]. Ora non sono in grado di stamparlo usando cout.
Bhavuk Mathur

Per aggiungere al tuo punto: poiché l'operatore << è sovraccarico così, cout << s, sebbene stamperà la stringa completa carattere per carattere, ma, se prendi c_str () e metti l'operatore << stamperà fino al carattere nullo. il seguente programma descrive questo punto. {stringa s ("SampleString"); cout << s.size () << "\ t" << s << endl; s [3] = "\ 0"; cout << "\ n \ n Dopo Null \ n \ n" << s.size () << "\ t" << s << endl; cout << "\ n \ n Prendendo c_str \ n \ n" << s.size () << "\ t" << s.c_str () << endl; }
Fooo

71

Non in C ++ 03, e non è nemmeno garantito prima di C ++ 11 che in un C ++ std :: string sia continuo in memoria. Solo le stringhe C (array di caratteri destinati alla memorizzazione di stringhe) avevano il terminatore null.

In C ++ 11 e versioni successive, mystring.c_str()è equivalente a mystring.data()è equivalente a &mystring[0]ed mystring[mystring.size()]è garantito che sia '\0'.


4
Con C ++ 11, ora è garantito che le stringhe siano contigue in memoria.
zneak

@zneak grazie! Aggiornato. Ma dubito che ci siano almeno compilatori C ++ 11-compilant ragionevolmente ... anche GCC ha rotto il supporto per esso.

4
@ H2CO3: C ++ 11 a parte, questo problema è stato risolto in DR 530 nel 2005 . La stragrande maggioranza delle implementazioni di librerie standard ha archiviato i dati delle stringhe nella memoria contigua per almeno il tempo.
ildjarn

3
Grazie @ildjarn, stavo cercando esattamente quello. Parte della logica alla base del trasferimento era che nessuno nel comitato conosceva un'implementazione STL che non utilizzava la memoria continua.
zneak

7
@ H2CO3: Onestamente, se questo ti ha offeso, hai bisogno di una pelle più spessa.
ildjarn

9

Questo dipende dalla tua definizione di "contiene" qui. In

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

ci sono poche cose da notare:

  • temp.size()restituirà il numero di caratteri dal primo hall'ultimo p(entrambi inclusi)
  • Ma allo stesso tempo temp.c_str()o temp.data()tornerà con un nullterminatore
  • O in altre parole int(temp[temp.size()])sarà zero

Lo so, io suono simile ad alcune delle risposte qui, ma voglio sottolineare che sizedi std::stringa C++è mantenuta separatamente e non è come in Cdove si tiene il conteggio a meno che non si trova il primo nullTerminator.

Per aggiungere, la storia sarebbe leggermente diversa se string literalcontenesse incorporata \0. In questo caso, la costruzione di si std::stringferma al primo nullcarattere, come segue:

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

Riferimenti:


2

Sì, se chiami temp.c_str(), restituirà una stringa c con terminazione null.

Tuttavia, i dati effettivi memorizzati nell'oggetto temppotrebbero non essere terminati da null, ma non importa e non dovrebbe importare al programmatore, perché quando poi il programmatore lo desidera const char*, chiamerebbe c_str()l'oggetto, che è garantito per restituire null -tringa terminata.


1
Né il terminatore nullo (se esiste) sarà incluso nel ritorno da temp.size().
jahhaj

1

Con le stringhe C ++ non devi preoccuparti di questo e probabilmente dipende dall'implementazione.

Usando temp.c_str()ottieni una rappresentazione in C della stringa, che conterrà sicuramente il \0carattere. Oltre a questo, non vedo davvero come sarebbe utile su una stringa C ++


1

std::stringmantiene internamente un conteggio del numero di caratteri. Internamente funziona utilizzando questo conteggio. Come altri hanno detto, quando hai bisogno della stringa per la visualizzazione o per qualsiasi motivo, puoi usare il suo c_str()metodo che ti darà la stringa con il terminatore nullo alla fine.


Puoi fornire alcuni riferimenti per questa affermazione, "std :: string internamente tiene un conteggio del numero di caratteri. Internamente funziona usando questo conteggio"
rimalroshan
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.