지니의 개발로그
[Java] 버퍼의 개행문자 제거. 라인을 읽어주고 버리기 (TIL #28일차) 본문
🚩 20240513 TIL 내일배움캠프 #28일차
🔴 문제
package scanner.ex;
import java.util.Scanner;
public class ScannerWhileEx1 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while(true) {
System.out.print("이름을 입력하세요 (종료를 입력하면 종료) : ");
String userName = sc.nextLine();
if (userName.equals("종료")) {
System.out.println("프로그램을 종료합니다.");
break;
}
System.out.print("나이를 입력하세요 : ");
int userAge = sc.nextInt();
if (userAge <= 0 || userAge >= 150) {
System.out.println("잘못된 나이를 입력하셨습니다. 다시 입력해주세요.");
}
System.out.println("입력한 이름 : " + userName + ", 나이 : " + userAge);
}
}
}
콘솔창에 실행 시 두번 째 반복부터 이름 입력을 생략하고 '나이를 입력하세요'가 나온다.
🟠 분석
Scanner의 nextInt() 메소드는 입력 스트림에서 정수를 읽어오지만,
입력 뒤에 오는 개행문자는 버퍼에 남아있게 된다.
sc.nextInt() 메소드 사용 후 버퍼에 남아있는 개행문자("\n") 때문에
바로 다음 반복으로 넘어가게 된다.
오류의 로직을 자세히 뜯어보면 다음과 같다.
- 프로그램이 실행되면 "이름을 입력하세요" 메시지가 출력된다.
- 사용자가 이름을 입력하고 엔터를 치면, sc.nextLine()이 이름과 엔터의 개행문자("\n")를 모두 읽어온다.
- "나이를 입력하세요" 메시지가 출력된다.
- 사용자가 나이를 입력하고 엔터를 치면, sc.nextInt()는 정수 부분만 읽고, 엔터의 개행문자("\n")는 버퍼에 남겨둔다.
- System.out.println("입력한 이름: " + userName + ", 나이: " + userAge); 코드가 실행되어 입력한 이름과 나이가 출력된다.
- 반복문이 다시 시작되고, "이름을 입력하세요" 메시지가 출력된다.
- 그런데 sc.nextLine()이 호출되면, 이전에 버퍼에 남아있던 개행문자("\n")가 읽혀진다.
- 프로그램은 이 개행문자를 유효한 이름 입력으로 인식한다.
- "나이를 입력하세요" 메시지가 출력되면서 바로 나이를 입력받기 위한 다음 반복으로 넘어가게 된다.
🟡 시도
nextInt() 후에 sc.nextLine()을 한 번 더 호출하여 버퍼의 개행문자를 제거해주었다.
🟢 배움
자바의 Scanner 클래스를 사용할 때,
nextInt() 메서드는 사용자가 입력한 정수만을 읽어오고 그 뒤에 입력된 개행문자(\n)는 버퍼에 남겨두기 때문에
이후 nextLine() 호출 시 버퍼에 남은 개행문자가 읽혀져서
해당 메서드에서 입력을 못받고 다음 코드로 넘어가는 문제가 발생한다.
개행문자를 남겨두는 메서드 사용 후에
nextLine()을 한 번 더 호출하여 버퍼에 남아있는 개행문자를 읽어내고 제거하여 문제를 해결 할 수 있다.
* 개행 문자를 남겨두는 메서드 예시 : nextInt(), nextFloat(), nextDouble(), nextByte(), nextShort(), nextLong()
반복문을 사용할 때 이러한 데이터 처리 로직에 오류가 발생하지 않도록 주의해야 한다.
위와같이 프로그래밍 언어와 그 기능들을 사용할 때
숨겨진 동작 원리를 이해하고 사용하는 것이 중요한 것 같다.
'내일배움캠프' 카테고리의 다른 글
API란? (TIL #31일차) (0) | 2024.05.17 |
---|---|
서버와 네트워크 (TIL #29일차) (0) | 2024.05.16 |
🏁 팀프로젝트 회고록 (TIL#25일차) (0) | 2024.05.10 |
InputMismatchException 에러(TIL #24일차) (0) | 2024.05.10 |
[Java] 정적 타입 바인딩 (TIL #23일차) (0) | 2024.05.09 |