【C++】容器string的常用成员函数接口

目录


string – C++ Reference

1 容量相关

1.1 size/length

size和length表示string里存储的有效数据的大小/长度。 

可以用来for循环遍历string:

string str("hello string");
for(int i = 0;i < str.size();++i)
{
    cout<<str[i];//[]重载
}
string str("hello string");
for(int i = 0;i < str.length();++i)
{
    cout<<str[i];//[]重载
}

注:

length用来表示线性数据结构的有效数据长度大小,size既可以用来表示线性数据结构的有效数据大小、也可以用来表示非线性结构的有效数据大小,可以说size是通用的

1.2 capacity

capacity表示已经分配的空间的大小,通常capacity>=size/length

1.3 resize

顾名思义,改变string对象的size,有两个函数重载

体现为两个方面:

①如果传入的n<原先的长度,仅仅会删除数据,不作数据修改,因此有效重载函数形式为

void resize(size_t n)

 vs编译器:

g++:

②如果传入的n>原先的长度,不仅会改变容量,而且可以指定增加的数据,因此有效函数重载形式为:

void resize (size_t n)
void resize (size_t n, char c)

 vs编译器:

指定增加的字符为’x’:

不指定增加的字符,可能放入的都是\0: 

 g++:

 不指定增加的字符,可能放入的都是\0:

1.4 reserve

顾名思义,reserve会改变capacity,而不会改变数据。

当传入的n小于当前的capacity,capacity会被缩小,叫做缩容;当传入的n大于当前的capacity,capacity会被扩大,叫做扩容

不同的编译器对于缩容和扩容的处理不同。

vs编译器:

①扩容机制

string s;
size_t old = s.capacity();
cout << old << endl;
//扩容机制
for (size_t i = 0; i < 100; ++i)
{
	s += 'x';
	if (old != s.capacity())
	{
		old = s.capacity();
		cout << old << endl;
	}
}

②无数据时,缩容到最小容量15;有数据时,不会缩容

g++:

①扩容机制

缩容顶多缩容至size的大小

1.5 empty

 函数返回类型为真或者假

2 运算符重载

2.1 operator=


我们原本以为的赋值运算符重载:

第二行还有报错,报错信息是:

实际上这并不是赋值运算符重载,实际的运算符重载应该是这样的:

vs下=号的颜色都变了,说明两次=的作用是不一样的。为什么呢?

这下我们明白了,之所以第二次是赋值运算符重载,是因为s1、s2、s3都已经初始化好了,而且都是调用的默认构造函数string() 。

赋值运算符的运算顺序是自右向左的,s1先赋值给s2,s2再赋值给s3。 

2.2 operator[]

operator[]为我们提供了通过下标直接访问字符串内容的便利,有两种函数重载,一种给普通对象,另一种给const对象。

2.3 operator+(非成员函数)

Concatenate strings:连接字符或字符串 

用法:

为什么这个重载是非成员函数呢?

        我们都知道成员函数的第一个参数是隐藏的this指针,指向实例化出来的对象, 因此如果把+重载写在类里面也就是成员函数,第一个参数就必然是实例化出来的对象,而相加的两个对象不必一定要有this,可以是其他的两个对象,所以STL库就把它设计成非成员函数。

2.4 operator+=

官网里的例子:

operator+=可以很方便地进行字符串尾插的操作,是尾插最常用且实用的操作,尾插前先检查容量,容量不够先扩容再尾插。下面还有push_back、append、insert等的接口函数,也是用来进行字符串增加的,但是没有+=运算符重载用的那么方便。

2.5 operator>> && operator<<(非成员函数)

为了方便输入和直接输出string里的内容,设计出了流插入和流提取的重载。

这两个必须设计成非成员函数否则就会导致cout和str的顺序颠倒:str<<cout

因为左右操作数和函数的传参类型要一致,成员函数的第一个参数永远是this指针!

3 增删查改的接口

3.1 push_back

尾插会先检查容量,容量不够先扩容,然后在进行尾插操作。尾插结束后再补一个\0,模拟一下:

void push_back(char c)
{
	if (_capacity == _size)
	{
		reserve(_capacity == 0 ? 4 : _capacity * 2);
	}
	_str[_size] = c;
	_size++;
	_str[_size] = '\0';
}

3.2 append

append提供了六种函数重载,可以看作push_back的plus版本。

string s = "hello";
string _s = " string";
s.append(_s);//hello string
s.append(_s,0,3);//hello st
s.append(" string");//hello string
s.append(" string", 2);//hello s
s.append(5,'x');//helloxxxxx
s.append(_s.begin(),_s.begin()+2);//hello s

讲解一下第二种和第四种:

substring(2):

string& append (const string& str, size_t subpos, size_t sublen)
string s = "hello";
string _s = " string";
s.append(_s,0,3);//hello st

功能:将副串_s的一部分尾插至主串s之后。

注:

subpos必须小于等于sublen,否则就会: 

如果sublen大于strlen(_s),编译器会多开空间吗? 

vs编译器:

g++:

答案是不会!

buffer(4):

string& append (const char* s, size_t n)
string s = "hello";
s.append(" string", 3);
cout<<s;//hello st

功能:将常量字符串的一部分尾插至s。

注:

如果传入的参数n大于strlen(s),编译器会多开空间吗?

vs编译器:

g++:

答案是会的! 

3.3 insert 

由于顺序表头插的时间复杂度为O(n),效率较低,所以STL库并没有实现string的头插接口,而是设计了一个insert,可以用来在pos位置插入字符或字符串,特殊的当pos为0时,就相当于头插。

其中前四种的设计和上面append的设计类似,后三种多了迭代器的传参:

void insert(iterator p,size_t n,char c);
iterator insert (iterator p, char c);
template <class InputIterator>
   void insert (iterator p, InputIterator first, InputIterator last);

第一种的用法:

第二种用法:

第三种用法:

3.4 erase

顾名思义,删除字符串中的字符。

用法:

第一种:


缺省参数pos=0,len=(size_t)(-1)=2^32-1

第二种:

传入迭代器,删除迭代器指向的单个字符,并返回迭代器。

顺序是先删除h再把删除后的s.begin()赋值给it。

第三种:

范围删除并返回迭代器,范围是[first,last),左闭右开!

3.5 assign

assign的用法其实就是新串代替旧串,举一个例子就行:

3.6 find

find还是挺好用的,至少不用自己写字符串查找算法,找到了就返回找到的最开始的位置,找不到就返回(size_t)(-1)。

4 其他接口

4.1 substr

功能:返回string的子串,从pos位置返回长度为len的子串。

4.2 c_str() 

功能:将string以const char*的形式返回。

string的私有成员:

char* _str;
size_t _size;
size_t _capacity;

 模拟实现c_str的话:

const char* c_str()
{
    return _str;
}

4.3 rfind

功能:从string的尾巴往前找指定的字符或字符串。

字符串最后一个单词的长度_牛客题霸_牛客网

用rfind解题:

#include <iostream>
using namespace std;

int main() 
{
    string s;
    getline(cin,s);
    size_t pos = s.rfind(" ");
    cout<<s.size()-pos-1;
    return 0;   
}

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
乘风的头像乘风管理团队
上一篇 2023年12月20日
下一篇 2023年12月20日

相关推荐