Привіт! Наше сьогоднішнє заняття буде особливим!
До цього під час розв'язання задач і написання програм алгоритм був простим: ми пишемо якийсь код, запускаємо метод main(), програма робить те, що від неї вимагається, і завершує свою роботу.
Але тепер усе зміниться! Сьогодні ми навчимося по-справжньому взаємодіяти з програмою: ми навчимо її реагувати на наші дії!
Можливо, ти вже зрозумів, до чого ми хилимо. Цю лекцію присвятимо детальному розбору одного з класів мови Java – Scanner. Цей клас стане в пригоді, якщо тобі потрібно буде зчитувати дані, які вводять юзери.
Перед тим, як ми перейдемо до вивчення коду, скажи, тобі колись доводилося зустрічатися з таким пристроєм як сканер?
Напевно так. Зсередини будова сканера досить складна, але суть його роботи доволі проста: він зчитує ті дані, які користувач у нього вводить (наприклад, паспорт або страховий поліс) і зберігає зчитану інформацію в пам'яті (наприклад, у вигляді зображення).
Так от, сьогодні ти створиш свій власний сканер! З документами він, звісно, не впорається, а ось із текстовою інформацією – цілком :) Поїхали!
Java Scanner Class
Перше і головне, з чим нам потрібно познайомитися, – клас java.util.Scanner. Його функціональність дуже проста. Він, немов справжній сканер, зчитує дані з джерела, яке ти для нього вкажеш. Наприклад, із рядка, з файлу, з консолі. Далі він розпізнає цю інформацію й обробляє потрібним чином. Наведемо найпростіший приклад:
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner("Тече вода в синє море,\n" +
"Та не витікає,\n" +
"Шука козак свою долю,\n" +
"А долі немає.");
String s = scanner.nextLine();
System.out.println(s);
}
}
Ми створили об'єкт сканера і вказали для нього джерело даних (рядок із текстом). Метод nextLine() звертається до джерела даних (нашого тексту з чотиривіршем), знаходить там наступний рядок, який він ще не зчитував (у нашому випадку – перший) і повертає його. Після чого ми виводимо його в консоль: Виведення в консоль:
Тече вода в синє море,
Ми можемо використовувати метод nextLine() кілька разів і вивести весь шматок поеми:
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner("Тече вода в синє море,\n" +
"Та не витікає,\n" +
"Шука козак свою долю,\n" +
"А долі немає.");
String s = scanner.nextLine();
System.out.println(s);
s = scanner.nextLine();
System.out.println(s);
s = scanner.nextLine();
System.out.println(s);
s = scanner.nextLine();
System.out.println(s);
}
}
Щоразу наш сканер робитиме один крок уперед і зчитуватиме наступний рядок. Результат роботи програми – виведення в консоль:
Тече вода в синє море,
Та не витікає,
Шука козак свою долю,
А долі немає.
Як ми вже казали, джерелом даних для сканера може бути не тільки рядок, а й, наприклад, консоль.
Важлива новина для нас: якщо раніше ми тільки виводили туди дані, тепер будемо вводити дані з клавіатури!
Подивимося, що ще вміє клас Scanner:
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Введіть число:");
int number = sc.nextInt();
System.out.println("Дякую! Ви ввели число " + number);
}
}
Метод nextInt() зчитує і повертає введене число. У нашій програмі він використовується для того, щоб присвоїти значення змінній number.
Це вже більше схоже на справжній сканер! Програма просить користувача ввести в рядок будь-яке число. Після того, як користувач це зробив, програма дякує йому, виводить в консоль результат своєї роботи і завершується.
Але у нас залишилася одна серйозна проблема. Користувач може помилитися і ввести щось не те.
Ось приклад, коли наша поточна програма перестане працювати:
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Введіть число:");
int number = sc.nextInt();
System.out.println("Дякую! Ви ввели число " + number);
}
}
Спробуємо ввести замість числа рядок "JavaRush". Виведення в консоль:
Введіть число:
JavaRush
Exception in thread "main" java.util.InputMismatchException
at java.util.Scanner.throwFor(Scanner.java:864)
at java.util.Scanner.next(Scanner.java:1485)
at java.util.Scanner.nextInt(Scanner.java:2117)
at java.util.Scanner.nextInt(Scanner.java:2076)
at Main.main(Main.java:8)
Process finished with exit code 1
Ой-ой, усе погано -_-
Щоб уникнути схожих ситуацій, нам потрібно придумати спосіб перевірки даних, які вводить користувач. Наприклад, користувач вводить що завгодно, крім числа, – добре б вивести в консоль попередження, що введена інформація не є числом, а якщо все гаразд – вивести текст підтвердження.
Але для цього нам треба фактично "зазирнути в майбутнє" – дізнатися, що там далі в нашому потоці. Чи вміє Scanner у Java це робити?
Ще як уміє! І для цього в нього є ціла група методів: hasNextInt() – метод перевіряє, чи є наступна порція введених даних числом або ні (повертає, відповідно, true або false).
hasNextLine() – перевіряє, чи є наступна порція даних рядком.
hasNextByte(), hasNextShort(), hasNextLong(), hasNextFloat(), hasNextDouble() – усі ці методи роблять те саме для інших типів даних.
Спробуємо змінити нашу програму для читання числа:
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Введіть число:");
if (sc.hasNextInt()) {
int number = sc.nextInt();
System.out.println("Дякую! Ви ввели число " + number);
} else {
System.out.println("Вибачте, але це явно не число. Перезапустіть програму і спробуйте знову!");
}
}
}
Тепер наша програма перевіряє, чи є наступний введений символ числом або ні. І тільки в разі, якщо є, виводить підтвердження. Якщо ж введення не пройшло перевірку, програма це помічає і просить спробувати знову.
По суті, ти можеш спілкуватися з об'єктом Scanner і заздалегідь дізнаватися, який тип даних тобі очікувати. "Гей, сканер, що там далі буде? Число, рядок, чи ще що? Число? А яке – int, short, long?"
Така гнучкість дає тобі можливість вибудовувати логіку своєї програми залежно від поведінки користувача.
Ще один важливий метод, на який варто звернути увагу – useDelimiter().
У цей метод передається рядок, який ви хочете використовувати як роздільник.
Наприклад, ми несподівано захопилися японською поезією і вирішили зчитати за допомогою сканера кілька хокку великого поета Мацуо Басьо.
Навіть якщо три різні вірші передані нам одним кострубатим рядком, ми легко можемо їх розділити і красиво відформатувати:
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner("На голій гілці'" +
"Ворон сидить самотньо.'" +
"Осінній вечір." +
"''***''" +
"У небі такий місяць,'" +
"Немов дерево спиляно під корінь:'" +
"Біліє свіжий зріз." +
"''***''" +
"Як розлилася річка!'" +
"Чапля бреде на коротких ніжках,'" +
"По коліно у воді.");
scan.useDelimiter("'");
while (scan.hasNext()) {
System.out.println(scan.next());
}
scan.close();
}
}
Ми використовуємо як роздільник рядків метод useDelimeter() класу Scanner: він відповідає за поділ вхідних даних на частини. У нашому випадку для поділу рядків як аргумент передається і використовується одинарна лапка ("'"). Наступний за цією лапкою текст відображається в новому рядку, оскільки в циклі while ми використовуємо метод println() класу System для зчитування даних.
Як наслідок, в консолі у нас з'явиться гарне виведення, зовсім як у книжках:
На голій гілці
Ворон сидить самотньо.
Осінній вечір.
***
У небі такий місяць,
Немов дерево спиляно під корінь:
Біліє свіжий зріз.
***
Як розлилася річка!
Чапля бреде на коротких ніжках,
По коліно у воді.
У цьому ж прикладі є ще один метод, на який потрібно обов'язково звернути увагу – close(). Як і будь-який об'єкт, що працює з потоками введення-виведення, сканер потрібно закрити після завершення своєї роботи, щоб більше не споживати ресурси нашого комп'ютера.
Ніколи не забувай про метод close()!
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Введіть число:");
int number = sc.nextInt();
System.out.println("Дякую! Ви ввели число " + number);
sc.close();// ось тепер ми зробили все правильно!
}
}
Ось і все! Як бачиш, клас Scanner досить простий у використанні та дуже корисний! :)
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ