移情别恋c++ ദ്ദി˶ー̀֊ー́ ) ——5.string(模拟实现)

news2024/9/21 12:41:07

1.存储结构

namespace zone
{
	class string
	{
	public:
		

	private: //设置私有,不允许随便访问底层数据
		char* _str; //字符串存储空间首地址指针
		size_t _size; //当前字符数量
		size_t _capaicty; //可用容量
        static const size_t npos;

	}
    const size_t string::nops = -1;//在类外面初始化
}

_str:指向字符串存放的空间的指针


_size:代表当前所存储的有效字符数量


_capacity:代表当前可存储的最大容量


nops:此值设置为 -1,无符号整型转换就是42亿,且此值为const和静态参数具有全局效应,某些函数设置其为缺省参数

2.默认成员函数

注意:在test.cpp文件中 #include“string.h“需要写在 using namespace std; 下方

因为构造函数需要调用iostream中的函数(strlen),而展开iostream需要使用using namespace std,而寻找默认从展开处往上找。

如果#include“string.h“写在 using namespace std上方

调用strlen时就会从#include“string.h“上方找,会找不到using namespace std,自然无法调用strlen。

2.1构造函数

1.初始化列表

string(const char* str="")// 传的是常量字符串 需要用const
	:_size(strlen(str))
	, _capacity(_size)
{
	_str = new char[_capacity+1];//+1是因为要存“\0"
	strcpy(_str, str);
};

1先得出字符串的长度,初始化size,capacity。

2.用 new 为str开空间。

3.复制字符串。

2.拷贝构造

	void swap(string& s)
	{
		std::swap(_str, s._str);
		std::swap(_size, s._size);
		std::swap(_capacity, s._capacity);
	}

	//s2(s1)
	string(const string& str)      //记得加&!!!!!!!!!!!!!!
		: _str(NULL)
		,_size(0)
		,_capacity(0)
	{
		string tmp(str._str);     //调用初始化列表
		swap(tmp);
	}

	//s2=s1
	string&operator=(string str)      //传值传参,调用拷贝构造(上文)
	{
		swap(str);    //这里将s1和str交换,出作用域后,将原来s1里的内容析构
		return *this;
	}

2.2 析构函数 

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

因为我们使用 new[ ] 申请,所以对应的释放是 delete[ ] ,这里需要注意! 

3.容量操作函数 

3.1.reserve(设置空间大小)

void reserve(size_t num)
{
	if (num >= _capacity)  //默认为扩容
	{
		char* str = new char[num + 1];   //+1表示为\0留空间
		strcpy(str, _str);
		delete[] _str;
		_str = str;
		_capacity = num;
	}
}

3.2  resize(重新设置string的长度)

void resize(size_t n, char ch = '\0')
{
	if (n <= _size)     //小于size,相当于删除
	{
		_str[n] = '\0';      
		_size = n;
	}
	else              //大于size,相当与添加
	{
		reserve(n);
		while (_size < n)
		{
			_str[_size] = ch;
			_size++;
		}

		_str[_size] = '\0';

	}
}

3.3 获取size和capacity 

size_t size()
{
	return _size;
}


size_t capacity()
{
	return _capacity;
}

4.字符串访问函数

4.1[]

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

实现数组的访问模式

4.2迭代器 

typedef char* iterator;
typedef const char* const_iterator;

	iterator begin()
	{
		return _str;
	}

	iterator end()
	{
		return _str+_size;
	}

	const iterator begin()const
	{
		return _str;
	}

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

通过返回指针的方式实现迭代器的功能

5.插入类函数 

   5.1 push_back(尾插字符)

void push_back(char str)        //这里可以不用const,因为是非指针的拷贝构造,str改变不会影响原字符的改变
{
	if (_size == _capacity)
		reserve(_capacity * 2);

	_str[_size] = str;
	_size++;
	_str[_size] = '\0';      //记得有\0
}

5.2 append (尾插字符串)

void append(const char* str)           //这里需要用const,因为是指针的拷贝构造(值拷贝),新指针也指向原字符串(常量),不能改变
{
	if (_size+ strlen(str) > _capacity)
		reserve(_capacity+strlen(str));

	strcpy(_str + _size, str);         //从最末尾处开始复制str
	_size += strlen(str);
}

5.3 insert(在某一位置插入字符或字符串) 

void insert(size_t pos, char str)   //插入字符
{
	assert(pos <= _size);

	if (_size == _capacity)
	{
		reserve(_capacity == 0 ? 4 : _capacity * 2);
	}

	int end = _size;
	while (end >= (int)pos)      //需要强制类型转换成int,否则会因为类型提升倒置死循环
	{
		_str[end + 1] = _str[end];
		end--;
	}
	_str[pos] = str;
	_size++;
}


void insert(size_t pos,const char* str)    //插入字符串
{
	int len = strlen(str);

	if (_size == _capacity)
	{
		reserve(_capacity == 0 ? len : _capacity+len);
	}

	int end = _size;

	while (end >= (int)pos)     //需要强制类型转换成int,否则会因为类型提升倒置死循环
	{
		_str[end + len] = _str[end];
		end--;
	}

	strncpy(_str + pos,str,len);//使用strncpy控制复制区间
	_size = _size + len;

}

6.删除类函数(erase) 

void erase(size_t pos, size_t len = npos)  //从pos位置开始,删除len个字符
{

	assert(pos < _size);
	if (len == npos || pos + len >= _size)      //从pos处开始删完 或者 超出_size也是删完
	{
		_str[pos] = '\0';
		_size = pos;
	}
	else
	{
		size_t  flag = pos + len;
		while (flag <= _size)
		{
			_str[flag - len] = _str[flag];
			++flag;
		}
		_size -= len;

	}
}

7.运算符重载 

7.1 +=

string& operator+=(char str)//字符
{
	push_back(str);
	return *this;
}


string& operator+=(const char* str)   //字符串,记得加const
{
	append(str);
	return *this;
}

7.2 逻辑判断运算符

bool operator<( const string& s)
{
	return strcmp(_str, s._str) < 0;
}

bool operator==(const string& s)
{
	return strcmp(_str, s._str) == 0;
}

bool operator<=(const string& s)
{
	return *this < s || *this == s;
}

bool operator>(const string& s)
{
	return !(*this <= s);
}

bool operator>=(const string& s)
{
	return !(*this < s);
}

bool operator!=(const string& s)
{
	return !(*this == s);
}

string类的比较

8.查找和提取函数 

8.1查找函数 find

size_t find(char ch, size_t pos = 0)       //查找字符, 提供缺省值,可以控制在何处开始查找
{
	for (size_t i = pos; i < _size; i++)    
	{
		if (_str[i] == ch)
			return i;
	}

	return pos;
}


size_t find(const char* str, size_t pos = 0)   //查找字符串,提供缺省值,可以控制在何处开始查找
{
	const char* p = strstr(_str+pos, str);
	if (p)
	{
		return p - _str;     //返回首个字符的位置
	}
	else
	return npos;
}

8.2 提取函数 substr 

string substr(size_t pos, size_t len = npos)     //从pos位置开始取len个字符
{
	string s;
	size_t end = pos + len;
	if (len == npos || pos + len > _size)
	{
		len = _size - pos;
		end = _size;
	}

	s.reserve(len);
	for (size_t i = pos; i < end; i++)
	{
		s += _str[i];
	}
	return s;          //传值返回,调用拷贝构造(深拷贝)
}

9.流操作(要写在class外,namespace内) 

9.1流插入

ostream& operator<<(ostream& out, const string& s)
{

	for (auto ch :s)
	{
		out << ch;
	}
	return out;
}

9.2 流提取 

istream& operator<<(istream& in, string& s)
{

	s.clear();       //需要先清空字符串,不然+=会调用尾插 到之前的字符串
	char ch;
	ch=in.get();    //用于读入空格
	while (ch != ' ' && ch != '\n')
	{
		s += ch;
		ch = in.get();
	}

	return in;

}

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

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

相关文章

MATLAB中ichol函数用法

目录 语法 说明 示例 不完全 Cholesky 分解 使用 ichol 作为预条件子 使用 diagcomp 选项 ichol函数的功能是对矩阵进行不完全 Cholesky 分解。 语法 L ichol(A) L ichol(A,options) 说明 L ichol(A) 通过零填充执行 A 的不完全 Cholesky 分解。A 必须为稀疏方阵。…

西瓜书学习笔记三 归纳偏好

1.4 归纳偏好 通过学习得到的模型对应了假设空间中的一个假设。于是&#xff0c;图1. 2的西瓜版本空间给我们带来一个麻烦:现在有三个与训练集一致的假设&#xff0c;但与它们对应的模型在面临新样本的时候&#xff0c;却会产生不同的输出。现在有一个新瓜&#xff0c;一个模型…

希腊字母大写、小写、音标

▪Αα ▪Ββ ▪Γγ ▪Δδ ▪Εε或ϵ ▪Ϝϝ ▪Ζζ ▪Ηη ▪Θθ ▪Ιι ▪Κκ ▪Λλ ▪Μμ ▪Νν ▪Ξξ ▪Οο ▪Ππ ▪Ρρ ▪Σσ或ς ▪Ττ ▪Υυ ▪Φφ或ϕ ▪Χχ ▪Ψψ ▪Ωω

C语言学习——指针(定义、变量的指针和指向变量的指针变量)

目录 十、指针 10.1地址和指针的概念 10.2变量的指针和指向变量的指针变量 定义一个指针变量 指针变量的引用 指针变量作为函数参数 十、指针 10.1地址和指针的概念 我们要想了解什么是指针&#xff0c;就必须弄清楚数据在内存中是如何存储的&#xff0c;又是如何读取的…

利用EditPlus进行Json数据格式化

利用EditPlus进行Json数据格式化 git下载地址&#xff1a;https://github.com/michael-deve/CommonData-EditPlusTools.git (安装过editplus的直接将里面的json.js文件复制走就行) 命令&#xff1a;Cscript.exe /nologo “D:\Program Files (x86)\EditPlus 3\json.js” D:\P…

代码随想录算法训练营第三十天| 01背包问题 二维, 01背包问题 一维 , 416. 分割等和子集

今天是动态规划学习的第三天&#xff0c;主要的学习内容包括&#xff1a;01背包问题二维数组解法和一维数组解法&#xff0c;以及01背包问题的应用。 01背包问题 二维 题目链接&#xff1a;46. 携带研究材料&#xff08;第六期模拟笔试&#xff09; (kamacoder.com) 首先我们…

胡姓名人伟人有哪些?胡姓最厉害三个名人是谁

胡姓名人伟人有哪些?胡姓最厉害三个名人是谁? 在中国悠久的历史长河中,胡姓不仅承载着丰富的文化遗产,更是孕育出无数杰出的历史人物。这些人物以其独特的贡献和影响力,成为中华文明的重要组成部分。以下是根据历史影响力和文化贡献精心挑选的十大胡姓名人,他们的故事和成就展…

GNU/Linux - systemd介绍

systemd官网&#xff1a; System and Service Manager systemd systemd Github地址&#xff1a; https://github.com/systemd/systemd 首次发布 2010年3月30日 System and Service Manager systemd 是一套 Linux 系统的基本构件。它提供了一个系统和服务管理器&#xff0c;作为…

USB 2.0 协议专栏之 USB 配置描述符(四)

前言&#xff1a;本篇博客为手把手教学的 USB 2.0 协议栈类精品博客&#xff0c;该专栏博客侧重针对 USB 2.0 协议进行讲解。第 4 篇重点为 USB 2.0 协议中的配置描述符 Configuration Descriptors 进行讲解&#xff0c;并结合 CH32V307 与 STM32 代码进行 Configuration Descr…

【工业机器人】工业异常检测大模型AnomalyGPT

AnomalyGPT 工业异常检测视觉大模型AnomalyGPT AnomalyGPT: Detecting Industrial Anomalies using Large Vision-Language Models AnomalyGPT是一种基于大视觉语言模型&#xff08;LVLM&#xff09;的新型工业异常检测&#xff08;IAD&#xff09;方法。它利用LVLM的能力来理…

Oracle VM VirtualBox虚拟机内存不够用的解决方案

一、 前言 在使用Oracle VM VirtualBox虚拟机的过程中&#xff0c;随着时间的推移&#xff0c;我们会感觉我们的内存越来越不够用&#xff0c;今天就来给大家分享一下我们如何解决虚拟机内存不够用的问题。 二、解决方法 1.虚拟机碎片化整理 我们第一步要做的是碎片整理&…

【protobuf】ProtoBuf——proto3语法详解、enum类型、enum类型的使用和注意事项、Any类型、通讯录录入号码类型和地址的功能实现

文章目录 ProtoBuf5. proto3语法详解5.3 enum类型5.4 Any类型 ProtoBuf 5. proto3语法详解 5.3 enum类型 定义规则&#xff1a; proto3支持我们定义枚举类型并使用&#xff1a; 枚举类型的名称采用驼峰命名法且首字母大写&#xff0c;如 MyEnum &#xff0c;这样的命名方式符合…

重启人生计划-且随风行

&#x1f973;&#x1f973;&#x1f973; 茫茫人海千千万万&#xff0c;感谢这一刻你看到了我的文章&#xff0c;感谢观赏&#xff0c;大家好呀&#xff0c;我是最爱吃鱼罐头&#xff0c;大家可以叫鱼罐头呦~&#x1f973;&#x1f973;&#x1f973; 如果你觉得这个【重启人生…

Element UI详解

目录 Element UIElement UI 简介开发使用开发指南概述总结 设计原则组件使用特性使用场景优势不足 Element UI Element UI 简介 Element UI 是由饿了么前端团队开发的一套基于 Vue.js 的桌面端组件库。它提供了一系列丰富的 UI 组件&#xff0c;用于快速搭建企业级的 Web 应用…

RCE编码绕过--php://filter妙用

目录 代码 如何绕过 payload构造 代码 <?php $content <?php exit; ?>; $content . $_POST[txt]; file_put_contents($_POST[filename],$content); 当你想要输入代码的时候前面会有<?php exit;?>;&#xff0c;代码没有办法执行下去&#xff0c;所以…

day32+学习记录

一.算法练习 509.斐波那契数 斐波那契数 &#xff08;通常用 F(n) 表示&#xff09;形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始&#xff0c;后面的每一项数字都是前面两项数字的和。也就是&#xff1a; F(0) 0&#xff0c;F(1) 1 F(n) F(n - 1) F(n - 2)&#xf…

(待会删)分享9款一键生成原创论文在线使用软件

在当前的学术研究和写作环境中&#xff0c;AI技术的应用已经变得越来越普遍。其中&#xff0c;一键生成原创论文的在线软件更是为学者们提供了极大的便利。本文将重点介绍一款备受推荐的AI原创论文写作平台——千笔-AIPassPaPer&#xff0c;并分享其他几款优秀的同类软件。 千…

政务大数据解决方案(五)

政务大数据解决方案旨在通过建立统一的数据平台&#xff0c;将各政府部门的数据资源进行有效整合与智能分析&#xff0c;利用先进的数据处理和人工智能技术实现对社会动态的实时监测和精准预测&#xff0c;从而优化政府决策、提升公共服务效率和透明度。该方案涵盖数据的采集、…

每日OJ_牛客HJ75 公共子串计算

目录 牛客HJ75 公共子串计算 解析代码 牛客HJ75 公共子串计算 公共子串计算_牛客题霸_牛客网 解析代码 求最大公共子串&#xff0c;使用递推实现 假设 x(i)&#xff1a;字符串第i个字符 y(j)&#xff1a;字符串第j个字符 dp[i][j]&#xff1a;以x(i)&#xff0c;y(j)结尾的最…

XSS-games

XSS 1.XSS 漏洞简介2.XSS的原理3.XSS的攻击方式4.XSS-GAMESMa SpaghetJefffUgandan KnucklesRicardo MilosAh Thats HawtLigmaMafiaOk, BoomerWW3svg 1.XSS 漏洞简介 ​ XSS又叫CSS&#xff08;Cross Site Script&#xff09;跨站脚本攻击是指恶意攻击者往Web页面里插入恶意Sc…