C++:string 相关接口的简单介绍

21 篇文章 0 订阅
14 篇文章 0 订阅

目录

介绍:

string类的常见接口说明 

1. string类的常见构造

1.1  string(const string& str,size_t pos,size_t len = npos);

1.2  string(const char* s)

1.3  string (const char * s , size_t  n);

 1.4 string(size_t n,char c);

 2.string类对象的容量操作 

 2.1 size  与  length

2.2 capacity 

2.2.1 capacity的扩容机制 

2.3 clear 

2.4 reserve 

2.5 resize 

(1)字符串变短

(2)字符串变长 

(3)修改长度比capacity大 

3. string类对象的访问及遍历操作 

 3.1 operator[] 与 at

3.2遍历操作 

1.使用operator[] 

2.begin + end 的 迭代器 遍历操作

3.1 反向迭代器 

4.string类对象的修改操作 

4.1push_back 

4.2 append 

4.3 operator +=  (最为常用) 

 4.4 assign

4.5 insert 

 4.6 erase

4.7 replace 

4.7.1 find与replace 

小总结


介绍:

  相关内容详细介绍:cplusplus.com/reference/string/string/?kw=string

  1. string是表示字符串的字符串类
  2. 该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。
  3. string在底层实际是:basic_string模板类的别名,typedef basic_string string,所以string 在底层的本质上也是一个模板
  4. 不能操作多字节或者变长字符的序列。
  5. 在使用string类时,必须包含#include头文件以及using namespace std;

string类的常见接口说明 

1. string类的常见构造

1.1  string(const string& str,size_t pos,size_t len = npos);

void test_string()
{
  string s1;
  string s2(s1 , 5 ,10);
}

提取字符串中的某个区间段的字符,作为一个新的字符串
或者可以说是从一个字符串中提取子字符串
  • str:要从中提取子字符串的源字符串。
  • pos:指定要开始提取子字符串的位置。
  • len:可选参数,指定要提取的子字符串的长度。默认值为 npos,表示提取从 pos 开始到源字符串的末尾的所有字符。

1.2  string(const char* s)

const char* cstr = "Hello, C++";
string str(cstr);  // 使用构造函数将字符串赋值给string的对象str
 
cout << str << endl;  // 输出:Hello, C++


接收一个char类型的字符串作为参数,也就是说将一个字符串赋予给string的对象 

1.3  string (const char * s , size_t  n);

const char* cstr = "Hello, World!"; 
size_t n = 5; 
std::string str(cstr, n); // 使用C风格字符串的前n个字符初始化std::string对象
  • 在这个例子中,cstr 指向字符串 "Hello, World!"。
  • 由于 n 被设置为5,std::string str(cstr, n); 会创建一个 std::string 对象 str并只包含 "Hello" 这5个字符,不包含后面的逗号和空格以及终止空字符。

 1.4 string(size_t n,char c);

string s6(10,'#');
cout << s6 << ednl;

//输出结果 : ##########

本质上是一种初始化

 2.string类对象的容量操作 

 2.1 size  与  length

void test_string()
{
   string s1("hello world");
   cout << s1.size() << endl; //输出结果: 11
   cout << s1.length() << endl; //输出结果: 11


}


size 与 length 的功能都是返回字符串的实际长度,二者并没有任何的区别

2.2 capacity 

void test_string()
{
   string s1("hello world");
   cout << s1.capacity() << endl; //输出结果: 15


}

返回字符串所处在的空间大小,在一般情况下capacity的返回值并不会包含\0所占用的空间

同时,我们需要直到的是capacity的返回值是比size和lenghth的返回值大的,理由如下:

在C++中,std::string是一个动态数组,它可以根据需要自动调整大小,当你创建一个字符串对象时,它会分配一定的内存空间来存储字符串的字符。

这个内存空间的大小由capacity决定,在例子中,字符串"s"的内容是"hello world",它包含11个字符,然而,为了提高性能,std::string通常会分配比实际字符串长度更大的内存空间。

这个额外的空间被称为capacity,它用于存储未来可能添加到字符串中的字符,以避免频繁的内存重新分配操作。所以,s.size()返回的是字符串实际包含的字符数,即11。而s.capacity()返回的是字符串当前分配的内存空间大小,即15。

2.2.1 capacity的扩容机制 

如上代码想要表达的意思如下:

  • 使用变量 sz 获取当前 字符串中的 空间大小,随后进入for循环中使用了 同为 string 的一种接口,push_back 对字符串内部的内容进行添加,随后,判断当前 sz 与 当前的capacity 大小相比较。
  • 由于,在字符串中添加了内容,以及在字符串内部添加了内容,导致了capacity 会因为字符串内容的添加进行空间的对策扩充。
  • 而这个扩充的机制便是,第一次扩充到原来空间的两倍左右,而之后则扩充到当前空间的1.5倍

2.3 clear 

void test_string()
{
   string s1("hello world");
   cout << s1  << endl; //输出结果: hello world
   s1.clear();
   cout << s1  << endl; //输出结果:一行空格

}

清除数据,但仅仅只是数据的清除,空间并不一定清理掉
也就空间不会被释放或者空间不会被销毁!只是清除了空间内部的数据


void test_string()
{
   string s1("hello world");
   cout << s1  << endl; //输出结果: hello world
   cout << s1.capacity() << endl ; // 输出结果:15
   
   s1.clear();
   cout << s1  << endl; //输出结果:一行空格
   cout << s1.capacity() << endl;//输出结果:15
}

如果想要释放空间或者在情况数据后释放空间,可以使用shrink_to_fit
但是这个只是缩小空间大小,但还是会保留一定量的空间,总之不会变成0

2.4 reserve 

string s;//创建一个string 的变量s
s.reserve(100);//提前为 s 进行空间的开辟
cout << s.capacity() <<endl;//输出结果是 111

reserve的功能是开辟空间,或者说是预留空间
当我们知道所需要的空间大小时,可以使用reserve进行空间的开辟
使得在内存空间中提前为我们需要的数据开辟空间

当然,使用了reserve后,因为编译器的问题,有些编译器为了灵活分配内存空间问题
会对reserve开辟的空间进行二次的开辟,也就说进行空间的二次预留

这样就导致开辟出来的空间可能比我们需要的空间还要多

同时,如果使用了reserve 进行空间的扩容,是完全可以的,但是要注意,reserve进行扩容的大小必须要比当前空间的大小还要大,不然reserve是无效扩容 

void test1()
{
  string s1("hello world xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
  cout << s1.capacity() << endl;
  
  s1.reserve(10);

  cout << s1.capacity() << endl;//因为reserve扩容的大小比capacity小,所以扩容无效

}



void test2()
{
  string s1("hello world xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
  cout << s1.capacity() << endl;
  
  s1.reserve(200);

  cout << s1.capacity() << endl;//因为reserve扩容的大小比capacity大,所以扩容成功
                                //输出的结果,应该是两百左右的大小

}

2.5 resize 

resize的主要作用是改变一个字符串的实际长度,但是resize改变长度的情况分为三种:

(1)字符串变短
string s("hello world");
cout << s.size() << endl; // 长度是 11
sout << s.capacity() << endl; // 空间大小是 15

s.resize(5);
cout << s.size() << endl; //长度是5
sout << s.capacity() << endl;//空间大小是15

当resize修改的长度比原本的长度还要小时,那么resize会保留前面的长度,删除后面的数据内容,以此达到相对因的长度,不包含\0 

(2)字符串变长 
string s("hello world");
cout << s.size() << endl; // 长度是 11
sout << s.capacity() << endl; // 空间大小是 15

s.resize(13);
cout << s.size() << endl; //长度是13
sout << s.capacity() << endl;//空间大小是15

当resize修改的长度比原本的长度还长,且resize修改的长度比capacity的空间大小要小时,字符串的长度会被添加至resize修改的长度,而多出来的部分则是用\0进行填充,或者被指定字符填充,以上的代码是默认情况,使用了\0填充 

(3)修改长度比capacity大 
string s("hello world");
cout << s.size() << endl; // 长度是 11
sout << s.capacity() << endl; // 空间大小是 15

s.resize(20);//修改的长度比空间大小还大
cout << s.size() << endl; //长度是20
sout << s.capacity() << endl;
//空间大小是31,因为修改长度超过了原来的空间大小,所以进行了扩容

当resize修改的长度大小比capacity还要大时,capacity会进行扩容处理 


3. string类对象的访问及遍历操作 

 3.1 operator[] 与 at

void test()
{
  
  string s1("hello world");
  cout << s[1] <<endl; //结果是 e
  cout << s.at(1) << endl; //结果是 e
   

}


注意这里和数组一样,遍历是从0开始的!

 at和[]的功能是类似的,二者虽然访问的功能是一样的,但是二者的检查越界的方式是不一样的。

如以上两张图,图1是[]的越界访问,是一个断言警告,图二是at的越界访问,是一个异常处理 

3.2遍历操作 
1.使用operator[] 

cout << s1[i]<<" " 可替换为下面的代码

而由于operator []的本质是返回当前位置的字符,所以可以利用它的特性对字符串中的字符进行++或者--等相关的加减操作

2.begin + end 的 迭代器 遍历操作

迭代器的行为像指针一样的类型对象,begin是返回第一个有效位置的迭代器,end是返回最后一个有效数据的下一个位置,这里的最后一个有效数据的下一个字符是\0,相当于指针的移动,从当前位置移动到\0位置结束

时使用迭代器也可以进行字符串中的字符修改操作  

3.1 反向迭代器 

 反向迭代器使用的是 rbegin 和 rend 进行字符串的反向输出操作 


4.string类对象的修改操作 

4.1push_back 

主要功能是在字符串的尾部插入字符,且只能插入一个字符 

void test()
{
  string s("hello world");
  s.push_back('!');//注意这里是单引号
  cout << s << endl; //输出结果:hello world!

}

4.2 append 

append(const & char*s)这个功能和push_back的功能类似,但是比push_back更强,因为它可以添加字符串

void test()
{
  string s("hello world");
  s.append(" hello bit");
  cout << s << endl; //输出结果:hello world hello bit

}

4.3 operator +=  (最为常用) 

void test()
{
  string s("hello world");
  s += " " ;
  s += "apple" ;
  cout << s << endl; //输出结果:hello world apple

}

 4.4 assign

 最常见的功能是字符的覆盖,将空间内部内容进行删除,然后在添加所需要的内容

void test()
{
  string s("hello world");
  s.assign("xxx");
  cout << s << endl; //输出结果:xxx

}

4.5 insert 

 主要功能在当前位置之前插入字符串

void test()
{
  string s("hello world");
  s.insert(0,"xxx");
  cout << s << endl; //输出结果:xxxhello world

}

 4.6 erase

 从某个位置开始删除几个字符,如果字符不够删,则有多少删多少

void test()
{
  string s("xxxhello world");
  s.erase(0,3);//前面的 0 是位置,后面的3是需要删除的字符个数
  cout << s << endl; //输出结果:hello world
  s.erase();
  cout << s << endl;//erase的默认是全部删除,只留下一行空格当作还要空间存在没有释放

}

4.7 replace 

 主要功能是字符的替换,某个区间位置的字符进行替换

void test()
{
  string s("hello world");
  s.replace(5,1,"%")//5是位置,1是替换的字符个数,%是替换的内容
  cout << s << endl; //输出结果:hello%world

}

4.7.1 find与replace 

find的功能是寻找字符串内部需要查询的字符,找到后返回字符所处在的位置下标,找不到则返回-1

如图配合了replace使用,就可以查询字符串中的空格符号,并且将空格符号进行替换,直到字符串内的所有空格符号都替换完成,其中的npos其实表示的是find找不到字符后的返回值。也就是-

小总结:

insert replace erase 这几个能少用就少用,因为基本都需要挪动数据,它们的底层代码就是挪动数据,所以效率不是很高,建议多使用operator += 

4.8 find

find接口主要的功能就是查找字符、字符串等等,当找到相对因的字符后find会返回字符所在的索引位置(从0开始的下标索引位置),如果没有找到,find则会返回-1,而在string中,-1通常由npos进行表示

string s1("file.cpp");
size_t pos1 = s1.find('.');
查询 字符  .  在字符串中所处的位置 ,这里的pos1获取到的数值是4
因为find是和数组一样从0开始进行查询位置的

同时,find还可以从指定的位置进行字符的查询:

string url1("https://mp.csdn.net/mp_blog/creation/editor/136343480?spm=1001.2014.3001.9457");
size_t i1 = url1.find('/',8);
表示从索引位置8开始进行查找,查找字符 / 并返回 /所在的索引位置

4.9 substr

从指定位置获取字符,并可以指定获取字符的个数,如果没有指定获取字符的个数,那么将会从指定的位置获取字符,获取到原字符串的结尾。 

同时,substr遵循左闭右开的原则:指定位置的字符获取,而从指定位置开始,进行获取字符的个数的计数,计数是从0开始的,当到指定的个数时,所处在该位数的字符不被substr获取 

问题思考

 string 和 char 、数组的区别是什么?

  • 首先,string比数组和char更好,这是取决于string内部有扩容机制,其次string因为扩容机制的原因不会导致空间的不足和空间的浪费
  • 比char和数组更灵活,更易于管理,同时也不需要和考虑计算空间的开辟问题
  • 同时需要注意,string修饰的变量或者字符串的结尾是有\0的,是以\0结束的!而\0结尾的原因是C++兼容C语言,所以必须要符合C语言的规则

  • 14
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值