Интерактивный ввод символов

Объект cin позволяет получить символ только после нажатия клавиши <Enter>. Если необходимо получить символ сразу после нажатия клавиши на клавиатуре, то можно воспользоваться функциями _getche() и _getch(). Прототипы функций:

#include <conio.h>
int _getche(void);
int _getch(void);

Функция _getche() возвращает код символа и выводит его на экран. При нажатии клавиши на клавиатуре функция _getch() возвращает код символа, но сам символ на экран не выводится. Это обстоятельство позволяет использовать функцию _getch() для получения конфиденциальных данных (например, пароля). Следует учитывать, что код символа возвращается и при нажатии некоторых служебных клавиш, например, <Home>, <End> и др.

В качестве примера использования функции _getch() создадим программу для ввода пароля (листинг 2.10). Пароль может содержать до 16 символов (цифры от 0 до 9 и латинские буквы от a до z в любом регистре). При нажатии клавиши вместо символа будем выводить звездочку. Если символ не входит в допустимый набор, выведем сообщение об ошибке и завершим программу. После нажатия клавиши <Enter> выведем на экран полученный пароль.

Листинг 2.10. Ввод пароля без отображения вводимых символов

#include <iostream>
#include <conio.h>
#include <clocale>

int main() {
   std::setlocale(LC_ALL, "Russian_Russia.1251");
   char passwd[17] = "";
   bool flag = false;
   int i = 0, ch = 0;
   std::cout << "Введите пароль: ";
   std::cout.flush();
   do {
      ch = _getch();
      if (i > 15 || ch == '\r' || ch == '\n') {
         flag = true;
         passwd[i] = '\0';
      }
      else if (   (ch > 47 && ch < 58)   // Цифры от 0 до 9
               || (ch > 64 && ch < 91)   // Буквы от A до Z
               || (ch > 96 && ch < 123)) // Буквы от a до z
      {
         passwd[i] = static_cast<char>(ch);
         std::cout << '*';
         std::cout.flush();
         ++i;
      }
      else { // Если недопустимый символ, то выходим
         std::cout << std::endl << "Вы ввели недопустимый символ"
                   << std::endl;
         return 1;
      }
   } while (!flag);

   std::cout << std::endl << "Вы ввели: " << passwd << std::endl;
   return 0;
}
Обратите внимание

В начале программы производим подключение файлов iostream, conio.h и clocale. Файл iostream необходим для использования объекта cout, файл conio.h — для функции _getch(), а файл clocale — для функции setlocale(), предназначенной для настройки локали. Объект cout и функция setlocale() находятся внутри пространства имен std, в то время как функция _getch() находится в глобальном пространстве имен, поэтому перед функцией _getch() имя пространства не указывается. Далее внутри функции main() объявляем четыре переменные. В символьный массив passwd, содержащий 17 элементов (16 символов плюс '\0'), будут записываться введенные символы. В переменную ch будем записывать код нажатой клавиши. Логическая переменная flag предназначена для хранения статуса ввода (если содержит значение true, то ввод пароля закончен), а целочисленная переменная i предназначена для хранения текущего индекса внутри массива passwd. Обратите внимание на то, что первый элемент массива имеет индекс 0, а не 1.

После объявления переменных выводим подсказку пользователю с помощью объекта cout и сбрасываем буфер. Затем внутри цикла do...while получаем текущий символ с помощью функции _getch() и сохраняем его код в переменной ch. В следующей строке проверяем выход индекса за границы массива (i > 15) и нажатие клавиши <Enter>. При нажатии клавиши <Enter> передается последовательность символов \r\n (перевод каретки плюс перевод строки), однако функция _getch() может получить только один символ, поэтому проверяется наличие или символа \r или символа \n. Между собой логические выражения разделяются с помощью оператора || (логическое ИЛИ). Чтобы все выражение вернуло истину достаточно, чтобы хотя бы одно из трех логических выражений было истинным. Если выражение i > 15 является ложным, то проверяется выражение ch == '\r', в противном случае все выражение считается истинным и дальнейшая проверка не осуществляется. Если выражение ch == '\r' является ложным, то проверяется выражение ch == '\n', в противном случае все выражение считается истинным и дальнейшая проверка не осуществляется. Если выражение ch == '\n' является ложным, то все выражение считается ложным, в противном случае все выражение считается истинным.

Если выражение является истинным, то ввод пароля закончен. Чтобы выйти из цикла присваиваем переменной flag значение true. Кроме того, вставляем нулевой символ в конец массива. Он будет обозначать конец строки с введенным паролем. После этих инструкций управление передается в конец цикла и производится проверка условия !flag. Так как условие вернет false (!true) происходит выход из цикла. После выхода из цикла производим вывод введенного пароля на консоль.

Если ввод пароля не закончен, то производим проверку вхождения символа в допустимый диапазон значений (цифры от 0 до 9 и латинские буквы от a до z в любом регистре). Выполнить проверку допустимости символа необходимо, так как функция _getch() возвращает также коды некоторых служебных клавиш, например, <Home>, <End> и др. Если условие не соблюдается, то выводим сообщение об ошибке и возвращаем значение 1, тем самым завершая выполнение программы.

Проверяемое условие содержит более сложное выражение, нежели в предыдущем условии. Выражение разбито на несколько мелких выражений с помощью круглых скобок. Внутри первых круглых скобок проверяется соответствие символа диапазону чисел от 0 до 9. Цифра 0 соответствует коду 48, а цифра 9 — коду 57. Коды остальных цифр находятся в диапазоне между этими кодами. Чтобы не перечислять в выражении коды всех цифр используется проверка двух условий, разделенных оператором && (логическое И). Выражение (ch > 47 && ch < 58) следует читать так: если переменная ch содержит символ, имеющий код больше 47 и меньше 58, то вернуть значение true, в противном случае — значение false. Если условие внутри первых скобок является истинным, то все выражение является истинным и дальнейшая проверка не производится. Если условие внутри первых круглых скобок является ложным, то проверяется условие внутри вторых круглых скобок. Условие внутри третьих круглых скобок проверяется только если условие внутри вторых круглых скобок является ложным. Вместо кодов символов можно указать сами символы внутри апострофов. В этом случае условие будет выглядеть так:

else if (   (ch >= '0' && ch <= '9')   // Цифры от 0 до 9
         || (ch >= 'A' && ch <= 'Z')   // Буквы от A до Z
         || (ch >= 'a' && ch <= 'z'))  // Буквы от a до z
{

Если символ входит в допустимый диапазон, то сохраняем символ в массиве, выводим звездочку в окно консоли, сбрасываем буфер, а затем увеличиваем значение в переменной i на единицу, тем самым перемещая указатель текущей позиции на следующий элемент массива. Выражение ++i соответствует выражению i = i + 1. После этих инструкций управление передается в конец цикла и производится проверка условия !flag. Так как условие вернет true (!false) инструкции внутри цикла будут выполнены еще раз.

Учебник C++ (MinGW-W64)
Учебник C++ (MinGW-W64) в формате PDF

Помощь сайту

ЮMoney (Yandex-деньги): 410011140483022

ПАО Сбербанк:
Счет: 40817810855006152256
Реквизиты банка:
Наименование: СЕВЕРО-ЗАПАДНЫЙ БАНК ПАО СБЕРБАНК
Корреспондентский счет: 30101810500000000653
БИК: 044030653
КПП: 784243001
ОКПО: 09171401
ОКОНХ: 96130
Скриншот реквизитов