Обробка некоректного вводу інформації
Якщо ви розробляєте програму, якою плануєте то варто усвідомлювати, що користувачі можуть бути різними. Вони можуть навіть не читати інструкцію як правильно користуватися вашою програмою, можуть помилитися і зробити різноманітні дії, які призведуть до того, що ваша програма буде працювати не очікувано або взагалі повідомить про помилку та завершить свою роботу.
Є чимало способів вашу програму та змусити її не правильно працювати. Найчастіше це проблема введення не коректної інформації. Ми розглянемо лише базові помилки, які можуть статися та запропонуємо деякі варіанти їх вирішення.
Такий захист називають І він предназначенний на той випадок, коли людина є не уважною, а не спеціально намагається викликати помилки у вашій програмі.
Але з початку розберімося навіщо цим взагалі запарюватися? Все просто, поки ви самі користуєтеся програмою, то чітко знаєте чого вона від вас хоче і яку інформацію потрібно ввести, щоб все працювало. Но, якщо ви випустите її у світ (тим більше за гроші), то користувачі можуть не розібравшись в ній сказати не працює, тому я напишу про неї поганий Після десятків таких відгуків готуйтесь, що ваші зусилля підуть котику під хвіст.
Обмеження правильного вводу
Буває ситуація, що є не велика кількість інформації з якої користувач має ввести щось. Наприклад, користувач має вказати один з варіантів відповіді на тести або вказати результат/оцінку тесту То, ви можете змушувати користувача вводити інформацію поки він не введе результат який вас влаштовує.
Для цього використовують цикли або які будуть працювати до моменту поки користувач не введе очікуваний результат. При чому використовувати на багато зручніше, оскільки він спрацьовує як мінімум один раз.
Розглянемо це на практиці. Припустимо користувач робить ставку на перегони в яких беруть участь скакунів. Відповідно, він має ввести номер свого фаворита.
Відразу зауважимо, що введене число має бути від до включно з цими числами. Тоді, найпростіший вигляд програми буде таким:
//do - while
#include <iostream>
int main()
{
int a;
do {
std::cout << "input number 1-8: ";
std::cin >> a;
} while (a < 1 || a>8);
std::cout << "\nnumber = " << a;
return 0;
}
//while
#include <iostream>
int main()
{
int a;
std::cout << "input number 1-8: ";
std::cin >> a;
while (a < 1 || a>8) {
std::cout << "input number 1-8: ";
std::cin >> a;
}
std::cout << "\nnumber = " << a;
return 0;
}
А, приклад її роботи буде таким:
input number 1-8: 9
input number 1-8: 11
input number 1-8: -1
input number 1-8: 4
number = 4
Звісно ж цей метод буде працювати лише при деяких умовах. Якщо, ви введете дробове число, то результат може бути різним. Погляньте на наступний приклад:
input number 1-8: 3.9
number = 3
Як бачите, програма запрацювала відкинувши дробове значення числа. При цьому, дробова частина залишилася в буфері введення і використається при наступному використанні Но, якщо ви введете або інший символ, то побачите «поламання» програми. Тому, потрібно покращувати наш
Наступне, що ми можемо зробити це після отримання інформації очистити поле вводу від зайвих символів.
Команда:
std::cin.ignore(32767, '\n');
Інформує програму, що потрібно очистити символів поки не зустрінеться кінець рядка Звісно ж ви можете використовувати іншу кількість символів для очищення. Але, мабуть, у вас питання що ж буде, якщо символів на багато Відповідь
Тому, краще за все використовувати такий рядок:
std::cin.ignore(std::numeric_limits <std::streamsize>::max(), '\n');
Лише пам’ятайте, що при використанні вам не потрібно кожного разу вказувати
Давайте змінимо програму. Спробуйте раз запустити програму з рядком ігнорування і раз без нього.
#include <iostream>
int main()
{
int a;
do{
std::cout << "input number 1-8: ";
std::cin >> a;
std::cin.ignore(std::numeric_limits <std::streamsize>::max(), '\n');
} while (a < 1 || a > 8);
int b;
do {
std::cout << "input next number 1-8: ";
std::cin >> b;
std::cin.ignore(std::numeric_limits <std::streamsize>::max(), '\n');
} while (b < 1 || b > 8);
std::cout << "\nnumber 'a' = " << a;
std::cout << "\nnumber 'b' = " << b;
return 0;
}
Приклад роботи з рядком ігнорування:
input number 1-8: 3.9
input next number 1-8: 11
input next number 1-8: 5
number 'a' = 3
number 'b' = 5
Як бачите, після введення програма забрала цілу частину та присвоїла її змінній (лише цілу частину, бо змінна є цілого а дробова частина залишилася в буфері. Командою ігнорування ми очищаємо наш буфер.
Що ж. Ми вже зробили нашу програму трішки розумнішою. Але, якщо ви введете якийсь символ (букву чи щось інше, головне, щоб не то наша програма зламається. Це відбувається через те, що програма не змогла значення з буфера введення. Відповідно, буфер видає помилку.
Для перевірки чи витягнення відбулося правильним використовують команду:
std::cin.fail();
Вона повертає якщо витягнення відбулося правильно і якщо витягнення не відбулося. Тому, цю команду потрібно використовувати разом з Перевірка відбувається відносно останнього який використовувався.
При цьому, щоб повернути буфер до нормального стану варто скористатися командою:
std::cin.clear();
Використання даних методів в нашій програмі виглядатиме так:
#include <iostream>
int main()
{
int a;
do{
std::cout << "input number 1-8: ";
std::cin >> a;
if (std::cin.fail())
{
std::cin.clear();
std::cin.ignore(std::numeric_limits <std::streamsize>::max(), '\n');
}
} while (a < 1 || a > 8);
int b;
do {
std::cout << "input next number 1-8: ";
std::cin >> b;
if (std::cin.fail())
{
std::cin.clear();
std::cin.ignore(std::numeric_limits <std::streamsize>::max(), '\n');
}
} while (b < 1 || b > 8);
std::cout << "\nnumber 'a' = " << a;
std::cout << "\nnumber 'b' = " << b;
return 0;
}
Приклад роботи програми:
input number 1-8: f
input number 1-8: -
input number 1-8: 4
input next number 1-8: g
input next number 1-8: a
input next number 1-8: +
input next number 1-8: 7
number 'a' = 4
number 'b' = 7
Звісно ж це лише базові приклади обробки не коректного вводу інформації, але вони допоможуть вам зробити свої програми безпечнішими під час використання.