your programing

스캐너가 next () 또는 nextFoo ()를 사용한 후 nextLine ()을 건너 뛰나요?

lovepro 2020. 10. 2. 23:02
반응형

스캐너가 next () 또는 nextFoo ()를 사용한 후 nextLine ()을 건너 뛰나요?


내가 사용하고 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()내가 원하는대로 실행됩니다.


그 이유는 Scanner.nextInt메소드가 "Enter"를 눌러 생성 된 입력에서 개행 문자를 읽지 않으므로 Scanner.nextLine해당 개행 을 읽은 후에 대한 호출이 반환 되기 때문 입니다.

Scanner.nextLineafter 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();
    

문제는 input.nextInt () 메서드에 있습니다. int 값만 읽습니다. 따라서 input.nextLine ()으로 계속 읽으면 "\ n"Enter 키를 받게됩니다. 따라서 이것을 건너 뛰려면 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();

당신이 다음을 눌러 숫자를 입력 할 때 때문입니다 Enter, input.nextInt()수만이 아니라 "줄의 끝을"소비한다. input.nextLine()실행 되면 첫 번째 입력에서 버퍼에있는 "줄 끝"을 사용합니다.

대신, 사용 input.nextLine()직후input.nextInt()


이 문제에 대한 많은 질문이있는 것 같습니다 java.util.Scanner. 더 읽기 쉽고 관용적 인 해결책은을 호출 scanner.skip("[\r\n]+")한 후 줄 바꿈 문자를 삭제 하도록 호출 하는 것 nextInt()입니다.

편집 : @PatrickParker가 아래에 언급했듯이 사용자가 숫자 뒤에 공백을 입력하면 무한 루프가 발생합니다. 건너 뛰기와 함께 사용할 더 나은 패턴에 대한 답변을 참조하십시오 : https://stackoverflow.com/a/42471816/143585


input.nextInt();개행을 캡처하지 않기 때문에 그렇게합니다. 당신은 input.nextLine();아래 에 추가하여 제안 된 다른 사람들처럼 할 수 있습니다.
또는 C # 스타일로 수행하고 nextLine을 다음과 같이 정수로 구문 분석 할 수 있습니다.

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

이렇게하면 잘 작동하며 코드 한 줄을 절약 할 수 있습니다.


알아야 할 사항 :

  • 몇 줄을 나타내는 텍스트에는 다음과 같이 줄 사이에 인쇄 할 수없는 문자도 포함됩니다 (줄 구분 기호라고 함).

    • 캐리지 리턴 (CR-로 표현되는 문자열 리터럴에서 "\r")
    • 줄 바꿈 (LF-로 표현되는 문자열 리터럴에서 "\n")
  • 콘솔에서 데이터를 읽을 때 사용자는 자신의 응답을 입력 할 수 있으며 완료되면 어떻게 든 그 사실을 확인 해야합니다 . 이를 위해 사용자는 키보드에서 "enter"/ "return"키를 눌러야합니다.

    중요한 것은 사용자 데이터를 표준 입력 ( System.inScanner표시됨)에 배치하는 것 외에이 키가 그 \r\n뒤에 OS 종속 줄 구분 기호 (예 : Windows )를 전송한다는 것입니다.

    따라서 사용자에게와 같은 값을 요청하고 사용자가 age42를 입력하고 Enter 키를 누르면 표준 입력에 "42\r\n".

문제

Scanner#nextInt(및 기타 방법) 스캐너가 이러한 줄 구분 기호 사용 하도록 허용하지 않습니다 . 그것은에서 읽을 것이다 (대표 사용자로부터 더 이상 자리가 있다는 것을 알고 얼마나 다른 스캐너 표준 입력에서 제거 할 공백에 직면 이상의 값?), 그러나 그것은 또한 것이다 캐시 내부적으로 그 라인 분리를 . 기억해야 할 것은 모든 Scanner 메소드가 항상 캐시 된 텍스트에서 시작하여 스캔한다는 것입니다.Scanner#nextTypeSystem.inage

이제 줄 구분 기호 (또는 스트림 끝)를 찾을 때까지Scanner#nextLine() 모든 문자를 수집하고 반환합니다 . 그러나 콘솔에서 번호를 읽은 후 줄 구분 기호는 Scanner의 캐시에서 즉시 발견되기 때문에 빈 문자열을 반환합니다. 이는 Scanner가 해당 줄 구분 기호 앞의 문자 (또는 스트림 끝)를 찾을 수 없음을 의미합니다. BTW 또한 소비 하는 라인 분리합니다.
nextLine

해결책

그래서 당신의 결과로 그 빈 문자열을 피하면서 전체 라인 다음 번호를 요청하고 싶을 때 nextLine중,

  • nextInt스캐너 캐시에서 남은 줄 구분 기호 사용
    • 전화 nextLine,
    • 또는 skip("\\R")스캐너가 \R줄 구분 기호를 나타내는 부분을 ​​건너 뛰도록 호출 하여 (자세한 정보 \R: https://stackoverflow.com/a/31060125 )
  • nextInt( next또는 어떤 nextTYPE방법도) 전혀 사용하지 마십시오 . 대신 전체 데이터를 한 줄씩 읽고 nextLine각 줄의 숫자 (한 줄에 숫자가 하나만 포함되어 있다고 가정)를 intvia 와 같은 적절한 유형으로 구문 분석합니다 Integer.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.


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

문자열과 정수를 모두 읽으려면 두 개의 스캐너를 사용하는 것이 해결책입니다.

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

문제를 방지 하려면 버퍼를 지우는 데 도움이되는 nextLine();즉시 사용 하십시오 nextInt();. 당신이 누르면 ENTERnextInt();새로운 라인을 캡처하고 따라서 생략하지 않습니다 Scanner나중에 코드를.

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

스캐너 클래스 nextLine () 메서드와 혼동하지 않고 빠르게 입력을 스캔하려면 사용자 정의 입력 스캐너를 사용하십시오.

코드 :

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 ()-Double 값 스캔
  • scanInt(int[] array) - scans complete Array(Integer)
  • scanLong(long[] array) - scans complete Array(Long)

Usage :

  1. Copy the Given Code below your java code.
  2. Initialise Object for Given Class

ScanReader sc = new ScanReader(System.in); 3. Import necessary Classes :

import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; 4. Throw IOException from your main method to handle Exception 5. Use Provided Methods. 6. Enjoy

Example :

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

sc.nextLine() is better as compared to parsing the input. Because performance wise it will be good.


I guess I'm pretty late to the party..

As previously stated, calling input.nextLine() after getting your int value will solve your problem. The reason why your code didn't work was because there was nothing else to store from your input (where you inputted the int) into string1. I'll just shed a little more light to the entire topic.

Consider nextLine() as the odd one out among the nextFoo() methods in the Scanner class. Let's take a quick example.. Let's say we have two lines of code like the ones below:

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

If we input the value below (as a single line of input)

54 234

The value of our firstNumber and secondNumber variable become 54 and 234 respectively. The reason why this works this way is because a new line feed (i.e \n) IS NOT automatically generated when the nextInt() method takes in the values. It simply takes the "next int" and moves on. This is the same for the rest of the nextFoo() methods except nextLine().

nextLine() generates a new line feed immediately after taking a value; this is what @RohitJain means by saying the new line feed is "consumed".

Lastly, the next() method simply takes the nearest String without generating a new line; this makes this the preferential method for taking separate Strings within the same single line.

I hope this helps.. Merry coding!


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

Use 2 scanner objects instead of one

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

if I expect a non-empty input

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


used in above example:

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

Why not use a new Scanner for every reading? Like below. With this approach you will not confront your problem.

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

참고URL : https://stackoverflow.com/questions/13102045/scanner-is-skipping-nextline-after-using-next-or-nextfoo

반응형