2009-04-01 8 views
1

У меня есть следующие данные, выглядит следующим образом, например:Как я могу правильно проанализировать файл? (Использование перерыва/продолжить)

34 Foo
34 бар
34 QUX
62 foo1
62 QUX
78 QUX

Они сортируются в зависимости от первого столбца.

То, что я хочу сделать, это обрабатывать строки, которые начинаются с 34, но я также хочу файл итерация, чтобы выйти после того, как он не находит более 34s, без необходимости проверять через весь файл. Как мне это сделать?

Причина в том, что количество обрабатываемых линий очень велико (~ 10^7). И те, которые начинаются с 34, составляют только около 1-10%.

Я знаю, что я могу grep строк и выводить их в другой файл, но это слишком утомительно и создает больше дискового пространства.

Этот код иллюстрирует мою неудачную попытку с помощью "Продолжить":

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

ответ

1

Исходя из предположения, что файл отсортирован по FirstCol, используйте переменную состояния, которая указывает, была ли вы найдена первая. Как только вы найдете первый, как только вы найдете столбец, который равен! = 34, вы можете выйти из цикла.

Например, предположим, что данные теперь:

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

... этот код будет делать то, что вы хотите:

#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

переключатель с только 1 случаем и по умолчанию кажется мне как-то-то ... –

+0

@Luc: Конечно, вперед. Это действительно вопрос стиля и предпочтений. Мне нравятся переключатели. –

+0

К сожалению, этот код по-прежнему содержит опасную ошибку, о которой я упоминал, связанную с бесконечным циклом ('while (! File.eof())). –

7

Использование break вместо continue! continue возвращается в начало цикла, только пропуская текущую итерацию, а break оставляет петлю навсегда.

В случае несвязанного примечания ваш код имеет ошибку, которая заставляет его зависать, если файл не может быть прочитан по какой-либо причине (например, пользователь удаляет его, пока ваша программа пытается получить к нему доступ, пользователь удаляет USB-накопитель файл включен и т. д.). Это происходит потому, что состояние петли, такие как:

while (!file.eof()) 

является опасным! Если поток файлов переходит в состояние ошибки, eof никогда не будет true, и цикл будет продолжать и продолжать .... Вам нужно проверить, находится ли файл в в любом состоянии. Это просто сделать с помощью неявного преобразования в логическое значение:

while (file) 

Это заставит цикл, чтобы работать только до тех пор, пока файл не дочитал и нет никакой ошибки.

+0

Он не может просто использовать перерыв, потому что он никогда не найдет первую запись, где FirstCol == 34, если самая первая запись не случается 34. –

2

Предполагая, что данные в файле отсортированы по первой колонке (как я заметил, в вашем примере), следует заменить, что если заявление от

if (FirstCol != 34) 
{ 
    continue; 
} 

что-то вроде:

if (FirstCol > 34) 
{ 
    break; 
} 
1

Предполагая, что линия должна содержать вход, это будет хорошая идея что-то прочитать в нем! Изменение:

while (! myfile.eof()) 

к:

while (getline(myfile, line))