当字符串可以是大写或小写时,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?
我知道对于 C++,如果两个词完全小写或完全大写,基本的比较运算符就可以完成任务。我有一个字符串数组,字母可以从低到高变化。这是我可以使用的字符串类型的一个小示例:
"ABUNDANT LIFE CH"
"NEW LIFE WMN MNSTRY"
"NEW LIFE ASSEMBLY"
我知道 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));
});
有关考虑语言环境的解决方案,请参阅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()));
}
是的,在 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);
在C++中通常用小于(bool less(type, type))来代替三值函数compare (int cmp(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
}
您可以使用 Boost 字符串算法:
#include <string>
#include <cassert>
#include <boost/algorithm/string.hpp>
int main() {
std::string s { "Test" };
assert(boost::iequals(s, "TEST"));
}
有一个更简单的解决方案,不涉及编码循环(呃!)或提升:
string a = "Foo";
string b = "foo"
return !_stricmp(a.str(), b.str());
字符串被转换为char[],然后进行比较,不区分大小写。 Returns 如果它们相等则为真。
(我的偏见:C++ 应该将此功能作为字符串方法提供。强迫数百万用户为这种常见操作手动编写循环代码是令人厌恶的,并且会在代码中引入不必要的“噪音”。)
我知道对于 C++,如果两个词完全小写或完全大写,基本的比较运算符就可以完成任务。我有一个字符串数组,字母可以从低到高变化。这是我可以使用的字符串类型的一个小示例:
"ABUNDANT LIFE CH"
"NEW LIFE WMN MNSTRY"
"NEW LIFE ASSEMBLY"
我知道 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));
});
有关考虑语言环境的解决方案,请参阅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()));
}
是的,在 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);
在C++中通常用小于(bool less(type, type))来代替三值函数compare (int cmp(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
}
您可以使用 Boost 字符串算法:
#include <string>
#include <cassert>
#include <boost/algorithm/string.hpp>
int main() {
std::string s { "Test" };
assert(boost::iequals(s, "TEST"));
}
有一个更简单的解决方案,不涉及编码循环(呃!)或提升:
string a = "Foo";
string b = "foo"
return !_stricmp(a.str(), b.str());
字符串被转换为char[],然后进行比较,不区分大小写。 Returns 如果它们相等则为真。
(我的偏见:C++ 应该将此功能作为字符串方法提供。强迫数百万用户为这种常见操作手动编写循环代码是令人厌恶的,并且会在代码中引入不必要的“噪音”。)