在c++中进行不区分大小写字符串比较而不将字符串转换为全大写或全小写的最佳方法是什么?
请指出这些方法是否对unicode友好,以及它们的可移植性如何。
在c++中进行不区分大小写字符串比较而不将字符串转换为全大写或全小写的最佳方法是什么?
请指出这些方法是否对unicode友好,以及它们的可移植性如何。
当前回答
假设您正在寻找一个方法,而不是一个已经存在的神奇函数,坦率地说,没有更好的方法。对于有限的字符集,我们都可以使用聪明的技巧编写代码片段,但在一天结束时,你必须转换字符。
这种转换的最佳方法是在比较之前进行转换。当涉及到编码方案时,这为您提供了很大的灵活性,而实际的比较操作符应该忽略这一点。
当然,你可以在你自己的字符串函数或类后面“隐藏”这个转换,但你仍然需要在比较之前转换字符串。
其他回答
看起来以上的解决方案没有使用比较方法和实现总数,所以这里是我的解决方案,希望它为你工作(它的工作很好)。
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
string tolow(string a)
{
for(unsigned int i=0;i<a.length();i++)
{
a[i]=tolower(a[i]);
}
return a;
}
int main()
{
string str1,str2;
cin>>str1>>str2;
int temp=tolow(str1).compare(tolow(str2));
if(temp>0)
cout<<1;
else if(temp==0)
cout<<0;
else
cout<<-1;
}
我有使用Unicode库的International Components的丰富经验——它们非常强大,并提供了转换、区域支持、日期和时间呈现、大小写映射(您似乎不想要)和排序(其中包括大小写和重音不敏感比较)的方法。我只使用了c++版本的库,但它们似乎也有Java版本。
方法可以执行标准化的比较,如@Coincoin所述,甚至可以解释地区-例如(这是一个排序的例子,不是严格的相等),传统的西班牙语(在西班牙),字母组合“ll”在“l”和“m”之间排序,因此“lz”<“ll”<“ma”。
迟来的派对,但这里有一个变种,使用std::locale,因此正确处理土耳其语:
auto tolower = std::bind1st(
std::mem_fun(
&std::ctype<char>::tolower),
&std::use_facet<std::ctype<char> >(
std::locale()));
提供一个函子,使用活动区域设置将字符转换为小写,然后可以通过std::transform生成小写字符串:
std::string left = "fOo";
transform(left.begin(), left.end(), left.begin(), tolower);
这也适用于基于wchar_t的字符串。
Boost包含一个方便的算法:
#include <boost/algorithm/string.hpp>
// Or, for fewer header dependencies:
//#include <boost/algorithm/string/predicate.hpp>
std::string str1 = "hello, world!";
std::string str2 = "HELLO, WORLD!";
if (boost::iequals(str1, str2))
{
// Strings are identical
}
如果是在POSIX系统上,可以使用strcasecmp。不过,这个函数不是标准C语言的一部分,在Windows上也不可用。这将对8位字符执行不区分大小写的比较,只要区域设置为POSIX。如果区域设置不是POSIX,则结果是未定义的(因此它可能进行本地化比较,也可能不进行)。没有宽字符的等效版本。
如果做不到这一点,大量历史上的C库实现都有stricmp()和strnicmp()函数。Windows上的Visual c++通过在它们前面加上下划线来重命名它们,因为它们不是ANSI标准的一部分,所以在那个系统中它们被称为_stricmp或_strnicmp。一些库可能还具有宽字符或多字节等效函数(通常命名为wcsicmp, mbcsicmp等)。
C和c++在很大程度上都不了解国际化问题,所以除了使用第三方库之外,这个问题没有好的解决方案。如果需要用于C/ c++的健壮库,请参阅IBM ICU (Unicode国际组件)。ICU适用于Windows和Unix系统。