내일배움캠프/TIL

2024 07 22 TIL : [Java] scanner 버퍼를 비워주기

동성만능크리너 2024. 7. 22. 21:19

 

자바 기초 문법 주차가 시작되고, 강의를 들으면서 숙제로 받은 "레시피 이름, 별점, 레시피 내용"을 입력받고 출력하는 간단한 프로그램을 만들다가, 이해가 되질 않는 부분이 있었다. 

 

import java.util.ArrayList;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        //스캐너 객체 생성
        Scanner sc = new Scanner(System.in);
        String recipeName = sc.nextLine();
        double recipeRating = sc.nextDouble();
        //실수로 받은 별점을 정수로 변환
        int irecipeRating = (int)recipeRating;
        ArrayList<String> recipeContents = new ArrayList<>();
        //레시피 한줄씩 10번 입력받기
        for (int i = 0; i < 10; i++) {
            recipeContents.add(sc.nextLine());
        }

        System.out.printf("[%s]\n",recipeName);
        System.out.printf("별점 : %d (%d%%) \n",irecipeRating,irecipeRating*20);

        for (int i = 0; i< 10; i++) {
            System.out.printf("%d. %s\n",i+1,recipeContents.get(i));
        }
    }
}

 

이런 코드를 짜고 입력을 쭉쭉하면 9번째 레시피를 입력하고나면 입력을 그만 받아버리고, 0번째 인덱스를 0으로 출력한 뒤, 그대로 10개를 만들어버리는 것이었다. 

입력값을 복붙으로 넣어서 10번째줄까지 입력을 받았지만, 수동으로 입력하면 9번에서 입력이 멈춰버린다.

 

도대체 왜 이러나 싶어서 scanner 사용법이 적힌 글들을 찾아보다가, nextDouble()을 사용했으면, 입력한 실수만 들어가고 개행문자 '\n'은 버퍼에 남아서 다음 입력에 사용된다는 것이다. 그리고 이를 해결하기 위해 nextDouble()과 같이 숫자형을 입력받거나 했으면, nextLine()을 한 번 써서 버퍼를 비워주면 문제없이 입력받은대로 출력해낼 수 있다. 

 

		Scanner sc = new Scanner(System.in);
        String recipeName = sc.nextLine();
        double recipeRating = sc.nextDouble();
        sc.nextLine(); //버퍼를 비워주기
        //실수로 받은 별점을 정수로 변환
        int irecipeRating = (int)recipeRating;
        ArrayList<String> recipeContents = new ArrayList<>();

 

코드 수정 후, 입력받은 대로 출력하는 모습

 

혹시 숫자형을 입력 받은 경우 말고도 스캐너를 쓸 때, 버퍼를 비워줘야 하는 경우는 없나 궁금해서 GPT에 물어봤더니 

 

더보기

 

  • 숫자형 입력 후 문자열 입력 시:
    • 앞서 설명한 것처럼, nextInt(), nextDouble() 등 숫자형 입력 메서드는 숫자만 읽고 줄바꿈 문자는 버퍼에 남깁니다. 따라서 다음 nextLine() 호출 전에 버퍼를 비워줘야 합니다.
  • 문자열 입력 후 줄바꿈 문자를 무시하고 싶을 때:
    • nextLine() 메서드는 줄바꿈 문자를 포함한 나머지 줄을 읽습니다. 만약 특정 조건 후 줄바꿈 문자만 제거하고 싶다면 nextLine()을 한 번 호출하여 버퍼를 비워줄 수 있습니다.
  • 특정 토큰 처리 후 다음 줄을 읽을 때:
    • next(), nextInt(), nextDouble() 등의 메서드는 공백이나 줄바꿈 문자를 구분자로 사용하여 입력을 처리합니다. 이러한 메서드들 후에 다음 줄을 완전히 읽고 싶을 때는 nextLine()을 호출하여 버퍼를 비워줘야 합니다.
  • 사용자 입력 패턴이 변경될 때:
    • 예를 들어, 숫자형 입력을 받다가 문자열 입력을 받거나, 여러 라인의 문자열 입력을 받다가 숫자형 입력을 받을 때, 줄바꿈 문자를 처리해야 할 필요가 생길 수 있습니다.

 

라는 답변을 받았다. 이를 잘 숙지해서 앞으로는 저런 상황 이후, 버퍼를 받아서 의도한 대로 프로그램이 동작할 수 있게 잘 써야겠다.