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

しかし、私は 'end' イテレータに固執しています。入力インターレータは std::advance を使用できず、同じソースで 2 つのストリームを使用することもできません...

これを解決するエレガントな方法はありますか? もちろん、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

これを少し調べてみると、実際に要素を追加するために挿入を呼び出す必要があるため、セットを直接読み取ることはうまくいかないと思います(誤解される可能性があります。ここではかなり早朝です)。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 に答える
2

エラー... copy_n()アルゴリズム?

于 2008-10-30T13:53:02.967 に答える
1

または、これを行うことができます:

my_set.insert(std::istream_iterator<int>(ins), std::istream_iterator<int>());
于 2011-04-06T16:01:19.120 に答える
1

代わりの反復子を使用してトラバーサルを行い、関数オブジェクト (またはラムダ) を使用してコンテナーを埋めるのはどうですか?

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 に答える
0

(編集:質問をもっと詳しく読むべきだった...)

多少疑わしいかもしれませんが、最初のループを「失敗」させるエントリをファイルに入れてから、ストリームの失敗ビットをクリアしてさらに読み始めることで、ほぼ正しい動作を得ることができます。

データ、明示的なサイズはありませんが、このように

1 1 2 358フィブ

以下のコードにフィードすると、少なくとも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 に答える