Skaner pomija nextline() po użyciu next () lub nextFoo ()?
Do odczytu danych wejściowych używam metod Scanner
nextInt()
i nextLine()
.
Wygląda to tak:
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)
Problem polega na tym, że po wpisaniu wartości liczbowej pierwsza input.nextLine()
jest pomijana, a druga input.nextLine()
jest wykonywana, tak że moje wyjście wygląda tak:
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
Przetestowałem moją aplikację i wygląda na to, że problem leży w użyciu input.nextInt()
. Jeśli go usunę, to zarówno string1 = input.nextLine()
, jak i string2 = input.nextLine()
zostaną wykonane tak, jak chcę.
15 answers
To dlatego, że Scanner.nextInt
metoda nie pobiera znaku ostatniego newline z twojego wejścia, a zatem newline jest pobierana w następnym wywołaniu do Scanner.nextLine
.
Podobne zachowanie napotkasz, gdy użyjesz Scanner.nextLine
po Scanner.next()
lub dowolną metodą Scanner.nextFoo
(z wyjątkiem samej metody nextLine
).
Obejście:
-
Albo wystrzelić puste
Scanner.nextLine
wywołanie poScanner.nextInt
lubScanner.nextFoo
, aby pochłonąć resztę tej linii w tym newlineint option = input.nextInt(); input.nextLine(); // Consume newline left-over String str1 = input.nextLine();
-
Lub, byłoby jeszcze lepiej, gdybyś odczytał dane wejściowe przez
Scanner.nextLine
i przekonwertował dane wejściowe do odpowiedniego formatu, którego potrzebujesz. Dla przykładu, do liczby całkowitej za pomocąInteger.parseInt(String)
metoda.int option = 0; try { option = Integer.parseInt(input.nextLine()); } catch (NumberFormatException e) { e.printStackTrace(); } String str1 = input.nextLine();
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-16 02:10:50
Problem jest z wejściem .metoda nextInt () - odczytuje tylko wartość int. Więc kiedy kontynuujesz Czytanie z wejściem.nextLine () otrzymasz klawisz Enter "\n". Aby to pominąć, musisz dodać input.nextLine () . Mam nadzieję, że teraz to będzie jasne.
Spróbuj tak:
System.out.print("Insert a number: ");
int number = input.nextInt();
input.nextLine(); // This line you have to add (It consumes the \n character)
System.out.print("Text1: ");
String text1 = input.nextLine();
System.out.print("Text2: ");
String text2 = input.nextLine();
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-29 06:57:36
To dlatego, że po wpisaniu liczby naciśnij Enter, input.nextInt()
zużywa tylko liczbę, a nie "koniec linii". Gdy input.nextLine()
zostanie uruchomiony, "koniec linii" będzie nadal w buforze od pierwszego wejścia.
Zamiast tego użyj input.nextLine()
natychmiast po input.nextInt()
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-14 12:25:35
Wydaje się być wiele pytań na ten temat z java.util.Scanner
. Myślę, że bardziej czytelnym / idiomatycznym rozwiązaniem byłoby wywołanie scanner.skip("[\r\n]+")
, aby zrzucić znaki nowej linii po wywołaniu nextInt()
.
EDIT: jak @PatrickParker zauważył poniżej, spowoduje to nieskończoną pętlę, jeśli użytkownik wprowadzi białe znaki po numerze. Zobacz ich odpowiedź, aby uzyskać lepszy wzór do użycia z pominięciem: https://stackoverflow.com/a/42471816/143585
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:41
Robi to, ponieważ input.nextInt();
nie przechwytuje nowej linii. możesz zrobić tak jak inne proponowane przez dodanie input.nextLine();
pod spodem.
Alternatywnie możesz to zrobić w stylu C# i przetworzyć następną linię do liczby całkowitej w następujący sposób:
int number = Integer.parseInt(input.nextLine());
To działa równie dobrze, i oszczędza Ci wiersz kodu.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-23 22:01:23
Rzeczy, które musisz wiedzieć:
-
Tekst, który reprezentuje kilka wierszy, zawiera również znaki niedrukowalne między wierszami (nazywamy je separatorami linii), takie jak
- carriage return (CR - w literałach łańcuchowych reprezentowanych jako
"\r"
) - line feed (LF - w literałach łańcuchowych reprezentowanych jako
"\n"
)
- carriage return (CR - w literałach łańcuchowych reprezentowanych jako
-
Kiedy czytasz dane z konsoli, pozwala to użytkownikowi na wpisanie odpowiedzi, a po jej zakończeniu musi jakoś potwierdź ten fakt. Aby to zrobić, użytkownik musi nacisnąć klawisz"enter"/" return " na klawiaturze.
Ważne jest to, że ten klucz oprócz zapewnienia umieszczania danych użytkownika na standardowym wejściu (reprezentowanym przez
System.in
, który jest odczytywany przezScanner
) wysyła po nim również separatory linii zależnych od systemu operacyjnego (jak Dla Windows\r\n
).Więc gdy zapytasz użytkownika o wartość jak
age
, i typ użytkownika 42 i naciśnie enter, standardowe wejście będzie zawierać"42\r\n"
.
Problem
Scanner#nextInt
(i inne Scanner#nextType
metody) nie pozwalają skanerowi na zużywanie tych separatorów linii. Odczyta je z System.in
(skąd inaczej Skaner wiedziałby, że nie ma więcej cyfr od użytkownika, które reprezentują wartość age
niż białe znaki?), które usunie je ze standardowego wejścia, ale będzie również buforować te separatory linii wewnętrznie. Musimy pamiętać, że wszystkie metody skanowania są zawsze skanowanie począwszy od tekstu w pamięci podręcznej.
Teraz Scanner#nextLine()
po prostu zbiera i zwraca wszystkie znaki , dopóki nie znajdzie separatorów linii (lub końca strumienia). Ponieważ jednak separatory linii po odczytaniu numeru z konsoli znajdują się bezpośrednio w pamięci podręcznej skanera, zwraca pusty łańcuch, co oznacza, że skaner nie był w stanie znaleźć żadnego znaku przed tymi separatorami linii (lub końcem strumienia).
BTW nextLine
również zużywa te separatory liniowe.
Rozwiązanie
Więc jeśli chcesz poprosić o liczbę, a następnie o całą linię, unikając pustego ciągu jako wyniku nextLine
, albo
- użyj separatora linii pozostawionego przez
nextInt
z pamięci podręcznej skanerów przez- wywołanie
nextLine
, - lub przez wywołanie
skip("\\R")
aby skaner pominął część dopasowaną przez\R
, która reprezentuje separator linii (więcej informacji o\R
: https://stackoverflow.com/a/31060125 )
- wywołanie
- nie używaj
nextInt
(aninext
, ani żadnychnextTYPE
metod) w ogóle. Zamiast tego odczytaj całe dane linia po linii za pomocąnextLine
i parsuj liczby z każdej linii (zakładając, że jedna linia zawiera tylko jedną liczbę) do odpowiedniego typu, takiego jakint
poprzezInteger.parseInt
.
BTW: Scanner#nextType
metody mogą pomijać ograniczniki (domyślnie wszystkie białe spacje, takie jak tabulatory, separatory linii) łącznie z tymi buforowanymi przez skaner, dopóki nie znajdą następnej wartości nie-ogranicznika (token). Dzięki temu za wprowadzenie kodu "42\r\n\r\n321\r\n\r\n\r\nfoobar"
int num1 = sc.nextInt();
int num2 = sc.nextInt();
String name = sc.next();
Będzie w stanie prawidłowo przypisać num1=42
num2=321
name=foobar
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-15 16:29:11
Zamiast input.nextLine()
Użyj input.next()
, to powinno rozwiązać problem.
Zmodyfikowany kod:
public static Scanner input = new Scanner(System.in);
public static void main(String[] args)
{
System.out.print("Insert a number: ");
int number = input.nextInt();
System.out.print("Text1: ");
String text1 = input.next();
System.out.print("Text2: ");
String text2 = input.next();
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-23 10:31:22
Aby uniknąć problemu, użyj nextLine();
natychmiast po nextInt();
, ponieważ pomaga to w wyczyszczeniu bufora. Po naciśnięciu ENTER
nextInt();
nie wychwytuje nowej linii, a tym samym pomija kod Scanner
później.
Scanner scanner = new Scanner(System.in);
int option = scanner.nextInt();
scanner.nextLine(); //clearing the buffer
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-17 00:51:29
Jeśli chcesz szybko przeskanować dane wejściowe bez pomyłki w metodzie Scanner class nextLine (), Użyj dla niej niestandardowego skanera wejściowego .
Kod:
class ScanReader {
/**
* @author Nikunj Khokhar
*/
private byte[] buf = new byte[4 * 1024];
private int index;
private BufferedInputStream in;
private int total;
public ScanReader(InputStream inputStream) {
in = new BufferedInputStream(inputStream);
}
private int scan() throws IOException {
if (index >= total) {
index = 0;
total = in.read(buf);
if (total <= 0) return -1;
}
return buf[index++];
}
public char scanChar(){
int c=scan();
while (isWhiteSpace(c))c=scan();
return (char)c;
}
public int scanInt() throws IOException {
int integer = 0;
int n = scan();
while (isWhiteSpace(n)) n = scan();
int neg = 1;
if (n == '-') {
neg = -1;
n = scan();
}
while (!isWhiteSpace(n)) {
if (n >= '0' && n <= '9') {
integer *= 10;
integer += n - '0';
n = scan();
}
}
return neg * integer;
}
public String scanString() throws IOException {
int c = scan();
while (isWhiteSpace(c)) c = scan();
StringBuilder res = new StringBuilder();
do {
res.appendCodePoint(c);
c = scan();
} while (!isWhiteSpace(c));
return res.toString();
}
private boolean isWhiteSpace(int n) {
if (n == ' ' || n == '\n' || n == '\r' || n == '\t' || n == -1) return true;
else return false;
}
public long scanLong() throws IOException {
long integer = 0;
int n = scan();
while (isWhiteSpace(n)) n = scan();
int neg = 1;
if (n == '-') {
neg = -1;
n = scan();
}
while (!isWhiteSpace(n)) {
if (n >= '0' && n <= '9') {
integer *= 10;
integer += n - '0';
n = scan();
}
}
return neg * integer;
}
public void scanLong(long[] A) throws IOException {
for (int i = 0; i < A.length; i++) A[i] = scanLong();
}
public void scanInt(int[] A) throws IOException {
for (int i = 0; i < A.length; i++) A[i] = scanInt();
}
public double scanDouble() throws IOException {
int c = scan();
while (isWhiteSpace(c)) c = scan();
int sgn = 1;
if (c == '-') {
sgn = -1;
c = scan();
}
double res = 0;
while (!isWhiteSpace(c) && c != '.') {
if (c == 'e' || c == 'E') {
return res * Math.pow(10, scanInt());
}
res *= 10;
res += c - '0';
c = scan();
}
if (c == '.') {
c = scan();
double m = 1;
while (!isWhiteSpace(c)) {
if (c == 'e' || c == 'E') {
return res * Math.pow(10, scanInt());
}
m /= 10;
res += (c - '0') * m;
c = scan();
}
}
return res * sgn;
}
}
Zalety:
- skanuje wejście szybciej niż BufferReader
- Zmniejsza Złożoność Czasu
- spłukuje bufor dla każdego następnego wejścia
Metody:
- scanChar () - skanowanie pojedynczego znaku
- scanInt () - wartość całkowita skanowania
- scanLong () - Scan Long wartość
- scanString () - scan String value
- scanDouble () - Skanuj podwójną wartość
- scanInt(int [] array) - scans complete Array (Integer)
- scanLong ( long [] array) - skanuje kompletną tablicę (Long)
Użycie:
- skopiuj podany kod poniżej kodu java.
- Initialise obiekt dla podanej klasy
ScanReader sc = new ScanReader(System.in);
3. Import niezbędnych klas :
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
4. Throw IOException from your main method to handle Exception
5. Użyj Podanych Metod.
6. Enjoy
Przykład:
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
class Main{
public static void main(String... as) throws IOException{
ScanReader sc = new ScanReader(System.in);
int a=sc.scanInt();
System.out.println(a);
}
}
class ScanReader....
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-16 08:12:55
Jeśli chcesz odczytać zarówno ciągi znaków, jak i ints, rozwiązaniem jest użycie dwóch skanerów:
Scanner stringScanner = new Scanner(System.in);
Scanner intScanner = new Scanner(System.in);
intScanner.nextInt();
String s = stringScanner.nextLine(); // unaffected by previous nextInt()
System.out.println(s);
intScanner.close();
stringScanner.close();
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-20 18:52:41
sc.nextLine()
jest lepszy w porównaniu do parsowania danych wejściowych.
Ponieważ wydajność wise to będzie dobre.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-14 10:45:34
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int i = scan.nextInt();
scan.nextLine();
double d = scan.nextDouble();
scan.nextLine();
String s = scan.nextLine();
System.out.println("String: " + s);
System.out.println("Double: " + d);
System.out.println("Int: " + i);
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-30 03:48:25
Moje testy dały takie same wyniki jak Prine, jednak pomyślałem o dość prostym obejściu:
Użycie BufferedReader#nextLine()
, gdzie można Scanner#readLine()
, pozwala uniknąć tego błędu. Możesz nawet napisać własne opakowanie skanera, aby zastąpić funkcję readLine skanera za pomocą funkcji BufferedReader nextLine.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-24 00:23:40
Chyba jestem spóźniony na imprezę..
Jak wcześniej wspomniano, wywołanie {[1] } po otrzymaniu wartości int rozwiąże problem. Powodem, dla którego twój kod nie działał, było to, że nie było nic innego do przechowywania z twojego wejścia (gdzie wprowadziłeś int) do string1
. Rzucę trochę więcej światła na cały temat.
Rozważmy nextline () jako nieparzystą spośród metod nextFoo() w klasie skanera. Weźmy szybki przykład.. Załóżmy, że mamy dwie linie kodu, takie jak te poniżej:
int firstNumber = input.nextInt();
int secondNumber = input.nextInt();
Jeśli wprowadzimy wartość poniżej (jako pojedynczy wiersz wejścia)
54 234
Wartość naszej zmiennej firstNumber
i secondNumber
wynosi odpowiednio 54 i 234. Powodem, dla którego to działa w ten sposób jest to, że nowy kanał linii ( tj.) nie jest generowane automatycznie, gdy metoda nextInt() przyjmuje wartości. Po prostu trwa "next int" i idzie dalej. To jest taka sama dla pozostałych metod nextfoo () z wyjątkiem nextline ().
NextLine () generuje nowy kanał linii natychmiast po pobraniu wartości; to właśnie @RohitJain ma na myśli mówiąc, że nowy kanał linii jest "zużyty".
Wreszcie, metoda next () po prostu pobiera najbliższy Ciąg BEZ generowania nowej linii; to sprawia, że jest to preferencyjna metoda pobierania oddzielnych ciągów w obrębie tej samej pojedynczej linii.
Mam nadzieję, że to pomoże.. Wesołego kodowania!Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-07 10:40:26
Dlaczego nie użyć nowego skanera do każdego odczytu? Jak poniżej. Dzięki takiemu podejściu nie skonfrontujesz się ze swoim problemem.
int i = new Scanner(System.in).nextInt();
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-13 11:06:54