【C++】STL之string

news2024/11/13 11:01:56

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言
  • string类的内部
      • 成员变量:
  • string的模拟实现
    • **六个默认成员函数**
    • **iterator**
    • **capacity**
    • **modify**
    • element access
    • **String operations**
    • Non-member function overloads


前言

本文将介绍如何实现string,从而提高对string类的理解


string类的内部

成员变量:

  1. 字符数组指针 - _str
  2. 大小 - _size
  3. 容量 - capacity
  4. 静态成员变量 npos
    在这里插入图片描述

在这里插入图片描述

string的模拟实现

六个默认成员函数

构造函数

string(const char* str = "")
			:_size(strlen(str))
			, _capacity(_size)
			, _str(new char[_capacity+1])
		{
			memcpy(_str, str, _size + 1);
		}

注意点:

  1. 未赋值的string,其实里面有\0 , 因此const char* str = ""
  2. 注意初始化列表的规则, 声明顺序对应初始化顺序
  3. 拷贝采用memset而不是strcpy,因为string里面的str中间可以有\0
    拷贝构造
string(const string& str)
		{
			_size = str._size;
			_capacity = str._capacity;
			_str = new char[_capacity];
			memcpy(_str, str._str, str._size + 1);
		}

析构函数

~string()
		{
			delete[] _str;
			_str = nullptr;
			_size = 0;
			_capacity = 0;
		}

赋值运算符重载

void swap(string& tmp)
		{
			std::swap(_str, tmp._str);
			std::swap(_size, tmp._size);
			std::swap(_capacity, tmp._capacity);
		}
		string& operator=(const string& str)
 		{
			if (this != &str)
			{
				string tmp(str);
				this->swap(tmp);
			}
			return *this;
		}
		//更简短的写法
		string& operator=(string tmp)
		{
			swap(tmp);
		}

iterator

string的迭代器是字符指针
typedef char* iterator
typedef const char* const_iterator

begin() - 字符数组的地址

iterator begin()
		{
			return _str;
		}
		const_iterator begin() const
		{
			return _str;
		}

end() - 字符数组地址 + size 即 ‘\0’

iterator end()
		{
			return _str + _size;
		}
		const_iterator end() const
		{
			return _str + _size;
		}

capacity

reserve
注意:
windows : 不能比原来的容量低
linux: 除非多余的空间无数据, 否则不能比size低

		void reserve(size_t n)
		{
			if (n > _capacity)
			{
				char* tmp = new char[n + 1];
				memcpy(tmp, _str, _size + 1);
				delete[] _str;
				_str = tmp;
				_capacity = n;
			}
		}

resize
注意:
window: 任意
linux:

		void resize(size_t n, char c = '\0')
		{
			if (n > _size)
			{
				if (n >= _capacity)
				{
					reserve(n + 4);
				}
				for (size_t i = 0; i < n; i++)
				{
					_str[i + _size] = c;
				}
				_size = n;
				_str[n] = '\0';
			}
			else
			{
				_size = n;
				_str[_size] = '\0';
			}
		}

modify

operator+=

		string& operator+=(char c)
		{
			if (_size == _capacity)
			{
				reserve(_capacity == 0 ? 4 : _capacity * 2);
			}
			_str[_size] = c;
			++_size;
			_str[_size] = '\0';
			return *this;
		}
		string& operator+=(const char* str)
		{
			size_t len = strlen(str);
			if (_size + len >= _capacity)
			{
				reserve(_size + len);
			}
			memcpy(_str + _size, str, len + 1);
			_size += len;
			return *this;
		}
		

注意:+=是需要返回本身

insert

		string& insert(size_t pos, size_t n, char c)
		{
			assert(pos <= _size);
			if (_size + n > _capacity)
			{
				reserve(_size + n);
			}
			//后移
			size_t end = _size;
			while (end >= pos && end != npos)
			{
				_str[end + n] = _str[end];
				--end;
			}
			for (size_t i = 0; i < n; i++)
			{
				_str[pos + i] = c;
			}
			_size += n;
			return *this;
		}
		string& insert(size_t pos, const char* str)
		{
			assert(pos <= _size);
			size_t len = strlen(str);
			if (_size + len > _capacity)
			{
				reserve(_size + len);
			}
			//后移
			size_t end = _size;
			while (end >= pos && end != npos)
			{
				_str[end + len] = _str[end];
				--end;
			}
			for (size_t i = 0; i < len; i++)
			{
				_str[pos + i] = str[i];
			}
			_size += len;
			return *this;
		}

注意:出现负数与无符号数的冲突
size_t end = _size; while (end >= pos && end != npos)
当pos = 0时,end会出现为-1的情况,但end为无符号数,因此end = max_size_t死循环

  1. 强转 - end >=(int)pos
  2. npos - size_t npos = -1, while(end >= pos && end != npos

element access

operator【】

//access
		char& operator[](size_t pos) 
		{
			assert(pos <= _size);
			return _str[pos];
		}
		const char& operator[](size_t pos) const
		{
			assert(pos <= _size);
			return _str[pos];
		}

有个典型错误:
reserve()之后, 直接访问。因为operator【】是看size

String operations

c_str

		const char* c_str() const
		{
			return _str;
		}

find

		size_t find(char c, size_t pos = 0)
		{
			assert(pos < _size);
			for (size_t i = pos; i < _size; i++)
			{
				if (_str[i] == c)
				{
					return i;
				}
			}
			return npos;
		}
		size_t find(const char* str, size_t pos = 0)
		{
			assert(pos < _size);
			const char* ptr = strstr(_str, str);
			if (ptr) return ptr - _str;
			else return npos;
		}

substr

		string substr(size_t pos = 0, size_t len = npos) const
		{
			assert(pos < _size);
			size_t n = len;
			if (len == npos || pos + len >= _size)
			{
				n = _size - pos;
			}
			string tmp;
			tmp.reserve(n);
			tmp._size = n;
			tmp[n] = '\0';
			memcpy(tmp._str, _str + pos, n);
			return tmp;
		}

Non-member function overloads

operator<<
标准:

  1. string的打印规则与字符串不一样,而是以size为终结
	std::ostream& operator<<(std::ostream& out, const sfw::string& str)
	{
		for (auto it : str)
		{
			out << it;
		}
		return out;
	}

operator>>
标准:

  1. 过滤前面的空格和换行
    注意:
  2. 流提取不会提取 ' ' 和 \n , 因此需使用输入流的成员函数get(),
  3. 每次提取会对原来进行覆盖
	std::istream& operator>>(std::istream& in, sfw::string& str)
	{
		str.clear();
		//清除缓冲区
		char c = in.get();
		while(!(c != '\n' && c != ' '))
		{
			c = in.get();
		}
		//读取,分批次读取
		char bag[128];
		int i = 0;
		while (c != '\n' && c != ' ')
		{
			bag[i++] = c;
			if (i == 127)
			{
				bag[i] = '\0';
				str += bag;
				i = 0;
			}
			c = in.get();
		}
		if (i)
		{
			bag[i] = '\0';
			str += bag;
		}
		return in;
	}

relation operator
注意:
对于比较 : 只用写出 == 以及 >(<), 其余根据逻辑关系调用就可以了

//operator==
bool operator==(const string& str) const
		{
			if (_size != str._size) return false;
			size_t i = 0;
			while (i < _size)
			{
				if (_str[i] != str._str[i]) return false;
				i++;
			}
			return true;
		}
//operator>
bool operator>(const string& str) const
		{
			size_t sz = min(str._size, _size);
			for (size_t i = 0; i < sz; i++)
			{
				if (_str[i] > str._str[i]) return true;
			}
			return _size > str._size;
		}

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

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

相关文章

分布式id的概述与实现

文章目录 前言一、分布式id技术选型二、雪花算法三、在项目中集成雪花算法 前言 随着业务的增长&#xff0c;数据表可能要占用很大的物理存储空间&#xff0c;为了解决该问题&#xff0c;后期使用数据库分片技术。将一个数据库进行拆分&#xff0c;通过数据库中间件连接。如果…

C语言顺序表

文章目录 前言线性表顺序表静态顺序表动态顺序表 接口实现 前言 我们先补一下上篇博客落下的知识点&#xff1a; 首先说一下斐波那契的时间复杂度和空间复杂度&#xff1a; long long Fac(size_t N) {if(0 N)return 1;return Fac(N-1)*N; }还是说一下size_t代表的类型是unsi…

C#,数值计算——伽马微分(Gammadev)的计算方法与源程序

1 文本格式 using System; namespace Legalsoft.Truffer { public class Gammadev : Normaldev { private double alph { get; set; } private double oalph { get; set; } private double bet { get; set; } private double a1 { g…

2023年第十届中文自修杯汉字小达人比赛安排、常见问题和试卷题型

好消息&#xff01;面向上海市小学生的2023年第十届中文自修杯汉字小达人比赛开始了&#xff01; 这个活动从2014年开始举办第一届&#xff0c;迄今已经举办了九届&#xff0c;活动的影响力越来越大&#xff0c;深受上海市的小学生们欢迎。而且&#xff0c;有一些外省市的学校…

软件测评报告需要提交什么材料?

软件测评报告 软件测评/软件测试的经典定义是在规定条件下对程序进行操作&#xff0c;以发现错误&#xff0c;对软件质量进行评估。因为软件是由文档、数据以及程序组成的&#xff0c;所以软件测试的对象也就不仅仅是程序本身&#xff0c;而是包括软件形成过程的文档、数据以及…

Liunx系统下载安装Nginx下载安装

目录 版本介绍 Liunx下安装步骤 补充&#xff1a;Docker安装nginx 版本介绍 Nginx开源版 http://nginx.org/en/ 官方原始的Nginx版本 Nginx plus商业版 开箱即用&#xff0c;集成了大量功能 Open Resty https://openresty.org/cn/ OpenResty是一个基于Nginx与 Lua 的高性…

ModuleNotFoundError: No module named ‘transformers.modeling_bert‘解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

【LeetCode题目详解】第九章 动态规划part17 647. 回文子串 ● 516.最长回文子序列(day57补)

本文章代码以c为例&#xff01; 一、力扣第647题&#xff1a;回文子串 题目&#xff1a; 给你一个字符串 s &#xff0c;请你统计并返回这个字符串中 回文子串 的数目。 回文字符串 是正着读和倒过来读一样的字符串。 子字符串 是字符串中的由连续字符组成的一个序列。 具…

html5学习笔记21-css简略学习

CSS https://www.runoob.com/css/css-tutorial.html CSS (Cascading Style Sheets&#xff0c;层叠样式表&#xff09;&#xff0c;是一种用来为结构化文档&#xff08;如 HTML 文档或 XML 应用&#xff09;添加样式&#xff08;字体、间距和颜色等&#xff09;的计算机语言&a…

Ngnix封禁IP与ip段

Ngnix IP封禁以及实现自动封禁IP 小白教程&#xff0c;一看就会&#xff0c;一做就成。 1.创建文件&#xff08;被封禁的ip写里面&#xff09; 在ngnix的conf目录下创建一个blockip.conf文件&#xff0c;里面放需要封禁的IP与ip段&#xff0c;格式如下&#xff08;deny是禁用…

C++ 将off格式文件转换成ply格式存储

文章目录 引言off格式文件ply格式文件C标准库实现off转ply 引言 三维模型是计算机图形学中的一个重要概念&#xff0c;它是由一系列三维坐标点构成的点云或多边形网格。 OFF格式是一种用于描述三维模型的文件格式&#xff0c;它可以描述点云和多边形网格等不同类型的三维模型。…

抖音小程序开发教学系列(5)- 抖音小程序数据交互

第五章&#xff1a;抖音小程序数据交互 5.1 抖音小程序的网络请求5.1.1 抖音小程序的网络请求方式和API介绍5.1.2 抖音小程序的数据请求示例和错误处理方法 5.2 抖音小程序的数据缓存和本地存储5.2.1 抖音小程序的数据缓存机制和使用方法5.2.2 抖音小程序的本地存储和数据持久化…

【工作记录】MQTT介绍、安装部署及springboot集成@20230912

背景 近期公司可能会有物联网设备相关项目内容&#xff0c;提前对用到的mqtt协议做预研和初步使用。 最初接触到mqtt协议应该是早些年的即时通讯吧&#xff0c;现在已经是物联网设备最热门的协议了。 作为记录&#xff0c;也希望能帮助到需要的朋友。 MQTT介绍 《MQTT 协议规…

HAlcon例子

气泡思想 * This example shows the use of the operator dyn_threshold for * the segmentation of the raised dots of braille chharacters. * The operator dyn_threshold is especially usefull if the * background is inhomogeneously illuminated. In this example, *…

开源日报 0830 | 免费计算机科学自学路径:系统化教育与全球支持

ossu/computer-science Stars: 141.9k License: MIT 这个开源项目是一个自学计算机科学的免费路径。它提供了一套完整的在线教育材料&#xff0c;旨在为那些希望获得全面、扎实基础和良好习惯的人们提供支持。该课程按照本科计算机专业要求设计&#xff0c;并且选取了来自哈佛…

抖音小游戏运营攻略:运营能力、用户获取和用户留存

抖音小游戏运营攻略&#xff1a;运营能力、用户获取和用户留存 前言一&#xff0c;运营能力1.1 录屏分享1.2 分享设置 二&#xff0c;用户获取2.1 新游冷启计划2.2 游戏中心推广素材2.3 搜索关键词2.4 搜索结果图2.5 游戏特征2.6 剪映视频模板 三&#xff0c;用户留存3.1 游戏加…

Redis哨兵集群的介绍及搭建

Redis 是一款开源的、内存中的数据结构存储系统&#xff0c;它可以用作数据库、缓存和消息中间件。然而&#xff0c;作为一个单点服务&#xff0c;Redis 在面临硬件故障或者网络问题时可能会导致服务不可用。为了解决这个问题&#xff0c;Redis 提供了哨兵模式&#xff0c;一个…

【玩玩Vue】使用elementui页面布局和控制页面的滚动

原文作者&#xff1a;我辈李想 版权声明&#xff1a;文章原创&#xff0c;转载时请务必加上原文超链接、作者信息和本声明。 文章目录 前言一、页面布局二、页面滚动1.禁用body的滑动2.禁用el-aside的滚动3.启动el-main的滚动 前言 一、页面布局 这里布局使用vueelementui&…

如何对安卓设备执行免Root设置?免Root后如何远程控制?

使用AirDroid个人版的远程控制功能时&#xff0c;对被控的安卓设备执行免Root设置是比较常用的一种方式&#xff08;安卓7.0及以上系统的设备可以选择通过辅助权限&#xff08;无障碍&#xff09;控制安卓设备&#xff09; 如何执行免Root设置&#xff1f; 前提条件 1&#…

每日一博 - Stack OveFlow Arch In Reality

文章目录 概述猜测 &#xff1f;Truth 概述 Stack Overflow 是一个与程序相关的 IT 技术问答网站&#xff0c;其技术架构主要采用微软的技术栈&#xff0c;包括 C#、ASP.NET、SQL Server 等。此外&#xff0c;Stack Overflow 还使用了一些开源框架&#xff0c;例如 HAProxy、R…