首页 > 编程语言 >15.C++STL 2(string类的使用,6000字详解)

15.C++STL 2(string类的使用,6000字详解)

时间:2024-11-23 17:58:40浏览次数:12  
标签:字符 15 string 6000 s1 字符串 include size

⭐本篇重点:string类的使用

⭐本篇代码:c++学习/05.string类的学习 · 橘子真甜/c++-learning-of-yzc - 码云 - 开源中国 (gitee.com)

一. C/C++字符与string类

        我们知道,C语言提供的字符串都是以'\0'为结尾的,在C语言中,库函数给我们提供了很多字符串函数,比如strlen(计算长度), strcmp(比较字符), strcpy(字符串拷贝), strstr(判断是否有子串), strcat(字符串追加)。这些函数可以帮助我们方便的管理字符串。

        但是在C++中,这些库函数和类分离,不符合OOP思想。并且字符串的底层需要我们自己去管理,容易越界。

        为了更方便的管理和操作字符串,C++ STL为我们提供了string类。string类为我们提供了更为丰富的接口和操作提供我们使用

二. STL中的string类的使用

        我们可以在这个文档中查找string类的信息:string文件介绍

//使用string所需头文件
#include <string>

//string包含在std命名空间中

2.1 string类常见的构造与赋值

常见构造方式如下表

构造方式解释
 string()构造空的string类对象,即空字符串
 string(const string&s)拷贝构造函数
 string(const string&s, size_t pos, size_t len = npos)

从另一个string对象 pos位置后一个字符开始拷贝,拷贝n个字符

如果没指定n,默认拷贝到结尾

 string(const char* s)用C语言字符串构造一个string对象
 string(size_t n, char c)构造一个含n个c字符的string对象
 string(const char* s, size_t n)构造一个string对象,包含s的前n个字符

测试代码如下:

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

int main()
{
	string s1; //定义一个string空对象
	string s2("hello world!");  //应该为 "hello world"
	string s3(s2);				//应该为 "hello world"
	string s4(s2, 2);			//应该是"llo world!"

	string s5(5, 'a');			//应该是"aaaaa"
	string s6("123456", 4);		//应该是"1234"

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

运行结果如下:

 赋值方法如下

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

int main()
{
	string s1 = "hello world";
	string s2 = s1;
	string s3;
	s3 = s1;

	cout << s1 << endl << s2 << endl << s3 << endl;
	return 0;
}

2.2 string对象的数据容量操作

string类中给我们提供了很多函数接口

函数名称功能介绍
size()返回这个字符串的有效元素长度
length()返回这个字符串的有效字符长度(这个和size功能一样)
capacity()返回字符串空间的大小
empty()判断string对象是否为空
clear()清空一个string对象,置空。不会改变底层容量

resize(size_t n)

resiize(size_t, char c)

将有效字符变为n个,多余空间是空字符,空间不够会扩容

将有效字符变为n个,多出的空间置为字符c。空间不够会扩容

如果是减少字符,不会减少底层空间

reverse(size_t n = 0)

为字符串预留n个空间。实际上,编译器会给我们提供的空间会大于n。防止越界访问的问题。

如果n小于当前容量,不会减少容量

测试代码1

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

int main()
{
	string s1 = "hello world!";
	cout << "s1的有效字符" << s1.size() << endl;
	cout << "s1的长度" << s1.length() << endl;
	cout << "s1的最大容量" << s1.capacity() << endl;

	if (s1.empty())
		cout << "s1为空" << endl;
	else
		cout << "s1为不为空" << endl;

	s1.clear();//清空有效字符,清空字符不会更改其最大容量
	cout << "s1的有效字符" << s1.size() << endl;
	cout << "s1的最大容量" << s1.capacity() << endl;

	return 0;
}

运行结果如下:

 测试代码2:

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

int main()
{
	string s1; "hello world!";
	cout << "s1的最大容量" << s1.capacity() << endl;
	s1.reserve(100);//将容量设置为100,不修改里面的内容1
	cout << "s1的最大容量" << s1.capacity() << endl;
	s1.reserve(250); // 实际设置的空间大于250
	cout << "s1的最大容量" << s1.capacity() << endl;

	string s2;
	s2.resize(100); //resize也会扩容

	string s3;
	s3.resize(100, '$');
	cout << s2 << endl;
	cout << s3 << endl;
	return 0;
}

2.3 string对象的遍历和访问操作(读写操作)

1 可以直接使用cout输出

2 可以使用类似数组的[]进行访问

3 使用迭代器访问

3 范围for 

operator []访问和范围for

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

int main()
{
	string s1 = "0123456789";
	//1 直接输出
	cout << s1 << endl;

	//2 使用类似数组的[]遍历访问,也能够修改
	//遍历
	for (int i = 0; i < s1.size(); i++)
	{
		cout << s1[i] << " ";
	}
	cout << endl;
	//修改
	for (int i = 0; i < s1.size(); i++)
	{
		s1[i] += 1;
	}


	//3.使用范围for
	for (const auto& c : s1)
	{
		cout << c << " ";
	}
	cout << endl;

	return 0;
}

运行结果如下

迭代器访问 

迭代器访问可以分为正向迭代器访问和逆向迭代器访问。

测试代码:

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

int main()
{
	string s1 = "0123456789";

	//正向迭代器,string::iterator表示的是string类的迭代器
	string::iterator sit = s1.begin();
	while (sit != s1.end())
	{
		//解引用一个迭代器,即可找到这个位置的元素,可以访问和修改这个元素
		cout << *sit << " "; 
		sit++;
	}
	cout << endl;

	//反向迭代器,可以逆向访问和修改容器元素
	string::reverse_iterator rsit = s1.rbegin();
	while (rsit != s1.rend())
	{
		cout << *rsit << " ";
		rsit++;
	}
	cout << endl;

	return 0;
}

测试结果如下:

2.4 string的修改操作

a 插入删除操作 *

函数

说明
push_back(char c)在字符串结尾插入字符c
append在字符串结尾追加一个字符串

operator+=

operator-=

在字符串结尾追加一个字符/字符串

在字符串结尾删除一个字符/字符串

insert(size_t pos, const string& s)

erase(size_t pos, size_t len = npos)

在pos位置后面插入字符或者字符串

在pos位置删除n个字符,默认删除到结尾

operator + 

同理可以在结尾加上一个字符/字符串。但是这个没有使用引用

效率没有+=高

一般建议使用+=这个重载,简单实用且效率较高

测试代码如下

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

int main()
{
	string s1;
	s1 += '1';			//1
	s1 += "23";			//123
	s1.append("45");	//12345	
	s1.push_back('6');	//123456
	cout << s1 << endl;


	string s2;
	s2.insert(s2.begin(), '0'); //0
	s2.insert(0, "1234");       //12340
	cout << s2 << endl;

	s2.erase(2);				//12
	cout << s2 << endl;     
	return 0;
}

b 函数c_str

该函数用于将string类转换成为一个C式字符串

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

int main()
{
	string s1 = "hello world!";
	const char* s2 = s1.c_str();
	cout << s2 << endl;
	return 0;
}

c 函数find和函数substr

find用于查找字符,函数原型如下,C式字符串,string对象,单个字符都能找

找到后返回其起始下标

找不到返回npos

size_t find (char c, size_t pos = 0) const
size_t find (const char* s, size_t pos = 0) const
size_t find (const string& str, size_t pos = 0)

还有 rfind用于从pos位置开始向前查找(用法find一样)

测试代码如下:

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

int main()
{
	//find
	string s1 = "123456@qq.com";
	string s2 = "qq";
	size_t pos1 = s1.find('@');		//单个字符c
	size_t pos2 = s1.find('.');		//单个字符c
	size_t pos3 = s1.find("com");	//C字符串
	size_t pos4 = s1.find(s2);		//string对象
	size_t pos5 = s1.find("yzc");	//找不到

	cout << "pos1:" << pos1 << endl;
	cout << "pos2:" << pos2 << endl;
	cout << "pos3:" << pos3 << endl;
	cout << "pos4:" << pos4 << endl;
	cout << "pos5:" << pos5 << endl;


	return 0;
}

运行结果 

substr用于取字串

 函数原型如下:从pos开始取字串(默认0位置),如果len没有指定,默认从pos位置取到结尾处

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

测试代码

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

int main()
{
	string s1 = "123456@qq.com";
	size_t pos1 = s1.find('@');		//单个字符c
	size_t pos2 = s1.find('.');		//单个字符c

	//substr获取pos位置后的子串
	string s2 = s1.substr(pos1);
	string s3 = s1.substr(pos2);
	cout << "s2:" << s2 << endl;	//结果应该为 @qq.com
	cout << "s3:" << s3 << endl;	//结果应该为 .com

	//可以连续获取子串,我们想要获取456
	string s4 = "123@456@789";

	size_t pos3 = s4.find('@');
	cout << s4.substr(pos3) << endl;			//获取@456@789
	int len = s4.substr(pos3 + 1).find('@');	//计算4到下一个@之间的长度
	
	string ans = s4.substr(pos3 + 1, len);
	cout << ans << endl;    //应该为456

	return 0;
}

测试结果 

三. string的简单应用-分离网站的协议/域名/资源

我们使用string分离网站的 协议,域名,资源

比如我的gitte 网站:橘子真甜 (yzc-YZC) - Gitee.com

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

void Test(const string& url)
{
	cout << "网站" << url << endl;
	// 1.分离协议
	size_t index1 = url.find(':');
	if (index1 != string::npos)
	{
		cout << "协议:" << url.substr(0, index1) << endl;;
	}

	//分离资源
	size_t index2 = url.find('/', index1 + 3);
	if (index2 != string::npos)
	{
		cout << "域名:" << url.substr(index1 + 3, index2 - (index1 + 3)) << endl;
	}

	//分离资源
	cout << "资源:" << url.substr(index2 + 1) << endl << endl;
}

//分离网站
int main()
{
	//我们知道网站可以分为3部分,实用string类可以将这3部分分离
	//1 协议		2 域名		3资源

	string url1 = "https://gitee.com/yzc-YZC";
	//协议 https 域名 gitee.com 资源 yzc-YZC

	Test(url1);

	string url2 = "https://mp.csdn.net/mp_blog/creation/editor/143991873?spm=1001.2014.3001.4503";
	Test(url2);
	return 0;
}

运行结果如下:

四. 下盘文章:string类的模拟实现 

标签:字符,15,string,6000,s1,字符串,include,size
From: https://blog.csdn.net/yzcllzx/article/details/143991873

相关文章

  • 掌握15个PHP8新特性 助你快速上手php
    1、命名参数:一种允许开发者通过参数名称而非位置顺序将参数传递给函数的特性。这种特性提供了更高的灵活性和可读性,使得函数调用更加清晰、直观。function greet($name, $age) {         echo "Hello $name, you are $age years old."; }  greet(age:......
  • 【问题描述】 教练给小智设定了一个每天锻炼的积分奖励计划。一天内,每锻炼15分钟,就能
    【问题描述】教练给小智设定了一个每天锻炼的积分奖励计划。一天内,每锻炼15分钟,就能获得1个体能积分。不足15分钟的锻炼时间被舍弃,不能获得积分。如果积分达到了7,这周就可以用积分来换一个奖品。编写一个程序来计算小智最快几天就能获得奖品。输入有一行,包含7个用空格隔开......
  • 基于MPC、PID、 ode15s的无人机开发模型预测控制研究(Matlab代码实现)
            ......
  • Java更新数据库报错:Data truncation: Cannot create a JSON value from a string with
    一、现象在Java中,使用mybatis-plus更新实体类对象到mysql,其中一个字段对应数据库中json数据类型,更新时报错:Datatruncation:CannotcreateaJSONvaluefromastringwithCHARACTERSET'binary'.​‍报错信息:Cause:com.mysql.cj.jdbc.exceptions.MysqlDataTruncation:......
  • 美团面试:String 为什么 不可变 ?(90%答错了,尼恩来一个绝世答案)
    本文原文链接文章很长,且持续更新,建议收藏起来,慢慢读!疯狂创客圈总目录博客园版为您奉上珍贵的学习资源:免费赠送:《尼恩Java面试宝典》持续更新+史上最全+面试必备2000页+面试必备+大厂必备+涨薪必备免费赠送:《尼恩技术圣经+高并发系列PDF》,帮你实现技术自由,完......
  • 802.15.4 WPAN协议-扫描、同步、入网和退网等消息流程
    802.15.4WPAN协议-扫描、同步、入网和退网等消息流程文章目录一、原语二、消息流程1.接收超帧和发送超帧的时序2.能量检测(ED)信道扫描3.主动扫描和被动扫描3.1主动扫描3.2被动扫描4.启动PAN网络5.重组PAN网络6.入网过程7.退网过程8.同步过程一、原......
  • 推荐15个 Vue 常用自定义指令,含实现原理与使用方式
    前言Vue.js是一个流行的前端框架,它的核心理念是通过指令(Directives)来扩展HTML的能力。尽管Vue.js已经内置了一些非常实用的指令(比如v-if,v-show,v-for等),但有时候我们还是需要创建自定义指令来满足特定的需求。今天我们就来聊聊Vue常用的自定义指令,它们能让你的......
  • 150份Java计算机毕业设计项目推荐(源码+论文+PPT)
    2024最新Java项目选题推荐哈喽,大家好,大四的同学马上要开始做毕业设计了,大家做好准备了吗?博主给大家详细整理了150个Java项目选题推荐,有什么疑问可在评论区留言哦!需要链接请私信我哦!或者在评论区打出来!02:基于Java+springboot的报名系统03:基于Java+springboot的培训管理系统......
  • 基于KU115+ZU19EG+C6678 的高性能6U VPX 载板
    基于KU115+ZU19EG+C6678的高性能6UVPX载板,板载2个HPC形式的FMC连接器(用于外部信号扩展)。板卡选用了1片Xilinx公司的KintexUltraScale系列FPGA家族中的XCKU115-2FLVA1517I和1片ZynqUltraScale+MPSoC家族的XCZU19EG-2FFVC1760I以及1片TI公司的DSP芯片T......
  • STM32第15章 RCC-使用HSE/HSI配置时钟
    时间:2024.10.21-10.23参考资料:《零死角玩转STM32》“RCC-使用HSE/HIS配置时钟”章节TIPS:从前面的历程中我们知道,程序在启动的时候会执行汇编文件,汇编文件里会调用System_Init(固件库编程的函数),它里面会把时钟初始化成72M,因此前面我们在用固件库写程序的时候,有关时钟这一部......