0

我正在寻找一种将文件中的字符串存储到字符串向量中的快速方法,以便我可以提前保留行数。做这个的最好方式是什么?我应该先继续换行字符还是只获取文件的总大小并保留说大小/ 80,以便粗略估计要保留的内容。理想情况下,我不希望每次都重新分配向量,这对于大文件来说会大大减慢速度。理想情况下,我会提前计算项目数,但我应该通过以二进制模式打开计算新行然后重新打开来做到这一点吗?这似乎很浪费,对此有些想法感到好奇。还有一种方法可以使用 emplace_back 来摆脱下面 getline 代码中的临时 somestring 。查找文本行数的最快方法(C++)

std::vector<std::string> vs;
std::string somestring;
std::ifstream somefile("somefilename");
while (std::getline(somefile, somestring))
vs.push_back(somestring);

我也可以做一些事情来提前获得总大小,我可以直接将这种情况下的 char* 转换为向量吗?这可以追溯到我说 size / 80 或某个常数的储备提示,以便预先为储备提供估计的大小。

        #include <iostream>   
        #include <fstream>     

        int main () {
          char* contents;
          std::ifstream istr ("test.txt");

          if (istr) 
          {
            std::streambuf * pbuf = istr.rdbuf();

            //which I can use as a reserve hint say size / 80  
            std::streamsize size = pbuf->pubseekoff(0,istr.end);  

            //maybe I can construct the vector from the char buf directly?
            pbuf->pubseekoff(0,istr.beg);       
            contents = new char [size];
            pbuf->sgetn (contents,size);
          }
          return 0;
    }
4

2 回答 2

1

与其浪费时间提前计算行数,我只reserve()需要一个初始值,然后开始推送实际的行,如果你碰巧推送了保留的项目数量,那么reserve()在继续更多推送之前只需更多空间,根据需要重复.

于 2013-07-26T01:43:55.647 回答
1

在 a 中保留空间的策略std::vector旨在“按需增长”。也就是说,您不会一次分配一个字符串,您将首先分配一个,然后是十个,然后是一百个等等(不完全是这些数字,但这就是想法)。换句话说, std::vector::push_back 的实现已经为您管理了这个。

考虑以下示例:我正在使用两个版本阅读《战争与和平》的整个文本(65007 行):一个分配,一个不分配(即,一个保留零空间,另一个保留完整的 65007 行;文本来自:http ://www.gutenberg.org/cache/epub/2600/pg2600.txt )

#include<iostream>
#include<fstream>
#include<vector>
#include<string>
#include<boost/timer/timer.hpp>

void reader(size_t N=0) {
  std::string line;  
  std::vector<std::string> lines;
  lines.reserve(N);

  std::ifstream fp("wp.txt");  
  while(std::getline(fp, line)) {
    lines.push_back(line);
  }
  std::cout<<"read "<<lines.size()<<" lines"<<std::endl;
}

int main() {
  {
    std::cout<<"no pre-allocation"<<std::endl;
    boost::timer::auto_cpu_timer t;
    reader();
  }
  {
    std::cout<<"full pre-allocation"<<std::endl;    
    boost::timer::auto_cpu_timer t;    
    reader(65007);
  }

  return 0;
}

结果:

no pre-allocation
read 65007 lines
 0.027796s wall, 0.020000s user + 0.000000s system = 0.020000s CPU (72.0%)
full pre-allocation
read 65007 lines
 0.023914s wall, 0.020000s user + 0.010000s system = 0.030000s CPU (125.4%)

你看,对于大量的文本,我有几毫秒的差异。

你真的需要事先了解这些线路吗?真的是瓶颈吗?例如,您是否节省了一秒钟的 Wall 时间,但通过预分配行使您的代码复杂了十倍?

于 2013-07-26T01:55:14.550 回答