【C++】掌握string类常用接口

前言


  • 🚄 输入是学习的本质,输出是学习的手段。
  • 🔖 分享每一次的学习,期待你我都有收获。
  • 🎇 欢迎🔎关注👍点赞⭐️收藏✉评论,共同进步!
  • 🌊 “要足够优秀,才能接住上天给的惊喜和机会”
  • 💬 博主水平有限,如若有误,望斧正,万分感谢!

☁️string类

旨在理解掌握string类的常见使用

为了方便后面string类的学习,先要了解一下string::npos

npos是string类里的一个静态成员函数,在string类成员函数中经常作为缺省参数出现

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dIgrgyre-1646464075483)(C:\Users\Z-zp\AppData\Roaming\Typora\typora-user-images\image-20220228100836719.png)]

这是npos的定义。其中size_t说明npos是一个无符号整型,因此,这里npos = -1,

npos的实际值是整型最大值,即42亿+。

☁️string类构造函数

string()
    
string(const char* a)
    
string(size_t n,char c)  //初始化为n个字符c.

string(const string& a)

void Test1()
{
	string s1;
	cout << s1 << endl;
    
	string s2("hello world");
	cout << s2 << endl;
    
	string s3(s2);
	cout << s3 << endl;
    
	string s4(10, 'x');  //初始化为10个字符x
	cout << s4 << endl;

}

☁️String类的容量操作

size()  //返回有效数据的个数(个数不包含\0)   
    
capacity() //返回当前容量
    
clear() //清空有效字符,但容量不一定会清空
    
resize(size_t n,char c) 
//从0开始,只给n个位置数据,多删少补。
    
//(多删:可能原本对象中的有效数据个数 >n ,则只留前n个数据,size修改为n,不会改变容量大小)
//(少补:补字符c,不传字符参数,默认补\0,size修改为n,容量不够时,会扩容)
    
//也就意味着会影响size,也会影响capacity(容量不够的时候)
//但是如果原来位置有值且在n范围内,不会覆盖原来位置的值。
    

reserve(size_t n = 0) //扩容,为对象预留空间,size不变。当 n< 当前对象空间,不会改变容量大小。


☁️String类对象的访问和遍历

☁️operator[ ]
operator[]   

//[]重载,数组怎么用,这个就这么用
☁️迭代器

原理类似指针,这里只讲用法,模拟实现后面单独写

  • 正向迭代器
string::iterator t = s1.begin();     //t变量名可随意取

string::const_iterator t = s1.begin();   //const修饰的对象要用这个const修饰的迭代器

begin()  //获取string类对象第一个字符的位置

end()	//获取string类对象最后一个位置的 下一个位置 

注意:这里我们利用 begin和end ,得到的是一个左闭右开的区间

样例1:

int main()
{
    string s1("hello world");
    string::iterator t = s1.begin();
    while (t != s1.end())   //注:这里写作 t < s1.end(),结果也一样,但是不规范。务必一定用!=
    {
        cout << *t;
        // *t = 'P';  //正确,不是const修饰的迭代器,所以可读可写。
        t++;
    }
    cout << endl;
    return 0;
}

样例2:

int main()
{
    string s1("hello world");
    string::const_iterator t = s1.begin();
    while (t != s1.end())   //注:这里写作 t < s1.end(),结果也一样,这是因为它是一块连续的空间,如果遇到像list等等不连续的空间,还是得用!=,为了统一写法,最好用!=
    {
        cout << *t;
        // *t = 'P';  //错误,const修饰的迭代器,只读,不具有写的权限
        t++;
    }
    cout << endl;
    return 0;
}

  • 反向迭代器
string::reverse_reiterator po = s1.begin();    //po变量名可随意取

string::const_reverse_iterator po = s1.begin();  //const修饰的对象要用这个const修饰的迭代器

rbegin()  //获取string类对象第一个字符的位置

rend()	//获取string类对象最后一个位置的 下一个位置 

注意和正向迭代器区分

样例:

int main()
{
    string s1("hello world");
    string::reverse_iterator t = s1.rbegin();
    while (t != s1.rend())
    {
        cout << *t;
        t++;
    }
    cout << endl;
    return 0;
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-s2GctSB7-1646464075483)(C:\Users\Z-zp\AppData\Roaming\Typora\typora-user-images\image-20220228113342612.png)]


最后再用一张图帮助理解一下迭代器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-W7PuDcQr-1646464075484)(C:\Users\Z-zp\AppData\Roaming\Typora\typora-user-images\image-20220228193757896.png)]

☁️范围for

要讲清楚范围for,要先理解auto类型

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-voPiOy7x-1646464075485)(C:\Users\Z-zp\AppData\Roaming\Typora\typora-user-images\image-20220228194539019.png)]

对于auto类型,编译器会自动根据右操作数,推导出auto定义的对象的类型。

void Test5()
{
	string s1 = "hello world";

	for (auto t : s1)
	{
		cout << t;
	}
	cout << endl;
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HgDbD6vw-1646464075486)(C:\Users\Z-zp\AppData\Roaming\Typora\typora-user-images\image-20220303091602893.png)]

这段代码的意思是,将s1的值一个一个取出赋给t,然后打印t。

此时改变t的值,不会改变s1的值,如果要改变s1的值,需加引用。

范围for最终会被编译器替换成迭代器形式,
所以也可以认为其底层实现是依靠迭代器的。


☁️string类对象的修改操作

push_bach(char c)  //对对象尾插字符c
    
append(const string& str)  //追加字符串str ,还有其他多种追加方式,详见官网标准库
    
operator+=  //追加字符或字符串 ,最常用的追加方式,一目了然

☁️c_str
c_str  //返回c格式字符串

直接说可能体会不到这个意思,我们看一段代码

void Test6()
{
	string s1 = "hello world";
	s1.resize(20);
	s1 += "!!!";
	
	cout << s1 << endl << endl;

	cout << s1.c_str() << endl;
	
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-S3OoxW0n-1646464075486)(C:\Users\Z-zp\AppData\Roaming\Typora\typora-user-images\image-20220303095008734.png)]

先是用resize修改了string类对象的size。前面说过,resize多删少补,默认补"\0"

正常string类的遍历是按照size的个数来进行的,也就是size是多少就会访问多少个字符,

**就算是遇到了\0,也不会停止访问,**只是我们看不到它输出\0,所以可能会以为它是遇到\0就停下。

以范围for遍历string对象来印证这一观点

void Test6()
{
	string s1 = "hello world";
	size_t count = 0;  //计数,既然看不到输出\0,观察计数就好
	cout << "resize 前:" << endl;
	cout << "s1.size = " << s1.size() << endl;
	for (auto t : s1)  //遍历
	{
		cout << t;
		count++;
	}
	cout << endl << "count = " << count << endl;


	cout << endl << "resize 后:" << endl;
	count = 0;  //重置为0
	s1.resize(20); 
	cout << "s1.size = " << s1.size() << endl;
	for (auto t : s1)
	{
		cout << t;
		count++;
	}
	cout << endl << "count = " << count << endl;
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BndMp9Up-1646464075487)(C:\Users\Z-zp\AppData\Roaming\Typora\typora-user-images\image-20220303100602343.png)]

由此可以确定,string类对象的遍历:

其依据是size的大小,即使是遇到了\0,也不会停下。

因为当还没访问完size个数的数据时,它不知道 \0 后面是否还存在有效数据,

如果自己直接停下,会不会导致有效数据没有访问到,所以它不会停下

但是c语言中,访问字符串遇到\0就会停下


至此,大家大概就能明白 c_str() 的作用了吧。

void Test7()
{
	string s1 = "hello world";
	cout << s1 << endl;
	cout << s1.c_str() << endl;

	s1.resize(20);
	s1 += "!!!";
	cout << s1 << endl;
	cout << s1[11] << " " << s1[12] << endl;  
	cout << s1.c_str() << endl;  //返回c语言格式字符串
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BitUWjGe-1646464075488)(C:\Users\Z-zp\AppData\Roaming\Typora\typora-user-images\image-20220303102038748.png)]


☁️find
size_t find (const string& str, size_t pos = 0) const;

size_t find (const char* s, size_t pos = 0) const;

从pos位置开始,往后寻找字符或字符串,并返回位置,如果没找到,返回npos

☁️rfind
size_t rfind (const string& str, size_t pos = npos) const;
	
size_t rfind (const char* s, size_t pos = npos) const;

从pos位置开始,往后寻找字符或字符串,并返回位置,如果没找到,返回npos。

pos给的缺省值是npos,如果pos大于字符串长度或者等于npos,都是从字符串最后一个字符开始往前找。


☁️substr
string substr (size_t pos = 0, size_t len = npos) const;

从pos位置开始,截取len个字符,并返回。


☁️getline

用string定义字符串,

如果输入字符串用 cin>> ,它和scanf有一样的问题:

会把空格或回车当做是两个字符串之间的分隔

所以要用getline输入字符串。

int main()
{
    string s;
    //cin>>s;
    getline(cin,s);
    cout<<s<<endl;
}

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿波呲der

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值