Korzystam z Scanner
metod nextInt()
i nextLine()
do odczytu danych wejściowych.
To wygląda 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 wprowadzeniu wartości liczbowej pierwsza input.nextLine()
jest pomijana, a druga input.nextLine()
wykonywana, dzięki czemu moje dane wyjściowe wyglądają następująco:
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 polega na użyciu input.nextInt()
. Gdybym go usunąć, a następnie oba string1 = input.nextLine()
i string2 = input.nextLine()
są wykonywane jak chcę je mieć.
java
io
java.util.scanner
blekione
źródło
źródło
Odpowiedzi:
Jest tak, ponieważ
Scanner.nextInt
metoda nie odczytuje znaku nowego wiersza w danych wejściowych utworzonych przez naciśnięcie klawisza „Enter”, a więc wywołanieScanner.nextLine
powrotu po przeczytaniu tego nowego wiersza .Będzie można napotkać podobne zachowanie podczas korzystania
Scanner.nextLine
poScanner.next()
lub dowolnyScanner.nextFoo
sposób (oprócznextLine
siebie).Obejście:
Albo umieścić
Scanner.nextLine
połączenia po każdymScanner.nextInt
lubScanner.nextFoo
zużywają resztę tej linii w tym nowej liniiLub jeszcze lepiej, przeczytaj dane wejściowe
Scanner.nextLine
i przekonwertuj dane wejściowe do odpowiedniego formatu, którego potrzebujesz. Na przykład możesz przekonwertować na liczbę całkowitą za pomocąInteger.parseInt(String)
metody.źródło
try-catch
, ponieważInteger.parseInt
rzuca,NumberFormatException
gdy zostanie przekazany nieprawidłowy argument. Później dowiesz się o wyjątku. Dla EG: -Integer.parseInt("abc")
. Nie chcesz, aby „abc” zostało przekonwertowane na int, prawda?Scanner#hasNextFoo
czek wcześniej niż try-catch, ale to też działa.Problem dotyczy metody input.nextInt () - odczytuje tylko wartość int. Więc kiedy będziesz kontynuować czytanie za pomocą input.nextLine (), otrzymasz klawisz „\ n” Enter. Aby to pominąć, musisz dodać input.nextLine () . Mam nadzieję, że to powinno być teraz jasne.
Spróbuj tak:
źródło
nextLine
, ale wciąż potrzebuję wyjaśnienia tego zachowaniaDzieje się tak dlatego, że po wprowadzeniu liczby, a następnie naciśnięciu Enter,
input.nextInt()
zużywa tylko liczbę, a nie „koniec linii”. Kiedy jestinput.nextLine()
wykonywany, zużywa „koniec linii” nadal w buforze od pierwszego wejścia.Zamiast tego użyj
input.nextLine()
natychmiast poinput.nextInt()
źródło
Wydaje się, że jest wiele pytań na ten temat
java.util.Scanner
. Myślę, że bardziej czytelnym / idiomatycznym rozwiązaniem byłoby wywołanie,scanner.skip("[\r\n]+")
aby usunąć znaki nowej linii po wywołaniunextInt()
.EDYCJA: jak zauważono poniżej @PatrickParker, spowoduje to nieskończoną pętlę, jeśli użytkownik wprowadzi dowolną spację po liczbie. Zobacz ich odpowiedź na lepszy wzór do użycia z pominięciem: https://stackoverflow.com/a/42471816/143585
źródło
Robi to, ponieważ
input.nextInt();
nie przechwytuje nowej linii. możesz zrobić tak, jak inne zaproponowane przez dodanieinput.nextLine();
spodu.Alternatywnie możesz to zrobić w stylu C # i parsować nextLine na liczbę całkowitą w następujący sposób:
Wykonanie tego działa równie dobrze i pozwala zaoszczędzić wiersz kodu.
źródło
TL; DR Użyj
scanner.skip("\\R")
przed każdymscanner.newLine()
połączeniem, które jest wykonywane po:scanner.next()
scanner.next*TYPE*()
metoda.Co musisz wiedzieć:
tekst reprezentujący kilka wierszy zawiera także znaki niedrukowalne między wierszami (nazywamy je separatorami wierszy), jak
"\r"
)"\n"
)kiedy odczytujesz dane z konsoli, użytkownik może wpisać swoją odpowiedź, a kiedy skończy, musi jakoś potwierdzić ten fakt. Aby to zrobić, użytkownik musi nacisnąć klawisz „enter” / „return” na klawiaturze.
Ważne jest to, że ten klucz, oprócz zapewnienia umieszczenia danych użytkownika na standardowym wejściu (reprezentowanym przez,
System.in
który jest czytany przezScanner
), wysyła również\r\n
po nim separatory linii zależne od systemu operacyjnego (jak w przypadku systemu Windows ).Więc kiedy pytasz użytkownika o wartość podobną
age
, a typy użytkowników 42 i prasy wchodzą, standardowe wejście będzie zawierać"42\r\n"
.Problem
Scanner#nextInt
(i inne metody) nie pozwalają Scanner zużywają tych separatorów. Odczyta je (skąd inaczej skaner wiedziałby, że nie ma więcej cyfr od użytkownika, które reprezentują wartość niż stojące przed białymi spacjami?), Co usunie je ze standardowego wejścia, ale również buforuje te separatory linii wewnętrznie . Musimy pamiętać, że wszystkie metody skanera zawsze skanują, zaczynając od buforowanego tekstu.Scanner#nextType
System.in
age
Teraz
Scanner#nextLine()
po prostu zbiera i zwraca wszystkie znaki, aż znajdzie separatory linii (lub koniec strumienia). Ale ponieważ separatory linii po odczytaniu numeru z konsoli znajdują się natychmiast w pamięci podręcznej skanera, zwraca pusty ciąg znaków, co oznacza, że skaner nie był w stanie znaleźć żadnego znaku przed tymi separatorami linii (lub końcem strumienia).BTW zużywa
nextLine
również te separatory linii.Rozwiązanie
Więc jeśli chcesz zapytać o liczbę, a następnie o całą linię, unikając w wyniku tego pustego ciągu znaków
nextLine
, albonextInt
pamięć podręczną skanerów przeznextLine
,skip("\\R")
lubskip("\r\n|\r|\n")
umożliwienie skanerowi pominięcia części dopasowanej przez separator linii (więcej informacji na temat\R
: https://stackoverflow.com/a/31060125 )nextInt
(aninext
żadnychnextTYPE
metod). Zamiast tego należy czytać całe dane linia po linii za pomocąnextLine
i analizować liczby z każdej linii (zakładając, że jedna linia zawiera tylko jedną liczbę) do odpowiedniego typu, np .int
ViaInteger.parseInt
.BTW : metody mogą pomijać separatory (domyślnie wszystkie białe spacje, takie jak tabulatory, separatory linii), w tym te buforowane przez skaner, dopóki nie znajdą następnej wartości innej niż separator (token). Dzięki temu za wprowadzanie jak kod
Scanner#nextType
"42\r\n\r\n321\r\n\r\n\r\nfoobar"
będzie mógł poprawnie przypisać
num1=42
num2=321
name=foobar
.źródło
Zamiast
input.nextLine()
stosowaniainput.next()
, które powinny rozwiązać ten problem.Zmodyfikowany kod:
źródło
Jeśli chcesz odczytać zarówno ciągi, jak i ints, rozwiązaniem jest użycie dwóch skanerów:
źródło
scanner.nextLine()
powinien działać.Jeśli chcesz szybko skanować dane wejściowe bez pomyłek w metodzie klasy NextLine () klasy Scanner, użyj do tego niestandardowego skanera wejściowego.
Kod :
Zalety :
Metody:
Stosowanie :
ScanReader sc = new ScanReader(System.in);
3. Zaimportuj niezbędne klasy:import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream;
4. Rzuć wyjątek IOException od swojej głównej metody obsługi wyjątku 5. Użyj dostarczonych metod. 6. Ciesz sięPrzykład:
źródło
Aby uniknąć tego problemu, użyj
nextLine();
natychmiast po tym,nextInt();
ponieważ pomaga wyczyścić bufor. Po naciśnięciu nie uchwycić nową linię, a więc pomija kod później.ENTER
nextInt();
Scanner
źródło
sc.nextLine()
jest lepszy w porównaniu do analizowania danych wejściowych. Ponieważ pod względem wydajności będzie dobrze.źródło
Chyba spóźniłem się na imprezę ...
Jak już wspomniano, wywołanie
input.nextLine()
po uzyskaniu 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 zapamiętania z danych wejściowych (gdzie wpisałeś int)string1
. Rzucę trochę więcej światła na cały temat.Rozważ nextLine () jako nieparzystą spośród metod nextFoo () w klasie Scanner. Weźmy szybki przykład. Powiedzmy, że mamy dwa wiersze kodu, takie jak poniższe:
Jeśli wprowadzimy wartość poniżej (jako pojedynczy wiersz danych wejściowych)
Wartość naszych
firstNumber
isecondNumber
zmiennych wynosi odpowiednio 54 i 234. Powodem, dla którego działa to w ten sposób, jest to, że nowy wysuw wiersza ( tj. \ N ) NIE JEST generowany automatycznie, gdy metoda nextInt () przyjmuje wartości. Po prostu bierze „next int” i idzie dalej. To samo dotyczy pozostałych metod nextFoo (), z wyjątkiem nextLine ().nextLine () generuje nowy wiersz informacji natychmiast po przyjęciu wartości; to właśnie oznacza @RohitJain, mówiąc, że nowy wiersz jest „zużyty”.
Wreszcie, metoda next () po prostu pobiera najbliższy ciąg bez generowania nowej linii; sprawia to, że jest to preferowana metoda pobierania oddzielnych ciągów znaków w tej samej pojedynczej linii.
Mam nadzieję, że to pomoże .. Wesołego kodowania!
źródło
Użyj 2 obiektów skanera zamiast jednego
źródło
źródło
jeśli oczekuję niepustego wejścia
użyte w powyższym przykładzie:
źródło
W jednym z moich przypadków użycia miałem scenariusz odczytu wartości ciągu poprzedzony kilkoma liczbami całkowitymi . Musiałem użyć „ pętli for / while ”, aby odczytać wartości. I żadna z powyższych sugestii nie zadziałała w tym przypadku.
Używanie
input.next()
zamiastinput.nextLine()
naprawionego problemu. Mam nadzieję, że może to być pomocne dla osób zajmujących się podobnym scenariuszem.źródło
Użyj tego kodu, aby rozwiązać problem.
źródło
Ponieważ
nextXXX()
metody nie czytająnewline
, z wyjątkiemnextLine()
. Możemy pominąćnewline
po odczytaniu dowolnejnon-string
wartości (int
w tym przypadku), wykonującscanner.skip()
następujące czynności:źródło
Dlaczego nie użyć nowego skanera do każdego czytania? Jak poniżej Dzięki takiemu podejściu nie będziesz mieć do czynienia z problemem.
źródło
Scanner
aby zapobiec wyciekom pamięci. Marnowanie czasu?nextInt()
nie zużyje nowego wiersza, niezależnie od tego, czy znajduje się w „nowym”,Scanner
czy już używanym.