C++Builder Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
C++빌더 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
메신저 프로젝트
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
볼랜드포럼 광고 모집

C++빌더 팁&트릭
C++Builder Programming Tip&Tricks
[345] Java 소스의 변환을 위해... AnsiString용 StringTokenizer
김백일 [cedar] 7451 읽음    2002-06-11 11:05
안녕하세요? 김백일입니다.

지난번(342번)글에서 AnsiString용 토크나이저를 만들 때는,
TStrings 객체에 모든 토큰을 전부 저장하는 구조로 만들었습니다.
이런 구조는 대부분의 경우에 편리하기는 하지만,
경우에 따라서는 한번의 함수 호출에, 하나의 토큰 만을 얻어오는 인터페이스도
필요할 때가 있습니다.
strtok()나 자바의 StringTokenizer 같은 경우가 그런 예이죠.
(XML을 해보신분을 아시겠지만, 이건 마치 DOM과 SAX의 차이와 비슷합니다.)

이번에는 특히, 자바에서 C++로 전향하신 분들을 위해
자바의 StringTokenizer와 비슷한 클래스를 만들어 보았습니다.

StringTokenizer는 자바를 조금이라도 해보신 분들은 다 아실만한 클래스입니다.
자세한 내용은 다음 JDK의 다큐먼트를 참고하세요.
http://java.sun.com/j2se/1.4/docs/api/java/util/StringTokenizer.html

저는 이 StringTokenizer의 구조에 대해 한가지 불만이 있는데요,
토큰과 구분자(delimiter)를 얻는 인터페이스를 다르게하지 않고,
StringTokenizer 생성자의 인자인 returnDelims를 true로 하여
토큰과 구분자의 구별이 없이 리턴받는 점입니다.
리턴받은 다음에 if문으로 다시 검사를 해야하는 귀찮은 점이 있지요.
(물론 지난번 글의 토크나이저는 구분자를 아예 리턴하지도 않았지만요.
이유는? 단지 귀찮아서... -_-;;)

그래서 이번에 올리는 AnsiString용 StringTokenizer의 인터페이스는
이부분의 인터페이스를 자바의 것과 다르게 구현했습니다.
자바 소스에서 변환하실 때 이부분만 유의해서 보시면 되겠습니다.

//---------------------------------------------------------------------------
// 지난번(341번) 글에 있는
// FirstDelimiter(),FirstNotDelimiter() 정의가 필요합니다.
//---------------------------------------------------------------------------

const AnsiString DefaultDelim("\t\v\f\r\n ");

class StringTokenizer
{
public:
    StringTokenizer(AnsiString str)
        : Str(str), N(str.Length()), Delim(DefaultDelim), Start(1), Stop(0) {}
    StringTokenizer(AnsiString str, AnsiString delim)
        : Str(str), N(str.Length()), Delim(delim), Start(1), Stop(0) {}

    int countTokens() const;

    bool hasMoreTokens();

    char nextToken(AnsiString& token, AnsiString delim);
       char nextToken(AnsiString& token) { return nextToken(token, Delim); }
protected:
    AnsiString Str, Delim;
         int Start, Stop, N;
};

inline bool StringTokenizer::hasMoreTokens()
{
    Start = Stop < 1 ? FirstNotDelimiter(Delim, Str) :
            FirstNotDelimiter(Delim, Stop + 1, Str);
    Stop = FirstDelimiter(Delim, Start, Str);
    return 1 <= Start && Start <= N;
}

// 이 부분이 자바와 다릅니다.
// 토큰은 이 함수의 token 인자로 출력하고,
// 구분자는 리턴값으로 출력합니다.
// 이렇게 하는 것이 훨씬 이해하고 쉽고 편리하지요.
char StringTokenizer::nextToken(AnsiString& token, AnsiString Delim)
{
    char cRet;

    if (Stop < 1 || Stop > N) {
        Stop = N + 1;
        cRet = '\0';
    } else {
        cRet = Str[Stop];
    }
    token = Str.SubString(Start, Stop - Start);
    return cRet;
}

int StringTokenizer::countTokens() const
{
    int start, stop, count = 0;

    for(start = FirstNotDelimiter(Delim, Str);
        1 <= start && start <= N;
        start = FirstNotDelimiter(Delim, stop + 1, Str)) {
        stop = FirstDelimiter(Delim, start, Str);
        if (stop < 1 || stop > N + 1) stop = N;
        count++;
    }

    return count;
}

//---------------------------------------------------------------------------

#pragma argsused
int main(int argc, char* argv[])
{
    AnsiString token, sentence = "This sentence contains five words.";
    char retDelim;
    StringTokenizer st(sentence);
    cout << st.countTokens() << endl;
    while (st.hasMoreTokens()) {
        retDelim = st.nextToken(token);
        cout << token << " \"" << retDelim << "\"" << endl;
    }

    return 0;
}
//---------------------------------------------------------------------------

정원희 [freesoft]   2002-08-06 17:40 X
음.. 먼가 오해가 있으신거 같은데 JAVA의 StringTokenizer 의 경우 생성자에 returnDelim 지정 안해주고 그냥 스트링이랑 delim 만 지정해주셔도 됩니다.
정원희 [freesoft]   2002-08-06 17:40 X
딜리미터까지 리턴받고 싶으면 new StringTokenier(스트링, 딜리미터, true) 이렇게 해서 생성하면 되구요..

+ -

관련 글 리스트
345 Java 소스의 변환을 위해... AnsiString용 StringTokenizer 김백일 7451 2002/06/11
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.