Std cin c что это
Поточный ввод-вывод в 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).
Результат выполнения
Функции-члены потока ввода
Функции — члены потока ввода используются для дисковых операций ввода.
Если используется входной поток файлов ( ifstream ), необходимо связать этот поток с конкретным файлом диска. Это можно сделать в конструкторе или можно использовать open функцию. В любом случае аргументы одни и те же.
Чтобы прочитать файл, сначала используйте функцию- fail член, чтобы определить, существует ли она:
Неформатированная get функция элемента работает как >> оператор с двумя исключениями. Во-первых, get функция включает пробелы, в то время как средство извлечения исключает пробелы при skipws установке флага (по умолчанию). Во-вторых, эта get функция менее вероятно приведет к тому, что связанный поток вывода ( cout например,) будет сброшен.
Вариант get функции указывает адрес буфера и максимальное число считываемых символов. Это полезно для ограничения количества символов, отправленных в конкретную переменную, как показано в примере:
Входные данные
Пример выходных данных
getline
getline Функция-член аналогична get функции. Обе функции допускают третий аргумент, который указывает завершающий символ для входных данных. Значение по умолчанию — символ новой строки. Обе функции резервируют один символ для необходимого завершающего символа. Однако get оставляет завершающий символ в потоке и getline удаляет завершающий символ.
В следующем примере задается завершающий символ для потока ввода:
Входные данные
чтение
Этот пример считывает двоичную запись из файла заработной платы в структуру:
Программа предполагает, что записи данных форматируются точно так же, как указано в структуре, без завершающего возврата каретки или символов перевода строки.
функции seekg и tellg
Чтобы использовать seekg для реализации систем управления данными, ориентированных на записи, умножьте размер записи фиксированной длины на номер записи, чтобы получить координату байта относительно конца файла, а затем используйте get объект для чтения записи.
close
close Функция члена закрывает файл диска, связанный с входным файлом потока, и освобождает файл операционной системы. ifstream Деструктор закрывает файл, но функцию можно использовать, close Если необходимо открыть другой файл для того же объекта потока.
Русские Блоги
cin.clear () и связанное с ним использование
1. cin.clear()
Используется для изменения индикатора состояния cin.
cin.sync () используется для очистки потока данных в области кэша.
Если идентификатор не изменился, его нельзя ввести, даже если поток данных очищен. Таким образом, эти два должны использоваться вместе.
Мы определяем переменную, которая будет введена как целое число, но если мы введем английские буквы или китайские символы, произойдет ошибка. В cin есть метод для обнаружения этой ошибки, который называется cin.rdstate (); когда cin.rdstate () При возврате 0 (то есть ios :: goodbit) ошибки нет, и вы можете продолжить ввод или работу. Если вы вернете 4, произойдет нефатальная ошибка, то есть ios :: failbit, вы не сможете продолжать вводить или работать. И cin.clear может контролировать нас. Идентификация этой проблемы в cin. Язык следующий: cin.clear (идентификатор); идентификационный символ:
Goodbit без ошибок
Eofbit достиг конца файла
нефитальная ошибка ввода / вывода при сбое, исправимая
badbit Фатальная ошибка ввода / вывода, не может быть исправлена. Если она находится в классе ввода / вывода, вам необходимо добавить ios :: identifier
С помощью cin.clear мы можем подтвердить его внутренний идентификатор и повторно ввести его, если он введен неправильно. В сочетании с методом реального очищения потока данных cin.sync () см. следующий пример:
2. cin.ignore()
Метод cin.ignore (a, ch) предназначен для извлечения символов из входного потока (cin). Извлеченные символы игнорируются и не используются. Каждый раз, когда символ отбрасывается, он подсчитывает и сравнивает символы: если число достигает a или символ, который отбрасывается, является ch, выполнение функции cin.ignore () прекращается, в противном случае он продолжает ждать. Обычной функцией является очистка содержимого буфера ввода, заканчивающегося возвратом каретки, что исключает влияние предыдущего ввода на следующий ввод. Например, это может быть использовано: cin.ignore (1024, ‘\ n’), обычно первый параметр устанавливается достаточно большим, так что на самом деле всегда работает только второй параметр ‘\ n’, так что это предложение ставится Все символы перед возвратом каретки (включая возврат каретки) удаляются из входного буфера (потока).
Если вы введете bcdabcd в адрес, то в это время в потоке останется bcd \ n, а cin.ignore (), в это время съедено b, что оставит оставшийся cd \ n в потоке непосредственно в cin.getline ( str3,30); должен быть символ \ n, поэтому getline возвращается прямо сюда.
3 Сравнение cin.sync () и cin.ignor ()
Но поскольку программа не всегда знает ход выполнения внешнего ввода во время выполнения программы, трудно контролировать, очищено ли содержимое буфера ввода. Часто мы можем просто отказаться от части, а не от всего входного буфера. Например, очистка текущей строки или очистка символов новой строки в конце строки. Но если в буфере уже есть следующая строка, эта часть может быть тем, что мы хотим сохранить. В настоящее время лучше не использовать sync (). Попробуйте вместо этого использовать функцию игнорирования.
cin.ignore (numeric_limits :: max (), ’/ n’); // очистить текущую строку
cin.ignore (numeric_limits :: max ()); // Очистить все в cin
Использование ignore, очевидно, более точно контролирует буфер, чем sync ().
Насколько медленны iostreams?
Потоки ввода-вывода в стандартной библиотеке C++ просты в использовании, типобезопасны, устойчивы к утечке ресурсов, и позволяют простую обработку ошибок. Однако, за ними закрепилась репутация «медленных». Этому есть несколько причин, таких как широкое использование динамической аллокации и виртуальных функций. Вообще, потоки — одна из самых древних частей стандартной библиотеки (они начали использоваться примерно в 1988 году), и многие решения в них сейчас воспринимаются как «спорные». Тем не менее, они широко используются, особенно когда надо написать какую-то простую программу, работающую с текстовыми данными.
Вопрос производительности iostreams не праздный. В частности, с проблемой производительности консольного ввода-вывода можно столкнуться в системах спортивного программирования, где даже применив хороший алгоритм, можно не пройти по времени только из-за ввода-вывода. Я также встречался с этой проблемой при обработке научных данных в текстовом формате.
Сегодня в комментариях у посту возникло обсуждение о медленности iostreams. В частности, freopen пишет
Забавно смотреть на ваши оптимизации, расположенные по соседству со считыванием через cin 🙂
Можно заменить на getchar_unlocked() для *nix или getchar() для всех остальных.
getchar_unlocked > getchar > scanf > cin, где «>» означает быстрее.
В этом посте я развею и подтвержу некоторые мифы и дам пару рекомендаций.
Все измерения в этом посте приведены для системы Ubuntu 14.10 с компилятором GCC 4.9.1, компилировалось с ключами
Запуск проводился на ноутбуке с процессором Intel Core2 Duo P8600 (2.4 ГГц).
Постановка задачи
В спортивном программировании, как и в UNIX-way, обычно входные данные подаются на входной поток. Итак, задача:
На входной поток (stdin) поступает много неотрицательных целых чисел по одному на строке. Программа должна вывести максимальное из входных чисел.
Сформируем входные данные
В файл data мы записали 10 миллионов последовательных целых чисел, общим объёмом 76 мегабайт.
Запускать программу мы будем так
1. scanf
Решим задачу с использованием старого доброго scanf.
Время работы: 1.41 c
2. Наивный std::cin
Теперь решим задачу самым простым способом при помощи iostreams:
Время работы: 4.41 c
Ого! Потоки оказались медленнее чем scanf в 3 раза! То есть выходит, что iostream оказываются действительно никуда не годится по скорости?
3. Быстрый std::cin
На самом деле, чтобы исправить ситуацию, достаточно добавить в программу одну единственную строчку. В самом начале функции main вставим:
Все последующие варианты с использованием std::cin будут использовать эту оптимизацию.
4. Наивный std::istringstream
Помимо ввода из файла, стандартная библиотека предоставляет также классы для ввода из строки с таким же интерфейсом. Посмотрим, насколько это медленно. Будем читать из входного потока по одной строке, а затем парсить её с помощью std::istringstream :
Время работы: 7.21 c
Очень медленно!
5. Переиспользование std::istringstream
Может показаться удивительным, но самое медленное в istringstream — это его создание. А мы создаём для каждой входной строки заново. Попробуем переиспользовать один и тот же объект:
Обратите внимание, что нужны 2 вызова — clear, чтобы сбросить флаги состояния, и str, чтобы задать новый буфер, из которого будет происходить чтение.
Время работы: 2.16 c
Это другое дело. Это ожидаемо медленнее, чем чтение напрямую из std::cin (данные проходят 2 раза через классы потоков), но не катастрофично.
6. Хотим ещё быстрее! (getchar/getchar_unlocked)
7. C++11: std::stoi
Время работы: 1.04 c
Это самый быстрый стандартный способ чтения целых чисел. (А для чисел с плавающей точкой есть аналогичные функции stof/stod).
8. Бонус: Чтение большими блоками + Boost::Spirit
Время работы: 0.18 c
Это рекорд!
Результаты и советы
Время работы:
No | Метод | GCC 4.9.1 | clang 3.5.0 + libc++ | GCC 100M* |
---|---|---|---|---|
1 | scanf | 1.41 | 1.48 | |
2 | std::cin | 4.41 | 13.30 | |
3 | std::cin и std::ios::sync_with_stdio(false) | 1.33 | 13.24 | |
4 | std::istringstream | 7.21 | 9.16 | |
5 | std::istringstream с переиспользованием | 2.16 | 7.92 | |
6a | getchar | 0.82 | 0.84 | 9.14 |
6b | getchar_unlocked | 0.28 | 0.26 | 2.94 |
7 | std::getline + std::stoi | 1.04 | 3.53 | 10.8 |
8 | Большой блок + Boost::Spirit | 0.18 | 1.67 | 1.90 |
* — Измерения на файле со 100 миллионами чисел (размер файла 848 мегабайт).
Рекомендации:
Update 1. По совету Lol4t0 добавлен метод номер 7.
Update 2. В таблицу добавлены времена выполнения на clang+libc++ (версия 3.5.0, выполнялось на той же системе). Видно, что производительность потоков очень плохая, да к тому же трюк с выключением синхронизации не работает. В результате stoi оказывается в 2 раза медленнее чем scanf.
Update 3. Добавлен вариант номер 8: чтение большими блоками и разбор с помощью Boost::Spirit. И это чемпион!
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 может содержать числа только до определенного размера. После этого он «переполняется». Мы обсудим переполнение в следующем уроке.