rfind 是 C++ 字符串类 std::string 和 std::wstring 的成员函数,用于从字符串的末尾向前搜索指定的子字符串或字符。
函数原型
1// 搜索整个字符串 2size_type rfind(const basic_string& str, size_type pos = npos) const noexcept; 3size_type rfind(const CharT* s, size_type pos = npos) const; 4size_type rfind(CharT ch, size_type pos = npos) const noexcept; 5 6// C++17 新增:带长度的版本 7size_type rfind(const CharT* s, size_type pos, size_type count) const; 8
参数说明
str/s/ch:要搜索的子字符串或字符pos:开始搜索的位置(从该位置向前搜索)count:要搜索的字符数(仅用于指针版本)
返回值
- 如果找到,返回匹配子串的起始位置(从 0 开始)
- 如果未找到,返回
std::string::npos
源码解析
以下是 rfind 的简化实现原理:
1#include <iostream> 2#include <string> 3#include <cstring> 4 5// 简化的 rfind 实现原理 6size_t simplified_rfind(const std::string& str, const std::string& pattern, size_t pos = std::string::npos) { 7 // 如果 pos 超过字符串长度,调整到字符串末尾 8 if (pos >= str.length()) { 9 pos = str.length() - 1; 10 } 11 12 // 如果模式串为空,返回 pos(标准行为) 13 if (pattern.empty()) { 14 return (pos < str.length()) ? pos : str.length(); 15 } 16 17 // 如果模式串比原字符串长,肯定找不到 18 if (pattern.length() > str.length()) { 19 return std::string::npos; 20 } 21 22 // 从 pos 开始向前搜索 23 for (size_t i = pos; i >= pattern.length() - 1; --i) { 24 bool found = true; 25 26 // 检查当前位置是否匹配模式串 27 for (size_t j = 0; j < pattern.length(); ++j) { 28 if (str[i - pattern.length() + 1 + j] != pattern[j]) { 29 found = false; 30 break; 31 } 32 } 33 34 if (found) { 35 return i - pattern.length() + 1; 36 } 37 38 // 处理无符号整数的下溢 39 if (i == 0) break; 40 } 41 42 return std::string::npos; 43} 44
使用示例
1#include <iostream> 2#include <string> 3 4int main() { 5 std::string text = "Hello, World! Hello, C++!"; 6 7 // 1. 搜索子字符串 8 size_t pos1 = text.rfind("Hello"); 9 std::cout << "Last 'Hello' at position: " << pos1 << std::endl; // 输出 14 10 11 // 2. 搜索字符 12 size_t pos2 = text.rfind('o'); 13 std::cout << "Last 'o' at position: " << pos2 << std::endl; // 输出 19 14 15 // 3. 从指定位置向前搜索 16 size_t pos3 = text.rfind("Hello", 10); 17 std::cout << "Last 'Hello' before position 10: " << pos3 << std::endl; // 输出 0 18 19 // 4. 搜索不存在的字符串 20 size_t pos4 = text.rfind("Python"); 21 if (pos4 == std::string::npos) { 22 std::cout << "'Python' not found" << std::endl; 23 } 24 25 // 5. 使用指针和长度 26 const char* search_str = "Hello"; 27 size_t pos5 = text.rfind(search_str, text.length(), 3); // 只搜索前3个字符 "Hel" 28 std::cout << "Last 'Hel' at position: " << pos5 << std::endl; 29 30 return 0; 31} 32
实际应用场景
1#include <iostream> 2#include <string> 3 4// 提取文件扩展名 5std::string getFileExtension(const std::string& filename) { 6 size_t dotPos = filename.rfind('.'); 7 if (dotPos != std::string::npos && dotPos < filename.length() - 1) { 8 return filename.substr(dotPos + 1); 9 } 10 return ""; 11} 12 13// 提取目录路径 14std::string getDirectory(const std::string& path) { 15 size_t slashPos = path.rfind('/'); 16 if (slashPos != std::string::npos) { 17 return path.substr(0, slashPos + 1); 18 } 19 return ""; 20} 21 22// 查找最后一个单词 23std::string getLastWord(const std::string& sentence) { 24 size_t lastSpace = sentence.rfind(' '); 25 if (lastSpace != std::string::npos) { 26 return sentence.substr(lastSpace + 1); 27 } 28 return sentence; // 没有空格,返回整个字符串 29} 30 31int main() { 32 std::string filename = "document.backup.txt"; 33 std::string path = "/home/user/documents/file.txt"; 34 std::string sentence = "The quick brown fox"; 35 36 std::cout << "File extension: " << getFileExtension(filename) << std::endl; 37 std::cout << "Directory: " << getDirectory(path) << std::endl; 38 std::cout << "Last word: " << getLastWord(sentence) << std::endl; 39 40 return 0; 41} 42
性能特点
- 时间复杂度:最坏情况 O(n×m),其中 n 是搜索范围,m 是模式串长度
- 空间复杂度:O(1)
- 适用场景:适合在长字符串中查找较短的模式串
注意事项
rfind从后向前搜索,但返回的位置是从字符串开头计算的- 如果
pos参数为npos,则从字符串末尾开始搜索 - 空字符串的搜索总是会成功(返回
pos或字符串长度) - 注意处理
npos的返回值
rfind 是字符串处理中非常有用的工具,特别适合需要从后向前搜索的场景,如文件路径处理、URL 解析等。
《C++ 中 rfind 方法详解》 是转载文章,点击查看原文。
