0%

string类的基本使用及常用接口

string类基本使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#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)
  • 迭代器是一个可读可写的接口

正向迭代器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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;
}

反向迭代器

1
2
3
4
5
6
7
8
9
10
11
12
void test()
{
string str("123456789");
string::reverse_iterator rit = str.rbegin();
while(rit != str.rend())
{
cout << *rit << " ";
//反向迭代器向前移动
++rit;
}
cout << endl;
}

正向const迭代器

1
2
3
4
5
6
7
8
9
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等接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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();
}
  1. n > size && n > capacity :增容(开新空间 + 拷贝 + 释放原有空间) + 新的位置赋值(如果没有给默认字符,默认是 ‘\0’ )
  2. n < size:只修改size
  3. 当 n > size && n < capacity:新的位置赋值(如果没有给赋值字符,默认赋值 ‘\0’ + 修改size )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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提前开好空间,后续节省增容开销,提高代码效率
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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也可读可写,如果需要修改,则接收类型为引用类型,底层通过迭代器实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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 追加
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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+= +=操作符重载(==常用==)
1
2
3
4
string s4;
s4 += '1'; //1
s4 += '234'; // 1234
s4 += s;// 1234abbcde
  • inster 插入,除尾插之外插入效率较低O(n)
1
2
3
4
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 赋值
1
2
s4.assign("11111");// 11111 效果和下面相同
s4 = "11111";
  • erase 删除
1
2
3
4
s4.erase(0, 2);// 111
s4.erase(s4.begin());//11
s4.erase(s4.end());// 11 此时end迭代器位置非法,不做操作
s4.erase(s4.begin, s4.end());// "" 删完了
  • replace 替换
1
2
3
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 交换
1
2
3
4
5
6
7
8
9
10
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_strdata,返回C风格的字符串,即字符串首元素地址,返回值类型是const char*
1
2
const char* ptr2 = s.c_str();
const char* ptr2 = s.data();
  • find正向查找,rfind反向查找,找到第一个匹配的位置 就结束,返回值类型为size_t
    • 找不到返回npos:static const size_t npos = -1, 可以通过与npos判断来确定是否找到
1
2
3
string s = "aaaaaaaaaa";
size_t pos = str.find('a');
size_t pos2 = str.rfind('a');
  • substr 截取字符串
  • substr(pos, len) 如果len大于从pos到结束位置的字符串长度,则把剩余字符串全部截取出来
1
2
string str = "0123456789";
string str2 = str.substr(0, 5);//01234 从索引为0开始截取五个字符
  • operator+, 非成员函数,拼接字符串,返回一个string对象

  • operator>operator=等关系运算符重载函数

    • 按照ASCII码值比较大小,与长度无关
    • 从第一个字符开始,逐字符比较,直到遇到不相等的字符出现,或者同时结束,按照不相等的码值确定大小
1
2
3
4
5
6
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常用接口

  1. 遍历:begin,endoperator[]
  2. 容量相关:sizeresizereserve
  3. 修改:+=pop_backswap
  4. 其他操作:c_strfindrfindsubstr
  5. 非成员函数:比较,>><<getline
-------------本文结束感谢您的阅读-------------