Leggi il file riga per riga

I contenuti di file.txt sono:

5 3 6 4 7 1 10 5 11 6 12 3 12 4 

Dove 5 3 è una coppia di coordinate. Come posso elaborare questo dato riga per riga in C ++?

Sono in grado di ottenere la prima riga, ma come faccio a ottenere la riga successiva del file?

 ofstream myfile; myfile.open ("text.txt"); 

    Innanzitutto, crea un ifstream :

     #include  std::ifstream infile("thefile.txt"); 

    I due metodi standard sono:

    1. Supponiamo che ogni riga consista di due numeri e di token letti per token:

       int a, b; while (infile >> a >> b) { // process pair (a,b) } 
    2. Analisi in base alla riga, utilizzando i flussi di stringhe:

       #include  #include  std::string line; while (std::getline(infile, line)) { std::istringstream iss(line); int a, b; if (!(iss >> a >> b)) { break; } // error // process pair (a,b) } 

    Non dovresti mischiare (1) e (2), dato che l’analisi basata su token non ingombra le nuove righe, quindi potresti finire con false righe vuote se usi getline() dopo che l’estrazione basata su token ti ha portato fine di una linea già.

    Usa ifstream per leggere i dati da un file:

     std::ifstream input( "filename.ext" ); 

    Se hai davvero bisogno di leggere riga per riga, allora fai questo:

     for( std::string line; getline( input, line ); ) { ...for each line in input... } 

    Ma probabilmente hai solo bisogno di estrarre le coppie di coordinate:

     int x, y; input >> x >> y; 

    Aggiornare:

    Nel tuo codice usi ofstream myfile; , tuttavia la o in ofstream sta per output . Se vuoi leggere dal file (input) usa ifstream . Se vuoi leggere e scrivere, usa fstream .

    Dal momento che le tue coordinate appartengono insieme come coppie, perché non scrivere una struttura per loro?

     struct CoordinatePair { int x; int y; }; 

    Quindi puoi scrivere un operatore di estrazione sovraccarico per istanze:

     std::istream& operator>>(std::istream& is, CoordinatePair& coordinates) { is >> coordinates.x >> coordinates.y; return is; } 

    E poi puoi leggere un file di coordinate direttamente in un vettore come questo:

     #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 } 

    Espansione sulla risposta accettata, se l’input è:

     1,NYC 2,ABQ ... 

    sarai ancora in grado di applicare la stessa logica, come questa:

     #include  std::ifstream infile("thefile.txt"); if (infile.is_open()) { int number; std::string str; char c; while (infile >> number >> c >> str && c == ',') std::cout << number << " " << str << "\n"; } infile.close(); 

    La lettura di un file riga per riga in C ++ può essere eseguita in diversi modi.

    [Fast] Loop con std :: getline ()

    L’approccio più semplice è quello di aprire uno std :: ifstream e loop usando le chiamate std :: getline (). Il codice è pulito e facile da capire.

     #include  std::ifstream file(FILENAME); if (file.is_open()) { std::string line; while (getline(file, line)) { // using printf() in all tests for consistency printf("%s", line.c_str()); } file.close(); } 

    [Veloce] Usa Boost’s file_description_source

    Un’altra possibilità è usare la libreria Boost, ma il codice diventa un po ‘più dettagliato. Le prestazioni sono abbastanza simili al codice precedente (Loop con 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::string line; while (std::getline(in, line)) { // using printf() in all tests for consistency printf("%s", line.c_str()); } fdDevice.close(); } } } 

    [Più veloce] Usa il codice C

    Se le prestazioni sono fondamentali per il tuo software, puoi prendere in considerazione l’utilizzo del linguaggio C. Questo codice può essere 4-5 volte più veloce rispetto alle versioni C ++ sopra, vedi benchmark sotto

     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); 

    Benchmark – Quale è più veloce?

    Ho fatto alcuni benchmark delle prestazioni con il codice sopra e i risultati sono interessanti. Ho testato il codice con file ASCII che contengono 100.000 righe, 1.000.000 di righe e 10.000.000 di righe di testo. Ogni riga di testo contiene in media 10 parole. Il programma viene compilato con -O3 ottimizzazione -O3 e il suo output viene inoltrato a /dev/null per rimuovere la variabile del tempo di registrazione dalla misura. Ultimo, ma non meno importante, ogni pezzo di codice registra ogni riga con la printf() per coerenza.

    I risultati mostrano il tempo (in ms) che ciascun pezzo di codice ha impiegato per leggere i file.

    La differenza di prestazioni tra i due approcci C ++ è minima e non dovrebbe fare alcuna differenza nella pratica. Le prestazioni del codice C sono ciò che rende il benchmark impressionante e può essere un punto di svolta in termini di velocità.

      10K lines 100K lines 1000K lines Loop with std::getline() 105ms 894ms 9773ms Boost code 106ms 968ms 9561ms C code 23ms 243ms 2397ms 

    inserisci la descrizione dell'immagine qui

    Sebbene non sia necessario chiudere manualmente il file, è consigliabile farlo se l’ambito della variabile file è maggiore:

      ifstream infile(szFilePath); for (string line = ""; getline(infile, line); ) { //do something with the line } if(infile.is_open()) infile.close(); 

    con gli argomenti della riga di comando:

     #include  #include  #include  #include  #include "print.h" using namespace std; int main (int argc, char *argv[]) { vector list; ifstream in_stream; string 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); }