tldr; Oui, ceci est garanti pour fonctionner, à moins que le flux ne soit initialement vide.
Il y a deux bits à considérer: le bit fail
et le bit eof
. std::getline
le fait, à partir de [string.io]:
Après avoir construit un objet sentry
, si la sentinelle se transforme en vrai, appelle str.erase()
et extraits puis de caractères est et les str
joint à comme si en appelant str.append(1, c)
[. ..] Si la fonction extrait pas de caractères, il appelle is.setstate(ios::failbit)
Et sentry
le fait, de [istream :: sentry]:
Effets: Si is.good()
est false
, appelle is.setstate(failbit)
. Sinon, prépare une entrée formatée ou non formatée. [...] Si is.rdbuf()->sbumpc()
ou is.rdbuf()->sgetc()
retours traits::eof()
, la fonction appelle setstate(failbit | eofbit)
Donc, étant donné tout cela, nous allons marcher à travers deux exemples:
Cas 1: "hello\n"
. Le premier appel à getline()
, the_stream.good()
est vrai, nous extrayons les caractères à travers le \n
, le flux est toujours good()
, et nous entrons dans le corps de la boucle avec line
mis à "hello"
.
Le deuxième appel à getline()
, le flux est encore good()
, de sorte que l'objet sentry
convertit en vrai, et nous appelons str.erase()
. La tentative d'extraction des caractères suivants échoue, puisque nous en avons terminé avec le flux, ainsi le failbit
est défini. Cela provoque le retour getline()
de convertir en faux afin que nous n'entrent pas dans le corps de la boucle une deuxième fois. À la fin de la boucle, line
est vide.
Cas 2: "goodbye"
, sans saut de ligne. Le premier appel à getline()
, the_stream.good()
est vrai, nous extrayons les caractères jusqu'à ce que nous atteignions eof()
.Le flux failbit
n'est pas encore défini, donc nous entrons toujours dans le corps de la boucle, avec la ligne définie sur "goodbye"
.
Le deuxième appel à getline()
, la construction de l'objet sentry
échoue parce que is.good()
est faux (is.good()
contrôles à la fois le eofbit
et le failbit
). En raison de cet échec, nous ne passons pas à la première étape de getline()
qui appelle str.erase()
. Et à cause de cet échec, le failbit
est réglé de sorte que nous n'entrons pas à nouveau dans le corps de la boucle. À la fin de la boucle, line
est toujours "goodbye"
.
Cas 3: ""
. Ici, getline()
n'extrayera aucun caractère, ainsi le failbit
est défini et la boucle n'est jamais entrée, et line
est toujours vide. Il existe plusieurs façons de distinguer ce cas de cas 1:
- Vous pouvez, à l'avant,
peek()
pour voir si le premier caractère est traits::eof()
avant de faire quoi que ce soit d'autre.
- Vous pouvez compter combien de fois vous entrez dans la boucle et vérifiez qu'elle est différente de zéro.
- Vous pouvez initialiser
line
à une valeur non vide de sentinelle. A la fin de la boucle, la ligne ne sera vide que si le flux se termine par le délimiteur.
Les flux de fichiers doivent se terminer par un saut de ligne. Ce test détectera un flux qui a ** seulement ** un seul saut de ligne ou qui se termine par ** deux ou plus de ** nouvelles lignes. –
Un flux de texte qui ne se termine pas par un saut de ligne n'est pas un flux d'entrée valide en C ou C++. Les opérations d'entrée sur ce flux ne sont pas nécessaires pour le gérer de manière rationnelle. –
Donc avec std :: stringstream the_stream (""); the_stream << "bonjour!"; est l'entrée illégale the_stream? Je crois que c'est ce que je reçois si je lis dans un fichier (en utilisant ifstream) qui ne se termine pas par un saut de ligne. – Jens