8

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

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() ) );

但是我坚持使用“结束”迭代器——输入插入器不能使用 std::advance ,我也不能使用具有相同源的两个流......

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

4

8 回答 8

3

您可以从 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())
            );
}
于 2008-10-30T16:03:04.153 回答
3

采用:

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

注意空参数:

std::istream_iterator<int>();
于 2008-12-11T18:19:38.720 回答
2

Errr ... copy_n()算法?

于 2008-10-30T13:53:02.967 回答
2

稍微研究一下,我认为直接读入一个集合是行不通的,因为您需要在其上调用 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());

希望这要么解决了你的问题,要么让你相信循环在宏伟的计划中并没有那么糟糕。

于 2008-10-30T14:38:16.867 回答
1

如何使用备用迭代器进行遍历,然后使用函数对象(或 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 的编译器。

顺便说一句,'counting_iterator<>' 是Boost.Iterator的一部分。

于 2008-10-31T07:52:05.643 回答
1

或者你可以这样做:

my_set.insert(std::istream_iterator<int>(ins), std::istream_iterator<int>());
于 2011-04-06T16:01:19.120 回答
0

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

虽然有些怀疑,但您可以通过在文件中添加一个“失败”第一个循环的条目来获得大致正确的行为,然后清除流上的失败位并开始阅读更多内容。

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

1 1 2 3 5 8 菲布

输入下面的代码似乎符合我的意思,至少在带有 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;
于 2008-10-30T13:25:20.260 回答
0

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

于 2008-10-30T13:28:06.150 回答