https://www.acmicpc.net/problem/10951
10951번: A+B - 4
두 정수 A와 B를 입력받은 다음, A+B를 출력하는 프로그램을 작성하시오....
www.acmicpc.net
문제
풀이
우선, 문제를 보면 5개의 입력을 받으라는 것이 아니라, 단순히 입력 쌍을 나열하는 것을 알 수 있다.
즉, 이 문제는 EoF(End of File)의 개념이 적용되었다. EoF가 무엇인지 먼저 살펴보자.
EoF란, 입력에서 더 이상 읽을 수 있는 데이터가 없을 때 우리는 EoF(End of File) 즉, 파일의 끝이라 한다.
읽을 수 있는 데이터가 없다는 뜻은 입력을 하지 않았다는 뜻과 같으므로 null을 뜻한다.
이를 처리하는 방법은 입력의 종류에 따라 여러 방법이 있다. 그중 Scanner 와 BufferedReader 두 가지 처리 방법을 알아보자.
▸ Scanner
Scanner 의 메소드들의 경우 더 이상 읽을 데이터가 없으면 NoSuchElementException 을 던지게 된다.
던져진 예외의 경우 hasNext() 메소드를 사용해 처리해 준다. EOF일 경우 false 반환, 값이 있는 경우 true 반환
Scanner sc = new Scanner(System.in);
while(sc.hasNext()){} //입력되는 형식에 따라 달리 작성
▸ BufferedReader
BufferedReader 의 경우 null 을 반환한다.
(str=br.readLine())!=null 사용해 처리해 준다. EOF일 경우 false 반환, 값이 있는 경우 true 반환
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String str;
while((str=br.readLine()) != null) {}
❗ 주의할 점
백준에 제출하면 성공으로 뜨지만, IDE나 터미널에서는 EoF를 알 수 없어 실행 종료가 되지 않는다. 그래서 EoF를 입력(Ctrl+D / ⌘+D on Mac)해주거나 정수가 아닌 문자열을 입력한다던가 등 다른 타입의 입력을 주어 InputMismatchException 을 던져주어야 한다.
- 이클립스에서는 Ctrl + Z이다. (윈도우의 경우)
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String str;
//입력의 끝에 Enter를 한 번 더 입력하면 그 입력을 EOF로 판별하여 처리한다.
while((str=br.readLine()) != null && !str.isEmpty()) {}
👉 Scanner 사용하는 방법
가장 기초적인 방법이다. 이 문제에서는 hasNextInt(), hasNext() 둘 중 아무거나 써도 괜찮다. 어차피 입력이 아예 들어오지 않기 때문에 예외가 발생하는 형태는 같기 때문이다.
그래도 nextInt() 를 통해 정수를 입력받고자 했으니 hasNextInt() 를 써주는 게 다른 코딩할 때도 착오가 발생하지 않는다.
참고로 hasNextInt() 의 경우 입력값이 정수일 경우 true를 반환하며, 정수가 아닐 경우 바로 예외를 던지며 더 이상의 입력을 받지 않고 hasNextInt()에서 false를 반환하면서 반복문이 종료된다.
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
while (scan.hasNextInt()) {
int a = scan.nextInt();
int b = scan.nextInt();
System.out.println(a+b);
}
scan.close();
}
}
👉 BufferedReader + StringTokenizer (문자열 분리) 사용하는 방법
readLine() 을 통해 입력을 하여 str에 저장된 데이터가 null 일 경우 while 반복문을 종료시키고 아닐 경우 반복문을 계속 수행한다.
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.StringTokenizer;
public class Main {
public static void main(String args[]) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
StringBuilder sb = new StringBuilder();
String str;
while((str=br.readLine()) != null) {
st = new StringTokenizer(str, " ");
int a = Integer.parseInt(st.nextToken());
int b = Integer.parseInt(st.nextToken());
sb.append(a+b).append("\n");
}
System.out.print(sb);
br.close();
}
}
👉 BufferedReader + String.charAt() 사용하는 방법
여기서 문제를 잘 보면 입력되는 정수는 반드시 ( 0 < A, B < 10 ) 이다. 즉, 1개의 정수만 입력받는다.
그렇게 되면 자연스레 공백(" ")의 위치는 배열로 봤을 때 항상 고정된 위치라는 것을 알 수 있다. 이 점을 이용하여 charAt()을 사용하여 풀면 된다.
charAt() 은 String으로 저장된 문자열 중에서 한 문자만 선택해서 해당 문자의 아스키코드 값을 반환하기 때문에 반드시 숫자로 받으려면 -48 또는 -'0'을 해주어야 한다.
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
public class Main {
public static void main(String args[]) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringBuilder sb = new StringBuilder();
String str;
while((str=br.readLine()) != null) {
int a = str.charAt(0) - 48;
int b = str.charAt(2) - 48;
sb.append(a+b).append("\n");
}
System.out.print(sb);
br.close();
}
}
실행 결과
시간을 보면 BufferedReader 와 Scanner 의 성능 차이가 나는 것을 볼 수 있다.