Страницы

Поиск по вопросам

вторник, 2 октября 2018 г.

Что такое поток (stream)?

В книжках пишут про стандартные потоки ввода-вывода в C++, запись в поток и чтение из потока.
Что такое поток, и что он из себя представляет?


Ответ

Поток это просто абстракция. Удобная абстракция для решения задач.
Но если так будет легче - считайте, что это такая труба. С одной стороны в нее пихаются данные, а с другой куда то уходят (например, на консоль или в файл). Так как труба не нулевого размера, часть данных там может "задерживаться" - это так называемая буферизация. Понимание этого может облегчить понимание некоторого странного поведения стандартных потоков.
Рассмотрим например, такое чтение с консоли:
int n; std::string s; std::cin >> n >> s;
и такие данные на вход:
123a aaa
Как это будет работать? Вначале стандартному потоку нужно прочитать число. Он будет читать до тех пор, пока там число. В n попадет 123. В "трубе осталось "a aaa". Дальше нужно прочитать строку. А строка читается до пробела или перевода строки. Поэтому прочитается только одно a. А многие полагают, что прочитается три а. Я привел этот пример не просто так. На него многие попадаются.
Как это реализовано внутри? Очень просто. Есть очередь (то есть, если очень грубо - массив), откуда читают данные байт за байтом. Если в очереди ничего нет - библиотечный код обращается к функциям операционной системы и читает с консоли/файла/сокета) и складывает в очередь. Конечно, в некоторых случаях эта очередь может быть реализована на базе операционной системы, а может и явно. Но для пользователя (то есть программиста) это прозрачно.
Аналогично работает и вывод.
Чем удобны потоки?
После того, как поток "подключен" к файлу или консоли, дальше все идет одинаково. Можно, к примеру написать функции, которые будут выводить в поток, но при этом абсолютно не знать, куда именно они выводят. Это позволяет писать обобщенные алгоритмы и прочие вкусности.
Например, нужно сделать функцию форматированного вывода числа на консоль (со спец. пожеланиями). Можно конечно закодить вывод на std::cout, но как протестить? Можно написать функцию, которая будет на вход получать ostream (предок std::cout) и выводить в него. Потом можно использовать такую функцию и выводить в stringstream, который легко преобразовывается в строку и результат можно выверить тестом.

Комментариев нет:

Отправить комментарий