How to read arbitrary number of values using std::

2019-02-12 23:42发布

I'm trying to code opposite action to this:

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

it should be something like this:

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

But I'm stuck with the 'end' iterator -- input interators can't use std::advance and neither I can use two streams with the same source...

Is there any elegant way how to solve this? Of course I can use for loop, but maybe there's something nicer :)

9条回答
时光不老,我们不散
2楼-- · 2019-02-13 00:13

Use:

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

Note the empty parameter:

std::istream_iterator<int>();
查看更多
迷人小祖宗
3楼-- · 2019-02-13 00:15

Errr... copy_n() algorithm?

查看更多
别忘想泡老子
4楼-- · 2019-02-13 00:16

(Edited: I should have read the question closer...)

While somewhat suspect, you can get approximately the right behavior by having an entry in the file that will "fail" the first loop, then clear the fail bit on the stream and start reading more.

Data, without an explicit size, but like this

1 1 2 3 5 8 Fibb

Fed to the code below seems to do what I meant, at least on VS2005 with STLPort.

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;
查看更多
放荡不羁爱自由
5楼-- · 2019-02-13 00:18

Yes sdg but when I want to use another data structures in that file / stream? I should probably explicitly write here, I want to store another stuff after this set, this is the reason why I'm storing the size as well.

查看更多
干净又极端
6楼-- · 2019-02-13 00:25

How about using an alternate iterator to do the traversal and then use a function object (or lambda) to fill in the container?

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++); }
);

Of course this assumes you have a C++0x compliant compiler.

BTW, 'counting_iterator<>' is part of Boost.Iterator.

查看更多
我欲成王,谁敢阻挡
7楼-- · 2019-02-13 00:32

Or you could do this:

my_set.insert(std::istream_iterator<int>(ins), std::istream_iterator<int>());
查看更多
登录 后发表回答