TL; DR Gunakan scanner.skip("\\R")
sebelum setiap scanner.newLine()
panggilan, yang dieksekusi setelah:
scanner.next()
scanner.next*TYPE*()
metode.
Hal-hal yang perlu Anda ketahui:
teks yang mewakili beberapa baris juga mengandung karakter yang tidak dapat dicetak antar baris (kami menyebutnya pemisah baris) seperti
- carriage return (CR - dalam String literals diwakili sebagai
"\r"
)
- umpan baris (LF - dalam String literals diwakili sebagai
"\n"
)
ketika Anda membaca data dari konsol, memungkinkan pengguna untuk mengetik jawabannya dan ketika dia selesai dia perlu entah bagaimana mengkonfirmasi fakta itu. Untuk melakukannya, pengguna harus menekan tombol "enter" / "return" pada keyboard.
Yang penting adalah bahwa kunci ini selain memastikan menempatkan data pengguna ke input standar (diwakili oleh System.in
yang dibaca Scanner
) juga mengirimkan pemisah baris yang tergantung OS (seperti untuk Windows \r\n
) setelahnya.
Jadi, ketika Anda meminta nilai dari pengguna age
, dan tipe pengguna 42 dan menekan enter, input standar akan berisi "42\r\n"
.
Masalah
Scanner#nextInt
(dan metode lainnya ) tidak memungkinkan Pemindai untuk mengkonsumsi pemisah garis ini. Ini akan membacanya dari (bagaimana lagi Pemindai akan tahu bahwa tidak ada lebih banyak digit dari pengguna yang mewakili nilai daripada menghadap spasi?) Yang akan menghapusnya dari input standar, tetapi juga akan menembolok pemisah garis tersebut secara internal . Yang perlu kita ingat, adalah bahwa semua metode Pemindai selalu memindai mulai dari teks yang di-cache. Scanner#nextType
System.in
age
Sekarang Scanner#nextLine()
cukup kumpulkan dan kembalikan semua karakter hingga menemukan pemisah garis (atau akhir aliran). Tetapi karena pemisah garis setelah membaca angka dari konsol ditemukan langsung di cache Pemindai, itu mengembalikan String kosong, yang berarti bahwa Pemindai tidak dapat menemukan karakter apa pun sebelum pemisah garis tersebut (atau ujung aliran).
BTW nextLine
juga mengkonsumsi pemisah garis tersebut.
Larutan
Jadi ketika Anda ingin meminta nomor dan kemudian untuk seluruh baris sambil menghindari string kosong sebagai akibatnya nextLine
, baik
- mengkonsumsi pemisah baris yang ditinggalkan oleh
nextInt
cache Pemindai oleh
- memanggil
nextLine
,
- atau IMO lebih mudah dibaca cara yang adalah dengan menelepon
skip("\\R")
atau skip("\r\n|\r|\n")
membiarkan Pemindai melewati bagian yang cocok dengan pemisah baris (info lebih lanjut tentang \R
: https://stackoverflow.com/a/31060125 )
- jangan gunakan
nextInt
(atau next
, atau apa punnextTYPE
metode ) sama sekali. Alih-alih membaca seluruh data baris demi baris menggunakan nextLine
dan mengurai angka dari setiap baris (dengan asumsi satu baris hanya berisi satu angka) ke tipe yang tepat seperti int
via Integer.parseInt
.
BTW :Scanner#nextType
metode dapat melewati pembatas (secara default semua spasi putih seperti tab, pemisah baris) termasuk yang di-cache oleh pemindai, sampai mereka akan menemukan nilai non-pembatas berikutnya (token). Berkat itu untuk input seperti "42\r\n\r\n321\r\n\r\n\r\nfoobar"
kode
int num1 = sc.nextInt();
int num2 = sc.nextInt();
String name = sc.next();
akan dapat menetapkan dengan benar num1=42
num2=321
name=foobar
.