Как сделать невидимый ввод c
m aroonrk → AtCoder Regular Contest 134 Announcement
_Gaara → Heeeeelp
ghostwriter → How to be quick at solving A and B.
Ashishgup → CodeChef December CookOff 2021 (with new contest timing!)
SmokinGun → Most likely cheating
neplox → Можно ли решить задачу Лямбда оптимизацией?
Monogon → How I Accidentally Became an OI Problemsetter
s lime → On NEAR prizes
antontrygubO_o → CodeChef January Lunchtime 2022
AmanAgr2509 → A small website to pump up your motivation.
300_are_queue → Things I know.
P etr → An incremental week
RNR → Warsaw debug template dissection
Majin_Boo → The feasibility of a local judge program?
SlavicG → Correlation between Math and CP skill
GloryNotAgain-LMB → Why need I start to take bronze again after taking part in the last platinum contest on USACO?
G_Batyrov → Can someone help me find a counterexample?
BERNARB.01 → Range Queries Problems
wtf. → Is there a way to hide my rating?
InternetOlympiads → Первая личная интернет-олимпиада + Первый отбор на ИОИП, Сезон 2021-22
jethaji → ABCs(Atcoder) topic wise ?
Proofy → Characteristics of the optimal solution, a technique for finding observations in a problem
Блог пользователя trionprog
Ввод неизвестного количества данных C++
Автор trionprog, 9 лет назад ,
Комментарии (19)
UPD. Some info
как проверить что ввод закончен?
Спасибо,а то я тут перед новым годом нанервничался )
может сделать фаг по этому,а то ,я думаю, с этим многие проблемы имеют
С файлом всё просто,а тут.
Можешь это место по-подробнее объяснить?
как я понял, топикстартеру с файлами проще потому что там EOF есть
BackendDeveloper имеет в виду, что тут EOF есть в точно таком же виде, как и в файлах.
В консоли это невозможно.
UPD: слишком поздно написал
UPD2: в консоли — имеется ввиду без файлов в codeblocks(или тому подобное) нажав на клавишу F9.
UPD3: Извините за неправильный ответ. Раньше мне всегда твердили что это невозможно. Слова беру назад и большое спасибо Avitella и andreyv. Узнал что-то новое)
В linux консоли есть комбинация клавиш CTRL + D. Так что все возможно :)
Ещё как возможно:
- Ctrl+Z, Enter под Windows
- Ctrl+D под Linux
спасибо, долго искал
Если нужен построчный ввод неизвестного количества данных поможет такое:
While(cin>>n) < // >или While(!cin.eof())< // >
еще же scanf-ом можно
int x; while (scanf("%d", &x) == 1)< //do smth >
Можно использовать итераторы:
В олимпиадах я такого не видел)
Моя не понимать. Вы тут объявили eos , но не инициализировали. Я правильно понимаю, что у него в стандартном конструкторе будет какая-то шняга, которая аналогична "бла-бла-бла" и позволяет понять, когда у нас конец ввода? Но тогда вопрос, в качестве так сказать инициализатора it мы передали cin , а почему без инициализатора будет то, что нам нужно? Объясните, пожалуйста, подробнее, а то лень копаться в референсах/исходниках и чекать у себя на компе, будет ли работать ваш пример.
UPD. Скомипилилось и отработало. Объясните, почему.
Вы понимаете правильно. Работает так потому что его так написали.
A special value for this iterator exists: the end-of-stream; When an iterator is set to this value . has been constructed using its default constructor (without associating it with any basic_istream object).
Чтобы включить отображение пароля в поле password нужно заменить атрибут type="password" на type="text" , сделать это можно на jQuery или чистом JS.
Показать пароль по чекбоксу
Результат:
Показать пароль по ссылке
Результат:
Показать пароль по иконке
Результат:
Без jQuery
Результат:
Комментарии
Другие публикации
Если добавить атрибут contenteditable к элементу, его содержимое становится доступно для редактирования пользователю, а.
По спецификации HTML в option нельзя вставить ссылку, если все-таки её туда вставить, то работать она не будет. В таких случаях можно сделать перенаправление браузера по клику на JS или имитацию.
строка заканчивается нажатием ENTER, поэтому лови "\n", т е:
while ((c = getchar()) != '\n')
Не не не (С) =)
У K&R написан именно EOF. Хочу разобратсья именно с ним.
P.S. Если изменим на '\n' программа сможет работать только со строками. А если нужно вставить текст.
P.P.S. Все равно на выходе вместо количества цифр непонятный массив.
Если ввести Ctrl-Z, то на нем и возвращается EOF.
То есть нормальные строки заканчиваются Enter. После каждой строки будет '\n'.
Под конец можно ввести какие-то символы, нажать Ctrl-Z и нажать Enter. Введутся набранные символы и после них EOF
FasterHarder, 10 это и есть '\n'. 13 - это '\r'. Символы в конце строки ты перепутал местами, хотя при выводе на принтер или экран в двоичном режиме результат выглядит одинаково.
Вот код 13 (вводится Ctrl+Enter) ловить не следует. При вводе в текстовом режиме пара '\r'/'\n' заменяется на один '\n'.
Вообще не рекомендуется пользоваться числовым значением. Есть кодировки, в которых перевод строки кодируется по-другому.
Под конец можно ввести какие-то символы, нажать Ctrl-Z и нажать Enter. Введутся набранные символы и после них EOF
amk, спасибо, понятно..
а еще по сабжу: EOF, это ведь вроде макрос, который по сути является там чем то. (-1 или Ctrl + Z или еще чего то).
Вот тот же ответ в Usenet.
> 12.1b: I have a simple little program that reads characters until EOF,
> but how do I actually *enter* that "EOF" value from the
> keyboard?
> A: It turns out that the value of EOF as seen within your C program
> has essentially nothing to do with the keystroke combination you
> might use to signal end-of-file from the keyboard. Depending on
> your operating system, you indicate end-of-file from the
> keyboard using various keystroke combinations, usually either
> control-D or control-Z.
Как то все очень абстрактно. Не могу понять связи.
Мда. Можно было бы пост свой подредактировать и высказываться менее категорично IMHO.
По теме: по Ctrl+Z она выходит, да, но для того, чтобы это произошло, нужно вставить Ctrl+Z на пустой строчке, т.е. если набрать что-то типа этого: "dhjjhet^Z" и нажать "Ввод", прога не поймет этого самого EOF, а курсор перейдет на следующую строчку. А нужно чтобы реакция была, как на прерывание, я так полагаю.
P.S. 2KILLER: у тебя код на С++. Я в нем, к сожалению, ничегошеньки не понимаю. =(
WBR
может потому что используешь буферизированную функцию getchar() (она без эхо печати еще). пока Enter не нажмешь, считывание из буфера не происходит..хотя не уверен что проблема именно в буферизации..
погоди, погоди , я исправил пост выше..
// printf("%d ", ch); если снять комменты, то на экране можно будет видеть КОДЫ нажатых клавиш. Удобно.
и в отладчике посмотрел, оказалось, нажатие Ctrl + Z вводит код 26 (непечатаемый символ)..если EOF равен -1, то понятно, что данная программа никогда не завершиться.
Большинство программ, имеющих какой-либо пользовательский интерфейс, должны обрабатывать вводимые пользователем данные. В программах, которые мы писали, мы использовали std::cin , чтобы попросить пользователя ввести текст. Поскольку ввод текста имеет произвольную форму (пользователь может вводить что угодно), пользователю очень легко ввести данные, которые не ожидаются.
При написании программ вы всегда должны учитывать, как пользователи (непреднамеренно или наоборот) будут использовать ваши программы некорректно. Хорошо написанная программа будет предвидеть, как пользователи будут использовать ее неправильно, и либо аккуратно обработает эти случаи, либо вообще предотвратит их появление (если это возможно). Программа, которая хорошо обрабатывает случаи ошибок, называется надежной.
В этом уроке мы подробно рассмотрим способы, которыми пользователь может вводить недопустимые текстовые данные через std::cin , и покажем вам несколько разных способов обработки таких случаев.
std::cin , буферы и извлечение
Чтобы обсудить, как std::cin и operator>> могут давать сбой, сначала полезно немного узнать, как они работают.
Когда пользователь вводит данные в ответ на операцию извлечения, эти данные помещаются в буфер внутри std::cin . Буфер (также называемый буфером данных) – это просто часть памяти, отведенная для временного хранения данных, пока они перемещаются из одного места в другое. В этом случае буфер используется для хранения пользовательских входных данных, пока они ожидают извлечения в переменные.
При использовании оператора извлечения происходит следующая процедура:
- Если во входном буфере уже есть данные, то для извлечения используются они.
- Если входной буфер не содержит данных, пользователя просят ввести данные для извлечения (так бывает в большинстве случаев). Когда пользователь нажимает Enter , во входной буфер помещается символ '\n' .
- operator>> извлекает столько данных из входного буфера, сколько может, в переменную (игнорируя любые начальные пробельные символы, такие как пробелы, табуляции или '\n' ).
- Любые данные, которые не могут быть извлечены, остаются во входном буфере для следующего извлечения.
Извлечение завершается успешно, если из входного буфера извлечен хотя бы один символ. Любые неизвлеченные входные данные остаются во входном буфере для дальнейшего извлечения. Например:
Если пользователь вводит "5a" , 5 будет извлечено, преобразовано в целое число и присвоено переменной x . А "a\n" останется во входном потоке для следующего извлечения.
Извлечение не выполняется, если входные данные не соответствуют типу переменной, в которую они извлекаются. Например:
Если бы пользователь ввел 'b' , извлечение не удалось бы, потому что 'b' не может быть извлечено в переменную типа int .
Проверка ввода
Процесс проверки того, соответствуют ли пользовательские входные данные тому, что ожидает программа, называется проверкой ввода.
Есть три основных способа проверки ввода:
- встроенный (по мере печати пользователя):
- прежде всего, не позволить пользователю вводить недопустимые данные;
- позволить пользователю ввести в строку всё, что он хочет, затем проверить правильность строки и, если она корректна, преобразовать строку в окончательный формат переменной;
- позволить пользователю вводить всё, что он хочет, позволить std::cin и operator>> попытаться извлечь данные и обработать случаи ошибок.
Некоторые графические пользовательские интерфейсы и расширенные текстовые интерфейсы позволяют проверять входные данные, когда пользователь их вводит (символ за символом). В общем случае, программист предоставляет функцию проверки, которая принимает входные данные, введенные пользователем, и возвращает true , если входные данные корректны, и false в противном случае. Эта функция вызывается каждый раз, когда пользователь нажимает клавишу. Если функция проверки возвращает истину, клавиша, которую только что нажал пользователь, принимается. Если функция проверки возвращает false , введенный пользователем символ отбрасывается (и не отображается на экране). Используя этот метод, вы можете гарантировать, что любые входные данные, вводимые пользователем, гарантированно будут корректными, потому что любые недопустимые нажатия клавиш обнаруживаются и немедленно отбрасываются. Но, к сожалению, std::cin не поддерживает этот стиль проверки.
Поскольку строки не имеют никаких ограничений на ввод символов, извлечение гарантированно завершится успешно (хотя помните, что std::cin прекращает извлечение на первом неведущем пробельном символе). После того, как строка введена, программа может проанализировать эту строку, чтобы узнать, корректна она или нет. Однако анализ строк и преобразование вводимых строк в другие типы (например, числа) может быть сложной задачей, поэтому это делается только в редких случаях.
Пример программы
Рассмотрим следующую программу-калькулятор, в которой нет обработки ошибок:
Эта простая программа просит пользователя ввести два числа и математический оператор.
Теперь подумайте, где неверный ввод пользователя может нарушить работу этой программы.
Сначала мы просим пользователя ввести несколько чисел. Что, если он введет что-то, отличающееся от числа (например, 'q' )? В этом случае извлечение не удастся.
Во-вторых, мы просим пользователя ввести один из четырех возможных символов. Что, если он введет символ, отличный от ожидаемых? Мы сможем извлечь входные данные, но пока не обрабатываем то, что происходит после.
В-третьих, что, если мы попросим пользователя ввести символ, а он введет строку типа "*q hello" . Хотя мы можем извлечь нужный нам символ '*' , в буфере останутся дополнительные входные данные, которые могут вызвать проблемы в будущем.
Типы недопустимых входных текстовых данных
Обычно мы можем разделить ошибки ввода текста на четыре типа:
- извлечение входных данных выполняется успешно, но входные данные не имеют смысла для программы (например, ввод 'k' в качестве математического оператора);
- извлечение входных данных выполняется успешно, но пользователь вводит дополнительные данные (например, вводя "*q hello" в качестве математического оператора);
- ошибка извлечения входных данных (например, попытка ввести 'q' при запросе ввода числа);
- извлечение входных данных выполнено успешно, но пользователь выходит за пределы значения числа.
Таким образом, чтобы сделать наши программы устойчивыми, всякий раз, когда мы запрашиваем у пользователя ввод, мы в идеале должны определить, может ли произойти каждый из вышеперечисленных возможных вариантов, и если да, написать код для обработки этих случаев.
Давайте разберемся в каждом из этих случаев и в том, как их обрабатывать с помощью std::cin .
Случай ошибки 1: извлечение успешно, но входные данные не имеют смысла
Это самый простой случай. Рассмотрим следующий вариант выполнения приведенной выше программы:
В этом случае мы попросили пользователя ввести один из четырех символов, но вместо этого он ввел 'k' . 'k' – допустимый символ, поэтому std::cin успешно извлекает его в переменную op , и она возвращается в main . Но наша программа не ожидала этого, поэтому она не обрабатывает этот случай правильно (и, таким образом, ничего не выводит).
Решение здесь простое: выполните проверку ввода. Обычно она состоит из 3 шагов:
- убедитесь, что пользовательский ввод соответствует вашим ожиданиям;
- если да, верните значение вызывающей функции;
- если нет, сообщите пользователю, что что-то пошло не так, и попросите его повторить попытку.
Вот обновленная функция getOperator() , которая выполняет проверку ввода.
Как видите, мы используем цикл while для бесконечного цикла до тех пор, пока пользователь не предоставит допустимые данные. Если он этого не делает, мы просим его повторить попытку, пока он не даст нам правильные данные, не закроет программу или не уничтожит свой компьютер.
Случай ошибки 2: извлечение успешно, но с посторонними входными данными
Рассмотрим следующий вариант выполнения приведенной выше программы:
Как думаете, что будет дальше?
Программа выводит правильный ответ, но форматирование испорчено. Давайте подробнее разберемся, почему.
Когда пользователь вводит "5*7" в качестве вводных данных, эти данные попадают в буфер. Затем оператор >> извлекает 5 в переменную x , оставляя в буфере "*7\n" . Затем программа напечатает "Enter one of the following: +, -, *, or /:" . Однако когда был вызван оператор извлечения, он видит символы "*7\n" , ожидающие извлечения в буфере, поэтому он использует их вместо того, чтобы запрашивать у пользователя дополнительные данные. Следовательно, он извлекает символ '*' , оставляя в буфере "7\n" .
После запроса пользователя ввести другое значение double , из буфера извлекается 7 без ожидания ввода пользователя. Поскольку у пользователя не было возможности ввести дополнительные данные и нажать Enter (добавляя символ новой строки), все запросы в выводе идут вместе в одной строке, даже если вывод правильный.
Хотя программа работает, выполнение запутано. Было бы лучше, если бы любые введенные посторонние символы просто игнорировались. К счастью, символы игнорировать легко:
Этот вызов удалит до 100 символов, но если пользователь ввел более 100 символов, мы снова получим беспорядочный вывод. Чтобы игнорировать все символы до следующего символа '\n' , мы можем передать std::numeric_limits ::max() в std::cin.ignore() . std::numeric_limits ::max() возвращает наибольшее значение, которое может быть сохранено в переменной типа std::streamsize . Передача этого значения в std::cin.ignore() приводит к отключению проверки счетчика.
Чтобы игнорировать всё, вплоть до следующего символа '\n' , мы вызываем
Поскольку эта строка довольно длинная для того, что она делает, будет удобнее обернуть ее в функцию, которую можно вызвать вместо std::cin.ignore() .
Поскольку последний введенный пользователем символ должен быть '\n' , мы можем указать std::cin игнорировать символы в буфере, пока не найдет символ новой строки (который также будет удален).
Давайте обновим нашу функцию getDouble() , чтобы игнорировать любой посторонний ввод:
Теперь наша программа будет работать, как ожидалось, даже если мы введем "5*7" при первом запросе ввода – 5 будет извлечено, а остальные символы из входного буфера будут удалены. Поскольку входной буфер теперь пуст, при следующем выполнении операции извлечения данные у пользователя будут запрашиваться правильно!
Случай ошибки 3: сбой при извлечении
Теперь рассмотрим следующий вариант выполнения нашей программы калькулятора:
Неудивительно, что программа работает не так, как ожидалось, но интересно, как она дает сбой:
и программа внезапно завершается.
Это очень похоже на случай ввода посторонних символов, но немного отличается. Давайте посмотрим подробнее.
Давайте, интегрируем это в нашу функцию getDouble() :
Примечание. До C++11 неудачное извлечение не приводило к изменению извлекаемой переменной. Это означает, что если переменная была неинициализирована, она останется неинициализированной в случае неудачного извлечения. Однако, начиная с C++11, неудачное извлечение из-за недопустимого ввода приведет к тому, что переменная будет инициализирована нулем. Инициализация нулем означает, что для переменной установлено значение 0, 0.0, "" или любое другое значение, в которое 0 преобразуется для этого типа.
Случай ошибки 4: извлечение успешно, но пользователь выходит за пределы значения числа
Рассмотрим следующий простой пример:
Что произойдет, если пользователь введет слишком большое число (например, 40000)?
Примечание. До C++11 неудачное извлечение не приводило к изменению извлекаемой переменной. Это означает, что если переменная была неинициализирована, в случае неудачного извлечения она останется неинициализированной. Однако, начиная с C++11, неудачное извлечение вне диапазона приведет к тому, что переменной будет присвоено ближайшее значение в диапазоне.
Собираем всё вместе
Вот наш пример калькулятора с полной проверкой ошибок:
Заключение
При написании программы подумайте о том, как пользователи будут неправильно использовать вашу программу, особенно при вводе текста. Для каждой точки ввода текста учтите:
- Могло ли извлечение закончиться неудачей?
- Может ли пользователь ввести больше, чем ожидалось?
- Может ли пользователь ввести бессмысленные входные данные?
- Может ли пользователь переполнить входные данные?
Вы можете использовать операторы if и булеву логику, чтобы проверить, являются ли входные данные ожидаемыми и осмысленными.
Следующий код очистит любые посторонние входные данные:
Следующий код будет проверять и исправлять неудачные извлечения или переполнение:
Наконец, используйте циклы, чтобы попросить пользователя повторно ввести данные, если исходные входные данные были недопустимыми.
Примечание автора
Проверка ввода важна и полезна, но она также делает примеры более сложными и трудными для понимания. Соответственно, на будущих уроках мы, как правило, не будем проводить никакой проверки вводимых данных, если они не имеют отношения к чему-то, чему мы пытаемся научить.
Поточный ввод-вывод в C++ выполняется с помощью функций сторонних библиотек. В С++, как и в С, нет встроенных в язык средств ввода-вывода.
В С для этих целей используется библиотека stdio.h .
В С++ разработана новая библиотека ввода-вывода iostream , использующая концепцию объектно-ориентированного программирования:Библиотека iostream определяет три стандартных потока:
Для их использования в Microsoft Visual Studio необходимо прописать строку:
Для выполнения операций ввода-вывода переопределены две операции поразрядного сдвига:
Возможно многократное назначение потоков:
coutint n;
char j;
cin >> n >> j;
cout "Значение n равно" n "j prog">cin >> идентификатор;При этом из входного потока читается последовательность символов до пробела, затем эта последовательность преобразуется к типу идентификатора, и получаемое значение помещается в идентификатор:
Возможно многократное назначение потоков:
cin >> переменная1 >> переменная2 >>. >> переменнаяn;При наборе данных на клавиатуре значения для такого оператора должны быть разделены символами (пробел, \n, \t ).
Особого внимания заслуживает ввод символьных строк. По умолчанию потоковый ввод cin вводит строку до пробела, символа табуляции или перевода строки.
Для ввода текста до символа перевода строки используется манипулятор потока getline() :
Манипуляторы потока
Функцию - манипулятор потока можно включать в операции помещения в поток и извлечения из потока ( >).
В С++ имеется ряд манипуляторов. Рассмотрим основные:
Пример Программа ввода-вывода значения переменной в C++
Та же программа, написанная на языке Си
Пример Использование форматированного вывода
Еще один пример использования форматированного вывода: для t∈[0;3] с шагом 0,5 вычислить значение y=cos(t).
Читайте также: