C++中string常用方法总结
- STL主要由以下六个部分组成:
在学习STL的时候,更多是一个探索过程,我们要多查文档了解用法,在实践和练习中学习。https://legacy.cplusplus.com/reference/这个文档按头文件整理,虽然不是官方的,但是对初学者较为友好。
二,string常用接口
在 C++ 里,std::string是标准库中的类,它处于std命名空间中。 首先介绍一下string和C风格字符串的区别:
代码语言:javascript
AI代码解释
string s1("hello world"); char s2[] = "hello world";对于上面两个字符串在内存中的存储,s1不带\0,s2带\0
所以对于C风格的字符串,我们无法直接使用string的方法,对于string类型的字符串,我们要使用C风格字符串的方法需要通过c_str()转换成C风格的字符串,因为C风格的字符串操作大多是需要使用\0的。
1. 构造函数
string(): 默认构造函数,创建一个空字符串。string(const char* s): 用 C 风格字符串初始化。string(const string& str): 拷贝构造函数。string(size_t n, char c): 创建一个包含n个字符c的字符串。
示例:
代码语言:javascript
AI代码解释
std::string s1; // 空的string类对象 // 使用 C 风格字符串初始化 std::string s2("Hello, World!"); // 使用拷贝构造函数,用 s2 初始化 s3 std::string s3(s2); // 创建一个包含 5 个字符 'A' 的字符串 std::string s4(5, 'A');2. 赋值操作
string& operator=(const string& str): 赋值操作符。
代码语言:javascript
AI代码解释
std::string str1 = "Initial value"; // 这是拷贝构造初始化 std::string str2; // 使用赋值操作符 = 将 str1 的内容赋给 str2 str2 = str1;3. 元素访问及遍历
char& operator[](size_t pos): 访问指定位置的字符(不检查边界)。就和使用数组下标一样。
代码语言:javascript
AI代码解释
std::string str = "Hello, World!"; // 使用 operator[] 访问指定位置的字符(不检查边界) // 修改指定位置的字符 str[0] = 'h';==迭代器==是学习容器非常重要的一个概念,迭代器类似指针,也可以加减来移动,但是不能大小比较,且不同类型的迭代器不能比较(如iterator和reverse_iterator类型不能比较)
iterator begin(): 返回指向字符串开头的迭代器。iterator end(): 返回指向字符串末尾的迭代器。reverse_iterator rbegin(): 返回指向字符串末尾的反向迭代器。reverse_iterator rend(): 返回指向字符串开头的反向迭代器。
利用迭代器访问:
代码语言:javascript
AI代码解释
int main() { std::string str = "Hello, World!"; // 使用 begin() 和 end() 正向遍历字符串 std::cout << "正向遍历字符串: "; for (std::string::iterator it = str.begin(); it != str.end(); ++it) { std::cout << *it; } std::cout << std::endl; // 使用 rbegin() 和 rend() 反向遍历字符串 std::cout << "反向遍历字符串: "; for (std::string::reverse_iterator rit = str.rbegin(); rit != str.rend(); ++rit) { std::cout << *rit; } std::cout << std::endl; return 0; }输出:
代码语言:javascript
AI代码解释
正向遍历字符串: Hello, World! 反向遍历字符串: !dlroW ,olleHauto用于自动推到类型,常用在替换较长的代码名称。 注意:auto声明的变量必须有初始值,因为编译器需要根据初始值来推导类型。且auto不能用在函数参数 利用auto和范围for访问:
代码语言:javascript
AI代码解释
// 使用范围 for 和 auto 访问 for (auto ch : str) { std::cout << ch; } return 0; }4. 大小和容量操作
size_t size() const: 返回字符串的长度。size_t length() const: 与size()相同,返回字符串的长度。bool empty() const: 判断字符串是否为空。void resize(size_t n): 调整字符串的大小。size_t capacity() const: 返回当前分配的存储空间大小。void reserve(size_t n): 预留存储空间。void clear(): 清空字符串。(但是开的空间不清)
代码语言:javascript
AI代码解释
#include <iostream> #include <string> int main() { // 定义一个字符串对象并初始化为 "Hello" std::string str = "Hello"; // 使用 size() 方法返回字符串的长度 // 这里输出字符串使用 size() 方法得到的长度 std::cout << "使用 size() 方法得到的字符串长度: " << str.size() << std::endl; // 使用 length() 方法返回字符串的长度 // length() 和 size() 功能一样,这里输出使用 length() 方法得到的长度 std::cout << "使用 length() 方法得到的字符串长度: " << str.length() << std::endl; // 使用 empty() 方法判断字符串是否为空 // 根据 empty() 的返回结果输出字符串是否为空的信息 std::cout << "字符串是否为空? " << (str.empty() ? "是" : "否") << std::endl; // 使用 resize() 方法调整字符串的大小 // 将字符串大小调整为 10,如果新长度大于原长度,用 '!' 填充,如果新长度小于原长度,则截断 str.resize(10, '!'); // 输出调整大小后的字符串 std::cout << "调整大小为 10 并用 '!' 填充后的字符串: " << str << std::endl; // 输出调整大小后字符串的新长度 std::cout << "调整大小后的新长度: " << str.size() << std::endl; // 使用 capacity() 方法返回当前为字符串分配的存储空间大小 std::cout << "当前字符串分配的存储空间大小: " << str.capacity() << std::endl; // 使用 reserve() 方法预留存储空间 // 预留至少能容纳 20 个字符的存储空间 str.reserve(20); // 输出预留存储空间后的容量 std::cout << "预留 20 个字符存储空间后的容量: " << str.capacity() << std::endl; // 使用 clear() 方法清空字符串 str.clear(); // 再次使用 empty() 方法判断字符串是否为空并输出结果 std::cout << "清空字符串后是否为空? " << (str.empty() ? "是" : "否") << std::endl; return 0; }运行结果:
说明:为什么预留
reserve(20)但是开的capacity是31? 首先,先了解一下string的自动扩容: 当向string中添加字符,使得字符数量超过其当前分配的容量capacity时,string会自动进行扩容操作。但是,不同的标准库实现可能采用不同的扩容策略,但常见的做法是按照一定的倍数进行扩容。例如,当需要扩容时,可能会将容量扩大为原来的2 倍,这样可以减少频繁扩容带来的性能开销。 所以当我们reserve(20)的时候,编译器会根据自己的标准进行扩容,确保开的空间是>=20的。 对于reserve(n),如果n比目前的字符串小,就不会执行,但是如果比capacity小,比字符串大则可能执行,由编译器决定.
5. 修改操作
string& append(const string& str): 在字符串末尾追加字符串。string& operator+=(const string& str): 追加字符串。void push_back(char c): 在字符串末尾追加一个字符。string& insert(size_t pos, const string& str): 在指定位置插入字符串。string& erase(size_t pos = 0, size_t len = npos): 删除从pos开始的len个字符。string& replace(size_t pos, size_t len, const string& str): 替换从pos开始的len个字符为str。
示例:
代码语言:javascript
AI代码解释
int main() { std::string str = "Hello"; // 使用 append(const string& str) 在字符串末尾追加字符串 std::string appendStr = ", World"; str.append(appendStr); std::cout << "使用 append 追加后: " << str << std::endl; // 使用 operator+=(const string& str) 追加字符串 std::string anotherAppend = "!"; str += anotherAppend; std::cout << "使用 += 追加后: " << str << std::endl; // 使用 push_back(char c) 在字符串末尾追加一个字符 str.push_back('?'); std::cout << "使用 push_back 追加字符后: " << str << std::endl; // 使用 insert(size_t pos, const string& str) 在指定位置插入字符串 std::string insertStr = " amazing"; str.insert(5, insertStr); std::cout << "在位置 5 插入字符串后: " << str << std::endl; // 使用 erase(size_t pos = 0, size_t len = npos) 删除从 pos 开始的 len 个字符 str.erase(5, insertStr.length()); std::cout << "删除插入的字符串后: " << str << std::endl; // 使用 replace(size_t pos, size_t len, const string& str) 替换从 pos 开始的 len 个字符为 str std::string replaceStr = "Hi"; str.replace(0, 5, replaceStr); std::cout << "替换前 5 个字符后: " << str << std::endl; return 0; }运行结果:
6. 子字符串操作
string substr(size_t pos = 0, size_t len = npos) const: 返回从pos开始的len个字符组成的子字符串。
示例:
代码语言:javascript
AI代码解释
std::string mainStr = "Hello, Hello, World!"; std::string Sub = mainStr.substr(3, 7); std::cout << Sub << std::endl; // 输出:lo, Hel7. 查找操作
size_t find(const string& str, size_t pos = 0) const: 从pos开始查找子字符串str。size_t rfind(const string& str, size_t pos = npos) const: 从pos开始反向查找子字符串str。
npos是static const size_t类型的-1,但是size_t是一种无符号整数类型,所以以补码的形式存储-1就相当于一个很大的数
示例:
代码语言:javascript
AI代码解释
#include <iostream> #include <string> int main() { std::string mainStr = "Hello, Hello, World!"; std::string subStr = "Hello"; // 使用 find(const string& str, size_t pos = 0) 从 pos 开始查找子字符串 str size_t foundPos = mainStr.find(subStr, 0); if (foundPos != std::string::npos) { std::cout << "使用 find 从位置 0 开始查找,首次找到 \"" << subStr << "\" 的位置是: " << foundPos << std::endl; } else { std::cout << "使用 find 从位置 0 开始查找,未找到 \"" << subStr << "\"。" << std::endl; } // 从位置 7 开始查找 foundPos = mainStr.find(subStr, 7); if (foundPos != std::string::npos) { std::cout << "使用 find 从位置 7 开始查找,找到 \"" << subStr << "\" 的位置是: " << foundPos << std::endl; } else { std::cout << "使用 find 从位置 7 开始查找,未找到 \"" << subStr << "\"。" << std::endl; } // 使用 rfind(const string& str, size_t pos = npos) 从 pos 开始反向查找子字符串 str size_t rfoundPos = mainStr.rfind(subStr); if (rfoundPos != std::string::npos) { std::cout << "使用 rfind 反向查找,最后一次找到 \"" << subStr << "\" 的位置是: " << rfoundPos << std::endl; } else { std::cout << "使用 rfind 反向查找,未找到 \"" << subStr << "\"。" << std::endl; } return 0; }运行结果:
8. 比较操作
bool operator==(const string& str) const: 判断两个字符串是否相等。bool operator!=(const string& str) const: 判断两个字符串是否不相等。int compare(const string& str) const: 比较两个字符串
C ++字符串支持常见的比较操作符(>,>=,<,<=,==,!=),甚至支持string与C-string的比较(如 str<”hello”)。 因为会发生隐式类型转换,把C风格的转换成string
示例:compare方法提供了更多的重载形式,支持用索引值和长度定位子串来进行比较,功能灵活
代码语言:javascript
AI代码解释
#include <iostream> #include <string> int main() { std::string str1 = "apple pie"; std::string str2 = "applesauce"; // 比较 str1 从位置 0 开始的 5 个字符和 str2 从位置 0 开始的 5 个字符 int result = str1.compare(0, 5, str2, 0, 5); if (result == 0) { std::cout << "str1 和 str2 的前 5 个字符相等" << std::endl; } return 0; }10. C 风格字符串转换
const char* c_str() const: 返回一个指向 C 风格字符串的指针。
示例:
代码语言:javascript
AI代码解释
#include <iostream> #include <string> #include <cstring> int main() { std::string str1 = "apple"; std::string str2 = "banana"; // 使用 c_str() 转换为 C 风格字符串 const char* cstr1 = str1.c_str(); const char* cstr2 = str2.c_str(); // 使用 C 风格的 strcmp 函数比较两个字符串 int result = strcmp(cstr1, cstr2); if (result < 0) { std::cout << "str1 小于 str2" << std::endl; } else if (result > 0) { std::cout << "str1 大于 str2" << std::endl; } else { std::cout << "str1 等于 str2" << std::endl; } return 0; }11. getline
getline用于从输入流(标准或文件)中读取一行文本(默认以\n作为分隔符)scanf和cin默认是以空白字符(空格、制表符、换行符等)作为分隔来读取数据的。 函数原型:std::istream& getline(std::istream& is, std::string& str, char delim);
is:输入流对象,通常是 std::cin 用于从标准输入读取数据。str:用于存储读取到的一行文本的 std::string 对象。delim(可选):分隔符,默认是换行符\n。当遇到该分隔符时,读取停止(不会读取分隔符)。
