String 类详解
2.1 std::string
类的引入和优势
std::string
类是 C++ 标准库中用于处理字符串的类。相比于 C 风格的字符数组,std::string
提供了以下优势:
- 自动内存管理: 无需手动分配和释放内存,避免了内存泄漏和缓冲区溢出的风险。
- 动态大小: 字符串的长度可以根据需要动态增长。
- 丰富的成员函数: 提供了各种方便的字符串操作函数。
- 更安全易用: 避免了 C 风格字符串操作中常见的错误。
2.2 std::string
类的常用构造函数
cpp
#include <string>
#include <iostream>
int main() {
std::string s1; // 默认构造函数,创建一个空字符串
std::string s2("Hello"); // 使用 C 风格字符串初始化
std::string s3 = "World"; // 拷贝初始化
std::string s4(s2); // 拷贝构造函数
std::string s5(s2, 1, 3); // 使用 s2 的子串初始化 (从索引 1 开始,长度为 3)
std::string s6(10, 'a'); // 创建包含 10 个 'a' 的字符串
std::string s7(s2.begin(), s2.end()); // 使用迭代器初始化
std::cout << "s1: " << s1 << std::endl;
std::cout << "s2: " << s2 << std::endl;
std::cout << "s3: " << s3 << std::endl;
std::cout << "s4: " << s4 << std::endl;
std::cout << "s5: " << s5 << std::endl;
std::cout << "s6: " << s6 << std::endl;
std::cout << "s7: " << s7 << std::endl;
return 0;
}
2.3 std::string
类的常用操作函数
函数 | 描述 | 示例 |
---|---|---|
+ (连接) |
连接两个字符串或字符串与字符/C 风格字符串 | std::string s = "Hello" + " " + "World"; |
+= (追加) |
将字符串或字符/C 风格字符串追加到现有字符串末尾 | std::string s = "Hello"; s += " World!"; |
append |
在字符串末尾追加字符串或其子串 | std::string s = "Hello"; s.append(" World"); |
find |
查找子串第一次出现的位置,找不到返回 std::string::npos |
std::string s = "abcdefg"; size_t pos = s.find("cde"); |
rfind |
查找子串最后一次出现的位置 | std::string s = "abcdecdef"; size_t pos = s.rfind("cde"); |
find_first_of |
查找字符串中第一个与指定字符集合中任何字符匹配的字符的位置 | std::string s = "abcdefg"; size_t pos = s.find_first_of("ce"); |
substr |
返回指定范围的子串 | std::string s = "abcdefg"; std::string sub = s.substr(1, 3); |
insert |
在指定位置插入字符串或字符 | std::string s = "abc"; s.insert(1, "xyz"); |
replace |
替换指定范围内的子串 | std::string s = "abcdefg"; s.replace(1, 3, "XYZ"); |
erase |
删除指定位置或范围内的字符 | std::string s = "abcdefg"; s.erase(1, 3); |
length / size |
返回字符串的长度 (字符个数) | std::string s = "Hello"; int len = s.length(); |
capacity |
返回当前已分配的存储空间大小 (可能大于实际长度) | std::string s = "Hello"; int cap = s.capacity(); |
empty |
检查字符串是否为空 | std::string s; bool isEmpty = s.empty(); |
clear |
清空字符串内容,使其长度变为 0 | std::string s = "Hello"; s.clear(); |
compare |
比较两个字符串 | std::string s1 = "abc"; std::string s2 = "abd"; int res = s1.compare(s2); |
c_str |
返回一个指向以 null 结尾的 C 风格字符串的常量指针 (const char*) | std::string s = "Hello"; const char* cstr = s.c_str(); |
示例:字符串的操作 |
cpp
#include <iostream>
#include <string>
using namespace std;
int main() {
string str = "Hello";
string world = " World";
// 连接字符串
string greeting = str + world;
cout << "Greeting: " << greeting << endl; // 输出:Hello World
// 追加字符串
greeting += "!";
cout << "Greeting: " << greeting << endl; // 输出:Hello World!
// 查找子串
size_t pos = greeting.find("World");
if (pos != string::npos) {
cout << "'World' found at position: " << pos << endl; // 输出:'World' found at position: 6
}
// 截取子串
string sub = greeting.substr(0, 5);
cout << "Substring: " << sub << endl; // 输出:Hello
// 替换子串
greeting.replace(6, 5, "Universe");
cout << "Greeting after replace: " << greeting << endl; // 输出:Hello Universe!
return 0;
}
2.4 访问字符串元素
与 C 风格字符串类似,std::string
允许通过下标访问单个字符,并提供了更安全的 at()
方法。
方法 | 描述 | 示例 |
---|---|---|
[] |
通过下标访问字符串元素,不进行越界检查,可能导致未定义行为 | char c = str[0]; |
at() |
通过下标访问字符串元素,进行越界检查 ,越界会抛出 std::out_of_range 异常 |
char c = str.at(0); |
front() |
返回字符串的第一个字符的引用 | char c = str.front(); |
back() |
返回字符串的最后一个字符的引用 | char c = str.back(); |
示例:访问字符串元素
cpp
#include <iostream>
#include <string>
#include <stdexcept> // 需要包含这个头文件来处理异常
using namespace std;
int main() {
string str = "Hello";
cout << "First character: " << str[0] << endl; // 输出:H
cout << "First character: " << str.at(0) << endl; // 输出:H
cout << "Last character: " << str.back() << endl; // 输出:o
try {
// str.at(10); // 这会抛出 std::out_of_range 异常
} catch (const out_of_range& e) {
cerr << "Caught an out_of_range exception: " << e.what() << endl;
}
return 0;
}
2.5 std::string
的迭代器
std::string
也支持迭代器,可以用于遍历字符串中的字符。
begin()
: 返回指向字符串第一个字符的迭代器。end()
: 返回指向字符串末尾之后一个位置的迭代器。rbegin()
: 返回指向字符串最后一个字符的反向迭代器。rend()
: 返回指向字符串开头之前一个位置的反向迭代器。
示例:使用迭代器遍历字符串
cpp
#include <iostream>
#include <string>
using namespace std;
int main() {
string str = "Hello";
cout << "Using forward iterators: ";
for (string::iterator it = str.begin(); it != str.end(); ++it) {
cout << *it << " "; // 输出:H e l l o
}
cout << endl;
cout << "Using reverse iterators: ";
for (string::reverse_iterator rit = str.rbegin(); rit != str.rend(); ++rit) {
cout << *rit << " "; // 输出:o l l e H
}
cout << endl;
// C++11 引入的基于范围的 for 循环更加简洁
cout << "Using range-based for loop: ";
for (char c : str) {
cout << c << " "; // 输出:H e l l o
}
cout << endl;
return 0;
}
2.6 std::string
的内存管理
std::string
负责管理其内部存储字符串数据的内存。当你对 std::string
对象进行操作(如追加、插入等)时,如果当前的内存空间不足以容纳新的字符串,std::string
会自动分配更大的内存空间,并将原有数据复制到新的空间。 这就是为什么使用 std::string
可以避免手动内存管理带来的问题。