是否可以使用 C++20 中的starts_with/ends_with 来比较不区分大小写?

fen*_*fen 1 c++ string c++20

使用 C++20 和P0457,string我们获得了和的成员函数string_view,用于检查前缀和后缀:

starts_with(),ends_with()

有没有办法不区分大小写地比较字符串?

例如此检查返回false

const std::string url { "https://isocpp.org" };
    
if (url.starts_with("HTTPS"))
    std::cout << "you're using the correct site!\n";
Run Code Online (Sandbox Code Playgroud)

例如,在 boost 中我们就istarts_with进行了这样的比较。

一种方法是“规范化”要检查的字符串和前缀/后缀(例如全部小写),但这需要对象的额外副本。

Atn*_*nNn 5

starts_withends_with使用char_traits字符串的。您可以扩展默认值char_traits以使用不区分大小写的比较:

struct case_insensitive_traits : public std::char_traits<char> {
    static bool eq(char c1, char c2) {
         return std::toupper(c1) == std::toupper(c2);
     }
    static bool lt(char c1, char c2) {
         return std::toupper(c1) <  std::toupper(c2);
    }
    static int compare(const char* s1, const char* s2, std::size_t n) {
        while (n-- != 0) {
            if (lt(*s1, *s2)) return -1;
            if (lt(*s2, *s1)) return 1;
            ++s1; ++s2;
        }
        return 0;
    }
};
Run Code Online (Sandbox Code Playgroud)

这允许您构造一个字符串类型,所有比较都不区分大小写:

using case_insensitive_string =
    std::basic_string<char, case_insensitive_traits>;

case_insensitive_string cistr = "Fundamental";

cistr.starts_with("fun"); // true
cistr == "FUNDAMENTAL"; // true
Run Code Online (Sandbox Code Playgroud)

std::string然而,如果没有副本,这将不起作用。您可以通过使用视图来避免复制:

using case_insensitive_string_view =
    std::basic_string_view<char, case_insensitive_traits>;

std::string str = "Fundamental";

case_insensitive_string_view(str.data(), str.size()).starts_with("fun"); // true
Run Code Online (Sandbox Code Playgroud)