【问题标题】:Read integers from a text file with C++ ifstream使用 C++ ifstream 从文本文件中读取整数
【发布时间】:2011-12-28 08:15:29
【问题描述】:

我想从文本文件中读取图形邻接信息并将其存储到向量中。

  • 文件有任意行数

  • 每一行有任意数量的以'\n'结尾的整数

例如,

First line:
0 1 4
Second line:
1 0 4 3 2
Thrid line:
2 1 3
Fourth line:
3 1 2 4
Fifth line:
4 0 1 3

如果我使用 getline() 一次读取一行,我如何解析该行(因为每行都有可变数量的整数)?

有什么建议吗?

【问题讨论】:

标签: c++


【解决方案1】:

标准行读成语:

#include <fstream>
#include <sstream>
#include <string>
#include <vector>


std::ifstream infile("thefile.txt");
std::string line;

while (std::getline(infile, line))
{
  std::istringstream iss(line);
  int n;
  std::vector<int> v;

  while (iss >> n)
  {
    v.push_back(n);
  }

  // do something useful with v
}

这是一个使用for 循环的单行版本。我们需要一个与std::move相反的辅助结构(感谢@Luc Danton!):

namespace std
{
  template <typename T> T & stay(T && t) { return t; }
}

int main()
{
  std::vector<std::vector<int>> vv;

  for (std::string line;
       std::getline(std::cin, line);
       vv.push_back(std::vector<int>(std::istream_iterator<int>(std::stay(std::istringstream(line))),
                                     std::istream_iterator<int>())
                    )
       ) { }

  std::cout << vv << std::endl;
}

【讨论】:

  • 这意味着,这是使用 C++11 功能,因为 &amp;&amp; 仅在 C++11 中可用。
  • @Nawaz:我的早期版本涉及更精细的结构和 const-cast,即 C++98。有兴趣可以私聊,不适合礼貌交谈:-)
  • @Kerrek,感谢您的解决方案。当我嵌套了 STL 容器时,比如 vector >,我该如何遍历它?我正在尝试以下操作: std::vector<:vector> > iter1; std::vector::iterator iter2; for (iter1 = vv.begin(); iter1 != vv.end(); ++iter1) { for (iter2 = (*vv).begin(); iter2 != (*vv).end(); + +iter2) cout
  • @itnovice:就是这样。 for (std::vector&lt;std::vector&lt;int&gt;&gt;::const_iterator it1 = v.begin(), end1 = v.end(); it1 != end1; ++it1) { for ( std::vector&lt;int&gt;::const_iterator it2 = it1-&gt;begin(), end2 = it1-&gt;end(); it2 != end2; ++it2) { ... } }
  • "std::stay" 从什么时候开始允许给std添加名字?
【解决方案2】:

首先使用std::getline函数读取一行,然后使用std::stringstream从该行读取整数:

std::ifstream file("input.txt");

std::vector<std::vector<int>> vv;
std::string line;
while(std::getline(file, line))
{
    std::stringstream ss(line);
    int i;
    std::vector<int> v;
    while( ss >> i ) 
       v.push_back(i);
    vv.push_back(v);
}

你也可以把循环体写成:

while(std::getline(file, line))
{
    std::stringstream ss(line);
    std::istream_iterator<int> begin(ss), end;
    std::vector<int> v(begin, end);
    vv.push_back(v);
}

这看起来更短,更好。或者合并——最后两行:

while(std::getline(file, line))
{
    std::stringstream ss(line);
    std::istream_iterator<int> begin(ss), end;
    vv.push_back(std::vector<int>(begin, end));
}

现在不要缩短它,因为它看起来很丑。

【讨论】:

  • 甚至for (std::string line; std::getline(file, line); vv.push_back(std::vector&lt;int&gt;(std::istream_iterator&lt;int&gt;(std::istringstream(line)), std::istream_iterator&lt;int&gt;()))) {}
  • @KerrekSB:呵呵。好一个。我喜欢最小化line 变量范围的想法。
  • 只是测试它,但可能是您无法从临时字符串流中获取迭代器:-(
  • @Nawaz:令人印象深刻——不,我不确定我是否理解。为什么返回值不再是右值?使用返回对其参数的引用的函数可以更简单地实现同样的目的吗?
  • 所以应该有一个 mixin 模板can_use_as_temporary&lt;T&gt;,您可以从中派生出T &amp; lvalue() { return *this; }
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-09
  • 2014-04-21
相关资源
最近更新 更多