Erro StringIndexOutOfBoundsException em Array?

Estou começando no primeiro semestre no curso de ciência da informação, por conta disse desconsidere caso seja um erro besta, segue codigo:

import java.util.Scanner;
public class prova {
  public static void main(String[] args) {
    Scanner ler = new Scanner(System.in);
    // Informando variaveis

    final int tam = 3;
    char perguntas = 0;
    char[] gabarito = {'a','b','a'/*,'d','d','c','b','a','c','c'*/};
    char[] respostas = new char[tam];
    String nome;
    int nota = 0;
    // Informar nome
    System.out.println("--PROVA JAVA--");
    System.out.print("Digite o seu nome: ");
    nome = ler.next();
    respostas[0] = 'a';
    respostas[1] = 'b';
    respostas[2] = 'a';
    // Fazendo perguntas e solicitando respostas
    for (int i = 0; i < tam; i++) {
      if (perguntas == 0) {
        System.out.println("1) Como escrever um comando de saída em java?");
        System.out.println("a- System.out.println(''Hello World'')");
        System.out.println("b- Cosole.WritLine(''Hello World'')");
        System.out.println("c- print(''Hello World'')");
        System.out.println("d- print('Hello World')");
        respostas[i] = ler.nextLine().charAt(0); // O erro vem dessa linha de codigo, e outras semelhantes abaixo
      } else if (perguntas == 1) {
        System.out.println("2) Qual a biblioteca é responsável para que o usuário possa inserir valores?");
        System.out.println("a- import.java.util.scanner;");
        System.out.println("b- import.java.util.Scanner;");
        System.out.println("c- import.java.util.Scanner");
        System.out.println("d- imoprt.java.util;");
        respostas[i] = ler.nextLine().charAt(0); 
      } else if (perguntas == 2) {
        System.out.println("3) Quais são os comandos de decisão?");
        System.out.println("a- if/if...else/switch");
        System.out.println("b- while/for/do while");
        System.out.println("c- if/if...else/for");
        System.out.println("d- switch/while/do while");
        respostas[i] = ler.nextLine().charAt(0);
      }
      perguntas++;
    }
    // Adcionando notas a cada resposta correta
    for (int i = 0; i < tam; i++) {
      if (gabarito[i] == respostas[i]) {
        nota++;
      }
    }
    System.out.println("O aluno " + nome + " tirou " + nota + " pontos na prova!");
  }
}

Mensagem de erro:

→ Exception in thread “main” java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0

1 curtida

Utilize next() em vez de nextLine():

package javaapplication4;
import java.util.Scanner;
public class JavaApplication4 {
    public static void main(String[] args) {       
        Scanner ler = new Scanner(System.in);
        // Informando variaveis
        final int tam = 3;
        char perguntas = 0;
        char[] gabarito = {'a','b','a'/*,'d','d','c','b','a','c','c'*/};
        char[] respostas = new char[tam];
        String nome;
        int nota = 0;
        String resp = "";
        // Informar nome
        System.out.println("--PROVA JAVA--");
        System.out.print("Digite o seu nome: ");
        nome = ler.next();
        respostas[0] = 'a';
        respostas[1] = 'b';
        respostas[2] = 'a';
        // Fazendo perguntas e solicitando respostas
        for (int i = 0; i < tam; i++) {
          if (perguntas == 0) {
            System.out.println("1) Como escrever um comando de saída em java?");
            System.out.println("a- System.out.println(''Hello World'')");
            System.out.println("b- Cosole.WritLine(''Hello World'')");
            System.out.println("c- print(''Hello World'')");
            System.out.println("d- print('Hello World')");
            resp = ler.next();            
            if (!resp.trim().isEmpty()) {
                respostas[i] = resp.charAt(0); 
                perguntas++;
            }
          } else if (perguntas == 1) {
            System.out.println("2) Qual a biblioteca é responsável para que o usuário possa inserir valores?");
            System.out.println("a- import.java.util.scanner;");
            System.out.println("b- import.java.util.Scanner;");
            System.out.println("c- import.java.util.Scanner");
            System.out.println("d- imoprt.java.util;");
            resp = ler.next();            
            if (!resp.trim().isEmpty()) {
                respostas[i] = resp.charAt(0); 
                perguntas++;
            }
          } else if (perguntas == 2) {
            System.out.println("3) Quais são os comandos de decisão?");
            System.out.println("a- if/if...else/switch");
            System.out.println("b- while/for/do while");
            System.out.println("c- if/if...else/for");
            System.out.println("d- switch/while/do while");
            resp = ler.next();            
            if (!resp.trim().isEmpty()) {
                respostas[i] = resp.charAt(0); 
                perguntas++;
            }
          }          
        }
        // Adcionando notas a cada resposta correta
        for (int i = 0; i < tam; i++) {
          if (gabarito[i] == respostas[i]) {
            nota++;
          }
        }
        System.out.println("O aluno " + nome + " tirou " + nota + " pontos na prova!");        
    }    
}

Em realmente não sei o motivo, alguém aqui que tenha conhecimento em Java pode nos auxiliar, eu acho que é por causa da quebra de linha. (não sei porque não é minha linguagem afim), o código pode ser bem melhor escrito:

package javaapplication4;
import java.util.Scanner;
public class JavaApplication4 {
    public static void leitura(Scanner ler, char[] respostas, int perguntas, int i){
        String resp = ler.next();
        if (!resp.trim().isEmpty()) {
            respostas[i] = resp.charAt(0); 
            perguntas++;
        }
    }
    public static void resultado(char[] gabarito,char[] respostas, int tam, int nota, String nome){
        for (int i = 0; i < tam; i++) {
          if (gabarito[i] == respostas[i]) {
            nota++;
          }
        }
        System.out.println("O aluno " + nome + " tirou " + nota + " pontos na prova!");
    }
    public static void imprimirPerguntas(String ...textos) {
        for(String texto : textos){
            System.out.println(texto);
        }    
    }
    public static void main(String[] args) {       
        Scanner ler = new Scanner(System.in);

        // Informando variaveis
        String nome;
        int tam = 3, nota = 0,perguntas = 0;
        char[] gabarito = {'a','b','c','d'};
        char[] respostas = new char[tam];
        
        // Informar nome
        System.out.println("--PROVA JAVA--");
        System.out.print("Digite o seu nome: ");
        nome = ler.next();        
        
        // Fazendo perguntas e solicitando respostas
        for (int i = 0; i < tam; i++) {
            switch (perguntas) {
                case 0:
                    imprimirPerguntas(
                        "1) Como escrever um comando de saída em java?",
                        "a- System.out.println(''Hello World'')",
                        "b- Cosole.WritLine(''Hello World'')",
                        "c- print(''Hello World'')",
                        "d- print('Hello World')"
                    );
                    leitura(ler, respostas, perguntas, i);
                    break;
                case 1:
                    imprimirPerguntas(
                        "2) Qual a biblioteca é responsável para que o usuário possa inserir valores?",
                        "a- import.java.util.scanner;",
                        "b- import.java.util.Scanner;",
                        "c- import.java.util.Scanner",
                        "d- imoprt.java.util;"
                    );
                    leitura(ler, respostas, perguntas, i);
                    break;
                case 2:
                    imprimirPerguntas(
                        "3) Quais são os comandos de decisão?",
                        "a- if/if...else/switch",
                        "b- while/for/do while",
                        "c- if/if...else/for",
                        "d- switch/while/do while"
                    );
                    leitura(ler, respostas, perguntas, i);
                    break;
                default:
                    break;
            }
        }
        resultado(gabarito,respostas, tam, nota, nome);                
    }    
}

pode ser melhorado mais, pode ser feito outras rotinas conforme o crescimento, mas, o problema inicial era em vez de nextLine() colocar next() com já dito não sei o motivo acho que é quebra de linha.

1 curtida

Na verdade o problema é o uso do next.
O único método da classe Scanner que consome a quebra de linha é o nextLine.
Então, quando alguém usa qualquer outro método next ou nextAlgumaCoisa, a quebra de linha gerada ao pressionar ENTER fica “pendurada” na memória, assim, quando for chamado o nextLine ele vai primeiro consumir a quebra de linha e retornar vazio.

Há duas soluções:

1 - quando usar o Scanner para ler o System.in, usar somente o método nextLine.

2 - a cada chamada de um método next ou nextAlgumaCoisa, chamar imediatamente o nextLine pra consumir a quebra de linha que ficou em memória.

3 curtidas

Complementando: por padrão, o Scanner usa espaços e quebras de linha para separar a entrada em tokens, e os métodos next e nextAlgumaCoisa sempre consomem apenas o próximo token. Mas esses métodos não consomem o separador, por isso acontece essa situação que o @staroski explicou, de ficar a quebra de linha “pendurada” e só ser consumida na próxima chamada.

Por isso o melhor nesses casos é usar nextLine, que é o único método que consome a linha toda, inclusive a quebra de linha.

Além disso tem outro detalhe: se no nome for digitado, por exemplo, “Fulano de Tal”, o next() só retorna “Fulano”, enquanto nextLine() retorna o nome completo (mas o principal motivo pra usá-lo é evitar esse problema da quebra de linha pendente).


Claro que dá pra mudar o separador e fazer outros “malabarismos”, mas nesse caso seria complicar à toa, usar apenas nextLine já seria suficiente pro seu caso.

Se quiser se aprofundar no uso do Scanner, leia aqui sim, é jabá do meu blog :slight_smile:

2 curtidas

Mano, genial, eu ainda não aprendi a criar outros public static void e referenciar na principal, mas vou dar uma olhada nisso hoje, muito obrigado mesmo.

1 curtida

Caramba então o problema todo é o primeiro next(), obrigado também @hugokotsubo e @staroski por tirar a duvida e somatizar no conhecimento.

Código refatorado e como deve ser pelas explicações já citadas pelos dois usuários que conhecem a linguagem Java.

package javaapplication4;
import java.util.Scanner;
public class JavaApplication4 {
    public static void leitura(Scanner ler, char[] respostas, int perguntas, int i){
        String resp = ler.nextLine();
        if (!resp.trim().isEmpty()) {
            respostas[i] = resp.charAt(0); 
            perguntas++;
        }
    }
    public static void resultado(char[] gabarito,char[] respostas, int tam, int nota, String nome){
        for (int i = 0; i < tam; i++) {
          if (gabarito[i] == respostas[i]) {
            nota++;
          }
        }
        System.out.println("O aluno " + nome + " tirou " + nota + " pontos na prova!");
    }
    public static void imprimirPerguntas(String ...textos) {
        for(String texto : textos){
            System.out.println(texto);
        }    
    }
    public static void main(String[] args) {       
        Scanner ler = new Scanner(System.in);

        // Informando variaveis
        String nome;
        int tam = 3, nota = 0,perguntas = 0;
        char[] gabarito = {'a','b','c','d'};
        char[] respostas = new char[tam];
        
        // Informar nome
        System.out.println("--PROVA JAVA--");
        System.out.print("Digite o seu nome: ");
        nome = ler.nextLine();        
        
        // Fazendo perguntas e solicitando respostas
        for (int i = 0; i < tam; i++) {
            switch (perguntas) {
                case 0:
                    imprimirPerguntas(
                        "1) Como escrever um comando de saída em java?",
                        "a- System.out.println(''Hello World'')",
                        "b- Cosole.WritLine(''Hello World'')",
                        "c- print(''Hello World'')",
                        "d- print('Hello World')"
                    );
                    leitura(ler, respostas, perguntas, i);
                    break;
                case 1:
                    imprimirPerguntas(
                        "2) Qual a biblioteca é responsável para que o usuário possa inserir valores?",
                        "a- import.java.util.scanner;",
                        "b- import.java.util.Scanner;",
                        "c- import.java.util.Scanner",
                        "d- imoprt.java.util;"
                    );
                    leitura(ler, respostas, perguntas, i);
                    break;
                case 2:
                    imprimirPerguntas(
                        "3) Quais são os comandos de decisão?",
                        "a- if/if...else/switch",
                        "b- while/for/do while",
                        "c- if/if...else/for",
                        "d- switch/while/do while"
                    );
                    leitura(ler, respostas, perguntas, i);
                    break;
                default:
                    break;
            }
        }
        resultado(gabarito,respostas, tam, nota, nome);                
    }    
}

Testada e funcional

2 curtidas

Dá uma olhada também no aspecto citados que é de suma importância ao seu e também eu que aprendi mais alguma coisa sobre Java que não é minha linguagem afim, mas, sempre tento ajudar.

package javaapplication4;
import java.util.Scanner;
public class JavaApplication4 {
    public static void leitura(Scanner ler, char[] respostas, int perguntas, int i){
        String resp = ler.nextLine();
        if (!resp.trim().isEmpty()) {
            respostas[i] = resp.charAt(0); 
            perguntas++;
        }
    }
    public static void resultado(char[] gabarito,char[] respostas, int tam, int nota, String nome){
        for (int i = 0; i < tam; i++) {
          if (gabarito[i] == respostas[i]) {
            nota++;
          }
        }
        System.out.println("O aluno " + nome + " tirou " + nota + " pontos na prova!");
    }
    public static void imprimirPerguntas(String ...textos) {
        for(String texto : textos){
            System.out.println(texto);
        }    
    }
    public static void main(String[] args) {       
        Scanner ler = new Scanner(System.in);

        // Informando variaveis
        String nome;
        int tam = 3, nota = 0,perguntas = 0;
        char[] gabarito = {'a','b','c','d'};
        char[] respostas = new char[tam];
        
        // Informar nome
        System.out.println("--PROVA JAVA--");
        System.out.print("Digite o seu nome: ");
        nome = ler.nextLine();        
        
        // Fazendo perguntas e solicitando respostas
        for (int i = 0; i < tam; i++) {
            switch (perguntas) {
                case 0:
                    imprimirPerguntas(
                        "1) Como escrever um comando de saída em java?",
                        "a- System.out.println(''Hello World'')",
                        "b- Cosole.WritLine(''Hello World'')",
                        "c- print(''Hello World'')",
                        "d- print('Hello World')"
                    );
                    leitura(ler, respostas, perguntas, i);
                    break;
                case 1:
                    imprimirPerguntas(
                        "2) Qual a biblioteca é responsável para que o usuário possa inserir valores?",
                        "a- import.java.util.scanner;",
                        "b- import.java.util.Scanner;",
                        "c- import.java.util.Scanner",
                        "d- imoprt.java.util;"
                    );
                    leitura(ler, respostas, perguntas, i);
                    break;
                case 2:
                    imprimirPerguntas(
                        "3) Quais são os comandos de decisão?",
                        "a- if/if...else/switch",
                        "b- while/for/do while",
                        "c- if/if...else/for",
                        "d- switch/while/do while"
                    );
                    leitura(ler, respostas, perguntas, i);
                    break;
                default:
                    break;
            }
        }
        resultado(gabarito,respostas, tam, nota, nome);                
    }    
}