• 《原創》加強版的 C++ 字串型別


    1. Abstract
    std::string 與 std::wstring 是 C++ 提供的字串型別,雖然說已經相當不錯用,但與CString[1]、 C#、VB.Net等語言所提供的 String 型別相比較,還是沒那麼實用。

    2. Introduction
    在原本的 std::basic_string 上在添加更多的功能,如 format、trim、split等等。

      1 #ifndef HAVE_STD_STRINGEX_H_INCLUDED
      2 #define HAVE_STD_STRINGEX_H_INCLUDED

      3 ///================================================================================///
      4 ///================================================================================///
      5 ///<類別名稱>
      6 ///     - base_stringex_t (Ver.4)
      7 ///
         -
      8 ///<使用說明>

      9 ///     - 1. 加強 C++ 標準庫中所提供的 std::basic_string 的功能上不足。
     10 ///
         - 2. std::stringex  對應於 std::string。
     11 ///
         - 3. std::wstringex 對應於 std::wstring。
     12 ///
         - 4. 可以直接應用於 std::cout, std::cin, std::wcout, std::wcin。
     13 ///
         - 
     14 ///<名稱空間範圍>

     15 ///     - std
     16 ///
         - 
     17 ///<資料成員列表>

     18 ///     -
     19 ///<成員函式列表>

     20 ///     - format()
     21 ///
         - format_append()
     22 ///
         - trim_left()
     23 ///
         - trim_right()
     24 ///
         - trim()
     25 ///
         - trim_left()  [Static版本]
     26 ///
         - trim_right() [Static版本]
     27 ///
         - trim()       [Static版本]
     28 ///
         - to_long()
     29 ///
         - to_double()
     30 ///
         - to_lower()
     31 ///
         - to_upper()
     32 ///
         - to_lower() [Static版本]
     33 ///
         - to_upper() [Static版本]
     34 ///     - split()    [傳回對應的 std::vector<std::stringex> or std::vector<std::wstringex>
    ]
     35 ///
         - 
     36 ///<繼承類別列表>

     37 ///     - Please lookup source code.
     38 ///
         -
     39 ///<特殊備註>

     40 ///     - Author   : Awen.Su
     41 ///     - WebSite  : http://awen.cnblogs.com/

     42 ///     - Copyright: BSD License
     43 ///
         - Please do not remove the copyright information. Thank you !!!
     44 ///
         - 
     45 ///================================================================================///

     46 ///================================================================================///
     47 
     48 ///C/C++ STANDARD INCLUDES
     49 #include <string>
     50 #include <sstream>
     51 #include <vector>
     52 #include <typeinfo>
     53 #include <cstring>
     54 #include <cstdarg>
     55 #include <cwchar>
     56 #include <cctype>
     57 #include <cwctype>
     58 #include <algorithm>
     59 #include <iterator>
     60 
     61 ///================================================================================///
     62 ///================================================================================///
     63 namespace
     std {
     64 ///================================================================================///

     65 ///================================================================================///
     66 

     67 template <typename _Derived, typename _Elem>
     68 class base_stringex_format;
     69 

     70 template <typename _Derived>
     71 class base_stringex_format<_Derived, char>
     72 {
     73 protected
    :
     74     static const int MAX_BUFFER = 8192
    ;
     75 

     76 public:
     77     _Derived& format(const char *
    fmt, )
     78 
        {
     79         _Derived *THIS = static_cast<_Derived*>(this
    );
     80 

     81         char  buffer[MAX_BUFFER] = {0};
     82         int   result = 0
    ;
     83 

     84         va_list args;
     85 
            va_start(args, fmt);
     86 

     87         result = vsnprintf(buffer, MAX_BUFFER - 1, fmt, args);
     88 

     89         va_end(args);
     90 

     91         THIS->assign(buffer, result);
     92 

     93         return(*THIS);
     94 
        }
     95 
    };
     96 

     97 template <typename _Derived>
     98 class base_stringex_format<_Derived, wchar_t>
     99 {
    100 protected
    :
    101     static const int MAX_BUFFER = 8192
    ;
    102 

    103 public:
    104     _Derived& format(const wchar_t *
    fmt, )
    105 
        {
    106         /// 格式中的 %s 須改用 %S

    107 
    108         _Derived *THIS = static_cast<_Derived*>(this);
    109 

    110         wchar_t  buffer[MAX_BUFFER] = {0};
    111         int      result= 0
    ;
    112 

    113         va_list args;
    114 
            va_start(args, fmt);
    115 

    116         result = vswprintf(buffer, MAX_BUFFER - 1, fmt, args);
    117 

    118         va_end(args);
    119 

    120         THIS->assign(buffer, result);
    121 

    122         return(*THIS);
    123 
        }
    124 
    };
    125 

    126 ///================================================================================///
    127 ///================================================================================///
    128 

    129 template <typename _Derived, typename _Elem>
    130 class base_stringex_format_append;
    131 

    132 template <typename _Derived>
    133 class base_stringex_format_append<_Derived, char>
    134 {
    135 protected
    :
    136     static const int MAX_BUFFER = 8192
    ;
    137 

    138 public:
    139     _Derived& format_append(const char *
    fmt, )
    140 
        {
    141         _Derived *THIS = static_cast<_Derived*>(this
    );
    142 

    143         char  buffer[MAX_BUFFER] = {0};
    144         int   result = 0
    ;
    145 

    146         va_list args;
    147 
            va_start(args, fmt);
    148 

    149         result = vsnprintf(buffer, MAX_BUFFER - 1, fmt, args);
    150 

    151         va_end(args);
    152 

    153         THIS->append(buffer, result);
    154 

    155         return(*THIS);
    156 
        }
    157 
    };
    158 

    159 template <typename _Derived>
    160 class base_stringex_format_append<_Derived, wchar_t>
    161 {
    162 protected
    :
    163     static const int MAX_BUFFER = 8192
    ;
    164 

    165 public:
    166     _Derived& format_append(const wchar_t *
    fmt, )
    167 
        {
    168         /// 格式中的 %s 須改用 %S

    169 
    170         _Derived *THIS = static_cast<_Derived*>(this);
    171 

    172         wchar_t  buffer[MAX_BUFFER] = {0};
    173         int      result= 0
    ;
    174 

    175         va_list args;
    176 
            va_start(args, fmt);
    177 

    178         result = vswprintf(buffer, MAX_BUFFER - 1, fmt, args);
    179 

    180         va_end(args);
    181 

    182         THIS->append(buffer, result);
    183 

    184         return(*THIS);
    185 
        }
    186 
    };
    187 

    188 ///================================================================================///
    189 ///================================================================================///
    190 

    191 template <typename _Derived, typename _Elem>
    192 class base_stringex_trim_left;
    193 

    194 template <typename _Derived>
    195 class base_stringex_trim_left<_Derived, char>
    196 {
    197 public
    :
    198     _Derived&
     trim_left()
    199 
        {
    200         _Derived *THIS = static_cast<_Derived*>(this
    );
    201 

    202         typename _Derived::size_type position = THIS->find_first_not_of(" \t\r\n");
    203 
            
    204         if(position != std::basic_string<char>
    ::npos)
    205             THIS->erase(0
    , position);
    206         else

    207             THIS->erase();
    208 

    209         return *THIS;
    210 
        }
    211 

    212     static _Derived trim_left(const _Derived _Source)
    213 
        {
    214         return static_cast<_Derived>
    (_Source).trim_left();
    215 
        }
    216 
    };
    217 

    218 template <typename _Derived>
    219 class base_stringex_trim_left<_Derived, wchar_t>
    220 {
    221 public
    :
    222     _Derived&
     trim_left()
    223 
        {
    224         _Derived *THIS = static_cast<_Derived*>(this
    );
    225 

    226         typename _Derived::size_type position = THIS->find_first_not_of(L" \t\r\n");
    227 
            
    228         if(position != std::basic_string<wchar_t>
    ::npos)
    229             THIS->erase(0
    , position);
    230         else

    231             THIS->erase();
    232 

    233         return(*THIS);
    234 
        }
    235 

    236     static _Derived trim_left(const _Derived _Source)
    237 
        {
    238         return static_cast<_Derived>
    (_Source).trim_left();
    239 
        }
    240 
    };
    241 

    242 ///================================================================================///
    243 ///================================================================================///
    244 

    245 template <typename _Derived, typename _Elem>
    246 class base_stringex_trim_right;
    247 

    248 template <typename _Derived>
    249 class base_stringex_trim_right<_Derived, char>
    250 {
    251 public
    :
    252     _Derived&
     trim_right()
    253 
        {
    254         _Derived *THIS = static_cast<_Derived*>(this
    );
    255 

    256         typename _Derived::size_type position = THIS->find_last_not_of(" \t\r\n");
    257 

    258         if(position != std::basic_string<char>::npos)
    259             THIS->erase(++
    position);
    260 

    261         return(*THIS);
    262 
        }
    263 

    264     static _Derived trim_right(const _Derived _Source)
    265 
        {
    266         return static_cast<_Derived>
    (_Source).trim_right();
    267 
        }
    268 
    };
    269 

    270 template <typename _Derived>
    271 class base_stringex_trim_right<_Derived, wchar_t>
    272 {
    273 public
    :
    274     _Derived&
     trim_right()
    275 
        {
    276         _Derived *THIS = static_cast<_Derived*>(this
    );
    277 

    278         typename _Derived::size_type position = THIS->find_last_not_of(L" \t\r\n");
    279 

    280         if(position != std::basic_string<wchar_t>::npos)
    281             THIS->erase(++
    position);
    282 

    283         return(*THIS);
    284 
        }
    285 

    286     static _Derived trim_right(const _Derived _Source)
    287 
        {
    288         return static_cast<_Derived>
    (_Source).trim_right();
    289 
        }
    290 
    };
    291 

    292 ///================================================================================///
    293 ///================================================================================///
    294 

    295 template <typename _Derived, typename _Elem>
    296 class base_stringex_trim;
    297 

    298 template <typename _Derived>
    299 class base_stringex_trim<_Derived, char>
    300 {
    301 public
    :
    302     _Derived&
     trim()
    303 
        {
    304         _Derived *THIS = static_cast<_Derived*>(this
    );
    305 

    306         THIS->trim_left().trim_right();
    307 

    308         return(*THIS);
    309 
        }
    310 

    311     static _Derived trim(const _Derived _Source)
    312 
        {
    313         return static_cast<_Derived>
    (_Source).trim_left().trim_right();
    314 
        }
    315 
    };
    316 

    317 template <typename _Derived>
    318 class base_stringex_trim<_Derived, wchar_t>
    319 {
    320 public
    :
    321     _Derived&
     trim()
    322 
        {
    323         _Derived *THIS = static_cast<_Derived*>(this
    );
    324 

    325         THIS->trim_left().trim_right();
    326 

    327         return(*THIS);
    328 
        }
    329 

    330     static _Derived trim(const _Derived _Source)
    331 
        {
    332         return static_cast<_Derived>
    (_Source).trim_left().trim_right();
    333 
        }
    334 
    };
    335 ///================================================================================///

    336 ///================================================================================///
    337 

    338 template <typename _Derived, typename _Elem>
    339 class base_stringex_to_integer;
    340 

    341 template <typename _Derived>
    342 class base_stringex_to_integer<_Derived, char>
    343 {
    344 public
    :
    345     long
     to_long() const
    346 
        {
    347 
            std::stringstream _SS;
    348         long
                  _Result;
    349 
            
    350         _Derived *THIS = static_cast<_Derived*>(this
    );
    351 

    352         _SS << THIS->c_str();
    353         _SS >>
     _Result;
    354 
            _SS.clear();
    355 

    356         return _Result;
    357 
        }
    358 

    359     double to_double() const
    360 
        {
    361         _Derived *THIS = static_cast<_Derived*>(this
    );
    362 

    363         std::stringstream _SS;
    364         double
                 _Result;
    365 

    366         _SS << THIS->c_str();
    367         _SS >>
     _Result;
    368 
            _SS.clear();
    369 

    370         return _Result;
    371 
        }
    372 
    };
    373 

    374 template <typename _Derived>
    375 class base_stringex_to_integer<_Derived, wchar_t>
    376 {
    377 public
    :
    378     long
     to_long() const
    379 
        {
    380         _Derived *THIS = static_cast<_Derived*>(this
    );
    381 

    382         std::wstringstream _SS;
    383         long
                   _Result;
    384 

    385         _SS << THIS->c_str();
    386         _SS >>
     _Result;
    387 
            _SS.clear();
    388 

    389         return _Result;
    390 
        }
    391 

    392     double to_double() const
    393 
        {
    394         _Derived *THIS = static_cast<_Derived*>(this
    );
    395 

    396         std::wstringstream _SS;
    397         double
                 _Result;
    398 

    399         _SS << THIS->c_str();
    400         _SS >>
     _Result;
    401 
            _SS.clear();
    402 

    403         return _Result;
    404 
        }
    405 
    };
    406 

    407 ///================================================================================///
    408 ///================================================================================///
    409 

    410 template <typename _Derived, typename _Elem>
    411 class base_stringex_case_converter;
    412 

    413 template <typename _Derived>
    414 class base_stringex_case_converter<_Derived, char>
    415 {
    416 public
    :
    417     _Derived&
     to_lower()
    418 
        {
    419         _Derived *THIS = static_cast<_Derived*>(this
    );
    420 

    421         std::transform(THIS->begin(), THIS->end(), THIS->begin(), ::tolower);
    422 

    423         return *THIS;
    424 
        }
    425 

    426     _Derived& to_upper()
    427 
        {
    428         _Derived *THIS = static_cast<_Derived*>(this
    );
    429 

    430         std::transform(THIS->begin(), THIS->end(), THIS->begin(), ::toupper);
    431 

    432         return *THIS;
    433 
        }
    434 

    435     static _Derived to_lower(const _Derived &_In)
    436 
        {
    437 
            _Derived the_transfer;
    438 

    439         std::copy(_In.begin(), _In.end(), std::back_inserter(the_transfer));
    440 
            std::transform(the_transfer.begin(), the_transfer.end(), the_transfer.begin(), ::tolower);
    441 

    442         return the_transfer;
    443 
        }
    444 

    445     static _Derived to_upper(const _Derived &_In)
    446 
        {
    447 
            _Derived the_transfer;
    448 

    449         std::copy(_In.begin(), _In.end(), std::back_inserter(the_transfer));
    450 
            std::transform(the_transfer.begin(), the_transfer.end(), the_transfer.begin(), ::toupper);
    451 

    452         return the_transfer;
    453 
        }
    454 
    };
    455 

    456 
    457 template <typename _Derived>
    458 class base_stringex_case_converter<_Derived, wchar_t>
    459 {
    460 public
    :
    461     _Derived&
     to_lower()
    462 
        {
    463         _Derived *THIS = static_cast<_Derived*>(this
    );
    464 

    465         std::transform(THIS->begin(), THIS->end(), THIS->begin(), ::towlower);
    466 

    467         return *THIS;
    468 
        }
    469 

    470     _Derived& to_upper()
    471 
        {
    472         _Derived *THIS = static_cast<_Derived*>(this
    );
    473 

    474         std::transform(THIS->begin(), THIS->end(), THIS->begin(), ::towupper);
    475 

    476         return *THIS;
    477 
        }
    478 

    479     static _Derived to_lower(const _Derived &_In)
    480 
        {
    481 
            _Derived the_transfer;
    482 

    483         std::copy(_In.begin(), _In.end(), std::back_inserter(the_transfer));
    484 
            std::transform(the_transfer.begin(), the_transfer.end(), the_transfer.begin(), ::towlower);
    485 

    486         return the_transfer;
    487 
        }
    488 

    489     static _Derived to_upper(const _Derived &_In)
    490 
        {
    491 
            _Derived the_transfer;
    492 

    493         std::copy(_In.begin(), _In.end(), std::back_inserter(the_transfer));
    494 
            std::transform(the_transfer.begin(), the_transfer.end(), the_transfer.begin(), ::towupper);
    495 

    496         return the_transfer;
    497 
        }
    498 
    };
    499 

    500 ///================================================================================///
    501 ///================================================================================///
    502 template <typename _Derived, typename _Elem>

    503 class base_stringex_split
    504 
    {
    505 public
    :
    506     typename typedef std::vector<_Derived>
     split_type;
    507 

    508     split_type split(const _Derived &_Delimiter) const
    509 
        {
    510         _Derived *THIS = static_cast<_Derived*>(this
    );
    511 

    512         _Derived   the_handler = *THIS;
    513 
            split_type the_result;
    514         int
            the_cut_at;
    515 

    516         while((the_cut_at = the_handler.find_first_of(_Delimiter)) != the_handler.npos)
    517 
            {
    518             if(the_cut_at > 0
    )
    519 
                {
    520                 the_result.push_back(the_handler.substr(0
    , the_cut_at));
    521 
                }
    522 

    523             the_handler = the_handler.substr(the_cut_at + 1);
    524 
            }
    525 

    526         if(the_handler.length() > 0)
    527 
                the_result.push_back(the_handler);
    528 

    529         return the_result;
    530 
        }
    531 
    };
    532 

    533 ///================================================================================///
    534 ///================================================================================///
    535 // Class Implemented Here:

    536 ///================================================================================///
    537 ///================================================================================///
    538 template <typename _Elem>

    539 class base_stringex_t : public basic_string<_Elem>,
    540                         public base_stringex_format<base_stringex_t<_Elem>, _Elem>
    ,
    541                         public base_stringex_format_append<base_stringex_t<_Elem>, _Elem>
    ,
    542                         public base_stringex_trim_left<base_stringex_t<_Elem>, _Elem>
    ,
    543                         public base_stringex_trim_right<base_stringex_t<_Elem>, _Elem>
    ,
    544                         public base_stringex_trim<base_stringex_t<_Elem>, _Elem>
    ,
    545                         public base_stringex_to_integer<base_stringex_t<_Elem>, _Elem>
    ,
    546                         public base_stringex_case_converter<base_stringex_t<_Elem>, _Elem>
    ,
    547                         public base_stringex_split<base_stringex_t<_Elem>, _Elem>

    548 {
    549 public
    :
    550     typename typedef base_stringex_t<_Elem>
     impl_type;
    551 

    552     base_stringex_t() : std::basic_string<_Elem>() {}
    553     virtual ~
    base_stringex_t(){}
    554 

    555     base_stringex_t(const base_stringex_t<_Elem> &in) : std::basic_string<_Elem>()   { this->assign(in.c_str()); }
    556     base_stringex_t(const std::basic_string<_Elem> &in) : std::basic_string<_Elem>() { this->assign(in
    ); }
    557     base_stringex_t(const _Elem *in, size_t size) : std::basic_string<_Elem>()       { this->assign(in
    , size); }
    558     base_stringex_t(const _Elem *in) : std::basic_string<_Elem>()                    { this->assign(in
    ); }
    559 

    560     base_stringex_t& operator=(const base_stringex_t<_Elem> &in)
    561 
        {
    562         if(this == &inreturn(*this
    );
    563         this->assign(in
    .c_str());
    564         return(*this
    );
    565 
        }
    566 

    567     base_stringex_t& operator=(const std::basic_string<_Elem> &in) { this->assign(in); return(*this); }
    568     base_stringex_t& operator=(const _Elem *in)                    { this->assign(in); return(*this
    ); }
    569 

    570     operator const _Elem*() const { return((*this).c_str()); }
    571 };//class base_stringex_t

    572 
    573 typedef base_stringex_t<char>    stringex;
    574 typedef base_stringex_t<wchar_t>
     wstringex;
    575 

    576 }//namespace std
    577 #endif//HAVE_STD_STRINGEX_H_INCLUDED
    578 



    3. Conclusion
    目前此 std::base_stringex_t 已經實作的 function 均為 Awen 在實際專案上經常使用的功能。希望未來能實作更多其他的功能。

    4. Reference
    [1] CString Management,The Code Project,http://www.codeproject.com/KB/string/cstringmgmt.aspx

  • 相关阅读:
    [转载]每天要说无数次的话,原来英语这么说
    [转载]What I Have Lived For 一生何求?
    WIN 7 和fedora双系统引导问题
    [转载]网站建设中一些容易被忽视的问题
    linux进程控制-wait()
    shell(2)
    电脑英语缩略词
    shell(1)
    [转载]无论成败 但求做最好的自己
    [转载]C++出错提示英汉对照表
  • 原文地址:https://www.cnblogs.com/awen/p/1139293.html
Copyright © 2020-2023  润新知