Le contenu de fichier.txt est:
5 3 6 4 7 1 10 5 11 6 12 3 12 4
Où 5 3
est une paire de coordonnées. Comment traiter ces données ligne par ligne en C ++?
Je peux obtenir la première ligne, mais comment puis-je obtenir la ligne suivante du fichier?
ofstream myfile; myfile.open ("text.txt");
Tout d’abord, faites un ifstream
:
#include std::ifstream infile("thefile.txt");
Les deux méthodes standard sont:
Supposons que chaque ligne se compose de deux nombres et lit un jeton:
int a, b; while (infile >> a >> b) { // process pair (a,b) }
Analyse basée sur les lignes, utilisant des stream de chaînes:
#include #include std::ssortingng line; while (std::getline(infile, line)) { std::issortingngstream iss(line); int a, b; if (!(iss >> a >> b)) { break; } // error // process pair (a,b) }
Vous ne devriez pas mélanger (1) et (2), car l’parsing basée sur des jetons ne gobe pas les nouvelles lignes, vous pouvez donc vous retrouver avec des lignes vides si vous utilisez getline()
après que l’extraction basée sur les jetons vous fin d’une ligne déjà.
Utilisez ifstream
pour lire les données d’un fichier:
std::ifstream input( "filename.ext" );
Si vous avez vraiment besoin de lire ligne par ligne, faites ceci:
for( std::ssortingng line; getline( input, line ); ) { ...for each line in input... }
Mais vous avez probablement juste besoin d’extraire des paires de coordonnées:
int x, y; input >> x >> y;
Mettre à jour:
Dans votre code, vous utilisez ofstream myfile;
, cependant, le o
in ofstream
représente la output
. Si vous voulez lire le fichier (input), utilisez ifstream
. Si vous voulez à la fois lire et écrire, utilisez fstream
.
Puisque vos coordonnées sont regroupées en paires, pourquoi ne pas écrire une structure pour elles?
struct CoordinatePair { int x; int y; };
Vous pouvez ensuite écrire un opérateur d’extraction surchargé pour istreams:
std::istream& operator>>(std::istream& is, CoordinatePair& coordinates) { is >> coordinates.x >> coordinates.y; return is; }
Et puis vous pouvez lire un fichier de coordonnées directement dans un vecteur comme celui-ci:
#include #include #include int main() { char filename[] = "coordinates.txt"; std::vector v; std::ifstream ifs(filename); if (ifs) { std::copy(std::istream_iterator (ifs), std::istream_iterator (), std::back_inserter(v)); } else { std::cerr << "Couldn't open " << filename << " for reading\n"; } // Now you can work with the contents of v }
En étendant la réponse acceptée, si l’entrée est:
1,NYC 2,ABQ ...
vous pourrez toujours appliquer la même logique, comme ceci:
#include std::ifstream infile("thefile.txt"); if (infile.is_open()) { int number; std::ssortingng str; char c; while (infile >> number >> c >> str && c == ',') std::cout << number << " " << str << "\n"; } infile.close();
La lecture d’un fichier ligne par ligne en C ++ peut se faire de différentes manières.
L’approche la plus simple consiste à ouvrir un std :: ifstream et une boucle en utilisant les appels std :: getline (). Le code est propre et facile à comprendre.
#include std::ifstream file(FILENAME); if (file.is_open()) { std::ssortingng line; while (getline(file, line)) { // using printf() in all tests for consistency printf("%s", line.c_str()); } file.close(); }
Une autre possibilité est d’utiliser la bibliothèque Boost, mais le code devient un peu plus prolixe. La performance est assez similaire au code ci-dessus (Boucle avec std :: getline ()).
#include #include #include namespace io = boost::iostreams; void readLineByLineBoost() { int fdr = open(FILENAME, O_RDONLY); if (fdr >= 0) { io::file_descriptor_source fdDevice(fdr, io::file_descriptor_flags::close_handle); io::stream in(fdDevice); if (fdDevice.is_open()) { std::ssortingng line; while (std::getline(in, line)) { // using printf() in all tests for consistency printf("%s", line.c_str()); } fdDevice.close(); } } }
Si les performances sont essentielles pour votre logiciel, vous pouvez envisager d’utiliser le langage C. Ce code peut être 4 à 5 fois plus rapide que les versions C ++ ci-dessus, voir la référence ci-dessous
FILE* fp = fopen(FILENAME, "r"); if (fp == NULL) exit(EXIT_FAILURE); char* line = NULL; size_t len = 0; while ((getline(&line, &len, fp)) != -1) { // using printf() in all tests for consistency printf("%s", line); } fclose(fp); if (line) free(line);
J’ai fait quelques tests de performance avec le code ci-dessus et les résultats sont intéressants. J’ai testé le code avec des fichiers ASCII contenant 100 000 lignes, 1 000 000 de lignes et 10 000 000 lignes de texte. Chaque ligne de texte contient 10 mots en moyenne. Le programme est compilé avec l’optimisation -O3
et sa sortie est transmise à /dev/null
afin de supprimer la variable de temps de consignation de la mesure. Enfin, chaque élément de code enregistre chaque ligne avec la fonction printf()
pour la cohérence.
Les résultats indiquent le temps (en ms) pris par chaque code pour lire les fichiers.
La différence de performance entre les deux approches C ++ est minime et ne devrait faire aucune différence dans la pratique. La performance du code C est ce qui rend la référence impressionnante et peut changer la donne en termes de vitesse.
10K lines 100K lines 1000K lines Loop with std::getline() 105ms 894ms 9773ms Boost code 106ms 968ms 9561ms C code 23ms 243ms 2397ms
Bien qu’il ne soit pas nécessaire de fermer le fichier manuellement, il est conseillé de le faire si la scope de la variable de fichier est plus grande:
ifstream infile(szFilePath); for (ssortingng line = ""; getline(infile, line); ) { //do something with the line } if(infile.is_open()) infile.close();
avec des arguments de ligne de commande:
#include #include #include #include #include "print.h" using namespace std; int main (int argc, char *argv[]) { vector list; ifstream in_stream; ssortingng line; in_stream.open(argv[1]); while(!in_stream.eof()) { in_stream >> line; list.push_back(line); } in_stream.close(); print(list); sort(list.begin(), list.end()); print(list); }