เครื่องสแกนกำลังข้าม nextLine () หลังจากใช้ next () หรือ nextFoo ()?


684

ฉันใช้ScannerวิธีการnextInt()และnextLine()การอ่านอินพุต

ดูเหมือนว่านี้:

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)

ปัญหาคือหลังจากป้อนค่าตัวเลขตัวแรกinput.nextLine()จะถูกข้ามและตัวที่สองinput.nextLine()จะถูกดำเนินการเพื่อให้ผลลัพธ์ของฉันเป็นดังนี้:

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

input.nextInt()ผมทดสอบใบสมัครของฉันและดูเหมือนว่าปัญหาอยู่ในการใช้ ถ้าฉันลบมันแล้วทั้งสองstring1 = input.nextLine()และstring2 = input.nextLine()จะถูกดำเนินการตามที่ฉันต้องการ


5
หรือคุณอาจเป็นเหมือนฉันและใช้ BufferedReader :) ฉันไม่สนหรอกว่ามันเป็นโรงเรียนเก่ามันใช้ได้เสมอและจะใช้ได้ผลเสมอสำหรับฉัน นอกจากนี้ความรู้ของ BufferedReader มีแอปพลิเคชันอื่น ฉันไม่ชอบสแกนเนอร์
Cruncher

คำตอบ:


831

นั่นเป็นเพราะScanner.nextIntวิธีการที่ไม่ได้อ่านบรรทัดใหม่ตัวละครในการป้อนข้อมูลของคุณที่สร้างโดยการกดปุ่ม "Enter" และเพื่อให้การเรียกร้องให้Scanner.nextLineผลตอบแทนหลังจากที่ได้อ่านว่าการขึ้นบรรทัดใหม่

คุณจะพบพฤติกรรมที่คล้ายกันเมื่อคุณใช้Scanner.nextLineหลังจากScanner.next()หรือScanner.nextFooวิธีการใด ๆ(ยกเว้นnextLineตัวเอง)

การแก้ปัญหา:

  • ทั้งวางScanner.nextLineสายหลังจากที่แต่ละคนScanner.nextIntหรือScanner.nextFooเพื่อใช้ส่วนที่เหลือของสายนั้นรวมถึงการขึ้นบรรทัดใหม่

    int option = input.nextInt();
    input.nextLine();  // Consume newline left-over
    String str1 = input.nextLine();
    
  • หรือดียิ่งขึ้นอ่านอินพุตScanner.nextLineและแปลงอินพุตเป็นรูปแบบที่เหมาะสมที่คุณต้องการ ตัวอย่างเช่นคุณอาจแปลงเป็นจำนวนเต็มโดยใช้Integer.parseInt(String)วิธีการ

    int option = 0;
    try {
        option = Integer.parseInt(input.nextLine());
    } catch (NumberFormatException e) {
        e.printStackTrace();
    }
    String str1 = input.nextLine();
    

4
@blekione คุณต้องใช้try-catchเพราะInteger.parseIntพ่นNumberFormatExceptionเมื่ออาร์กิวเมนต์ที่ไม่ถูกต้องถูกส่งผ่านไป คุณจะได้เรียนรู้เกี่ยวกับข้อยกเว้นในภายหลัง สำหรับเช่น: Integer.parseInt("abc")- คุณไม่ต้องการให้ "abc" แปลงเป็น int ใช่ไหม
Rohit Jain

3
@blekione ดังนั้นในกรณีข้างต้นรหัสของคุณจะหยุด ณ จุดนั้นและคุณจะไม่สามารถดำเนินการต่อได้ ด้วยการจัดการข้อยกเว้นคุณสามารถจัดการกับเงื่อนไขดังกล่าวได้
Rohit Jain

4
ในระดับไหนดีกว่ากัน? สแกนเนอร์ AFAIK # nextInt () เป็นวิธีที่ผ่อนปรนมากขึ้นในการค้นหา ints ที่ถูกต้องโดยการอนุญาตให้ใช้เครื่องหมายจุลภาคและคำนำหน้ากลุ่มสถานที่และคำต่อท้าย จำนวนเต็ม # parseInt () อนุญาตให้ใช้ตัวเลขและจุดทศนิยมเพียงเครื่องหมายบวกเท่านั้น
Mordechai

5
ฉันชอบScanner#hasNextFooเช็คก่อนเป็นการส่วนตัวมากกว่าลองดู แต่ก็ใช้ได้เหมือนกัน
MildlyMilquetoast

1
ใช้ ParseDouble มีปัญหาใหม่นั่นคือถัดไปสองใช้การกำหนดค่าภูมิภาคของทศนิยม (. หรือ,) แต่ Parsedouble ได้รับ US decimal (.) เสมอ
olmerg

209

ปัญหาเกิดขึ้นกับเมธอด input.nextInt () - เพียงแค่อ่านค่า int ดังนั้นเมื่อคุณอ่านต่อด้วย input.nextLine () คุณจะได้รับปุ่ม "\ n" ดังนั้นเพื่อข้ามไปนี้คุณจะต้องเพิ่มinput.nextLine () หวังว่าตอนนี้น่าจะชัดเจนแล้ว

ลองแบบว่า:

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();

umm ดูเหมือนจะเป็นวิธีแก้ปัญหาทำให้การข้ามบรรทัดไม่ได้ใช้nextLineแต่ฉันยังต้องการคำอธิบายเกี่ยวกับพฤติกรรมนี้
Eng.Fouad

2
FYI: ผสานจากstackoverflow.com/questions/7056749/…
Shog9

คำถาม: ถามวันที่ 27 ตุลาคม 2555 เวลา 16:37 น. ตอบ 14 สิงหาคม '11 ที่ 12:24 สิ่งนี้เป็นไปได้ยังไง
Apoorv Patne

79

มันเป็นเพราะเมื่อคุณใส่ตัวเลขแล้วกดEnter, input.nextInt()กินเพียงจำนวนไม่ "ปลายสาย" เมื่อinput.nextLine()เรียกใช้งานจะสิ้นเปลือง "end of line" ในบัฟเฟอร์จากอินพุตแรก

ให้ใช้input.nextLine()ทันทีหลังจากinput.nextInt()


7
@Victor ไม่ใช่ข้อผิดพลาด มันทำงานตามที่ระบุไว้ คุณสามารถโต้เถียงได้ว่าควรมีวิธีที่ง่ายในการบอก api ให้ใช้พื้นที่ว่างใด ๆ ต่อจากอินพุตเป้าหมาย
โบฮีเมียน

ฉันเห็น. ขอบคุณ @ โบฮีเมียนนั่นคือสิ่งที่ฉันโต้เถียง ฉันคิดว่าควรเปลี่ยนสิ่งนี้บางทีคุณสามารถชี้ให้ฉันได้ว่าจะแนะนำปัญหานี้ใน JCP ถัดไปได้ที่ไหน
วิกเตอร์

@victor คุณสามารถขอใช้ (และหาวิธีที่จะมีส่วนร่วมในรหัส) คุณสมบัติผ่านทางรายงานข้อบกพร่องหรือขอคุณลักษณะหน้า
ภาษาโบฮีเมียน

FYI: ผสานจากstackoverflow.com/questions/7056749/…
Shog9

48

java.util.Scannerดูเหมือนจะมีคำถามมากมายเกี่ยวกับเรื่องนี้ด้วย ผมคิดว่าการแก้ปัญหาการอ่านได้มากขึ้น / สำนวนจะโทรscanner.skip("[\r\n]+")จะลดลงอักขระขึ้นบรรทัดใหม่ใด ๆ nextInt()หลังจากที่โทร

แก้ไข: ตามที่ @PatrickParker บันทึกไว้ด้านล่างนี้จะทำให้เกิดการวนรอบไม่สิ้นสุดหากผู้ใช้ป้อนช่องว่างใด ๆ หลังจากหมายเลข ดูคำตอบสำหรับรูปแบบที่ดีกว่าสำหรับใช้กับการข้าม: https://stackoverflow.com/a/42471816/143585


FYI: ผสานจากstackoverflow.com/questions/7056749/…
Shog9

ฉันรู้ว่าสิ่งที่เราทำเพื่อลบข้อมูลในบัฟเฟอร์ แต่กรณีนี้โปรดช่วยฉันด้วยนี้: stackoverflow.com/questions/33585314/having-issues-with-scanner
Khuong

1
FYI สิ่งนี้จะทำให้เกิดการวนซ้ำไม่สิ้นสุดคือผู้ใช้พิมพ์แท็บหรือช่องว่างใด ๆ หลังจากป้อนตัวเลข ดูคำตอบของฉันที่นี่เพื่อข้ามดีกว่า: stackoverflow.com/a/42471816/7098259
Patrick Parker

@PatrickParker: มันทำให้เกิดการวนซ้ำไม่สิ้นสุด! ขอขอบคุณแก้ไขคำตอบเพื่อลิงก์กับคุณ
Denis Tulskiy

33

มันเป็นเพราะinput.nextInt();ไม่ได้ขึ้นบรรทัดใหม่ คุณสามารถทำเหมือนคนอื่น ๆ ที่เสนอโดยการเพิ่มinput.nextLine();ภายใต้
อีกทางเลือกหนึ่งคุณสามารถทำมันในลักษณะ C # และแยกบรรทัดถัดไปเป็นจำนวนเต็มดังนี้:

int number = Integer.parseInt(input.nextLine()); 

การทำเช่นนี้จะทำงานได้ดีเช่นกันและช่วยให้คุณประหยัดบรรทัดของรหัส


FYI: ผสานจากstackoverflow.com/questions/7056749/…
Shog9

1
คุณต้องใช้ลองจับที่นี่ จะเกิดอะไรขึ้นถ้าอินพุตไม่ใช่ตัวเลข ต้องจัดการ NumberFormatException ที่นี่
Arundev

นี่จะถือว่ามีโทเค็น int เพียงอันเดียวในแต่ละบรรทัดที่คุณลองใช้
เซเล่โพ

25

TL; DR ใช้scanner.skip("\\R")ก่อนการscanner.newLine()โทรแต่ละครั้งซึ่งจะดำเนินการหลังจาก:

  • scanner.next()
  • scanner.next*TYPE*() วิธี.

สิ่งที่คุณต้องรู้

  • ข้อความที่แสดงถึงไม่กี่บรรทัดยังมีอักขระที่ไม่สามารถพิมพ์ได้ระหว่างบรรทัด (เช่นเราเรียกว่าตัวคั่นบรรทัด)

    • carriage return (CR - เป็นตัวอักษรสตริงที่แทนด้วย"\r")
    • การป้อนบรรทัด (LF - เป็นตัวอักษรสตริงที่แทนด้วย"\n")
  • เมื่อคุณกำลังอ่านข้อมูลจากคอนโซลจะช่วยให้ผู้ใช้สามารถพิมพ์คำตอบของเขาและเมื่อเขาจะทำเขาต้องอย่างใดยืนยันความจริงที่ว่า หากต้องการทำเช่นนั้นผู้ใช้จะต้องกดปุ่ม "Enter" / "return" บนคีย์บอร์ด

    สิ่งสำคัญคือกุญแจนี้อยู่ข้างๆเพื่อให้แน่ใจว่าการวางข้อมูลผู้ใช้ไปยังอินพุตมาตรฐาน (แสดงโดยSystem.inที่อ่านโดยScanner) ยังส่งตัวแยกบรรทัดขึ้นอยู่กับระบบปฏิบัติการ (เช่นสำหรับ Windows \r\n) หลังจากนั้น

    ดังนั้นเมื่อคุณขอให้ผู้ใช้สำหรับค่าเหมือนageและประเภทผู้ใช้ 42 "42\r\n"และเครื่องรีดป้อนเข้ามาตรฐานจะมี

ปัญหา

Scanner#nextInt(และวิธีการอื่น ๆ) ไม่อนุญาตให้สแกนเนอร์ใช้ตัวแยกบรรทัดเหล่านี้ มันจะอ่านพวกเขาจาก(วิธีอื่นที่เครื่องสแกนเนอร์จะรู้ว่ามีตัวเลขไม่มากจากผู้ใช้ซึ่งเป็นตัวแทนของมูลค่ากว่าหันหน้าไปทางช่องว่าง?) ซึ่งจะลบออกจากการป้อนข้อมูลมาตรฐาน แต่ก็ยังจะแคชแยกเส้นเหล่านั้นภายใน สิ่งที่เราต้องจำไว้ก็คือวิธีการสแกนทั้งหมดนั้นมักจะสแกนเริ่มต้นจากข้อความที่แคช Scanner#nextTypeSystem.inage

ตอนนี้Scanner#nextLine()เพียงแค่รวบรวมและส่งกลับอักขระทั้งหมดจนกว่าจะพบตัวแยกบรรทัด (หรือจุดสิ้นสุดของสตรีม) แต่เนื่องจากตัวแยกบรรทัดหลังจากอ่านหมายเลขจากคอนโซลพบได้ทันทีในแคชของสแกนเนอร์จึงส่งคืนสตริงว่างเปล่าซึ่งหมายความว่าสแกนเนอร์ไม่สามารถค้นหาอักขระใด ๆ ก่อนหน้าตัวแยกบรรทัด (หรือสิ้นสุดสตรีม)
BTW nextLineยังใช้ตัวแยกบรรทัดเหล่านั้นด้วย

สารละลาย

ดังนั้นเมื่อคุณต้องการที่จะขอหมายเลขแล้วสำหรับสายทั้งหมดขณะที่หลีกเลี่ยงที่สตริงที่ว่างเปล่าเป็นผลมาจากnextLineทั้ง

  • กินเส้นคั่นที่เหลือโดยnextIntจากสแกนเนอร์แคชโดย
    • โทรnextLine,
    • หรือ IMO อ่านได้ง่ายขึ้นโดยการโทรskip("\\R")หรือskip("\r\n|\r|\n")ให้สแกนเนอร์ข้ามส่วนที่จับคู่โดยตัวแยกบรรทัด (ข้อมูลเพิ่มเติมเกี่ยวกับ\R: https://stackoverflow.com/a/31060125 )
  • อย่าใช้nextInt( nextหรือหรือnextTYPEวิธีการใด ๆ) เลย แทนที่จะอ่านข้อมูลทั้งหมดบรรทัดโดยบรรทัดใช้nextLineและตัวเลขแยกจากแต่ละบรรทัด (สมมติว่าหนึ่งบรรทัดมีเพียงจำนวนหนึ่ง) ประเภทที่เหมาะสมเช่นผ่านทางintInteger.parseInt

BTW : วิธีการสามารถข้ามตัวคั่น (โดยค่าเริ่มต้นช่องว่างทั้งหมดเช่นแท็บตัวคั่นบรรทัด) รวมถึงสิ่งที่แคชโดยสแกนเนอร์จนกว่าพวกเขาจะหาค่าที่ไม่ใช่ตัวคั่นถัดไป (โทเค็น) ขอบคุณสำหรับการป้อนข้อมูลเช่นรหัสScanner#nextType"42\r\n\r\n321\r\n\r\n\r\nfoobar"

int num1 = sc.nextInt();
int num2 = sc.nextInt();
String name = sc.next();

num1=42 num2=321 name=foobarจะสามารถกำหนดได้อย่างถูกต้อง


14

แทนที่จะinput.nextLine()ใช้input.next()มันควรจะแก้ปัญหาได้

รหัสที่แก้ไข:

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();
}

FYI: ผสานจากstackoverflow.com/questions/7056749/…
Shog9

13

หากคุณต้องการอ่านทั้งสตริงและ int วิธีแก้ไขคือใช้สแกนเนอร์สองเครื่อง:

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();

1
นี่คือสิ่งที่ฉันกำลังมองหาบางเวลาตอนนี้ ย้ายอย่างชาญฉลาด!
เลียมวิลสัน

1
@Blearear scanner.nextLine()ควรทำงาน
André Valenti

11

หากคุณต้องการสแกนอินพุตอย่างรวดเร็วโดยไม่สับสนกับวิธีสแกนเนอร์ class nextLine () ให้ใช้ Custom Input Scanner ในการสแกน

รหัส:

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;
    }

}

ข้อดี:

  • สแกนอินพุตเร็วกว่า BufferReader
  • ลดความซับซ้อนของเวลา
  • ฟลัชบัฟเฟอร์สำหรับอินพุตทุกครั้งถัดไป

วิธีการ:

  • scanChar () - สแกนอักขระเดี่ยว
  • scanInt () - สแกนค่าจำนวนเต็ม
  • scanLong () - สแกนค่า Long
  • scanString () - สแกนค่าสตริง
  • scanDouble () - สแกนค่าสองเท่า
  • scanInt (int [] array) - สแกนอาร์เรย์ที่สมบูรณ์ (จำนวนเต็ม)
  • scanLong (long [] array) - สแกนอาร์เรย์ที่สมบูรณ์ (Long)

การใช้งาน:

  1. คัดลอกรหัสที่ระบุด้านล่างรหัส java ของคุณ
  2. วัตถุเริ่มต้นสำหรับคลาสที่กำหนด

ScanReader sc = new ScanReader(System.in); 3. นำเข้าคลาสที่จำเป็น:

import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; 4. โยน IOException จากวิธีการหลักของคุณเพื่อจัดการข้อยกเว้น 5. ใช้วิธีการที่ให้มา 6. เพลิดเพลิน

ตัวอย่าง:

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....

10

เพื่อหลีกเลี่ยงปัญหาใช้nextLine();ทันทีหลังจากnextInt();ที่มันช่วยในการล้างบัฟเฟอร์ เมื่อคุณกดไม่จับบรรทัดใหม่และด้วยเหตุนี้ข้ามรหัสภายหลังENTERnextInt();Scanner

Scanner scanner =  new Scanner(System.in);
int option = scanner.nextInt();
scanner.nextLine(); //clearing the buffer

9

sc.nextLine()ดีกว่าเมื่อเปรียบเทียบกับการแยกวิเคราะห์อินพุต เพราะประสิทธิภาพการทำงานที่ชาญฉลาดมันจะดี


5

ฉันเดาว่าฉันมาปาร์ตี้ช้าไปหน่อย ..

ตามที่ระบุไว้ก่อนหน้าการโทรinput.nextLine()หลังจากรับค่า int ของคุณจะช่วยแก้ปัญหาของคุณได้ เหตุผลที่ว่าทำไมรหัสของคุณไม่ได้ทำงานเป็นเพราะมีอะไรอย่างอื่นในการจัดเก็บจากการป้อนข้อมูลของคุณ (ที่คุณป้อน int) string1ลง ฉันจะเพิ่มความกระจ่างให้กับหัวข้อทั้งหมดเล็กน้อย

พิจารณาnextLine ()เป็นคี่หนึ่งในวิธีnextFoo ()ในคลาส Scanner ลองมาตัวอย่างอย่างรวดเร็ว .. สมมติว่าเรามีโค้ดสองบรรทัดเหมือนบรรทัดด้านล่าง:

int firstNumber = input.nextInt();
int secondNumber = input.nextInt();

หากเราป้อนค่าด้านล่าง (เป็นอินพุตบรรทัดเดียว)

54 234

ค่าของเราfirstNumberและsecondNumberตัวแปรกลายเป็น 54 และ 234 ตามลำดับ เหตุผลที่ทำให้วิธีนี้เป็นเช่นนี้เพราะฟีดบรรทัดใหม่ ( เช่น \ n ) ไม่ได้ถูกสร้างขึ้นโดยอัตโนมัติเมื่อเมธอด nextInt () รับค่า ใช้เวลาเพียงแค่"int ถัดไป"และเดินหน้าต่อไป สิ่งนี้จะเหมือนกันสำหรับเมธอด nextFoo () ที่เหลือยกเว้น nextLine ()

nextLine () สร้างการขึ้นบรรทัดใหม่ทันทีหลังจากรับค่า นี่คือสิ่งที่ @RohitJain หมายถึงการพูดว่าการป้อนบรรทัดใหม่ "บริโภค"

สุดท้ายวิธีถัดไป () ใช้สตริงที่ใกล้ที่สุดโดยไม่ต้องสร้างบรรทัดใหม่ สิ่งนี้ทำให้นี่เป็นวิธีการพิเศษสำหรับการแยกสตริงภายในบรรทัดเดียวกัน

ฉันหวังว่านี้จะช่วย .. การเข้ารหัส Merry!


"ฟีดบรรทัดใหม่" คืออะไร
นายขมังธนู

@Abcd โดยทั่วไปการป้อนบรรทัดใหม่หมายถึง 'เริ่มต้นจากบรรทัดใหม่'
Taslim Oseni

1
ตัวอย่างเช่น "54 234" นั้นให้ความกระจ่าง
Alonso del Arte

3

ใช้วัตถุสแกนเนอร์ 2 ชิ้นแทนหนึ่งวัตถุ

Scanner input = new Scanner(System.in);
System.out.println("Enter numerical value");    
int option;
Scanner input2 = new Scanner(System.in);
option = input2.nextInt();

2
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);
    }

หากคุณใช้เมธอด nextLine () ทันทีต่อจากเมธอด nextInt () ให้จำว่า nextInt () อ่านโทเค็นจำนวนเต็ม ด้วยเหตุนี้อักขระขึ้นบรรทัดใหม่ล่าสุดสำหรับบรรทัดของอินพุตจำนวนเต็มนั้นยังคงอยู่ในคิวอินพุตและ nextLine ถัดไป () จะอ่านส่วนที่เหลือของบรรทัดจำนวนเต็ม (ซึ่งว่างเปล่า)
Neeraj Gahlawat

2

หากฉันคาดหวังอินพุตที่ไม่ว่างเปล่า

public static Function<Scanner,String> scanLine = (scan -> {
    String s = scan.nextLine();
    return( s.length() == 0 ? scan.nextLine() : s );
  });


ใช้ในตัวอย่างด้านบน:

System.out.println("Enter numerical value");    
int option = input.nextInt(); // read numerical value from input

System.out.println("Enter 1st string"); 
String string1 = scanLine.apply( input ); // read 1st string
System.out.println("Enter 2nd string");
String string2 = scanLine.apply( input ); // read 2nd string

2

ในตอนหนึ่งของ USECASE ของฉันฉันมีสถานการณ์ของการอ่านที่ค่าสตริงนำโดยคู่ของค่าจำนวนเต็ม ฉันต้องใช้ " for / while loop " เพื่ออ่านค่า และข้อเสนอแนะข้างต้นไม่ทำงานในกรณีนี้

ใช้input.next()แทนการinput.nextLine()แก้ไขปัญหา หวังว่านี่อาจเป็นประโยชน์สำหรับผู้ที่เกี่ยวข้องกับสถานการณ์ที่คล้ายกัน


2

ใช้รหัสนี้มันจะแก้ไขปัญหาของคุณ

System.out.println("Enter numerical value");    
int option;
option = input.nextInt(); // Read numerical value from input
input.nextLine();
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)

2

ในฐานะที่เป็นnextXXX()วิธีการที่ไม่ได้อ่านยกเว้นnewline nextLine()เราสามารถข้ามnewlineหลังจากอ่านnon-stringค่าใด ๆ( intในกรณีนี้) โดยใช้scanner.skip()ดังต่อไปนี้:

Scanner sc = new Scanner(System.in);
int x = sc.nextInt();
sc.skip("(\r\n|[\n\r\u2028\u2029\u0085])?");
System.out.println(x);
double y = sc.nextDouble();
sc.skip("(\r\n|[\n\r\u2028\u2029\u0085])?");
System.out.println(y);
char z = sc.next().charAt(0);
sc.skip("(\r\n|[\n\r\u2028\u2029\u0085])?");
System.out.println(z);
String hello = sc.nextLine();
System.out.println(hello);
float tt = sc.nextFloat();
sc.skip("(\r\n|[\n\r\u2028\u2029\u0085])?");
System.out.println(tt);

0

ทำไมไม่ใช้สแกนเนอร์ใหม่สำหรับการอ่านทุกครั้ง? ชอบด้านล่าง ด้วยวิธีนี้คุณจะไม่เผชิญหน้ากับปัญหาของคุณ

int i = new Scanner(System.in).nextInt();

3
แต่คุณต้องปิดScannerเพื่อป้องกันหน่วยความจำรั่ว เสียเวลา?
TheCoffeeCup

1
GC ไม่สนใจหรือไม่ถ้าสแกนเนอร์ห่อด้วยวิธีการ? ไลค์: String getInput () {ส่งคืนสแกนเนอร์ใหม่ (System.in) .nextLine ()};
Tobias Johansson

สิ่งนี้ไม่ถูกต้องอย่างแน่นอน nextInt()จะไม่ใช้การขึ้นบรรทัดใหม่ไม่ว่าจะอยู่ใน "ใหม่" Scannerหรือใช้แล้ว
Dawood ibn Kareem
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.