Projects/Java [Personal]

[Java] 특정 문자열을 입력해야만 무한루프를 종료하는 기능 구현 (Con'd)

montmer27 2025. 12. 9. 14:44
  • 요약

scanner.nextLine()은 버퍼에 남아 있는 개행문자를 모두 읽어옴으로써 버퍼를 비워주는 역할을 수행하므로, 직접적으로 값을 받을 목적이 아니더라도 버퍼를 비우는 목적으로 활용할 수 있다.

  • 이전 포스팅과의 비교

이전 포스팅은 인수를 정상적으로 입력한 경우에 한해 사용자 입력을 기다리지 않는 문제를 해결했다면, 이번 포스팅은 사용자가 잘못된 타입의 데이터를 입력했을 경우에도 동일 문제를 해결하는 과정이다. 

  • 의도한 수행 결과
계산기 시작
[1/2] 음이 아닌 정수를 입력하세요 : .
인수를 잘못 입력했습니다.
계속하겠습니까? (종료는 'exit' 입력) :
  • 실제 수행 결과
계산기 시작
[1/2] 음이 아닌 정수를 입력하세요 : /
인수를 잘못 입력했습니다.
계속하겠습니까? (종료는 'exit' 입력) : [1/2] 음이 아닌 정수를 입력하세요 :

 

  • 원인 분석

문제가 된 부분은 아래와 같다. 정수 또는 연산 부호를 입력하는 단계에서 타입에 맞지 않는 데이터를 입력하고 엔터를 누르면 InputMismatchException이 발생하고, 14행이 실행된다.

 

System.out.println("인수를 잘못 입력했습니다.");  //14행

 

이후 코드는 17행과 18행을 수행하기 시작하는데, 원래는 사용자의 입력을 기다려야 할 18행이 자동으로 실행되고 무한루프의 처음으로 진행한다. 18행의 scanner.next();는 엔터만 있었더라면 정상적으로 값 입력을 기다렸을 텐데, 그렇지 않았다는 것은 곧 버퍼에 다른 값이 함께 남아있었다는 것을 의미한다. 그럼 이 값은 어디서 왔을까?

 

바로 사용자가 타입에 맞지 않는 데이터를 입력하고 엔터를 누른 순간부터다.

 while (true) {
            try {
                System.out.print("[1/2] 음이 아닌 정수를 입력하세요 : ")
                int num1 = scanner.nextInt();
                System.out.print("[2/2] 음이 아닌 정수를 입력하세요 : ");
                int num2 = scanner.nextInt();

                System.out.print("연산 부호를 입력하세요 (+, -, *, / 중 택1) : ");
                char op = scanner.next().charAt(0);

                int result1 = calc1.calculate(num1, num2, op); //연산 수행
                System.out.println("연산 결과 : " + result1);
            } catch (InputMismatchException e) {
                System.out.println("인수를 잘못 입력했습니다."); //14행
     			//버퍼에 개행문자와 함께 잘못 입력한 값이 들어 있어 비워줘야 함
            } // catch문 종료
            System.out.print("계속하겠습니까? (종료는 'exit' 입력) : "); //17행
            String answer = scanner.next(); //18행
            if (answer.equals("exit")) {
                break;
            } //if문 종료
        } //무한루프 종료

 

  • 해결 방안

여러 해결 방안이 있을 수 있지만, 핵심은 버퍼를 비워주는 것이다. 우리의 목적은 18행의 scanner.next()가 실행되기 전에 버퍼에 개행 문자가 아닌 다른 값이 남아있지 않도록 하는 것이다. 개행문자만 남아있다면 어차피 읽지 않으니 상관 없다.

 

18행의 scanner.next()에 도달하는 방법은 2가지다 - 정상적으로 입력하거나, InputMismatchException을 발생시킨 뒤 도달하는 방법이다.

 

- 정상적으로 입력한 경우 두 번의 nextInt()와 한 번의 next().charAt(0)으로 인해 버퍼에는 개행 문자를 제외한 다른 값은 남아있지 않게 된다.

- 한번이라도 InputMismatchException을 발생시킨 경우 버퍼에는 해당 예외를 발생시킨 문자 또는 숫자가 남아있게 된다. 이는 그대로 17행을 거쳐 18행의 scanner.next()를 만나 answer 변수에 String으로 저장하여, 그대로 아래 if문까지 도달하여 test를 통과하여 while문의 처음으로 실행 위치를 이동시킨다.

 

따라서 InputMismatchException을 처리하는 catch문에서 17행으로 넘어가기 전, 버퍼를 한 번 비워주는 조작이 필요하다.

 

위 로직에 따라 수정한 코드는 아래와 같다.

catch (InputMismatchException e) {
                System.out.println("인수를 잘못 입력했습니다."); //14행
     			//버퍼 비워주기
                scanner.nextLine();
            } // catch문 종료

 

이후 성공적으로 수행된다.

 

계산기 시작
[1/2] 음이 아닌 정수를 입력하세요 : /
인수를 잘못 입력했습니다.
계속하겠습니까? (종료는 'exit' 입력) : 98
[1/2] 음이 아닌 정수를 입력하세요 : 9
[2/2] 음이 아닌 정수를 입력하세요 : 1
연산 부호를 입력하세요 (+, -, *, / 중 택1) : 9
입력이 잘못되었습니다. 연산을 수행할 수 없습니다.
연산 결과 : 0
계속하겠습니까? (종료는 'exit' 입력) : exit
저장된 연산 결과가 없습니다. //calc1.getItem(0);
삭제할 항목이 없습니다. //calc1.deleteFirstItem();

종료 코드 0(으)로 완료된 프로세스

 

출처

https://hwangpenguin.tistory.com/44

 

[Java] 입력 버퍼 비우기(Next(), NextLine())

1. 왜 이런 결과가 나오지? public void inputScanner2() { Scanner sc = new Scanner(System.in); System.out.println("이름 : "); String name = sc.nextLine(); System.out.println("나이 : "); int age = sc.nextInt(); System.out.println("주소 : "); St

hwangpenguin.tistory.com