Awen's Blog

Sharing, Always Sharing ...
  首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

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

Posted on 2008-04-06 17:20  Awen's Blog  阅读(585)  评论(0编辑  收藏  举报

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