Поток (stream) — абстракция источника или приёмника данных. Стандартные потоки
объявлены в <iostream>: std::cin — ввод, std::cout — вывод,
std::cerr — вывод ошибок.
Не из лекции
На занятии разбирались
std::cin,std::cout, цепочки>>и<<,'\n'иstd::boolalpha. Сравнение сstd::endl,std::cerr,std::getlineи проверка состояния потока — материал не оттуда.
#include <iostream>
int main() {
int value = 0;
std::cin >> value;
std::cout << "Получено: " << value << '\n';
return 0;
}Операторы >> и << можно выстраивать цепочкой, потому что каждый возвращает
сам поток: std::cin >> a >> b читает два значения подряд.
Если программа ждёт ввод, отсутствие нового вывода ещё не означает, что она зависла.
В std::cout << x символы << означают вывод, а не сдвиг: смысл операции
определяют операнды, а не значок. См. Побитовые операции.
Логические значения на выводе
По умолчанию bool печатается числом. std::boolalpha меняет формат
на словесный:
std::cout << std::boolalpha;
std::cout << (0.1 + 0.2 == 0.3) << '\n'; // false вместо 0Манипулятор липкий — действует до отмены (std::noboolalpha) и меняет только
формат вывода, а не сами значения.
Как читается ввод
>> пропускает ведущие пробельные символы (пробелы, табуляции, переводы строк),
читает столько, сколько подходит под тип, и останавливается на первом
неподходящем символе, оставляя его в потоке.
Отсюда следствия:
- разделение чисел пробелами или переводами строк для
>>неразличимо; - чтение строки через
>>даёт одно слово, а не всю строку — для строки целиком естьstd::getline; - если во вводе не число, чтение не выполняется, поток переходит в состояние ошибки и переменная остаётся с прежним значением. Именно поэтому её важно инициализировать заранее.
Проверить успешность можно прямо в условии — поток приводится к bool:
if (!(std::cin >> value)) {
// ввод не удался
}'\n' или std::endl
Оба переводят строку, но std::endl дополнительно сбрасывает буфер вывода
(flush). Сброс — обращение к операционной системе; в цикле на сотни тысяч
итераций разница заметна и решает задачу по времени.
std::cout << value << '\n'; // просто перевод строки
std::cout << value << std::endl; // перевод строки + сброс буфераПо умолчанию используют '\n'. std::endl нужен, когда вывод должен появиться
немедленно: перед долгой операцией, при отладке падающей программы.
Одиночный символ пишут в одинарных кавычках: '\n' — это char, а "\n" —
строка из двух байт, включая завершающий ноль.
Тонкости
- Вывод буферизуется. Если программа падает, часть вывода может не появиться —
при отладке печатью это сбивает с толку, и здесь
std::endlуместен. std::cerrне буферизуется и не смешивается сstd::coutпри перенаправлении в файл — для сообщений об ошибках используют его.- Форматирование (ширина поля, заполнитель, точность) живёт в
<iomanip>, см. Форматирование вывода. - В соревновательных задачах ускоряют ввод-вывод отключением синхронизации с C-потоками; в учебных задачах это не нужно.
Частые ошибки
std::endlв цикле на большом объёме вывода — потеря времени на ровном месте.- Чтение строки с пробелами через
>>— получится только первое слово. - Отсутствие проверки, что ввод вообще прочитался.