Saya menggunakan Scanner
metode nextInt()
dan nextLine()
untuk membaca input.
Ini terlihat seperti ini:
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)
Masalahnya adalah bahwa setelah memasukkan nilai numerik, yang pertama input.nextLine()
dilewati dan yang kedua input.nextLine()
dieksekusi, sehingga output saya terlihat seperti ini:
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
Saya menguji aplikasi saya dan sepertinya masalahnya terletak pada penggunaannya input.nextInt()
. Jika saya menghapusnya, maka keduanya string1 = input.nextLine()
dan string2 = input.nextLine()
dieksekusi seperti yang saya inginkan.
java
io
java.util.scanner
blekione
sumber
sumber
Jawaban:
Itu karena
Scanner.nextInt
metode ini tidak membaca karakter baris baru di input Anda yang dibuat dengan menekan "Enter," dan panggilan untukScanner.nextLine
kembali setelah membaca baris baru itu .Anda akan menemukan perilaku serupa ketika Anda menggunakan
Scanner.nextLine
setelahScanner.next()
atauScanner.nextFoo
metode apa pun (kecualinextLine
dirinya sendiri).Penanganan masalah:
Baik melakukan
Scanner.nextLine
panggilan setelah masingScanner.nextInt
- masing atauScanner.nextFoo
untuk mengkonsumsi sisa baris itu termasuk baris baruAtau, lebih baik lagi, baca input melalui
Scanner.nextLine
dan konversi input Anda ke format yang tepat yang Anda butuhkan. Misalnya, Anda dapat mengonversi ke integer menggunakanInteger.parseInt(String)
metode.sumber
try-catch
, karenaInteger.parseInt
melemparNumberFormatException
ketika argumen yang tidak valid diteruskan ke sana. Anda akan belajar tentang pengecualian nanti. Untuk EG: -Integer.parseInt("abc")
. Anda tidak ingin "abc" dikonversi menjadi int, bukan?Scanner#hasNextFoo
cek sebelumnya daripada try-catch, tetapi itu juga berhasil.Masalahnya adalah dengan metode input.nextInt () - hanya membaca nilai int. Jadi ketika Anda melanjutkan membaca dengan input.nextLine () Anda menerima tombol Enter "\ n". Jadi untuk melewati ini, Anda harus menambahkan input.nextLine () . Semoga ini harus jelas sekarang.
Cobalah seperti itu:
sumber
nextLine
, tapi saya masih perlu penjelasan tentang perilaku iniItu karena ketika Anda memasukkan nomor lalu tekan Enter,
input.nextInt()
hanya mengkonsumsi nomor, bukan "ujung jalur". Ketikainput.nextLine()
dijalankan, ia mengkonsumsi "end of line" yang masih ada di buffer dari input pertama.Sebagai gantinya, gunakan
input.nextLine()
segera setelahnyainput.nextInt()
sumber
Tampaknya ada banyak pertanyaan tentang masalah ini
java.util.Scanner
. Saya pikir solusi yang lebih mudah dibaca / idiomatis adalah meneleponscanner.skip("[\r\n]+")
untuk menjatuhkan karakter baris baru setelah meneleponnextInt()
.EDIT: seperti yang dicatat oleh @PatrickParker di bawah ini, ini akan menyebabkan loop tak terbatas jika pengguna memasukkan spasi kosong setelah nomor. Lihat jawaban mereka untuk pola yang lebih baik untuk digunakan dengan lewati: https://stackoverflow.com/a/42471816/143585
sumber
Itu karena
input.nextInt();
tidak menangkap baris baru. Anda dapat melakukan seperti yang lain yang diusulkan dengan menambahkan diinput.nextLine();
bawahnya.Atau Anda dapat melakukannya dengan gaya C # dan mem-parsing nextLine ke integer seperti:
Melakukan ini juga berfungsi dengan baik, dan itu akan menyelamatkan Anda satu baris kode.
sumber
TL; DR Gunakan
scanner.skip("\\R")
sebelum setiapscanner.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
"\r"
)"\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 dibacaScanner
) 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
, baiknextInt
cache Pemindai olehnextLine
,skip("\\R")
atauskip("\r\n|\r|\n")
membiarkan Pemindai melewati bagian yang cocok dengan pemisah baris (info lebih lanjut tentang\R
: https://stackoverflow.com/a/31060125 )nextInt
(ataunext
, atau apa punnextTYPE
metode ) sama sekali. Alih-alih membaca seluruh data baris demi baris menggunakannextLine
dan mengurai angka dari setiap baris (dengan asumsi satu baris hanya berisi satu angka) ke tipe yang tepat sepertiint
viaInteger.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"
kodeakan dapat menetapkan dengan benar
num1=42
num2=321
name=foobar
.sumber
Alih-alih
input.nextLine()
digunakaninput.next()
, itu seharusnya memecahkan masalah.Kode yang dimodifikasi:
sumber
Jika Anda ingin membaca string dan int, solusinya adalah menggunakan dua Pemindai:
sumber
scanner.nextLine()
harus bekerja.Jika Anda ingin memindai input dengan cepat tanpa bingung dengan metode kelas Scanner nextLine (), Gunakan Custom Input Scanner untuk itu.
Kode:
Keuntungan :
Metode:
Penggunaan:
ScanReader sc = new ScanReader(System.in);
3. Impor Kelas yang diperlukan:import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream;
4. Lempar IOException dari metode utama Anda untuk menangani Pengecualian 5. Gunakan Metode yang Disediakan. 6. NikmatiContoh:
sumber
Untuk menghindari masalah, gunakan
nextLine();
segera setelahnextInt();
karena membantu dalam membersihkan buffer. Ketika Anda menekanENTER
tombolnextInt();
tidak menangkap baris baru dan karenanya, melewatkanScanner
kode nanti.sumber
sc.nextLine()
lebih baik dibandingkan dengan parsing input. Karena kinerja bijaksana itu akan bagus.sumber
Saya kira saya sangat terlambat ke pesta ..
Seperti yang dinyatakan sebelumnya, menelepon
input.nextLine()
setelah mendapatkan nilai int Anda akan menyelesaikan masalah Anda. Alasan mengapa kode Anda tidak berfungsi adalah karena tidak ada lagi yang dapat disimpan dari input Anda (tempat Anda memasukkan int)string1
. Saya hanya akan memberi sedikit lebih banyak cahaya untuk seluruh topik.Pertimbangkan nextLine () sebagai yang aneh di antara metode nextFoo () di kelas Scanner. Mari kita ambil contoh cepat .. Katakanlah kita memiliki dua baris kode seperti di bawah ini:
Jika kita memasukkan nilai di bawah ini (sebagai satu baris input)
Nilai variabel kami
firstNumber
dansecondNumber
menjadi 54 dan 234 masing-masing. Alasan mengapa ini bekerja seperti ini adalah karena umpan baris baru ( yaitu \ n ) TIDAK secara otomatis dihasilkan ketika metode nextInt () mengambil nilai-nilai. Ini hanya membutuhkan "int berikutnya" dan bergerak. Ini sama untuk sisa metode nextFoo () kecuali nextLine ().nextLine () menghasilkan umpan baris baru segera setelah mengambil nilai; inilah yang dimaksud @RohitJain dengan mengatakan bahwa umpan baris baru "dikonsumsi".
Terakhir, metode next () hanya mengambil String terdekat tanpa menghasilkan baris baru; ini menjadikan ini metode preferensial untuk mengambil String terpisah dalam satu baris yang sama.
Saya harap ini membantu .. Selamat coding!
sumber
Gunakan 2 objek pemindai bukan satu
sumber
sumber
jika saya mengharapkan input yang tidak kosong
digunakan dalam contoh di atas:
sumber
Di salah satu usecase saya, saya memiliki skenario membaca nilai string yang didahului oleh beberapa nilai integer . Saya harus menggunakan loop " for / while " untuk membaca nilai-nilai. Dan tidak ada saran di atas yang berfungsi dalam kasus ini.
Menggunakan
input.next()
alih-alihinput.nextLine()
memperbaiki masalah. Semoga ini bisa bermanfaat bagi mereka yang berurusan dengan skenario serupa.sumber
Gunakan kode ini untuk memperbaiki masalah Anda.
sumber
Karena
nextXXX()
metode tidak membacanewline
, kecualinextLine()
. Kita dapat melewatkannewline
setelah membacanon-string
nilai apa pun (int
dalam hal ini) dengan menggunakanscanner.skip()
seperti di bawah ini:sumber
Mengapa tidak menggunakan Scanner baru untuk setiap bacaan? Seperti di bawah ini. Dengan pendekatan ini Anda tidak akan menghadapi masalah Anda.
sumber
Scanner
untuk mencegah kebocoran memori. Membuang-buang waktu?nextInt()
tidak akan mengkonsumsi baris baru, terlepas dari apakah itu dalam "baru"Scanner
atau yang sudah digunakan.