C++ STL string类

news2024/11/25 7:19:17

目录

一.为什么学习string类

(1) C语言中的字符串

(2)标准库里面的string类

二. string类的常用接口说明

(1)string类对象的常见构造

(2)string类对象的容量操作

1.size(),length().

2. capacity()

3.empty()

 4.clear()

 5.reserve()

 6.resize()

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

 1.operator[ pos ] ,at(size_t pos)

 2.back(),front()

(4)string类的迭代器

1.begin(),end()

2.rbegin() ,rend()

3.范围for

(5) string类对象的修改操作

1.push_bank( )

 2.append()

3.operator +=

 4.insert ()

 5.erase()

6.swap()

(6)字符串相关算法

1.c_str()

 2.find()

3.substr()

(7) 非成员函数重载

1.getline()


一.为什么学习string类

(1) C语言中的字符串

C语言中,字符串是以'\0'结尾的一些字符的集合,为了操作方便,C标准库中提供了一些str系列的库函数,但是这些库函数与字符串是分离开的,不太符合OOP的思想,而且底层空间需要用户自己管理,稍不留神可能还会越界访问。

在OJ中,有关字符串的题目基本以string类的形式出现,而且在常规工作中,为了简单、方便、快捷,基本都使用string类,很少有人去使用C库中的字符串操作函数。

(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类的常用接口说明

(1)string类对象的常见构造

string() (重点)创建空的string类型对象,即空字符串
string(const char* s) (重点)用C-string来构造string类对象
string(size_t n, char c)string类对象中包含n个字符c
string(const string&s) (重点)拷贝构造函数
#include<iostream>
#include<string>
using namespace std;
int main()
{
	//创建空字符串
	string str1;
	cout << str1 << endl;
	//使用字符串构造对象
	string str2("hello world");
	cout << str2 << endl;
	//使用n个字符构造对象
	string str3(15, '*');
	cout << str3 << endl;
	//拷贝构造函数
	string str4(str2);
	cout << str4 << endl;

	return 0;
}

(2)string类对象的容量操作

课件代码/C++课件V6/string的接口测试及使用/TestString.cpp · will/C++上课 - Gitee.com

1.size(),length().

size()和lenth都是返回字符串有效长度的。

注意:我们一般表示字符串的长度时使用length,引入size()的原因是为了与其他容器的接口保持一致,一般情况下基本都是用size()。

int main()
{
	string str("hello world");
	cout << str.size() << endl;
	cout << str.length() << endl;

	return 0;
}

2. capacity()

capacity()是返回字符串对象的总空间大小的,因为string自己本身是可以扩容的。

int main()
{
	string str("hello world");
	cout << str.size() << endl;
	cout << str.length() << endl;
	cout << str.capacity() << endl;

	return 0;
}

3.empty()

检测字符串释放为空串,是返回true,否则返回false。

int main()
{
	string str("hello world");
	string str1;
	cout << str.empty() << endl;
	cout << str1.empty() << endl;

	return 0;
}

 4.clear()

清楚有效字符。

注意:clear()只是将string中有效字符清空,不改变底层空间大小。

int main()
{
	string str("hello world hello world hello ");
	cout << "clear前:" << str <<" 容量:" << str.capacity() << endl;
	str.clear();
	cout << "clear前:" << str << "容量:" << str.capacity() << endl;
	return 0;
}

 5.reserve()

为字符串预留空间,我们直到在一些情况下如果我们提前知道了字符串的大小,就可以提前为字符串开好空间,避免后面的扩容带来的效率上的消耗。

注意:实际上的申请后的空间会比我们申请的空间大一些,这也是一种保护机制。但是我们如果我们预留的空间比原本的空间还要小时,此时函数会进行优化,个根据我们存储的串的长度经行合适的改表。

 6.resize()

resize(size_t n)resize(size_t n, char c)都是将字符串中有效字符个数改变到n个,不同的是当字符个数增多时:resize(n)用0来填充多出的元素空间,resize(size_t n, char c)用字符c来填充多出的元素空间。注意:resize在改变元素个数时,如果是将元素个数增多,可能会改变底层容量的大小,如果是将元素个数减少,底层空间总大小不变。如果 n 小于字符串长度,就删去字符串保留前 n 个。

int main()
{
	string str("abcde");
	cout << str << endl;
	//扩容+初始化
	str.resize(str.size() + 5, '#');
	cout << str << endl;
	//减小长度
	str.resize(4);
	cout << str << endl;

	return 0;
}

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

 1.operator[ pos ] ,at(size_t pos)

operator [ ] 都是返回pos位置的字符,const string类对象调用。operater[ ]是对[ ]的运算符重载,就像数组一样的访问。

注意:两者的区别在,处理越界方面,operator[ ]使用断言处理,而 at(pos) 是抛出一个异常。

int main()
{
	string str("hello");
	for (int i = 0; i < str.size(); i++)
	{
		cout << str[i] << " ";
	}
	cout << endl;
	for (int i = 0; i < str.size(); i++)
	{
		cout << str.at(i) << " ";
	}
	return 0;
}

 2.back(),front()

back():返回最后一字符,front():返回第一个字符。

(4)string类的迭代器

1.begin(),end()

begin():返回一个迭代器,该迭代器指向字符串的开始字符。

end():返回一个迭代器,该迭代器指向字符串的结束字符。

迭代器,也是一个用来遍历对象的一个东西,它有自己的类型 iterator ,针对begin(),和end(),也都有自己的const版本,也就是仅可读迭代器。string的迭代器的使用和指针差不多。

当前可以这么理解,随着我们STL的不断学习,会对迭代器有更加深刻的理解。

int main()
{
	string str("helloworld");
	//非const迭代器,可读,可写
	for (string::iterator it = str.begin();it!=str.end();it++)
	{
		*it = '*';
	}
	for (string::iterator it = str.begin(); it != str.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
	//const 迭代器 仅可读
	const string str1("helloworld");
	for (string::const_iterator it = str1.begin(); it != str1.end(); it++)
	{
		cout << *it << " ";
	}
	return 0;
}

2.rbegin() ,rend()

rbegin():返回反向迭代器以反向开始,返回一个反向迭代器,指向字符串的最后一个字符(即其反向开头),反向迭代器向后迭代:增加迭代器会将它们移向字符串的开头。

rend():返回一个反向迭代器,该迭代器指向字符串的第一个字符之前的理论元素(被视为其反向结尾)。

反向迭代器的类型是,reverse_iterator,同时都提供了,const版本。

int main()
{
	string str("helloworld");
	
	for (string::reverse_iterator it = str.rbegin(); it != str.rend(); it++)
	{
		cout << *it << " ";
	}
	return 0;
}

 

对于迭代器的类型写起来非常的不方便,我们可以使用auto来自动识别。

3.范围for

范围for是将str对象的字符一个一个取出来,放到 c 中。其底层还是使用的迭代器。

int main()
{
	string str("helloworld");

	for (auto c : str)
	{
		cout << c << " ";
	}
	return 0;
}

(5) string类对象的修改操作

1.push_bank( )

在字符串后尾插字符c。

int main()
{
	string str("hello");
	cout << str << endl;
	str.push_back('w');
	str.push_back('o');
	str.push_back('r');
	str.push_back('l');
	str.push_back('d');
	cout << str<<endl;
	return 0;
}

 2.append()

在字符串后追加一个字符串,同时也提供了多个版本:

string& append (const string& str):追加一个字符串 str 。

string& append (const string& str, size_t subpos, size_t sublen):追加字符串str的pos位置后的sublen个字符。

string& append (const char* s):追加一个C字符串,(即以‘/0’结束的字符串)。

string& append (const char* s, size_t n):追加C字符串s的后n个字符。

string& append (size_t n, char c):追加 n 个字符 c  

int main()
{
	string str;
	string str1;
	cout << str << endl;
	string str2 = "Writing ";
	//str1追加str2的第四个位置的后三个字符
	str1.append(str2, 4,3);
	//str追加str2
	str.append(str2);
	cout << str << endl;
	cout << str1 << endl;
	//str2z追加一个C字符串
	str2.append("work");
	cout << str2 << endl;
	//str2追加一个c字符串的前两个字符
	str2.append("hello", 2);
	cout << str2 << endl;
	//str2追加10个‘#’
	str2.append(10, '#');
	cout << str2 << endl;

	return 0;
}

3.operator +=

 对于上述的push_bank和append其实在string类中使用并不多,我们一般常用operator+=来追加字符串或者追加字符。

例:

int main()
{
	string str1("hello");
	string str2("world");
	str1 += str2;
	
	cout << str1 << endl;

	return 0;
}

 4.insert ()

字符串插入函数,可以支持在某一位,或者迭代器位置插入固定个数的字符,和字符串。

 例:

int main()
{
	string str1("hello");
	string str2("world");
	int pos = 0;
	//1.在pos位置插入一个 string 
	str2.insert(pos, str1);
	cout << str2 << endl;

	string str3("bcde");
	int size = 5;
	//2.在pos位置插入size个字符a
	str3.insert(pos, size, 'a');
	cout << str3 << endl;

	string str4("bcde");
	//3.插入位置还可以是迭代器
	str4.insert(str4.begin(), 10, 'A');
	cout << str4 << endl;

	string str5("world");
	const char* cstr = "hello ";
	//3.在pos位置插入一个 C风格字符串。
	str4.insert(pos,cstr);
	cout << str5 << endl;

	return 0;
}

 注意:insert,在插入时,特别是在字符串的前部插入是,会有字符的移动消耗。相当于顺序表的头插。

 5.erase()

rases字符串的一部分,缩短其长度。

例:

int main()
{
	int pos = 5;
	int size = 3;
	string str1("hello   C++");
	string str2 = str1;
	cout << "erase前str1:" << str1 << endl;
	cout << "erase前str2:" << str2 << endl;
	//删除pos位置包括pos位置的后size个字符,删除位置也可以是一段迭代器区间
	str1.erase(pos, size);
	str2.erase(str2.begin()+5,str2.begin()+5+3);
	cout << "erase后str1:" << str1 << endl;
	cout << "erase后str2:" << str2 << endl;

	return 0;
}

注意:

  • 如果给出的删除个数大于字符串后面的字符数,就会将后面字符全部删除。
  • 如果不给出删除位置设定的缺省参数从0开始删除。
  • 如果不给出删除个数,缺省参数设定的删除个数是 size_t npos = -1,约42亿。
  • 删除以后字符串的长度(length)会变,但是容量(capacity)不会变。

6.swap()

swap交换函数,非功能上非常简单,就不多介绍了。但是在 std 里面也有一个swap,我们两个swap来对比一下。

std::swap()底层是一个由借助函数模板实现。不仅仅可以对string类型,对任何可以修改的类型都可以实现交换。

原理类似:


template<class T>
void Swap(T& e1,T& e2)
{
	T tmp = e1;
	e1 = e2;
	e2 = tmp;
}

string::swap()底层是交换string里面的字符串指针来实现的,总体效率要比std::swap()高得多。

(6)字符串相关算法

1.c_str()

返回一个C风格字符串。

 2.find()

在字符串中搜索由其参数指定的序列的第一个匹配项。
指定pos时,搜索仅包括位置pos处或之后的字符,忽略任何可能出现的位置pos之前的字符。

 例如:

int main()
{

	string str = "this is a string";
    //从1位置开始查找字符a,并返回位置。
	size_t pos = str.find('a', 1);
	cout << "a 在" << pos << "位置" << endl;

    return 0;
}

 注意:

  • 如果未给出查找位置,就从缺省位置0开始查找。
  • 如果没有找到会返回size_t npos = -1。

3.substr()

返回一个新构造的字符串对象,该对象的值初始化为此对象的子字符串的副本。
子字符串是对象的一部分,从字符位置pos开始,跨越len个字符(或直到字符串结束,以先到者为准)。

例:

int main()
{

	int pos = 0;
	int length = 4;
	string str = "this is a string";
	//返回一个从pos位置开始,跨越长度为4的子串。
	string Substr = str.substr(0, 4);

	cout << "Substr:" << Substr << endl;

    return 0;
}

 注意:

如果没给出起始位置,缺省参数设置为0。

如果没给出跨越长度,缺省参数设置为size_t npos = -1。

(7) 非成员函数重载

1.getline()

 从is中提取字符并将其存储到str中,直到找到定界字符delim。没有delim时默认是 ' \n '为定界符 。

 例:

int main()
{
	string str;
	cout << "输入:";
	std::getline(cin, str,'a');
	cout << "str:" << str << endl;

	return 0;
}

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

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

相关文章

2023年中期奶粉行业分析报告(京东数据开放平台)

根据国家统计局和民政部数据公布&#xff0c;2022年中国结婚登记数创造了1980年&#xff08;有数据公布&#xff09;以来的历史新低&#xff0c;共计683.3万对。相较于2013年巅峰时期的数据&#xff0c;2022年全国结婚登记对数已接近“腰斩”。 2023年“520”期间的结婚登记数…

拖拽宫格vue-grid-layout详细应用及案例

文章目录 1、前言2、安装3、属性4、事件5、占位符样式修改6、案例 1、前言 vue-grid-layout是一个适用于vue的拖拽栅格布局库&#xff0c;功能齐全&#xff0c;适用于拖拽高度/宽度自由调节的布局需求&#xff0c;本文将讲述一些常用参数和事件&#xff0c;以及做一个同步拖拽…

[原创]从model-based推导到model-free(到PG+general advantage estimation)

前言 这篇博客很久之前就想做了&#xff0c;一直在拖是因为觉得自己对知识点理解还没有足够的透彻。但是每当去复盘基本概念的时候又很难理清逻辑&#xff0c;所以觉得即便现在半吊子水平&#xff0c;但是也想通过博客记录一下自己肤浅的学习心得&#xff0c;权当是为自己巩固…

metersphere性能压测执行过程

(1) 首先在controller层&#xff0c;通过RunTestPlanRequest接收请求参数 PostMapping("/run")public String run(RequestBody RunTestPlanRequest request) (2) 在PerformanceTestService中的run中进行具体的逻辑处理&#xff0c; 首先根据请求中ID来获取库中存储…

128.【Maven】

Maven仓库 (一)、Maven 简介1.传统项目管理的缺点2.Maven是什么3.Maven的作用 (二)、Maven 的下载与安装1.下载与认识目录2.配置Maven的全局环境 (三)、Maven 的基础概念1.Maven 仓库(1).仓库分类 2. Maven 坐标3.Maven 本地仓库配置(1).改变默认的仓库地址(2).改变远程仓库地址…

SpringWeb项目核心功能总结

SpringWeb项目核心功能总结 文章目录 SpringWeb项目核心功能总结1.浏览器与Java程序的连接&#xff08;个人偏好使用RequestMapping&#xff09;2.参数的传入3.结果的返回请求转发和请求重定向的区别 核心功能用到的注解&#xff1a; RestControllerControllerResponseBodyRequ…

vr禁毒宣传展厅展馆为观众带来了沉浸式的真实体验

毒品是当今社会的一大毒瘤&#xff0c;给人们的生命和家庭带来了极大的伤害&#xff0c;禁毒教育一直是我们必须重视的一项工作。为了更好地宣传禁毒知识&#xff0c;我们不断地探索新的教育方式&#xff0c;其中&#xff0c;VR禁毒体验已经成为了一股新潮流。 三维网上展厅以数…

从《封神》中看动作捕捉对影视制作的作用

在电影《封神》中的角色雷震子不同于往常由真人演员化妆扮演&#xff0c;而是采用了动作捕捉技术&#xff0c;通过真人演员穿戴动作捕捉设备&#xff0c;实时动作捕捉数字角色进行演绎&#xff0c;让数字角色雷震子在电影中呈现出动作流畅、自然、形象逼真的精致画面效果&#…

果粉装机必备软件有哪些

作为一名从Windows全面切换到Mac的果粉&#xff0c;在一开始的时候确实感到诸多不便&#xff0c;比如文件管理器操作别扭&#xff0c;鼠标移动不够跟手等等。 后来才发现&#xff0c;除了游戏&#xff0c;大多数问题都能用软件来解决。Mac虽然小众&#xff0c;但是用户群体有很…

VScode : 过程试图写入的管道不存在

前言 由于这个问题比较常见&#xff0c;所以想记录一下。以下记录的问题都是我自己遇到的比较多的问题以及解决方案。 常见问题和解决方案 问题1.网段不一样 解决方案&#xff1a;通常服务器的网段是内网&#xff0c;自己如果远程连接&#xff0c;需要挂v&#xff0c;p&…

Azure Kinect DK使用教程

作者&#xff1a; Herman Ye Galbot Auromix 版本&#xff1a; V1.0 测试环境&#xff1a; Ubuntu20.04 更新日期&#xff1a; 2023/08/08 注1&#xff1a; 本文内容中的硬件由 Galbot 提供支持。 注2&#xff1a; Auromix 是一个机器人爱好者开源组织。 注3&#xff1a; 本文在…

安全防御(3)

1.总结当堂NAT与双机热备原理&#xff0c;形成思维导图 2.完成课堂nat与双机热备试验 引用IDS是指入侵检测系统&#xff0c;它可以在网络中检测和防御入侵行为。IDS的签名是指根据已知入侵行为的特征制定的规则&#xff0c;用于检测和警告可能存在的入侵行为。签名过滤器可以根…

怎么理解linux内核栈?

内核栈有不同含义。一是内核线程使用的栈&#xff0c;比如初始化线程&#xff0c;idle&#xff0c;kthread&#xff0c;这些仅在内核空间运行&#xff0c;只有内核栈&#xff0c;没有用户态以及用户空间栈。还有就是用户线程发生中断&#xff0c;系统调用进入内核态时候使用的栈…

linux下.run安装脚本制作

1、安装文件(install.sh) PS: .run安装包内部执行脚本文件 2、资源文件(test.zip) PS: 待安装程序源文件 3、制作.run脚本(install.run) cat install.sh test.zip > install.run chmod ax install.run

【单片机】DS2431英文手册,中文手册,翻译

DS2431是一款1024位的1-Wire EEPROM芯片&#xff0c;以每个256位的四个内存页面组织。数据被写入8字节的暂存区&#xff0c;经过验证&#xff0c;然后复制到EEPROM存储器中。作为一个特殊功能&#xff0c;四个内存页面可以单独地被写保护&#xff0c;或者被置于EPROM仿真模式&a…

ETHERCAT转CANOPEN协议网关canopen分类

1.产品功能 JM-ECT-COP是自主研发的一款 ETHERCAT 从站功能的通讯网关。该产品主要功能是将 ETHERCAT 网络和 CANOPEN 网络连接起来。 本网关连接到 ETHERCAT 总线中做为从站使用&#xff0c;连接到 CANOPEN 总线中做为主站使用。 3.技术参数 ETHERCAT 技术参数 网关做为 E…

【论文阅读】基于深度学习的时序异常检测——TransAD

系列文章链接 数据基础&#xff1a;多维时序数据集简介 论文一&#xff1a;2022 Anomaly Transformer&#xff1a;异常分数预测 论文二&#xff1a;2022 TransAD&#xff1a;异常分数预测 论文链接&#xff1a;TransAD.pdf 代码库链接&#xff1a;https://github.com/imperial…

openGauss学习笔记-34 openGauss 高级数据管理-SCHEMA

文章目录 openGauss学习笔记-34 openGauss 高级数据管理-SCHEMA34.1 语法格式34.2 参数说明34.3 示例 openGauss学习笔记-34 openGauss 高级数据管理-SCHEMA SCHEMA又称作模式。通过管理SCHEMA&#xff0c;允许多个用户使用同一数据库而不相互干扰&#xff0c;可以将数据库对象…

1706. 球会落何处;875. 爱吃香蕉的珂珂;1914. 循环轮转矩阵

1706. 球会落何处 核心思想&#xff1a;判断什么时候球会被卡住&#xff0c;1&#xff0c;当球在最左边的时候&#xff0c;挡板是向左的。2&#xff0c;当球在最右边的时候&#xff0c;挡板是向右的。3&#xff0c;当球当前的挡板是向左的&#xff0c;但是同一行的另一个挡板是…

模仿火星科技 基于cesium+ 贴地测量+可编辑

当您进入Cesium的编辑贴地测量世界&#xff0c;下面是一个详细的操作过程&#xff0c;帮助您顺利使用这些功能&#xff1a; 1. 创建提示窗&#xff1a; 启动Cesium应用&#xff0c;地图场景将打开&#xff0c;欢迎您进入编辑模式。在屏幕的一角&#xff0c;一个友好的提示窗将…