Is there a built-in function for std :: string in C ++ to compare two strings in alphabetical order, when any string can be uppercase or lowercase?

I know that for C ++, basic comparison operators can complete a task if both words are either fully or fully capitalized. I have an array of strings and letters that can vary from bottom to top. Here is a small example of the type of strings I can work with:

"BIG LIFE CH"

"NEW LIFE WMN MNSTRY"

"NEW LIFE ASSEMBLY"

I know that in Java there is a String.compareToIgnoreCase() function. Is there a C ++ equivalent of this function?

+6
source share
5 answers

I don't know any case-insensitive functions in the standard library, but you can specify your own predicate for std::equal :

 std::string a("hello"); std::string b("HELLO"); std::cout << std::equal(a.begin(), a.end(), b.begin(), [] (const char& a, const char& b) { return (std::tolower(a) == std::tolower(b)); }); 

For a solution that takes into account the locale, see Case Insensitive std :: string.find () .

 #include <locale> template<typename charT = std::string::value_type> struct my_equal { my_equal( const std::locale& loc ) : loc_(loc) {} bool operator()(charT ch1, charT ch2) { return std::toupper(ch1, loc_) == std::toupper(ch2, loc_); } private: const std::locale& loc_; }; int main() { std::string a("hello"); std::string b("HELLO"); std::cout << std::equal(a.begin(), a.end(), b.begin(), my_equal<>(std::locale())); } 
+6
source

Yes, there is a random way to compare strings in C ++. The key is that std::string is a template:

 template <class charT, class traits = char_traits<charT>, class Allocator = allocator<charT>> class basic_string; 

Here, traits control how charT relate to each other. For a normal std::string they do what you expect, but we can just write our own traits that are case insensitive:

 struct case_insensitive_traits : char_traits<char> { static bool eq(char a, char b) { return tolower(a) == tolower(b); } static bool ne(char a, char b) { return !eq(a, b); } static bool lt(char a, char b) { return tolower(a) < tolower(b); } static bool gt(char a, char b) { return tolower(a) > tolower(b); } static int compare(const char* a, const char* b, size_t n) { for (size_t i = 0; i < n; ++i) { int delta = tolower(a[i]) - tolower(b[i]); if (delta != 0) return delta; } return 0; } static const char* find(const char* s, size_t n, char c) { c = tolower(c); for (size_t i = 0; i < n; ++i, ++s) { if (tolower(*s) == c) return s; } return nullptr; } }; 

With this:

 using case_insensitive_string = std::basic_string<char, case_insensitive_traits>; case_insensitive_string a{"hello"}; case_insensitive_string b{"hElLo"}; assert(a == b); 
+3
source

You can use Boost String algorithms:

 #include <string> #include <cassert> #include <boost/algorithm/string.hpp> int main() { std::string s { "Test" }; assert(boost::iequals(s, "TEST")); } 
+2
source

In C ++, usually less (bool less (type, type)) is used in places where three-valued functions are compared (int cmp (type, type)). Of course, each of them can be trivially defined in terms of the other.

Here's something that can easily be connected to STL algorithms:

 template<class String> struct ciless { locale l_; explicit ciless(locale l = locale()) : l_(l) {} bool operator() ( String const &a , String const &b) const { auto fa = a.begin(); auto fb = b.begin(); while (fa != a.end() && fb != b.end() && (tolower(*fa, l_) == tolower(*fb, l_))) { ++fa; ++fb; } return (fa == a.end() && fb != b.end()) || ( fa != a.end() && fb != b.end() && tolower(*fa, l_) < tolower(*fb, l_)); } }; 

And here is something that can convert less () to java-style compare ():

 template<class T, class Less = std::less<T>> struct compare { Less l_; explicit compare(Less l = Less()) : l_(l) {} int operator() ( T const &a , T const &b) const { if (l_(a, b)) return -1; if (l_(b, a)) return 1; return 0; } }; 
+1
source

Nothing standard, but if you are running Windows or have access to the Posix interface, you can use the following: https://msdn.microsoft.com/en-us/library/k59z8dwe.aspx

 // didn't run it through a compiler // but it would look like something like this: { using namespace std; string a = "HELLO"s; string b = "HelLO"s; bool bIsMatch = _stricmp(a.c_str(), b.c_str()) == 0; // bIsMatch = true } 
0
source

Source: https://habr.com/ru/post/982149/


All Articles