Jak obsługiwać nieskończoną pętlę spowodowaną nieprawidłowym wejściem (InputMismatchException) za pomocą skanera
Więc utknąłem z tym kawałkiem kodu:
import java.util.InputMismatchException;
import java.util.Scanner;
public class ConsoleReader {
Scanner reader;
public ConsoleReader() {
reader = new Scanner(System.in);
//reader.useDelimiter(System.getProperty("line.separator"));
}
public int readInt(String msg) {
int num = 0;
boolean loop = true;
while (loop) {
try {
System.out.println(msg);
num = reader.nextInt();
loop = false;
} catch (InputMismatchException e) {
System.out.println("Invalid value!");
}
}
return num;
}
}
A oto moje wyjście:
Wstaw liczbę całkowitą:
Nieprawidłowa wartość!
Wstaw liczbę całkowitą:
Nieprawidłowa wartość!
...
5 answers
Zgodnie z javadoc dla skanera:
Gdy skaner rzuca InputMismatchException, skaner nie przejdzie token, który spowodował wyjątek, tak aby mógł być pobrane lub pominięte przez inne metoda.
Oznacza to, że jeśli następny token nie jest int
, rzuca InputMismatchException
, ale token zostaje. Tak więc przy następnej iteracji pętli reader.nextInt()
ponownie odczytuje ten sam token i ponownie rzuca wyjątek. Musisz użyć do góry. Dodaj reader.next()
wewnątrz catch
, aby zużyć token, który jest nieprawidłowy i musi zostać odrzucony.
...
} catch (InputMismatchException e) {
System.out.println("Invalid value!");
reader.next(); // this consumes the invalid token
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-08-26 05:27:09
To, co bym zrobił, to odczytanie całej linii za pomocą skanera.nextLine (). Następnie utwórz inny skaner, który odczytuje zwrócony ciąg znaków.
String line = reader.nextLine();
Scanner sc = new Scanner(line);
To sprawi, że Twoja przykładowa funkcja będzie wyglądać tak:
public int readInt(String msg) {
int num = 0;
boolean loop = true;
while (loop) {
try {
System.out.println(msg);
String line = reader.nextLine();
Scanner sc = new Scanner(line);
num = sc.nextInt();
loop = false;
} catch (InputMismatchException e) {
System.out.println("Invalid value!");
}
}
return num;
}
W ten sposób masz jeden skaner, który pobiera dane wejściowe i jeden, który je waliduje, więc nie musisz się martwić, że czytelnik będzie dbał o to, czy wprowadzi poprawną formę danych wejściowych.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-08-26 05:29:08
Strażnikiem while-do jest zmienna 'loop'.
Sam wyjątek rzucony zanim twój kod dotrze do pętli przypisania = false; Aby być precyzyjnym, wyjątek jest wyrzucany w poprzednim poleceniu, które jest num = reader.nextInt ();
Po rzuceniu wyjątku, wartość zmiennej 'loop' jest 'true', ale twój kod przeskakuje, aby złapać blok, a następnie powtarza while-do. To while-do nigdy się nie skończy, ponieważ następna iteracja ponownie rzuci wyjątek, skoczy ponownie złapać blok i tak on
Aby zakończyć to while-do, musisz strzec swojego while-do z inną logiczną rzeczą, taką jak:
- wyjście, gdy czytelnik otrzyma znak nie-int
- Exit when EOF
Można to zrobić w bloku catch lub w innych liniach. Ale precyzyjne rozwiązanie zależy od twoich specyfikacji.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-08-26 05:34:00
Możesz również spróbować tego:
public int readInt(String msg) {
int num = 0;
try {
System.out.println(msg);
num = (new Scanner(System.in)).nextInt();
} catch (InputMismatchException e) {
System.out.println("Invalid value!");
num = readInt(msg);
}
return num;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-08-26 05:34:48
package nzt.nazakthul.app;
import java.util.*;
public class NztMainApp {
public static void main(String[] args) {
ReadNumber readObj = new ReadNumber();
readObj.readNumber();
}
}
class ReadNumber {
int no;
int readNumber() {
Scanner number = new Scanner(System.in);
int no=0;
boolean b=true;
do {
try {
System.out.print("Enter a number:\t");
no = number.nextInt();
} catch (InputMismatchException e) {
System.out.println("No Number");
//e.printStackTrace();
b=false;
}
}
while (b);
return no;
}
}
Osobiście używam BufferedReader i InputStreamReader do odczytu String i sprawdzenia czy jest liczbą czy nie, ale ze skanerem jest mniej kodu. Kod jest zaznaczony i uruchom ok.