Estou usando os Scanner
métodos nextInt()
e nextLine()
para ler entradas.
Se parece com isso:
System.out.println("Enter numerical value");
int option;
option = input.nextInt(); // Read numerical value from input
System.out.println("Enter 1st string");
String string1 = input.nextLine(); // Read 1st string (this is skipped)
System.out.println("Enter 2nd string");
String string2 = input.nextLine(); // Read 2nd string (this appears right after reading numerical value)
O problema é que, depois de inserir o valor numérico, o primeiro input.nextLine()
é ignorado e o segundo input.nextLine()
é executado, para que minha saída fique assim:
Enter numerical value
3 // This is my input
Enter 1st string // The program is supposed to stop here and wait for my input, but is skipped
Enter 2nd string // ...and this line is executed and waits for my input
Testei meu aplicativo e parece que o problema está no uso input.nextInt()
. Se eu excluí-lo, ambos string1 = input.nextLine()
e string2 = input.nextLine()
são executados como eu quero que sejam.
java
io
java.util.scanner
blekione
fonte
fonte
Respostas:
Isso
Scanner.nextInt
ocorre porque o método não lê o caractere de nova linha em sua entrada criada pressionando "Enter" e, portanto, a chamadaScanner.nextLine
retorna depois de ler essa nova linha .Você encontrará o comportamento semelhante ao usar o método
Scanner.nextLine
posteriorScanner.next()
ou qualquer outroScanner.nextFoo
método (excetonextLine
ele próprio).Gambiarra:
Faça uma
Scanner.nextLine
chamada após cada umaScanner.nextInt
ouScanner.nextFoo
consuma o restante dessa linha, incluindo a nova linhaOu, melhor ainda, leia a entrada
Scanner.nextLine
e converta-a no formato adequado que você precisa. Por exemplo, você pode converter para um número inteiro usando oInteger.parseInt(String)
métodofonte
try-catch
, porqueInteger.parseInt
lançaNumberFormatException
quando um argumento inválido é passado para ele. Você aprenderá sobre a exceção mais tarde. Para EG: -Integer.parseInt("abc")
. Você não quer que "abc" seja convertido para int, certo?Scanner#hasNextFoo
cheque antes do que um try-catch, mas isso também funciona.O problema está no método input.nextInt () - ele somente lê o valor int. Então, quando você continuar lendo com input.nextLine (), receberá a tecla Enter "\ n". Então, para pular isso, você deve adicionar o input.nextLine () . Espero que isso esteja claro agora.
Tente assim:
fonte
nextLine
, mas ainda precisa de uma explicação para este comportamentoÉ porque quando você digita um número e pressiona Enter,
input.nextInt()
consome apenas o número, não o "fim de linha". Quandoinput.nextLine()
executado, consome o "fim de linha" ainda no buffer desde a primeira entrada.Em vez disso, use
input.nextLine()
imediatamente apósinput.nextInt()
fonte
Parece haver muitas perguntas sobre esse problema
java.util.Scanner
. Eu acho que uma solução mais legível / idiomática seria ligarscanner.skip("[\r\n]+")
para descartar qualquer caractere de nova linha depois de ligarnextInt()
.EDIT: como @PatrickParker observou abaixo, isso causará um loop infinito se o usuário inserir qualquer espaço em branco após o número. Consulte a resposta para obter um padrão melhor para usar com o pular: https://stackoverflow.com/a/42471816/143585
fonte
Faz isso porque
input.nextInt();
não captura a nova linha. você poderia fazer como os outros propostos adicionando uminput.nextLine();
por baixo.Como alternativa, você pode fazê-lo no estilo C # e analisar um nextLine em um número inteiro da seguinte maneira:
Fazer isso funciona da mesma maneira e economiza uma linha de código.
fonte
TL; DR Use
scanner.skip("\\R")
antes de cadascanner.newLine()
chamada, que é executada após:scanner.next()
scanner.next*TYPE*()
método.Coisas que você precisa saber:
O texto que representa poucas linhas também contém caracteres imprimíveis entre as linhas (nós os chamamos de separadores de linha), como
"\r"
)"\n"
)quando você está lendo dados do console, ele permite que o usuário digite sua resposta e, quando terminar, ele precisa de alguma forma confirmar esse fato. Para isso, o usuário deve pressionar a tecla "Enter" / "Return" no teclado.
O importante é que essa chave, além de garantir a colocação dos dados do usuário na entrada padrão (representada pela
System.in
qual é lida porScanner
), também envie separadores de linha dependentes do SO (como no Windows\r\n
) depois dela.Portanto, quando você pede ao usuário um valor como
age
, e o usuário digita 42 e pressiona enter, a entrada padrão conterá"42\r\n"
.Problema
Scanner#nextInt
(e outros métodos) não permite que o Scanner consuma esses separadores de linha. Ele as lerá (de que outra forma o Scanner saberia que não há mais dígitos do usuário que representam valor do que espaços em branco?) Que os removerão da entrada padrão, mas também armazenarão em cache esses separadores de linha internamenteScanner#nextType
System.in
age
. O que precisamos lembrar é que todos os métodos do Scanner estão sempre digitalizando a partir do texto em cache.Agora,
Scanner#nextLine()
basta coletar e retornar todos os caracteres até encontrar os separadores de linha (ou final do fluxo). Porém, como os separadores de linha após a leitura do número no console são encontrados imediatamente no cache do Scanner, ele retorna String vazia, o que significa que o Scanner não conseguiu encontrar nenhum caractere antes desses separadores de linha (ou no final do fluxo).BTW
nextLine
também consome esses separadores de linha.Solução
Portanto, quando você deseja solicitar o número e a linha inteira, evitando a sequência vazia como resultado de
nextLine
,nextInt
cache ScannersnextLine
,skip("\\R")
ouskip("\r\n|\r|\n")
permitindo que o Scanner pule parte correspondente ao separador de linhas (mais informações sobre\R
: https://stackoverflow.com/a/31060125 )nextInt
(nemnext
, nem nenhumnextTYPE
método). Em vez disso, leia os dados inteiros linha por linha usandonextLine
e analisando números de cada linha (assumindo que uma linha contenha apenas um número) para o tipo apropriado, comoint
viaInteger.parseInt
.BTW : os métodos podem ignorar delimitadores (por padrão, todos os espaços em branco, como guias, separadores de linha), incluindo os armazenados em cache pelo scanner, até encontrar o próximo valor não-delimitador (token). Graças a isso para entrada como código
Scanner#nextType
"42\r\n\r\n321\r\n\r\n\r\nfoobar"
será capaz de atribuir corretamente
num1=42
num2=321
name=foobar
.fonte
Em vez de
input.nextLine()
usarinput.next()
, isso deve resolver o problema.Código modificado:
fonte
Se você quiser ler as strings e ints, uma solução é usar dois scanners:
fonte
scanner.nextLine()
deve funcionar.Se você deseja digitalizar rapidamente a entrada sem se confundir com o método nextLine () da classe Scanner, use o Custom Input Scanner.
Código:
Vantagens:
Métodos :
Uso:
ScanReader sc = new ScanReader(System.in);
3. Importar Classes necessárias:import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream;
4. Lance IOException do seu método principal para lidar com a exceção 5. Use métodos fornecidos. 6. AproveiteExemplo:
fonte
Para evitar o problema, use
nextLine();
imediatamente depoisnextInt();
, pois ajuda a limpar o buffer. Quando você pressionaENTER
o botãonextInt();
não captura a nova linha e, portanto, ignora oScanner
código posteriormente.fonte
sc.nextLine()
é melhor em comparação com a análise da entrada. Porque o desempenho será bom.fonte
Eu acho que estou muito atrasado para a festa ..
Como declarado anteriormente, chamar
input.nextLine()
depois de obter seu valor int resolverá seu problema. A razão pela qual seu código não funcionou foi porque não havia mais nada para armazenar da sua entrada (onde você inseriu o int) nostring1
. Vou lançar um pouco mais de luz para todo o tópico.Considere nextLine () como o ímpar entre os métodos nextFoo () na classe Scanner. Vamos dar um exemplo rápido. Digamos que temos duas linhas de código como as abaixo:
Se inserirmos o valor abaixo (como uma única linha de entrada)
O valor de nossa
firstNumber
esecondNumber
variável se tornam 54 e 234, respectivamente. A razão pela qual isso funciona dessa maneira é porque um novo avanço de linha (por exemplo, \ n ) NÃO É gerado automaticamente quando o método nextInt () recebe os valores. Simplesmente pega o "próximo int" e segue em frente. É o mesmo para o restante dos métodos nextFoo (), exceto nextLine ().nextLine () gera um novo feed de linha imediatamente após obter um valor; é isso que @RohitJain significa dizendo que o novo feed de linha é "consumido".
Por fim, o método next () simplesmente pega a String mais próxima sem gerar uma nova linha; isso o torna o método preferencial para obter seqüências de caracteres separadas na mesma linha única.
Espero que isso ajude .. Feliz codificação!
fonte
Use 2 objetos do scanner em vez de um
fonte
fonte
se eu espero uma entrada não vazia
usado no exemplo acima:
fonte
Em um dos meus casos de uso, tive o cenário de ler um valor de cadeia precedido por alguns valores inteiros . Eu tive que usar um loop " for / while " para ler os valores. E nenhuma das sugestões acima funcionou neste caso.
Usando em
input.next()
vez deinput.nextLine()
corrigido o problema. Espero que isso possa ser útil para aqueles que lidam com um cenário semelhante.fonte
Use este código para corrigir o seu problema.
fonte
Como os
nextXXX()
métodos não leemnewline
, excetonextLine()
. Podemos pular anewline
após ler qualquernon-string
valor (int
neste caso) usandoscanner.skip()
o seguinte:fonte
Por que não usar um novo scanner para todas as leituras? Como abaixo. Com essa abordagem, você não enfrentará seu problema.
fonte
Scanner
para evitar vazamento de memória. Desperdiçando tempo?nextInt()
não consumirá a nova linha, independentemente de estar em uma "nova"Scanner
ou em uma já usada.