Problem generating random value using Random class

1

The program is generating a random value, but sometimes it pops the array, or simply does not display anything.

Error examples:

Mycode:

importjava.util.Scanner;importjava.util.Random;publicclassSorteio{publicstaticvoidmain(String[]args){Scannersc=newScanner(System.in);System.out.println("Informe o numero de pessoas no sorteio: ");
        int n = sc.nextInt();

        String pessoa [] = new String [n];

        for (int i = 0; i < n; i++) {
            System.out.println("Informe a " + (i + 1) + "a pessoa: ");
            pessoa[i] = sc.nextLine();
            if (i == 0) sc.nextLine();
        }

        Random rd = new Random();

        System.out.println("O vencedor do sorteio e: " + pessoa[rd.nextInt(n)]);
    }
}
    
asked by anonymous 13.09.2017 / 20:51

1 answer

4

The problem is that your if (i == 0) sc.nextLine(); is in the wrong place.

Note that this is after the previous line that has pessoa[i] = sc.nextLine(); . So, it does not assign an empty string to the name of pessoa[0] and will skip the name it should be from the first person. So when it does not show anything it is because the first person had been drawn.

The solution is to remove if and move that sc.nextLine(); to soon after 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)]);
        }
    }
}

Please note that I placed the draw being made 200 times to show you always give 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 a bit bad. The solution is to eliminate nextInt() and only use 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 running the ideone.

This strange behavior occurs with sc.nextInt() and sc.nextLine() because of these reasons:

  • The System.in is the object that gives other objects what the user has entered.

  • The System.in stores what the user typed in a memory area called buffer .

  • Other objects (in this case Scanner ) can ask System.in to provide some of the characters or bytes entered by the user. (It works with bytes, but these are interpreted / converted into characters by Scanner .)

  • When there is something in the buffer and the System.in is required to provide some bytes, it will provide them by removing them from the beginning of the buffer >. If surplus bytes are left in buffer , they will remain there.

  • When the buffer is empty and System.in is prompted to provide some bytes, it will hang and wait for the user to type some text ending with enter . This text, including enter is stored in the buffer and then it 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 nextLine() method of Scanner is called, it will consume all the bytes that it finds until it finds enter and returns what it consumed kbd> enter . That is, it will consume the first line of what is in System.in and discard enter .

  • While the nextInt() method works differently, it will consume only bytes that match digits, leaving enter behind in the buffer .

  • In this way, we have an important difference: nextLine() consumes and discards enter at the end of the line, but nextInt() leaves it there. This is why nextLine() after nextInt() is required and it returns an empty string. The function is to remove the enter that was dropped at the beginning of buffer by nextInt() .

  • This incoherent behavior is resolved by using only nextLine() and leaving nextInt() . The Integer.parseInt(String) is used to transform the read line into a number.

13.09.2017 / 21:15