C++ std::string starts_with/ends_with 不区分大小写的版本?
C++ std:: string starts_with/ends_with case insensitive versions?
C++20 添加了 starts_with、ends_with 到 std::string。
有什么好的方法可以让它变得敏感吗?
请注意性能很重要,所以我不想 lowercase/uppercase 两个字符串(或 std::min(len1, len2)
部分字符串)。
与常规 <algorithm>
算法不同 starts_with
没有比较器过载,所以我认为没有什么好的方法可以做到这一点。
而且我有点理解 90% 以上的情况是区分大小写的,并且 C++ 中的成员 fns 被避免除非非常有用......所以我知道为什么存在这个限制,我只是好奇是否有相对可读的东西可以在 C++20 中一起破解,而无需我使用自定义比较器手动调用 std::equal(或相等的范围版本)。
我很想知道应用 this answer 的建议如何运作。这是结果。
上述答案的代码:
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;
那里的答案建议使用 ci_string
而不是 std::string
。这里我们只想创建ci_views
到std::string
s:
typedef std::basic_string_view<char, ci_char_traits> ci_string_view;
int main()
{
std::string x{"ABCD"};
std::string y{"abcd"};
std::cout << ci_string_view{x.begin(),x.end()}.ends_with(ci_string_view{y.begin(),y.end()});
}
输出:
1
std::mismatch(s1.begin(), s1.end(), s2.begin(), s2.end(), <comparator>)
会为所欲为。您必须编写 case-insensitve 比较器,但我相信您可以解决这个问题。
我最近也遇到了这个问题
如果您不介意使用 boost,这里有 istarts_with and iends_with 个函数。
他们正是您所需要的。
C++20 添加了 starts_with、ends_with 到 std::string。
有什么好的方法可以让它变得敏感吗?
请注意性能很重要,所以我不想 lowercase/uppercase 两个字符串(或 std::min(len1, len2)
部分字符串)。
与常规 <algorithm>
算法不同 starts_with
没有比较器过载,所以我认为没有什么好的方法可以做到这一点。
而且我有点理解 90% 以上的情况是区分大小写的,并且 C++ 中的成员 fns 被避免除非非常有用......所以我知道为什么存在这个限制,我只是好奇是否有相对可读的东西可以在 C++20 中一起破解,而无需我使用自定义比较器手动调用 std::equal(或相等的范围版本)。
我很想知道应用 this answer 的建议如何运作。这是结果。
上述答案的代码:
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;
那里的答案建议使用 ci_string
而不是 std::string
。这里我们只想创建ci_views
到std::string
s:
typedef std::basic_string_view<char, ci_char_traits> ci_string_view;
int main()
{
std::string x{"ABCD"};
std::string y{"abcd"};
std::cout << ci_string_view{x.begin(),x.end()}.ends_with(ci_string_view{y.begin(),y.end()});
}
输出:
1
std::mismatch(s1.begin(), s1.end(), s2.begin(), s2.end(), <comparator>)
会为所欲为。您必须编写 case-insensitve 比较器,但我相信您可以解决这个问题。
我最近也遇到了这个问题
如果您不介意使用 boost,这里有 istarts_with and iends_with 个函数。
他们正是您所需要的。