Как прочитать N целых чисел в вектор? - PullRequest
0 голосов
/ 18 января 2019

Если я хочу прочитать все целые числа из стандартного ввода в вектор, я могу использовать удобную команду:

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

Или есть какой-нибудь более правосторонний способ сделать это?

Ответы [ 2 ]

0 голосов
/ 18 января 2019

Обычно это не следует делать с std::copy_n, что предполагает, что предоставленный итератор при увеличении n раз остается действительным:

Копирует ровно count значений из диапазона, начинающегося с first, до диапазона, начинающегося с result. Формально для каждого неотрицательного целого числа i < n выполняется *(result + i) = *(first + i).

( cppreference.com статья на std::copy_n)

Если вы можете гарантировать это, то хорошо, но обычно с std::cin это невозможно. Вы можете легко разыменовать недействительный итератор:

Построенный по умолчанию std::istream_iterator известен как итератор конца потока. Когда действительный std::istream_iterator достигает конца основного потока, он становится равным итератору конца потока. Разыменование или его приращение в дальнейшем вызывает неопределенное поведение.

( cppreference.com статья в std::istream_iterator)

Вы в значительной степени находитесь там с вашим циклом, хотя я бы, вероятно, использовал более сильное условие завершения, чтобы избежать лишних чтений из "мертвого" потока:

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

На самом деле я бы соблазнился обернуть это во что-то вроде std::copy_n, но принимает полный «диапазон», границы которого могут быть проверены в дополнение к подсчету от 0 до 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 , в зависимости от того, что меньше.

( живая демонстрация )

0 голосов
/ 18 января 2019

Как указано в комментариях, 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 элементов или до конца

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...