c++,string,compare,nocase,for copy

来源:互联网 发布:淘宝客生成链接以后 编辑:程序博客网 时间:2024/05/16 03:08

总结:如何在c++中进行大小写忽略的比较,基于std:string 

ref1,ref2,ref3


问题由来:

标准字符 (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:

#include <boost/algorithm/string.hpp>std::string str1 = "hello, world!";std::string str2 = "HELLO, WORLD!";if (boost::iequals(str1, str2)){    // Strings are identical}
策略2

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.

struct 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;


策略3

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(*c1) != tolower(*c2)) {            return false;        }    }    return true;}
策略5

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.

bool 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;}
策略6

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 );}

原创粉丝点击