如何使用std::copy读取任意数量的值

How to read arbitrary number of values using std::copy?

本文关键字:任意数 copy 何使用 std 读取      更新时间:2023-10-16

我正试图编写与此相反的操作:

std::ostream outs; // properly initialized of course
std::set<int> my_set; // ditto
outs << my_set.size();
std::copy( my_set.begin(), my_set.end(), std::ostream_iterator<int>( outs ) );

应该是这样的:

std::istream ins;
std::set<int>::size_type size;
ins >> size;
std::copy( std::istream_iterator<int>( ins ), std::istream_iterator<int>( ins ) ???, std::inserter( my_set, my_set.end() ) );

但我一直使用"end"迭代器——输入interator不能使用std::advance,也不能使用具有相同源的两个流。。。

有什么优雅的方法可以解决这个问题吗?当然,我可以使用for循环,但也许还有更好的方法:)

您可以从istream_iterator<T>
虽然使用Daemin生成器方法是另一种选择,但我会直接生成到集合中,而不是使用中间向量。

#include <set>
#include <iterator>
#include <algorithm>
#include <iostream>

template<typename T>
struct CountIter: public std::istream_iterator<T>
{
    CountIter(size_t c)
        :std::istream_iterator<T>()
        ,count(c)
    {}
    CountIter(std::istream& str)
        :std::istream_iterator<T>(str)
        ,count(0)
    {}
    bool operator!=(CountIter const& rhs) const
    {
        return (count != rhs.count) && (dynamic_cast<std::istream_iterator<T> const&>(*this) != rhs);
    }
    T operator*()
    {
        ++count;
        return std::istream_iterator<T>::operator*();
    }
    private:
        size_t  count;
};
int main()
{
    std::set<int>       x;
    //std::copy(std::istream_iterator<int>(std::cin),std::istream_iterator<int>(),std::inserter(x,x.end()));
    std::copy(
                CountIter<int>(std::cin),
                CountIter<int>(5),
                std::inserter(x,x.end())
            );
}

使用:

std::copy( std::istream_iterator<int>(ins),
           std::istream_iterator<int>(),
           std::inserter(my_set, my_set.end())
         );

注意空参数:

std::istream_iterator<int>();

错误。。。copy_n()算法?

仔细研究一下,我认为直接读取一个集合是行不通的,因为你需要在它上调用insert来实际添加元素(我可能错了,现在还很早)。虽然简单地看了一下VS2005中的STL文档,但我认为使用generate_n函数的东西应该可以工作,例如:

std::istream ins;
std::set<int> my_set;
std::vector<int> my_vec;
struct read_functor
{
    read_functor(std::istream& stream) :
        m_stream(stream)
    {
    }
    int operator()
    {
        int temp;
        m_stream >> temp;
        return temp;
    }
private:
    std::istream& m_stream;
};
std::set<int>::size_type size;
ins >> size;
my_vec.reserve(size);
std::generate_n(my_vec.begin(), size, read_functor(ins));
my_set.insert(my_vec.begin(), my_vec.end());

希望这要么解决了你的问题,要么让你相信这个循环在总体上并没有那么糟糕。

使用替代迭代器进行遍历,然后使用函数对象(或lambda)填充容器如何?

istream ins;
set<int>::size_type size;
set<int> new_set;
ins >> size;
ostream_iterator<int> ins_iter(ins);
for_each(counting_iterator<int>(0), counting_iterator<int>(size),
  [&new_set, &ins_iter](int n) { new_set.insert(*ins_iter++); }
);

当然,这是假设您有一个兼容C++0x的编译器。

BTW,'counting_iterator<>'是Boost的一部分。迭代器。

或者您可以这样做:

my_set.insert(std::istream_iterator<int>(ins), std::istream_iterator<int>());

是sdg,但当我想在该文件/流中使用另一个数据结构时?我可能应该在这里明确地写,我想在这个集合之后存储另一个东西,这就是我存储大小的原因。

(编辑:我应该仔细阅读这个问题…)

虽然有点可疑,但您可以通过在文件中设置一个条目来获得大致正确的行为,该条目将使第一个循环"失败",然后清除流上的失败位并开始读取更多内容。

数据,没有明确的大小,但像这个

1 1 2 3 5 8光纤

Fed到下面的代码似乎做到了我的意思,至少在带有STLPort的VS2005上是这样。

typedef std::istream_iterator<int,char,std::char_traits,ptrdiff_t>is_iter;std::copy(is_iter(cin),is_iter),inserter(my_set,my_set.end());cin.clear();std::cin>>instr;