Выбрать главу

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.

Каждая из двух данных последовательностей считается составленной из пяти строк, разделенных пробелами, если для чтения используются операторы ввода с типами const char* или string:

A fine and private place

"A fine and private place"

Наличие кавычек не делает пробелы внутри закавыченной строки ее частью. Просто открывающая кавычка становится начальным символом первого слова, а закрывающая – конечным символом последнего.

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

#include algorithm

#include string

#include vector

#include iostream

int main()

{

istream_iterator string in( cin ), eos ;

vector string text ;

// копировать прочитанные из стандартного ввода значения

// в вектор text

copy( in , eos , back_inserter( text ) ) ;

sort( text.begin() , text.end() ) ;

// удалить дубликаты

vector string ::iterator it;

it = unique( text.begin() , text.end() ) ;

text.erase( it , text.end() ) ;

// вывести получившийся вектор

int line_cnt = 1 ;

for ( vector string ::iterator iter = text.begin() ;

iter != text.end() ; ++iter , ++line_cnt )

cout *iter

( line_cnt % 9 ? " " : " \n" ) ;

cout endl;

}

Пусть входом для этой программы будет файл istream_iter.C с исходным текстом. В системе UNIX мы можем перенаправить стандартный ввод на файл следующим образом (istream_iter – имя исполняемого файла программы):