应使用 std::string::rfind(‘.’) 安全获取最后一个点位置,配合 std::filesystem::path 剥离路径并提取扩展名,再统一转小写比对白名单,同时按业务规则处理多点、隐藏文件等边界情况。
用 std::string::find_last_of 定位最后一个点更安全
直接用 std::string::rfind('.') 找最后一个点,比从头遍历或硬切位置靠谱得多——文件名可能带路径(如 "./data/report.tar.gz"),也可能没点(如 "Makefile"),甚至点在开头(".gitignore")。rfind 返回 std::string::npos 时说明没扩展名,这是唯一可信赖的判断依据。
常见错误是写成 find('.') ,结果在 "archive.tar.gz" 里只拿到第一个点,截出 "tar.gz" 前面那段;或者用 substr(pos + 1) 却不检查 pos == npos,导致越界崩溃。
- 先调用
size_t pos = filename.rfind('.'); - 检查
if (pos == std::string::npos || pos == 0 || pos == filename.length() - 1)—— 排除".bashrc"(点在开头)和"name."(点在末尾)这类无效情况 - 确认有效后再取
filename.substr(pos + 1)
处理路径时必须先剥离目录部分
std::filesystem::path 是 C++17 起最省心的选择。它自动识别不同平台路径分隔符(/ 或 ),且 .extension() 方法返回的是带点的扩展名(如 ".txt"),而 .stem() 和 .filename() 能帮你避开手动解析路径的坑。
自己用 find_last_of("/\") 截路径容易漏掉 Windows UNC 路径("\\server\share\file.log")或混用分隔符的情况。而且很多用户忘了:扩展名属于文件名层面的概念,跟路径无关。
立即学习“C++免费学习笔记(深入)”;