exit를 입력해도 while문이 종료되지 않았던 이유오늘 간단한 자바 계산기를 만들다가,
계산 결과를 출력한 뒤 "exit"를 입력하면 반복문이 종료되어야 하는데
계속 다시 첫 번째 숫자를 입력하세요:가 뜨는 문제가 있었다.
처음에는 if (answer.equals("exit")) 비교가 잘못된 줄 알았는데,
원인은 Scanner 입력 방식 차이와 입력 버퍼에 남아 있는 엔터값 때문이었다.
내가 작성한 계산기 코드는 대략 이런 구조였다.
package com.example.calculator;
import java.util.Scanner;
public class Calculator {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int result = 0;
while (true) {
System.out.print("첫 번째 숫자를 입력하세요: ");
int a = scanner.nextInt();
System.out.print("두 번째 숫자를 입력하세요: ");
int b = scanner.nextInt();
System.out.print("사칙연산 기호를 입력하세요: ");
char c = scanner.next().charAt(0);
if (c == '+') {
result = a + b;
}
else if (c == '-') {
result = a - b;
}
else if (c == '*') {
result = a * b;
}
else if (c == '/') {
if (b == 0) {
System.out.println("나눗셈 연산에서 분모(두번째 정수)에 0이 입력될 수 없습니다.");
continue;
} else {
result = a / b;
}
}
System.out.println("결과: " + result);
System.out.print("더 계산하시겠습니까? (exit 입력 시 종료): ");
String answer = scanner.nextLine();
if (answer.equals("exit")) {
break;
}
}
}
}
예를 들어 아래처럼 입력했다.
첫 번째 숫자를 입력하세요: 1
두 번째 숫자를 입력하세요: 2
사칙연산 기호를 입력하세요: +
결과: 3
더 계산하시겠습니까? (exit 입력 시 종료): exit
첫 번째 숫자를 입력하세요:
분명히 exit를 입력했는데도 반복문이 종료되지 않았다.
심지어 어떤 경우에는 아래와 같은 에러도 발생했다.
java.util.InputMismatchException
처음에는 이렇게 생각했다.
"exit" 비교를 equals()로 했으니 문제없다exit를 입력했는데 왜 break가 안 걸리지?if문의 break를 밖으로 빼야하나?그런데 문제는 문자열 비교가 아니라,
answer 변수에 실제로 "exit"가 저장되지 않고 있었다는 점이었다.
nextInt(), next()와 nextLine()의 차이nextInt()와 next()는 값만 읽는다nextInt()와 next()는 입력값 자체만 읽고,
사용자가 마지막에 누른 엔터(\n)는 입력 버퍼에 남겨둘 수 있다.
예를 들어 사용자가 +를 입력하고 엔터를 누르면,
프로그램 입장에서는 +는 읽었지만 엔터는 남아 있을 수 있다.
nextLine()은 남아 있던 엔터를 먼저 읽는다문제는 여기서 발생했다.
String answer = scanner.nextLine();
나는 이 줄이 exit를 읽을 거라고 생각했지만,
실제로는 바로 직전에 남아 있던 엔터만 읽고 끝나버렸다.
즉, answer에는 "exit"가 아니라
빈 문자열 "" 이 들어가게 된 것이다.
그래서 아래 조건문은 false가 된다.
if (answer.equals("exit")) {
break;
}
실제로는 이런 느낌이었던 셈이다.
if ("".equals("exit")) {
break;
}
당연히 종료되지 않는다.
InputMismatchException까지 발생했을까?반복문이 종료되지 않고 다시 처음으로 돌아가면,
프로그램은 또 숫자를 입력받으려고 한다.
int a = scanner.nextInt();
그런데 나는 방금 exit를 입력한 상태였다.
즉, 프로그램 입장에서는
정수를 입력받아야 하는 자리에 "exit"가 들어온 것이다.
그래서 이런 예외가 발생했다.
java.util.InputMismatchException
이 에러의 뜻은 간단하다.
숫자를 받아야 하는데 숫자가 아닌 값이 들어왔다.
해결 방법은 남아 있는 엔터를 먼저 한 번 비워주고,
그 다음 실제 사용자 입력을 받는 것이다.
System.out.print("더 계산하시겠습니까? (exit 입력 시 종료): ");
scanner.nextLine(); // 남아 있는 엔터 제거
String answer = scanner.nextLine(); // 실제 입력 받기
if (answer.equals("exit")) {
break;
}
이렇게 순서를 바꾸니 정상적으로 동작했다.
이제 입력 흐름은 이렇게 된다.
char c = scanner.next().charAt(0);
+는 읽음nextLine()scanner.nextLine();
nextLine()String answer = scanner.nextLine();
exit를 읽음if (answer.equals("exit")) {
break;
}
answer에 실제로 "exit"가 들어 있으므로 종료됨이번 트러블 슈팅을 하면서 가장 크게 느낀 건
Scanner의 입력 방식 차이를 정확히 이해해야 한다는 것이었다.
nextInt()next()nextLine()즉, nextInt()나 next() 뒤에 바로 nextLine()을 쓰면
내가 원하는 입력이 아니라 남아 있던 엔터를 먼저 읽어버릴 수 있다.
package com.example.calculator;
import java.util.Scanner;
public class Calculator {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int result = 0;
while (true) {
System.out.print("첫 번째 숫자를 입력하세요: ");
int a = scanner.nextInt();
System.out.print("두 번째 숫자를 입력하세요: ");
int b = scanner.nextInt();
System.out.print("사칙연산 기호를 입력하세요: ");
char c = scanner.next().charAt(0);
if (c == '+') {
result = a + b;
}
else if (c == '-') {
result = a - b;
}
else if (c == '*') {
result = a * b;
}
else if (c == '/') {
if (b == 0) {
System.out.println("나눗셈 연산에서 분모(두번째 정수)에 0이 입력될 수 없습니다.");
continue;
} else {
result = a / b;
}
}
System.out.println("결과: " + result);
System.out.print("더 계산하시겠습니까? (exit 입력 시 종료): ");
scanner.nextLine();
String answer = scanner.nextLine();
if (answer.equals("exit")) {
break;
}
}
scanner.close();
}
}
이번 문제는 단순히 break나 equals()의 문제가 아니라,
입력 버퍼와 Scanner 메서드의 동작 방식을 이해해야 해결할 수 있는 문제였다.
처음에는 왜 exit가 안 먹는지 감이 안 왔지만,
원인을 하나씩 따라가 보니
결국 남아 있던 엔터가 문제라는 걸 알 수 있었다.
앞으로 Scanner를 사용할 때는
특히 nextInt(), next(), nextLine()을 섞어 쓸 때
입력 버퍼를 꼭 의식해야겠다고 느꼈다.
---