string-utf8
string是用来管理字符串数组的容器类,但是不能操作多字节或者变长字符的序列。它的编码是utf8。
主要涉及字符串编码的问题。在c语言阶段接触的是ASCII码,美国信息交换代码,目前位置定义了128个字符。
现在介绍一下 统一码Unicode,满足跨语言、跨平台进行文本处理和转换的需求。UTF-8(兼容ASCII码,使用最广泛),UTF-16,UTF-32。
//STL库string类的由来
//这是动态增长的字符数组,要动态扩容
template<class T>
class basic_string
{
private:
T* _str;
size_t _size;
size_t _capacity;
};
typedef basic_string<char> string;
//其他编码的字符同理
typedef basic_string<char16_t> u16string;
typedef basic_string<char32_t> u32string;
typedef basic_string<wchar_t> wstring;
----------------
basic_string<char> s1;//等价于下面这个写法
string s1;
typedef不能对basic_string操作,普通类的类名就是类型,而类模板的类名不是类型,所以不能直接用typedef
构造函数
默认成员函数 | 语法 |
---|---|
default (1) | string(); |
copy (2) | string (const string& str); |
substring (3) | string (const string& str, size_t pos, size_t len = npos); |
from c-string (4) | string (const char* s); |
from sequence (5) | string (const char* s, size_t n); |
fill (6) | string (size_t n, char c); |
range (7) | template string (InputIterator first, InputIterator last); |
operator= | 语法 |
string (1) | string& operator= (const string& str); |
c-string (2) | string& operator= (const char* s); |
character (3) | string& operator= (char c); |
string s1;//1默认构造
string s2("浙江宁波");//4字符串构造
string s3(s2);//2拷贝构造
string s4(s3, 4, 4);//3
string s5("浙江宁波", 4);//5
string s6(10, '*');//6
string s7 = "今天是12月21日";//无explicit修饰
根据=操作符的声明可知没有用explicit,说明可以隐式类型转换,故容许(2)的写法,即
string s1 = "浙江";//从const char*转换成string,这个过程涉及临时变量拷贝构造得到string,通过编译器优化等等
功能函数
3种遍历字符串的方法
string s1 = "12345";
//遍历该字符串
// 1 [下标] 仅适用于底层结构是顺序表的数据结构
for (size_t i = 0; i < s1.size(); i++)
{
s1[i]++;
}
cout << s1 << endl;
// 2 范围for
for (auto& ch : s1)
{
ch--;
}
cout << s1 << endl;
// 3 迭代器 ---- 讲解重点
string::iterator it1 = s1.begin();
while (it1 != s1.end())
{
(*it1)++;
cout << (*it1) << " ";
it1++;
}
cout << endl;
// 翻转这个字符串
size_t begin = 0;
size_t end = s1.size() - 1;
while (begin < end)
{
swap(s1[begin], s1[end]);
begin++;
end--;
}
cout << s1 << endl;
迭代器可以看作是一个指针,begin()和end()函数分别返回首字符指针和最后一个字符下一个位置的指针。用迭代器去遍历是容器类的通用访问方式,要掌握!!
迭代器
正向迭代器
iterator
,对应begin和end。
反向迭代器
reverse_iterator
对应rbegin和rend。
const迭代器
const_iterator
对应begin和end。保护容器里的内容不能修改,只读。
string::const_iterator it = s.begin();//正确写法,it可以++,(*it)不可以++
const string::iterator it = s.begin();//错误写法,这个写法保护的是it,而不是容器的内容,无法进行it++的遍历操作
正向/反向+const
只读
at
越界访问会抛异常,throw an out-of-range
operator[]
越界操作直接assert报错
size
返回字符串有效字符长度
capacity
返回空间总大小。VS下容量按1.5倍增长扩容的,capacity返回值不包括\0的长度;而linux下的容量是按2倍增长的,capacity返回值包括\0长度
empty
检测字符串释放为空串,是返回true,否则返回false
clear
清空有效字符
reverse
为字符串预留空间capacity,一次性开辟给定字节数的空间,若已知要用的空间大小就可以一次开辟,避免扩容更高效。VS下不一定刚好达到要求,可能会比要求的大;linux是一定符合要求空间的。如果空间不够用,还是可以扩容的。
不一定会到要求的capacity。
resize
会改变原字符的size到指定长度n,大于原size的部分用指定字符来填充。分为以下三种情况:如果capacity < n
,就会扩容,插入数据,会改变size;如果size < n < capapcity
,插入数据,不改变capacity,会改变size;n < size
,删除数据,不改变capacity,会改变size。
一定会到要求的size。
maxsize
此函数返回字符串可以达到的最大长度。正常来说32位系统下,最大长度位2^32=4294967296
,但是实际值有以下两种情况:
1、VS2013实际得到的是4294967294(32位)。原因:①-1被占用为不存在的位置string::npos,因此不能用于长度(2^32-1
);②字符串最后一字节保留给\0
,因此只能再少一字节(2^32-2
)。对应的是11111111 11111111 11111111 11111111 = 4294967295
,所以是42亿9千万的值。
2、VS2019实际得到的是2147483647(32位),是32 位无符号整数-1对应的值 10000000 00000000 00000000 00000000 = 2147483648
。
push_back
尾插一个字符
append
尾插字符串。有很多重载,和构造函数风格很像。
总结
1、只读功能函数 只有const版本;
2、只写功能函数 只有非const版本;
3、读写功能函数 const+非const版本。