C++string的使用

news2024/11/15 12:33:06

· CSDN的uu们,大家好。这里是C++入门的第十六讲。
· 座右铭:前路坎坷,披荆斩棘,扶摇直上。
· 博客主页: @姬如祎
· 收录专栏:C++专题

目录

1.构造函数

1.1 string()

1.2 string(const char* s)

1.3 string(const char* s, size_t n)

1.4 string(size_t n, char c)

1.5 string (const string& str)

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

2. size_t size() const

3. size_t length() const

4. size_t max_size() const

5. resize

5.1 void resize (size_t n)

​编辑5.2 void resize (size_t n, char c)

6. size_t capacity() const

7: void reserve (size_t n = 0)

8. void clear()

9. bool empty() const

10. operator[]

11. char at(size_t pos) 

12. char& back()

13. char& front()

14. operator+=

15. string& append (const char* s)

​编辑

16. void push_back (char c)

17. insert()

17.1 string& insert (size_t pos, const char* s)

17.2 string& insert (size_t pos, size_t n, char c)

18. string& erase (size_t pos = 0, size_t len = npos)

19. void pop_back()

20. const char* c_str() const

21. find()

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

21. 2 size_t find (char c, size_t pos = 0) const

22. rfind()

​编辑

22.1 size_t rfind (const char* s, size_t pos = npos) const

22.2 size_t rfind (char c, size_t pos = npos) const

23. string substr (size_t pos = 0, size_t len = npos) const


1.构造函数

1.1 string()

这是 string 的无参构造,在 string 的底层就是构造了一个空字符串:“”,即在下标为 0 的位置存储了一个 '\0' 。

#include<iostream>
#include<string>
using namespace std;

int main()
{
    string s;
    cout << s;
    return 0;
}

这是VS2022下看到的结果。VS对 string 的封装比较复杂,他一上来就开了很多空间,并且直接把开辟出来的空间全部初始化为了0。我们看到的现象会因编译器的不同有所差异。

1.2 string(const char* s)

这个构造函数表示可以使用常量字符串来初始化 string!或者使用字符数组来初始化,字符数组的数组名也是 char* 类型的嘛,char* 是可以用const char* 来接收的。

#include<iostream>
#include<string>
using namespace std;

int main()
{
	string s("csdn yyds!");
	cout << s << endl; //输出:csdn yyds!
    
    char arr[12] = { 'c', 's', 'd', 'n', ' ','y' ,'y', 'd', 's', '!'};
    string s1(arr);
    cout << s1 << endl; //输出:csdn yyds!

}

1.3 string(const char* s, size_t n)

 这个构造函数表示可以使用一个常量字符串 或者 字符数组的前 n 个字符来初始化 string。

#include<iostream>
#include<string>
using namespace std;

int main()
{
	string s("csdn yyds!", 4);
	cout << s << endl; //输出:csdn

	char arr[10] = { 'c', 's', 'd', 'n', ' ','y' ,'y', 'd', 's' };
	string s1(arr, 4);
	cout << s1 << endl; //输出:csdn
}

1.4 string(size_t n, char c)

这个构造函数表示可以用 n 个 字符 来构造一个string对象。

#include<iostream>
#include<string>
using namespace std;

int main()
{
	string s(8, '8');
	cout << s << endl; //输出:88888888
}

1.5 string (const string& str)

这个构造函数表示可以使用另一个string对象来构造一个string对象(拷贝构造)。

#include<iostream>
#include<string>
using namespace std;

int main()
{
	string s("csdn yyds!");

	string s1(s);
	cout << s1 << endl; //输出:csdn yyds!
}

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

这个构造函数表示可以用另一个 string 对象 从 pos 位置开始截取 n 个字符来构造一个 string 对象。

我们看到 len 参数有个缺省值:npos。这个 npos 是定义在 string 类中一个public属性的静态常量,其值为 -1。但是因为 len 的类型为无符号的整形,因此 len 的实际大小是无符号整形的最大值。我们可以直接打印 npos :

#include<iostream>
#include<string>
#include<climits>
using namespace std;

int main()
{
	cout << (int)string::npos << endl; //int输出的npos
	cout << string::npos << endl; //size_t输出的npos
	cout << UINT32_MAX << endl; //32位机器下无符号整形的最大值

}

当我们的 pos + len 大于参数一字符串的长度时就是截取 pos 位置后的全部字符来构造string。不传 len ,len = npos 那可是相当大呢!所以不传 len 就是截取 pos 后面的全部字符来构造string。 

#include<iostream>
#include<string>
using namespace std;

int main()
{
	string s("csdn yyds!");

	string s1(s, 5, 4); //从下标为 5 的位置(第一个y)向后截取 4 个字符来构造一个string
	cout << s1 << endl; //输出 yyds

	string s2(s, 5, 188); //len 传入很大
	cout << s2 << endl; //输出 yyds!

	string s3(s, 5); //不传len
	cout << s3 << endl; //输出 yyds!

}

2. size_t size() const

 这个函数用于返回一个 string 对象存储的有效字符的数量。为什么要有后面的那个const呢?我们知道这个const是修饰 *this 的,加上const 常对象与普通对象都可以调用啦!

#include<iostream>
#include<string>
using namespace std;

int main()
{
	string s1("I love scdn!");
	cout << s1.size() << endl; //输出:12

	const string s2("csdn yyds!");
	cout << s2.size() << endl; //输出:10
	
}

3. size_t length() const

 这个接口跟 size_t size() const 实现的效果是一毛一样的!那你就可能会问了,为什么设计者要搞出来两个功能相同的接口呢?那是因为 string 类的出现早于 STL 库,string 在很久以前是没有 size() 这个接口的。但是呢 STL出现以后,求容器的大小都是实现的 size(), 于是 string 就也加上了一个 size() 接口!

4. size_t max_size() const

这个函数返回 一个string 对象多能存储的最多的字符数量,每个编译器的结果不尽相同!此函数用得也不多!

5. resize

5.1 void resize (size_t n)

在 string 的底层维护了一个字符数组,一个表示有效字符个数的size,和字符数组实际的容量capacity。而 resize 函数就是用来改变有效字符的个数的函数。

情况1:当 n 小于原字符串的大小,底层实现很简单,直接改变size,在添加一个 '\0' 表示字符的结束即可! 因此会保留原字符串的数据。

#include<iostream>
#include<string>
using namespace std;

int main()
{
	string s1("csdn yyds");
	s1.resize(4);
	cout << s1 << endl; //输出:csdn
	cout << s1.size() << endl; //输出:4
	
}

通过调试观察 string 的内存,也可以证明我的描述:

 

情况2: 当 n 大于原字符串的大小。会将原字符串的 size 扩展到相应的大小,但是在 VS2022 上,多余的空间他会全部初始化为 0 ,resize 之后的字符串的打印结果与原来并无不同。但是可以通过打印 size 来观察不同!

#include<iostream>
#include<string>
using namespace std;

int main()
{
	string s1("csdn yyds!");
	cout << s1.size() << endl; //resize之前输出:10
	s1.resize(20);
	cout << s1 << endl; //输出:csdn yyds!
	cout << s1.size() << endl; //输出:20
}

通过观察 string 内存,能够证实我的讲解: 

5.2 void resize (size_t n, char c)

 这是一个重载的版本,在改变字符串大小的同时增加了初始化的功能!这个初始化的功能仅在 n 的大小大于原字符串的大小时生效(也就是 5.1 情况二的时候生效。)

#include<iostream>
#include<string>
using namespace std;

int main()
{
	string s1("csdn yyds!");
	s1.resize(20, 'a');
	cout << s1 << endl; //输出: csdn yyds!aaaaaaaaaa
	cout << s1.size() << endl;//输出:20
}

6. size_t capacity() const

我们刚才提到 string 的底层维护了一个 capacity 用来表示字符数组的实际大小,这个函数就是用来返回这个 capacity 的。此函数用得也不多!

不同编译器对于 string 维护的数组开空间的规则不同,因此返回相同字符串的capacity,不同编译器得到的值也不一定相同。下面是VS2022的结果:

#include<iostream>
#include<string>
using namespace std;

int main()
{
	string s;
	cout << s.capacity() << endl; //输出:15
}

7: void reserve (size_t n = 0)

这个函数是用来改变 string 维护的字符数组的实际容量的。

8. void clear()

清空一个字符串的内容,使之变为空串!

9. bool empty() const

判断一个字符串是不是空串!

10. operator[]

operator[] 能够使得字符串支持下标访问,这个是平时用得非常多的!他提供了两个版本,一个是非const版本,一个是const版本。const 修饰的string对象,通过下标访问得到的字符不允许修改。而非const的string对象通过下标访问得到的字符可以修改。

#include<iostream>
#include<string>
using namespace std;

int main()
{
	string s1("hello world");
	s1[5] = '#';
	cout << s1 << endl; //输出:hello#world
}

const修饰的string对象不可修改:

11. char at(size_t pos) 

此函数完全可以被operator[]代替哈,at函数返回的是下标为 pos 的字符。 同样也有const版本和非const版本。

12. char& back()

该函数返回字符串的最后一个字符,同样也有 const 和非const 两个版本。

const版本:const char& back() const

非const版本:char& back()

#include<iostream>
#include<string>
using namespace std;

int main()
{
	string s1("hello world");
	char& tail = s1.back(); //非const支持修改
	tail = 'C';
	cout << s1 << endl;//输出:hello worlC
}

13. char& front()

该函数返回字符串的第一个字符,同样有 const 和非 const 两个版本。

const char& front() const

char& front()

14. operator+=

string 重载了 += 运算符,支持一个字符串加等一个字符,一个字符串常量,一个string 对象。

#include<iostream>
#include<string>
using namespace std;

int main()
{
	string s("csdn yyds!");
	s += 'a';
	cout << s << endl; //输出:csdn yyds!a

	s += "bbb";
	cout << s << endl; //输出:csdn yyds!abbb

	string tmp("ccc");
	s += tmp;
	cout << s << endl; //输出:csdn yyds!abbbccc
}

15. string& append (const char* s)

往一个string对象的末尾追加一个 常量字符串 或者 数组。

#include<iostream>
#include<string>
using namespace std;

int main()
{
	string s1("hello ");
	s1.append("world");
	cout << s1 << endl; //输出:hello world
}

我们查阅 资料 发现 append 重载了很多版,是不是觉得string的设计有点冗余。个人感觉最好用的还是operator+=。 

16. void push_back (char c)

 往string后面追加一个字符,只能说非常鸡肋。不如operator+=。

17. insert()

我们可以看到 insert 重载了巨多版本,真令人头大呢!我们就讲讲两个具有代表性的。其他的都大同小异。

17.1 string& insert (size_t pos, const char* s)

 该函数用于在pos位置插入一个 常量字符串 或者 字符数组(字符数组一定要有 '\0' 哦)。

#include<iostream>
#include<string>
using namespace std;

int main()
{
	string s1("hello csdn");
	s1.insert(5, " hi"); //在下标为5的位置插入 hi
	cout << s1 << endl; //输出:hello hi csdn
	
}

17.2 string& insert (size_t pos, size_t n, char c)

该函数用于在pos位置插入n个相同的字符。

#include<iostream>
#include<string>
using namespace std;

int main()
{
	string s1("hello csdn");
	s1.insert(5, 5, '1'); //在下标为5的位置插入5个'1'
	cout << s1 << endl; //输出:hello11111 csdn
	
}

18. string& erase (size_t pos = 0, size_t len = npos)

这个函数可以将从pos位置开始,后面的len个字符全部删除,不传len,表示len很大,也就是移除pos后面的所有字符啦!

#include<iostream>
#include<string>
using namespace std;

int main()
{
	string s1("hello csdn");
	s1.erase(0, 6); //移除下标 0 后面的6个字符
	cout << s1 << endl; //输出:csdn
	
	string s2("hello csdn");
	s2.erase(1); //移除下标1后的所有字符
	cout << s2 << endl; //输出:h

}

19. void pop_back()

 这个函数简单,删除string的最后那个字符。

20. const char* c_str() const

这个函数可以返回 C风格的字符串。

#include<iostream>
#include<string>
using namespace std;

int main()
{
	string s1("hello csdn");
	const char* s = s1.c_str();
	cout << s << endl; //输出:hello csdn
	return 0;
}

C风格的字符串:char类型的数组,每个下标对应一个字符,末尾有一个 '\0'。

21. find()

find 重载的版本也是比较多的呢!老规矩讲常用的!

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

 这个函数用来在一个string中,从pos位置开始查找一个常量字符串。pos不传的话就是从头查找。如果查找到了,返回起始下标,如果没有查找到返回 npos 。

#include<iostream>
#include<string>
using namespace std;

int main()
{
	string s1("hello csdn");
	//从下标为1的位置开始查找 csdn 这个常量字符串
	cout << s1.find("csdn", 1) << endl; //输出:6

	//从下标为7的位置开始查找 csdn 这个常量字符串
	cout << s1.find("csdn", 7) << endl; //输出:4294967295(这是无符号整形的最大值)
	cout << (int)s1.find("csdn", 7) << endl; //输出:-1

}

21. 2 size_t find (char c, size_t pos = 0) const

这个函数用来在一个string中,从pos位置开始查找字符 c。pos不传就是从头开始查找。一旦查找成功 (即从pos位置开始第一个字符 c ),返回查找成功的下标,否则返回 npos。

#include<iostream>
#include<string>
using namespace std;

int main()
{
	string s1("hello csdn");

	//从下标为 1 的位置开始查找字符'l'
	cout << s1.find('l', 1) << endl; //输出:2

	//从下标为 4 的位置开始查找字符'l'
	cout << s1.find('l', 4) << endl; //输出:4294967295(这是无符号整形的最大值)
	cout << (int)s1.find('l', 4) << endl; //输出:-1
}

22. rfind()

我们可以看到参数的形式跟find完全一样!rfind只是从后往前找罢了!

22.1 size_t rfind (const char* s, size_t pos = npos) const

表示:在 string 对象中从pos位置往前,查找常量字符串 s 。pos不传就是从末尾向前查找。查找成功,返回起始位置的下标,查找失败,返回 npos。

#include<iostream>
#include<string>
using namespace std;

int main()
{
	string s1("hello csdn");

	//从下标为 8 的位置往前,查找常量字符串 csdn
	cout << s1.rfind("csdn", 8) << endl; //输出:6

	//从下标为 5 的位置往前,查找常量字符串 csdn
	cout << s1.rfind("csdn", 5) << endl; //输出:4294967295(这是无符号整形的最大值)
	cout << (int)s1.rfind("csdn", 5); //输出:-1

}

22.2 size_t rfind (char c, size_t pos = npos) const

表示:从pos位置开始向前查找字符 c 。pos不传就是从末尾向前查找。一旦查找成功 (pos位置往前,第一个字符c的下标) 返回该下标,否则返回 npos。

#include<iostream>
#include<string>
using namespace std;

int main()
{
	string s1("hello csdn");

	//从下标为 8 的位置开始向前查找字符'c'
	cout << s1.rfind('c', 8) << endl; //输出:6

	//从下标为 5 的位置开始向前查找字符'c'
	cout << s1.rfind('c', 5) << endl; //输出:4294967295(这是无符号整形的最大值)
	cout << (int)s1.rfind('c', 5) << endl; //输出:-1
}

23. string substr (size_t pos = 0, size_t len = npos) const

 这是用截取原string对象中的一部分连续字符,返回一个新的string对象。简言之:获取子串。

表示:从 pos 位置开始截取 len 个长度的字符来构造新的string。pos不传默认从头开始截取。len不传默认截取到末尾。

#include<iostream>
#include<string>
using namespace std;

int main()
{
	string s1("hello csdn");

	//不传len,默认截取到末尾,从 6 截取到末尾
	cout << s1.substr(6) << endl; //输出:csdn

	//从 0 开始截取 5 个字符
	cout << s1.substr(0, 5) << endl; //输出 hello
}

 总结:不需要死记硬背,用得多了自然就记得了!string的接口真的很多,记不起来查查文档就知道了!

string - C++ Reference (cplusplus.com)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1107102.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Cinema 4D云渲染一分钟动画要多少钱?如何进行Cinema 4D云渲染?看完就懂了

&#xfeff;1.为什么Cinema 4D要使用云渲染&#xff1f; 近年来&#xff0c;Cinema 4D在实现视觉效果方面取得了很大的进展。但是&#xff0c;随着视觉效果的复杂化&#xff0c;渲染的工作量也相应增加&#xff0c;导致渲染时间变长。在这种情况下&#xff0c;云渲染平台就能…

Linux嵌入式系统开发之路:从小白到大牛

&#x1f482; 个人网站:【工具大全】【游戏大全】【神级源码资源网】&#x1f91f; 前端学习课程&#xff1a;&#x1f449;【28个案例趣学前端】【400个JS面试题】&#x1f485; 寻找学习交流、摸鱼划水的小伙伴&#xff0c;请点击【摸鱼学习交流群】 嵌入式系统开发是一个充…

Spring framework Day22:Aware接口

前言 在Spring框架中&#xff0c;有许多接口和类都有一个非常重要的作用——让我们能够更方便地构建应用程序和管理组件。其中&#xff0c;Aware接口就是其中一个非常重要的接口之一。通过实现该接口&#xff0c;我们可以让Spring容器感知到特定的组件和资源&#xff0c;并进行…

媒体转码和输出软件:Media Encoder 2024中文版

想要高效地转码、优化输出吗&#xff1f;那就来尝试全新的Media Encoder 2024吧&#xff01;Media Encoder是Adobe公司出品的一款媒体转码和输出软件&#xff0c;可以帮助您快速、高效地将多种格式的视频和音频转换为所需的输出格式。 全新的Media Encoder 2024提供了更加智能…

【CANoe】XML Test Module使用实例

文章目录 一、实操步骤1、增加XML Test Module节点2、配置XML Test Module节点3、XML Test Module节点增加CAPL脚本(.can文件)4、文件夹结构5、使用仿真节点开始测试6、测试结果与测试报告7、同理&#xff0c;在Test Setup也可如此操作 一、实操步骤 1、增加XML Test Module节…

使用conda install一直卡在solving environment的解决方法

使用国内镜像源&#xff0c;但install仍旧一直卡在solving environment&#xff0c;超过10分钟就不用等了&#xff1b; 检查C:\Users\UserName 路径下的.condarc文件 将这个defaults这一行删掉即可

【Linux-常用命令-基础命令-复制-copy-命令-笔记】

【Linux-常用命令-基础命令-复制文件-copy-命令-笔记】 1、前言2、操作3、自己的实践 1、前言 最近&#xff0c;在使用Linux的时&#xff0c;使用相关基础命令是&#xff0c;总是容易忘记&#xff0c;上网一搜&#xff0c;大部分都写的比较繁琐&#xff0c;我就找下复制命令&a…

【算法设计与分析qwl】04 NP-hard——只是举例几个,货郎,双机调度,01背包

NP-hard问题&#xff1a; 有效算法是 输入规模的多项式时间算法。 这些问题的难度处于可有效计算的边界。 算法数据结构程序设计 例4 货郎问题 建模与算法&#xff1a; 解是一个排列&#xff0c; 0-1背包问题&#xff1a; 建模&#xff1a; 双机调度&#xff1a; 建模&#x…

【PPT技巧】如何将多张幻灯片打印在一张纸上?

PPT页面很多&#xff0c;想在打印的时候&#xff0c;多张幻灯片放置在同一页面&#xff0c;也就是打印在一张纸上&#xff0c;如何设置呢&#xff1f; 首先&#xff0c;打开需要打印的PPT文件&#xff0c;点击菜单选项卡【文件】&#xff0c;然后在弹出的页面中点击【打印】选…

单链表经典OJ题:找出链表的中间节点

题目&#xff1a; 给你单链表的头结点 head &#xff0c;请你找出并返回链表的中间结点。如果有两个中间结点&#xff0c;则返回第二个中间结点。 图例&#xff1a; 解法&#xff1a; 解法1: 先遍历链表确定链表节点的数量&#xff0c;然后再找到中间位置的节点 解法2: 快慢…

Linux性能优化--补充

14.1. 性能工具的位置 本书描述的性能工具来源于Internet上许多不同的位置。幸运的是&#xff0c;大多数主要发行版都把它们放在一起&#xff0c;包含在了其发行版的当前版本中。表A-1描述了全部工具&#xff0c;提供了指向其原始源位置的地址&#xff0c;并注明它们是否包含在…

百度地图高级进阶开发:圆形区域周边搜索地图监听事件(覆盖物重叠显示层级\图像标注监听事件、setZIndex和setTop方法)

百度地图API 使用百度地图API添加多覆盖物渲染时&#xff0c;会出现覆盖物被相互覆盖而导致都无法触发它们自己的监听&#xff1b;在百度地图API里&#xff0c;map的z-index为0&#xff0c;但是触发任意覆盖物的监听如click时也必定会触发map的监听&#xff1b; 项目需求 在…

6.7 案例分析与实现

思维导图&#xff1a; 6.7 案例分析与实现 #### 案例6.2: 六度空间理论 【案例分析】 - **背景介绍**&#xff1a; 六度空间理论提及在任意两人之间最多仅有6个人的连接。尽管这一理论被广泛提及并得到了某种程度的验证&#xff0c;但从科学角度看&#xff0c;它仍然只是一…

模型的选择与调优(网格搜索与交叉验证)

1、为什么需要交叉验证 交叉验证目的&#xff1a;为了让被评估的模型更加准确可信 2、什么是交叉验证(cross validation) 交叉验证&#xff1a;将拿到的训练数据&#xff0c;分为训练和验证集。以下图为例&#xff1a;将数据分成4份&#xff0c;其中一份作为验证集。然后经过…

C/C++面试常见问题——指针和引用的区别

首先想要理解指针和引用的区别&#xff0c;我们要明确什么是指针&#xff0c;什么是引用 一&#xff0c;指针和引用的基本概念及特性 指针是一个特殊变量&#xff0c;其中存储着所指向变量的地址 指针主要有以下特性&#xff1a; 1. 在使用时需要*解引用 2. sizeof(指针)的…

关于我对 jeecg-boot 的项目理解、使用心得和改进建议

一句话总结&#xff1a; JeecgBoot帮助我提升了后端技术水平&#xff0c;入门了前端&#xff0c;让我在公司内部慢慢能够成长为全栈开发。 一、项目理解 JeecgBoot 项目的核心理念是快速开发、低代码、易扩展。它采用了前后端分离的架构&#xff0c;后端使用Spring Boot Myba…

5.覆盖增强技术——PUCCHPUSCH

PUSCH增强方案的标准化工作 1.PUSCH重复传输类型A增强&#xff0c;包括两种增强机制&#xff1a;增加最大重复传输次数&#xff0c;以及基于可用上行时隙的重复传输次数技术方式。 2.基于频域的解决方案&#xff0c;包括时隙间/时隙内跳频的增强 3.支持跨多个时隙的传输块&…

spring配置文件第一行导致读取配置失败

遇到读取配置存在问题&#xff0c;尤其当配置到第一行 通过spring执行测试类&#xff0c;没有问题&#xff0c;但是相同配置启动项目时&#xff0c;老找不到JdbcTemplate 使用配置&#xff1a; spring.shardingsphere.datasource.namesmaster,slavespring.shardingsphere.dat…

服务器往浏览器推消息(SSE)应用

1&#xff0c;SSE 和 WebSocket 对比 SSE&#xff08;服务器发送事件&#xff09; SSE是一种基于HTTP的单向通信机制&#xff0c;用于服务器向客户端推送数据。它的工作原理如下&#xff1a; 建立连接&#xff1a;客户端通过发送HTTP请求与服务器建立连接。在请求中&#xff…

【linux API 分析】register_chrdev

linux kernel&#xff1a;4.19 在注册字符设备的时候&#xff0c;可使用register_chrdev()函数&#xff0c;其对应的注销函数是unregister_chrdev()&#xff0c;其定义是在include\linux\fs.h文件 register_chrdev() 首先分析register_chrdev()函数 其定义如下 static inlin…