Практический курс по C/C++: https://stepik.org/course/193691
Раз уж мы в
первой программе на С++ использовали объект cout для вывода
строки в стандартный выходной поток, то давайте сразу разберем работу двух
таких объектов:
- cin – объект класса
istream для работы с потоком stdin;
- cout – объект класса
ostream для работы с потоком stdout.
Если вы не
знакомы с концепцией классов и их объектов, то есть, с ООП языка С++, то фраза
«объект класса» вас может поставить в тупик. Конечно, мы сейчас не будем
пускаться во все тяжкие и уходить в изучение ООП. На данном этапе будет вполне
достаточным воспринимать объекты cin/cout, как некие
переменные, через которые можно работать со стандартными потоками ввода/вывода.
Я напомню, что в
курсе по языку Си мы подробно с вами говорили об этих потоках, которые часто
обозначаются через определения stdin/stdout. И я приводил
следующую схему их работы:
Так вот, в С++ вместо
функций printf(), scanf() и им подобных
предлагается использовать более дружественные объекты cout и cin. В чем их
дружественность и отличия от уже знакомых нам функций ввода/вывода? Начнем с
более простого объекта cout. Чтобы им воспользоваться, в программе
на С++ вначале необходимо подключить файл iostream. После этого в
пространстве имен std будет доступен объект cout. Затем, объявим
в программе несколько переменных разных типов и выведем их в стандартный поток
с помощью cout. Сделать это
можно следующим образом:
#include <iostream>
int main()
{
char str[100] = "Hi, Sergey!";
short old = 99;
double weight = 82.54;
std::cout << str << "\n";
std::cout << old << "\n";
std::cout << weight << std::endl;
}
Первое, что
бросается в глаза – это вывод значения переменной без дополнительного указания
ее типа. Например, если бы мы эту же операцию захотели бы повторить с помощью
функции printf(), то пришлось
бы прописывать форматную строку со спецификаторами:
printf("%s\n%d\n%.2f\n", str, old, weight);
При
использовании объекта cout ничего этого
делать не нужно. Просто прописываем переменную, значение которой хотим вывести
в поток stdout и все.
Если кому
интересно, как это все работает «под капотом», то скажу буквально пару слов. У
каждого класса в С++ можно делать переопределение стандартных операций. В
частности, операция << для класса ostream переопределена для каждого
стандартного, базового типа и компилятор в соответствии с типом переменной
(или, в общем случае, по данным в правом операнде), выбирает соответствующую
реализацию операции <<. Сама же операция << выполняет передачу в выходной
поток stdout соответствующих данных
и возвращает объект cout. А раз так, то мы можем записать вывод трех
переменных следующим образом:
std::cout << str << '\n' << old << "\n" << weight << std::endl;
Получим
абсолютно тот же самый результат.
Второе, на что
следует обратить внимание – это использование управляющих символов ‘\n’. Сначала я его
прописал, как символ, а второй раз – как строку. Для объекта cout это не имеет
большого значения, но, конечно, если нам нужно вывести отдельный символ, то
лучше это делать через одинарные кавычки.
В самом конце
вывода прописана функция endl. Она выполняет два действия: переводит
курсор на новую строку и очищает выходной буфер, указывая конечному устройству,
связанному с выходным потоком, что все данные переданы и их можно обрабатывать.
В случае с выводом на монитор очистка мало что дает, т.к. информация сразу
отображается на экране. Но, вполне могут быть и другие ситуации, когда вместо
монитора подключено другое устройство и вывод осуществляется только в момент
очистки выходного буфера.
Следующий объект
cin работает похожим
образом, но осуществляет уже считывание информации из стандартного входного
потока stdin и запись
прочитанных данных в указанную переменную или, в общем случае, lvalue выражение.
Давайте, для
примера выполним считывание данных в переменные old и weight с помощью cin следующим
образом:
#include <iostream>
int main()
{
char str[100] = "Hi, Sergey!";
short old = 99;
double weight = 82.54;
std::cin >> old;
std::cin >> weight;
std::cout << str << '\n' << old << '\n' << weight << std::endl;
}
Обратите
внимание, что для объекта cin переопределена операция
>> также для каждого стандартного типа языка С++. Поэтому нам достаточно
прописать переменную без указания ее типа. Причем после имени переменной не
нужно прописывать операцию взятия адреса, как это мы делали в функции scanf(). В операции >>
для этого применяется механизм ссылок. О них мы с вами еще будем подробнее
говорить.
Если данные
введены верно (целочисленное значение и вещественное), то переменные old и weight будут содержать корректные
введенные значения. Причем ввести их можно каждый с новой строки или через
пробел. Если во входном потоке stdin встречаются
данные, не соответствующие типу переменной, то значение переменной обнуляется с
неверной интерпретацией последующих операций считывания. Поэтому формат входных
данных в stdin должен совпадать
с типами читаемых данных.
Операция >>
после чтения порции данных возвращает объект cin, поэтому два
последовательных вызова cin можно объединить
в один:
std::cin >> old >> weight;
Результат будет
тем же самым.
Последний важный
момент, связанный с использованием объекта cin, это чтение
строк из входного потока. Допустим, мы в переменную str читаем строковые
данные следующим образом:
и вводим строку
«hello world». В результате
в массив str будет помещен
только первый фрагмент до пробела, то есть, «hello», а второй
останется во входном потоке. То есть, cin со строками
работает так же, как и функция scanf() языка Си. Если вам нужно читать
строку целиком (до символа перевода строки или до конца данных), то следует
использовать новую функцию getline() языка С++. Она работает с
объектом std::string и речь о ней еще впереди.
Я думаю, вы
теперь в целом хорошо понимаете, как использовать объекты cout/cin языка С++ для
работы со стандартными потоками ввода/вывода.
Практический курс по C/C++: https://stepik.org/course/193691