W tym artykule dowiesz się, jak w języku Java wprowadzać dane do programu z klawiatury, przy pomocy klasy Scanner. Dzięki temu stworzysz programy, wykonujące tę samą operację dla różnych danych wejściowych.
Do czego służy klasa Scanner.java?
„Klasa Scanner odczytuje sformatowane dane wejściowe i konwertuje je do postaci binarnej. Klasa może być używana do odczytywania danych wejściowych z konsoli, pliku, łańcuchów […]. Przykładowo możemy wykorzystać tę klasę do odczytywania liczb z klawiatury i przypisywania jej do odpowiedniej zmiennej”
H. Schildt, Java Kompendium Programisty
A więc, przy pomocy klasy Scanner możemy odczytać dane z konsoli/pliku i zapisać je do zmiennej w celu dalszego wykorzystania.
Przygotowanie Java Scanner(a)
Na samym początku należy zadeklarować zmienną klasy Scanner, przekazując jej informację „skąd będziemy czytać”. A więc już na samym początku wskazujemy, że chodzi nam o czytanie z konsoli (klawiatury).
Zgodnie z dokumentacją, do konstruktora należy przekazać instancję klasy InputStream. W naszym przypadku skorzystamy ze zmiennej systemowej o nazwie „System.in”, która przechowuje informacje o domyślnym „wejściu” programu. Domyślne wejście, ustawione jest na konsolę.
Stworzenie instancji klasy Scanner:
Scanner scanner = new Scanner(System.in);
Klasa Scanner nie jest domyślnie widoczna w naszej klasie, dlatego należy ją zaimportować. W Javie importy definiujemy na samym początku pliku, jeszcze przed deklaracją klasy.
import java.util.Scanner;
Przykładowy program:
import java.util.Scanner;
public class App {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
}
}
Jak wczytać słowo? (np. Marek)
Do wczytania słowa, możemy użyć metody next(), która jest dostępna na obiekcie typu Scanner.
String name = scanner.next();
W klasie Scanner zdefiniowane są 3 przeciążone wersje metody next, my zaś skorzystamy z tej, która nie przyjmuje żadnych argumentów wejściowych. Zwraca ona obiekt typu String, a dokładniej jest to pierwsze słowo, które wpisałeś w konsoli. Pamiętaj zatem, aby wpisać tylko jedno słowo i wcisnąć enter.
Przykład 1 – wczytanie imienia:
import java.util.Scanner;
public class App {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Enter your name: ");
String name = scanner.next();
System.out.println("Your name is: "+name);
}
}
Uruchomienie programu
Enter your name: Marek
Your name is: Marek
Program zapytał nas o imię, wprowadziliśmy słowo Marek <enter>, „Marek” został przypisany do zmiennej name, ta zaś wyświetlona w linii 10-tej.
A co jeśli, wprowadzimy więcej niż jedno słowo?
Uruchomienie programu
Enter your name: Marek Nowak
Your name is: Marek
Metoda next() pobrała pierwsze słowo, którym jest Nowak. To słowo zostało przypisane do zmiennej name i wyświetlone w linii 10-tej. Następnie program zakończył działanie.
Przykład 2 – wczytanie imienia i nazwiska
Imię i nazwisko możemy wczytać na dwa sposoby. Pierwszy z nich to dwukrotne wywołanie metody next(). Jedna odczyta imię, a kolejna nazwisko. Drugi sposób to wczytanie imienia i nazwiska do jednej zmiennej, poprzez użycie metody nextLine(). Metodą nextLine() zajmiemy się w następnym przykładzie, dlatego teraz przyjrzymy się pierwszemu podejściu.
import java.util.Scanner;
public class App {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Enter your name: ");
String name = scanner.next();
System.out.print("Enter your surname: ");
String surname = scanner.next();
System.out.println("Your name is: "+name);
System.out.println("Your surname is: "+surname);
}
}
Uruchomienie programu:
Enter your name: Marek
Enter your surname: Nowak
Your name is: Marek
Your surname is: Nowak
Program wczytał imię Marek do zmiennej name i nazwisko Nowak do zmiennej surname. W liniach 13-14 program wyświetlił imię i nazwisko.
A co jeśli, wprowadzimy imię i nazwisko, już przy pierwszym zapytaniu?
Uruchomienie programu:
Enter your name: Marek Nowak
Enter your surname:
Your name is: Marek
Your surname is: Nowak
Co tutaj się wydarzyło??!! W linii 8. program zapytał o imię. Świadomie lub nie, wprowadziliśmy imię i nazwisko. Nasz obiekt scanner wczytał cały tekst, ale… metoda next() wywołana w linii 8., pobrała tylko jedno słowo, którym jest Marek. Program poszedł dalej i zapytał o nazwisko. Nie czekając na to, co wprowadzimy, pobrał ze zmiennej scanner kolejne słowo, które wprowadziliśmy wcześniej. A więc słowo Nowak i przypisał do zmiennej surname.
Szczęśliwie wynik tego programu się nie zmienił. Ale… pamiętaj o tym, że jeśli masz sekwencję wielu wywołań, różnych metod pobierających tekst/liczby, to znaki nigdzie nie giną i będą wczytywane przez kolejne metody. Istotne jest więc, jaki tekst wpisujesz i jaka metoda go przetwarza.
Zapamiętaj! Podczas czytania, tekst jest dzielony po separatorach (domyślnie białe znaki), następnie metoda next(), odczytuje pierwsze słowo. Jeśli jest kilka wywołań next(), to każdy kolejny next(), bierze odpowiednio kolejne słowo.
„biały znak” – to np. spacja, tabulacja czy nowa linia (enter).
Jak wczytać zdanie? (np. Gdańsk, ul. Kościuszki 28)
Do wczytania zdania, możemy użyć metody nextLine(), która jest dostępna na obiekcie typu Scanner.
String address = scanner.nextLine();
Jest tylko jedna wersja tej metody, bezparametrowa, zwracająca obiekt typu String. Pobiera wszystko, do znaku nowej linii (<enter>). Znak nowej linii jest również odczytywany, natomiast nie jest wyświetlany.
Przykład 3 – wczytanie adresu
import java.util.Scanner;
public class App {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("Enter your address: ");
String address = scanner.nextLine();
System.out.println("Your address is: "+address);
}
}
Uruchomienie programu:
Enter your address: Gdańsk, ul. Kościuszki 28
Your address is: Gdańsk, ul. Kościuszki 28
Tutaj sprawa jest bardzo prosta. W linii 8. wczytany zostaje cały wprowadzony tekst, aż do znaku nowej linii. Następnie zostaje zapisany w zmiennej address. Nie ma co się tutaj popsuć, dlatego zróbmy bardziej rozbudowany przykład 🙂
Przykład 4 – wczytanie adresu, imienia i nazwiska
import java.util.Scanner;
public class App {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Enter your address: ");
String address = scanner.nextLine();
System.out.print("Enter your name: ");
String name = scanner.next();
System.out.print("Enter your surname: ");
String surname = scanner.next();
System.out.println("Your address is: "+address);
System.out.println("Your name is: "+name);
System.out.println("Your surname is: "+surname);
}
}
Uruchomienie programu:
Enter your address: Gdańsk, ul. Kościuszki 28
Enter your name: Marek
Enter your surname: Nowak
Your address is: Gdańsk, ul. Kościuszki 28
Your name is: Marek
Your surname is: Nowak
Najpierw zobaczmy jak zachowają się metody next() i nextLine().
Metoda nextLine() odczytuje wszystko wraz ze znakiem nowej linii. Następnie do zmiennej address przypisywane jest to, co zostało odczytane, poza znakiem nowej linii. Metoda next() odczytuje imię oraz nazwisko.
Spójrzmy, co się stanie, gdy zamienimy miejscami metody next() i nextLine() 🙂
[PROBLEM] Scanner „pomija” metodę nextLine()?
Przykład 5 – wczytanie imienia, nazwiska i adresu (NIEPOPRAWNIE)
W stosunku do poprzedniego przykładu zachodzi jedna zmiana. Adres nie jest pobierany na początku, tylko na końcu. A więc najpierw są wywoływane metody next(), a później nextLine().
import java.util.Scanner;
public class App {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Enter your name: ");
String name = scanner.next();
System.out.print("Enter your surname: ");
String surname = scanner.next();
System.out.print("Enter your address: ");
String address = scanner.nextLine();
System.out.println("Your name is:"+name);
System.out.println("Your surname is: "+surname);
System.out.println("Your address is: "+address);
}
}
Uruchomienie programu:
Enter your name: Marek
Enter your surname: Nowak
Enter your address:
Your name is: Marek
Your surname is: Nowak
Your address is:
Co tutaj się stało??!! Program wczytał imię, wczytał nazwisko, natomiast nie zatrzymał się, aby wprowadzić adres. Gdy zastosujemy wiedzę, którą już posiadamy na temat metody nextLine(), to wszystko stanie się jasne.
Pierwszy i najważniejszy wniosek jest taki, że kolejność wywoływanych metod ma znaczenie. Jeśli pierwszy jest nextLine(), a potem next(), to nie ma problemów. Natomiast jeśli najpierw wywołamy next(), a potem nextLine(), to ten drugi sczyta znak nowej linii z poprzedniego wywołania i potraktuje to jako wpisywaną daną.
Oczywiście nie oznacza to, że musimy zawsze wywoływać nextLine() przed next(). Jest pewien powszechnie stosowany sposób, który rozwiąże ten problem. Czytaj dalej 🙂
[ROZWIĄZANIE] Przykład 6 – wczytanie imienia, nazwiska i adresu (POPRAWNIE)
Gdy chcemy, aby metoda nextLine() na nas „poczekała”, należy wywołać jeden raz puste nextLine() w celu przechwycenia znaku nowej linii (<enter>) z poprzedniego wywołania. To rozwiązanie jest uniwersalne i jest potrzebne tylko wtedy, gdy przed metodą nextLine() wywołujemy inną metodą z klasy Scanner, która nie czyta znaków końca linii.
import java.util.Scanner;
public class App {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Enter your name: ");
String name = scanner.next();
System.out.print("Enter your surname: ");
String surname = scanner.next();
scanner.nextLine();
System.out.print("Enter your address: ");
String address = scanner.nextLine();
System.out.println("Your name is: "+name);
System.out.println("Your surname is: "+surname);
System.out.println("Your address is: "+address);
}
}
Uruchomienie programu:
Enter your name: Marek
Enter your surname: Nowak
Enter your address: Gdańsk, ul. Kościuszki 28
Your name is: Marek
Your surname is: Nowak
Your address is: Gdańsk, ul. Kościuszki 28
Teraz działa poprawnie. Jak widzisz, w stosunku do poprzedniego przykładu, zmianie uległa tylko linia 13. Jest tam wywołanie metody nextLine(), tylko po to, aby sczytała nieistotny dla nas znak końca linii.
Jak wczytać liczbę?
(np. wiek 25 lat, albo pensja 5342.12zł) Scanner Java
Liczba całkowita (np. wiek 25)
Do wczytania liczby całkowietej, możemy użyć metody nextInt(), która jest dostępna na obiekcie typu Scanner.
int age = scanner.nextInt();
Metoda ta zwraca wartość typu int. Zczytuje jedną liczbę całkowitą. Jeśli wprowadzisz więcej niż jedną liczbę, oddzielone spacjami i następnie wciśniesz <enter>, to scanner odczyta tylko pierwszą z nich.
Przykład 7 – wczytanie wieku
import java.util.Scanner;
public class App {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Enter your age: ");
int age = scanner.nextInt();
System.out.println("Your age is: "+age);
}
}
Uruchomienie programu:
Enter your age: 25
Your age is: 25
Przykład 8 – wczytanie imienia, nazwiska, adresu i wieku
import java.util.Scanner;
public class App {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Enter your name: ");
String name = scanner.next();
System.out.print("Enter your surname: ");
String surname = scanner.next();
scanner.nextLine();
System.out.print("Enter your address: ");
String address = scanner.nextLine();
System.out.print("Enter your age: ");
int age = scanner.nextInt();
System.out.println("Your name is: "+name);
System.out.println("Your surname is: "+surname);
System.out.println("Your address is: "+address);
System.out.println("Your age is: "+age);
}
}
Uruchomienie programu:
Enter your name: Marek
Enter your surname: Nowak
Enter your address: Gdańsk, ul. Kościuszki 28
Enter your age: 25
Your name is: Marek
Your surname is: Nowak
Your address is: Gdańsk, ul. Kościuszki 28
Your age is: 25
Liczba rzeczywista (np. pensja 5342.12zł)
Do wczytania liczby rzeczywistej, możemy użyć metody nextDouble(), która jest dostępna na obiekcie typu Scanner.
double salary = scanner.nextDouble();
Metoda nie przyjmuje parametrów i zwraca wartość typu double. Pobiera jedną liczbę rzeczywistą. Ważne! Wartość dzisiętną należy wprowadzić po przecinku. Jeśli użyjesz kropki, to otrzymasz błąd java.util.InputMismatchException
Przykład 9 – wczytanie pensji
import java.util.Scanner;
public class App {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Enter your salary: ");
double salary = scanner.nextDouble();
System.out.println("Your salary is: "+salary);
}
}
Uruchomienie programu:
Enter your salary: 5342,12
Your salary is: 5342,12
Przykład 10 – wczytanie imienia , nazwiska, adresu, wieku i pensji
import java.util.Scanner;
public class App {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Enter your name: ");
String name = scanner.next();
System.out.print("Enter your surname: ");
String surname = scanner.next();
scanner.nextLine();
System.out.print("Enter your address: ");
String address = scanner.nextLine();
System.out.print("Enter your age: ");
int age = scanner.nextInt();
System.out.print("Enter your salary: ");
double salary = scanner.nextDouble();
System.out.println("Your name is: "+name);
System.out.println("Your surname is: "+surname);
System.out.println("Your address is: "+address);
System.out.println("Your age is: "+age);
System.out.println("Your salary is: "+salary);
}
}
Uruchomienie programu:
Enter your name: Marek
Enter your surname: Nowak
Enter your address: Gdańsk, ul. Kościuszki 28
Enter your age: 25
Enter your salary: 5342,12
Your name is: Marek
Your surname is: Nowak
Your address is: Gdańsk, ul. Kościuszki 28
Your age is: 25
Your salary is: 5342,12
java.util.InputMismatchException
Błąd ten występuje za każdym razem, gdy próbujesz przypisać niepoprawną wartość. Np.
- wywołujesz nextInt(), a wprowadzasz tekst „Marek”
- wywołujesz nextDouble(), ale liczbę rozdzielasz kropką „123.21„
W tym artykule omówione zostały najpopularniejsze metody pozwalające wczytać dane z konsoli (z klawiatury). Dzięki tym metodom możesz tworzyć programy, które będą wchodziły w interakcję z użytkownikiem.
Jako kolejny krok przetestuj wszystkie metody na własnym przykładzie. Sprawdź, czy program zachowuje się tak jakbyś tego oczekiwał.
Zadanie 1: Stwórz program dla Bilbioteki. Program będzie umożliwaił wprowadzanie danych o książkach: tytuł, autor, liczba stron oraz cena.
Zadanie 2: (wymaga znajomości pętli) Stwórz prostą grę typu 'zakład’. Założenia:
1. na starcie Gracz otrzymuje 1000 monet
2. Gracz ma 2 opcje: graj lub zakończ grę
3. gra polega na tym, że Gracz podaje liczbę od 1 do 5, którą chce obstawić, np. 2.
Następnie Gracz podaje kwotę jaką zastawia, np. 200monet. Program sprawdza czy gracz ma wystarczającą liczbę monet, jeśli tak to odejmuje je z portfela, jeśli nie, to wyświetla informację, że gra niemożliwa z powodu zbyt małej ilości monet.
Następnie gra generuje liczbę od 1 do 5 i porównuje ją z obstawianą przez gracza. Jeśli wygenerowana liczba równa się liczbie podanej przez Gracza, to obstawiana kwota jest pomnażana przez 10 i dodawana do portfela. Jeśli Gracz pomylił się o 1, to obstawiana kwota jest pomnażana przez 2 i dodawana do portfela. Ponownie wyświetlane są opcje od wyboru: graj lub zakończ grę
4. zakończenie gry powoduje przerwanie wykonywanie programu oraz wyświetlenie kwoty, która jest aktualnie w portfelu.
Masz pytania, sugestie? Zapraszam Ciebie do mojej społeczności na Discordzie, z chęcię odpowiem na wszelkie pytania.
Powodzenia!
Jeden komentarz do „Java Scanner, wprowadzanie danych z klawiatury.”
Możliwość komentowania została wyłączona.