Is there a built in function for std::string in C++ to compare two strings alphabetically when either string can be uppercase or lowercase?

二次信任 提交于 2020-12-26 06:31:47

问题


I know for C++ that basic comparative operators can accomplish the task if both words are either entirely lower or entirely upper case. I have an array of strings and letters can vary from lower to upper. Here is a small examle of the kind of strings I can be working with:

"ABUNDANT LIFE CH"

"NEW LIFE WMN MNSTRY"

"NEW LIFE ASSEMBLY"

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


回答1:


I don't know of any case-insensitive functions in the standard library, but you can specify a custom 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 which takes locale into account, refer to 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()));
}



回答2:


Yes there is a case insensitive 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;

The traits here control how the charT's relate to each other. For normal std::string, they do what you'd 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 that:

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:


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



回答4:


In C++ usually less-than (bool less(type, type)) is used in places of tri-value function compare (int cmp(type, type)). Of course each one of them can be trivially defined in terms of the other.

Here's something that can easily be plugged into 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's something that can convert less() into 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;
  }
};



回答5:


Nothing standard, but if you happen to be developing for Windows or have access to a Posix interface you could 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
}


来源:https://stackoverflow.com/questions/28387362/is-there-a-built-in-function-for-stdstring-in-c-to-compare-two-strings-alpha

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!