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_viewsstd::strings:

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

Live Example

std::mismatch(s1.begin(), s1.end(), s2.begin(), s2.end(), <comparator>) 会为所欲为。您必须编写 case-insensitve 比较器,但我相信您可以解决这个问题。

我最近也遇到了这个问题

如果您不介意使用 boost,这里有 istarts_with and iends_with 个函数。

他们正是您所需要的。