一、STL简介
STL(standard template libaray-标准模板库):是C++标准库的重要组成部分,不仅是一个可复用的组件库,而且是一个包罗数据结构与算法的软件框架。
模板是C++程序设计语言中的一个重要特征,而标准模板库正是基于此特征。标准模板库使得C++编程语言在有了强大的类库的同时,保有了更大的可扩展性。
STL有6大组件:
其中,容器、算法、迭代器、函数是很重要的部分,有了STL,许多底层的数据结构以及算法都不需要自己重新造轮子,站在前人的肩膀上,肯定飞的更快嘛。
二、string类
C语言中,字符串是以'\0'结尾的一些字符的集合。为了操作方便,C标准库中提供了一些str系列的库函数,但是这些库函数与字符串是分离开的,不太符合面向对象的思想,而且底层空间需要用户自己管理,稍不留神可能还会越界访问。
因此C++的标准库中定义了string类:
(1)string是表示字符串的字符串类
(2)该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。
(3)string在底层实际是:basic_string模板类的别名,typedef basic_string<char, char_traits, allocator> string;
(4)不能操作多字节或者变长字符的序列。
1. string()//构造空字符串 2. string(const char* s);//拷贝s所指向的字符串序列 3. string(const char* s, size_t n);//拷贝s所指向的字符串序列的第n个到结尾的字符 4. string(size_t n, char c);//将字符c复制n次 5. string(const string& str);//拷贝构造函数 6. string(const string& str, size_t pos, size_t len = npos);//拷贝s中从pos位置起的len个字符,若npos>字符串长度,就拷贝到字符串结尾结束
如下所示:
1. #include <iostream> 2. #include <string> 3. using namespace std; 4. 5. int main() 6. { 7. string s0 = "Hello World"; 8. string s1(); //构造空字符串 9. string s2("good start");//拷贝s0所指向的字符串序列(隐式类型转换,先构造再拷贝构造,被编译器优化成直接构造) 10. string s3(s0,1);//拷贝s0所指向的字符串序列的第1个到结尾的字符 11. string s4(5, 'h');//将字符'h'复制5次 12. string s5(s0);//用s0拷贝构造s5 13. string s6(s0,2,30);//拷贝s0中从第2个位置起的30个字符,拷贝到字符串结尾就结束了 14. 15. cout << "s2:" << s2 << endl; 16. cout << "s3:" << s3 << endl; 17. cout << "s4:" << s4 << endl; 18. cout << "s5:" << s5 << endl; 19. cout << "s6:" << s6 << endl; 20. 21. return 0; 22. }
1. char& operator[] (size_t pos);//返回pos位置字符的引用,字符串可读可写,[]重载了operator[] 2. reference at(size_type pos);//同char& operator[],返回pos位置字符的引用,字符串可读可写
1. #include <iostream> 2. #include <string> 3. using namespace std; 4. 5. int main() 6. { 7. string s0 = "Hello World"; 8. 9. for (size_t i = 0; i < s0.size(); i++) 10. { 11. s0[i] = 'x';//使用operator[]访问字符串元素 12. cout << s0[i]; 13. } 14. cout << endl; 15. 16. for (size_t i = 0; i < s0.size(); i++) 17. { 18. s0.at(i) = 'y';//使用at访问字符串元素 19. cout << s0[i]; 20. } 21. cout << endl; 22. 23. return 0; 24. }
[ ]和at的区别在于,[ ]的越界报断言错,而at的越界抛异常。
string、vector支持[ ]遍历,但是list、map等容器不支持[ ]遍历,迭代器是一种可以统一使用的遍历方式。迭代器是类似于指针。
1. iterator begin(); //返回指向字符串第一个字符的迭代器 2. iterator end(); //返回指向字符串最后一个字符的下一个位置的迭代器 3. reverse_iterator rbegin(); //返回字符串最后一个字符的反向迭代器 4. reverse_iterator rend(); //返回指向字符串第一个字符之前的反向迭代器
begin和end是正向迭代器,rbegin和rend是反向迭代器:
1. #include <iostream> 2. #include <string> 3. using namespace std; 4. 5. int main() 6. { 7. //正向迭代器 8. string s0 = "Hello World"; 9. cout << s0 << endl; 10. 11. string::iterator it = s0.begin(); 12. char ch0 = 'a'; 13. 14. while (it != s0.end()) 15. { 16. *it = ch0; 17. ch0++; 18. cout << *it; 19. it++; 20. } 21. cout << endl; 22. 23. //反向迭代器 24. string s1("1234"); 25. cout << s1 << endl; 26. string::reverse_iterator rit = s1.rbegin(); 27. char ch1 = 'a'; 28. 29. while (rit != s1.rend()) 30. { 31. //从右向左依次赋值 32. *rit = ch1; 33. ch1++; 34. cout << *rit; 35. rit++; 36. } 37. cout << endl; 38. cout << s1 << endl; 39. return 0; 40. }
范围for
范围for也可以实现遍历:依次取容器中的数据赋值给e,自动判断结束
1. for(auto& e:s) 2. {}
取s的值赋值给e,e是s的拷贝,因此加引用,如果不加引用,就只能对s读,不能对s写。auto是自动推导,使用方便:
1. for (auto& e : s1) 2. { 3. e += 1; 4. } 5. cout << s1 << endl;
①在字符串末尾插入
void push_back (char c); //向字符串末尾追加一个字符
②在指定位置插入
1. string& insert(size_t pos, const string& str);//插入字符串拷贝 2. string& insert (size_t pos, const char* s);//插入c形式的字符串 3. string& insert (size_t pos, const char* s, size_t n);//将字符串s的前n个字符插到pos位置
1. #include<iostream> 2. #include<string> 3. using namespace std; 4. int main() 5. { 6. string s0(""); 7. s0.push_back('h');//s0尾插h 8. cout << s0 << endl; 9. 10. string s1("ell"); 11. s0.insert(1, s1);//在下标为1的位置插入s1的拷贝 12. cout << s0 << endl; 13. 14. s0.insert(4, "o");//在下标为4的位置插入字符串o 15. cout << s0 << endl; 16. 17. s0.insert(0, "cplusplus",2);//在下标为0的位置插入"cplusplus"的前2个字符 18. cout << s0 << endl; 19. 20. return 0; 21. }
①使用append进行拼接
1. string& append (const string& str); //向字符串对象末尾追加字符串 2. string& append (const char* s);//向字符串末尾追加字符 3. string& append(size_t n, char c);//向字符串末尾追加n个相同字符
1. #include<iostream> 2. #include<string> 3. using namespace std; 4. int main() 5. { 6. string s0(""); 7. s0.append("hello");//将hello追加到s0末尾 8. cout << s0 << endl; 9. string s1 = " world"; 10. s0.append(s1);//s0.append(s1.begin().s1.end());//将字符串s1追加到s0末尾 11. cout << s0 << endl; 12. s0.append(3, '!');//想s0末尾追加3个! 13. cout << s0 << endl; 14. 15. //用+=追加很方便,比append更常用 16. s0 += '!'; 17. s0 += " yes"; 18. string s2 = " it is."; 19. s0 += s2; 20. cout << s0 << endl; 21. }
②使用全局函数operator+拼接
string operator+ (const string& lhs, const string& rhs);//拼接lhs和rhs
1. #include<iostream> 2. #include<string> 3. using namespace std; 4. 5. int main() 6. { 7. string s1 = "cplusplus"; 8. string s2 = ".com"; 9. string s3 = s1 + s2; 10. cout << s3 << endl; 11. 12. return 0; 13. }
string& erase (size_t pos = 0, size_t len = npos);//从第pos个位置开始删除len个字符,pos缺省为0
1. #include<iostream> 2. #include<string> 3. using namespace std; 4. 5. int main() 6. { 7. string s0 = "cplusplus.com"; 8. s0.erase(2, 2); 9. cout << s0 << endl; 10. s0.erase(2, 100);//len超过字符串长度也不会报错,npos为-1,转换成无符号数为4294967295,100远远小于这个数,因此不会报错 11. cout << s0 << endl; 12. 13. unsigned int a = - 1; 14. printf("%u", a); 15. 16. return 0; 17. }