Est-ce que std :: string contient un terminateur nul?

87

La chaîne ci-dessous contiendra-t-elle le terminateur nul '\ 0'?

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

Merci! :)

Monsieur
la source
1
À l'heure actuelle, la réponse acceptée de @jahhaj est en conflit avec la réponse de user529758, dont la réponse est sans doute plus à jour. En regardant attentivement, j'ai sauté le commentaire de Jesse Good, c'est donc ici pour souligner son importance.
Jonathan Komar le

Réponses:

99

Non, mais si vous dites temp.c_str()qu'un terminateur nul sera inclus dans le retour de cette méthode.

Cela vaut également la peine de dire que vous pouvez inclure un caractère nul dans une chaîne comme n'importe quel autre caractère.

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

impressions

5 5

et pas 5 1comme on pourrait s'y attendre si les caractères nuls avaient une signification particulière pour les chaînes.

jahhaj
la source
5
Si vous appelez, temp.c_str()le caractère nul sera inclus. Si vous en avez vraiment besoin dans la chaîne, ajoutez-le simplement comme n'importe quel autre caractère. temp.push_back('\0'). Maintenant , temp.c_str()comprendra deux caractères nuls.
jahhaj
1
@dupdupdup, comme certaines réponses l'ont mentionné, si vous avez besoin d'une chaîne terminée par un nul, vous devez appeler un s.c_str () sur l'objet construit. Il renverra un pointeur vers un tableau de caractères dont la fin est garantie d'avoir «\ 0».
Maksim Skurydzin
@Rico, Jahhaj Comment terminer la chaîne alors. Par exemple - j'ai ajouté quelques caractères à ma chaîne en tant que str [i]. Maintenant, je ne peux pas l'imprimer en utilisant cout.
Bhavuk Mathur
Pour ajouter à votre point: comme l'opérateur << est surchargé, cout << s, affichera bien la chaîne complète char par char, mais, si vous prenez c_str () et mettez l'opérateur <<, il imprimera jusqu'à ce que le caractère nul. programme suivant illustre ce point. {string s ("SampleString"); cout << s.size () << "\ t" << s << endl; s [3] = '\ 0'; cout << "\ n \ n Après Null \ n \ n" << s.size () << "\ t" << s << endl; cout << "\ n \ n Prenant c_str \ n \ n" << s.size () << "\ t" << s.c_str () << endl; }
Fooo
70

Pas en C ++ 03, et il n'est même pas garanti avant C ++ 11 que dans un C ++ std :: string soit continu en mémoire. Seules les chaînes C (tableaux de caractères destinés à stocker des chaînes) avaient le terminateur nul.

Dans C ++ 11 et versions ultérieures, mystring.c_str()équivaut à mystring.data()est équivalent à &mystring[0]et mystring[mystring.size()]est garanti '\0'.

Quuxplusone
la source
4
Avec C ++ 11, les chaînes sont désormais garanties d'être contiguës en mémoire.
zneak
@zneak merci! Mis à jour. Mais je doute qu'il y ait au moins raisonnablement des compilateurs compilants C ++ 11 ... même GCC en a cassé le support.
4
@ H2CO3: C ++ 11 mis à part, cela a été résolu dans DR 530 en 2005 . La grande majorité des implémentations de bibliothèques standard ont stocké des données de chaîne dans une mémoire contiguë pendant au moins aussi longtemps.
ildjarn
3
Merci @ildjarn, je cherchais cela exactement. Une partie de la justification de cette décision était que personne au sein du comité n'était au courant d'une implémentation de STL qui n'utilisait pas de mémoire continue.
zneak
7
@ H2CO3: Honnêtement, si cela vous a offensé, vous avez besoin d'une peau plus épaisse.
ildjarn
8

Cela dépend de votre définition de «contenir» ici. Dans

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

il y a peu de choses à noter:

  • temp.size()renverra le nombre de caractères du premier hau dernier p(les deux inclus)
  • Mais en même temps temp.c_str()ou temp.data()reviendra avec un nullterminateur
  • Ou en d'autres termes int(temp[temp.size()])sera nul

Je sais, je semble similaire à quelques - unes des réponses ici , mais je tiens à souligner que sized' std::stringen C++est maintenue séparément et il est pas comme dans Coù vous gardez le comptage à moins que vous trouvez la première nullterminaison.

Pour ajouter, l'histoire serait un peu différente si votre string literalcontient intégré \0. Dans ce cas, la construction des std::stringarrêts au premier nullcaractère, comme suit:

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

Références:

aniliitb10
la source
2

Oui, si vous appelez temp.c_str(), il renverra une chaîne de caractères terminée par null.

Cependant, les données réelles stockées dans l'objet temppeuvent ne pas être terminées par null, mais cela n'a pas d'importance et ne devrait pas avoir d'importance pour le programmeur, car quand le programmeur le veut const char*, il appellerait c_str()l'objet, ce qui est garanti pour retourner null - chaîne terminée.

Nawaz
la source
1
Le terminateur nul (s'il existe) ne sera pas non plus inclus dans le retour de temp.size().
jahhaj
1

Avec les chaînes C ++, vous n'avez pas à vous en soucier, et cela dépend peut-être de l'implémentation.

En utilisant, temp.c_str()vous obtenez une représentation C de la chaîne, qui contiendra certainement le \0char. A part ça, je ne vois pas vraiment en quoi cela serait utile sur une chaîne C ++

Siestes62
la source
1

std::stringconserve en interne un décompte du nombre de caractères. En interne, cela fonctionne en utilisant ce décompte. Comme d'autres l'ont dit, lorsque vous avez besoin de la chaîne pour l'affichage ou pour quelque raison que ce soit, vous pouvez c_str()utiliser sa méthode qui vous donnera la chaîne avec le terminateur nul à la fin.

Superman
la source
Pouvez-vous donner quelques références pour cette instruction, "std :: string conserve en interne un décompte du nombre de caractères. En interne, il fonctionne en utilisant ce décompte"
rimalonfire