Что такое поточный ввод
Поточный ввод-вывод в C++
Поточный ввод-вывод в C++ выполняется с помощью функций сторонних библиотек. В С++, как и в С, нет встроенных в язык средств ввода-вывода.
Библиотека iostream определяет три стандартных потока:
Для их использования в Microsoft Visual Studio необходимо прописать строку:
Для выполнения операций ввода-вывода переопределены две операции поразрядного сдвига:
Возможно многократное назначение потоков:
cout
Ввод информации
При этом из входного потока читается последовательность символов до пробела, затем эта последовательность преобразуется к типу идентификатора, и получаемое значение помещается в идентификатор:
Возможно многократное назначение потоков:
cin >> переменная1 >> переменная2 >>. >> переменнаяn;
При наборе данных на клавиатуре значения для такого оператора должны быть разделены символами (пробел, \n, \t ).
Особого внимания заслуживает ввод символьных строк. По умолчанию потоковый ввод cin вводит строку до пробела, символа табуляции или перевода строки.
Результат выполнения
Для ввода текста до символа перевода строки используется манипулятор потока getline() :
Результат выполнения
Манипуляторы потока
В С++ имеется ряд манипуляторов. Рассмотрим основные:
Манипулятор | Описание |
endl | Помещение в выходной поток символа конца строки ‘\n’ |
dec | Установка основания 10-ой системы счисления |
oct | Установка основания 8-ой системы счисления |
hex | Установка основания 16-ой системы счисления |
setbase | Вывод базовой системы счисления |
width(ширина) | Устанавливает ширину поля вывода |
fill(‘символ’) | Заполняет пустые знакоместа значением символа |
precision(точность) | Устанавливает количество значащих цифр в числе (или после запятой) в зависимости от использования fixed |
fixed | Показывает, что установленная точность относится к количеству знаков после запятой |
showpos | Показывает знак + для положительных чисел |
scientific | Выводит число в экспоненциальной форме |
get() | Ожидает ввода символа |
getline(указатель, количество) | Ожидает ввода строки символов. Максимальное количество символов ограничено полем количество |
Пример Программа ввода-вывода значения переменной в C++
Та же программа, написанная на языке Си
Пример Использование форматированного вывода
Результат выполнения
Еще один пример использования форматированного вывода: для t∈[0;3] с шагом 0,5 вычислить значение y=cos(t).
Результат выполнения
Урок №207. Потоки ввода и вывода
Обновл. 15 Сен 2021 |
Функционал потоков ввода/вывода не определен как часть языка C++, а предоставляется Стандартной библиотекой C++ (и, следовательно, находится в пространстве имен std). На предыдущих уроках мы подключали заголовочный файл библиотеки iostream и использовали объекты cin и cout для простого ввода/вывода данных. На этом уроке мы детально рассмотрим библиотеку iostream.
Библиотека iostream
При подключении заголовочного файла iostream, мы получаем доступ ко всей иерархии классов библиотеки iostream, отвечающих за функционал ввода/вывода данных (включая класс, который называется iostream). Иерархия этих классов выглядит примерно следующим образом:
Первое, что вы можете заметить в этой иерархии — множественное наследование (то, что на самом деле не рекомендуется использовать). Тем не менее, библиотека iostream была разработана и тщательно протестирована соответствующим образом, дабы избежать типичных ошибок, которые возникают при работе с множественным наследованием, поэтому вы можете спокойно использовать эту библиотеку.
Потоки в С++
Второе, что вы могли бы заметить — это частое использование слова «stream» (т.е. «поток»). По сути, ввод/вывод в языке C++ реализован с помощью потоков. Абстрактно, поток — это последовательность символов, к которым можно получить доступ. Со временем поток может производить или потреблять потенциально неограниченные объемы данных.
Мы будем иметь дело с двумя типами потоков. Поток ввода (или «входной поток») используется для хранения данных, полученных от источника данных: клавиатуры, файла, сети и т.д. Например, пользователь может нажать клавишу на клавиатуре в то время, когда программа не ожидает ввода. Вместо игнорирования нажатия клавиши, данные помещаются во входной поток, где затем ожидают ответа от программы.
И наоборот, поток вывода (или «выходной поток») используется для хранения данных, предоставляемых конкретному потребителю данных: монитору, файлу, принтеру и т.д. При записи данных на устройство вывода, это устройство может быть не готовым принять данные немедленно. Например, принтер все еще может прогреваться, когда программа уже записывает данные в выходной поток. Таким образом, данные будут находиться в потоке вывода до тех пор, пока принтер не начнет их использовать.
Некоторые устройства, такие как файлы и сети, могут быть источниками как ввода, так и вывода данных.
Хорошая новость заключается в том, что программисту не нужно знать детали взаимодействия потоков с разными устройствами и источниками данных, ему нужно только научиться взаимодействовать с этими потоками для чтения и записи данных.
Ввод/вывод в C++
Класс istream используется для работы с входными потоками. Оператор извлечения >> используется для извлечения значений из потока. Это имеет смысл: когда пользователь нажимает на клавишу клавиатуры, код этой клавиши помещается во входной поток. Затем программа извлекает это значение из потока и использует его.
Класс ostream используется для работы с выходными потоками. Оператор вставки используется для помещения значений в поток. Это также имеет смысл: вы вставляете свои значения в поток, а затем потребитель данных (например, монитор) использует их.
Класс iostream может обрабатывать как ввод, так и вывод данных, что позволяет ему осуществлять двунаправленный ввод/вывод.
Стандартные потоки в C++
Стандартный поток — это предварительно подключенный поток, который предоставляется программе её окружением. Язык C++ поставляется с 4-мя предварительно определенными стандартными объектами потоков, которые вы можете использовать (первые три вы уже встречали):
Небуферизованный вывод обычно обрабатывается сразу же, тогда как буферизованный вывод обычно сохраняется и выводится как блок. Поскольку clog используется редко, то его обычно игнорируют.
Пример на практике
Вот пример использования ввода/вывода данных со стандартными потоками:
Потоковый ввод-вывод
Эти функции обрабатывают данные различных размеров и форматов, — от одного символа до больших структур данных. Они также предоставляют возможность буферизации, которая может повысить производительность. Размер буфера потока по умолчанию составляет 4 КБ. Эти подпрограммы влияют только на буферы, созданные подпрограммами библиотеки времени выполнения, и не затрагивают буферы, созданные операционной системой.
Потоковые подпрограммы ввода-вывода
Файлы, открытые с помощью потоковых подпрограмм, по умолчанию буферизуются. Функции stdout и stderr сбрасываются, когда они полны или — при записи в символьное устройство — после каждого вызова библиотеки. Если программа завершается аварийно, буферы вывода могут не быть сброшены, что приводит к потере данных. С помощью fflush или _flushall можно гарантировать, что буфер, связанный с заданным файлом, или все открытые буферы будут сброшены в операционную систему, которая может кэшировать данные перед их записью на диск. Функция фиксации на диск гарантирует, что сброшенное содержимое буфера не потеряется в случае сбоя системы.
Существует два способа сохранить зафиксировать содержимое буфера на диске:
Если программа не закрывает поток явно, поток автоматически закроется, когда завершится выполнение программы. Следует, однако, закрывать поток, когда программа завершает работу с ним, так как количество потоков, которые могут одновременно быть открыты, ограничено. _setmaxstdio Сведения об этом ограничении см. в разделе.
Что такое поточный ввод
Один из основных механизмов, который делает программу полезной является ввод/вывод. Все языки программирования имеют такой механизм. Среди операторов и ключевых слов нет ввода/вывода. Потому что в языке С++ ввод/вывод реализован в виде библиотеки. И вообще многие механизмы, которые делают язык С++ таким мощным реализованы в библиотеках (стандартные, специализированные, персональные).
Вывод: Помещение (направление) данных в поток вывода осуществляется с помощью оператора cout
Можно определить операторы потокового ввода/вывода и для созданных абстрактных типов данных.
Ввод: Ввод данных из потока осуществляется аналогично с использованием обратного оператора >> (inserter):
Переменную любого временного типа можно ввести (считать) из потока:
Для использования стандартной библиотеки нужно включить ее описание в текст программы. Это делается с помощью директивы препроцессору #include.
#include // подключение стандартной библиотеки
using namespace std; // объявление об использовании стандартного пространства имен
void main() // функция main
<
cout
Форматированный ввод/вывод
Примеры, которые приводились выше и ввод/вывод, который вы использовали на практических занятиях до сих пор, обычно называют неформатированным выводом.
Часто программисту нужно более детализированное управление. Управление осуществляется для каждого потока отдельно, т.е. если вы определили какой-то формат для потока ввода, то на поток вывода он не подействует. Более того, управление влияет только на следующее выводимое значение.
Управление можно организовать используя манипуляторы потока, которые вставляются между объектами (записываемыми или читаемыми) и тем самым изменяют состояние потока (формат вывода значений):
для вывода целых чисел
dec; // устанавливает десятичную систему счисления
hex; // устанавливает шестнадцатеричную систему счисления
oct; // устанавливает восьмеричную систему счисления
setbase(int b); // вывод целых чисел в системе счисления с основанием b(10,8. )
show base; // показывает основание системы счисления
для вывода чисел с плавающей точкой
float f=1234.56789;
cout
для вывода логических переменных
Дополнительно можно определить ширину вывода переменных в количестве символов:
setw(int n); // если строка или число длиннее, то будут выведены все setw(0)
А также задать символ для заполнения
Можно определить место размещения заполнителей. По умолчанию как видите заполнители размещаются до значения. Это аналогично записи:
endl; // заканчивается строка, т.е. вставляется символ ‘\n’
ends; // заканчивается строка записью ‘ ‘
flush; // очистка буфера потока
Это лишь основные манипуляторы, которые вы можете использовать для форматирования. С остальными познакомьтесь самостоятельно:
Манипулятор | Действие на поток |
---|---|
showbase noshowbase | инициирует отображение основания системы счисления |
showpos noshowpos | инициирует явное отображение знака (+) для положительных значений |
uppercase nouppercase | инициирует преобразование выводимых символов в верхний регистр |
showpoint noshowpoint | инициирует отображение десятичной точки при выводе вещественных чисел |
skipws noskipws | инициирует пропуск пробельных символов при вводе |
left | инициирует левое выравнивание, заполнение справа |
right | инициирует правое выравнивание, заполнение слева |
internal | инициирует внутреннее заполнение (между значением и знаком или основанием системы счисления) |
scientific | инициирует вывод вещественных значений в научном формате (d.ddddddddE+dd) |
fixed | инициирует вывод вещественных значений в фиксированном формате (d.dddddd) |
setbase (int base) | изменяет систему счисления (10, 8, 16) |
dec | инициирует вывод целочисленных значений в десятичной системе счисления |
oct | инициирует вывод целочисленных значений в восьмеричной системе счисления |
hex | инициирует вывод целочисленных значений в шестнадцатеричной системе счисления |
setfill (char n) | задает заполняющий символ |
setprecision (int n) | изменяет точность выводимых значений |
setw (int n) | задает ширину поля вывода |
Файловые потоки
Для первых программ стандартных потоков ввода/вывода будет достаточно, но по мере усложнения программ не обойтись без работы с файлом, которая в С++ осуществляется так же на основе механизма потоков.
void main()
<
ifstream inputfile(«z:\data.txt»); // создается поток ввода из файла
inputfile>>x; // все то же самое что и для cin
ofstream outputfile(«z:\res.txt»); // создается поток вывода в файл
outputfile
По умолчанию ввод и вывод данных в поток осуществляется в текстовом режиме. Для того, чтобы данные выводились в двоичном режиме следует использовать следующую запись:
По умолчанию файл открываемый для вывода создается (если он создан), а если существует, то очищается. Для того чтобы открыть файл для добавления:
Можно создать файловый поток, который запускает и ввод и вывод:
Обзор средств ввода-вывода в C++
Приложение, написанное на любом языке программирования, должно взаимодействовать с окружающим миром. Иначе пользы от него не будет. Как правило, такое взаимодействие осуществляется посредством ввода-вывода информации на монитор или в файл. Правда, есть некоторое множество программ, которые не используют файловый или консольный ввод-вывод: это программы, осуществляющие низкоуровневое взаимодействие с аппаратной частью компьютера и периферией (ядро ОС, драйверы и пр.), но это уже экзотика.
В стандартном C++ существует два основных пути ввода-вывода информации: с помощью потоков, реализованных в STL (Standard Template Library) и посредством традиционной системы ввода-вывода, унаследованной от C. Если копнуть немного глубже, то окажется, что и потоки, и традиционная система ввода-вывода для осуществления необходимых действий используют вызовы операционной системы. И это правильно.
Дальнейшее изложение не претендует на полноту, но описывает основные принципы использования библиотек. Подробности использования можно посмотреть в многочисленной литературе по C++ и STL, в MSDN и пр.
Традиционный ввод-вывод
Библиотека stdio предоставляет необходимый набор функций для ввода и вывода информации как в текстовом, так и в двоичном представлении. Следует отметить, что в отличие от классической C‑библиотеки, в современных библиотеках имеются более безопасные аналоги «классических» функций. Как правило, они имеют такое же имя, к которому добавлен суффикс _s. Рекомендуется использовать именно эти, безопасные функции.
Самая Первая Программа с использованием библиотеки stdio выглядит так:
В stdio для консольного ввода-вывода предусмотрена отдельная группа функций. Однако эти функции, как правило, являются обёртками для аналогичных функций файлового ввода-вывода, для которых аргумент типа FILE задан по умолчанию.
Самая Первая Программа с использование файлового вывода из библиотеки stdio выглядит так:
Некоторые популярные функции из stdio:
Сущность FILE представляет собой структуру, в которой хранится вся информация для управления потоком ввода-вывода.
Файл открывается функцией fopen(), которой передаются два параметра. Первый параметр определяет имя файла. Второй — определяет режим открытия файла: чтение, запись, произвольный доступ и т.п., а также указание на то, как работать с данными: в текстовом или двоичном режиме. Подробности — см. в документации.
Пример использования stdio
Ввод-вывод с помощью потоков STL
Самая Первая Программа с использованием потоков STL выглядит так:
Потоки cin, cout и cerr соответствуют потокам stdin, stdout и stderr соответственно.
Иерархия классов ввода-вывода STL достаточно сложна. Любители тонких ощущений могут найти её описание в литературе. Впрочем, остальных также не минует чаша сия, но только позже, когда потребуются знания чуть повыше того базового уровня, который описывается здесь.
Для ввода-вывода сначала необходимо создать поток — экземпляр соответствующего класса STL, а затем связать его с файлом. Для потока вывода используется класс ofstream, для потока ввода — ifstream, для потока ввода-вывода — fstream. В каждом из этих классов есть метод open(), который связывает поток с файлом. Проще говоря, открывает файл. Методу передаются два параметра: имя файла и режим открытия файла. Второй параметр представляет собой набор битовых флагов, определяющих режим открытия файла (чтение, запись и пр.) и способ работы с данными (текстовый или двоичный режим). Второй параметр опционален, т.е. имеет значение по умолчанию, соответствующее классу.
Вышеупомянутые классы имеют также конструкторы, позволяющие открыть файл сразу при создании потока. Параметры этих конструкторов полностью совпадают с параметрами метода open().
При ошибке открытия файла (в контексте логического выражения) поток получает значение false.
Файл закрывается методом close(). Этот метод также вызывается при разрушении экземпляров классов потоков.
Операции чтения и записи в поток, связанный с файлом, осуществляются либо с помощью операторов >, перегруженных для классов потоков ввода-вывода, либо с помощью любых других методов классов потоков ввода-вывода.
Некоторые наиболее употребляемые методы:
Пример использования потоков STL
Взаимодействие потокового и традиционного ввода-вывода
Апологеты C++ рекомендуют использовать для ввода-вывода только потоки STL и отказаться от использования традиционного ввода-вывода в духе C. Однако, ничто не мешает, по крайней мере пока, использовать традиционную систему ввода-вывода. Более того, предусмотрена специальная функция для синхронизации ввода-вывода, выполненного посредством потоков и посредством старых функций.
Заключение
Какой механизм использовать — вопрос предпочтений программиста, если работодателем явно не предписано использование конкретного механизма. В любом случае для физического ввода-вывода используются вызовы операционной системы. Всё остальное — обёртка, набор более или менее удобных функций или классов для взаимодействия с ОС.
Использование механизма потоков считается более безопасным. Но, как известно, плохую программу можно написать на любом языке программирования. Это также относится и к использованию библиотек. Автор статьи: Череп.