在c++中进行不区分大小写字符串比较而不将字符串转换为全大写或全小写的最佳方法是什么?
请指出这些方法是否对unicode友好,以及它们的可移植性如何。
在c++中进行不区分大小写字符串比较而不将字符串转换为全大写或全小写的最佳方法是什么?
请指出这些方法是否对unicode友好,以及它们的可移植性如何。
当前回答
支持unicode的Visual c++字符串函数:http://msdn.microsoft.com/en-us/library/cc194799.aspx
您可能正在寻找的是_wcsnicmp
其他回答
你说的是一个愚蠢的不区分大小写的比较还是一个完全标准化的Unicode比较?
哑比较不会找到可能相同但二进制不相等的字符串。
例子:
U212B (ANGSTROM SIGN)
U0041 (LATIN CAPITAL LETTER A) + U030A (COMBINING RING ABOVE)
U00C5 (LATIN CAPITAL LETTER A WITH RING ABOVE).
都是等价的,但它们也有不同的二进制表示。
也就是说,Unicode标准化应该是必读的,特别是如果您计划支持韩文,Thaï和其他亚洲语言。
此外,IBM几乎为大多数优化的Unicode算法申请了专利,并将它们公开提供。它们还维护一个实现:IBM ICU
对于非unicode版本,我的第一个想法是这样做的:
bool caseInsensitiveStringCompare(const string& str1, const string& str2) {
if (str1.size() != str2.size()) {
return false;
}
for (string::const_iterator c1 = str1.begin(), c2 = str2.begin(); c1 != str1.end(); ++c1, ++c2) {
if (tolower(static_cast<unsigned char>(*c1)) != tolower(static_cast<unsigned char>(*c2))) {
return false;
}
}
return true;
}
仅供参考,strcmp()和stricmp()容易受到缓冲区溢出的影响,因为它们只处理到遇到空结束符为止。使用_strncmp()和_strnicmp()更安全。
对于我基本的不区分大小写的字符串比较需求,我宁愿不使用外部库,也不想要一个与所有其他字符串不兼容的不区分大小写特征的单独字符串类。
所以我想到的是:
bool icasecmp(const string& l, const string& r)
{
return l.size() == r.size()
&& equal(l.cbegin(), l.cend(), r.cbegin(),
[](string::value_type l1, string::value_type r1)
{ return toupper(l1) == toupper(r1); });
}
bool icasecmp(const wstring& l, const wstring& r)
{
return l.size() == r.size()
&& equal(l.cbegin(), l.cend(), r.cbegin(),
[](wstring::value_type l1, wstring::value_type r1)
{ return towupper(l1) == towupper(r1); });
}
一个简单的函数,一个重载char,另一个重载whar_t。不使用任何非标准的东西,所以应该在任何平台上都很好。
相等性比较不会考虑像变长编码和Unicode规范化这样的问题,但据我所知,basic_string不支持这一点,而且这通常不是一个问题。
在需要对文本进行更复杂的词典操作的情况下,您只需使用像Boost这样的第三方库,这是可以预料到的。
只需使用strcmp()区分大小写,使用strcmpi()或stricmp()进行不区分大小写的比较。它们都在头文件<string.h>
格式:
int strcmp(const char*,const char*); //for case sensitive
int strcmpi(const char*,const char*); //for case insensitive
用法:
string a="apple",b="ApPlE",c="ball";
if(strcmpi(a.c_str(),b.c_str())==0) //(if it is a match it will return 0)
cout<<a<<" and "<<b<<" are the same"<<"\n";
if(strcmpi(a.c_str(),b.c_str()<0)
cout<<a[0]<<" comes before ball "<<b[0]<<", so "<<a<<" comes before "<<b;
输出
apple和apple是一样的
A在b之前,所以苹果在球之前