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

C/C++ 팁&트릭
[37] [Boost]lexical_cast: 문자열을 숫자로, 또는 그 반대로 변환
김백일 [cedar] 16520 읽음    2002-08-29 00:37
문자열을 숫자로, 또는 그 반대로 변환하는 함수는
기존 C 라이브러리에 존재합니다.

우선 문자열을 숫자로 변환하는 함수는 다음과 같은 ANSI C 라이브러리에 있습니다.

char*를 int로 변환: atoi
char*를 long으로 변환: atol, strtol
char*를 double로 변환: atof, strtod

숫자를 문자열로 변환하는 함수는 ANSI C 라이브러리에는 없지만,
BC++에는 있습니다(VC++에도 있습니다.).

int를 char*로 변환: itoa
long을 char*로 변환: ltoa
double을 char*로 변환: ecvt, fcvt, gcvt

그 외에 번거롭지만, 다양한 서식을 지정할 수 있는 방법인,
sprintf와 sscanf를 사용하는 방법이 있지요.
C++에서는 stringstream 객체를 사용하는 방법이 있죠.

이러한 방법들은, 각 함수마다 사용법과 특성(확장성과 안정성 등)이 제각각이라,
일일히 레퍼런스(도움말)를 뒤져가며 사용해야 합니다.
C++에서는 문자열을 char* 보다는 string 객체를 쓰는 것을 권장하기 때문에
위의 C 함수를 쓰는 코드는 별로 깔끔해 보이지 않지요.
게다가, 기본 타입인 int, long, double 만을 변환할 수 있습니다.
std::complex나 boost::rational과 같은 것들은 물론 변환할 수 없죠.

어떠한 변환이든 항상 동일한 방법으로 할 수 있다면 편리하겠죠?
이를 위해 Boost 라이브러리는 lexical_cast 연산자(정확히는 템플릿 함수)를 제공합니다.
stringstream 객체를 사용하는 방법을 약간 개선한 겁니다.
stringstream 객체를 사용해서 변환하려면 별도의 로컬 변수를 선언하는 등,
귀찮은 점이 많은데요, 이런 것들을 간단하게 쓸 수 있는 템플릿 함수를 제공하는 거죠.

물론 lexical_cast의 구현은 매우 간단합니다.
컴파일러 환경 설정을 위한 잡다한 프리프로세서 문장을 모두 제거하면
다음 코드와 같습니다.
(부스트 라이브러리 전체를 설치하시기 싫으신 분은 다음 코드만 있으면 됩니다.)

    class bad_lexical_cast : public std::bad_cast
    {
    public:
        // constructors, destructors, and assignment operator defaulted

        // function inlined for brevity and consistency with rest of library
        virtual const char * what() const throw()
        {
            return "bad lexical cast: "
                   "source type value could not be interpreted as target";
        }
    };

    template<typename Target, typename Source>
    Target lexical_cast(Source arg)
    {
        std::stringstream interpreter;
        Target result;

        if(!(interpreter << arg) || !(interpreter >> result) ||
           !(interpreter >> std::ws).eof())
            throw bad_lexical_cast();

        return result;
    }

캐스팅에 실패하면 bad_lexical_cast(bad_cast 예외 클래스를 계승한) 예외를 throw하지요.
(dynamic_cast에서 캐스팅 실패시 bad_cast 예외를 throw하는 것은 알고 계시겠죠?)

사용법은 상당히 간단합니다. 간단한 예제 코드를 올립니다.

int main(int argc, char * argv[])
{
    using boost::lexical_cast;
    using boost::bad_lexical_cast;

    std::vector<short> args;

    while(*++argv)
    {
        try
        {
            args.push_back(lexical_cast<short>(*argv));
        }
        catch(bad_lexical_cast &)
        {
            args.push_back(0);
        }
    }
    ...
}

예외 처리 부분에 주목해보세요.
사실상 if ... else 대신 try ... catch 가 대신 사용되었다고 할 수 있지요.

+ -

관련 글 리스트
37 [Boost]lexical_cast: 문자열을 숫자로, 또는 그 반대로 변환 김백일 16520 2002/08/29
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.