That’s the problem with you if (i == 0) sc.nextLine();
that is in the wrong place.
Note that this is after the previous line that has the pessoa[i] = sc.nextLine();
. Thus, it does not assign an empty string to the name of pessoa[0]
and will skip the name that should be the first person. So when it shows nothing it is because the first person had been drawn.
The solution is to remove the if
and move that sc.nextLine();
for just after the sc.nextInt();
:
import java.util.Scanner;
import java.util.Random;
class Sorteio {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Informe o numero de pessoas no sorteio: ");
int n = sc.nextInt();
sc.nextLine();
String[] pessoas = new String[n];
for (int i = 0; i < n; i++) {
System.out.println("Informe a " + (i + 1) + "a pessoa: ");
pessoas[i] = sc.nextLine();
}
Random rd = new Random();
for (int j = 0; j < 200; j++) {
System.out.println("O vencedor do sorteio e: " + pessoas[rd.nextInt(n)]);
}
}
}
Note that I have placed the draw 200 times to show you that it always gives an answer that is one of the names and never gives an exception.
See here working on ideone.
The need to use this nextLine()
to empty the buffer is kind of bad. The solution is to eliminate the nextInt()
and just use the nextLine()
:
import java.util.Scanner;
import java.util.Random;
class Sorteio {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Informe o numero de pessoas no sorteio: ");
int n = Integer.parseInt(sc.nextLine());
String[] pessoas = new String[n];
for (int i = 0; i < n; i++) {
System.out.println("Informe a " + (i + 1) + "a pessoa: ");
pessoas[i] = sc.nextLine();
}
Random rd = new Random();
for (int j = 0; j < 200; j++) {
System.out.println("O vencedor do sorteio e: " + pessoas[rd.nextInt(n)]);
}
}
}
See here working ideone.
This strange behavior occurs with the sc.nextInt()
and with the sc.nextLine()
on those grounds:
The System.in
is the object that provides other objects that the user has typed.
The System.in
stores what the user has typed in a memory area called buffer.
Other objects (in this case Scanner
) may request the System.in
to provide some of the characters or bytes typed by the user. (It works with bytes, but these are interpreted/converted into characters by Scanner
).
When there’s something in buffer and the System.in
is asked to provide a few bytes, it will provide them when removing them from the beginning of the buffer. If surplus bytes remain in the buffer, they will continue there.
When the buffer is empty and the System.in
is asked to provide some bytes, it will crash and wait for the user to type some text finished with enter. That text, including the enter is stored in the buffer and then follows what is in the previous item: some bytes are taken from the beginning of buffer and delivered. Any surplus bytes remain there.
When the method nextLine()
of Scanner
is called, it will consume all bytes you find until you find the enter and return what he consumed without the enter. That is, it will consume the first line of whatever is in System.in
and discard the enter.
Already the method nextInt()
works in a different way, it will consume only the bytes that correspond to digits, leaving the enter back inside the buffer.
In this way, we have an important difference: The nextLine()
consumes and discards the enter at the end of the line, but the nextInt()
let it go. That’s why the nextLine()
after the nextInt()
is necessary and it returns an empty string. Its function is to remove the enter which was dropped at the beginning of buffer for nextInt()
.
This incoherent behavior is solved by using only the nextLine()
and abandon the nextInt()
. The Integer.parseInt(String)
is used to turn the read line into a number.
Man, I used this
sc.nextLine
without knowing what it’s for. I was trying without it, only it skipped the reading execution of the first person, going straight to second. I searched and saw that it serves to "empty the keyboard buffer" (whatever it Means), and after I put it right after thepessoas[i] = sc.nextLine()
within the loopfor
, I realized that he did not jump, but now it was necessary to press enter once again after informing the name for reading.– Jow
The way I found to not skip reading and not have to press enter twice every time you read a value, was putting this
sc.nextLine()
only at first reading of the loop. You could kindly explain, or indicate some site with explanation of what this is forsc.nextLine()
loose?– Jow
@Jow Edited answer to explain this.
– Victor Stafusa
I understand very well. Thanks for taking the time to solve my problem. He still took the trouble to edit the answer and add more information, explaining in a very clear way. Hug!
– Jow
Just one thing: at the end of the third topic from the bottom up, wouldn’t it just be "letting enter" instead of "leaving the enter behind"? @Victor Stafusa
– Jow
@Jow I edited the end of this item too. It became clearer?
– Victor Stafusa