C++中string类的使用

目录

一.string类

1.1为什么学习string类?

1.2.标准库中的string类

二.string对象的元素访问

 2.1.1使用operator[]与at实现访问

2.1.2正向迭代器访问

2.1.3反向迭代器访问

2.1.4const正向迭代器(不能修改)

2.1.5const反向迭代器(不能修改)

2.1.6范围for

三.string类对象的常见构造

三. string类对象的容量操作

四. string类对象的修改操作

 find

五.string类非成员函数

六.将string对象int互相转换

6.1stoi 将string里第一次遇到的数字字符转换成int

6.2, to_string 将数字转化成string对象

七.vs和g++下string结构的说明

7.1vs下string的结构

7.2g++下string的结构


一.string类

1.1为什么学习string类?

C 语言中,字符串是以 '\0' 结尾的一些字符的集合,为了操作方便, C 标准库中提供了一些 str 系列的库函数,但是这些库函数与字符串是分离开的,不太符合OOP 的思想,而且底层空间需要用户自己管理,稍不留神可能还会越界访问。
OJ 中,有关字符串的题目基本以 string 类的形式出现,而且在常规工作中,为了简单、方便、快捷,基本 都使用string 类,很少有人去使用 C 库中的字符串操作函数。

1.2.标准库中的string类

string类的文档介绍

1. 字符串是表示字符序列的类
2. 标准的字符串类提供了对此类对象的支持,其接口类似于标准字符容器的接口,但添加了专门用于操作
单字节字符字符串的设计特性。
3. string 类是使用 char( 即作为它的字符类型,使用它的默认 char_traits 和分配器类型 ( 关于模板的更多信 息,请参阅basic_string)
4. string类是basic_string模板类的一个实例,它使用char来实例化basic_string模板类,并用char_traits 和allocator作为basic_string的默认参数(根于更多的模板信息请参考basic_string)。
5. 注意,这个类独立于所使用的编码来处理字节 : 如果用来处理多字节或变长字符 ( UTF-8) 的序列,这个 类的所有成员( 如长度或大小 ) 以及它的迭代器,将仍然按照字节 ( 而不是实际编码的字符 ) 来操作。
总结:
1. string 是表示字符串的字符串类
2. 该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作 string 的常规操作。

3. string 在底层实际是: basic_string 模板类的别名, typedef basic_string<char, char_traits, allocator> string;
4. 不能操作多字节或者变长字符的序列。 使用string类时,必须包含#include头文件以及using namespace std;

二.string对象的元素访问

 2.1.1使用operator[]与at实现访问

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

int main()
{
	string s("hello");//构造
	for (size_t i = 0; i < s.size(); i++)//读
	{
		cout << s[i] << "  ";
	}
	cout << endl;

	for (size_t i = 0; i < s.size(); i++)
	{
		cout << s.at(i) << "  ";
	}
	cout << endl;

    for (size_t i = 0; i < s.size(); i++)//写,at同理
	{
		cout << s[i]+=1 << "  ";
	}

}

operator[]与at的区别:

operator[]在元素越界访问时,采用断言,at采用抛出异常

2.1.2正向迭代器访问

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

int main()
{
	string s("hello C++");

	string::iterator it = s.begin();
	while (it != s.end())//读
	{
		cout << *it << "  ";
		it++;
	}
	cout << endl;
	it = s.begin();

	while (it != s.end())//写
	{
		*it += 1;
		cout << *it << "  ";
	}
	cout << endl;
	return 0;
}

2.1.3反向迭代器访问

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

int main()
{
	string s("hello C++");

	string::reverse_iterator it = s.rbegin();
	while (it != s.rend())//读
	{
		cout << *it << "  ";
		it++;
	}
	cout << endl;
	it = s.rbegin();

	while (it != s.rend())//写
	{
		*it += 1;
		cout << *it << "  ";
	}
	cout << endl;
	return 0;
}

2.1.4const正向迭代器(不能修改)

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

int main()
{
	string s("hello C++");

	string::const_iterator it = s.begin();
	while (it != s.end())//读
	{
		cout << *it << "  ";
		it++;
	}
	cout << endl;
	return 0;
}

2.1.5const反向迭代器(不能修改)

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

int main()
{
	string s("hello C++");

	string::const_reverse_iterator it = s.rbegin();
	while (it != s.rend())//读
	{
		cout << *it << "  ";
		it++;
	}
	cout << endl;
	return 0;
}

2.1.6范围for

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

int main()
{
	string s("hello C++");
    for(auto ch:s)//无法修改
    {
        cout<<ch<<"  ";
    }
    
    for(auto& ch:s)//可以修改
    {
        ch+=1;
        cout<<ch<<"  ";
    }
    
	return 0;
}

三.string类对象的常见构造

string()   重点无参构造函数
string(const char* s)  重点用字符串构造对象
string(size_t n,char c)  重点用n个字符构造对象
string(const string& s) 重点拷贝构造
string(const string& str,size_t pos,size_t len=npos)用str从下标(包括)之后len长度的内容,构造对象
string(const char* s,size_t n)用字符串前n个构造对象

template <class InputIterator first,InputIterator last>

string(InputIterator first,InputIterator last)

迭代器区间构造对象

注:第四个构造方法,中的npos,是string类中的一个被static修是的,类型为size_t(无符号整形),值为-1

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

int main()
{
	string s1;//无参构造

	string s2("abcdefg");//用字符串构造对象

	string s3(5, 's');//string类对象中包含n个字符

	string s4(s2);//拷贝构造

	string s5(s2, 0, 3);//用str从下标(包括)之后len长度的内容,构造对象

	string s6("abcdefg", 3);//用字符串前n个构造对象

	string s7(s6.begin(), s6.end());//迭代器区间构造对象

	cout << "s1=" << s1 << endl;
	cout << "s2=" << s2 << endl;
	cout << "s3=" << s3 << endl;
	cout << "s4=" << s4 << endl;
	cout << "s5=" << s5 << endl;
	cout << "s6=" << s6 << endl;
	cout << "s7=" << s7 << endl;
	return 0;
}

三. string类对象的容量操作

size (重点)返回字串有效字符长度
length返回字符串有效长度
capacity  返回空间总大小
empty (重点)检测字符串是否为空串,是返回true,否则返回false
clear (重点)清空有效字符
reserve (重点)为字符串预留空间
resize (重点)将有效字符个数改成n个,多出的空间用字符c填充

1.reverse(修改总容量)

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

int main()
{
	string s("hello C++");
	cout << s.size() << "  " << s.capacity() << endl;
	s.reserve(100);
	cout << s.size() << "  " << s.capacity() << endl;
	s.reserve(10);
	cout << s.size() << "  " << s.capacity() << endl;
	return 0;
}

reserve用于预开空间,如果开辟的空间小于原空间,并不会改变容量

2.resize(调整size)
#include<iostream>
#include<string>
using namespace std;

int main()
{
	//resize(n)
	// resize(size_t n,char x)
	//分三种情况
	//1.  n<size
	//2.  n>size && n<=capacity
	//3.  n>capacity

	string s("hello world");
	s.resize(10);//
	cout << s.size() << "  " << s.capacity() << "  " << s<<endl;
	s.resize(17);//将size改为17,多出来的用'\0'填充
	cout << s.size() << "  " << s.capacity() << "  " << s<<endl;
	s.resize(40, 'x');//将size改为40,多出来的位置用'x'填充
	cout << s.size() << "  " << s.capacity() << "  " << s<<endl;
	return 0;
}

resize用于调整size,当n大于容量是,会扩容,并用对于的字符填充。

当n>size && n< 容量时,用对应的字符填充多出来的

当n<size 时,会缩容放弃超过的空间。

注意:
1. size() length() 方法底层实现原理完全相同,引入 size() 的原因是为了与其他容器的接口保持一
致,一般情况下基本都是用 size()
2. clear() 只是将 string 中有效字符清空,不改变底层空间大小。
3. resize(size_t n) resize(size_t n, char c) 都是将字符串中有效字符个数改变到 n 个,不同的是当字 符个数增多时:resize(n) 0 来填充多出的元素空间, resize(size_t n, char c) 用字符 c 来填充多出的 元素空间。注意:resize 在改变元素个数时,如果是将元素个数增多,可能会改变底层容量的大 小,如果是将元素个数减少,底层空间总大小不变。
4. reserve(size_t res_arg=0) :为 string 预留空间,不改变有效元素个数,当 reserve 的参数小于 string的底层空间总大小时, reserver 不会改变容量大小。

四. string类对象的修改操作

push_back
在字符串后尾插字符c
append
在字符串后追加一个字符串
operator+= ( 重点)
在字符串后追加字符串 str
c_str ( 重点 )
返回 C 格式字符串
find + npos ( 重点 )
从字符串 pos 位置开始往后找字符 c ,返回该字符在字符串中的位置
rfind
从字符串 pos 位置开始往前找字符 c ,返回该字符在字符串中的位置
substr
str 中从 pos 位置开始,截取 n 个字符,然后将其返回

 find

//从pos位置开始找,str
size_t find (const string& str, size_t pos = 0) const noexcept;

//从pos位置开始找字符串第一次出现的下标,若不存在返回npos	
size_t find (const char* s, size_t pos = 0) const;
	
//从pos位置找字符串s的前n个第一次出现的下标,不存在返回npos
size_t find (const char* s, size_t pos, size_type n) const;


size_t find (char c, size_t pos = 0) const noexcept;

通常finf与substr配合使用对找一个网址对应的协议,域名,地址

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

int main()
{
//string s3("https://legacy.cplusplus.com/reference/string/string/rfind/");
    string s3("ftp://www.baidu.com/?tn=65081411_1_oem_dg");
    // 协议
    // 域名
    // 资源名

    string sub1, sub2, sub3;
    size_t i1 = s3.find(':');
    if (i1 != string::npos)
        sub1 = s3.substr(0, i1);//查找协议
    else
        cout << "没有找到i1" << endl;

    size_t i2 = s3.find('/', i1+3);
    if (i2 != string::npos)
        sub2 = s3.substr(i1+3, i2-(i1+3));//查找域名
    else
        cout << "没有找到i2" << endl;

    sub3 = s3.substr(i2 + 1);//查找地址

    cout << sub1 << endl;
    cout << sub2 << endl;
    cout << sub3 << endl;
}

五.string类非成员函数

operator+  
尽量少用,因为传值返回,导致深拷贝效率低
operator>> (重点)
输入运算符重载
operator<< (重点)
输出运算符重载
getline (重点)
获取一行字符串
流提取不能接受空格和换行,需要用接受带有空格的字符串时,可以用getline
getline
istream& getline(istream& in, string&str, char delim);//从流提取中提取字符串到str中,直到delim或'\n'

istream& getline(istream& in,string& str, char);//从流提取中取字符串到str

六.将string对象int互相转换

6.1stoi 将string里第一次遇到的数字字符转换成int

将一个string对象转化成int类型的数字
idx不传参为nullptr,表示不使用这个参数,反之,&idx指向string对象数字字符的后一个位置

6.2, to_string 将数字转化成string对象

七.vs和g++下string结构的说明

注意:下述结构是在 32 位平台下进行验证, 32 位平台下指针占 4 个字节

7.1vs下string的结构

string 总共占 28 个字节 ,内部结构稍微复杂一点,先是 有一个联合体,联合体用来定义 string 中字
符串的存储空间
当字符串长度小于 16 时,使用内部固定的字符数组来存放
当字符串长度大于等于 16 时,从堆上开辟空间
union _Bxty
{ // storage for small buffer or pointer to larger one
 value_type _Buf[_BUF_SIZE];
 pointer _Ptr;
 char _Alias[_BUF_SIZE]; // to permit aliasing
} _Bx;
这种设计也是有一定道理的,大多数情况下字符串的长度都小于 16 ,那 string 对象创建好之后,内
部已经有了 16 个字符数组的固定空间,不需要通过堆创建,效率高。
其次:还有 一个 size_t 字段保存字符串长度,一个 size_t 字段保存从堆上开辟空间总的容量
最后:还 有一个指针 做一些其他事情。
故总共占 16+4+4+4=28 个字节。

7.2g++下string的结构 ​​​​​​​

G++ 下, string 是通过写时拷贝实现的, string 对象总共占 4 个字节,内部只包含了一个指针,该指
针将来指向一块堆空间,内部包含了如下字段:
空间总大小
字符串有效长度
引用计数
struct _Rep_base
{
 size_type _M_length;
 size_type _M_capacity;
 _Atomic_word _M_refcount;
};
指向堆空间的指针,用来存储字符串。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

智能优化算法应用:基于纵横交叉算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于纵横交叉算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于纵横交叉算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.纵横交叉算法4.实验参数设定5.算法结果6.…

2024 年 8 款最佳数据恢复软件深度评测(Windows 和 Mac)

由于意外删除、格式化或损坏而立即丢失重要数据是一场噩梦。当您开始寻找 2024 年最好的数据恢复软件时&#xff0c;由于选项太多&#xff0c;您可能会不知所措。 2024 年 8 款最佳数据恢复软件深度评测 有些工具适用于 Windows&#xff0c;其他工具适用于 Mac&#xff0c;但并…

以太网协议与DNS

以太网协议 以太网协议DNS 以太网协议 以太网用于在计算机和其他网络设备之间传输数据,以太网既包含了数据链路层的内容,也包含了物理层的内容. 以太网数据报: 其中目的IP和源IP不是网络层的目的IP和源IP,而是mac地址.网络层的主要负责是整体的转发过程,数据链路层负责的是局…

【STM32】ADC模数转换器

1 ADC简介 ADC&#xff08;Analog-Digital Converter&#xff09;模拟-数字转换器 ADC可以将引脚上连续变化的模拟电压转换为内存中存储的数字变量&#xff0c;建立模拟电路到数字电路的桥梁 STM32是数字电路&#xff0c;只有高低电平&#xff0c;没有几V电压的概念&#xff…

MySQL之DML语句

文章目录 DML语句创建表添加表字段**插入数据**查询数据更新数据替换数据删除数据清除表数据删除表 DML语句 数据操作语言DML&#xff08;Data Manipulation Langua&#xff09; 是SQL语言的一个分类&#xff0c;用于对表的数据进行增&#xff0c;删&#xff0c;改&#xff0c…

外贸SOHO建站怎么做?海洋建站方法策略?

外贸SOHO建站多少钱&#xff1f;外贸自助建站系统有哪些&#xff1f; 随着全球化的加速发展&#xff0c;外贸SOHO已经成为越来越多创业者的选择。然而&#xff0c;要想在竞争激烈的外贸市场中脱颖而出&#xff0c;一个专业的外贸网站是必不可少的。接下来海洋建站将探讨外贸SO…

openGauss学习笔记-148 openGauss 数据库运维-备份与恢复-逻辑备份与恢复之gs_dumpall

文章目录 openGauss学习笔记-148 openGauss 数据库运维-备份与恢复-逻辑备份与恢复之gs_dumpall148.1 背景信息148.2 注意事项148.3 语法148.4 参数说明148.4.1 通用参数148.4.2 转储参数 148.5 说明148.6 示例 openGauss学习笔记-148 openGauss 数据库运维-备份与恢复-逻辑备份…

在HTML中如何设置音频和视频?

目录 一、设置音频二、设置视频 一、设置音频 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Document</title> </head> <body> <!-- controls:控制播放暂停的按钮autop…

[LLM]nanoGPT---训练一个写唐诗的GPT

karpathy/nanoGPT: The simplest, fastest repository for training/finetuning medium-sized GPTs. (github.com) 原有模型使用的莎士比亚的戏剧数据集, 如果需要一个写唐诗机器人&#xff0c;需要使用唐诗的文本数据&#xff0c; 一个不错的唐诗&#xff0c;宋词数据的下载…

可视化 Java 项目

有一定规模的 IT 公司&#xff0c;只要几年&#xff0c;必然存在大量的代码&#xff0c;比如腾讯&#xff0c;2019 年一年增加 12.9 亿行代码&#xff0c;现在只会更多。不管是对于公司&#xff0c;还是对于个人&#xff0c;怎么低成本的了解这些代码的对应业务&#xff0c;所提…

PDF控件Spire.PDF for .NET【转换】演示:将 PDF 转换为线性化

PDF 线性化&#xff0c;也称为“快速 Web 查看”&#xff0c;是一种优化 PDF 文件的方法。通常&#xff0c;只有当用户的网络浏览器从服务器下载了所有页面后&#xff0c;用户才能在线查看多页 PDF 文件。然而&#xff0c;如果 PDF 文件是线性化的&#xff0c;即使完整下载尚未…

聚焦 | 2023世界中文大会倡导开创智慧语言学堂,助力教育全球化

在遥远的历史时光中&#xff0c;人类曾经集结在一座高耸入云的巨塔下&#xff0c;试图用共同的语言构筑一座通往天堂的巴别塔。而随着时间的推移&#xff0c;语言的多样性渐渐让这座塔的基石岌岌可危&#xff0c;通往“天堂”的道路就此封闭&#xff0c;这就是著名典故——巴别…

C# 图解教程 第5版 —— 第16章 接口

文章目录 16.1 什么是接口16.2 声明接口16.3 实现接口16.4 接口是引用类型16.5 接口和 as 运算符16.6 实现多个接口16.7 实现具有重复成员的接口16.8 多个接口的引用&#xff08;*&#xff09;16.9 派生成员作为实现&#xff08;*&#xff09;16.10 显示接口成员实现16.11 接口…

易生支付与青岛国资之间的合作即将成为现实。青岛国资决定以曲线入股易生支付。

易生金服的次要股权可能会有新的控制方。 根据西米支付网的消息&#xff0c;经营支付服务的持牌机构“易生支付”的唯一股东“易生金服”的第二大股东凯撒同盛发展股份有限公司的控股权将转让给青岛环海湾文化旅游发展有限公司&#xff0c;同时实际控制权也将交由青岛市市北区国…

车载导航系统UI界面,可视化大屏设计(PS源文件)

大屏组件可以让UI设计师的工作更加便捷&#xff0c;使其更高效快速的完成设计任务。现分享车载导航系统科技风蓝黑简约UI界面、车载系统UI主界面、车载系统科技风UI界面、首页车载系统科技感界面界面的大屏Photoshop源文件&#xff0c;开箱即用&#xff01; 若需 更多行业 相关…

Networkx实现小世界网络的分析

Networkx实现小世界网络的分析 小世界网络 小世界现象&#xff0c;也被称为六度分离原则&#xff0c;即如果你在地球上的任何地方随便选择任何两个人&#xff0c;你会发现一条至多由他们之间的6个熟人形成的路径。在网络科学语言中&#xff0c;六度也被称为小世界性质&#x…

产品经理必掌握自定义元件流程图泳道图

&#x1f3ac; 艳艳耶✌️&#xff1a;个人主页 &#x1f525; 个人专栏 &#xff1a; 《产品经理管理项目周期及【Axure RP9】简介&安装&基本使用》 ⛺️ 越努力 &#xff0c;越幸运 目录 一、什么是自定义元件 1.1如何自定义元件 二、什么是流程图 &…

Axure的流程图/泳道图以及自定义元件库的使用

目录 1.ProcessOn的介绍 2.流程图以及泳道图的介绍 2.1流程图 2.2流程图的特点 2.3泳道图 2.4泳道图的特点 2.5流程图跟泳道图的优缺点 2.5.1优点&#xff1a; 2.5.2缺点&#xff1a; 2.6流程图的使用 2.7流程图的案列 2.8泳道图的使用 3.自定义元件库 4.门诊流程…

串口通信(4)-C#串口通信入门实例

本文通过实例讲解C#串口通信。 入门实例设计一个串口助手&#xff0c;能够很好的涵盖串口要点的使用。 目录 一、成品图 二、界面文件 三、后台代码 四、实例中要点 一、成品图 如下&#xff1a; 实现的过程 创建winform项目&#xff0c;将Form1文件的名称改为MainForm&…

Conda 使用教程大全来啦

什么是 Conda&#xff1f; Conda 是一款功能强大的软件包管理器和环境管理器&#xff0c;您可以在 Windows 的 Anaconda 提示符或 macOS 或 Linux 的终端窗口中使用命令行命令 Conda 可以快速安装、运行和更新软件包及相关依赖项。Conda 可以在本地计算机上创建、保存、加载和…