사용자 도구

사이트 도구


kb:cppsnippetsstring

차이

문서의 선택한 두 판 사이의 차이를 보여줍니다.

차이 보기로 링크

kb:cppsnippetsstring [2014/11/10 19:05] (현재)
줄 1: 줄 1:
 +{{INLINETOC}}
 +\\
 +
 +====== C++ / Snippets / String ======
 +문자열 관련 코드 조각들
 +
 +====== 문자열 조인&​스플릿 ======
 +<code cpp>
 +#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;
 +        }
 +    }
 +}
 +</​code>​
 +조인의 경우, stringstream에 집어넣을 수 있는 타입이라면 아무 거나 문자열로 만들 수 있다.
 +
 +====== 문자열 좌우의 공백을 제거하기 ======
 +<code cpp>
 +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);​
 +}
 +</​code>​
 +
 +속도가 중요하다면 좀 모양이 그렇다만,​ 다음과 같은 코드가 낫다. 위 코드에 비해 2배 정도 빠르다. 임시 객체를 생성하지 않기 때문이다.
 +
 +<code cpp>
 +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;
 +}
 +</​code>​
 +
 +====== 문자열에서 find & replace 수행하기 ======
 +<code cpp>
 +/// \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);​
 +}
 +</​code>​
 +
 +응용하면 다음과 같은 함수도 만들 수 있다.
 +
 +<code cpp>
 +/// \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;
 +}
 +</​code>​
 +
 +====== find_first_not_of,​ find_last_not_of C 버전 구현 ======
 +<code cpp>
 +// 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
 +</​code>​
 +
 +----
 +  * see also [[CppSnippets|C++ Snippets]]
  
kb/cppsnippetsstring.txt · 마지막으로 수정됨: 2014/11/10 19:05 (바깥 편집)