Std cout что это
Поточный ввод-вывод в 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).
Результат выполнения
Обзор средств ввода-вывода в 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. Однако, ничто не мешает, по крайней мере пока, использовать традиционную систему ввода-вывода. Более того, предусмотрена специальная функция для синхронизации ввода-вывода, выполненного посредством потоков и посредством старых функций.
Заключение
Какой механизм использовать — вопрос предпочтений программиста, если работодателем явно не предписано использование конкретного механизма. В любом случае для физического ввода-вывода используются вызовы операционной системы. Всё остальное — обёртка, набор более или менее удобных функций или классов для взаимодействия с ОС.
Использование механизма потоков считается более безопасным. Но, как известно, плохую программу можно написать на любом языке программирования. Это также относится и к использованию библиотек. Автор статьи: Череп.
1.5 – Знакомство с iostream: cout, cin и endl
Библиотека ввода/вывода
Библиотека ввода/вывода (библиотека io) является частью стандартной библиотеки C++, которая имеет дело с базовым вводом и выводом. Мы будем использовать функции этой библиотеки для получения ввода с клавиатуры и вывода данных в консоль. Буквы io в iostream означают «input/output» (ввод/вывод).
std::cout
Вспомним нашу программу Hello world :
std::cout может печатать не только текст, но и числа:
Это дает результат:
Его также можно использовать для вывода значений переменных:
Это дает результат:
Чтобы напечатать несколько элементов в одной строке, для объединения (связывания) нескольких частей выводимых данных, оператор вставки ( ) можно использовать несколько раз в одном выражении. Например:
Эта программа печатает:
Вот еще один пример, в котором мы печатаем и текст, и значение переменной в одном выражении:
Эта программа печатает:
std::endl
Как вы думаете, что напечатает следующая программа?
Результат может вас удивить:
Отдельные выражения вывода не приводят к отдельным выводимым строкам в консоли.
Если мы хотим выводить в консоль отдельные выводимые строки, нам нужно указать консоли, когда необходимо переместить курсор на следующую строку.
Совет
В приведенной выше программе второй std::endl технически не нужен, так как программа сразу же после этого завершается. Однако он служит двум полезным целям: во-первых, он помогает указать, что строка вывода является «законченной мыслью». Во-вторых, если мы позже захотим добавить дополнительные выражения вывода, нам не нужно будет изменять существующий код. Мы можем просто добавить новые выражения.
std::endl против ‘\n’
Вот пример, в котором ‘\n’ используется двумя разными способами:
Этот код напечатает:
Обратите внимание, что когда ‘\n’ используется сам по себе для перемещения курсора на следующую строку, необходимы одинарные кавычки. При встраивании в текст, который уже заключен в двойные кавычки, одинарные кавычки не нужны.
Мы рассмотрим, что такое ‘\n’ более подробно, когда перейдем к уроку о символах (4.11 – Символы).
Лучшая практика
Предупреждение
‘\n’ использует обратный слеш (как и все специальные символы в C++), а не прямой слеш. Использование прямого слеша (например, ‘/n’ ) может привести к неожиданному поведению.
std::cin
Если ваш экран закрывается сразу после ввода числа, обратитесь к уроку «0.8 – Несколько основных проблем C++» для решения этой проблем.
Лучшая практика
Существуют споры о том, нужно ли инициализировать переменную непосредственно перед тем, как передать ей значение, предоставленное пользователем, через другой источник (например, std::cin ), поскольку значение, предоставленное пользователем, просто перезапишет значение инициализации. В соответствии с нашей предыдущей рекомендацией о том, что переменные всегда следует инициализировать, лучше всего сначала инициализировать переменную.
Мы обсудим, как std::cin обрабатывает недопустимые входные данные в следующем уроке (7.16 – std::cin и обработка недопустимых входных данных).
Для продвинутых читателей
Резюме
Подробнее об операторах мы поговорим в уроке «1.9 – Знакомство с литералами и операторами».
Небольшой тест
Вопрос 1
Рассмотрим следующую программу, которую мы использовали выше:
Запустите эту программу несколько раз и опишите, что произойдет, если вместо этого вы введете следующие типы входных данных:
б) Число с дробной частью. Попробуйте числа с дробными составляющими меньше 0,5 и больше 0,5 (например, 3,2 и 3,7).
Дробная составляющая опущена.
Всё прекрасно работает.
г) Слово, например «Hello».
д) Действительно большое число (минимум 3 миллиарда).
Вы получаете, казалось бы, случайное число.
Последнее предложение может быть особенно неожиданным. Попробуйте! Это происходит потому, что x может содержать числа только до определенного размера. После этого он «переполняется». Мы обсудим переполнение в следующем уроке.
Изучаем C++.Часть 4. Ввод данных и обработка исключений
Разбираемся, как правильно использовать ввод данных, чтобы ничего не сломалось.
Это четвёртая часть из серии статей «Глубокое погружение в C++». В прошлый раз мы познакомились с ветвлением и условными конструкциями. Сейчас поговорим о том, как сделать программу более полезной за счёт ввода данных и обработки исключений.
Если программа работает с изначально заданными данными, то она полезна только один раз, потому что результат будет всегда один и тот же. Гораздо эффективнее она становится, когда можно использовать разные данные:
Как получить и обработать данные через консоль? Давайте пробовать.
Пишет о программировании, в свободное время создает игры. Мечтает открыть свою студию и выпускать ламповые RPG.
Команды ввода и вывода в C++
В самом начале кода каждой программы мы подключаем библиотеку iostream — Input/Output Stream (поток ввода/вывода). Именно в ней находится команда cout, что позволяет выводить данные на экран консоли. В ней же есть команда cin, которая, наоборот, запрашивает пользовательский ввод.
Давайте напишем простую программу, которая спрашивает имя пользователя.
Сначала мы объявили переменную name строкового типа, а потом сказали пользователю, что именно нужно ввести, и в конце выдали сообщение «Hello, %name%!». Это выглядит так:
Важно! Старайтесь всегда сообщать пользователю, какие действия от него требуются и что происходит в программе.
Также вы можете запросить от пользователя данные других типов. Например, числовые:
Получается простейший калькулятор:
Это работает с символами, числами с плавающей запятой и другими данными.
Проверка консольного ввода в C++
Как мы уже говорили в первой статье, компьютер может только выполнять инструкции. Когда что-то идёт не по плану, он не способен самостоятельно решить, что ему делать, поэтому выдаёт ошибку.
Допустим, нам нужно, чтобы пользователь ввёл свой возраст. Мы ожидаем число вроде 8, 15 или 21, но кто-то может ввести эти числа прописью, например «двадцать один». Для программы эти варианты будут неожиданными, потому что она уже подготовила переменную типа int — строка в неё никак не влезет.
Чтобы избежать таких ошибок, любые данные от пользователей стоит принимать как строку, а потом переводить в нужный нам тип. Процесс преобразования данных из одного типа в другой называется конвертацией.
Конвертация данных
В C++ самый простой способ конвертировать строку в число — использовать функцию stoi () или аналогичную:
Вот пример корректной и некорректной конвертации:
Как видно на скриншоте, в первом случае всё прошло успешно, но в следующих случаях программа выдала ошибку. Давайте рассмотрим последнюю:
Разберём некоторые моменты подробнее:
Чтобы программа не закрывалась при выбрасывании исключений, их нужно обработать.
Обработка исключений в C++
Для этого нам пригодится конструкция try-catch.
Вот код программы, которая проверяет корректность введённых данных:
Теперь можно запустить её и попробовать ввести любые значения — программа определит, какое сообщение вывести, и благополучно завершится.
6.12 – Объявления using и директивы using
Вы, наверное, видели эту программу во многих учебниках и учебных руководствах:
Некоторые старые компиляторы также начинают новые проекты с аналогичной программы.
Если вы это видите, бегите. Возможно, ваш учебник, руководство или компилятор устарели. В этом уроке мы выясним, почему.
Краткий урок истории
Перенесемся в сегодняшний день – если вы много используете стандартную библиотеку, набирание std:: перед всем, что вы используете из стандартной библиотеки, может стать повторяющейся рутиной, а в некоторых случаях может затруднить чтение вашего кода.
Но сначала давайте определим два термина.
Полные и неполные имена
Имя может быть полным или неполным.
Полное имя – это имя, которое включает в себя связанную область видимости. Чаще всего имена дополняются пространством имен с помощью оператора разрешения области видимости ( :: ). Например:
Для продвинутых читателей
Неполное имя – это имя, которое не включает в себя квалификатор области видимости. Например, cout и x являются неполными именами, поскольку они не включают связанную область видимости.
Объявления using
Директивы using
Вот снова наша программа Hello World с директивой using в строке 5:
Директивы using – это решение, которое было предоставлено для баз старого кода до пространства имен, которые использовали неполные имена для функций стандартной библиотеки. Вместо того, чтобы вручную обновлять каждое неполное имя до полного имени (что было рискованно), можно было бы разместить одну директиву using (т.е. using namespace std; ) в верхней части каждого файла, и все имена, которые были перемещены в пространство имен std всё еще можно было использовать неполными.
Проблемы с директивами using
Однако для современного кода C++ директивы using дают немного выгоды (экономия на вводе текста) по сравнению с риском.
Поскольку директивы using импортируют все имена из пространства имен (потенциально включая множество имен, которые вы никогда не будете использовать), вероятность возникновения конфликтов имен значительно возрастает (особенно, если вы импортируете пространство имен std ).
Для наглядности рассмотрим пример, в котором директивы using вызывают неоднозначность:
Вот еще один более коварный пример:
или использовалось объявление using вместо директивы using :
тогда наша программа вообще не имела бы никаких проблем.
Даже если директивы using не вызывают конфликтов имен сегодня, они делают код более уязвимым для будущих конфликтов. Например, если ваш код включает директиву using для какой-либо библиотеки, которая затем обновляется, все новые имена, представленные в обновленной библиотеке, теперь являются кандидатами на конфликты имен с вашим существующим кодом.
Может возникнуть и более коварная проблема. В обновленной библиотеке может появиться функция, которая не только имеет то же имя, но и лучше подходит для некоторых вызовов функций. В таком случае компилятор может решить отдать предпочтение новой функции, и поведение вашей программы неожиданно изменится.
Рассмотрим следующую программу:
Когда компилятор встречает вызов функции, он должен определить, с каким определением функции он должен сопоставить этот вызов. При выборе функции из набора потенциально совпадающих функций он предпочтет ту функцию, которая не требует преобразования аргументов, а не ту, которая требует преобразования аргументов. Поскольку литерал 0 принадлежит целочисленному типу, C++ предпочтет сопоставить someFcn(0) с недавно добавленной someFcn(int) (без преобразований), а не с someFcn(double) (требуется преобразование из int в double). Это вызывает неожиданное изменение результатов работы нашей программы.
Этого бы не произошло, если бы мы использовали объявление using или явный квалификатор области видимости.
Область видимости объявлений и директив using
Если объявление using или директива using используется в блоке, имена применимы только в этом блоке (они следуют обычным правилам области видимости блока). Это хорошо, поскольку снижает вероятность возникновения конфликтов имен внутри этого блока.
Если объявление using или директива using используются в глобальном пространстве имен, имена применимы ко всему остальному файлу (они имеют область видимости файла).
Отмена или замена инструкции using
После объявления инструкции using ее невозможно отменить или заменить ее другой инструкцией using в той области видимости, в которой она была объявлена.
Лучшее, что вы можете сделать, – это намеренно с самого начала ограничить область видимости инструкции using с помощью правил области видимости блока.
Конечно, всей этой головной боли можно избежать, в первую очередь, используя явным образом оператор разрешения области видимости ( :: ).
Лучшие практики для инструкций using
В современном C++ на самом деле нет места для использования директив. Они увеличивают вероятность коллизий имен сейчас и в будущем и могут вызывать более коварные проблемы. Хотя во многих учебниках и руководствах они широко используются, использования директив лучше вообще избегать.
Объявления using обычно считаются безопасными для использования внутри блоков. Ограничьте их использование в глобальном пространстве имен файлов исходного кода и никогда не используйте их в глобальном пространстве имен заголовочных файлов.
Лучшая практика