1. 为什么学习string类?
C语言中的字符串
C语言中,字符串是以'\0'结尾的一些字符的集合,为了操作方便,C标准库中提供了一些str系列 的库函数,但是这些库函数与字符串是分离开的,不太符合OOP的思想,而且底层空间需要用户 自己管理,稍不留神可能还会越界访问。
c++string类
提供了对类对象的支持,且设计了对于单个字节的字符串中的字符进行操作。
注意⚠️:在使用string类时,必须包含#include头文件以及using namespace std;
2 string类的常用接口说明
1. string类对象的常见构造
| 默认 (1) | string(); 构造空的string类对象,即空字符串
|
| 拷贝 (2) | string (const string& str); 拷贝构造函数
|
| 子字符串 (3) | string (const string& str, size_t pos, size_t len = npos); 从字符位置pos开始并跨越len字符的str部分
|
| 从 c-string (4) | string (const char* s); 用C-string来构造string类对象
|
| (5) | string (const char* s, size_t n); 从s指向的字符数组中复制前n个字符。
|
| (6) | string (size_t n, char c); string类对象中包含n个字符c ,c可以的字符,也可以是ask码值。
|
范围 (7) | template <class InputIterator> string (InputIterator first, InputIterator last); 范围构造函数以相同的顺序复制范围中的字符序列\[第一个,最后一个\] |
---|
#include <iostream> #include <string> int main() { std::string s0("Initial string"); // 构造函数的使用顺序与上述相同: std::string s1; std::string s2(s0); std::string s3(s0, 8, 3); std::string s4("A character sequence"); std::string s5("Another character sequence", 12); std::string s6a(10, 'x'); std::string s6b(10, 66); // 66 is the ASCII code for 'B' std::string s7(s0.begin(), s0.begin() + 7); std::cout << "s1: " << s1 << "\ns2: " << s2 << "\ns3: " << s3; std::cout << "\ns4: " << s4 << "\ns5: " << s5 << "\ns6a: " << s6a; std::cout << "\ns6b: " << s6b << "\ns7: " << s7 << '\n'; return 0; }
2. string类对象的容量操作
2.size 重要
返回字符串的长度,单位为字节。
这是符合字符串内容的实际字节数,它不一定等于它的存储容量。
#include <iostream> #include <string> int main() { std::string str("Test string"); std::cout << "str 的大小是" << str.size() << " 字节\n"; return 0; }
3.length重要
返回字符串的长度,单位为字节。
这是符合字符串内容的实际字节数,它不一定等于它的存储容量。
#include <iostream> #include <string> int main() { std::string str("Test string"); std::cout << "str 的大小是" << str.length() << " 字节\n"; return 0; }
注意⚠️:size()与length()方法底层实现原理完全相同,引入size()的原因是为了与其他容器的接 口保持一致,一般情况下基本都是用size()。
3.capacity
返回当前为该字符串分配的存储空间大小,以字节表示。
这个容量不一定等于字符串长度。它可以等于或大于,额外的空格允许对象在向字符串中添加新字符时优化itsl操作。
扩展
请注意,这个容量没有限制字符串的长度。当该容量耗尽,需要更多时,自动按对象进行扩容(重新分配存储空间)。字符串长度的理论极限由成员max_size给出。
#include <iostream> #include <string> int main () { std::string str ("Test string"); std::cout << "size: " << str.size() << "\n"; std::cout << "length: " << str.length() << "\n"; std::cout << "capacity: " << str.capacity() << "\n"; std::cout << "max_size: " << str.max_size() << "\n"; return 0; }
4.resize (调整)重要
将有效字符的个数该成n个,多出的空间用字符c填充
#include <iostream> #include <string> int main() { std::string str("I like to code in C"); std::cout << str << '\n'; unsigned sz = str.size(); str.resize(sz + 2, '+'); std::cout << str << '\n'; str.resize(14); std::cout << str << '\n'; return 0; }
3. string类对象的访问及遍历操作
3.1 operator[](重 点)
这样写const 我之前博客中有
返回pos位置的字符,const string类对象调用
#include <iostream> #include <string> int main() { std::string str("Test string"); for (int i = 0; i < str.length(); ++i) { std::cout << str[i]; } return 0; }
3.2 begin + end
begin获取一个字符的迭代器 + end获取最后一个字符下一个位 置的迭代器
3.3rbegin + rend
begin获取一个字符的迭代器 + end获取最后一个字符下一个位 置的迭代器
4. string类对象的修改操作
4.1push_back
在字符串后尾插字符c
#include <iostream> #include <string> int main() { std::string str("Test string"); str.push_back(6); std::cout << str; return 0; }
4.2 append
在字符串后追加一个字符串
#include <iostream> #include <string> int main() { std::string str; std::string str2 = "Writing "; std::string str3 = "print 10 and then 5 more"; // used in the same order as described above: str.append(str2); // "Writing " str.append(str3, 6, 3); // "10 " str.append("dots are cool", 5); // "dots " str.append("here: "); // "here: " str.append(10u, '.'); // ".........." str.append(str3.begin() + 8, str3.end()); // " and then 5 more" std::cout << str << '\n'; return 0; }
4.3 operator+= (重 点)
在字符串后追加字符串str
// string::operator+= #include <iostream> #include <string> int main () { std::string name ("John"); std::string family ("Smith"); name += " K. "; // c-string name += family; // string name += '\n'; // character std::cout << name; return 0; }
4.4 c_str (重 点)
返回C格式字符串
#include <iostream> #include <cstring> #include <string> int main() { std::string str("Please split this sentence into tokens"); char* cstr = new char[str.length() + 1]; std::strcpy(cstr, str.c_str()); // cstr now contains a c-string copy of str char* p = std::strtok(cstr, " "); while (p != 0) { std::cout << p << '\n'; p = std::strtok(NULL, " "); } delete[] cstr; return 0; }
4.5 find+npos(重 点)
从字符串pos位置开始往后找字符c,返回该字符在字符串中的 位置
5. string类非成员函数(操作符)
5.1 operator+
尽量少用,因为传值返回,导致深拷贝效率低
#include <iostream> #include <string> int main() { std::string firstlevel("com"); std::string secondlevel("cplusplus"); std::string scheme("http://"); std::string hostname; std::string url; hostname = "www." + secondlevel + '.' + firstlevel; url = scheme + hostname; std::cout << url << '\n'; return 0; }
5.2 operator>> (重点)
输入运算符重载
//提取操作符 #include <iostream> #include <string> main() { std::string name; std::cout << "Please, enter your name: "; std::cin >> name; std::cout << "Hello, " << name << "!\n"; return 0; }
5.3 perator <<(重点)
输出运算符重载
#include <iostream> #include <string> int main() { std::string str = "Hello world!"; std::cout << str << '\n'; return 0; }
5.4 getline (重点)
获取一行字符串
#include <iostream> #include <string> int main() { std::string name; std::cout << "Please, enter your full name: "; std::getline(std::cin, name); std::cout << "Hello, " << name << "!\n"; return 0; }
5.5 relational operators (重点)
大小比较
#include <iostream> #include <vector> int main () { std::string foo = "alpha"; std::string bar = "beta"; if (foo==bar) std::cout << "foo 和 bar are 相等\n"; if (foo!=bar) std::cout << "foo 和 bar are 不相等\n"; if (foo< bar) std::cout << "foo 小于 less \n"; if (foo> bar) std::cout << "foo 大于 greater \n"; if (foo<=bar) std::cout << "foo 小于等于 less \n"; if (foo>=bar) std::cout << "foo 大于等于 greater\n"; return 0; }