STL——string类

news2024/12/24 0:23:41

一、标准库中的string类

1.string类文档介绍

(1)字符串是表示字符序列的类。

(2)标准的字符串类提供了对此类对象的支持,其接口类似于标准字符容器的接口,但添加了专门用于操作单字节字符字符串的设计特性。

(3)string类是使用char(即作为他的字符类型,使用它的默认char_traits和分配器类型)。

(4)string类是basic_string模板类的一个实例,它使用char来实例化basic_string模板类,并使用char_traits和allocator作为basic_string的默认参数。

(5)这个类独立于所使用的编码来处理字节,如果用来处理多字节或变长字符(如utf-8)的序列,这个类的所有成员(如长度、大小)以及它的迭代器,将仍然按照字节(而不是实际编码的字符)来操作。

2.string类常用接口介绍

2.1string类对象的常见构造

2.2string类对象的容量操作

 注意:

(1)size和length方法的底层实现原理完全相同,引入size的原因是为了与其他容器的接口保持一致,一般情况下基本都是使用size。

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

(3)resize(size_t n)与resize(size_t n, char c)都是将字符串中有效字符个数改变到n个,不同的是当字符个数增多时,resize(size_t n)用0来填充多出的元素空间,而resize(size_t n, char c)是用字符c来填充多出的元素空间。

注意:resize在改变元素个数时,若是将元素个数增多,可能会改变底层容量的大小,若是将元素个数减少,底层空间总大小不变。

(4)reserve(size_t res_arg=0):为string预留空间,不改变有效元素的个数,当reserve的参数小于string的底层空间总大小时,reserve不会改变容量大小。

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

2.4string类对象的修改操作

二、模拟实现string类

1.实现的接口

1.1类默认的成员函数

构造函数

拷贝构造函数

赋值运算符重载

析构函数

1.2迭代器相关

        迭代器通过指针模拟实现。

1.3容量相关

1.4元素访问

1.5元素修改相关

        字符/字符串追加

1.6字符串操作相关

获取C语言格式字符串

查找字符

获取子串

字符串交换

1.7IO操作相关

        输入输出

2.代码实现

#define _CRT_SECURE_NO_WARNINGS

#include <iostream>
#include <assert.h>
using namespace std;

namespace MyString {
	class string {
	public:
		//用指针模拟实现迭代器
		typedef char* iterator;
		typedef char* reverse_iterator;

		/*--------------默认成员函数--------------*/

		//默认构造
		string(const char* str = "") {
			if (str == nullptr) str = "";
			_size = strlen(str);
			_capacity = _size;

			_str = new char[_size + 1];//需要加上\0所占的空间
			strcpy(_str, str);
		}

		//拷贝构造
		string(const string& s)
			: _str(nullptr)
			, _size(0)
			,_capacity(0)
		{
			//传统写法
			//_str = new char[strlen(s._str) + 1];
			//strcpy(_str, s._str);

			string str_temp(s._str);
			this -> swap(str_temp);
		}

		//n_char构造
		string(size_t n, char ch) {
			_size = n;
			_capacity = n;
			_str = new char[n + 1];
			memset(_str, ch, n);
			_str[n] = '\0';
		}

		//赋值运算符重载
		string& operator=(string s) {
			if (this != &s) {//防止自己给自己赋值
				//传统写法
				//char* temp = new char[strlen(s._str) + 1];
				//strcpy(temp, s._str);
				//delete[] _str;
				//_str = temp;

				this -> swap(s);
			}
			return *this;
		}

		//析构
		~string() {
			if (_str) {
				delete[] _str;
				_str = nullptr;
			}
		}

		/*--------------迭代器--------------*/
		/*使用指针模拟实现*/

		iterator begin() {
			return _str;
		}
		iterator end() {
			return _str + _size;
		}
		reverse_iterator rbegin() {
			return end();
		}
		reverse_iterator rend() {
			return begin();
		}

		/*--------------容量--------------*/
		size_t size() const {
			return _size;
		}
		size_t capacity() const {
			return _capacity;
		}
		bool empty() const {
			return 0 == _size;
		}
		void clear() {
			_size = 0;
		}
		void resize(size_t new_size, char ch) {
			if (new_size > _size) {
				size_t old_size = _size;
				if (new_size > _capacity) {//需要扩容
					reserve(new_size);
				}
				memset(_str + _size, ch, new_size - old_size);
			}
			_size = new_size;
			_str[_size] = '\0';
		}
		void resize(size_t n) {
			resize(n, 0);
		}
		void reserve(size_t new_capacity) {//扩容
			size_t old_capacity = _capacity;
			if (new_capacity > old_capacity) {
				char* temp = new char[new_capacity + 1];
				strcpy(temp, _str);
				delete[] _str;
				_str = temp;
				_capacity = new_capacity;
			}
		}

		/*--------------元素访问--------------*/
		char& operator[](size_t index) {
			assert(index < _size);
			return _str[index];
		}
		const char& operator[](size_t index) const {
			assert(index < _size);
			return _str[index];
		}

		/*--------------元素修改--------------*/
		void push_back(char ch) {
			if (_size == _capacity) {//需要扩容
				if (_capacity == 0) _capacity = 1;//若初始为0,按2倍扩容方式则无法扩容
				reserve(_capacity * 2);
			}
			_str[_size] = ch;
			_size++;
			_str[_size] = '\0';
		}
		string& operator+=(char ch) {
			push_back(ch);
			return *this;
		}
		string& operator+=(const string& s) {
			*this += s._str;
			return *this;
		}
		string& operator+=(const char* s) {
			size_t len = strlen(s);
			char* temp = new char[_size + len + 1];
			strcpy(temp, _str);
			strcat(temp, s);

			delete[] _str;
			_str = temp;

			_size += len;
			_capacity = _size;

			return *this;
		}

		/*--------------字符串操作--------------*/
		const char* c_str() const {
			return _str;
		}
		size_t find(char ch, size_t pos = 0) {
			for (size_t i = pos; i < _size; ++i) {
				if (_str[i] == ch) return i;
			}
			return npos;
		}
		size_t rfind(char ch, size_t pos = npos) {
			//注意无符号-1是一个非常大的数字
			pos = pos < _size ? pos : _size - 1;
			for (int i = pos; i >= 0; --i) {
				if (_str[i] == ch) return i;
			}
			return npos;
		}
		string substr(size_t pos, size_t n = npos) {
			if (n == npos) n = _size;// 没有传入n时,最多截取_size长度
			if (pos + n >= _size) {
				n = _size - pos;
			}
			char* temp = new char[n + 1];
			strncpy(temp, _str + pos, n);
			temp[n] = '\0';

			string sub(temp);
			delete[] temp;
			return sub;
		}
		//交换函数
		void swap(string& s) {
			std::swap(_str, s._str);
			std::swap(_size, s._size);
			std::swap(_capacity, s._capacity);
		}
			 
		/*--------------IO操作--------------*/
		friend ostream& operator<<(ostream& _cout, const string& s) {
			_cout << s._str;
			return _cout;
		}
		friend istream& operator>>(istream& _cin, string& s) {
			//直接输入无法扩容
			while (1) {
				char ch = _cin.get();
				if (ch == '\n' || ch == ' ') break;
				s.push_back(ch);
			}
			return _cin;
		}

	private:
		char* _str;
		size_t _size;
		size_t _capacity;
	public:
		static size_t npos;
	};

	size_t string::npos = -1;
}

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

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

相关文章

IOS逆向--恢复Dyld的内存加载方式

之前我们一直在使用由dyld及其NSCreateObjectFileImageFromMemory/NSLinkModule API方法所提供的Mach-O捆绑包的内存加载方式。虽然这些方法我们今天仍然还在使用&#xff0c;但是这个工具较以往有一个很大的区别…现在很多模块都被持久化到了硬盘上。 roguesys 在 2022 年 2 …

还在用 OpenFeign?来试试 SpringBoot3 中的这个新玩意!

好久没发技术文章了&#xff0c;最近回到工作地&#xff0c;晚上有空又可以码码技术了&#xff0c;今天我们就来聊一个 Spring Boot3 中的新鲜玩意&#xff0c;声明式 HTTP 调用。 1. 由来 Spring Boot3 去年底就已经正式发布&#xff0c;我也尝了一把鲜&#xff0c;最近有空…

(02)Cartographer源码无死角解析-(53) 2D后端优化→位姿图优化理论(SPA)讲解、核型函数调用流程

讲解关于slam一系列文章汇总链接:史上最全slam从零开始&#xff0c;针对于本栏目讲解(02)Cartographer源码无死角解析-链接如下: (02)Cartographer源码无死角解析- (00)目录_最新无死角讲解&#xff1a;https://blog.csdn.net/weixin_43013761/article/details/127350885 文末…

Docker镜像部署至Rancher全局配置 以xxl-job-admin为例

流程以xxl-job-admin为例 1.基础环境 win/mac/linuxRancherDocker 2.下载源码 从Github上下载xxl-job xxl-jobGithub xxl-job官方地址 3.修改源码 打开 xxl-job 下的 xxl-job-admin 修改 application-properties 文件 修改数据库 修改为这种格式&#xff1a; 大括号包…

MPLS实验

目录实验要求mpls简介mpls工作过程实验的配置环回的配置R1和R5之间公网的ospf配置配置mpls-ldp配置R1和R5间的mplsvpn私网的rip及ospf的宣告配置公网mp-bgp的建立R2和R4上面的双向重发布R7和R8之间创建R7和R8间的mplsvpn配置静态路由及环回重发布实验要求 如图 要求&#xff1…

【C++修炼之路】15.C++继承

每一个不曾起舞的日子都是对生命的辜负 继承C继承一. 继承的概念及定义1.1 继承的引出1.2 继承的概念1.3 继承的定义二.基类和派生类对象赋值转换三.继承中的作用域3.1 作用域的概念3.2 举例说明同名冲突四.派生类的默认成员函数4.1 派生类的构造函数4.2 派生类的拷贝构造函数4…

【python学习笔记】:数据科学库操作(二)

接上一篇&#xff1a; 4、PIL Python Imaging Library(PIL) 已经成为 Python 事实上的图像处理标准库了&#xff0c;这是由于&#xff0c;PIL 功能非常强大&#xff0c;但API却非常简单易用。但是由于PIL仅支持到 Python 2.7&#xff0c;再加上年久失修&#xff0c;于是一群志…

如果写不好 SQL,有没有好用的报表软件?

业务和技术在做报表这件事情上&#xff0c;究竟有多大差别&#xff1f; 一家企业、一个组织&#xff0c;只要一直在经营和运作&#xff0c;因为税务和其他原因就需要通过数据报表来反映当期的经营管理状况。而“做报表”这个事情&#xff0c;在企业内部不管是业务人员还是技术人…

HTTP之Referrer和Referrer-policy

目录 HTTP之Referrer和Referrer-policy Referer Referrer-policy 如何设置referrer 盗链 防盗链的工作原理 绕过图片防盗链 利用https网站盗链http资源网站&#xff0c;refer不会发送 设置meta 设置referrerpolicy"no-referrer" 利用iframe伪造请求refe…

C语言指针变量的运算

指针变量保存的是地址&#xff0c;而地址本质上是一个整数&#xff0c;所以指针变量可以进行部分运算&#xff0c;例如加法、减法、比较等&#xff0c;请看下面的代码&#xff1a;#include<stdio.h>intmain(){ int a 10,*pa &a,*paa &a; double b 99.9,*pb &a…

JTAG和SWD调试器

文章目录一、调试器二、JTAG三、SWD三、各自优缺点一、调试器 当我们开发单片机程序时&#xff0c;通常是在Windows或Linux上进行代码编写和编译&#xff0c;但是单片机并不直接集成在电脑上&#xff0c;怎么验证我们的单片机程序是否正确并烧录到单片机中&#xff0c;此时就需…

某游戏平台检测加速辅助案例分析

加速类辅助会对游戏平衡造成极大的破坏&#xff0c;这类辅助会通过HOOK api的方式来达到修改游戏对时间判断的目的&#xff0c;一般情况下&#xff0c;在R3层&#xff0c;这类辅助会在 QueryPerformanceCounter TimeGetTime GettickCount这三个API上HOOK&#xff0c;修改他们的…

Java-黑马Java学习作业-day15面向对象进阶(抽象类接口内部类)

学习视频链接&#xff1a;https://www.bilibili.com/video/BV17F411T7Ao 文章目录第一题&#xff1a;&#xff08;抽象类求面积和周长&#xff09;第二题&#xff1a;&#xff08;接口实现新旧手机功能&#xff09;第三题&#xff1a;&#xff08;使用子类和匿名内部类调用接口…

大厂高薪测试在线讲解Jmeter全套性能测试

Jmeter进行性能测试基本包含如下基本过程&#xff1a;1&#xff09;新增线程组创建测试线程组&#xff0c;并设置线程数量及线程初始化启动方式。2&#xff09;新增 JMeter 元组创建各种默认元组及测试元组&#xff0c;填入目标测试静态资源请求和动态资源请求参数及数据。3&am…

Task9:Excel数据透视表

文章目录一 Excel数据透视表1 数据透视表2 切片器3 数据透视的注意事项4 透视表常用法二 Excel数据透视图一 Excel数据透视表 1 数据透视表 什么是透视表&#xff1a;把明细表分类汇总的过程&#xff0c;可以按照不同的组合方式进行数据计算使用场景&#xff1a; 1.大量数据&…

QT入门Buttons之QCheckBox

目录 一、界面布局介绍 1、布局器中的位置及使用 2、常用属性 二、属性功能介绍 1、常用信号 2、测试信号stateChanged(int) 3、组合框效果 三、Demo展示 此文为作者原创&#xff0c;转载标明出处&#xff01; 一、界面布局介绍 1、布局器中的位置及使用 QCheckBox复选…

除了console.log,你还用过console其它的属性么?

目录前言console.infoconsole.debugconsole.errorconsole.warnconsole.time 和 console.timeEndconsole.group 和 console.groupEndconsole.table前言 刚学习前端的时候&#xff0c;vue还没用vue-devtools&#xff0c;react还没用 React Developer Tools&#xff0c;我们经常通…

fastjson 1.2.47 RCE漏洞保姆级复现

1.漏洞概述 Fastjson提供了autotype功能&#xff0c;允许用户在反序列化数据中通过“type”指定反序列化的类型&#xff0c;Fastjson自定义的反序列化机制时会调用指定类中的setter方法及部分getter方法&#xff0c;那么当组件开启了autotype功能并且反序列化不可信数据时&…

Sklearn中的算法效果评估手段

我们曾在《算法效果评估&#xff1a;均方根误差&#xff08;RMSE&#xff09;/ 标准误差》一文中介绍过评估算法效果使用的主要方法&#xff1a;均方根误差&#xff08;RMSE&#xff09;&#xff0c;但在实际应用中&#xff0c;评估算法效果还有更多内容&#xff0c;本文我们以…

VsCode安装及修改插件存储位置

【官网】&#xff1a; https://code.visualstudio.com/ 【修改插件仓库】&#xff1a; 创建名为VSCODE_EXTENSIONS的环境变量&#xff0c;内容指向自定义的文件夹即可&#xff08;位置无需限制&#xff09;。 【需要安装的插件】&#xff1a;