[Java] BufferedReader, StringTokenizer 클래스 사용방법, 백준 4344번 문제 풀이

자바로 알고리즘 문제를 풀 때 Scanner 클래스를 사용하면 편리하나 속도가 느리다는 단점이 있다. 그래서 Scanner 대신에 버퍼를 사용하는 BufferedReader 클래스를 사용하여 알고리즘 문제를 풀면 시간복잡도 효율성에서 유리하다.

BufferedReader, StringTokenizer 클래스 사용예제

public class StringRepeat {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        StringTokenizer st = new StringTokenizer(br.readLine()); //공백단위로 읽어드릴수 있는 라인 추가
        int c = Integer.parseInt(st.nextToken()); //한줄에서 공백 단위로 읽음
        int d = Integer.parseInt(st.nextToken()); //한줄에서 공백 단위로 읽음
        System.out.println(c + " " + d);

        st = new StringTokenizer(br.readLine(),","); // , 단위로 읽어드릴수 있는 라인 추가
        int e = Integer.parseInt(st.nextToken()); //한줄에서 , 단위로 읽음
        int f = Integer.parseInt(st.nextToken()); //한줄에서 , 단위로 읽음
        System.out.println(e + " " + f);
    }
}

BufferedReader로 라인을 읽고 그 라인에서 특정 문자열로 읽어드릴 수 있으려면 StringTokenizer 클래스를 사용해야 한다. new StringTokenizer(br.readLine)) 하면 라인을 읽어드릴 수 있고 nextToken()으로 공백단위로 읽어드릴 수 있다.

 

Scanner 클래스에 비해서 사용이 힘든점은 반드시 throws IOException을 해줘야 하고, nextToken()으로 읽어드릴 때는 String으로 밖에 읽어드릴 수 없어 정수로 읽고 싶을 때는 Integer.parseInt()로 숫자로 된 문자열을 숫자형으로 형변환 시켜줘야 한다.

 

라인 한줄을 읽고 다음 라인을 읽고 싶을 때는 new StringTokenizer(br.readLine()) 을 추가해야 하고 특정 문자열 단위로 읽고 싶을 때는 new StringTokenizer(st.nextToken(), 특정문자열)) 뒤에 인자를 추가하면 된다. (default는 공백이다.)

 

 

만약에 공백단위로 한 줄을 다 읽고 싶다면 hasMoreTokens()를 사용하면 된다.

StringTokenizer st = new StringTokenizer(br.readLine()); //공백단위로 읽어드릴수 있는 라인 추가
while(st.hasMoreTokens()) {
    System.out.println(st.nextToken());
}

 

 

백준 4344번 문제풀이 https://www.acmicpc.net/problem/4344

BuffferedReader와 StringTokenizer를 통해서 문제를 풀었다. 

public class AboveAverage {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());

        LinkedHashMap<ArrayList<Integer>, Double> hashMap = new LinkedHashMap<ArrayList<Integer>, Double>();

        int C = Integer.parseInt(st.nextToken());

        //테스트케이스
        for (int i = 0; i < C; i++) {
            st = new StringTokenizer(br.readLine());
            ArrayList<Integer> al = new ArrayList<>();
            //학생수
            int stuCnt = Integer.parseInt(st.nextToken());

            //학생수만큼 스코어 입력
            for(int j =0; j<stuCnt; j++) {
                int score = Integer.parseInt(st.nextToken());
                al.add(score);
            }

            hashMap.put(al, 0.0);
        }

        new AboveAverage().solve(hashMap);
    }
    public void solve(LinkedHashMap<ArrayList<Integer>, Double> hashMap) {
        int sum = 0;
        double average = 0;

        for (ArrayList<Integer> al : hashMap.keySet()) {
            for (Integer i : al) {
                sum += i;
            }
            average = (double)sum/al.size();
            hashMap.put(al, average);
            sum = 0;
        }
        int cnt = 0;
        for (ArrayList<Integer> al : hashMap.keySet()) {
            for (Integer i : al) {
                if ((double)i > hashMap.get(al)) {
                    cnt++;
                };
            }

            double result = (double)cnt  / al.size() * 100.0;
            //System.out.println(Math.round(result * 1000) / 1000.0 + "%");
            System.out.printf("%.3f%%\n", result);
            cnt = 0;
        }
    }
}

테스트케이스 C의 값만큼 for문을 돌리고 for문이 실행될 때마다.

st = new StringTokenizer(br.readLine(); 을 통해서 한줄을 읽고 그 한줄을 공백 단위로 짜른 배열을 가져온다.

그리고 공백단위로 짤라진 값을 st.nextToken() 함수로 데이터를 가져와 리스트에 담는다.

댓글

Designed by JB FACTORY