标准字符 (typedef basic_string<char> string)由于国际化过程中,没有实现每一种语言的大小写转换函数,也没要提供基于ansi字符的大小写忽略比较。
解决方案1:先转换大小写再比较
策略1. std method
C++ — Convert string to upper/lower case
To convert an std::string to upper case you can use the following:
#include <algorithm>
#include <string>
…
std::string data = “Abc”;
std::transform(data.begin(), data.end(),
data.begin(), ::toupper);
For converting to lower case, you need to replace::toupper with ::tolower.
If you really hate tolower(), here's an alternative:
char easytolower(char in){ if(in<='Z' && in>='A') return in-('Z'-'z'); return in; } std::transform(data.begin(), data.end(), data.begin(), easytolower);
策略2. boost method
There is a Boost string algorithm for this:
#include <boost/algorithm/string.hpp> std::string str = "HELLO, WORLD!"; boost::algorithm::to_lower(str);
解决方案2:直接比较
策略1
Boost includes a handy algorithm for this:
策略2#include <boost/algorithm/string.hpp> std::string str1 = "hello, world!"; std::string str2 = "HELLO, WORLD!"; if (boost::iequals(str1, str2)) { // Strings are identical }
Take advantage of the standard char_traits
. Recall that a std::string
is in fact a typedef for std::basic_string<char>
, or more explicitly,std::basic_string<char, std::char_traits<char> >
. The char_traits
type describes how characters compare, how they copy, how they cast etc. All you need to do is typedef a new string over basic_string
, and provide it with your own customchar_traits
that compare case insensitively.
策略3struct ci_char_traits : public char_traits<char> { static bool eq(char c1, char c2) { return toupper(c1) == toupper(c2); } static bool ne(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) { while( n-- != 0 ) { if( toupper(*s1) < toupper(*s2) ) return -1; if( toupper(*s1) > toupper(*s2) ) return 1; ++s1; ++s2; } return 0; } static const char* find(const char* s, int n, char a) { while( n-- > 0 && toupper(*s) != toupper(a) ) { ++s; } return s; } }; typedef std::basic_string<char, ci_char_traits> ci_string;
策略5bool 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(*c1) != tolower(*c2)) { return false; } } return true; }
The trouble with boost is that you have to link with and depend on boost. Not easy in some cases (e.g. android).
And using char_traits means all your comparisons are case insensitive, which isn't usually what you want.
This should suffice. It should be reasonably efficient. Doesn't handle unicode or anything though.
策略6bool iequals(const string& a, const string& b) { unsigned int sz = a.size(); if (b.size() != sz) return false; for (unsigned int i = 0; i < sz; ++i) if (tolower(a[i]) != tolower(b[i])) return false; return true; }
ere is a method of doing this, although it does transforming the strings, and is not Unicode friendly, it should be portable which is a plus:
bool caseInsensitiveStringCompare( const std::string& str1, const std::string& str2 ) { std::string str1Cpy( str1 ); std::string str2Cpy( str2 ); std::transform( str1Cpy.begin(), str1Cpy.end(), str1Cpy.begin(), ::tolower ); std::transform( str2Cpy.begin(), str2Cpy.end(), str2Cpy.begin(), ::tolower ); return ( str1Cpy == str2Cpy ); }