跳到主要内容

C++ 字符串搜索

在C++编程中,字符串搜索是一项非常常见的操作。无论是检查用户输入、处理文件内容,还是进行文本分析,我们都需要能够在字符串中查找特定的子字符串或字符。本篇教程将深入介绍C++ string 类提供的各种搜索方法,帮助你有效地进行字符串搜索操作。

字符串搜索的基础

在C++的 string 类中,提供了多种搜索函数,包括:

  • find():从前向后搜索
  • rfind():从后向前搜索
  • find_first_of():查找第一次出现的任何指定字符
  • find_last_of():查找最后一次出现的任何指定字符
  • find_first_not_of():查找第一个不在指定字符集中的字符
  • find_last_not_of():查找最后一个不在指定字符集中的字符

这些函数返回找到的位置索引,如果没找到则返回 string::npos

find() 函数

find() 函数从字符串的开始位置向后搜索指定的子字符串,返回第一次出现的位置。

语法

cpp
size_t find (const string& str, size_t pos = 0) const;
size_t find (const char* s, size_t pos = 0) const;
size_t find (const char* s, size_t pos, size_t n) const;
size_t find (char c, size_t pos = 0) const;

示例

cpp
#include <iostream>
#include <string>
using namespace std;

int main() {
string str = "Hello, welcome to C++ programming!";

// 查找子字符串
size_t pos = str.find("welcome");
if (pos != string::npos) {
cout << "子字符串 'welcome' 在位置 " << pos << " 找到" << endl;
} else {
cout << "未找到子字符串 'welcome'" << endl;
}

// 从指定位置开始查找
pos = str.find("o", 5);
if (pos != string::npos) {
cout << "从位置5开始,字符 'o' 在位置 " << pos << " 找到" << endl;
}

// 查找不存在的字符串
pos = str.find("Java");
if (pos == string::npos) {
cout << "未找到子字符串 'Java'" << endl;
}

return 0;
}

输出:

子字符串 'welcome' 在位置 7 找到
从位置5开始,字符 'o' 在位置 15 找到
未找到子字符串 'Java'
提示

记住,C++中字符串索引是从0开始的,所以第一个字符的索引是0。

rfind() 函数

rfind() 函数从字符串的末尾向前搜索指定的子字符串,返回最后一次出现的位置。

语法

cpp
size_t rfind (const string& str, size_t pos = npos) const;
size_t rfind (const char* s, size_t pos = npos) const;
size_t rfind (const char* s, size_t pos, size_t n) const;
size_t rfind (char c, size_t pos = npos) const;

示例

cpp
#include <iostream>
#include <string>
using namespace std;

int main() {
string str = "Hello, welcome to C++ programming! C++ is fun.";

// 从后向前查找子字符串
size_t pos = str.rfind("C++");
if (pos != string::npos) {
cout << "最后一个 'C++' 在位置 " << pos << " 找到" << endl;
}

// 在指定位置之前查找
pos = str.rfind("C++", 30);
if (pos != string::npos) {
cout << "在位置30之前,最后一个 'C++' 在位置 " << pos << " 找到" << endl;
}

return 0;
}

输出:

最后一个 'C++' 在位置 34 找到
在位置30之前,最后一个 'C++' 在位置 19 找到

find_first_of() 与 find_last_of() 函数

这两个函数用于查找指定字符集合中的任意字符在字符串中的位置。

语法

cpp
size_t find_first_of (const string& str, size_t pos = 0) const;
size_t find_last_of (const string& str, size_t pos = npos) const;

示例

cpp
#include <iostream>
#include <string>
using namespace std;

int main() {
string str = "Hello, welcome to C++ programming!";
string chars = "aeiou";

// 查找第一个元音字母
size_t pos = str.find_first_of(chars);
if (pos != string::npos) {
cout << "第一个元音字母 '" << str[pos]
<< "' 在位置 " << pos << " 找到" << endl;
}

// 查找最后一个元音字母
pos = str.find_last_of(chars);
if (pos != string::npos) {
cout << "最后一个元音字母 '" << str[pos]
<< "' 在位置 " << pos << " 找到" << endl;
}

return 0;
}

输出:

第一个元音字母 'e' 在位置 1 找到
最后一个元音字母 'i' 在位置 31 找到

find_first_not_of() 与 find_last_not_of() 函数

这两个函数用于查找不在指定字符集合中的任意字符在字符串中的位置。

语法

cpp
size_t find_first_not_of (const string& str, size_t pos = 0) const;
size_t find_last_not_of (const string& str, size_t pos = npos) const;

示例

cpp
#include <iostream>
#include <string>
using namespace std;

int main() {
string str = "Hello, welcome to C++ programming!";
string letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";

// 查找第一个非字母字符
size_t pos = str.find_first_not_of(letters);
if (pos != string::npos) {
cout << "第一个非字母字符 '" << str[pos]
<< "' 在位置 " << pos << " 找到" << endl;
}

// 查找最后一个非字母字符
pos = str.find_last_not_of(letters);
if (pos != string::npos) {
cout << "最后一个非字母字符 '" << str[pos]
<< "' 在位置 " << pos << " 找到" << endl;
}

return 0;
}

输出:

第一个非字母字符 ',' 在位置 5 找到
最后一个非字母字符 '!' 在位置 34 找到

实际应用案例

案例1:提取文件扩展名

cpp
#include <iostream>
#include <string>
using namespace std;

string getFileExtension(const string& filename) {
size_t dotPos = filename.find_last_of(".");
if (dotPos != string::npos) {
return filename.substr(dotPos + 1);
}
return ""; // 没有扩展名
}

int main() {
string filename = "document.txt";
cout << "文件扩展名: " << getFileExtension(filename) << endl;

filename = "image.jpg";
cout << "文件扩展名: " << getFileExtension(filename) << endl;

filename = "noextension";
cout << "文件扩展名: " << getFileExtension(filename) << endl;

return 0;
}

输出:

文件扩展名: txt
文件扩展名: jpg
文件扩展名:

案例2:统计单词出现次数

cpp
#include <iostream>
#include <string>
using namespace std;

int countWordOccurrences(const string& text, const string& word) {
int count = 0;
size_t pos = 0;

while ((pos = text.find(word, pos)) != string::npos) {
count++;
pos += word.length(); // 移动到下一个可能的位置
}

return count;
}

int main() {
string text = "C++ is a powerful language. C++ allows object-oriented programming. I love C++!";
string word = "C++";

int occurrences = countWordOccurrences(text, word);
cout << "单词 '" << word << "' 在文本中出现了 " << occurrences << " 次" << endl;

return 0;
}

输出:

单词 'C++' 在文本中出现了 3 次

案例3:URL解析

cpp
#include <iostream>
#include <string>
using namespace std;

void parseURL(const string& url) {
// 查找协议(http:// 或 https://)
size_t protocolEnd = url.find("://");
if (protocolEnd != string::npos) {
string protocol = url.substr(0, protocolEnd);
cout << "协议: " << protocol << endl;

// 查找域名(从协议后到第一个斜杠或结束)
size_t domainStart = protocolEnd + 3;
size_t pathStart = url.find("/", domainStart);

string domain;
if (pathStart != string::npos) {
domain = url.substr(domainStart, pathStart - domainStart);

// 查找路径
string path = url.substr(pathStart);
cout << "路径: " << path << endl;
} else {
domain = url.substr(domainStart);
cout << "路径: /" << endl;
}

cout << "域名: " << domain << endl;
} else {
cout << "无效的URL格式" << endl;
}
}

int main() {
string url = "https://www.example.com/path/to/resource?param=value";
parseURL(url);

return 0;
}

输出:

协议: https
域名: www.example.com
路径: /path/to/resource?param=value

性能考虑

在处理大量文本或者需要频繁搜索操作时,字符串搜索的效率非常重要。标准库中的 string 搜索函数在大多数情况下表现良好,但对于更复杂的搜索需求,可能需要考虑使用更高效的算法或第三方库。

警告

对于非常大的字符串或需要频繁搜索的情况,标准的字符串搜索可能不是最佳选择。在这些情况下,考虑使用如KMP、Boyer-Moore或Rabin-Karp等高效搜索算法。

总结

C++字符串类提供了丰富的搜索功能,让我们能够轻松地在字符串中找到需要的内容:

  1. find()rfind() 用于正向和反向搜索子字符串
  2. find_first_of()find_last_of() 用于查找指定字符集中任意字符的位置
  3. find_first_not_of()find_last_not_of() 用于查找不在指定字符集中的字符

掌握这些搜索函数可以让你更有效地处理字符串数据,无论是简单的用户输入验证还是复杂的文本处理任务。

练习

  1. 编写一个程序,从一个给定的句子中统计元音字母的数量。
  2. 实现一个函数,将文本中的所有特定单词替换成另一个单词。
  3. 创建一个简单的CSV文件解析器,使用字符串搜索函数分割字段。
  4. 编写一个函数,检查一个字符串是否是回文(正读和反读都一样)。
  5. 实现一个简单的模板替换系统,从一个包含 {placeholder} 形式标记的模板字符串中替换所有标记。

通过这些练习,你将能够更好地掌握C++字符串搜索功能,为更复杂的文本处理任务打下坚实的基础。