string类的使用
C++ 中的
string
类是标准库<string>
中提供的一个类,封装了动态数组的字符序列,常用于处理字符串。
string 类对象的常见构造
默认构造函数:
std::string str; // 创建一个空字符串,长度为0
通过另一个 string 对象复制:
std::string str1 = "Hello";
std::string str2(str1); // 复制 str1 到 str2
通过子串构造
std::string str1 = "hello";
std::string str2(str1,2,2)// 创建一个str1的子串,从下标2开始,长度为2
//默认长度为string::npos,即字符串长度最大值。
通过字符串字面量初始化:
std::string str = "Hello"; // 创建一个内容为 "Hello" 的字符串
通过字符数组初始化:
const char* cstr = "World";
std::string str(cstr); // 将字符数组 cstr 转换为 string 对象
通过部分字符数组初始化:
const char* cstr = "Hello, World!";
std::string str(cstr, 5); // 创建一个内容为 "Hello" 的字符串,限制长度为 5
通过重复某个字符初始化:
std::string str(5, 'A'); // 创建一个字符串 "AAAAA",长度为 5,内容为 'A'
通过迭代器初始化:
std::string str1 = "hello";
std::string str3(str1.begin(), str1.end());// 创建一个str1的拷贝,从begin到end
构造函数文档
string类对象的容量操作
size()
或 length()
:
size_t len = str.size(); // 返回字符串的长度(字符数)
empty()
:
bool isEmpty = str.empty(); // 判断字符串是否为空
capacity()
:
size_t cap = str.capacity(); // 返回当前分配的容量,可能大于或等于字符串的实际大小
clear()
str.clear();//清空字符串内容
resize()
-
作用:
resize()
改变字符串的 实际大小,即字符串的字符数。它可以增加或减少字符串的大小。 -
参数:
resize(n)
:将字符串的大小调整为n
。如果n
大于当前的大小,字符串会被 填充(默认使用空字符'\0'
)。如果n
小于当前大小,则会 截断 字符串。resize(n, c)
:将字符串的大小调整为n
,如果增加字符,则用字符c
填充。
-
示例:
std::string str = "Hello"; str.resize(10, 'X'); // 字符串变为 "HelloXXXXX",长度为 10,末尾填充 'X' str.resize(3); // 字符串变为 "Hel",长度为 3,截断多余字符
-
特点:
- 改变的是 字符串的大小,也就是字符的数量。
- 增加大小时,可能会使用填充字符(默认是
'\0'
,除非指定填充字符)。 - 如果
n
小于当前大小,字符串会被 截断。 - 可能会重新分配内存,尤其是增加大小时。
string::resize - C++ Reference
reserve()
-
作用:
reserve()
改变字符串的 容量(即为内部存储预分配内存)。它不会改变字符串的实际大小,只是确保字符串的内部缓冲区能够容纳至少n
个字符。reserve()
是为了优化内存分配,减少未来的内存重新分配。 -
参数:
reserve(n)
:为字符串分配至少n
个字符的内存空间。如果n
比当前容量大,则会分配新的内存;如果n
小于或等于当前容量,则什么都不做。
-
示例:
std::string str = "Hello"; str.reserve(20); // 为字符串预留至少 20 个字符的空间 // 字符串的大小仍然是 5,但内部容量变为 20
-
特点:
- 改变的是 字符串的容量,即分配的内存大小,而不是字符串的实际字符数。
reserve()
并不会改变字符串的大小,实际字符数保持不变,容量变大是为了后续可能的字符添加。- 它 不会增加或减少字符串的字符数,仅仅是内存优化。
- 提高效率:如果知道之后会向字符串中添加大量字符,提前调用
reserve()
可以避免多次分配内存,从而提高效率。
string::reserve - C++ Reference
string类对象的访问及遍历操作
operator[]
(访问字符)
operator[]
允许你通过下标直接访问字符串中的字符。这是最常见的访问方式,返回指定位置的字符。
-
语法:
char c = str[pos]; // 访问字符串中位置为 pos 的字符
-
特点:
- 不会检查越界,若
pos
超出了字符串的长度,会导致未定义行为。
- 不会检查越界,若
-
示例:
std::string str = "Hello"; char c = str[1]; // c = 'e'
at()
(访问字符并进行边界检查)
at()
函数类似于 operator[]
,但它会 进行边界检查。如果访问越界,它会抛出 std::out_of_range
异常。
-
语法:
char c = str.at(pos); // 访问字符串中位置为 pos 的字符
-
特点:
- 如果
pos
超出有效范围,会抛出异常。 - 更安全,因为会进行越界检查。
- 如果
-
示例:
std::string str = "Hello"; try {char c = str.at(10); // 抛出 std::out_of_range 异常 } catch (const std::out_of_range& e) {std::cout << "Out of range: " << e.what() << std::endl; }
begin()
和 end()
(获取迭代器)
begin()
和 end()
返回指向字符串开始和结束位置的 迭代器。
-
begin()
返回指向第一个字符的迭代器。 -
end()
返回指向最后一个字符 下一个位置 的迭代器。 -
语法:
auto it_begin = str.begin(); // 指向第一个字符的迭代器 auto it_end = str.end(); // 指向最后一个字符之后的迭代器 std::string::iterator it_begin = str.begin();//指向第一个字符 std::string::iterator it_end = str.end();//指向最后一个字符的下一个位置
-
特点:
begin()
返回一个指向第一个字符的迭代器,end()
返回一个指向末尾之后位置的迭代器。
-
示例:
std::string str = "Hello"; for (auto it = str.begin(); it != str.end(); ++it) {std::cout << *it; // 输出每个字符 }
rbegin()
和 rend()
(反向迭代器)
rbegin()
和 rend()
返回指向字符串 末尾 和 开头前一个位置 的 反向迭代器。反向迭代器从字符串的最后一个字符开始,向前遍历。
-
语法:
auto it_rbegin = str.rbegin(); // 指向最后一个字符的反向迭代器 auto it_rend = str.rend(); // 指向第一个字符前一个位置的反向迭代器
-
特点:
rbegin()
返回指向最后一个字符的反向迭代器,rend()
返回指向第一个字符前一个位置的迭代器。- 使用反向迭代器可以从后往前遍历字符串。
-
示例:
std::string str = "Hello"; for (auto it = str.rbegin(); it != str.rend(); ++it) {std::cout << *it; // 输出每个字符,从后往前 }
范围 for
循环(C++11 )
C++11 引入的范围 for
循环使得遍历容器变得更加简洁。它可以直接遍历容器中的元素,而不需要显式使用迭代器或下标。
-
语法:
for (auto ch : str) {std::cout << ch; // 直接遍历字符串中的每个字符 }
-
特点:
- 语法简洁。
- 自动根据容器类型选择适当的迭代器。
- 更加安全,不需要手动控制迭代器的增量或结束条件。
-
示例:
std::string str = "Hello"; for (char ch : str) {std::cout << ch; // 输出每个字符 }
string类对象的修改操作
push_back()
push_back()
方法用于将一个字符追加到字符串的末尾。
str.push_back('c'); // 在字符串的末尾添加字符 'c'
append()
append()
方法用于将一个字符串或字符序列添加到另一个字符串的末尾。你可以指定追加的字符数量,或者追加整个字符串。
str.append(" World"); // 将 " World" 追加到 str 后面
str.append("!", 1); // 将 "!" 追加到 str 后面,指定长度
operator+=
operator+=
用于将一个字符串或字符序列追加到现有的字符串对象的末尾。
它支持不同类型的操作数,包括:
- 另一个
std::string
对象 - 一个字符
- 一个 C 风格字符串
std::string str("hello");
std::string str1(" world");
str += str1; //string
str += "!!!"; //C-string
str += "!"; //character
c_str()
c_str()
返回一个指向 const char*
的指针,这个指针指向字符串对象内部数据的起始位置。这个字符串的内容是以 null 字符 ('\0'
) 结尾的,与 C 风格字符串的要求一致。
c_str()
的语法
const char* cstr = str.c_str();
- 其中
str
是一个std::string
对象,cstr
是返回的 C 风格字符串指针。 - 返回值
cstr
是一个指向const char
的指针,它指向str
内部数据的首字符
find
函数
find
用于在字符串中查找指定字符或子字符串的首次出现位置。如果找到了指定内容,find
返回它在字符串中的位置(索引);如果没有找到,则返回一个特殊的常量 std::string::npos
,表示未找到。
基本语法
size_t find(char ch, size_t pos = 0) const;
size_t find(const std::string& str, size_t pos = 0) const;
ch
:要查找的字符。str
:要查找的子字符串。pos
:开始查找的位置(默认为 0,表示从字符串的开始查找)。- 返回值:
- 如果找到了字符或子字符串,返回其位置(索引,从 0 开始)。
- 如果没有找到,返回
std::string::npos
注意
find
只返回首次出现的位置。如果有多个相同的字符或子字符串,只有第一个会被找到。
rfind
函数
rfind
是 find
的反向版本。它用于从字符串的末尾开始查找指定字符或子字符串的 最后一次 出现位置。
size_t rfind(char ch, size_t pos = std::string::npos) const;
size_t rfind(const std::string& str, size_t pos = std::string::npos) const;
ch
:要查找的字符。str
:要查找的子字符串。pos
:开始查找的位置,默认为std::string::npos
,表示从字符串的末尾开始查找。- 返回值:
- 如果找到了字符或子字符串,返回其位置(索引)。
- 如果没有找到,返回
std::string::npos
。
注意
rfind
只返回最后一次出现的位置。如果有多个相同的字符或子字符串,它会返回最后一个出现的索引。
substr
函数
用于提取字符串的子串。它允许从原始字符串中提取出一部分字符串,并返回一个新的 std::string
对象。
substr
的基本语法
std::string substr(size_t pos = 0, size_t len = npos) const;
pos
:表示子串的起始位置(索引),默认为 0,表示从字符串的开头开始。len
:表示要提取的子串的长度,默认为std::string::npos
,即直到字符串的结尾。如果指定的len
大于从pos
开始的位置到字符串末尾的剩余长度,则substr
会提取到字符串的结尾。
返回值:
- 返回一个新的
std::string
对象,包含从pos
开始,长度为len
的子串
string类非成员函数
std::getline
(从流中读取一行)
用于从输入流(如 std::cin
)中读取一行数据,并将其存储到一个 std::string
对象中。
语法
std::istream& std::getline(std::istream& is, std::string& str);
std::istream& std::getline(std::istream& is, std::string& str, char delim);
is
:输入流对象(如std::cin
或文件流)。str
:存储输入的一行文本的std::string
对象。delim
(可选):指定行结束符的分隔符(默认为换行符)。