Plus précisément, je suis intéressé par istream& getline ( istream& is, string& str );
. Existe-t-il une option dans le constructeur d'ifstream pour lui demander de convertir tous les encodages de nouvelles lignes en ' \n sous le capot ? Je veux pouvoir appeler getline
et qu'il gère gracieusement toutes les fins de ligne.
Mise à jour : Pour clarifier, je veux être capable d'écrire du code qui compile presque n'importe où, et qui prend des données de presque n'importe où. Y compris les rares fichiers qui ont ' \r ' sans ' \n '. Minimiser les inconvénients pour les utilisateurs du logiciel.
Il est facile de contourner le problème, mais je suis toujours curieux de savoir quelle est la bonne façon, dans la norme, de gérer de manière flexible tous les formats de fichiers texte.
getline
se lit sur une ligne complète, jusqu'à un '. \n dans une chaîne de caractères. La chaîne ' \n ' est consommé dans le flux, mais getline ne l'inclut pas dans la chaîne. Tout va bien jusqu'à présent, mais il se peut qu'il y ait un ' \r ' juste avant le ' \n qui est incluse dans la chaîne.
Il y a trois types de fin de ligne dans les fichiers texte : ' \n ' est la terminaison conventionnelle sur les machines Unix, ' \r était (je crois) utilisé sur les anciens systèmes d'exploitation Mac, et Windows utilise une paire, ' \r ' suivi de ' \n '.
Le problème est que getline
laisse l'option ' \r ' à la fin de la chaîne.
ifstream f("a_text_file_of_unknown_origin");
string line;
getline(f, line);
if(!f.fail()) { // a non-empty line was read
// BUT, there might be an '\r' at the end now.
}
Editer Merci à Neil de l'avoir signalé f.good()
n'est pas ce que je voulais. !f.fail()
c'est ce que je veux.
Je peux les supprimer manuellement (voir l'édition de cette question), ce qui est facile pour les fichiers texte de Windows. Mais je crains que quelqu'un n'introduise un fichier contenant uniquement des ' \r '. Dans ce cas, je suppose que getline consommera tout le fichier, pensant qu'il s'agit d'une seule ligne !
et c'est sans compter l'Unicode :-)
peut-être que Boost a une bonne façon de consommer une ligne à la fois à partir de n'importe quel type de fichier texte ?
Editer Je l'utilise pour gérer les fichiers Windows, mais j'ai toujours l'impression que je ne devrais pas avoir à le faire ! Et ce n'est pas le cas pour les fichiers ' \r Fichiers 'uniquement'.
if(!line.empty() && *line.rbegin() == '\r') {
line.erase( line.length()-1, 1);
}
2 votes
\n signifie nouvelle ligne, quelle que soit la manière dont elle est présentée dans le système d'exploitation actuel. La bibliothèque s'en charge. Mais pour que cela fonctionne, un programme compilé sous Windows doit lire les fichiers texte de Windows, un programme compilé sous Unix, les fichiers texte d'Unix, etc.
1 votes
@George, même si je compile sur une machine Linux, j'utilise parfois des fichiers texte provenant d'une machine Windows. Je vais peut-être publier mon logiciel (un petit outil d'analyse de réseau), et je veux pouvoir dire aux utilisateurs qu'ils peuvent fournir presque n'importe quel type de fichier texte (de type ASCII).
3 votes
Petit testcase qui démontre votre problème .
1 votes
Notez que if(f.good()) ne fait pas ce que vous semblez penser qu'il fait.
0 votes
Merci @Neil, je suis tombé dans le panneau alors que j'ai tout vérifié il y a quelques jours ! Je l'ai bien compris à l'époque. Je pense que je me suis laissé aller à supposer que
f.good()
devrait être le contraire def.fail()
.0 votes
@LightningRacisinObrit Arg, ideone.com J'étais en train d'essayer de trouver un exemple en ligne de ceci. Pouvez-vous me raconter ce que vous aviez fait il y a 4 ans ?
1 votes
@JonathanMee : C'était peut-être comme cette . Peut-être.