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

4 回答 4

7

使用break代替continuecontinue返回到循环的头部,只跳过当前的迭代,而break永远离开循环。

在不相关的说明中,如果由于任何原因无法读取文件,您的代码有一个错误会导致它挂起(例如,用户在您的程序尝试访问它时将其删除,用户删除了文件所在的 USB 记忆棒, ETC。)。这是因为一个循环条件,例如:

while (!file.eof())

危险!如果文件流进入错误状态,eof则永远不会true,并且循环将继续进行...... 您需要测试文件是否处于任何可读状态。这可以通过使用隐式转换为布尔值来简单地完成:

while (file)

只要文件未完成读取并且没有错误,这将导致循环运行。

于 2009-04-01T13:58:53.233 回答
2

假设文件中的数据按第一列排序(正如我在您的示例中注意到的那样),您应该替换 if 语句

if (FirstCol != 34) 
{
    continue;
}

有类似的东西:

if (FirstCol > 34) 
{
    break;
}
于 2009-04-01T14:04:30.240 回答
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;
}
于 2009-04-01T14:19:58.800 回答
1

假设 line 应该包含输入,那么将一些内容读入其中是个好主意!改变:

  while (! myfile.eof() ) 

到:

  while ( getline( myfile, line ) ) 
于 2009-04-01T14:23:49.663 回答