StringTokenizer / BufferedReader / EOF 백준 10951

jungseo·2023년 4월 25일
0

강해지고싶다

목록 보기
2/2


처음 문제를 보고 단순한 문제라고 생각했고 Scanner를 이용하여 코드를 작성했다.

public class BJ_10951_scanner {
    public static void main(String[] args) {

        Scanner sc = new Scanner(System.in);
        StringBuilder sb = new StringBuilder();


        while (sc.hasNext()) {
            int a = sc.nextInt() + sc.nextInt();

            sb.append(a).append("\n");
        }
        System.out.println(sb);

    }
}

우선 Scanner의 hasNext() 메서드를 사용하여 읽어들일 값이 정수일 경우 두 수를 더해 StringBuilder에 쌓고 마지막에 출력하는 식으로 작성을 했다.

그리고 실행을 했는데 정수들을 입력하다 원하는 곳에서 종료시킬 수가 없었다. hasNext()가 다음으로 받아들일 값이 정수일 경우 true를 반환한다고 하여 공백이나 개행문자가 입력되면 당연히 종료될 것이라 생각했다.

다른 문제들의 경우 테스트 케이스의 수가 처음 정해져있어서 반복문이 끝나는 곳이 정해져 있었는데 이 문제의 경우 그렇지 않았다. 검색을 해보니 BufferedReader를 사용해야 한다는 글을 보고 시도해보기로 했다.


BufferedReader 와 Scanner

  • 두 클래스 모두 입력 스트림에서 데이터를 읽을 수 있는 클래스이나 차이점이 있다.
    • BufferedReader는 문자열로 처리되는 한줄씩 읽어들인다.
    • Scanner는 공백을 기준으로 읽어들인다.
    • BufferedReader는 입력 데이터를 버퍼에 저장하고 한 줄씩 읽어들여 Scanner보다 빠르게 데이터를 처리할 수 있다.
    • Scanner는 다양한 입력 데이터 타입을 처리할 수 있고 적절한 자료형으로 변환할 수 있다.
    • BufferedReader는 텍스트 데이터를 처리할때,
    • Scanner는 다양한 데이터 타입을 처리하고 토큰으로 분리된 데이터를 처리할 때 사용된다.
import java.io.BufferedReader; // java 패키지의 io패키지의 BufferedReader 클래스를 불러온다.
import java.io.IOException;
import java.io.InputStreamReader;

public class Br_test {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String str = br.readLine();
        System.out.println(str);
    }
}

그동안 위쪽에 import 부분이 무엇을 의미하는지 잘 모르고 써왔는데 오늘 드디어 관련 내용을 배워서 전체적인 흐름이 좀 더 이해가 되는 것 같다.

throw IOException은 BufferedReader의 경우 Scanner와 달리 읽어올 데이터가 없어서 null을 반환하는 경우 같은 예외가 있어 이를 예외로 처리하기 위해서라고 한다.

    BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 
    이 부분은 왜 뒤쪽이 이런 형식이 되는지 아직 이해를 못하겠다...

결국 BufferedReader는 개행 문자가 입력되기 전까지 입력된 데이터를 하나의 문자열로 처리하고 이 문자열을 공백 단위로 나누어 처리하려면 StringTokenizer가 필요한 것 같다. 파생되는 클래스나 개념들이 너무 많은 것 같아 조금 힘들다..


StringTokenizer

  • StringTokenizer는 기본적으로 공백문자를 기준으로 문자열을 분리하여 토큰으로 나눈다. (다른 구분자도 지정할 수 있다.)

  • 메서드
    - countTokens() : 분리된 토큰의 총 개수를 반환한다.
    - hasMoreTokens() : 아직 반환하지 않은 토큰이 있는지 여부를 반환한다.
    - nextToken() : 다음 토큰을 반환한다.

import java.util.StringTokenizer;

public class ST {
    public static void main(String[] args) {
        String str = "너 나 안 본 지 두 달 다 돼 감";
        StringTokenizer st = new StringTokenizer(str);

        while (st.hasMoreTokens()) {
            System.out.println(st.nextToken());
            System.out.print(st.countTokens());
        }
    }
}
----
출력
----9876543210

새로 배운 것들을 만지작 거리며 겨우 코드를 작성해봤다.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class BJ_10951_BR {
    public static void main (String[] arg) throws IOException {

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringBuilder sb = new StringBuilder();

        String str;

        while ((str = br.readLine()) != null) {

            StringTokenizer st = new StringTokenizer(str);

            int a = Integer.parseInt(st.nextToken());
            int b = Integer.parseInt(st.nextToken());
            sb.append(a + b + "\n");
        }
        System.out.println(sb);
    }
}

문자열 str을 BufferedReader로 읽어들이는데 이 값이 null이 아니면 str을 토큰화 하고 두개의 토큰 씩 정수형으로 변환 후 더한 후 그 값을 StringBuilder로 쌓아 문자열 str이 null이 됐을때 반복문을 종료하고 StringBuilder를 출력한다.

그런데 Scanner를 사용했을 때와 마찬가지로 입력을 그만 받고 출력을 할 수가 없었다..

개행문자도 null이 아닌 하나의 문자라고 한다..

ctrl + D 를 누르면 표준 입력으로부터 더 이상 입력을 받지 않고 중단한다고 한다..

항상 사용하던 Scanner 말고 다른 입력 방식인 BufferedReader를 알아보고 StringTokenizer를 공부해 앞으로 문제에 접근할 수 있는 방법이 늘어난 것 같다. 다만 문제가 너무 간단하게 해결돼서 조금 허무했다. 코드를 작성하다보면 이렇게 작은 것들로 해결 될 때가 많은 것 같다..

0개의 댓글