string类的基本使用以及常用接口
string类基本使用
#include <string>
void test()
{
string str;//""
string str2("123");//"123"
string str3 = "abc";//"abc"
string str4("0123456789", 5);//"01234"
string cpy(str3);//"abc"
string str5(str4, 2, 2);//"23" 从str4的第2个位置拿两个字符创建一个字符串
string str6(10, a);//"aaaaaaaaaa"
str6 = str5;//操作符重载
str6 = "321";
str6 = "xyz";
}
迭代器
访问容器的一种通用方式, 所有支持迭代器的容器,其迭代器的使用方式完全相同
迭代器的使用方式:类似于指针的使用方式,可以通过解引用获取元素内容,可以通过++, --
进行位置移动
- begin迭代器:第一个元素的位置
- end迭代器:最后一个元素的下一个位置
- 迭代器的范围,左闭右开
[begin, end)
- 迭代器是一个可读可写的接口
正向迭代器
void test()
{
string str("0123456789");
//迭代器的遍历方式
string::iterator it = str.begin();
while(it != str.end())
{
//迭代器的解引用
cout << *it << " ";
//迭代器可读可写
*it = 'a';
//迭代器向后移动
++it;
}
cout << endl;
//#include<vector>
vector<int> vec = {1, 2, 3, 4, 5, 6, 7, 8, 9};
vector<int>::iterator vit = vec.begin();
while(vit != vec.end())
{
cout << *vit << " ";
++vit;
}
cout << endl;
}
反向迭代器
void test()
{
string str("123456789");
string::reverse_iterator rit = str.rbegin();
while(rit != str.rend())
{
cout << *rit << " ";
//反向迭代器向前移动
++rit;
}
cout << endl;
}
正向const迭代器
string::const_iterator cit = str.begin();
string::const_iterator cit2 = str.cbegin();
//const迭代器建议使用const接口获取:c...
while(cit != str.cend())
{//const迭代器不支持写操作,其为只读迭代器
cout << *cit << " ";
++cit;
}
- const创建的对象只能使用const接口
小结:
- 可读可写的迭代器
iterator, reverse_iterator
- 只读迭代器
const_iterator, const_reverse_iterator
begin();
iterator begin()
—> 非const对象调用const_iterator begin() const
—> const对象调用
end();
iterator end()
—> 非const对象调用const_iterator end() const
—> const对象调用
rbegin, rend
同上,也有两个接口cbegin, cend, crbegin, crend
—> 都返回const迭代器
capacity等接口
void test()
{
string str("0123456789");
//size:返回有效字符的个数(常用)
int ret = str.size();
//length:返回有效字符的个数
ret = str.length();
//capacity:可以存放的最大有效字符个数
ret = str.capacity();
size_t maxSize = str.max_size();
str.clear();
}
void test()
{
string str("0123456789");
int size = str.size();
int cap = str.capacity();
str.resize(20);//9之后用'\0'填充
size = str.size();
cap = str.capacity();
str.resize(10);
size = str.size();
cap = str.capacity();
str.resize(30, 'a');//9之后用'a'填充
size = str.size();
cap = str.capacity();
}
- n > size && n > capacity :增容(开新空间 + 拷贝 + 释放原有空间) + 新的位置赋值(如果没有给默认字符,默认是 ‘\0’ )
- n < size:只修改size
- 当 n > size && n < capacity:新的位置赋值(如果没有给赋值字符,默认赋值 ‘\0’ + 修改size )
void test()
{
string str("0123456789");
int size = str.size();
int cap = str.capacity();
str.reserve(20);
size = str.size();
cap = str.capacity();
str.reserve(5);
size = str.size();
cap = str.capacity();
}
-
reserve:调整容量大小:增加容量(原有基础上增加),不修改size,也可减少容量,按需减小,如果要减小的容量小于size,不做任何操作,如果要减小的容量大于size,则进行减小操作。
-
PJ版string增容过程:如果为空字符串对象,初识容量大小为15,第一次增容为2倍,后续按照1.5倍增容。
-
可使用reserve提前开好空间,后续节省增容开销,提高代码效率
void test()
{
string s;
s.reserve(100);
int size = str.size();
int cap = str.capacity();
s.reserve(20);
size = str.size();
cap = str.capacity();
s.shrink_to_fit();
size = str.size();
cap = str.capacity();
}
shrink_to_fit()
缩小容量到合适范围
遍历操作
operator[]
可读可写接口,如str[i]
,如果越界,非法访问
at
可读可写接口,如str.at(i)
,但是代码可读性不强,如果越界,抛异常
范围for也可读可写,如果需要修改,则接收类型为引用类型,底层通过迭代器实现
for(int i = 0; i < str.size(); i++)
{
cout << str[i] << " ";
}
for(int i = 0; i < str.size(); i++)
{
cout << str.at(i) << " ";
}
for(auto& ch : str)
{
cout << ch << " ";
}
back
返回最后一个字符
front
返回第一个字符
string类对象的修改操作
push_back
尾插append
追加
string s;
s.push_back('a');// a
s.append(2, 'b');// abb 追加两个b
s.append("cde");// abbcde 追加cde
string s2;
s2.append(s);// abbcde 追加addcde
string s3;
s3.append(s, 3, 2);// cd 从s的第三个位置追加两个字符
char strArr[] = "1234";
s3.append(strArr, strArr + 2);// cd34 //从strArr第二个位置之后追加到s3
s3.append(s2.begin(), s2.end());// cd34abbcde 通过迭代器追加
operator+=
+=操作符重载(常用)
string s4;
s4 += '1'; //1
s4 += '234'; // 1234
s4 += s;// 1234abbcde
inster
插入,除尾插之外插入效率较低O(n)
s4.inster(0, s3);//cd1234abbcde
s4.inster(0, s3, 7, 3);
s4.inster(s4.end(), 3, '1');
s4.inster(s4.end(), strArr + 1, strArr + 3);
assign
赋值
s4.assign("11111");// 11111 效果和下面相同
s4 = "11111";
erase
删除
s4.erase(0, 2);// 111
s4.erase(s4.begin());//11
s4.erase(s4.end());// 11 此时end迭代器位置非法,不做操作
s4.erase(s4.begin, s4.end());// "" 删完了
replace
替换
string s = "0123456789";
s.replace = (3, 5, "aa");// 12aa89 从第三个元素开始替换五个字符
s.replace = (s.begin() + 1, s.end() - 1, "0");// 009 迭代器左闭右开,begin + 1第二个字符开始,end - 1指的是9
swap
交换
string s2 = "abc";
s2.swap(s, s2);//s2: 009, s: abc
//调用string成员函数交换
swap(s, s2);//s2: abc, s: 009
//全局swap函数:内部调用string的成员函数swap完成交换
int a = 1;
int b = 2;
swap(a, b);
//全局任何类型的swap函数
c_str
、data
,返回C风格的字符串,即字符串首元素地址,返回值类型是const char*
const char* ptr2 = s.c_str();
const char* ptr2 = s.data();
find
正向查找,rfind
反向查找,找到第一个匹配的位置 就结束,返回值类型为size_t
- 找不到返回npos:
static const size_t npos = -1
, 可以通过与npos判断来确定是否找到
string s = "aaaaaaaaaa";
size_t pos = str.find('a');
size_t pos2 = str.rfind('a');
substr
截取字符串substr(pos, len)
如果len大于从pos到结束位置的字符串长度,则把剩余字符串全部截取出来
string str = "0123456789";
string str2 = str.substr(0, 5);//01234 从索引为0开始截取五个字符
-
operator+
, 非成员函数,拼接字符串,返回一个string对象 -
operator>
、operator=
等关系运算符重载函数- 按照ASCII码值比较大小,与长度无关
- 从第一个字符开始,逐字符比较,直到遇到不相等的字符出现,或者同时结束,按照不相等的码值确定大小
string s = "9";
string s2 = "123";
string s3 = "1234";
bool ret = s > s2; //true
ret = s2 > s3; //false
ret = s > s3; //true
- string支持
>>
和<<
cin
:遇到空格,结束内容读取,如果读取的内容有空格,可以使用getline
接口,getline(cin, s)
遇到换行结束。还可以指定结束的标记字符,标记字符不会存放在string对象当中getline(cin, s, '。')
string常用接口
- 遍历:
begin
,end
,operator[]
- 容量相关:
size
,resize
,reserve
- 修改:
+=
,pop_back
,swap
- 其他操作:
c_str
,find
,rfind
,substr
- 非成员函数:比较,
>>
,<<
,getline