ProgramingTip

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

bestdevel 2020. 12. 9. 21:30
반응형

스캐너가 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.nextIntScanner.nextLine

Scanner.nextLine이후 또는 다른 메서드 를 사용할 때 사용할 때 동작이 발생합니다 ( 자체 제외 ).Scanner.next()Scanner.nextFoonextLine

해결 방법 :

  • 중 하나 넣어 각 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를 입력하고 키를 입력 표준 입력에 입력 "42\r\n"합니다.

문제

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

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

하는 라인 분리합니다.
nextLine

해결책

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

  • nextInt스캐너 캐시에서 남은 줄 구분 기호 사용
  • nextInt( next또는 어떤 nextTYPE방법도) 전혀 사용하지 않습니다 . 전체 데이터를 대신 한 줄씩 읽고 nextLine각 줄의 숫자 (한 줄에 숫자가 하나만 포함되어 있다고 가정 )를 int통해 와 같은 적절한 유형으로 구문 분석합니다 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)-전체를 스캔합니다. Array (Integer)
  • scanLong (long [] array)-전체 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....

sc.nextLine()입력을 구문 분석하는 것보다 낫습니다. 성능이 현명하기 때문에 좋을 것입니다.


파티에 꽤 늦었 나봐 ..

앞서 언급했듯이 input.nextLine()int 값을 얻은 후 호출 하면 문제가 해결됩니다. 코드가 작동하지 않는 이유는 입력 (int를 입력 한 위치)에서에 저장할 다른 것이 없기 때문 string1입니다. 전체 주제에 대해 조금 더 설명하겠습니다.

고려 () 꽵를 중 괴상 한 개로서 nextFoo () 스캐너 클래스 방법. 간단한 예를 들어 보겠습니다. 아래 코드와 같은 두 줄의 코드가 있다고 가정 해 보겠습니다.

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

아래 값을 입력하면 (한 줄의 입력으로)

54234

우리 firstNumbersecondNumber변수 의 값은 각각 54와 234가됩니다. 이것이 이런 방식으로 작동하는 이유 는 nextInt () 메서드가 값을받을 때 새 줄 바꿈 ( 예 : \ n )이 자동으로 생성 되지 않기 때문 입니다. 단순히 "next int" 를 취하고 계속 진행합니다. nextLine ()을 제외한 나머지 nextFoo () 메서드에 대해서도 동일합니다.

nextLine ()은 값을 취한 직후 새 줄 바꿈을 생성합니다. 이것이 @RohitJain이 새로운 줄 바꿈이 "소비된다"는 의미입니다.

마지막으로 next () 메서드 는 새 줄 생성 하지 않고 가장 가까운 문자열 가져옵니다 . 이것은 동일한 한 줄 내에서 별도의 문자열을 가져 오기위한 우선적 인 방법이됩니다.

도움이 되었기를 바랍니다 .. 즐거운 코딩!


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

하나 대신 2 개의 스캐너 개체 사용

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

비어 있지 않은 입력을 기대한다면

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

모든 판독에 새 스캐너를 사용하는 것은 어떻습니까? 아래와 같습니다. 이 접근 방식을 사용하면 문제에 직면하지 않습니다.

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

참고 URL : https://stackoverflow.com/questions/7056749/scanner-issue-when-using-nextline-after-nextxxx

반응형