设为首页 加入收藏

TOP

条款2:大小写不敏感的字符串--之一(1)
2013-10-07 15:18:06 来源: 作者: 【 】 浏览:67
Tags:条款 大小写 敏感 字符串 之一

条款2:大小写不敏感的字符串--之一(1)

是否需要一个大小写不敏感(case-insensitive)的字符串类?如果乐意的话,你可以自己编写一个。

在本条款中包括以下三个相关的问题。

1."大小写不敏感"的含义是什么?

2.编写一个ci_string类,并且这个类的用法与标准库中std::string类一致。不同的是,ci_string对大小写不敏感,与通常提供的标准库扩展函数stricmp() 一样。ci_string应该可以像下面这样使用:

  1. ci_string s( "AbCdE" );   
  2. // 大小写不敏感  
  3. //  
  4. assert( s == "abcde" );  
  5. assert( s == "ABCDE" );  
  6. // 当然,大小写将保持不变  
  7. //  
  8. assert( strcmp( s.c_str(), "AbCdE" ) == 0 );  
  9. assert( strcmp( s.c_str(), "abcde" ) != 0 );  

3.将大小写敏感作为对象的属性是否合适?

解答

上述三个问题的解答如下所示。

1."大小写不敏感"的含义是什么?

"大小写不敏感"的确切含义完全取决于你的应用程序和所使用的自然语言。例如,在许多自然语言中根本就没有大小写的概念。而对于那些支持大小写的自然语言,你可能还需要决定重音字符与非重音字符在比较时是否相等,以及其他一些诸如此类的情况。本条款所要解答的问题是:如何在标准的字符串上实现大小写不敏感性,而不考虑你所处的语言环境是什么。

2.编写一个ci_string类,并且这个类的用法与标准库中std::string类一致。不同的是,ci_string对大小写不敏感,与通常提供的标准库扩展函数stricmp()一样。

像"如何实现一个大小写不敏感的字符串类"这样的问题太常见了,我们甚至可以为其建立一个FAQ--因此就有了本条款。

以下是我们想要实现的功能:

  1. ci_string s( "AbCdE" );   
  2. // 大小写不敏感  
  3. //  
  4. assert( s == "abcde" );  
  5. assert( s == "ABCDE" );  
  6. //当然,大小写将保持不变  
  7. //  
  8. assert( strcmp( s.c_str(), "AbCdE" ) == 0 );  
  9. assert( strcmp( s.c_str(), "abcde" ) != 0 );  

这里的关键之处在于:我们要理解在标准C++(www.cppentry.com)中,string类的底层表示是什么。如果查看string的头文件,将会看到下面这样的代码:
  1. typedef basic_string<char> string;  

从上面可以看到,string并不是一个类,它实际上是一个由模板生成的类型。然后,我们来看看下面模板basic_string<>的声明,其中也可以指定其他的模板特化参数:
  1. template<class charT,   
  2.             class traits = char_traits<charT>,  
  3.         class Allocator = allocator<charT> > 
  4. class basic_string;  

因此,"string"的实际含义是"basic_string<char, char_traits<char>, allocator<char> >",在使用这个模板时也可以指定其他的模板特化参数。在这里无须关心allocator部分,重点在于char_traits部分,因为char_traits定义了字符之间的交互方式--包括字符的比较。

现在来对字符串进行比较。在basic_string模板类中提供了一些有用的比较函数,通过这些函数可以知道一个字符串是否等于、小于,或者大于另外一个字符串等等。这些字符串比较函数都是建立在char_traits模板提供的字符比较函数之上的。例如,在char_traits模板中提供了字符比较函数eq()和lt(),来比较两个字符是否相等,以及一个字符是否小于另一个,此外还提供compare()和find()这两个函数来对字符串进行比较和查找。

如果希望改变这些字符串比较函数的行为,那么就需要提供一个不同于char_traits的模板。以下是一种最简单的方法:

  1. struct ci_char_traits : public char_traits<char>   
  2.               // 对于不需要替换的函数,   
  3.               // 只需继承下来即可  
  4. {  
  5.   static bool eq( char c1, char c2 )  
  6.     { return toupper(c1) == toupper(c2); }  
  7.   static bool lt( char c1, char c2 )  
  8.     { return toupper(c1) <  toupper(c2); }  
  9.   static int compare( const char* s1,  
  10.                           const char* s2,  
  11.                           size_t n )  
  12.     { return memicmp( s1, s2, n ); }  
  13.            // 如果你的系统支持memicmp函数,则可以直接使用;  
  14.            // 否则的话,要自行实现这个功能  
  15.   static const char*  
  16.   find( const char* s, int n, char a )  
  17.   {  
  18.     while( n-- > 0 && toupper(*s) != toupper(a) )  
  19.     {  
  20.         ++s;  
  21.     }  
  22.     return n >= 0   s : 0;  
  23.   }  
  24. };  

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇条款2:大小写不敏感的字符串--之.. 下一篇条款4:可重用性最高的泛型容器--..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: