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

Второй оператор выводит endl — специальное значение, называемое манипулятором (manipulator). При его записи в поток вывода происходит переход на новую строку и сброс буфера (buffer), связанного с данным устройством. Сброс буфера гарантирует, что весь вывод, который программа сформировала на данный момент, будет немедленно записан в поток вывода, а не будет ожидать записи, находясь в памяти.

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

Использование имен из стандартной библиотеки

Внимательный читатель, вероятно, обратил внимание на то, что в этой программе использована форма записи std::cout и std::endl, а не просто cout и endl. Префикс std:: означает, что имена cout и endl определены в пространстве имен (namespace) по имени std. Пространства имен позволяют избежать вероятных конфликтов, причиной которых является совпадение имен, определенных в разных библиотеках. Все имена, определенные в стандартной библиотеке, находятся в пространстве имен std.

Побочным эффектом применения пространств имен библиотек является то, что названия используемых пространств приходится указывать явно, например std. В записи std::cout применяется оператор области видимости :: (scope operator), позволяющий указать, что здесь используется имя cout, которое определено в пространстве имен std. Как будет продемонстрировано в разделе 3.1, существует способ, позволяющий программисту избежать частого использования подробного синтаксиса.

Чтение из потока

Отобразив приглашение к вводу, необходимо организовать чтение введенных пользователем данных. Сначала следует определить две переменные (variable), в данном случае v1 и v2, которые и будут содержать введенные данные:

int v1 = 0, v2 = 0;

Эти переменные определены как относящиеся к типу int, который является встроенным типом данных для целочисленных значений. Мы также инициализируем (initialize) их значением 0. При инициализации переменной ей присваивается указанное значение в момент создания.

Следующий оператор читает введенные пользователем данные:

std::cin >> v1 >> v2;

Оператор ввода (input operator) (т.е. оператор >>) ведет себя аналогично оператору вывода. Его левым операндом является объект типа istream, а правым операндом — объект, заполняемый данными. Он читает значение из потока, представляемого объектом типа istream, и сохраняет его в объекте, заданном правым операндом. Подобно оператору вывода, оператор ввода возвращает в качестве результата свой левый операнд. Другими словами, эта операция эквивалентна следующей:

(std::cin >> v1) >> v2;

Поскольку оператор возвращает свой левый операнд, мы можем объединить в одном операторе последовательность из нескольких запросов на ввод данных. Наше выражение ввода читает из объекта std::cin два значения, сохраняя первое в переменной v1, а второе в переменной v2. Другими словами, рассматриваемое выражение ввода выполняется как два следующих:

std::cin >> v1;

std::cin >> v2;

Завершение программы

Теперь осталось лишь вывести результат сложения на экран.

std::cout << "The sum of " << v1 << " and " << v2

          << " is " << v1 + v2 << std::endl;

Хоть этот оператор и значительно длиннее оператора, отобразившего приглашение к вводу, принципиально он ничем не отличается. Он передает значения каждого из своих операндов в поток стандартного устройства вывода. Здесь интересен тот факт, что не все операнды имеют одинаковый тип значений. Некоторые из них являются строковыми литералами, например "The sum of ", другие значения относятся к типу int, например v1 и v2, а третьи представляют собой результат вычисления арифметического выражения v1 + v2. В библиотеке определены версии операторов ввода и вывода для всех этих встроенных типов данных.