You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否使用C++20的starts_with/ends_with进行大小写不敏感比较?

好问题!确实C++20新增的starts_with()和ends_with()是大小写敏感的,就像你举的例子那样,用大写的"HTTPS"去匹配小写开头的url会返回false。如果不想依赖Boost的istarts_with,也不想通过转全小写/大写产生额外的字符串副本,我们可以自己实现高效的大小写不敏感版本。

方案1:手动逐字符比较(直观可控)

直接基于std::string_view实现,避免字符串拷贝,只在比较时临时转换单个字符的大小写:

#include <string_view>
#include <cctype>
#include <iostream>

// 大小写不敏感的前缀检查
bool istarts_with(std::string_view str, std::string_view prefix) {
    if (prefix.size() > str.size()) {
        return false;
    }
    for (size_t i = 0; i < prefix.size(); ++i) {
        // 转成unsigned char避免tolower处理有符号char的未定义行为
        if (std::tolower(static_cast<unsigned char>(str[i])) != 
            std::tolower(static_cast<unsigned char>(prefix[i]))) {
            return false;
        }
    }
    return true;
}

// 同理实现后缀检查
bool iends_with(std::string_view str, std::string_view suffix) {
    if (suffix.size() > str.size()) {
        return false;
    }
    auto str_pos = str.end() - suffix.size();
    auto suffix_pos = suffix.begin();
    while (str_pos != str.end()) {
        if (std::tolower(static_cast<unsigned char>(*str_pos)) != 
            std::tolower(static_cast<unsigned char>(*suffix_pos))) {
            return false;
        }
        ++str_pos;
        ++suffix_pos;
    }
    return true;
}

// 测试你的例子
int main() {
    const std::string url { "https://isocpp.org" };
    if (istarts_with(url, "HTTPS")) {
        std::cout << "you're using the correct site!\n";
    }
    return 0;
}

方案2:用std::equal简化代码

利用标准库的std::equal算法,配合自定义谓词实现更简洁的版本,同样无额外拷贝:

#include <algorithm>
#include <string_view>
#include <cctype>
#include <iostream>

bool istarts_with(std::string_view str, std::string_view prefix) {
    return prefix.size() <= str.size() &&
           std::equal(prefix.begin(), prefix.end(), str.begin(),
               [](unsigned char a, unsigned char b) {
                   return std::tolower(a) == std::tolower(b);
               });
}

bool iends_with(std::string_view str, std::string_view suffix) {
    return suffix.size() <= str.size() &&
           std::equal(suffix.rbegin(), suffix.rend(), str.rbegin(),
               [](unsigned char a, unsigned char b) {
                   return std::tolower(a) == std::tolower(b);
               });
}

// 测试
int main() {
    const std::string url { "https://isocpp.org" };
    if (istarts_with(url, "HTTPS")) {
        std::cout << "you're using the correct site!\n";
    }
    return 0;
}

注意事项

  • 上面的代码基于ASCII字符处理,std::tolower在处理非ASCII字符时可能不符合预期(比如带重音的字母)。如果需要支持Unicode,可以考虑使用专门的字符处理函数,但这会引入额外依赖。
  • 用static_cast<unsigned char>包裹字符是必要的:因为char可能是有符号类型,当字符值为负(比如某些扩展ASCII)时,std::tolower的行为是未定义的,转成无符号类型可以避免这个问题。

这样实现的函数和Boost的istarts_with效果类似,而且不需要依赖第三方库,也不会产生额外的字符串副本,效率很高。

内容的提问来源于stack exchange,提问作者fen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 19:27:41