从文本文件到std :: vector <string>读取行的最有效方法

时间:2017-05-16 10:37:26

标签: c++ c++11 vector fstream

将从文本文件中提取的行添加到std :: vector&lt;中的常用方法std :: string&gt;向量的每个元素对应一个文件的行就像这样的例子:

https://stackoverflow.com/a/8365024/7030542

std::string line;
std::vector<std::string> myLines;
while (std::getline(myfile, line))
{
    myLines.push_back(line);
}

https://stackoverflow.com/a/12506764/7030542

std::vector<std::string> lines;
for (std::string line; std::getline( ifs, line ); /**/ )
    lines.push_back( line );

是否存在一种最有效的方法来避免辅助字符串?

3 个答案:

答案 0 :(得分:6)

不要过分思考它:

std::vector<std::string> lines;
std::string line;
while(std::getline( ifs, line ))
    lines.push_back(std::move(line));

请注意,从line移动的状态是有效但不确定的,因此调用std::getline即可,因为这会替换std::string的内容(无论他们是什么)可能是)完全消除move遗留下来的任何不确定状态。

答案 1 :(得分:1)

@ rubenvb的答案很棒。

作为替代

bool get_line_into_vector( std::istream& is, std::vector<std::string>& v ) {
  std::string tmp;
  if (!std::getline(is, tmp))
     return false;
  v.push_back(std::move(tmp));
  return true;
}

std::vector<std::string> lines;
while(get_line_into_vector( ifs, lines ))
{} // do nothing

这是rubenvb的解决方案,临时转移到帮助函数。

我们可以避免小缓冲区优化大小的字符副本:

bool get_line_into_vector( std::istream& is, std::vector<std::string>& v ) {
  v.emplace_back();
  if (std::getline(is, v.back()))
    return true;
  v.pop_back();
  return false;
}

这可以(在边缘情况下)导致额外的大规模重新分配,但这是渐近罕见的。

与@ pschill的答案不同,此处无效状态在辅助函数中被隔离,并且所有流控制都以避免这些无效状态泄漏为中心。

好消息是

std::vector<std::string> lines;
while(get_line_into_vector( ifs, lines ))
{} // do nothing

是你如何使用它;您使用的这两个实现中的哪一个被隔离到get_line_into_vector函数中。这可以让你在它们之间进行交换,并确定哪个更好。

答案 2 :(得分:-1)

如果要避免临时变量,可以使用最后一个向量元素作为缓冲区:

std::vector<std::string> lines(1);
while (std::getline(ifs, lines.back())
    lines.emplace_back();
lines.erase(--lines.end());  // remove the buffer element