Простой вопрос istream_iterator

Я новичок в C++, извините, если это глупый вопрос. Я не могу понять, почему это не работает. Он копирует в первый вектор и, кажется, пропускает второй вызов копирования.

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

using namespace std;

int main ()
{
    vector<int> first;
    vector<int> second;

    copy(istream_iterator<int>(cin),istream_iterator<int>(),back_inserter(first));
    cin.clear();
    copy(istream_iterator<int>(cin),istream_iterator<int>(),back_inserter(second)); 
    return 0;
}

Я хочу использовать функцию копирования для считывания ввода istream_iterator в любое количество векторов (один вызов для копирования на вектор). Другими словами: я хочу, чтобы я мог ввести "1 2 3 4 5 ctrl+d" в консоль и ввести 1,2,3,4,5 в первый вектор. Затем введите "6 7 8 9 10 ctrl+d" в консоль и введите 6,7,8,9,10 во второй вектор.

Проблема в том, что после того, как я ввел некоторый вход в первый вектор и нажал control+d, istream_iterator для cin остается равным istream_iterator(), независимо от состояния сбоя cin. Это приводит к сбою при каждом последующем вызове "copy" (потому что istream_iteratorcin уже равен istream_iterator(), который программа интерпретирует как eof). Итак, мой вопрос: что мне нужно сделать, чтобы "сбросить" итератор вместе с потоком cin? cin.clear() действительно очищает все биты сбоя. Однако istream_iterator(cin) все равно равен istream_iterator () независимо. Из того, что я понимаю, istream_iterators, которые связаны с потоком, должны быть равны значению istream_iterator по умолчанию, только когда поток находится в состоянии сбоя. Что мне не хватает?

1 ответ

Решение

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

Почему бы просто не сказать vector<int> second(first); сделать копию?


Обновление: после того как вы прояснили вопрос, вот новый ответ: вы неправильно понимаете, как stdin работает. Есть только один вход. Ctrl-D не является чем-то присущим C++; скорее это соглашение вашей платформы, и ваша платформа завершит входной буфер, когда вы подадите сигнал Ctrl-D, После этого ввод "файла" завершается, и дальнейшие данные не могут быть записаны в него.

Хотя ваш подход немного неортодоксален. Обычно вы просто читаете построчно, разделенные Enterи токенизируйте каждую строку. Используя строковые потоки, вы получаете очень похожий код:

std::string line;
std::vector<int> first, second;

// Read line 1
if (std::getline(std::cin, line))
{
  std::istringstream iss(line);
  std::copy(std::istream_iterator<int>(iss), std::istream_iterator<int>(), std::back_inserter(first));
}
else { /* error */ }

// Read line 2
if (std::getline(std::cin, line))
{
  std::istringstream iss(line);
  std::copy(std::istream_iterator<int>(iss), std::istream_iterator<int>(), std::back_inserter(second));
}
else { /* error */ }
Другие вопросы по тегам