【问题标题】:C++ Read file into Array / List / VectorC++ 将文件读入数组/列表/向量
【发布时间】:2013-10-16 20:30:19
【问题描述】:

我目前正在开发一个小程序来连接两个文本文件(类似于数据库连接)。一个文件可能如下所示:


    269ED3
    86356D
    818858
    5C8ABB
    531810
    38066C
    7485C5
    948FD4

第二个类似:


    hsdf87347
    7485C5
    rhdff
    23487
    948FD4

这两个文件都有超过 1.000.000 行,并且不限于特定数量的字符。我想做的是在两个文件中找到所有匹配的行。

我已经尝试了一些东西,数组、向量、列表 - 但我目前正在努力决定什么是最好的(最快且记忆容易)的方法。

我的代码目前看起来像:



    #include iostream>
    #include fstream>
    #include string>
    #include ctime>
    #include list>
    #include algorithm>
    #include iterator>
    using namespace std;


    int main()
    {

        string line;

        clock_t startTime = clock();

        list data;
        //read first file
        ifstream myfile ("test.txt");
        if (myfile.is_open())
        {
            for(line; getline(myfile, line);/**/){
                data.push_back(line);
            }

            myfile.close();
        }

        list data2;
        //read second file
        ifstream myfile2 ("test2.txt");
        if (myfile2.is_open())
        {
            for(line; getline(myfile2, line);/**/){
                data2.push_back(line);
            }

            myfile2.close();
        }
        else cout  data2[k], k++
        //if data[j] > a;

        return 0;


    }

我的想法是:使用向量,对元素的随机访问非常困难,并且跳转到下一个元素不是最佳的(不是在代码中,但我希望你明白这一点)。通过使用 push_back 并逐行添加将文件读入向量也需要很长时间。使用数组,随机访问更容易,但是将 >1.000.000 条记录读入数组将非常占用内存并且也需要很长时间。列表可以更快地读取文件,随机访问又很昂贵。

最终我不仅会寻找完全匹配,还会寻找每行的前 4 个字符。

你能帮我决定,最有效的方法是什么?我尝试过数组、向量和列表,但目前对速度并不满意。有没有其他方法可以找到我没有考虑过的匹配项?很高兴彻底改代码,期待大家的建议!

非常感谢!

编辑:输出应列出匹配的值/行。在此示例中,输出应如下所示:


    7485C5
    948FD4

【问题讨论】:

  • 您能否更具体地了解要求或限制条件?是需要报告匹配行的行号还是只输出匹配的行?

标签: c++ arrays optimization join vector


【解决方案1】:

阅读 200 万行不会太慢,可能会变慢的是您的比较逻辑:

使用:std::intersection

data1.sort(data1.begin(), data1.end()); // N1log(N1)
data2.sort(data2.begin(), data2.end()); // N2log(N2)

std::vector<int> v; //Gives the matching elements

std::set_intersection(data1.begin(), data1.end(),
                      data2.begin(), data2.end(),
                      std::back_inserter(v)); 

 // Does 2(N1+N2-1) comparisons (worst case)

您也可以尝试使用std::set 并将两个文件中的行插入其中,结果集将只有唯一元素。

【讨论】:

  • 您还应该考虑在整体复杂性中对数据向量进行排序所需的O(NlogN) + O(MlogM) 额外复杂性。虽然对你来说可能很明显,但对 OP 来说可能不是。
  • 非常感谢,200 万条记录只是一个开始——它会增长并且必须以相当快的速度运行。效率越高越好。
【解决方案2】:

如果此值在第一个文件中是唯一的,则在利用集合的O(nlogn) 特征时,这将变得微不足道。下面存储第一个文件中的所有行作为命令行参数传递给一个集合,然后对第二个文件中的每一行执行O(logn) 搜索。

编辑:添加了仅 4 个字符的前导搜索。为此,该集合仅包含每行的前四个字符,并且从第二个开始的搜索仅查找每个搜索行的前四个字符。如果有匹配项,则完整打印第二个文件行。完整打印第一个文件的整行会更具挑战性。

#include <iostream>
#include <fstream>
#include <string>
#include <set>

int main(int argc, char *argv[])
{
    if (argc < 3)
        return EXIT_FAILURE;

    // load set with first file
    std::ifstream inf(argv[1]);
    std::set<std::string> lines;
    std::string line;
    for (unsigned int i=1; std::getline(inf,line); ++i)
        lines.insert(line.substr(0,4));

    // load second file, identifying all entries.
    std::ifstream inf2(argv[2]);
    while (std::getline(inf2, line))
    {
        if (lines.find(line.substr(0,4)) != lines.end())
            std::cout << line << std::endl;
    }

    return 0;
}

【讨论】:

  • 哇,这看起来很棒,但我必须仔细研究一下才能完全理解代码。我什至不知道在哪里输入文件名......为了记录,文件可能有重复,它们也没有完全匹配,如果前 4 个字符匹配,我也想输出它。
  • 执行四字符匹配并不难。只需使用line.substr(0,4) 而不是line 加载地图,然后在搜索循环中搜索相同的内容; line.substr(0,4)。关于文件名的来源,此示例将它们作为命令行参数。你可以以progname file1 file2 运行它。我把文件名输入的任务留给了你,因为它与你的实际问题无关。希望这是有道理的。如果需要,我可以更新示例以执行此处描述的四字符前导匹配,但我认为这对您来说是一项很好的任务。
  • 一段很棒的代码,非常感谢!这真的是太快了!!现在最后一件事:我想匹配前四个字符,但仍想输出整行。我可以做类似的事情吗:while (std::getline(inf2, line.substr(0,4))) { if (lines.find(line.substr(0,4)) != lines.end()) std::cout &lt;&lt; line &lt;&lt; std::endl; }
  • 还是我在这里误会了什么?!编辑:刚刚测试了我的版本 - 猜我弄错了。
  • 离开了一会儿。我会更新它。它很简单。如果这个或任何其他答案有帮助,您应该支持他们,并且无论哪个答案(这个或另一个)被认为是您问题的最佳解决方案,都应该“检查”。以防万一您不了解此站点的一般操作。
【解决方案3】:

一种解决方案是一次读取整个文件。

使用 istream::seekg 和 istream::tellg 计算两个文件的大小。分配一个足够大的字符数组来存储它们。使用 istream::read 在适当的位置将这两个文件读入数组。

Here is an example of the above functions.

【讨论】:

  • 谢谢,我会试一试并报告结果!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-03
  • 2018-06-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多