目录
6.1 find_last_of - 查找字符集中任意字符首次出现
6.2 find_last_of - 查找字符集中任意字符最后一次出现
6.3 find_first_not_of - 查找不在字符集中的首个字符
1.容器操作
1.1 size() 和 length()
-
功能:返回字符串当前的字符数(长度)
-
区别:二者功能完全相同,size() 是STL容器的通用接口,length() 更直观表示字符串长度。
-
示例:
string s = "hello";
cout << s.size() <<endl; // 输出 5
cout << s.length(); // 输出 5
注意:length() 只能用于string类,其余的容器使用 size() 表示长度
1.2 capacity()
-
功能:返回字符串当前分配的内存容量(以字节为单位),可能大于实际长度
-
示例:
string s;
s.reserve(100);
cout << s.capacity(); // 输出至少 100
1.3 reserve(n)
-
功能:预分配至少n字节的内存,避免后续操作频繁扩容
-
注意:若n小于当前容量吗,可能无效果(不缩减内存,即:不会主动释放或者减少已分配的内存)
-
示例:
string s;
s.reserve(100); // 预分配内存
1.4 resize()
resize()是成员函数,直接修改原字符串,不返回值
1.4.1 resize(n , c)
-
功能:调整字符串长度为n
若 n > 当前长度,多出部分用字符 c 填充(默认为空字符 \0 )
若 n < 当前长度,截断字符串至前 n 个字符
-
示例:
string s = "hi";
s.resize(5, 'x'); // 变为 "hixxx"
cout << s << endl;
注意:resize()是成员函数,直接修改原字符串,不返回值
string s = "hi";
cout << s.resize(5, 'x') << endl; // error
1.4.2 resize(n)
-
功能:将字符串长度改为 n,如果 n 小于当前长度,会截断字符串
-
示例:
string s = "hello";
s.resize(3); // 变为 "hel"
cout << s << endl;
1.5 clear()
-
功能:清空字符串内容,长度置零,但不释放内存(容量不变)
-
示例:
string s = "hello";
cout << "原长度:" << s.size() << endl; // 输出 0
cout << "原容量:" << s.capacity() << endl;
s.clear();
cout << "现长度:" << s.size() << endl; // 输出 0
cout << "现容量:" <<s.capacity(); // 容量不变
1.6 empty()
-
功能:判断字符串是否为空(等价于 size() == 0 )
-
示例:
string s;
cout << s.empty() << endl; // 输出 true
s = "test";
cout << s.empty(); // 输出 false
2.基本迭代器访问
2.1 begin()与end()
string str = "Hello World";
// ===== 1. 正向遍历(begin/end)=====
cout << "正向遍历: ";
for (auto it = str.begin(); it != str.end(); ++it) {
cout << *it;
}
cout << "\n";
// 输出: Hello World
注意:begin()是第一个字符,而end()则是最后一个字符的后一位 [begin(),end())
2.2 rbegin()与rend()
// ===== 2. 反向遍历(rbegin/rend)=====
cout << "反向遍历: ";
for (auto rit = str.rbegin(); rit != str.rend(); ++rit) {
cout << *rit;
}
cout << "\n";
// 输出: dlroW olleH
2.3修改内容
// ===== 3. 修改内容 =====
// 将所有字母转为大写
for (auto it = str.begin(); it != str.end(); ++it) {
if (islower(*it)) {
*it = toupper(*it);//toupper需调用<cctype>,作用是将用于将小写字母转换为大写字母
}
}
cout << "转为大写: " << str << "\n";
// 输出: HELLO WORLD
2.4使用函数
// ===== 4. 使用算法(reverse)=====
reverse(str.begin(), str.end());
cout << "反转字符串: " << str << "\n";
// 输出: DLROW OLLEH
注意:reverse()(反转字符串,需要algorithm的库)与之前的reserve()(预留内存)的拼写
2.5查找字符
// ===== 5. 查找字符 =====
auto found = find(str.begin(), str.end(), 'O');
if (found != str.end()) {
cout << "找到'O',位置: " << (found - str.begin()) << "\n";
} else {
cout << "未找到'O'\n";
}
// 输出: 找到'O',位置: 5
3.转换函数
转换函数主要的作用就是使c++有更好的兼容性,更好的对接传统C语言库
3.1 c_str()
-
功能:返回一个指向以
\0
结尾的C风格字符串(const char*)的指针 -
特点:
-
保证返回的指针指向的字符串以\0结尾
-
返回的指在std::string修改或销毁后失效(悬空指针)
-
-
用途:需要与C语言接口交互时(如调用printf,strcpy等)。
-
实例:
string s = "Hello";
const char* ptr = s.c_str();
cout << ptr << std::endl; // 输出: Hello
// 注意:修改s会导致ptr失效
s += " World";
// 以下行为未定义(可能崩溃或输出错误)
// cout << ptr << endl;
为什么会出现错误,并且时未被定义???
回答:是因为std::string是一个动态储存,c_str()是通过返回的指针来储存C语言字符串的,所以若是在使用c_str()后改变字符串可能会由于std::string导致内存地址改变,而使得从c_str()的指针无法正确指向,从而出现错误
3.2 data()
-
C++11及之前:返回const char*,但不保证以\0结尾(尽管大多数实现会结尾)
-
C++17及之后:与c_str()完全一致,保证以\0结尾
-
用途:需要直接访问底层字符数组(C++17后可以安全替代c_str())
-
示例:
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
int main() {
string s = "Hello";
const char* ptr = s.data();
cout << ptr << endl; // 输出: Hello
// C++17后可以安全使用
cout << strlen(ptr) << endl; // 输出: 5
}
3.3 copy(char* arr,len,pos)
-
功能:将std::string中从位置pos开始的len个字符复制到用户提供的字符数组arr中。
-
特点:
-
不自动添加\0,需手动处理。
-
返回实际复制的字符数(可能小于len,如果字符串不够长)
-
-
用途:需要将字符串内容复制到预分配的缓冲区(如网络传输、文件操作)
-
示例
#include <iostream>
#include <string>
using namespace std;
int main() {
string s = "Hello World";
char arr[20] = {0}; // 初始化为全0
// 复制前5个字符(不包括\0)
size_t copied = s.copy(arr, 5, 0);
arr[copied] = '\0'; // 手动添加结尾
cout << arr << endl; // 输出: Hello
return 0;
}
4.输入输出
4.1 getline(istream,string)
string line;
cout << "Enter a line with spaces: ";
getline(cin, line); // 读取整行,包括空格
cout << "You entered: " << line << endl;
将输入的值赋给string处定义的变量
5.比较运算符
5.1默认比较规则(字典序)
std::string 的比较是基于 逐个字符的 ASCII 值,类似于字典排序:
-
从第一个字符开始比较,如果不同,直接返回结果
-
如果所有字符都相同,但长度不同,较短的字符串更小
#include <iostream>
#include <string>
using namespace std;
int main() {
string s1 = "apple";
string s2 = "banana";
string s3 = "app";
string s4 = "apple";
cout << std::boolalpha;
cout << (s1 < s2) << "\n"; // true,因为 'a' < 'b'
cout << (s1 > s3) << "\n"; // true,因为 "apple" 比 "app" 长
cout << (s1 == s4) << "\n"; // true,完全相同
cout << (s1 != s2) << "\n"; // true,不同
}
5.2特殊情况
5.2.1大小写敏感
由于比较基于 ASCII 码,大写字母('A'=65)比小写字母('a'=97)小:
"Apple" < "apple" // true,因为 'A' < 'a'
5.2.2数组字符串比较
"100" < "99" // true,因为 '1' < '9'(逐字符比较,不是数值比较)
5.2.3空字符串
空字符串 "" 比任何非空字符串小:
"" < "a" // true
6.其他查找函数
6.1 find_last_of - 查找字符集中任意字符首次出现
size_t find_first_of(const string& str, size_t pos = 0) const;
size_t find_first_of(const char* s, size_t pos = 0) const;
size_t find_first_of(const char* s, size_t pos, size_t n) const;
size_t find_first_of(char c, size_t pos = 0) const;
#include <iostream>
#include <string>
int main() {
std::string str = "Hello, World! 123";
// 查找第一个数字
size_t found = str.find_first_of("0123456789");
if (found != std::string::npos) {
std::cout << "First digit at position " << found
<< ": " << str[found] << std::endl;
}
// 查找第一个标点符号
found = str.find_first_of(",.!?");
if (found != std::string::npos) {
std::cout << "First punctuation at position " << found
<< ": " << str[found] << std::endl;
}
return 0;
}
输出是
-
find_first_of("0123456789") 会查找字符串中第一个出现在 "0123456789"(即任意数字)中的字符
-
在 "Hello, World! 123" 中,第一个数字是 '1',位于索引 14('H' 是 0,以此类推)
-
如果找到,found 存储该位置;否则返回 std::string::npos
第二段同理。。。。。。。
6.2 find_last_of - 查找字符集中任意字符最后一次出现
size_t find_last_of(const string& str, size_t pos = npos) const;
size_t find_last_of(const char* s, size_t pos = npos) const;
size_t find_last_of(const char* s, size_t pos, size_t n) const;
size_t find_last_of(char c, size_t pos = npos) const;
#include <iostream>
#include <string>
int main() {
std::string filename = "example.txt";
// 查找最后一个点号(文件扩展名分隔符)
size_t dot_pos = filename.find_last_of(".");
if (dot_pos != std::string::npos) {
std::string ext = filename.substr(dot_pos + 1);
std::cout << "File extension: " << ext << std::endl;
}
// 查找最后一个路径分隔符
std::string path = "/usr/local/bin/program";
size_t slash_pos = path.find_last_of("/\\");
if (slash_pos != std::string::npos) {
std::string program_name = path.substr(slash_pos + 1);
std::cout << "Program name: " << program_name << std::endl;
}
return 0;
}
-
find_last_of(".") 从字符串末尾向前查找最后一个 '.' 的位置
-
在 "example.txt" 中,'.' 位于索引 7('e' 是 0,'x' 是 1,...,'.' 是 7)
-
filename.substr(dot_pos + 1) 提取 '.' 之后的部分,即 "txt"
第二段同理。。。。。。。
6.3 find_first_not_of - 查找不在字符集中的首个字符
size_t find_first_not_of(const string& str, size_t pos = 0) const;
size_t find_first_not_of(const char* s, size_t pos = 0) const;
size_t find_first_not_of(const char* s, size_t pos, size_t n) const;
size_t find_first_not_of(char c, size_t pos = 0) const;
#include <iostream>
#include <string>
int main() {
std::string str = " Hello, World!";
// 查找第一个非空白字符
size_t first_non_space = str.find_first_not_of(" \t\n\r");
if (first_non_space != std::string::npos) {
std::cout << "First non-space at position " << first_non_space
<< ": " << str[first_non_space] << std::endl;
}
// 验证字符串是否全是数字
std::string number = "12345a";
size_t non_digit = number.find_first_not_of("0123456789");
if (non_digit != std::string::npos) {
std::cout << "Non-digit character found at position " << non_digit
<< ": " << number[non_digit] << std::endl;
}
return 0;
}
-
find_first_not_of(" \t\n\r") 查找第一个不在 " \t\n\r"(空格、制表符、换行符、回车符)中的字符
-
在 " Hello, World!" 中,前 4 个字符是空格,第 5 个字符 'H' 是第一个非空白字符
7.数值转换(C++11)
7.1字符串转数值的函数
stoi() - 将字符串转换为 int
stol() - 将字符串转换为 long
stoll() - 将字符串转换为 long long
stof() - 将字符串转换为 float
stod() - 将字符串转换为 double
stold() - 将字符串转换为 long double
#include <string>
#include <iostream>
using namespace std;
int main() {
string numStr = "123";
// 字符串转整数
int n1 = std::stoi(numStr); // 123
long n2 = std::stol(numStr); // 123L
float f = std::stof("3.14"); // 3.14f
double d = std::stod("3.14159"); // 3.14159
// 可以指定转换的基数(如16进制)
int hex = std::stoi("FF", nullptr, 16); // 255
cout << n1 << ", " << n2 << ", " << f << ", " << d << ", " << hex << endl;
}
7.2数值转字符串的函数
to_string - 将数值转化为字符串
#include <string>
#include <iostream>
using namespace std;
int main() {
// 数值转字符串
string s1 = to_string(42); // "42"
string s2 = to_string(3.14); // "3.140000"
string s3 = to_string(2.718f); // "2.718000"
cout << s1 << ", " << s2 << ", " << s3 << endl;
}
8.swap函数
作用:高效的交换两个字符串内容
string a = "apple", b = "banana";
a.swap(b); // a变为"banana",b变为"apple"
cout << "a是 " << a << endl;
cout << "b是 " << b ;
9.移动语义(C++11)
移动构造函数与移动赋值运算符
string s1 = "Hello";
string s2 = move(s1); // 调用移动构造函数
string s3;
s3 = move(s2); // 调用移动赋值运算符
以上不管是移动构造函数还是移动赋值运算符都是用到了std::move,(所以就我来说,我的第一映像就是move即是移动构造函数又是移动赋值运算符,但,这种理解是错误的!!!)实际上,std::move是一个类型转换工具,只是将左值转换为右值引用(std::move的作用可以理解为:它不移动任何数据,只是告诉编译器:"这个对象可以被移动"),实际上,移动赋值运算符就是一个经过重载的“=”(operator=)
两者之间的区别:
-
移动构造函数用于初始化新对象时直接“窃取”资源(如 string s2 = std::move(s1);)
-
移动赋值运算符用于已存在对象赋值时先释放旧资源再“窃取”新资源(如 s3 = std::move(s2);)
10.其他函数
10.1 shrink_to_fit()
因为std::string在储存中内存会随着字符串的而增长,而自动分配更大的内存(通常是按指数级增长策略),以容纳新字符;但是,在字符串缩短时,size()会减少,但capacity()通常会保持不变,所以需要有一种显式的方式释放内存----------shrink_to_fit()
#include <iostream>
#include <string>
int main() {
std::string str = "This is a long string that will be erased later.";
std::cout << "Before erase - Size: " << str.size()
<< ", Capacity: " << str.capacity() << std::endl;
str.erase(10); // 删除第10个字符之后的所有内容
std::cout << "After erase - Size: " << str.size()
<< ", Capacity: " << str.capacity() << std::endl;
str.shrink_to_fit(); // 请求释放多余内存
std::cout << "After shrink - Size: " << str.size()
<< ", Capacity: " << str.capacity() << std::endl;
}
10.2 substr(pos,len)
-
作用:返回从 pos 开始、长度为 len 的子串(新 std::string 对象)
-
参数:
-
pos:起始位置(默认 0)
-
len:子串长度(默认到末尾)
-
-
注意:
-
不修改原字符串,返回独立拷贝
-
越界检查:若 pos > size() 抛出 std::out_of_range
-
-
示例:
std::string s = "Hello World";
std::string sub1 = s.substr(6); // "World"(从第6字符到末尾)
std::string sub2 = s.substr(0, 5); // "Hello"(前5字符)
在以下链接中的“获得子串”部分有substr()更详细的示例
愿你在代码的世界里如鱼得水,bug退散,灵感如泉涌!保持热爱,奔赴下一场山海,轻松快乐永远是主旋律~ 🎉(附赠一只蹦跶的电子猫:=^・ω・^=)