사용자 도구

사이트 도구


kb:cppsnippetsstring


C++ / Snippets / String

문자열 관련 코드 조각들

문자열 조인&스플릿

#if defined(UNICODE) || defined(_UNICODE)
    typedef std::basic_string<wchar_t> tstring;
    typedef std::wstringstream tstringstream;
#else
    typedef std::basic_string<char> tstring;
    typedef std::stringstream tstringstream;
#endif
 
template <typename Iterator, typename Seperator>
tstring join(const Iterator& first, const Iterator& last, Seperator seperator)
{
    tstringstream stream;
    stream.imbue(std::locale::classic());
    for (Iterator itr(first); itr != last; ++itr)
    {
        if (std::distance(itr, last) > 1)
            stream << *itr << seperator;
        else
            stream << *itr;
    }
    return stream.str();
}
 
template <typename Iterator, typename Selector, typename Seperator>
tstring join(const Iterator& first, const Iterator& last, Selector selector, Seperator seperator)
{
    tstringstream stream;
    stream.imbue(std::locale::classic());
    for (Iterator itr(first); itr != last; ++itr)
    {
        if (std::distance(itr, last) > 1)
            stream << selector(*itr) << seperator;
        else
            stream << selector(*itr);
    }
    return stream.str();
}
 
template <typename Container>
void split(const tstring& text, TCHAR seperator, Container& result)
{
    std::back_insert_iterator<Container> inserter(result);
 
    size_t before = 0, end = 0;
    tstring token = _T("");
    while (before < text.size() && end < text.size())
    {
        if ((end = text.find_first_of(seperator, before)) != tstring::npos)
        {
            token = text.substr(before, end - before);
 
            if (!token.empty())
                *inserter = token;
 
            before = end + 1;
        }
        else
        {
            token = text.substr(before, text.size() - before);
            if (!token.empty()) { *inserter = token; }
            break;
        }
    }
}
 
template <typename Container>
void split(const tstring& text, const tstring& seperators, Container& result)
{
    std::back_insert_iterator<Container> inserter(result);
 
    size_t before = 0, end = 0;
    tstring token = _T("");
    while (before < text.size() && end < text.size())
    {
        if ((end = text.find_first_of(seperators, before)) != tstring::npos)
        {
            token = text.substr(before, end - before);
 
            if (!token.empty())
                *inserter = token;
 
            before = end + 1;
        }
        else
        {
            token = text.substr(before, text.size() - before);
            if (!token.empty()) { *inserter = token; }
            break;
        }
    }
}

조인의 경우, stringstream에 집어넣을 수 있는 타입이라면 아무 거나 문자열로 만들 수 있다.

문자열 좌우의 공백을 제거하기

std::string trim_right(const std::string& source, const std::string& whitespaces=" \t\r\n")
{
    std::string str(source);
    return str.erase(str.find_last_not_of(whitespaces) + 1);
}
 
std::string trim_left(const std::string& source, const std::string& whitespaces=" \t\r\n")
{
    std::string str(source);
    return str.erase(0, str.find_first_not_of(whitespaces));
}
 
std::string trim(const std::string& source, const std::string& whitespaces=" \t\r\n")
{
    std::string str(source);
    return trim_left(trim_right(source, whitespaces), whitespaces);
}
 
std::wstring trim_right(const std::wstring& source, const std::wstring& whitespaces=L" \t\r\n")
{
    std::wstring str(source);
    return str.erase(str.find_last_not_of(whitespaces) + 1);
}
 
std::wstring trim_left(const std::wstring& source, const std::wstring& whitespaces=L" \t\r\n")
{
    std::wstring str(source);
    return str.erase(0, str.find_first_not_of(whitespaces));
}
 
std::wstring trim(const std::wstring& source, const std::wstring& whitespaces=L" \t\r\n")
{
    std::wstring str(source);
    return trim_left(trim_right(source, whitespaces), whitespaces);
}

속도가 중요하다면 좀 모양이 그렇다만, 다음과 같은 코드가 낫다. 위 코드에 비해 2배 정도 빠르다. 임시 객체를 생성하지 않기 때문이다.

std::string trim(const std::string& str, const std::string& whitespaces=" \t\r\n")
{
    std::string result("");
 
    size_t begin = source.find_first_not_of(whitespaces);
    size_t end = source.find_last_not_of(whitespaces);
    if (begin != std::string::npos && end != std::string::npos)
        result = source.substr(begin, end - begin + 1);
 
    return result;
}

문자열에서 find & replace 수행하기

/// \brief 주어진 문자열 내에 존재하는 문자열을 다른 문자열로 치환한다.
/// \param text 원본 문자열
/// \param find_token 찾고자 하는 문자열
/// \param replace_token 치환하고자 하는 문자열
void replace(std::string& text, const std::string& find_token, const std::string& replace_token)
{
    size_t i = 0;
    while ((i = text.find(find_token)) != string::npos)
        text.replace(i, find_token.size(), replace_token);
}

응용하면 다음과 같은 함수도 만들 수 있다.

/// \brief 문장 내부에 연속적인 대상 문자를 하나로 만든다.
///
/// 즉 target을 ' '로 준 경우, 두 개 이상의 ' '를 하나의 ' '로 만든다.
/// 
/// \param text 원본 문자열
/// \param target 대상이 되는 글자
/// \return string 변환한 문자열
std::string squeeze(const std::string& text, char target)
{
    std::string str(text);
    replace(str, string(2, target), string(1, target));
    return str;
}

find_first_not_of, find_last_not_of C 버전 구현

// find_first_not_of
const char* str_spnp(const char* str, const char* charset) 
{ 
    return str == NULL ? NULL : ((*(str += strspn(str, charset)) != 0) ? str : NULL); 
}
 
// find_first_not_of
const wchar_t* wcs_spnp(const wchar_t* str, const wchar_t* charset) 
{ 
    return str == NULL ? NULL : ((*(str += wcsspn(str, charset)) != 0) ? str : NULL);
}
 
// find_last_not_of
const char* str_rspnp(const char* str, const char* charset)
{
    const char* last = NULL;
    const char* current = str;
 
    for (; *current; ++current)
    {
        if (!strchr(charset, *current))
            last = current;
    }
 
    return last;
}
 
// find_last_not_of
const wchar_t* wcs_rspnp(const wchar_t* str, const wchar_t* charset)
{
    const wchar_t* last = NULL;
    const wchar_t* current = str;
 
    for (; *current; ++current)
    {
        if (!wcschr(charset, *current))
            last = current;
    }
 
    return last;
}
 
#if defined(UNICODE) || defined(_UNICODE)
    #define tstrspnp(str, charset)  wcs_spnp(str, charset)
    #define tstrrspnp(str, charset) wcs_rspnp(str, charset)
#else
    #define tstrspnp(str, charset)  str_spnp(str, charset)
    #define tstrrspnp(str, charset) str_rspnp(str, charset)
#endif

kb/cppsnippetsstring.txt · 마지막으로 수정됨: 2014/11/10 19:05 (바깥 편집)