【爱上C++】万字详解string类1:经典常用接口、操作
hello,今天咱们进入C++中string类的学习,今天这部分主要讲解string类的部分经典常用接口,其他很少使用的接口要学会及时查文档,现查现用。string类的模拟实现和深浅拷贝问题放在后面一篇讲解。
目录
- 一.string类简介
- 二.常见构造
- 三.容量操作
- 四.访问及遍历操作
- 1.下标+[ ]
- 2.at
- 拓展:try,catch 异常处理
- 3.迭代器
- 4.范围for
- begin+end,rbegin+rend
- 五.修改、运算操作(重点)
- 拓展:C风格字符串与string类型字符串
- 1.字符串连接和追加
- 2.字符串插入
- 3.字符串删除
- 4.字符串替换
- 5.字符串交换
- 6.字符串赋值
- 7.字符串内容访问
- 8.字符串查找
- 9.字符串子序列提取
- 六.非成员函数
- 本篇文章思维导图
一.string类简介
string类是C++标准库中的一个类,用于处理字符串。它封装了字符数组(通常是char类型)的操作,提供了许多方便的方法来创建、修改、访问和操作字符串。使用string类可以简化字符串的编程工作,并减少常见的错误,如缓冲区溢出.
在使用string类时需要包含头文件#include ,以及using namespace std;注意!不是C语言中是string.h
官方参考文档
上面是string类的文档介绍,在学习C++过程中,我们需要慢慢提高看英文文献,文档的能力。
- 字符串是表示字符序列的类
- 标准的字符串类提供了对此类对象的支持,其接口类似于标准字符容器的接口,但添加了专门用于操作
单字节字符字符串的设计特性。
- string类是使用char(即作为它的字符类型,使用它的默认char_traits和分配器类型(关于模板的更多信
息,请参阅basic_string)。
- string类是basic_string模板类的一个实例,它使用char来实例化basic_string模板类,并用char_traits
和allocator作为basic_string的默认参数(根于更多的模板信息请参考basic_string)。
- 注意,这个类独立于所使用的编码来处理字节:如果用来处理多字节或变长字符(如UTF-8)的序列,这个
类的所有成员(如长度或大小)以及它的迭代器,将仍然按照字节(而不是实际编码的字符)来操作。
总结:
- string是表示字符串的字符串类
- 该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。
- string在底层实际是:basic_string模板类的别名,typedef basic_string
string;
- 不能操作多字节或者变长字符的序列。
二.常见构造
string类提供了多种构造函数,用于创建字符串对象。这些构造函数允许你使用不同的方式初始化字符串,如使用字符数组、其他字符串对象、单个字符、或者一定数量的字符来填充。
注意:string 类重载了流插入和流体取,所以可以直接cin,cout;
string(); //构造一个空字符串 string(const char* s); //复制s所指的字符序列 string(const char* s, size_t n); //复制s所指字符序列的前n个字符 string(size_t n, char c); //生成n个c字符的字符串 string(const string& str); //生成str的复制品 string(const string& str, size_t pos, size_t len = npos); //复制str中从字符位置pos开始并跨越len个字符的部分 string(const string& str, size_t pos); //复制str中从pos位置开始直到末尾的字符
使用示例:
string s1; //构造空字符串 string s2("hello world"); //复制hello world到s2 string s3("hello,world", 3); //复制hello world的前3个字符 string s4(s2, 0, 4); //从s2的0位置开始,复制4个 string s5(s2, 3); //从s2的3位置开始,一直复制到末尾 string s6(s2); string s7 = s2; //两个都是拷贝构造,复制s2的值 string s8(s2, 0, 10000); //第三个参数大于字符串长度,就是一直复制直到末尾 //注意区别s3和s5; string s9(9, 'a'); //填充9个'a' //拓展: string s10 = s2;//拷贝赋值操作,将 s2 的内容复制到 s1 中。 string s11 = "hello"; //字符串字面值会隐式转换为 std::string 对象,然后再赋给 s1。这涉及到了转换构造函数和拷贝赋值操作 string s12 = "x"; //由于 std::string 类型重载了接受单个字符作为参数的赋值运算符 (operator=),这行代码将一个只包含字符 'x' 的字符串赋给了 s1 //注意:string s12='x';是错的 //在 C++ 中,使用单引号括起来的字符 'x' 表示一个字符字面值(char literal),而不是字符串。因此,将一个字符字面值直接赋给一个 std::string 对象会导致编译错误,因为类型不匹配。要将字符 'x' 转换为一个字符串,可以使用双引号将其括起来,例如:"x"。npos:在这个示例中,npos 并没有直接出现在代码中,而是作为string类的一个静态成员变量,
表示字符串的末尾位置。它的值是一个特殊的常量 ,通常是一个 大整数值,用来表示字符
串中的无效位置或者末尾位置。在构造函数的默认参数中,len 的默认值就是npos,这意
味着如果不显式地指定长度,则会从起始位置一直复制到字符串的末尾。
总之,npos是string类来表示字符串末尾位置的特殊常量。
三.容量操作
☆讲解:
1. size
2. length
size()与length()方法底层实现原理完全相同,引入size()的原因是为了与其他容器的接口保持一
致,一般情况下基本都是用size()。size() 和 length() 的计算不包含 \0。
string s1("hello,bit"); cout using namespace std; string s = "Hello, World!"; try { // 访问并打印指定位置的字符 cout cout // 可能抛出异常的代码块 } catch (异常类型1 参数名) { // 处理异常类型1的代码 } catch (异常类型2 参数名) { // 处理异常类型2的代码 } catch (...) { // 处理其他所有未被前面catch块捕获的异常 } try { throw std::runtime_error("Something went wrong"); // 抛出一个异常 } catch (const std::runtime_error& e) { // 捕获 runtime_error 类型的异常 std::cout // 捕获其他所有类型的异常 std::cout using namespace std; vector1, 2, 3, 4, 5}; // 使用迭代器遍历vector for (vector cout using namespace std; list1, 2, 3, 4, 5}; // 使用迭代器修改list中的元素 for (list *it += 10; // 解引用迭代器并增加10 } // 打印修改后的list for (list cout 1, 2, 3, 4, 5}; vector *it+=1; cout { cout cout cout cout // 循环体 } string str = "hello"; // 1. 遍历访问字符串中的字符 for (char c : str) { cout // 引用类型,可以直接修改字符串中的字符 c = toupper(c); // 将字符转换为大写形式 } // 3. 遍历访问字符串中的索引和字符 size_t index = 0; for (auto c : str) { cout // 注意字符串为 const,因此迭代器也是 const 的 cout // 使用逆向迭代器构造逆序字符串 cout cout cout string filename("test1.cpp"); //FILE* fout = fopen(filename, "r"); FILE* fout = fopen(filename.c_str(), "r"); char ch = fgetc(fout); while (ch != EOF) { cout cout cout string str; getline(cin, str); size_t pos = str.rfind(' '); if (pos != string::npos) { cout //找不到的时候(只有一串没有空格的字符串) cout
- 本篇文章思维导图


