#include vector
int main()
{
vectorint ivec;
int ival;
while ( cin ival )
ivec.push_back( ival );
// ...
}
Подвыражение
cin ival;
читает целое число из стандартного ввода и копирует его в переменную ival. Результатом является левый операнд – объект класса istream, в данном случае cin. (Как мы увидим, это позволяет сцеплять операторы ввода.)
Выражение
while ( cin ival )
читает последовательность значений, пока cin не станет равно false. Значение istream может быть равно false в двух случаях: достигнут конец файла (т.е. все значения из файла прочитаны успешно) или встретилось неверное значение, скажем 3.14159 (десятичная точка недопустима в целом числе), 1e-1 (буква e недопустима) или любой строковый литерал. Если вводится неверное значение, объект istream переводится в состояние ошибки и чтение прекращается. (В разделе 20.7 мы подробнее расскажем о таких состояниях.)
Есть набор предопределенных операторов ввода, принимающих аргументы любого встроенного типа, включая C-строки, а также стандартных библиотечных типов string и complex:
#include iostream
#include string
int main()
{
int item_number;
string item_name;
double item_price;
cout "Пожалуйста, введите item_number, item_name и price: "
endl;
cin item_number;
cin item_name;
cin item_price;
cout "Введены значения: item# "
item_number " "
item_name " @$"
item_price endl;
}
Вот пример выполнения этой программы:
Пожалуйста, введите item_number, item_name и price:
10247 widget 19.99
Введены значения: item# 10247 widget @$19.99
Можно ввести каждый элемент на отдельной строке. По умолчанию оператор ввода отбрасывает все разделяющие пустые символы: пробел, символ табуляции, символ перехода на новую строку, символ перевода страницы и символ возврата каретки. (О том, как отменить это поведение, см. в разделе 20.9.)
Пожалуйста, введите item_number, item_name и price:
10247
widget
19.99
Введены значения: item# 10247 widget @$19.99
При чтении ошибка iostream более вероятна, чем при записи. Если мы вводим такую последовательность:
// ошибка: item_name должно быть вторым
BuzzLightyear 10009 8.99
то инструкция
cin item_number;
закончится ошибкой ввода, поскольку BuzzLightyear не принадлежит типу int. При проверке объекта istream будет возвращено false, поскольку возникло состояние ошибки. Более устойчивая к ошибкам реализация выглядит так:
cin item_number;
if ( ! cin )
cerr "ошибка: введено некорректное значение item_number!\n ";
Хотя сцепление операторов ввода поддерживается, проверить корректность каждой отдельной операции нельзя, поэтому пользоваться таким приемом следует лишь тогда, когда ошибка невозможна. Наша программа теперь выглядит так:
#include iostream
#include string
int main()
{
int item_number;
string item_name;
double item_price;
cout "Пожалуйста, введите item_number, item_name и price: "
endl;
// хорошо, но легче допустить ошибку
cin item_number item_name item_price;
cout "Введены значения: item# "
item_number "
item_name " @$"
item_price endl;
}
Последовательность
ab c
d e
составлена из девяти символов: 'a', 'b', ' ' (пробел), 'c', '\n' (переход на новую строку), 'd', '\t' (табуляция), 'e' и '\n'. Однако приведенная программа читает лишь пять букв:
#include iostream
int main()
{
char ch;
// прочитать и вывести каждый символ
while ( cin ch )
cout ch;
cout endl;
// ...
}
И печатает следующее:
abcde
По умолчанию все пустые символы отбрасываются. Если нам нужны и они, например для сохранения формата входного текста или обработки пустых символов (скажем, для подсчета количества символов перехода на новую строку), то можно воспользоваться функцией-членом get() класса istream (обычно в паре с ней употребляется функция-член put() класса ostream; они будут рассмотрены ниже). Например:
#include iostream
int main()
{
char ch;
// читать все символы, в том числе пробельные
while ( cin.get( ch ))
cout.put( ch );
// ...
}
Другая возможность сделать это – использовать манипулятор noskipws.