[Baekjoon] for문 문제

2019. 7. 8. 11:09
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import java.util.*;
 
public class Main {
    public static void main(String args[]) throws Exception {
    
        try(BufferedReader bf = new BufferedReader(new InputStreamReader(System.in))){
            int test = Integer.parseInt(bf.readLine());
            int num[] = new int[test];
            
            for(int i = 0; i < test; i++) {
                StringTokenizer st = new StringTokenizer(bf.readLine());
                int A = Integer.parseInt(st.nextToken());
                int B= Integer.parseInt(st.nextToken());
                num[i] = A+B;
                //st.nextToken()bf.readLine()
            }
            bf.close();
            
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
            for(int j = 0; j<test; j++) {
                bw.write(String.valueOf(num[j])+ "\n");
            }
            bw.flush();
            bw.close();
        }
        catch(NumberFormatException e) {
            System.out.println(e);
        }
        catch (IOException ex) {
            System.out.println(ex);
        }
    }    
}
 

오늘도 알고리즘 문제를 5문제(for문 관련된) 속전속결로 풀었지만 이번에는 조금 새로운 내용을 접했다.

수업시간에 배울 때는 그렇게 중요하지 않았던 것 같았는데... 생각보다 중요한 내용이었다.

오늘은 BufferedReader, Writer를 이용한 코드 작성법에 대해 메모를 해보겠다.

 

1. BufferedReader

- 선언 방법:

BufferedReader bf = new BufferedReader(new InputStreamReader(System.in))
 
int test = Integer.parseInt(bf.readLine());
 

위와 같이 선언을 한다. 주의할 점은, 이것의 반환 타입은 항상 String이기 때문에 다른 타입으로 사용을 원한다면 꼭 형변환을 해주어야 한다. int 타입으로 받고 싶다면 위와 같은 방법으로 형변환을 해주면 된다.

여기서 readLine()은 입력을 받을 때 줄 단위로 받겠다는 뜻으로, 엔터를 쳐야만 인식이 된다. 스페이스바로 끊어지지 않음을 유의하자. 

 

2. StringTokenizer

  StringTokenizer st = new StringTokenizer(bf.readLine());
                int A = Integer.parseInt(st.nextToken());
                int B= Integer.parseInt(st.nextToken());
 

StringTokenizer는 readLine()과는 달리 스페이스바로도 토큰을 분리할 수 있다. 

nextToken() - 토큰 읽어오기(리턴 타입 String)

이 역시 리턴 타입이 String이기 때문에 출력시 별도의 형변환이 필요함을 잊지말자.

 

처음에 이 과정에서 int A = Integer.parsenInt(bf.readLine())을 하고 엔터를 쳤더니 Numberformat오류가 발생했다.
numberformat오류, 즉 이것은 형변환 오류로 변수 타입에 맞지 않는 객체가 들어가려고 하니 오류가 발생하는 것이었다. 나의 경우를 예로 들자면, 그러니까 내가 만약 1(스페이스바)4를 입력했을 때 지금 1따로 4따로로 인식을 하지 않고
1 4로 하나의 문자열로 인식을 하고 '1 4'의 문자열, 이걸 int 형으로 바꾸려고 하니 안된다는 오류인가? 했다.

당연히 안되는게 당연하다. 아까 말했듯이 readLine()은 스페이스바로 토큰을 구별할 수 없다고 하니 당연한 결과였다. 그렇기 때문에 nextToken()을 써서 스페이스바도 허용되도록 해주었다.

 

3. BufferedWriter

- 선언 방법:

 BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
            for(int j = 0; j<test; j++) {
                bw.write(String.valueOf(num[j])+ "\n");
            }
            bw.flush();
            bw.close();
        }
 

Writer의 선언 방법도 Reader와 유사하다. 나는 입력받아 연산한 결과를 배열에 넣어 이 배열에서 한꺼번에 출력하도록 만들었다. 맞다, 이러한 Buffered를 쓰려면 try-catch 구문에 넣어서 사용해야한다고 한다. 이 점도 유의하자.

아무튼, 반환 타입이 항상 String이라고 했으므로, 그냥 그대로 num[j]를 출력하면 네모안의 ?가 출력된다.

 

이 오류는 String을 int타입으로 변환해주지 않아서 생기는 오류이다. 이 오류를 해결하려면 아래와 같은 코드를 작성해야한다. 

 

bw.write(String.valueOf());

 

여기서 bw.write는 System.out.printIn();과 같은 역할을 한다. 이 역시 속도가 sysout보다는 빠르다는 점이다.

 

작은 수의 데이터를 처리한다면 Scanner나 sysout을 쓰는 것도 나쁘지 않지만, 방대한 양을 처리하는 경우라면 BufferedReader, BufferedReader를 사용하는 편을 추천한다. 특히 알고리즘 문제를 풀 때 좋을 것 같다!

 

BELATED ARTICLES

more