C++中是否有一个std::string的内置函数,当两个字符串都可以是大写或小写时,可以按字母顺序比较两个字符串

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

本文关键字:两个 字符串 顺序 比较 string 函数 std C++ 内置 都可以 是否      更新时间:2023-10-16

对于C++,我知道如果两个单词都是完全小写或完全大写,基本的比较运算符就可以完成任务。我有一个字符串数组,字母可以从下到上变化。下面是我可以使用的字符串的一个小例子:

"丰富的生命CH"

"新生命WMN-MNSTRY"

"新生命装配"

我知道在Java中存在函数String.compareToIgnoreCase()。这个函数有C++等价物吗?

我不知道标准库中有任何不区分大小写的函数,但您可以为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));
    });

有关考虑区域设置的解决方案,请参阅不区分大小写的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()));
}

是的,在C++中有一种不区分大小写的方法来比较字符串。关键是std::string是一个模板:

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

这里的traits控制charT如何相互关联。对于正常的std::string,它们会做你所期望的事情,但我们可以写下我们自己的不区分大小写的特征:

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

有了这个:

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

您可以使用Boost字符串算法:

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

在C++中,通常在三值函数compare(int cmp(type,type))的位置使用小于(bool-less(type,type))。当然,它们中的每一个都可以根据另一个进行琐碎的定义。

以下是可以很容易地插入STL算法的东西:

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

这里有一些东西可以将less()转换为java风格的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;
  }
};

没有标准,但如果您碰巧是为Windows开发的,或者可以访问Posix接口,则可以使用以下内容: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
}

有一个更简单的解决方案,它不涉及编码循环(ugh!)或Boost:

string a = "Foo";
string b = "foo"
return !_stricmp(a.str(), b.str());

字符串被转换为char[],然后进行比较,不区分大小写。如果它们相等,则返回true。

(我有偏见的观点:C++应该把这个功能作为一个字符串方法来提供。强迫数百万用户为这样一个常见的操作进行代码循环是令人恶心的,并在代码中引入了不必要的"噪音"。)