【C++】string进一步介绍

个人主页 : zxctscl
如有转载请先通知

文章目录

  • 1. 前言
  • 2. 迭代器
    • 2.1 反向迭代器
    • 2.2 const对象迭代器
  • 3. Capacity
    • 3.1 size和length
    • 3.2 max_size
    • 3.3 capacity
    • 3.4 clear
    • 3.5 shrink_to_fit (了解即可)
    • 3.6 reserve
    • 3.7 resize
  • 4. Element access
    • 4.1 operator[]
    • 4.2 at
  • 5. Modifiers
    • 5.1 push_back
    • 5.2 append
    • 5.3 operator+=
    • 5.4 assign(了解即可)
    • 5.5 insert
    • 5.6 erase
    • 5.7 replace
    • 5.8 swap
  • 6. String operations
    • 6.1 c_str
    • 6.2 find 和 substr
    • 6.3 rfind
    • 6.4 compare
  • 7. Non-member function overloads
    • 7.1 operator+
    • 7.2 getline

1. 前言

在之前的博客中初步介绍了string一下: 【C++】string类初步介绍,那么这次来看看它的实现。

2. 迭代器

string类对象的访问及遍历操作:

函数名称功能说明
operator[] (重点)返回pos位置的字符,const string类对象调用
begin+ endbegin获取一个字符的迭代器 + end获取最后一个字符下一个位置的迭代器
范围forC++11支持更简洁的范围for的新遍历方式
rbegin + rendrbegin反向迭代器以反向开始,end将迭代器返回到末尾

2.1 反向迭代器

在前面的一篇中已经提到了前面三个,这次来看看反向迭代器。
reverse_iterator:将给的字符串反向逆置。
在这里插入图片描述

void test_string3()
{
	string s1("hello,world");
	string::reverse_iterator rit = s1.rbegin();
	while (rit != s1.rend())
	{
		cout << *rit <<" ";
		rit++;
	}
	cout << endl;


}

在这里插入图片描述
rbegin给rit,rit!=rend,然后加加rit。它本身就是反过来的,所以得用加加。
在这里插入图片描述
在这里插入图片描述

2.2 const对象迭代器

在这里插入图片描述
这里还有const对象的迭代器,他们两个有什么区别呢?
const要用const迭代器(const_iterator),不能修改对象值。

在这里插入图片描述

**iterator是可读可写,const_iterator只读。**会根据自己属性去调用。

string::iterator it2 = s1.begin();
	while (it2 != s1.end())
	{
		*it2 += 3;
		cout << *it2 << " ";
		it2++;
	}
	cout << endl;
	
const string s3("hello world");
	string::const_iterator it3 = s3.begin();
	while (it3 != s3.end())
	{
		cout << *it3 << " ";
		it3++;
	}
	cout << endl;

在这里插入图片描述
在这里插入图片描述

rbegin同样有两种。
在这里插入图片描述
在这里插入图片描述
总共有四种迭代器:正向反向iterator,和正向反向const_iterator。用到最多是正向iterator。

3. Capacity

在这里插入图片描述

3.1 size和length

这里的size和length有什么区别呢?
直接用代码来测试一下:

void test_string4()
{
	string s1("hello world");
	cout << s1.size() << endl;
	cout << s1.length() << endl;
}

在这里插入图片描述
很显然,它们没有区别。有两个的原因是:string产生得比较早,没有出数据结构规范,在字符串长度取名字时候取的是length,后来stl出来之后,就增加了一个size。length是一个局限的取名,用size更统一。C++是两种都是兼容的。

3.2 max_size

在x86环境下来看看max_size有多大:

在这里插入图片描述
但是不同平台的max_size可能有所不同。

3.3 capacity

在这里插入图片描述

来看看capacity大小:
发现会比size要大
在这里插入图片描述
在这里插入图片描述
来看看string的扩容机制:
先取string当前的capacity,然后push_back,如果空间不够可能会引起capacity的变换;每次插入前获取新的capacity和旧的相比较看看相不相等,如果不相等,就把新的capacity赋值给旧的,并输出新的capacity。

    string s;
	size_t sz = s.capacity();
	cout << "making s grow:\n";
	cout << sz << endl;
	for (int i = 0; i < 100; ++i)
	{
		s.push_back('c');
		if (sz != s.capacity())
		{
			sz = s.capacity();
			cout << "capacity changed: " << sz << '\n';
		}
	}

第一次扩容的是原基础的2倍,剩下的都是1.5倍
在这里插入图片描述
在这里插入图片描述

与linux的扩容机制是不同的。
来看看linux的扩容机制:
在这里插入图片描述
g++扩容是两倍扩:
在这里插入图片描述
STL是一个规范,规定功能,没有规定实现细节。

3.4 clear

在这里插入图片描述

clear是指的清数据,空间不一定清理:

string s1("hello world");
	cout << s1.size() << endl;
	cout << s1.length() << endl;
	cout << s1.capacity() << endl;
	
	cout << s1 << endl;
	cout << s1.capacity() << endl;

	s1.clear();
	cout << s1 << endl;
	cout << s1.capacity() << endl;

capacity并没有改变。
在这里插入图片描述

就算将s1多输入字符,它的的capacity在clear后也不会改变;
在这里插入图片描述

3.5 shrink_to_fit (了解即可)

如果想要缩容用就要用shrink_to_fit :
在这里插入图片描述

string s1("hello worldxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
	cout << s1.size() << endl;
	cout << s1.length() << endl;
	cout << s1.capacity() << endl;
	
	cout << s1 << endl;
	cout << s1.capacity() << endl;
	cout << s1.size() << endl;

	s1.clear();
	cout << s1 << endl;
	cout << s1.capacity() << endl;
	cout << s1.size() << endl;

	s1.shrink_to_fit();
	cout << s1 << endl;
	cout << s1.capacity() << endl;
	cout << s1.size() << endl;

这里缩容到15
在这里插入图片描述

3.6 reserve

注意区分:
reserve是保留
reverse是反转,翻转

reserve是用来扩容的。
在这里插入图片描述

string s;
	s.reserve(100);
	size_t sz = s.capacity();
	cout << "making s grow:\n";
	cout << sz << endl;
	
	for (int i = 0; i < 100; ++i)
	{
		s.push_back('c');
		if (sz != s.capacity())
		{
			sz = s.capacity();
			cout << "capacity changed: " << sz << '\n';
		}
	}

在这里插入图片描述
在linux里面:
在这里插入图片描述
在这里插入图片描述
reserve会不会缩容呢?
来看看代码:

string s1("hello worldxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
	cout << s1.size() << endl;
	cout << s1.capacity() << endl;

	s1.reserve(20);
	cout << s1.size() << endl;
	cout << s1.capacity() << endl;

reserve是不会缩容的。
reserve比capacity大才扩容。
在这里插入图片描述

3.7 resize

resize改变size。
在这里插入图片描述

resize有三种情况。

resize从三个角度来对它进行分析:
假设这里size是17,capacity是32
在这里插入图片描述

  1. resize给的比size小,会删除
string s2("hello worldxxxx");
	cout << s2.size() << endl;
	cout << s2.capacity() << endl;
	s2.resize(10);

	cout << s2.size() << endl;
	cout << s2.capacity() << endl;

在这里插入图片描述

  1. resize给的在size和capacity之间,插入
   string s2("hello worldxxxx");
	cout << s2.size() << endl;
	cout << s2.capacity() << endl << endl;
	/*s2.resize(10);*/
	s2.resize(20);

	cout << s2.size() << endl;
	cout << s2.capacity() << endl;

默认插入\0
在这里插入图片描述

  1. resize给的比capacity大,扩容+插入

在这里插入图片描述

在这里插入图片描述
总之:
在这里插入图片描述
所以知道要插入多少数据,就提前开好空间,避免了扩容,提高了效率。

4. Element access

在这里插入图片描述

4.1 operator[]

在上一篇博客中已经提过了,有需要可以看看【C++】string类初步介绍
在这里插入图片描述
在用[]越界是断言错误:在这里插入图片描述

4.2 at

在这里插入图片描述

    string s1("hello world");
	cout << s1[6] << endl;
	cout << s1.at(6)<< endl;

在这里插入图片描述
at与[]的越界报错不一样
用at越界时候报的是非法在这里插入图片描述

5. Modifiers

5.1 push_back

尾插一个字符
在这里插入图片描述
想尾插一个字符:

void test_string7()
{
	string s1("hello world");
	s1.push_back('!');
	cout << s1 << endl;
}

在这里插入图片描述

5.2 append

append尾插,可以插入一个字符,也可以插入字符串。
在这里插入图片描述

    string s1("hello world");
	/*s1.push_back('!');*/

	s1.append("!");
	cout << s1 << endl;

	s1.append("abcd");
	cout << s1 << endl;

在这里插入图片描述

在这里插入图片描述
一般用得最多的就是:
在这里插入图片描述

5.3 operator+=

+=用起来就比较方便

来看个例子:

   string s1("hello world");
	s1 += ' ';
	s1 += "abc";
	cout << s1 << endl;

在这里插入图片描述

5.4 assign(了解即可)

assign赋值,字符覆盖在这里插入图片描述

可以把当前字符覆盖:

	string s1("hello world");
	cout << s1 << endl;

	s1.assign("xxxxx");
	cout << s1 << endl;

在这里插入图片描述

5.5 insert

insert都是在当前位置的前面插入
在这里插入图片描述
常用的就是:
在这里插入图片描述
举个例子:

string s1("hello world");
	cout << s1 << endl;

	s1.insert(0, "abc");
	cout << s1 << endl;

在这里插入图片描述

5.6 erase

erase删除
在这里插入图片描述
常用:
在这里插入图片描述
如果这个内容太短小于npos,就全部删除。

举个例子:

string s1("hello world");
	cout << s1 << endl;

	/*s1.insert(0, "abc");*/

	s1.erase(5,10);
	cout << s1 << endl;

在这里插入图片描述
erase不给值就直接删空了:
在这里插入图片描述

5.7 replace

replace替换
在这里插入图片描述

把pos位置,一个字符替换成两个xx:

    string s2("hello world");
	cout << s2 << endl;
	s2.replace(6, 1, "xx");
	cout << s2 << endl;

在这里插入图片描述

一般结合find()使用:
在这里插入图片描述

在这里插入图片描述
来看个代码:

string s2("hello world hello abcd");

	size_t pos = s2.find(' ');
	while (pos != string::npos)
	{
		s2.replace(pos, 1, "%20");
		pos = s2.find(' ');
	}
	cout << s2 << endl;

在这里插入图片描述
insert erase replace要少用,因为基本上都要挪动数据,效率不高。

像替换这里还可以用范围for:

string s3;
	for (auto ch : s2)
	{
		if (ch != ' ')
		{
			s3 += ch;
		}
		else
		{
			s3 += "%20";
		}
	}
	cout << s3 << endl;

在这里插入图片描述

5.8 swap

在这里插入图片描述
来看一个例子:把空格位置换成20%:

void test_string9()
{
    string s2("hello world hello abcd");
	string s3;
	s3.reserve(s2.size());
	for (auto ch : s2)
	{
		if (ch != ' ')
		{
			s3 += ch;
		}
		else
		{
			s3 += "20%";
		}
	}
	cout << s3 << endl;
	s2.swap(s3);
	cout << s2 << endl;
}

在这里插入图片描述

6. String operations

在这里插入图片描述

6.1 c_str

在C语言中有打开文件的操作,在c++里面要打开文件就要用到c_str,让它来兼容C语言。
在这里插入图片描述
来个例子:

void test_string10()
{
	string s1("hello world");
	string filename("test.cpp");
	FILE* fout = fopen(filename.c_str(), "r");

}

6.2 find 和 substr

find查找
在这里插入图片描述

substr去一个字符串的字串。

在这里插入图片描述
如果想要拿到一个文件的后缀,就用find,但要将后缀拷贝下来就得用到substr。
来看看简单的实现:

void test_string10()
{
	string s1("file.cpp");
	size_t pos1= s1.find('.');
	if (pos1 != string::npos)
	{
		string suffix = s1.substr(pos1);
		cout << suffix << endl;
	}
	else
	{
		cout << "没有后缀" << endl;
	}
}

在这里插入图片描述
在这里插入图片描述

6.3 rfind

如果查最后一个序列怎么办呢?
用rfind,从后往前找
在这里插入图片描述

void test_string10()
{
	string s1("file.cpp.tar.zip");
	size_t pos1= s1.rfind('.');
	if (pos1 != string::npos)
	{
		string suffix = s1.substr(pos1);
		cout << suffix << endl;
	}
	else
	{
		cout << "没有后缀" << endl;
	}
}

在这里插入图片描述
在这里插入图片描述
如果给的网站很多怎么按协议,域名,网址分开呢?
在这里插入图片描述
协议到:,域名从i+3的位置开始,到第一个/就结束。网址就是剩下的部分

void test_string10()
{
    string url1("https://legacy.cplusplus.com/reference/string/string/substr/");
	string protocol, domain, uri;//协议,域名,网址
	size_t i1 = url1.find(':');
	if (i1 != string::npos)
	{
		protocol = url1.substr(0, i1 - 0);
		cout << protocol << endl;
	}

	size_t i2 = url1.find('/',i1+3);
	if (i2 != string::npos)
	{
		domain = url1.substr(i1+3, i2-(i1+3));
		cout << domain << endl;

		uri = url1.substr(i2+1);
		cout << uri << endl;
	}
}

在这里插入图片描述

6.4 compare

compare是按照ascii比较
在这里插入图片描述

    string str1("green apple");
	string str2("red apple");

	cout << (str1 < str2) << endl;

	

r的ASCII比g的ASCII小:
在这里插入图片描述

7. Non-member function overloads

在这里插入图片描述

7.1 operator+

在这里插入图片描述
来用代码实现一下:

    string ss1 = "xxx";
	string ss2 = "yyy";
	string ret = ss1 + ss2;
	cout << ret << endl;

在这里插入图片描述

还支持这样的写法:

   string ret1 = ss1 + "yyy";
	string ret2 =  "yyy"+ss2;
	cout << ret1 << endl;
	cout << ret2 << endl;

在这里插入图片描述
在这里插入图片描述

7.2 getline

getline获取一行。
在这里插入图片描述
举个例子:获得一个字符串里面最后一个单词的长度

#include<iostream>
#include<string>
using namespace std;
int main()
{
	string line;
	// 不要使用cin>>line,因为会它遇到空格就结束了
	// while(cin>>line)
	while (getline(cin, line))
	{
		size_t pos = line.rfind(' ');
		cout << line.size() - pos - 1 << endl;
	}
	return 0;
}

有问题请指出,大家一起进步!!!

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

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

相关文章

一台服务器部署两个独立的mysql实例

&#x1f341;博主简介&#xff1a; &#x1f3c5;云计算领域优质创作者 &#x1f3c5;2022年CSDN新星计划python赛道第一名 &#x1f3c5;2022年CSDN原力计划优质作者 &#x1f3c5;阿里云ACE认证高级工程师 &#x1f3c5;阿里云开发者社区专…

STM32平替GD32有多方便

众所周知, GD32一直模仿STM32,从未被超越。 我最近公司使用的GD32E230C6T6 这款芯片有48个引脚。 属于小容量的芯片。 我有一个用STM32写的代码,之前是用的 STM32F103CB 这款芯片是中容量的。 不过在keil中,只需要这两步,就能使用原来的逻辑,几乎不用修改代码。 1. …

【Swing】Java Swing实现省市区选择编辑器

【Swing】Java Swing实现省市区选择编辑器 1.需求描述2.需求实现3.效果展示 系统&#xff1a;Win10 JDK&#xff1a;1.8.0_351 IDEA&#xff1a;2022.3.3 1.需求描述 在公司的一个 Swing 的项目上需要实现一个选择省市区的编辑器&#xff0c;这还是第一次做这种编辑器&#xf…

【数据结构】二叉树OJ题目

965. 单值二叉树 如果二叉树每个节点都具有相同的值&#xff0c;那么该二叉树就是单值二叉树。 只有给定的树是单值二叉树时&#xff0c;才返回 true&#xff1b;否则返回 false。 示例 1&#xff1a; 输入&#xff1a;[1,1,1,1,1,null,1] 输出&#xff1a;true示例 2&#x…

考研复试C语言篇

第一章 概述 1.1什么是程序 为了让计算机执行某些操作或解决某个问题而编写的一系列有序指令的合集。 1.4C语言的特点 代码级别的跨平台&#xff1a;由于标准的存在&#xff0c;使得几乎同样的C代码可用于多种操作系统&#xff0c;也适用于多种机型。使允许直接访问物理地址…

Java基础 - 9 - 集合进阶(一)

集合是一种容器&#xff0c;用来装数据的&#xff0c;类似于数组&#xff0c;但集合的大小可变&#xff0c;开发中非常常用 为了满足不同的业务场景需求&#xff0c;Java除了ArrayList还提供了很多不同特点的集合给我们选择 一. 集合的体系结构 集合可以分为两类&#xff1a;…

案例--某站视频爬取

众所周知&#xff0c;某站的视频是&#xff1a; 由视频和音频分开的。 所以我们进行获取&#xff0c;需要分别获得它的音频和视频数据&#xff0c;然后进行音视频合并。 这么多年了&#xff0c;某站还是老样子&#xff0c;只要加个防盗链就能绕过。&#xff08;防止403&#xf…

Git之版本回退

文章转载于&#xff1a;https://www.jianshu.com/p/3020740561a8 以前&#xff0c;如果是要去除某一块功能&#xff0c;我都是选择性删除&#xff0c;选择性注释&#xff0c;然后前后逻辑各种查看&#xff0c;各种比较。每一次&#xff0c;改完这些我总感觉心好累啊&#xff01…

Prompt进阶3:LangGPT(构建高性能质量Prompt策略和技巧2)--稳定高质量文案生成器

Prompt进阶3:LangGPT(构建高性能质量Prompt策略和技巧2)–稳定高质量文案生成器 1.LangGPT介绍 现有 Prompt 创建方法有如下缺点&#xff1a; 缺乏系统性&#xff1a;大多是细碎的规则&#xff0c;技巧&#xff0c;严重依赖个人经验缺乏灵活性&#xff1a;对他人分享的优质 …

数据结构 day2

1:思维导图 2&#xff1a;计算结构体大小 3&#xff1a;大小端存储 &#xff08;1&#xff09;&#xff1a;数据溢出 1 #include <stdio.h>2 #include <string.h>3 #include <stdlib.h>4 int main(int argc, const char *argv[])5 {6 short a 0x1234;…

STM32输入捕获频率和占空比proteus仿真失败

这次用了两天的时间来验证这个功能&#xff0c;虽然实验没有成功&#xff0c;但是也要记录一下&#xff0c;后面能解决了&#xff0c;回来再写上解决的办法&#xff1a; 这个程序最后的实验结果是读取到的CCR1和CCR2的值都是0&#xff0c;所以没有办法算出来频率和占空比。 还…

FPGA - 单总线协议(one-wire)

1&#xff0c;简介 单总线&#xff08;one-wire&#xff09;是美国 DALLAS 公司推出的外围串行扩展总线技术&#xff0c;与 SPI、I2C 等串行数据通信方式不同&#xff0c;它采用单根信号线&#xff0c;既传输时钟又传输数据&#xff0c;而且数据传输是双向的。它具有节省 I/O口…

数据结构中的平衡搜索树 --- 红黑树 (如何旋转与变色)

目录 红黑树的概念 红黑树的性质 红黑树节点的定义 红黑树的插入 1. 按照二叉搜索的树规则插入新节点 2. 检测新节点插入后&#xff0c;红黑树的性质是否造到破坏 红黑树的概念 红黑树&#xff0c;是一种二叉搜索树&#xff0c;但在每个结点上增加一个存储位表示结点的颜…

基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的农作物害虫检测系统(深度学习模型+UI界面+训练数据集)

摘要&#xff1a;开发农作物害虫检测系统对于提高农业生产效率和作物产量具有关键作用。本篇博客详细介绍了如何运用深度学习构建一个农作物害虫检测系统&#xff0c;并提供了完整的实现代码。该系统基于强大的YOLOv8算法&#xff0c;并对比了YOLOv7、YOLOv6、YOLOv5&#xff0…

Linux——多线程

目录 线程概念 线程控制 线程创建 进程 vs 线程 线程异常 线程等待 线程终止 pthread_cancel 进程替换 线程分离 线程互斥 mutex mutex接口 mutex的理解 互斥锁的实现 可重入和线程安全 死锁 什么是死锁 死锁产生的必要条件 避免死锁 线程同步 概念 条件…

论坛管理系统|基于Spring Boot+ Mysql+Java+B/S架构的论坛管理系统设计与实现(可运行源码+数据库+设计文档+部署说明+视频演示)

推荐阅读100套最新项目 最新ssmjava项目文档视频演示可运行源码分享 最新jspjava项目文档视频演示可运行源码分享 最新Spring Boot项目文档视频演示可运行源码分享 目录 目录 前台功能效果图 管理员功能登录前台功能效果图 用户功能模块 系统功能设计 数据库E-R图设计 l…

webpack面试题

1、webpack是干什么的 Webpack是一个现代的JavaScript应用程序的静态模块打包工具。当webpack处理应用程序时&#xff0c;它会在内部构建一个依赖图&#xff0c;此依赖图对应映射到项目所需的每个模块&#xff0c;然后将所有这些模块打包成一个或多个bundle。Webpack的主要功能…

Java初阶数据结构队列的实现

1.队列的概念 1.队列就是相当于排队打饭 2.在排队的时候就有一个队头一个队尾。 3.从队尾进对头出 4.所以他的特点就是先进先出 所以我们可以用链表来实现 单链表实现要队尾进队头出{要有last 尾插头删} 双向链表实现效率高&#xff1a;不管从哪个地方当作队列都是可以的&…

HttpContext请求接收上下文模块设计与实现(http模块四)

目录 类功能 类定义 类实现 编译测试 类功能 类定义 // HttpContext接收请求上下文模块功能设计 typedef enum {RECV_HTTP_ERROR,RECV_HTTP_LINE,RECV_HTTP_HEAD,RECV_HTTP_BODY,RECV_HTTP_OVER } HttpRecvStatu;class HttpContext { private:int _resp_statu; …

Games101笔记-变换

Scale Reflection Shear Rotate 没有额外提示默认绕原点旋转 线性变换 Transiation 不属于线性变换&#xff0c;仿射变换 齐次坐标 二维的点和向量增加一个维度 点加点等于两个点的中点 所有的仿射变换都可以写成齐次坐标的形式 在表示二维情况下的仿射变换时&#…