Посимвольный ввод с помощью cin.get() в С++

Довольно часто в решениях программистов может встречаться нужда посимвольного ввода данных. Символы могут приходить из клавиатуры (в простейшем для нас виде), из файлов, со сканера и из любых других устройств ввода. Т. е. что-то может сообщать компьютерам программам информацию, а сообщать информацию можно не только в чистых байтах, но и в удобном для нас (но неудобном для компьютера) виде: посимвольно.
Поскольку мой читатель, следующий порядку следования тем сайта, с большой вероятностью только успел ознакомится с типом char, обозначающим тип-символ, то пока что я ограничусь вводом символов только с клавиатуры.
Для понимания этой темы нужно знать:

Имеет смысл осознать термин буферизация. Под буферизацией понимают временное накопление входящих данных в память. Например, когда мы вводим слово, буферизируется каждый символ слова и каждый символ слова попадает в собственную ячейку памяти. Не совсем, конечно, всё прям так, как я пишу, но после разбора примеров, вы прекрасно поймёте, что это такое. Просто чтобы сами примеры было проще объяснять, имело смысл начать разъяснение непонятного некоторым новичкам термина. Буфер — это карман. Информация в карман попадает, информация из кармана вытаскивается. Т. е. если путник идёт по дороге и в каждом новом населённом пункте он получает себе магнитик-сувенир. В конце своего пути путник вытаскивает все магнитики, чтобы, например, полюбоваться ими. Этот процесс и называется буферизацией.
Итак, чтобы вводить посимвольно, например, строки, нам нужно задействовать два механизма: цикл и операцию ввода.

Пример работы программы показан на рисунке
Очень важно спровоцировать сам запуск цикла. Так, например, если ch не инициализировано (непрекращающим цикл) значением или если не ввести (непрекращающее цикл) значение в ch непосредственно перед началом работы цикла, то в ch может оказаться вообще любой символ, в том числе тот, которым обозначено, что цикл прекратит свою работу. Т. е. в нашем случае мы задаём любой символ, который не решётка, чтобы по стечению обстоятельств решётка (как завершающий цикл символ) не попало в ch перед началом работы цикла.
Немного модифицируем программу так, чтобы нам выводилось какое-нибудь сообщение. Пусть этим сообщением будет значение ch.

Результат работы программы можно увидеть на рисунке:

Ввод cin буферизуется. Поэтому мы можем легко замаскировать посимвольный ввод в вод строки. Обратите внимание, что одиночный символ и набор одиночных символов — вообще разные сущности. В нашем случае мы выводим на экран одиночный символ, но почему видим строковое представление? Помните нашего путника, собирающего сувениры? Так вот, каждый вводимый символ запоминался в буфере (подобно сувениру путнику в карман), а когда сбор закончился (путник закончил свой путь) — всё что собралось мы разом вывели на экран (путник опустошил свой карман в конце своего пути).

Небольшое неудобство данной программы будет видно при нажатии клавиши Enter, если забыть в строке упомянуть символ, завершающий цикл. Даже если попробовать включить символ нажатия Enter, этот ни к чему не приведёт (в листинге #3 показывается код с условием). В таком случае произойдёт переход на новую строчку и будет ожидание дальнейшего ввода символов. Этот момент показывается на очередном рисунке:

Т. е. если поспешить и забыть ввести символ-решётку для окончания ввода, у нас происходит небольшой конфуз, который портит эстетичный вид программы. Можно конечно пробовать всеми силами исправить эту мелкую неприятность, например, попробовать изменить условие в цикле:

Но тут менять не условие надо, а сам подход. Здесь сказывается свойство операции >>, которая игнорирует все пробельные символы, т. е. игнорируются и пробелы и перенос строки и символ табуляции и всё, что попадает в категорию пробельных символов. Т. е. перенос строки в ch никогда не попадает.
Для решения подобной проблемы и придания нашей программе более изящного вида, нужно задейтвовать механизмы ввода, которые позволяют использовать пробельные символы. Одним из таких механизмов является умение объекта cib сохранять в буфере все символы:

Исправим нашу программу, внеся поправки, согласно только что узнанной информации:

Теперь наша программа имеет привлекательный эстетический вид. К тому же обновлённая версия считает не только отображаемые символы, но и пробелы, включая символ переноса строки. Как и в первом случае, ввод буферизуется, поэтому можно ввести больше информации, чем на самом деле попадёт в программу. Т. е. у нас ничего не изменилось, кроме того, что стали учитываться все символы, а выход стал возможен по нажатию клавиши Enter.
  • Перед чтением дальше вам нужно осознать уже описанное в этой статье.
У cin.get есть три формы. Одну из форм мы использовали при написании нами цикла.Есть похожая форма, но с пустыми круглыми скобками.

Этой формой можно подменить первую. Вся разница в том, что хдесь мы используем прямое присваивание, что может давать больше ясности в коде. Будет понятнее, что ch изменяется.

Оставшаяся форма выглядит так:

Последняя показанная форма предполагает ввод массива символов, причём введённый массив символ самостоятельно добьётся нуль-символом, создав нам из массива символов строку в стиле C. Если символов будет введено больше, чем указано, то всё, что не вместилось в заявленное количество, будет проигнорировано. (Можно вспомнить предыдущие примеры)
Поскольку автор этой статьи считает немного неразумным слишком идеально разжёвывать каждую отдельную форму, автор решил объединить их все в одном простом примере. Просто покажу, как оно может использоваться. К тому же попрошу обратить внимание, что иногда нужно пропускать попадающий в буфер символ нажатого Enter, иначе этот символ способен учитываться как введённый. По примеру вы сможете легко усвоить, что если операцией ввода нсимвол нажатого Enter игнорируется, то вообще он попадает в память компьютера. Просто при запросе прогараммы к памяти компьютера и обнаружении необрабатываемого символа, символ не попадает в cin.

Надеюсь, что эта статья добавила вам полезных знаний.
Два показанные ниже кода полностью эквивалентны (т. е. конечный результат один и тот же):

Использованные материалы:

Язык программирования C++. Лекции и упражнения. 6-е изд (Стивен Прата)

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Поиск

 
     

Случайная книга в электронном формате

https://www.litres.ru/arnold-villemer/programmirovanie-na-s/?lfrom=15589587
Яндекс.Метрика