목차
📌System.in.read()
💡System.in.read()의 주요 특징
- 입력 데이터 처리
- 한 번 호출 시 1바이트(8비트)를 읽음
- 반환값은 0부터 255 사이의 정수 값. ASCII 코드로 입력받음
- 예: 'A'입력 -> 65
- 만약 입력이 없으면 -1 반환 = EOF(End Of File)
- 입력이 있을 때까지 프로그램 실행이 멈추는(블로킹) 방식으로 동작
- 사용자가 키보드로 Enter를 누를 때까지 대기
- 버퍼 사용
- 사용자가 입력한 내용은 내부적으로 입력 버퍼에 저장
- System.in.read()는 버퍼에서 데이터를 하나씩 읽어온다. 예를 들어, 사용자가 abc\n를 입력하면:
- 'a'를 읽고 반환
- 'b'를 읽고 반환
- 'c'를 읽고 반환
- '\n'(줄 바꿈 문자)를 읽고 반환
- 입력은 문자로 다뤄짐
- 입력값 은문자(ASCII 코드 값)로 반환되므로, 숫자로 사용하려면 추가 처리가 필요
- 예: 입력 '1'(ASCII 값 49)를 숫자 1로 변환하려면 '1' - '0' 연산을 수행
- 입력값 은문자(ASCII 코드 값)로 반환되므로, 숫자로 사용하려면 추가 처리가 필요
📌System.in.read()로 공백으로 구분된 정수 입력받기
💡입출력 예시
다음과 같이 입력했을 때
3 -23 6
다음과 같이 출력되도록 코드를 구현해보자.
3
-23
6
💡구현 코드
import java.io.IOException;
public class Sir {
//실행 부분
public static void main(String[] args) throws IOException {
int ex1 = readInt();
int ex2 = readInt();
int ex3 = readInt();
System.out.println("첫 번째 입력: " + ex1);
System.out.println("두 번째 입력: " + ex2);
System.out.println("세 번째 입력: " + ex3);
}
//구현 부분
private static int readInt() throws IOException {
int ans = 0;
boolean isNegative = false;
while (true) {
//System.in.read() : 입력받은 데이터를 한 문자씩 읽음
int n = System.in.read();
if(n<=32) { //공백이 나오면 리턴
return isNegative ? ans * (-1) : ans;
}
else if (n == '-') isNegative = true; //음수면 부호 저장
//아스키 코드를 숫자로 변환
else ans = (ans <<3) + (ans <<1) + (n&15) ;
}
}
}
💡설명
구현 부분 코드를 자세히 살펴보자.
ans 는 최종 결과물을 담을 변수고, isNegative는 음수/양수를 확인하기 위해 선언한 변수이다.
(System.in.read()는 '문자'를 입력받기 때문에 -3이란 정수가 나와도 음수,양수를 판단할 수 없으므로 우리가 직접 판단해주어야 한다.)
int ans = 0;
boolean isNegative = false;
while 문을 살펴보자.
while (true) {
//System.in.read() : 입력받은 데이터를 한 문자씩 읽음
int n = System.in.read();
if(n<=32) { //공백이 나오면 리턴
return isNegative ? ans * (-1) : ans;
}
else if (n == '-') isNegative = true; //음수면 부호 저장
//아스키 코드를 숫자로 변환
else ans = (ans <<3) + (ans <<1) + (n&15) ;
}
공백을 만나면 음수면 -를 붙여서, 양수면 그대로 출력한다.
if(n<=32) { //공백이 나오면 리턴
return isNegative ? ans * (-1) : ans;
}
❗n<=32로 설정하는 이유
→ 공백관련 문자가 32 이하에 있기 때문
9 - Tab
10 - Line Feed, 줄 바꿈
13 - Carriage Return, Enter
0 - 종료(Null)
-가 나오면 음수이므로, isNegative에 음수임을 저장해준다.
else if (n == '-') isNegative = true; //음수면 부호 저장
아스키코드를 숫자로 변환하고, 각 자리수를 맞춰준다. (0 = 48, 1=49, ...)
//아스키 코드를 숫자로 변환
else ans = (ans <<3) + (ans <<1) + (n&15) ;
ans << 3 = ans * 8
ans << 1 = ans * 2
→ (ans << 3) + (ans << 1) = ans * 10 을 의미한다.
❗(ans << 3) + (ans << 1)을 해주는 이유 → 입력값이 10 이상일 경우, 자리수를 맞춰주기 위해
예시: 입력 값 123
첫 번째 입력 문자 '1' : ans = 0 → ans = (0 * 10) + 1 = 1
두 번째 입력 문자 '2' : ans = 1 → ans = (1 * 10) + 2 = 12
세 번째 입력 문자 '3' : ans = 2 → ans = (12 * 10) + 3 = 123
- ❗& 15 연산을 사용하는 이유
- ASCII 코드에서 숫자 문자 '0'~'9'의 마지막 4비트가
실제 숫자 값(0~9)과 동일하기 때문 15는 2진수로 00001111
→ &15 연산을 통해 뒤의 4비트만 추출하면 숫자 값을 바로 얻을 수 있다.
'0' → 48 (2진수: 00110000) 48&15 = 00110000&00001111 = 00000000 = 0
'1' → 49 (2진수: 00110001) 49&15 = 00110001&00001111 = 00000001 = 1
'2' → 50 (2진수: 00110010) 50&15 = 00110010&00001111 = 00000010 = 2
'3' → 51 (2진수: 00110011) 51&15 = 00110011&00001111 = 00000011 = 3
'4' → 52 (2진수: 00110100) 52&15 = 00110100&00001111 = 00000100 = 4
'5' → 53 (2진수: 00110101) 53&15 = 00110101&00001111 = 00000101 = 5
'6' → 54 (2진수: 00110110) 54&15 = 00110110&00001111 = 00000110 = 6
'7' → 55 (2진수: 00110111) 55&15 = 00110111&00001111 = 00000111 = 7
'8' → 56 (2진수: 00111000) 56&15 = 00111000&00001111 = 00001000 = 8
'9' → 57 (2진수: 00111001) 57&15 = 00111001&00001111 = 00001001 = 9
💡구현 부분 정리
System.in.read()로 입력받은 문자열을 ASCII 코드에서 숫자로 변환한 후 공백을 만나면 변환을 멈추고, 음수인지, 양수인지 판별하여 return한다.
private static int readInt() throws IOException {
int ans = 0;
boolean isNegative = false;
while (true) {
//System.in.read() : 입력받은 데이터를 한 문자씩 읽음
int n = System.in.read();
if(n<=32) { //공백이 나오면 리턴
return isNegative ? ans * (-1) : ans;
}
else if (n == '-') isNegative = true; //음수면 부호 저장
//아스키 코드를 숫자로 변환
else ans = (ans <<3) + (ans <<1) + (n&15) ;
}
끝까지 읽어주셔서 감사합니다 :)
Have a good day🐱
📢
1. 개발자 준비생이 공부한 내용을 정리한 글입니다. 내용에 오류가 있을 수 있습니다.
2. 위와 같은 이유로 내용에 대한 지적과 조언은 감사하게 받습니다.
3. 이 글의 내용은 계속 공부함으로써 언제든지 추가/수정 될 수 있습니다.