標籤:char_traits c++ stl cstring cwchar
本人寫過與此相關的兩篇部落格,一個是<cstring>標頭檔的實現,另一個是<cwchar>的實現,這裡的char_traits模板類在此基礎上實現。
為了方便,將原始碼一起封裝於名字空間mystd裡。
代碼如下!!!
// 此檔案命名為 "char_traits.h"// vs2012 調試通過#pragma once #ifndef MYSTD_CHAR_TRAITS_H#define MYSTD_CHAR_TRAITS_H#include<cstddef> // std::size_t #include<cassert>#pragma push_macro("EOF")#undef EOF #define EOF (-1)#pragma push_macro("WEOF")#undef WEOF #define WEOF (unsigned short)(0xFFFF)#define MYSTD_BEGIN namespace mystd{#define MYSTD_END }#ifdef __cplusplusMYSTD_BEGIN //cstring.htypedef std::size_t size_type;typedef unsigned char UCHAR;// C語言版本,void * memchr(const void *,int,size_type); inline const void* memchr(const void *pointer,int val, size_type num){assert(pointer != 0);UCHAR *ptr = (UCHAR*)pointer; for(size_type i = 0; i < num; ++i){if(*ptr == val)break;++ptr;}return ptr;} inline void* memchr(void *pointer, int val,size_type num) //c++重載{assert(pointer != 0);return (void*)mystd::memchr((const void*)pointer,val,num); // 轉調}inline size_type strlen(const char *str){assert(str != 0);size_type count = 0;while(*str++)++count;return count;}inline void* memmove(void *destination,const void *source, size_type num){ // 對於memmove函數的實現,c++之父在《c++ 程式設計語言》(十周年中文紀念版第16章開篇) //就說過,此函數無法由c++語言本身達到最優實現,實際應用時還是用標準庫吧! assert(destination != 0 && source != 0); if(destination == source || num == 0)return destination;UCHAR *des = (UCHAR*)destination; const UCHAR *src = (UCHAR*)source; if(des < src || des >= src + num) {while(num--)*des++ = *src++;return destination;}des += num;src += num;while(num--) // 倒序複製*--des = *--src;return destination;}inline void* memcpy(void *destination,const void *source, size_type num){assert(destination != 0 && source != 0);return mystd::memmove(destination,source,num);}inline int memcmp(const void *pointer_1,const void *pointer_2,size_type num){assert(pointer_1 != 0 && pointer_2 != 0);const UCHAR *ptr_1 = (UCHAR*)pointer_1;const UCHAR *ptr_2 = (UCHAR*)pointer_2;while(num-- && *ptr_1 == *ptr_2)++ptr_1,++ptr_2;if(num == size_type(-1))return 0;elsereturn *ptr_1 - *ptr_2;}inline void* memset(void *pointer,int val,size_type num){assert(pointer != 0);UCHAR *ptr = (UCHAR*)pointer;while(num--)*ptr++ = val;return pointer;}inline char* strcat(char *destination,const char *source){assert(destination != 0 && source != 0);char *ptr = destination + mystd::strlen(destination);while(*ptr++ = *source++);return destination;}inline char *strncat(char *destination,const char *source,size_type num){assert(destination != 0 && source != 0);char *ptr = destination + mystd::strlen(destination);while(num-- && *source)*ptr++ = *source++;*ptr = 0; // null-character 複製return destination;}inline char *strcpy(char *destination,const char *source){assert(destination != 0 && source != 0);char *des = destination;while(*des++ = *source++); return destination; // null-character被複製}inline char *strncpy(char *destination,const char *source,size_type num){assert(destination != 0 && source != 0);char *des = destination;while(num--)*des++ = *source++; return destination; // null-character可能沒有被複製}inline int strcmp(const char *str1,const char *str2){ assert(str1 != 0 && str2 != 0); while(*str1 && *str1 == *str2) ++str1, ++str2; return *str1 - *str2;}inline int strncmp(const char *str1,const char *str2,size_type num){assert(str1 != 0 && str2 != 0);while(num-- && *str1 && *str1 == *str2)++str1, ++str2;if(num == size_type(-1)) // 包含了num == 0的情況return 0;elsereturn *str1 - *str2;}//C語言只有一個版本 char* strchr(const char *, int); inline const char* strchr(const char *str,int character){assert(str != 0);// 語言標準規定character 為int,這裡轉換一下const char chr = *(char*)&character;while(*str && *str != chr) ++str;if(*str)return str;elsereturn 0;} inline char* strchr(char *str,int character) //c++重載{assert(str != 0);return (char*)mystd::strchr((const char*)str,character);}inline const char* strrchr(const char *str,int character){ //這裡的character 可能包括null-characterassert(str != 0);// 語言標準規定character 為int,這裡轉換一下const char chr = *(char*)&character;size_type len = mystd::strlen(str);const char *ptr = str + len;if(chr == 0)return ptr;--ptr;while(len--)if(*ptr == chr)return ptr;else--ptr;return 0; //無匹配的字元} inline char* strrchr(char *str,int character){assert(str != 0);return (char*)mystd::strrchr((const char*)str,character); // 轉調}//c語言版本char* strstr(const char *,const char*);inline const char* strstr(const char* str1,const char* str2){assert(str1 != 0 && str2 != 0);size_type len_1 = mystd::strlen(str1);size_type len_2 = mystd::strlen(str2);if(len_1 < len_2) return 0;const char *search_last = str1 + (len_1 - len_2);while(str1 <= search_last){if(mystd::strncmp(str1,str2,len_2) == 0)return str1;else++str1;}return 0;} inline char* strstr(char *str1,const char *str2) //c++重載{assert(str1 != 0 && str2 != 0);return (char*)mystd::strstr((const char*)str1,str2);}inline bool is_inside(const char *str,char chr) // 輔助函數,內部使用{assert(str != 0);while(*str){if(*str == chr)return true;else ++str;}return false;}inline size_type strspn(const char* str1,const char *str2){assert(str1 != 0 && str2 != 0);size_type count = 0;while(*str1 && is_inside(str2,*str1)) ++count, ++str1;return count;}inline size_type strcspn(const char* str1,const char *str2){assert(str1 != 0 && str2 != 0);size_type count = 0;while(*str1 && !is_inside(str2,*str1))++count, ++str1;return count;}// c語言版本char* strpbrk(const char *,const char *); inline const char* strpbrk(const char *str1,const char *str2){assert(str1 != 0 && str2 != 0);while(*str1 && !is_inside(str2,*str1))++str1;if(*str1 == 0)return 0;elsereturn str1;} inline char* strpbrk(char *str1,const char *str2) //c++重載{assert(str1 != 0 && str2 != 0);return (char*)strpbrk((const char*)str1,str2); //轉調}inline char* strtok(char *str,const char *delim){ #ifdef _DEBUGstatic bool first_switch = false;if(!first_switch)assert(str != 0);assert(delim != 0);#endifstatic char * p_location = 0; //記錄搜尋起始位置if(str)p_location = str;char *ptr = mystd::strpbrk(p_location,delim);char *temp = p_location;if(ptr == 0) // 找不到分隔字元,預設為搜尋結束{#ifdef _DEBUGfirst_switch = false; // 搜尋結束,first_switch置為false #endifp_location = 0; // 搜尋結束,p_location 複位return temp;}#ifdef _DEBUGfirst_switch = true;#endif*ptr = 0;p_location = ptr + 1; // 位置更新return temp;}inline size_type strxfrm(char *destination,const char *source,size_type num);inline int strcoll(const char *str1,const char *str2);inline char* strerror(int errnum);MYSTD_END // end of namespace mystd MYSTD_BEGIN //寬字元版本typedef std::size_t size_type;typedef wchar_t char_type;inline size_type wcslen(const char_type* wcs){ assert(wcs != 0); size_type count = 0; while(*wcs++) ++count; return count;}inline char_type* wcscat(char_type* destination,const char_type *source){assert(destination != 0 && source != 0);char_type *des = destination + mystd::wcslen(destination);while(*des++ = *source++);return destination;}inline char_type* wcsncat(char_type* destination,const char_type *source,size_type num){assert(destination != 0 && source != 0);char_type *des = destination + mystd::wcslen(destination);while(num-- && *source)*des++ = *source++;*des = 0; return destination;}inline char_type* wcscpy(char_type *destination,const char_type *source){assert(destination != 0 && source != 0);char_type *des = destination;while(*des++ = *source++);return destination;}inline char_type* wcsncpy(char_type *destination,const char_type *source,size_type num){assert(destination != 0 && source != 0);char_type *des = destination;while(num--)*des++ = *source++; return destination; // 可能不包含null wide character }inline int wcscmp(const char_type *wcs1,const char_type *wcs2){assert(wcs1 != 0 && wcs2 != 0);while(*wcs1 && *wcs1 == *wcs2)++wcs1, ++wcs2;return *wcs1 - *wcs2;}inline int wcsncmp(const char_type *wcs1,const char_type *wcs2,size_type num){assert(wcs1 != 0 && wcs2 != 0);while(num-- && *wcs1 && *wcs1 == *wcs2)++wcs1, ++wcs2;if(num == size_type(-1)) // 包含了num == 0的情況return 0;elsereturn *wcs1 - *wcs2;}inline const char_type* wmemchr(const char_type* pointer,char_type val,size_type num){ assert(pointer != 0);char_type *ptr = (char_type*)pointer; for(size_type i = 0; i < num; ++i){if(*ptr == val)break;++ptr;}return ptr;} inline char_type* wmemchr(char_type* pointer,char_type val,size_type num){assert(pointer != 0);return (char_type*)wmemchr((const char_type*)pointer,val,num);}inline int wmemcmp(const char_type *ptr_1,const char_type *ptr_2,size_type num){assert(ptr_1 != 0 && ptr_2 != 0);while(num-- && *ptr_1 == *ptr_2)++ptr_1, ++ptr_2;if(num == size_type(-1))return 0;elsereturn *ptr_1 - *ptr_2;}inline char_type* wmemset(char_type *pointer,char_type val,size_type num){assert(pointer != 0);char_type *ptr = pointer;while(num--)*ptr++ = val;return pointer;}inline char_type* wmemmove(char_type *destination,const char_type *source,size_type num){assert(destination != 0 && source != 0); if(destination == source || num == 0)return destination;char_type *des = (char_type*)destination; const char_type *src = (char_type*)source; if(des < src || des >= src + num) {while(num--)*des++ = *src++;return destination;}des += num;src += num;while(num--) // 倒序複製*--des = *--src;return destination;}inline char_type* wmemcpy(char_type *destination,const char_type *source,size_type num){assert(destination != 0 && source != 0);return mystd::wmemmove(destination,source,num);}inline bool w_is_inside(const char_type *wcs,char_type val) // 輔助函數,內部使用{assert(wcs != 0);while(*wcs){if(*wcs == val)return true;else ++wcs;}return false;}inline size_type wcsspn(const char_type *wcs1,const char_type *wcs2){assert(wcs1 != 0 && wcs2 != 0);size_type count = 0;while(*wcs1 && w_is_inside(wcs2,*wcs1))++count, ++wcs1;return count;}inline size_type wcscspn(const char_type *wcs1,const char_type *wcs2){assert(wcs1 != 0 && wcs2 != 0);size_type count = 0;while(*wcs1 && !w_is_inside(wcs2,*wcs1))++count, ++wcs1;return count;}inline const char_type* wcsstr(const char_type *wcs1,const char_type *wcs2){assert(wcs1 != 0 && wcs2 != 0);size_type len_1 = mystd::wcslen(wcs1);size_type len_2 = mystd::wcslen(wcs2);if(len_1 < len_2) return 0;const char_type *search_last = wcs1 + (len_1 - len_2);while(wcs1 <= search_last){if(mystd::wcsncmp(wcs1,wcs2,len_2) == 0)return wcs1;else++wcs1;}return 0;} inline char_type* wcsstr(char_type *wcs1,const char_type *wcs2){assert(wcs1 != 0 && wcs2 != 0);return (char_type*)mystd::wcsstr((const char_type*)wcs1,wcs2);}inline const char_type* wcschr(const char_type *wcs,char_type val){assert(wcs != 0);while(*wcs && *wcs != val)++wcs;if(*wcs)return wcs;elsereturn 0;}inline char_type* wcschr(char_type *wcs,char_type val){assert(wcs != 0);return (char_type*)mystd::wcschr((const char_type*)wcs,val);}inline const char_type* wcsrchr(const char_type *wcs,char_type val){ // val可能為null wide character assert(wcs != 0);size_type len = mystd::wcslen(wcs);const char_type *ptr = wcs + len;if(val == 0)return ptr;--ptr;while(len--)if(*ptr == val)return ptr;else--ptr;return 0; //無匹配的字元}inline char_type* wcsrchr(char_type *wcs,char_type val){ //val可能為null wide character assert(wcs != 0);return (char_type*)mystd::wcsrchr((const char_type*)wcs,val); // 轉調} inline const char_type* wcspbrk(const char_type *wcs1,const char_type *wcs2){assert(wcs1 != 0 && wcs2 != 0);while(*wcs1 && !w_is_inside(wcs2,*wcs1))++wcs1;if(*wcs1 == 0)return 0;elsereturn wcs1;}inline char_type* wcspbrk(char_type *wcs1,const char_type *wcs2){assert(wcs1 != 0 && wcs2 != 0);return (char_type*)mystd::wcspbrk((const char_type*)wcs1,wcs2);}inline char_type* wcstok(char_type *wcs,const char_type *delim){#ifdef _DEBUGstatic bool first_switch = false;if(!first_switch)assert(wcs != 0);assert(delim != 0);#endifstatic char_type * p_location = 0; //記錄搜尋起始位置if(wcs)p_location = wcs;char_type *ptr = mystd::wcspbrk(p_location,delim);char_type *temp = p_location;if(ptr == 0) // 找不到分隔字元,預設為搜尋結束{#ifdef _DEBUGfirst_switch = false; // 搜尋結束,first_switch置為false #endifp_location = 0; // 搜尋結束,p_location 複位return temp;}#ifdef _DEBUGfirst_switch = true;#endif*ptr = 0;p_location = ptr + 1; // 位置更新return temp;}inline size_type wcsxfrm(char_type *destination,const char_type *source,size_type num); MYSTD_ENDMYSTD_BEGIN typedef unsigned short wint_t;template<class charT>struct char_traits{typedef std::size_t size_type;};template<> // char特化struct char_traits<char>{typedef int int_type;typedef char char_type;public:static size_type length(const char_type *str) throw(){assert(str != 0);return mystd::strlen(str);} static void assign(char_type& chr,const char_type& val) throw() { chr = val; } static char_type assign(char_type *ptr,size_type num,char_type chr) throw() { assert(ptr != 0); mystd::memset(ptr,chr,num); return chr; } static int compare(const char_type *str1,const char_type *str2,size_type num) throw() { assert(str1 != 0 && str2 != 0); return mystd::strncmp(str1,str2,num); // 注意C風格字串 } static char_type* move(char_type *des,const char_type *src,size_type num) throw() { assert(des != 0 && src != 0);#ifdef _DEBUG return (char_type*)mystd::memmove(des,src,num);#else return (char_type*)std::memmove(des,src,num); // 標準庫版本效率更高#endif } static char_type* copy(char_type *des,const char_type *src,size_type num) throw() { assert(des != 0 && src != 0);#ifdef _DEBUG return (char_type*)mystd::memcpy(des,src,num);#else return (char_type*)std::memcpy(des,src,num); // 標準庫版本效率更高#endif } static bool eq(const char_type& chr_1,const char_type& chr_2) { return chr_1 == chr_2; } static const char_type* find(const char_type* ptr,size_t num,const char_type& chr) { assert(ptr != 0); while(num-- && *ptr != chr) ++ptr; if(*ptr == chr && num != size_type(-1)) // 不依賴於null character return ptr; else return 0; } static char_type to_char_type(const int_type& chr) throw() { assert(chr < 0xFF); return *(char_type*)&chr; } static int_type to_int_type(const char_type& chr) throw() { return static_cast<char_type>(chr); } static int_type eof() throw() { return EOF; }};template<> // 寬字元版本struct char_traits<wchar_t>{typedef wint_t int_type;typedef wchar_t char_type;public:static size_type length(const char_type *wcs) throw(){return mystd::wcslen(wcs);} static void assign(char_type& wc,const char_type& val) throw() { wc = val; } static char_type assign(char_type *ptr,size_type num,char_type wc) throw() { assert(ptr != 0); while(num--) *ptr++ = wc; return wc; } static int compare(const char_type *wcs1,const char_type *wcs2,size_type num) throw() { assert(wcs1 != 0 && wcs2 != 0); return mystd::wcsncmp(wcs1,wcs2,num); } static char_type* move(char_type *des,const char_type *src,size_type num) throw() { assert(des != 0 && src != 0);#ifdef _DEBUG return (char_type*)mystd::wmemmove(des,src,num);#else return (char_type*)std::wmemmove(des,src,num); // 標準庫版本效率更高#endif } static char_type* copy(char_type *des,const char_type *src,size_type num) throw() { assert(des != 0 && src != 0);#ifdef _DEBUG return (char_type*)mystd::wmemcpy(des,src,num);#else return (char_type*)std::wmemcpy(des,src,num); // 標準庫版本效率更高#endif } static bool eq(const char_type& wc_1,const char_type& wc_2) { return wc_1 == wc_2; } static const char_type* find(const char_type* ptr,size_t num,const char_type& wc) { assert(ptr != 0); while(*ptr && num-- && *ptr != wc) ++ptr; if(*ptr == wc) return ptr; else return 0; } static char_type to_char_type(const int_type& wc) throw() { assert(wc < 0xFFFF); return wc; } static int_type to_int_type(const char_type& wc) throw() { assert(wc < 0xFFFF); return wc; } static int_type eof() throw() { return WEOF; }};MYSTD_END // end of namespace mystd #endif // __cplusplus #pragma pop_macro("WEOF")#pragma pop_macro("EOF") #endif // MYSTD_CHAR_TRAITS_H
希望高手批評指正!!!
c++ char_traits模板類的實現!!!