StringTokenizer 이해하기

‍박태우·2024년 9월 11일

nbc_spring

목록 보기
14/28

이걸 왜 알아보려고 하지?

  • 자바를 이용한 알고리즘을 풀때 보통 Scanner 클래스를 이용하여 입력 받기도 하지만 대부분의 경우 BufferedReader 로 String 으로 입력을 받고 StringTokenizer 를 이용하여 띄어쓰기를 통해서 구분하여 입력 받는 것을 본 기억이 있다.

  • 입력 부분이기는 하나 생각보다 사용하는 메서드도 많고 여간 까다로운 것이 아니라 한번 제대로 이해해 보기로 했다.

1. 주요 메서드

생성자 / 메서드설명
StringTokenizer(String str, String delim)문자열(str)을 지정된 구분자(delim)로 나누는 StringTokenizer를 생성 (구분자는 토큰으로 간주되지 않음)
StringTokenizer(String str, String delim, boolean returnDelims)문자열 (str)을 지정된 구분자(delim)로 나누는 StringTokenizer를 생성하고 returnDelims 의 값을 true 로 하면 구분자도 토큰으로 간주된다.
int countTokens()전체 토큰의 수를 반환한다.
boolean hasMoreTokens()토큰이 남아 있는지 알려준다
String nextToken()다음 토큰을 반환한다.

2. 코딩을 통해 사용해보기

1)

package ch09_java_lang_package.StringTokenizerEx;

import java.util.StringTokenizer;

public class StringTokenizerEx01 {
    public static void main(String[] args) {
        String source = "100,200,300,400";
        StringTokenizer st = new StringTokenizer(source,","); 
        // 만약 두번째 인자가 없으면 디폴트로 공백문자, 개행문자로 취급
        while (st.hasMoreTokens()) {
            System.out.println(st.nextToken());
        }
    }
}

, 를 구분으로 하여 100, 200, 300, 400 을 토큰으로 저장한다.


2)

package ch09_java_lang_package.StringTokenizerEx;

import java.util.StringTokenizer;

public class StringTokenizerEx02 {
    public static void main(String[] args) {
        String expression = "x=100*(200+300)/2";
        StringTokenizer st = new StringTokenizer(expression, "+-*/=()", true);

        while(st.hasMoreTokens()) {
            System.out.println(st.nextToken());
        }
    }
}

위처럼 returnDelims 를 true 로 하게 되면 지정된 delim 도 토큰으로 지정되어 st.hasMoreTokens를 이용하여 출력을 할 수 있다.
""로 묶여진 delim의 경우 합쳐서가 아닌 하나하나의 문자로 구분된다.
(false 인 경우 연산자 제외 숫자만 나옴)


3)

package ch09_java_lang_package.StringTokenizerEx;

import java.util.StringTokenizer;

public class StringTokenizerEx03 {
    public static void main(String[] args) {
        String source = "1,김천재,100,100,100|2,박수재,95,80,90|3,이자바,80,90,90";
        StringTokenizer st = new StringTokenizer(source, "|");

        while (st.hasMoreTokens()) {
            String token = st.nextToken();

            StringTokenizer st2 = new StringTokenizer(token, ",");
            while (st2.hasMoreTokens()) {
                System.out.println(st2.nextToken());
            }
            System.out.println("----------------");
        }
    }
}

위 코드를 보면 | 문자를 기준으로 토큰을 생성하고 각 토큰을 또다시 , 를 기준으로 토큰들을 생성한다. (여러번의 토큰 사용) 그리고 각 토큰들을 출력하게 되는 코드예시이다.

4)

package ch09_java_lang_package.StringTokenizerEx;

import java.util.StringTokenizer;

public class StringTokenizerEx04 {
    public static void main(String[] args) {
        String input = "삼십만삼천백십오";
        System.out.println(input);
        System.out.println(hangulToNum(input));
    }

    public static long hangulToNum(String input) { // 한글을 숫자로 변경하는 메서드
        long result = 0;
        long tmpResult = 0;
        long num = 0;

        final String NUMBER = "영일이삼사오육칠팔구";
        final String UNIT = "십백천만억조";
        final long[] UNIT_NUM = {10, 100, 1000, 10000, (long) 1e8, (long) 1e12}; // 각각 십, 백, 천, 만, 억, 조 ...

        StringTokenizer st = new StringTokenizer(input, UNIT, true);
        while (st.hasMoreTokens()) {
            String token = st.nextToken();
            int check = NUMBER.indexOf(token);
            if (check == -1) { // 0~9 가 아닌 경우 (단위 숫자)
                if ("만억조".indexOf(token) == -1) {
                    tmpResult += (num != 0 ? num : 1) * UNIT_NUM[UNIT.indexOf(token)];
                } else {
                    tmpResult += num;
                    result += (tmpResult != 0 ? tmpResult : 1) * UNIT_NUM[UNIT.indexOf(token)];
                    tmpResult = 0;
                }
                num = 0;
            } else {
                num = check;
            }
        }
        return result + tmpResult + num;
    }
}

tokenizer를 이용하여 한글을 숫자로 바꾸는 다소 까다로운 문제이다.
tmpResult는 만억조와 같은 큰 단위가 나오기 전까지 십백천 단위의 값을 저장하기 위한 임시공간이고 result 가 실제 값을 저장하기 위한 공간이다.
한글로 된 숫자로 구분자(단위)로 잘라서 토큰이 숫자면 num 에 저장하고 단위면 num에 단위를 곱해서 tmpResult 에 저장한다.
ex) "삼십" 은 '3 * 10 = 30' 이 되어 tmpResult 에 저장된다.

"만삼천" 과 같이 숫자 없이 바로 단위로 시작하는 경우 nu의 값이 0이기 때문에 단위의 값을 곱해도 결과가 0이 되므로 삼항연산자를 이용해 num의 값을 1로 바꾼후 단위 값을 곱하도록 하였다.

그다음에 "만억조" 와 같이 큰 단위가 오면 tmpResult에 저장된 값에 큰 단위 값을 곱해서 result 에 저장하고 tmpResult는 0으로 초기화 한다.
ex) "삼십만" 은 tmpResult에 저장되어 있던 30에 10000을 곱해서 저장하고, tmpResult 는 0으로 초기화 한다.


5)

package ch09_java_lang_package.StringTokenizerEx;

import java.util.StringTokenizer;

public class StringTokenizerEx05 {
    public static void main(String[] args) {
        String data = "100,,,200,300";

        String[] result = data.split(",");
        StringTokenizer st = new StringTokenizer(data, ",");

        for(int i=0;i<result.length;i++){ // 단순히 split을 이용한 경우
            System.out.print(result[i] + "|");
        }
        System.out.println("개수 : " + result.length);

        int i=0;
        for(;st.hasMoreElements();i++){
            System.out.print(st.nextElement() + "|");
        }
        System.out.println("개수 : " + i);
    }
}

StringTokenizersplit 의 차이를 단적으로 보여주는 예시이다 위와 같이 , 가 여러개 있고 이경우 split을 사용하게 되면 길이가 5가 되는 반면
StringTokenizer를 이용하게 된다면 해당 값을 무시해버리면서 다른 값만 쪽 뽑아오게 되면서 해당 길이가 3이 되는 원하는 목표를 이룰 수 있게 된다.

profile
잘 부탁드립니다.

0개의 댓글