條款2~3:GotW#29 不區分大小寫的string
阿新 • • 發佈:2018-12-29
編寫一個與標準的std::string類完全相同ci_string類,但是它與通常提供的擴充套件函式stricmp一樣是不區分大小寫的。ci_string應用能夠如下使用:
ci_string s("AbCde");
//不區分大小
assert(s == "abcde");
assert(s == "ABCDE");
assert(strcmp(s.c_str(),"AbCdE") == 0);
assert(strcmp(s.c_str(),"abcde") == 0);
C++標準庫中,string的標頭檔案宣告如下:
typedef basic_string<char> string; template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT> > class basic_string;
函式中,char_traits定義了字串之間的相互作用和比較的方式;char_traits模板提供了名為eq()和lt()的字串比較函式,提供了compare()和find()函式來比較和查詢字串,如果我們想這些函式有不同的行為表現,所要做的只是提供一個不同的char_traits模板:
struct ci_char_traits : public char_traits<char> { static bool eq(char c1,char c2) { return toupper(c1) == toupper(c2); } static bool lt(char c1,char c2) { return toupper(c1) < toupper(c2); } static int compare(const char* s1,const char* s2, size_t n) { return memicmp(s1,s2,n);//linux可以使用strncasecmp替代 } static const char* find(const char* s,int n,char a) { while(n-- > 0 && toupper(*s) != toupper(a)) { ++s; } return s; } } typedef basic_string<char,ci_char_traits> ci_string;
我們重新定義了一個ci_string,它的操作非常像標準的string,只是使用了ci_char_traits替代了char_traits<char>以使用特別的規則。
這次GotW揭示了basic_string模板工作的原理以及實現使用上的靈活性。
問題:
1.使用這種方式從char_traits<char>繼承ci_char_traits是安全的麼?
繼承是安全的,但是這裡不能多型的使用ci_char_traits。
2.為什麼如下的程式碼編譯失敗呢(由於C++的改進,現在可以編譯通過,並正常執行。)?
ci_string s = "abc"; cout << s << endl;
因為在C++標準庫中,base_string的operator<<宣告如下(C++標準中已將base_ostream<charT,traits>& os改為“ostream&”,所以沒問題了):
template<class charT,char traits,class Allocator>
basic_ostream<charT,traits>&
operator <<(basic_ostream<charT,traits>& os,
const basic_string<charT,traits,Allocator& str>);
有兩個解決方法:定義ci_string自己的輸入/輸出流函式,或使用".c_str()":
cout << s.c_str() << endl;
3.當在標準string物件和ci_string物件間使用其他的(如+,+=,=)時,例如:
sting a = "aaa";
ci_string b = "bbb";
string c = a + b;
解決方法還是定義自己的這些操作函式,或者新增使用“.c_str()”:
cout << c = a + b.c_str();