First let’s understand this example code:
Scanner sc = new Scanner(System.in);
try {
System.out.println("digite um número: ");
System.out.println(sc.nextInt());
} catch (InputMismatchException e) {
System.out.println("deu erro, tente novamente: ");
System.out.println(sc.nextInt());
}
Suppose in the first nextInt()
i do not enter a number. The output will be:
digite um número:
abc
deu erro, tente novamente: 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)
...
What happens is, since I didn’t type a number, the first nextInt()
makes the exception and the scanner does not advance in the string (it remains stopped before the abc
). Then when I call nextInt()
again, he tries to read again the abc
, and gives error again (InputMismatchException
).
That’s what’s happening in your loop. When the nextInt()
receives an invalid value, falls within the catch
(and the scanner does not advance the string). Then it goes to the next iteration of for
and the nextInt()
tries to read the invalid value previously typed (and falls inside the catch
again, and back to the nextInt
, that falls in the catch
...). And as inside the catch
you decrement the control variable of the loop, he never leaves the for
.
What you can do is call for nextLine()
while the entered value is not a number (what can be verified with hasNextInt()
), thus the scanner skip the invalid section:
for (int c = 0; c < students; c++) {
try {
while(! sc.hasNextInt()) {
// consome a entrada até que seja encontrado um número
sc.nextLine();
}
listOfStudents.add(sc.nextInt());
} catch (InputMismatchException e) {
System.out.println("Invalid code! Try again");
}
}
So I guarantee that the nextInt()
will only be called when the next value to be read is a number. Note also that now you do not need to be decreasing the c
, because it only goes to the next iteration of for
when you can read a number.
*it is in an infinite loop *, yes it will be, look at your code, if it is wrong you decrement the variable "c", and what it does in
for
? increments again. To handle this, the invalid value, it would be better to place this block inside awhile
, as a condition of running until the value is valid– Ricardo Pontual
Yes, I understood, but this is exactly what I want to do, let’s say that the 'c' is worth 0, when a mistake is made, it will go to -1, and will be increased to 0 again (so I don’t miss the "time" to register a student), so I should enter the 'Try' block novamento, but he gets in a loop on the catch. I’m sorry if I misunderstood you, but could you show me an example if that’s the case?
– SpekTron X
only that loops are not made to change the value of the variable in this way, it is a continuous counter and should not move it, for what you want to do there are other means, as for example what I said, use a loop
while
which will only come out if the value is valid, without changing the value of thefor
, try to do it that way– Ricardo Pontual
I did it with 'while' and it keeps giving the same problem. Leave the 'while' inside the 'for', and inside there is the 'Try/catch' block, and still keep giving that loop. Is there something specific about catch that I don’t know? I’m kind of new to this area yet
– SpekTron X
@Ricardopunctual to variable
int c
is a simple variable like any other, only visible in Scope offor
, can be used like other variables. This way, you should not receive a "special treatment".– chriptus13
I’m just saying that the purpose of
for
is to be a linear counter, going from 1 to 10, etc... if you need to keep changing a counter, thefor
is not the best option, but changing the value of the variable can, but is not the best way to control the loop :)– Ricardo Pontual
Aaaah understood, so I can change the value of the variable of the 'for', but it is not advisable, it is neh?
– SpekTron X