copy_n或直到eof?

时间:2011-12-04 23:32:09

标签: c++ algorithm file

我如何使用STL算法做到这一点?

std::ifstream file(filename);

std::vector<unsigned char> buf;
for(auto file_it = std::istreambuf_iterator<char>(file); file_it != std::istreambuf_iterator<char>() && buf.size() < 2048; ++file_it)
    buf.push_back(*file_it);

注意buf.size() < 2048

e.g。如果我执行以下操作会发生什么,并且文件小于2048字节?

std::copy_n(std::istreambuf_iterator<char>(file), 2048, std::back_inserter(buf));

2 个答案:

答案 0 :(得分:1)

与文档说的一样,std::copy_n()将完全复制 n个项目。它将继续读取迭代器引用的序列的结尾。不过,我不确定关于istreambuf_iterator<>的标准是什么。它可能是未定义的行为,但是流可能会在结束时产生大量eof()的副本。当可用的字节少于2048时,这可能会导致大量垃圾。

在任何情况下,如果您想要可靠地将复制到 n项目,您需要编写自己的函数:

template<typename I1, typename I2, typename size_type>
I copy_upto_n ( I1 begin, I1 end, size_type n, I2 out )
{
    for (size_type i=0; (i < n) && (begin != end); ++i)
    {
        *out++ = *begin++;
    }
    return out;
}

有些人可能会使用std::iterator_traits<>而不是额外的模板参数来强制使用与迭代器相同的距离类型。

答案 1 :(得分:0)

您可以使用特殊的back_insert_iterator来放弃基于谓词的操作。

此代码已被无耻地从GCC实施中获取 stdlib和改编。 C ++ 03版本应该只需要一个 在作业中Container::const_reference

template<typename Container, typename Predicate>
class discarding_back_inserter
  : public iterator<output_iterator_tag, void, void, void, void>
{
  Container* container;
  Predicate p;
public:
  typedef Container          container_type;

  explicit
  back_insert_iterator(Container& x, Predicate p) : container(&__x), p(p) { }

  back_insert_iterator&
  operator=(const typename Container::value_type& value)
    {
      if(*container) 
        container->push_back(__value);
      return *this;
    }

  back_insert_iterator&
  operator=(typename _Container::value_type&& value)
    {
      if(*container) 
        container->push_back(std::move(__value));
      return *this;
    }

  back_insert_iterator&
  operator*()
    { return *this; }

  back_insert_iterator&
  operator++()
    { return *this; }

  back_insert_iterator
  operator++(int)
    { return *this; }
};