Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
C++ для начинающих.pdf
Скачиваний:
183
Добавлен:
01.05.2014
Размер:
3.97 Mб
Скачать

Это друзья Пуха: Тигра Пятачок Иа-Иа Кролик

Упражнение 20.1

string sa[4] = { "пух", "тигра", "пятачок", "иаиа" };

vector< string > svec( sa, sa+4 ); string robin( "кристофер робин" ); const char *pc = robin.c_str(); int ival = 1024;

char blank = ' '; double dval = 3.14159;

Даны следующие определения объектов: complex purei( 0, 7 );

(a)Направьте значение каждого объекта в стандартный вывод.

(b)Напечатайте значение адреса pc.

(c)Напечатайте наименьшее из двух значений ival и dval, пользуясь оператором условного выражения:

ival < dval ? ival : dval

20.2. Ввод

Основное средство реализации ввода – это оператор сдвига вправо (>>). Например, в следующей программе из стандартного ввода читается последовательность значений

#include <iostream> #include <vector>

int main()

{

vector<int> ivec; int ival;

while ( cin >> ival ) ivec.push_back( ival )

;

// ...

типа int и помещается в вектор:

}

Подвыражение

cin >> ival;

читает целое число из стандартного ввода и копирует его в переменную ival. Результатом является левый операнд – объект класса istream, в данном случае cin. (Как мы увидим, это позволяет сцеплять операторы ввода.)

Выражение

while ( cin >> ival )

читает последовательность значений, пока cin не станет равно false. Значение istream может быть равно false в двух случаях: достигнут конец файла (т.е. все значения из файла прочитаны успешно) или встретилось неверное значение, скажем 3.14159 (десятичная точка недопустима в целом числе), 1e-1 (буква e недопустима) или любой строковый литерал. Если вводится неверное значение, объект istream переводится в состояние ошибки и чтение прекращается. (В разделе 20.7 мы подробнее расскажем о таких состояниях.)

Есть набор предопределенных операторов ввода, принимающих аргументы любого встроенного типа, включая C-строки, а также стандартных библиотечных типов string и

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

complex:

}

Вот пример выполнения этой программы:

Пожалуйста, введите 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_nu mber;

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

de

составлена из девяти символов: 'a', 'b', ' ' (пробел), 'c', '\n' (переход на новую строку), 'd', '\t' (табуляция), 'e' и '\n'. Однако приведенная программа читает лишь

#include <iostream>

int main()

{

char ch;

// прочитать и вывести каждый символ

while ( cin >> ch ) cout << ch;

cout << endl;

// ...

пять букв:

}

И печатает следующее:

abcde

По умолчанию все пустые символы отбрасываются. Если нам нужны и они, например для сохранения формата входного текста или обработки пустых символов (скажем, для подсчета количества символов перехода на новую строку), то можно воспользоваться функцией-членом get() класса istream (обычно в паре с ней употребляется функция-

#include <iostream>

int main()

{

char ch;

// читать все символы, в том числе пробельные

while ( cin.get( ch )) cout.put( ch );

// ...

член put() класса ostream; они будут рассмотрены ниже). Например:

}

Другая возможность сделать это – использовать манипулятор noskipws.

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

A fine and private place "A fine and private place"

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

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

#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_iterator:

}

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

istream_iter < istream_iter.C

(Для других систем необходимо изучить документацию.) В результате программа выводит:

!= " " "\n" #include % ( ) *iter ++iter ++line_cnt , 1 9 : ; << <algorithm> <iostream.h>

<string> <vector> = > >::difference_type >::iterator ? allocator back_inserter(

cin copy( cout diff_type eos for in in( int

istream_iterator< it iter line_cnt main() sort( string test test.begin()