c++中如何判断字符串开头或结尾_c++ starts_with与ends_with用法【实例】

只有启用C++20或更高标准时,std::string才原生支持starts_with和ends_with;需用GCC 10+/Clang 12+/MSVC 19.30+并指定-std=c++20,否则编译报错。

std::string::sta

rts_with 在 C++20 中的使用条件

只有启用 C++20 或更高标准时,std::string 才原生支持 starts_withends_with 成员函数。如果你用的是 GCC 10+、Clang 12+ 或 MSVC 19.30+,需确认编译选项包含 -std=c++20(或 /std:c++20)。否则会报错:error: 'starts_with' is not a member of 'std::basic_string'

常见误判点:C++17 及更早版本不提供这两个函数,强行调用会编译失败;即使某些 STL 实现(如 libstdc++ 11)在 C++17 模式下“悄悄”加了实验性支持,也不具备可移植性,务必以标准为准。

  • 检查编译器是否支持:
    #include 
    #include 
    int main() {
        std::string s = "hello.txt";
        // 编译通过才说明可用
        if (s.starts_with("hello")) {
            std::cout << "OK\n";
        }
    }
  • 若编译失败,不要尝试「重载」或「宏替换」来伪造接口,应降级使用 substr + comparestd::string_view 方案(见下节)

兼容 C++11~C++17 的等效写法

在无法升级到 C++20 的项目中(如嵌入式、LTS 系统、遗留代码库),推荐用 std::string_view 实现零拷贝判断,兼顾性能与可读性。它不需要分配内存,且对字面量、子串、临时字符串都友好。

关键点:std::string_view 构造开销极小,starts_with / ends_with 是其原生成员函数(C++17 引入),且可接受 const char*std::stringstd::string_view 作为参数。

  • 判断开头:
    std::string s = "/home/user/file.log";
    if (std::string_view{s}.starts_with("/home")) {
        // true
    }
  • 判断结尾:
    std::string s = "report.pdf";
    if (std::string_view{s}.ends_with(".pdf")) {
        // true
    }
  • 注意边界:若 s 长度小于前缀/后缀长度,starts_with/ends_with 自动返回 false,无需手动长度检查

starts_with 与 ends_with 的参数类型差异

std::string_view::starts_with 接受三种参数:std::string_viewconst char*、单个 char;而 ends_with 同理,但不支持单字符(C++17 标准规定仅 starts_with 有单字符重载)。

这意味着以下写法合法:

  • sv.starts_with('a')
  • sv.ends_with('z') ❌ 编译错误 —— 必须写成 sv.ends_with("z")sv.ends_with(std::string_view{"z"})
  • sv.starts_with("http://") ✅ 字面量自动转为 std::string_view
  • sv.ends_with(std::string{"tmp"}) ✅ 会隐式构造 std::string_view(不触发拷贝)

std::string 是安全的,但若频繁调用且字符串较长,建议提前转成 std::string_view 变量复用,避免重复构造。

容易忽略的空字符串与大小写问题

starts_with("")ends_with("") 恒为 true(空串是任意字符串的前缀和后缀),这在路径处理或协议解析中可能引发逻辑漏洞。例如过滤“以 https:// 开头”的 URL,若未校验非空,空字符串也会通过。

另一个高频坑:这两个函数**严格区分大小写**。没有内置的 ignore-case 版本。需要忽略大小写时,不能直接比较,得先转换再判断:

  • 简单场景(ASCII):
    std::string s = "HTTP://EXAMPLE.COM";
    std::string lower_s = s;
    std::transform(lower_s.begin(), lower_s.end(), lower_s.begin(), ::tolower);
    if (std::string_view{lower_s}.starts_with("https://")) { ... }
  • 生产环境建议用 ICU 或 std::locale 处理 Unicode 大小写,而非 ::tolower(对非 ASCII 字符行为未定义)
  • 正则不适用:别为了大小写去调 std::regex_match,性能差且易出错;优先做预处理

最常被跳过的其实是空值检查:如果 s 来自用户输入或网络,先确认 !s.empty() 再调 starts_with,否则虽不会崩溃,但语义可能不符合预期。