2009-04-01 7 views
1

je les données suivantes qui ressemble à ceci par exemple:Comment puis-je analyser correctement mon fichier? (Avec pause/continuer)

34 foo
34 bar
34 qux
62 foo1
62 qux
78 qux

Ils sont triés en fonction de la première colonne.

Ce que je veux faire est de traiter les lignes commençant par 34, mais je veux aussi l'itération de fichier à quitter après ne trouve plus 34s, sans avoir à analyser par fichier entier. Comment ferais-je cela? La raison en est que le nombre de lignes à traiter est très important (~ 10^7). Et ceux qui commencent par 34 n'en représentent qu'environ 1-10%.

Je suis conscient que je peux grep les lignes et la sortie dans un autre fichier, mais cela est trop fastidieux et crée plus de consommation d'espace disque.

Ce code illustre ma tentative a échoué en utilisant "continuer":

#include <iostream> 
#include <vector> 
#include <fstream>  
#include <sstream>  
using namespace std;  

int main() { 
    string line; 
    ifstream myfile ("mydata.txt"); 
    vector<vector<string> > dataTable; 
    if (myfile.is_open()) 
    { 
     while (! myfile.eof()) 
     { 
       stringstream ss(line);  
       int FirstCol; 
       string SecondCol; 

       if (FirstCol != 34) { 
        continue; 
       } 

       // This will skip those other than 34 
       // but will still iterate through all the file 
       // until the end. 

       // Some processing to FirstCol and SecondCol 

       ss >> FirstCol >> SecondCol; 
       cout << FirstCol << "\t << SecondCol << endl; 


     } 
     myfile.close(); 
    } 

    else cout << "Unable to open file"; 


    return 0; 
} 

Répondre

1

En supposant que le fichier est trié par FirstCol, utilisez une variable d'état qui indique si vous avez ou non trouvé le premier. Une fois que vous avez trouvé le premier, dès que vous trouvez une colonne qui est! = 34, vous pouvez sortir de la boucle.

Par exemple, supposons que vos données sont maintenant:

15 boo 
32 not 
34 foo 
34 bar 
34 qux 
62 foo1 
62 qux 
78 qux 

... ce code va faire ce que vous voulez:

#include "stdafx.h" 
#include <iostream> 
#include <vector> 
#include <fstream>  
#include <sstream>  
using namespace std;  

int main() { 
    string line; 
    ifstream myfile ("mydata.txt"); 
    vector<vector<string> > dataTable; 
    if (myfile.is_open()) 
    { 
     bool found34 = false; 

     while (myfile) 
     { 
       stringstream ss(line);  
       int FirstCol; 
       string SecondCol; 
       // This will skip those other than 34 
       // but will still iterate through all the file 
       // until the end. 

       // Some processing to FirstCol and SecondCol 

       myfile >> FirstCol >> SecondCol; 
       cout << FirstCol << "\t" << SecondCol << endl; 

       switch(FirstCol) 
       { 
       case 34 : 
        found34 = true; 
        cout << "Processing a 34"; 
        continue; // keep looping 
       default : 
        if(found34) 
        { 
         // we found all the 34's and now we're on to the next value, so we're done 
         cout << "We're done."; 
         break; 
        } 
        else 
        { 
         // we haven't found the first 34 yet, so keep scanning until we do 
         cout << "Keep on looking for a 34..."; 
         continue; 
        } 
       } 
     } 
     myfile.close(); 
    } 

    else cout << "Unable to open file"; 


    return 0; 
} 
+0

Un interrupteur avec seulement 1 cas et un défaut semble être un si-alors-autre pour moi ... –

+0

@Luc: Bien sûr, allez-y. C'est vraiment juste une question de style et de préférences. J'aime les interrupteurs. –

+0

Malheureusement, ce code a toujours le bug dangereux que j'ai mentionné lié à la boucle infinie ('while (! File.eof())'). –

7

Utilisez break au lieu de continue! continue revient en tête de la boucle, en ignorant uniquement l'itération en cours, tandis que break quitte définitivement la boucle. Sur une note non liée, votre code a un bug qui le fait se bloquer si le fichier ne peut pas être lu pour une raison quelconque (par exemple, l'utilisateur le supprime pendant que votre programme tente d'y accéder, l'utilisateur enlève la clé USB le fichier est allumé, etc.). En effet, une condition de boucle telle que:

while (!file.eof()) 

est dangereux! Si le flux de fichier passe dans un état d'erreur, eof ne sera jamais true et la boucle continuera encore et encore et encore .... Vous devez tester si le fichier est en n'importe quel état lisible. Cela se fait simplement en utilisant la conversion implicite à une valeur booléenne:

while (file) 

Cela entraînera la boucle de fonctionner aussi longtemps que le fichier ne soit pas terminé la lecture et il n'y a pas d'erreur.

+0

Il ne peut pas simplement utiliser pause parce qu'il ne trouvera jamais la première entrée où FirstCol == 34 à moins que le premier disque se trouve être 34. –

2

En supposant que les données du fichier sont triées par la première colonne (comme je l'ai remarqué dans votre exemple), vous devez remplacer que si la déclaration de

if (FirstCol != 34) 
{ 
    continue; 
} 

avec quelque chose comme:

if (FirstCol > 34) 
{ 
    break; 
} 
1

ligne En supposant est censé contenir l'entrée, ce serait une bonne idée d'y lire quelque chose! Changement:

while (! myfile.eof()) 

à:

while (getline(myfile, line)) 
Questions connexes