15552번: 빠른 A+B
첫 줄에 테스트케이스의 개수 T가 주어진다. T는 최대 1,000,000이다. 다음 T줄에는 각각 두 정수 A와 B가 주어진다. A와 B는 1 이상, 1,000 이하이다.
www.acmicpc.net
[문제]
Java를 사용하고 있다면, Scanner와 System.out.println 대신 BufferedReader와 BufferedWriter를 사용할 수 있다. BufferedWriter.flush는 맨 마지막에 한 번만 하면 된다. 첫 줄에 테스트케이스의 개수 T가 주어진다. T는 최대 1,000,000이다. 다음 T줄에는 각각 두 정수 A와 B가 주어진다. A와 B는 1 이상, 1,000 이하이다. 각 테스트케이스마다 A+B를 한 줄에 하나씩 순서대로 출력한다.
이 문제에서 지금까지 입력을 받을 때 사용했던 Scanner를 사용하게 되면 시간초과로 오답처리가 된다.
문제에서 제시한 방법처럼 BufferedReader/Writer를 사용해야 한다.
사용법은 다음과 같다.
BufferedReader 객체명 = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter 객체명 = new BufferedWriter(new OutputStreamWriter(System.out));
우선 위와 같은 방법을 이용해 객체를 생성한다.
생성 후에는 메소드를 이용해 입력받고, 출력할 수 있다. (Scanner의 nextInt() 와 같음)
메소드들은 다음과 같다.
클래스 | 메소드 | 리턴타입 | 작동방식 |
BufferedReader | read() | int | 문자 하나를 읽어 int형으로 리턴 |
readLine() | String | 한 줄의 문자열을 읽음 | |
skip(n) | long | n개의 문자 스킵 | |
BufferedWriter | write(s) | - | 문자 또는 문자열 s출력 |
newLine() | - | 빈 줄 작성 | |
flush() | - | 남은 값 모두 출력 | |
close() | - | 스트림 종료 |
이 방법을 대략적으로 알아두고 코드를 작성했다.
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.StringTokenizer;
public class No15552 {
public static void main(String[] args) throws IOException{
// TODO Auto-generated method stub
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
int t = Integer.parseInt(br.readLine());
StringTokenizer st;
for(int i=0;i<t;i++) {
st = new StringTokenizer(br.readLine()," ");
bw.write((Integer.parseInt(st.nextToken())+Integer.parseInt(st.nextToken()))+"\n");
}
br.close();
bw.flush();
bw.close();
}
}
BufferedReader/Writer 클래스에 있는 메소드들을 사용하려면 입출력에러가 발생한 예외상황에 대한 코드를 작성해주어야 한다. 예외처리 코드는 IOException을 던지는 방법과 try-catch를 이용하는 방법이 있다. 나는 trhows IOEXception을 이용했다.
메인함수 안에서 우선 클래스의 객체들을 정의해주고 테스트케이스의 개수 t를 입력받았다.
분명 BufferedReader 클래스의 메소드에는 int형을 리턴하는 read()라는 메소드가 있었는데 왜 readLine()을 이용했을까?
read()가 int형을 반환하기는 하지만 쓰여진 정수 그대로를 반환하는 것은 아니다.
우선적으로 문자를 읽은 다음, 그 문자에 해당하는 아스키 10진수 값을 int형으로 반환하기 때문이다.
문자 그대로의 정수를 사용하려면 읽은 값에서 -48을 해주는 계산이 필요하다.
따라서 나는 문자를 읽어 정수로 변환해주는 Integer.parseInt(s)를 이용해 문자 그대로를 입력받고 변환해주었다.
이후 공백을 기준으로 문자들을 토큰화 하여 A, B 값을 구분하기 위해 StringTokenizer를 이용해 객체를 생성했다.
for문을 이용해 테스트 케이스 t만큼의 반복을 진행한다.
st = new StringTokenizer(br.readLine()," ");
읽어온 한 줄의 문자열을 공백 " "을 기준으로 토큰화 한다.
bw.write((Integer.parseInt(st.nextToken())+Integer.parseInt(st.nextToken()))+"\n");
그리고 출력을 위한 BufferWriter 객체 bw에 문자를 출력하는 write메소드를 사용한다.
첫번째 Integer.parseInt(st.nextToken())을 보면 st.nextToken()을 이용해 첫번째 토큰인 A를 읽고, Integer.parseInt()를 통해 정수형으로 변환한다. 이후 두번째 Integer.parseInt(st.nextToken())에서 두번째 토큰인 B를 읽고, 정수 변환을 해준다.
이렇게 읽어온 A, B값을 더한 값과 개행까지 출력메소드에 넣는다.
모든 과정이 완료된 후 close() 메소드로 스트림을 종료시킨다.