目录
2.1.1.5 用字符串(C类型字符串或string类)的前n个字符构造
一、STL中的string类简介
1. 字符串是表示字符序列的类。
2. 标准的字符串类提供了对此类对象的支持,其接口类似于标准字符容器的接口,但添加了专门用于操作单字节字符字符串的设计特性。
3. string类是使用char作为它的字符类型,使用它的默认char_traits和分配器类型(关于模板的更多信息,请参阅basic_string)。
4. string类是basic_string模板类的一个实例,它使用char来实例化basic_string模板类,并用char_traits和allocator作为basic_string的默认参数(关于更多的模板信息请参考basic_string)。
5. 注意,这个类独立于所使用的编码来处理字节:如果用来处理多字节或变长字符(如UTF-8)的序列,这个类的所有成员(如长度或大小)以及它的迭代器,将仍然按照字节(而不是实际编码的字符)来操作。
总结:
1. string是表示字符串的字符串类,实质上是存储字符类型的顺序表。
2. 该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。
3. string在底层实际是:basic_string模板类的别名,typedef basic_string string;
4. 不能操作多字节或者变长字符的序列。
注:在使用string类时,必须包含#include头文件并使用std命名空间。
二、部分API介绍
2.1 成员函数
2.1.1 构造函数
2.1.1.1 构造空字符串
string()
2.1.1.2 用C-string来构造字符串
string(const char* s)
2.1.1.3 用n个相同字符构造字符串
string(size_t n, char c)
2.1.1.4 拷贝构造
string(const string&s)
2.1.1.5 用字符串(C类型字符串或string类)的前n个字符构造
string (const string& str, size_t pos, size_t len = npos)
string (const char* s, size_t n)
2.1.2 赋值运算符重载
2.1.3 容量操作
2.1.3.1 返回字符串的有效长度
size_t size() const
size_t length() const
size()与length()函数底层实现原理完全相同,引入size()的原因是为了与其他容器的接口保持一致,一般情况下基本都是用size()。
注:string是不以'\0'结尾的!!!
2.1.3.2 返回字符串的总容量
size_t capacity() const
因为string实质上是存储类型为char的顺序表,所以理所当然的就有容量这一属性,capacity()能够得到字符串的容量。
2.1.3.3 检查字符串是否为空串
bool empty() const
如果是空串就返回true,不是就返回false。
2.1.3.4 清空字符串
void clear()
clear()只是将string中有效字符清空,不改变底层空间(容量)大小。
2.1.3.5 为字符串扩容
void reserve (size_t n = 0)
【文档描述】
2.1.3.6 将有效字符的个数(字符串的长度)改成n个
【文档描述】
resize(size_t n) 与 resize(size_t n, char c)都是将字符串中有效字符个数改变到n个,不同的是当字符个数增多时:resize(n)用'\0'来填充多出的元素空间,resize(size_t n, char c)用字符c来填充多出的 元素空间。
注意:resize在改变元素个数时,如果是将元素个数增多,可能会改变底层容量的大小,如果是将元素个数减少,底层空间(容量)总大小不变。
int main()
{
//改变字符串的长度
string str1 = "我怎么天天被改?";
string str2(str1);
string str3 = str2;
//缩小字符串的长度
cout << "修改前:" << endl;
cout << "str1的内容为 " << str1 << endl;
cout << "str1的长度为" << str1.size() << endl;
cout << "str1的容量为" << str1.capacity() << endl;
cout << endl;
str1.resize(6);
cout << "修改后:" << endl;
cout << "str1的内容为 " << str1 << endl;
cout << "str1的长度为" << str1.size() << endl;
cout << "str1的容量为" << str1.capacity() << endl;
cout << endl;
//扩大字符串的长度
cout << "修改前:" << endl;
cout << "str2的内容为 " << "#" << str2 << "#" << endl;
cout << "str2的长度为" << str2.size() << endl;
cout << "str2的容量为" << str2.capacity() << endl;
cout << endl;
//不指定字符c
str2.resize(32);
cout << "修改后:" << endl;
cout << "str2的内容为 " << "#" << str2 << "#" << endl;
cout << "str2的长度为" << str2.size() << endl;
cout << "str2的容量为" << str2.capacity() << endl;
cout << endl;
cout << "修改前:" << endl;
cout << "str3的内容为 " << "#" << str3 << "#" << endl;
cout << "str3的长度为" << str3.size() << endl;
cout << "str3的容量为" << str3.capacity() << endl;
cout << endl;
//指定字符c
str3.resize(32, 'x');
cout << "修改后:" << endl;
cout << "str3的内容为 " << "#" << str3 << "#" << endl;
cout << "str3的长度为" << str3.size() << endl;
cout << "str3的容量为" << str3.capacity() << endl;
cout << endl;
return 0;
}
2.1.3.7 获取字符串的最大长度
size_t max_size() const
2.1.4 元素访问
2.1.4.1 []操作符重载
【文档描述】
因为string由顺序表实现,所以[]操作符重载可以让我们访问顺序表(数组)一样访问string,并且因为返回值是引用,因此我们还可以对进进行修改。
注:字符串的第一个位置被标识为0而不是1。
2.1.5 修改操作
2.1.5.1 对字符串尾插一个字符
void push_back (char c)
2.1.5.2 对字符串尾插一个字符串
2.1.5.3 +=运算符重载
+=操作符既可以尾插一个字符串(string或C类型),也可以尾插一个字符。
2.1.5.4 在string任意位置插入字符或字符串
注:当pos == 0时,此时为头插,效率最低。
2.1.5.5 在字符串任意位置删除字符或字符串
注:当pos == 0时,此时为头删,效率最低。
2.1.5.6 交换两个字符串
void swap (string& str)
2.1.5.7 对字符串尾删一个字符
void pop_back()
2.1.6 字符串操作
2.1.6.1 将string转化为C类型字符串
const char* c_str() const;
因为printf只能打印内置类型(int、double等),所以如果想用printf打印string类型对象,就需要先将其转化为C类型字符串。
注:string在转化为C类型字符串时,会往C类型字符串后面补上'\0'。
2.1.6.2 在string正向查找字符或字符串
2.1.6.3 在string中反向查找字符或字符串
2.1.6.4 在字符串中截取子串
string substr (size_t pos = 0, size_t len = npos) const
2.1.6.5 将string拷贝到C类型数组
size_t copy (char* s, size_t len, size_t pos = 0) const
【文档描述】
注:拷贝形成的字符串并不会携带'\0',如果要使用记得自行补充'\0'!!!
2.1.7 迭代器
2.1.7.1 正向迭代器
【文档描述】
2.1.7.2 反向迭代器
【文档描述】
2.1.7.3 注意事项
注:如果字符串被const修饰,那么迭代器也必须带上const,否则会报错。
2.1.7.4 迭代器的意义
迭代器的意义是提供了一种统一访问或修改容器元素的方式。对于string(字符串)、vector(顺序表)等用数组来实现的容器来说,用下标访问确实是一个好方式,但是对于list(链表)、map(树)这些还能用下标访问吗?那明显是不能的,所以迭代器对于容器来说是非常重要的。
这里以list做演示:
除此之外,迭代器还能与一些算法搭配使用,这里以reverse做演示:
【文档描述】
2.2 成员常量
static const size_t npos = -1
npos是string类中的一个静态成员常量,在使用npos时需要用作用域运算符(::)。
虽然npos的表面上的值是-1,但因为npos的类型为size_t(无符号整形),所以npos最后的值会是一个非常大的正整数。
在Windows64位平台,size_t的定义如下:
2.3 非成员函数重载
2.3.1 加运算符重载
加运算符也是起到对字符串尾插的作用,但是因为其的返回值并不是引用,所以效率较低,因此在能用+=的情况不建议用+运算符。
2.3.2 关系运算符重载
关系运算符提供了比较两个字符串大小的方法,比较的规则与strcmp相同。
2.3.3 流提取(<<)和流插入(>>)操作符重载
操作符<<和>>的重载支持我们可以通过cout和cin直接输出、输入字符串。
注:cin的读取读取到空格或者换行就结束了!
2.3.4 从输入设备中读取一行字符串
getline解决了cin不能读取一行的问题。
2.4 字符串转其他类型
2.5 其他类型转字符串
三、string的三种遍历方式
3.1 下标访问(可修改内容)
3.2 迭代器访问(可修改内容)
3.3 范围for循环
范围for(range-based for loop)是C++11新引入的特性,可遍历各种序列结构的容器(如数组、vector、list等),每次循环都会将序列中的一个元素赋值给声明的变量,直到循环结束。
//element_declaration 声明循环变量的类型和名字
//sequence 是一个序列结构,例如数组、顺序表、链表等,或具有迭代器接口的对象
for ( element_declaration : sequence ) {
// 循环体
}
范围for的原理是通过序列的迭代器来遍历其中的元素,编译器会自动处理迭代器的初始化、增量及结束等细节,无需手动操作。