web-dev-qa-db-ja.com

N個の整数をベクトルに読み込む方法は?

標準入力からベクトルにall整数を読みたい場合は、便利な方法を使用できます。

vector<int> v{istream_iterator<int>(cin), istream_iterator()};

しかし、n整数のみを読みたいとしましょう。手で入力したループは私が手に入れたものすべてですか?

vector<int> v(n);
for(vector<int>::size_type i = 0; i < n; i++)
    cin >> v[i];

または、これを行うためのより右利きの方法はありますか?

18
gaazkam

コメントに記載されているように、copy_nはこのジョブには安全ではありませんが、可変ラムダでcopy_ifを使用できます。

#include <iterator>
#include <vector>
#include <iostream>
#include <algorithm>

int main(){
    const int N = 10;
    std::vector<int> v;
    //optionally v.reserve(N);
    std::copy_if(
        std::istream_iterator<int>(std::cin),
        std::istream_iterator<int>(), 
        std::back_inserter(v), 
        [count=N] (int)  mutable {
            return count && count--;
    });

    return 0;
}

この回答で指摘されているように、 std :: copy n elements or the end

12
bartop

通常、これを_std::copy_n_で行うべきではありません。これは、提供された反復子がインクリメントされたときにn回有効であると想定します。

countで始まる範囲からfirstで始まる範囲まで正確にresult値をコピーします。正式には、負でない整数_i < n_ごとに*(result + i) = *(first + i)を実行します。

std::copy_n_ に関するcppreference.comの記事)

あなたがそれを保証できるなら、それで結構ですが、一般的に_std::cin_ではそれは不可能です。無効なイテレータを逆参照することは非常に簡単です。

デフォルトで構築された_std::istream_iterator_は、ストリームの終わり反復子として知られています。有効な_std::istream_iterator_が基になるストリームの終わりに到達すると、ストリームの終わり反復子と等しくなります。それを逆参照または増分すると、未定義の動作がさらに呼び出されます。

std::istream_iterator_ に関するcppreference.comの記事)

「デッド」ストリームからの過剰な読み取りを回避するために、おそらくより強力な終了条件を使用することになりますが、ループはほとんどあります。

_vector<int> v(n);
for(vector<int>::size_type i = 0; i < n; i++)
    if (!cin >> v[i])
       break;
_

私は実際にこれを_std::copy_n_のようなものにラップするように誘惑されますが、から[までのカウントに加えて、境界が検証される完全な「範囲」を受け入れます〜#〜] n [〜#〜]

実装は次のようになります。

_template<class InputIt, class Size, class OutputIt>
OutputIt copy_atmost_n(InputIt first, InputIt last, Size count, OutputIt result)
{
   for (Size i = 0; i < count && first != last; ++i)
      *result++ = *first++;
   return result;
}
_

次のように使用します。

_copy_atmost_n(
   std::istream_iterator<int>(std::cin),
   std::istream_iterator<int>(),
   N,
   std::back_inserter(v)
);
_

[〜#〜] m [〜#〜]要素を取得します。ここで、-[〜#〜] m [〜#〜]は、提供された入力数または[〜#〜] n [〜#〜]、どちらか小さい方。

ライブデモ