Простой вопрос 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 */ }