[Java 에러] BufferedReader 활용 및 에러

2024. 1. 17. 14:49카테고리 없음

728x90
반응형

백준 알고리즘 15552번 문제.


Java를 사용하고 있다면, Scanner와 System.out.println 대신 BufferedReader와 BufferedWriter를 사용할 수 있다. 
BufferedWriter.flush는 맨 마지막에 한 번만 하면 된다.


입력
첫 줄에 테스트케이스의 개수 T가 주어진다. T는 최대 1,000,000이다. 다음 T줄에는 각각 두 정수 A와 B가 주어진다. A와 B는 1 이상, 1,000 이하이다.

출력

각 테스트케이스마다 A+B를 한 줄에 하나씩 순서대로 출력한다.

 

https://www.acmicpc.net/problem/15552

 

15552번: 빠른 A+B

첫 줄에 테스트케이스의 개수 T가 주어진다. T는 최대 1,000,000이다. 다음 T줄에는 각각 두 정수 A와 B가 주어진다. A와 B는 1 이상, 1,000 이하이다.

www.acmicpc.net

 

 

BufferedReader 활용

위 문제에 대해 아래와 같이 접근했다. BufferedReader를 호출하고 연산횟수를 입력했다. 그리고 for문 안에서 연산할 값들을 입력하기 위해 BufferedReader를 통해 입력값을 넣었다. 


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Scanner;
public class Main {
       public static void main(String[] args) throws IOException {

 

           BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
           int t = Integer.parseInt(bf.readLine());
           for (int i = 0; i < t; i++) {
               System.out.println(Integer.parseInt(bf.readLine()) + Integer.parseInt(bf.readLine()));
           }
     }
}

 

하지만 이때 NumberFormatException이 발생했다. 

Exception in thread "main" java.lang.NumberFormatException: For input string: "2 3" at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:67) at java.base/java.lang.Integer.parseInt(Integer.java:661) at java.base/java.lang.Integer.parseInt(Integer.java:777) at practice.main(practice.java:14)

 

for문 안에서 숫자를 입력할 때마다 enter로 개행을 해주면 문제가 없지만 "2 3" 처럼 공백으로 두 값을 구분해주려고 할 때 문제가 되는 것이다. String 값을 Integer로 변환하는 과정에서 "2 3"와 같이 공백이 포함된 값을 정수값으로 변환할 수가 없기 때문이다. 해당 문제는 두 개의 입력값을 공백으로 구분하도록 요구하고 있으므로 이 문제를 해결해야 한다. 

 

StringTokenizer

이때 많이 사용하는 방법이 StringTokenizer 클래스를 활용하는 것이다. 오라클 문서를 살펴보면 StringTokenizer를 " The string tokenizer class allows an application to break a string into tokens." 라고 설명하고 있다. 즉, 문자열을 토큰 단위로 분리시켜주는 역할을 한다.

 

예를 들어, "this is a test" 라는 문자열을 입력받으면 각각 "this", "is", "a", "test"로 분리시키는 기능을 하는 것이다. 따라서 위의 경우 처럼 "2 3"을 입력했을 때, StringTokenizer 클래스를 활용하면 "2 3"을 각각 "2", "3"을 입력한 것으로 인식하게 된다는 의미다. 

 

그리고 입력값을 받기 위해서는 nextToken() 메서드를 사용한다.  nextToken() 메서드는 StringTokenizer 이후에 입력된 문자 단위(token)를 반환하는 기능을 한다. 

 

StringTokenizer의 생성자로는 StringTokenizer(String str)이 있다.  따라서 다음과 같이 사용할 수 있다. 

 

StringTokenizer st = new StringTokenizer(br.readline());

 

BufferedReader로 입력받은 String 값을 토큰화하겠다는 선언이다. 만약 공백 또는 구분자를 포함한 값이 입력된다면 토큰화하여 분리시킬 것이다.

 


import java.io.*;
import java.util.Scanner;
import java.util.SimpleTimeZone;
import java.util.StringTokenizer;
 
          public class Main {
       
               public static void main(String[] args) throws IOException {
 
               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");
               }
               bw.flush();
               bw.close();
               br.close();
        }
}

 

 

하지만 공식문서에 따르면 StringTokenizer는 legacy class이므로, 이와 같은 기능을 사용하고자 한다면, String 클래스의 split 메서드를 사용하라고 권하고 있다. 

 

String 클래스의 split 메서드

 

String의 split 메서드는 특정 인자를 기준으로 입력된 String 값을 나누어주는 역할을 하며 반환타입은 String[] 이다. 따라서 위 코드에서는 BufferedReader 클래스로 입력받은 값을 띄어쓰기(" ") 기준으로 나누어 그것을 길이가 2인 String 배열에 저장했다.


import java.io.*;
import java.util.Scanner;
import java.util.SimpleTimeZone;
import java.util.StringTokenizer;
           public class Main {
                      public static void main(String[] args) throws IOException {
                      BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
                      BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
                      int t = Integer.parseInt(br.readLine());
                      for (int i = 0; i < t; i++) {
                              String a = br.readLine();
                              String[] arr = new String[t];
                              arr = a.split(" ");
                             bw.write(Integer.parseInt(arr[0]) + Integer.parseInt(arr[1]) + "\n");
                       }
                      br.close();
                      bw.close();
               }
      }

 

728x90
반응형