String的底层构造

news2024/9/28 5:22:38

1.String类对象的构造(后面有每一个接口的实现)

#define _CRT_SECURE_NO_WARNINGS 1
#pragma once
#include<iostream>
#include<assert.h>
using namespace std;

namespace bit
{
	class string
	{
	public:
		typedef char* iterator;
		typedef const char* const_iterator;

		iterator begin();
		iterator end();

		const_iterator begin() const;
		const_iterator end() const;

		//string();
		string(const char* str = "");
		string(const string& s);
		string& operator=(const string& s);
		~string();

		const char* c_str() const;

		size_t size() const;
		char& operator[](size_t pos);
		const char& operator[](size_t pos) const;

		void reserve(size_t n);

		void push_back(char ch);
		void append(const char* str);

		string& operator+=(char ch);
		string& operator+=(const char* str);

		void insert(size_t pos, char ch);
		void insert(size_t pos, const char* str);
		void erase(size_t pos = 0, size_t len = npos);

		size_t find(char ch, size_t pos = 0);
		size_t find(const char* str, size_t pos = 0);

		void swap(string& s);
		string substr(size_t pos = 0, size_t len = npos);

		bool operator<(const string& s) const;
		bool operator>(const string& s) const;
		bool operator<=(const string& s) const;
		bool operator>=(const string& s) const;
		bool operator==(const string& s) const;
		bool operator!=(const string& s) const;
		void clear();
	private:
		// char _buff[16];
		char* _str;

		size_t _size;
		size_t _capacity;

		//  
		//const static size_t npos = -1;

		// ֧
		//const static double N = 2.2;

		const static size_t npos;
	};

	istream& operator>> (istream& is, string& str);
	ostream& operator<< (ostream& os, const string& str);
}

2.String类常见的构造方式

void test_string1()
{
	// 常用
	string s1;
	string s2("hello world");
	string s3(s2);

	// 不常用 了解
	string s4(s2, 3, 5);
	string s5(s2, 3);
	string s6(s2, 3, 30);
	string s7("hello world", 5);
	string s8(10, 'x');

	cout << s1 << endl;
	cout << s2 << endl;
	cout << s3 << endl;
	cout << s4 << endl;
	cout << s5 << endl;
	cout << s6 << endl;
	cout << s7 << endl;
	cout << s8 << endl;

	cin >> s1;
	cout << s1 << endl;
}

3.String的隐式类型转换与构造

void test_string2()
{
	string s1("hello world"); //构造
	string s2 = "hello world"; //隐式类型转换
	const string& s3 = "hello world";// 临时对象具有常性,加const
 }

4.String类的基本操作函数

void test_string3()
{
  string s1("hello world");
  cout << s1.size() << endl;
//capacity 比 实际空间少一个,有一个多的是预留给\0
  cout << s1.capacity() << endl;
  cout << s1.max_size() << endl;
}

5.String的三种遍历方式

        5.1  :使用[]来完成遍历

        

string s1 = "hello world";
	for (int i = 0; s1[i]; i++)
	{
		cout << s1[i] << " ";
	}
	cout << endl;

        5.2 : 使用迭代器完成遍历

        

string::iterator it1 = s1.begin();
	while (it1 != s1.end()) { 
		cout << *it1 << " ";
		++it1;
	}
	cout << endl;
 
	cout << typeid(it1).name() << endl

        5.3 :使用auto 来完成遍历

//遍历方式3:范围for
	// 底层:就是迭代器
	for (auto e : s1) {
		cout << e << " ";
	}

6.String的逆置 - reverse

void test_string5() //反向迭代器
{
	string s1("hello world");
	string::const_iterator it1 = s1.begin();
	//auto it1 = s1.begin();
	while (it1 != s1.end())
	{
		//*it1 += 3;// 不能修改
		cout << *it1 << " ";
		++it1;
	}
	string s2("hello world");
 
	string::reverse_iterator it2 = s2.rbegin();
	while (it2 != s2.rend()) {
		*it2 += 3;
		cout << *it2 << " ";
		++it2;
	}
}

7.String的sort 排序

void test_string6()
{
	string s1("hello world");
	cout << s1 <<endl;
 
	//按字典序排序
	sort(s1.begin(), s1.end());
	
	//第一个和最后一个参与排序
	sort(++s1.begin(), --s1.end());
 
	//前五个排序
	sort(s1.begin(), s1.begin() + 5);
	cout << s1 << endl;
}

8.string 的插入删除

void push_back(char ch);
void append(const char* str);
void insert(size_t pos, char ch);
void insert(size_t pos, const char* str);
void string::insert(size_t pos, char ch)
{
	assert(pos <= _size);

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

	/*int end = _size;
	while (end >= (int)pos)
	{
		_str[end + 1] = _str[end];
		--end;
	}*/

	size_t end = _size + 1;
	while (end > pos)
	{
		_str[end] = _str[end - 1];
		--end;
	}

	_str[pos] = ch;
	++_size;
}

8.2:在pos位置插入字符串

        

void string::insert(size_t pos, const char* str)
{
	assert(pos <= _size);

	size_t len = strlen(str);
	if (_size + len > _capacity)
	{
		reserve(_size + len);
	}

	/*int end = _size;
	while (end >= (int)pos)
	{
		_str[end + len] = _str[end];
		--end;
	}*/

	size_t end = _size + len;
	while (end > pos + len - 1)
	{
		_str[end] = _str[end - len];
		--end;
	}

	memcpy(_str + pos, str, len);
	_size += len;
}

对于push_back,直接复用insert

void string::push_back(char ch)
{
	insert(_size, ch);
}

8.3 earse的实现

        

void string::erase(size_t pos, size_t len)
{
	assert(pos < _size);

	// len大于前面字符个数时,有多少删多少
	if (len >= _size - pos)
	{
		_str[pos] = '\0';
		_size = pos;
	}
	else
	{
		strcpy(_str + pos, _str + pos + len);
		_size -= len;
	}
}

9.String中查找一个字符与字符串(Find 的实现)

size_t string::find(char ch, size_t pos)
{
	for (size_t i = pos; i < _size; i++)
	{
		if (_str[i] == ch)
		{
			return i;
		}
	}

	return npos;
}
size_t string::find(const char* sub, size_t pos)
{
	char* p = strstr(_str + pos, sub);
	return  p - _str;
}

10.resize与reserve

        

void test_string11()
{
	string s1;
	s1.resize(5, '0'); //初始值
	cout << s1 << endl;
 
	// 再扩容
	s1.reserve(100);
	cout << s1.size() << "  " << s1.capacity() << endl;
 
	//reserve 在vs下不会缩容,没有规定
	s1.reserve(20);
	cout << s1.size() << "  " << s1.capacity() << endl;
 
	s1.resize(10);
	cout << s1.size() << "  " << s1.capacity() << endl;
 
	s1.resize(120);
	cout << s1.size() << "  " << s1.capacity() << endl;
 
   //由此发现resize影响capacity、size
   (当再开辟空间大于原先capacity才会影响capacity), 
   reserve不影响size
 
	//插入(空间不够扩容)
	string s2("hello world");
	s2.resize(20, 'x'); //不会清掉之前的字符,在后面填写
	cout << s2 << endl;
 
	// 删除
	s2.resize(5); 
}

11.c_str的比较

void test_string13()
{
	string a = "abc";
	string b = a;
 
	//a.c_str() == b.c_str()比较的是存储字符串位置的地址,
	// a和b是两个不同的对象,内部数据存储的位置也不相同,因此不相等
	if (a.c_str() == b.c_str())cout << "True" << endl;
	else cout << "False" << endl;
}

12.string的总接口的实现

        接口:

#define _CRT_SECURE_NO_WARNINGS 1
#pragma once
#include<iostream>
#include<assert.h>
using namespace std;

namespace bit
{
	class string
	{
	public:
		typedef char* iterator;
		typedef const char* const_iterator;

		iterator begin();
		iterator end();

		const_iterator begin() const;
		const_iterator end() const;

		//string();
		string(const char* str = "");
		string(const string& s);
		string& operator=(const string& s);
		~string();

		const char* c_str() const;

		size_t size() const;
		char& operator[](size_t pos);
		const char& operator[](size_t pos) const;

		void reserve(size_t n);

		void push_back(char ch);
		void append(const char* str);

		string& operator+=(char ch);
		string& operator+=(const char* str);

		void insert(size_t pos, char ch);
		void insert(size_t pos, const char* str);
		void erase(size_t pos = 0, size_t len = npos);

		size_t find(char ch, size_t pos = 0);
		size_t find(const char* str, size_t pos = 0);

		void swap(string& s);
		string substr(size_t pos = 0, size_t len = npos);

		bool operator<(const string& s) const;
		bool operator>(const string& s) const;
		bool operator<=(const string& s) const;
		bool operator>=(const string& s) const;
		bool operator==(const string& s) const;
		bool operator!=(const string& s) const;
		void clear();
	private:
		// char _buff[16];
		char* _str;

		size_t _size;
		size_t _capacity;

		//  
		//const static size_t npos = -1;

		// ֧
		//const static double N = 2.2;

		const static size_t npos;
	};

	istream& operator>> (istream& is, string& str);
	ostream& operator<< (ostream& os, const string& str);
}

接口的实现:

#include"string.h"

namespace bit
{
	const size_t string::npos = -1;

	//string::string()
	//{
	//	_str = new char[1]{'\0'};
	//	_size = 0;
	//	_capacity = 0;
	//}

	string::iterator string::begin()
	{
		return _str;
	}

	string::iterator string::end()
	{
		return _str + _size;
	}

	string::const_iterator string::begin() const
	{
		return _str;
	}

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

	// 21:10
	string::string(const char* str)
		:_size(strlen(str))
	{
		_str = new char[_size + 1];
		_capacity = _size;
		strcpy(_str, str);
	}

	// s2(s1)
	string::string(const string& s)
	{
		_str = new char[s._capacity + 1];
		strcpy(_str, s._str);
		_size = s._size;
		_capacity = s._capacity;
	}

	// s1 = s3
	// s1 = s1
	string& string::operator=(const string& s)
	{
		if (this != &s)
		{
			char* tmp = new char[s._capacity + 1];
			strcpy(tmp, s._str);
			delete[] _str;
			_str = tmp;
			_size = s._size;
			_capacity = s._capacity;
		}

		return *this;
	}

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

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

	size_t string::size() const
	{
		return _size;
	}

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

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

	void string::reserve(size_t n)
	{
		if (n > _capacity)
		{
			char* tmp = new char[n + 1];
			strcpy(tmp, _str);
			delete[] _str;

			_str = tmp;
			_capacity = n;
		}
	}

	void string::push_back(char ch)
	{
		/*if (_size == _capacity)
		{
			size_t newcapacity = _capacity == 0 ? 4 : _capacity * 2;
			reserve(newcapacity);
		}

		_str[_size] = ch;
		_str[_size + 1] = '\0';
		++_size;*/

		insert(_size, ch);
	}

	// "hello"  "xxxxxxxxxxxxx"
	void string::append(const char* str)
	{
		/*size_t len = strlen(str);
		if (_size + len > _capacity)
		{
			reserve(_size + len);
		}

		strcpy(_str+_size, str);
		_size += len;*/

		insert(_size, str);
	}

	string& string::operator+=(char ch)
	{
		push_back(ch);

		return *this;
	}

	string& string::operator+=(const char* str)
	{
		append(str);

		return *this;
	}

	void string::insert(size_t pos, char ch)
	{
		assert(pos <= _size);

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

		/*int end = _size;
		while (end >= (int)pos)
		{
			_str[end + 1] = _str[end];
			--end;
		}*/

		size_t end = _size + 1;
		while (end > pos)
		{
			_str[end] = _str[end - 1];
			--end;
		}

		_str[pos] = ch;
		++_size;
	}

	void string::insert(size_t pos, const char* str)
	{
		assert(pos <= _size);

		size_t len = strlen(str);
		if (_size + len > _capacity)
		{
			reserve(_size + len);
		}

		/*int end = _size;
		while (end >= (int)pos)
		{
			_str[end + len] = _str[end];
			--end;
		}*/

		size_t end = _size + len;
		while (end > pos + len - 1)
		{
			_str[end] = _str[end - len];
			--end;
		}

		memcpy(_str + pos, str, len);
		_size += len;
	}

	// 17:10
	void string::erase(size_t pos, size_t len)
	{
		assert(pos < _size);

		// len大于前面字符个数时,有多少删多少
		if (len >= _size - pos)
		{
			_str[pos] = '\0';
			_size = pos;
		}
		else
		{
			strcpy(_str + pos, _str + pos + len);
			_size -= len;
		}
	}

	size_t string::find(char ch, size_t pos)
	{
		for (size_t i = pos; i < _size; i++)
		{
			if (_str[i] == ch)
			{
				return i;
			}
		}

		return npos;
	}

	size_t string::find(const char* sub, size_t pos)
	{
		char* p = strstr(_str + pos, sub);
		return  p - _str;
	}

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

	string string::substr(size_t pos, size_t len)
	{
		// len大于后面剩余字符,有多少取多少
		if (len > _size - pos)
		{
			string sub(_str + pos);
			return sub;
		}
		else
		{
			string sub;
			sub.reserve(len);
			for (size_t i = 0; i < len; i++)
			{
				sub += _str[pos + i];
			}

			return sub;
		}
	}

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

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

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

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

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

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

	void string::clear()
	{
		_str[0] = '\0';
		_size = 0;
	}

	istream& operator>> (istream& is, string& str)
	{
		str.clear();
		char ch = is.get();
		while (ch != ' ' && ch != '\n')
		{
			str += ch;
			ch = is.get();
		}

		return is;
	}

	ostream& operator<< (ostream& os, const string& str)
	{
		for (size_t i = 0; i < str.size(); i++)
		{
			os << str[i];
		}

		return os;
	}
}

13.补充:大小写转换

transform(s.begin(),s.end(),s.begin(),::tolower);
transform(s.begin(),s.end(),s.begin(),::toupper);

13.2 substr取子串

str = str.substr(cnt); //取从cnt下标开始一直到结束的所有字符

str = str.substr(cnt,m); //取从cnt下标开始的m个字符

13.3 字符串与数字的相互转化

a、字符串转数字

1 .string s="12";

2 .int y=stoi(s);

b、数字转字符串

     string x=to_string(12);

14.string的相关题型

1.字符串相加

2.仅仅反转字母

3.字符串中第一个唯一字符

4.字符串中最后一个单词长度

5.验证回文串

6.字符串相加

7.反转字符串II

8.反转字符串III

9.字符串相乘

10.找出字符串中第一个只出现一次的字符

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

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

相关文章

提升写作技能:掌握ai写作免费生成器的高效使用法

最近&#xff0c;#沉浸式感受火把节#话题在网络上爆红&#xff0c;相关的宣传视频和文案铺天盖地。 但仔细观察&#xff0c;你会发现这些文案大多千篇一律&#xff0c;缺乏创意。火把节&#xff0c;这个充满激情与神秘的节日&#xff0c;难道就无法以更独特的方式呈现吗&#…

Linux:Linux权限解析

一、Linux下的用户分类 在Linux下&#xff0c;有两种用户&#xff0c;一种是超级用户&#xff0c;一种是普通用户 超级用户&#xff1a;可以再linux系统下做任何事情&#xff0c;不受权限限制&#xff08;制定规则&#xff0c;但不需要遵守规则&#xff09; 普通用户&#xff1…

Stable-Diffusion1.5

SD1.5权重&#xff1a;https://huggingface.co/runwayml/stable-diffusion-v1-5/tree/main SDXL权重&#xff1a;https://huggingface.co/stabilityai/stable-diffusion-xl-base-1.0/tree/main diffusers库中的SD代码pipelines&#xff1a;https://github.com/huggingface/di…

来点八股文(六) 网络Linux调优

性能指标 如何衡量程序的网络性能&#xff1f;你会看哪一层&#xff1f;看哪些指标&#xff1f;用哪些工具&#xff1f; 我们通常用带宽、吞吐量、延时、PPS&#xff08;Packet Per Second&#xff09;等指标衡量网络的性能。 应用层**[wrk、Jmeter]** **每秒处理请求数和延…

ComfyUI插件:ComfyUI-BrushNet节点

前言&#xff1a; 学习ComfyUI是一场持久战&#xff0c;而ComfyUI-BrushNet是最近的局部重绘节点&#xff0c;其包含BrushNet和Powerpaint两个主要节点&#xff0c;其中BrushNet有SD1.5和SDXL两个版本&#xff0c;PowerPaint只有1.5的模型可以使用&#xff0c;学会该插件&…

自动驾驶中的三维坐标系变换:原理、方法与实践

文章目录 1. 摘要2. 背景介绍2. 常用的坐标系定义2.1 全局坐标系&#xff08;Global Coordinate System&#xff09;2.2 车体坐标系&#xff08;Vehicle Coordinate System&#xff09;2.3 相机坐标系&#xff08;Camera Coordinate System&#xff09;2.4 图像坐标系&#xff…

Tech Talk: SSD架构与功能模块详解

在之前的系列文章中&#xff0c;我们介绍了固态硬盘的系列知识&#xff0c;包括闪存的介质、原理&#xff0c;以及作为SSD大脑的控制器设计&#xff0c;本文将详细介绍SSD架构以及功能模块。 SSD架构简介 ◎SSD架构示意图 如上图所示&#xff0c;典型的SSD架构包括主机接口、SS…

vue编译为render函数:模板编译过程

模板编译过程&#xff1a;模板编译为render函数&#xff0c;返回vnode。再执行diff和patch。 使用webpack&#xff0c;vue-loader,会在开发环境下编译模板。 虚拟dom和diff算法 1&#xff0c;将dom抽象为虚拟dom&#xff0c;diff算法对比新旧虚拟dom&#xff0c;只把变化的部…

瓜子二手车在财务中台结账核心系统 TiDBTiFlash 实践

作者&#xff1a; jshan 原文来源&#xff1a; https://tidb.net/blog/69f61649 一、前言 瓜子二手车&#xff0c;作为业界独树一帜的二手车电商平台&#xff0c;正以其创新力量重塑整个二手车行业。我们以用户为中心&#xff0c;致力于提供卓越的交易和服务体验&#xff0…

熊海1.0cmsPHP代码审计

熊海1.0cmsPHP代码审计 环境搭建 下载之后直接使用phpstduy搭建就好了 工具使用 比如使用seay审计系统 sql大多数是存在的&#xff0c;但是没有文件上传&#xff0c;这个就是需要自己去验证 漏洞审计 SQL注入 有点多&#xff0c;随便拿一个举例子 就比如我们的登录页面…

蚓链数字化生态系统:引领企业迈向数字化新时代

在当今竞争激烈的商业世界中&#xff0c;数字化转型已成为企业生存和发展的关键。然而&#xff0c;面对复杂的业务流程、海量的数据以及不断变化的市场需求&#xff0c;许多企业在数字化的道路上举步维艰。这时&#xff0c;蚓链数字化生态系统解决方案宛如一盏明灯&#xff0c;…

苹果手机清理软件:让你的iPhone保持最佳状态

随着iPhone成为我们生活中不可或缺的一部分&#xff0c;设备上积累的无用数据也在日益增多。这些数据不仅占据宝贵的存储空间&#xff0c;还可能影响设备的性能。幸运的是&#xff0c;市场上提供了多种苹果手机清理软件&#xff0c;帮助用户有效管理手机空间&#xff0c;提升设…

具有重加权位置和变换稀疏性的鲁棒非刚性配准算法 (RPTS)

该算法针对非刚性配准的问题。相较于刚性配准&#xff0c;非刚性配准更具有挑战性。要解决的问题通常是不适定的&#xff08;ill-posed&#xff09;、且自由度高&#xff0c;因此对噪声和异常值很敏感。为了提高非刚性配准算法对噪声和异常值的鲁棒性&#xff0c;李坤等人提出了…

【MetaGPT系列】【MetaGPT完全实践宝典——多智能体实践(辩论赛)构建】

目录 前言一、智能体1-1、Agent概述1-2、Agent与ChatGPT的区别 二、多智能体框架MetaGPT&#xff08;特朗普与拜登的二人辩论&#xff09;2-1、安装&配置2-2、使用已有的Agent&#xff08;ProductManager&#xff09;2-3、智能体对抗辩论——背景2-4、定义动作2-5、定义角色…

美亚科技现场检查问题不少:应收账款大幅攀升,与前员工交易金额巨大

《港湾商业观察》施子夫 6月27日&#xff0c;广东美亚旅游科技集团股份有限公司&#xff08;以下简称&#xff0c;美亚科技&#xff09;的IPO被北交所受理&#xff0c;保荐机构为广发证券。7月24日&#xff0c;北交所下发审核问询函。 此次IPO&#xff0c;美亚科技计划投资总…

GIS图形库更新2024.7.29-8.4

更多精彩内容请访问 dt.sim3d.cn Cesium 上周发布了1.120版本&#xff0c; ✨ 功能和改进 添加Transforms.computeIcrfToMoonFixedMatrix和Transforms.computeMoonFixedToIcrfMatrix这两个方法&#xff0c;用来计算给定时间内的月球固定坐标系和 ICRF&#xff08;国际天球参…

WLAN国家码与信道顺从表

国家码和信道顺从表及信道功率限制 不同的国家和地区规定了在本国或本地区可以使用的信道、射频信号在信道中的最大发射功率。工作在不同信道的射频信号&#xff0c;信号强度可能会有差别。国家码和信道顺从表、各信道的功率限制值、信道编号和频率对照关系请参见国家码和信道…

LED透明屏与LED显示屏

在当今数字化时代&#xff0c;显示技术的发展日新月异&#xff0c;LED显示屏作为其中的重要一员&#xff0c;已经渗透到我们生活的方方面面。而LED透明屏作为LED显示屏的创新产品&#xff0c;以其独特的优势在多个领域展现出巨大的应用潜力。本文将全面介绍LED透明屏与传统LED显…

18981 正方形和圆

这个问题可以通过计算正方形和圆的面积并比较它们的大小来解决。正方形的面积可以通过边长的平方来计算&#xff0c;圆的面积可以通过半径的平方乘以π来计&#xfffd;&#xfffd;&#xfffd;。 以下是使用C的代码实现&#xff1a; #include <iostream> #include &l…

云原生-利用容器和编排器

容器和编排器旨在解决单片部署方法中常见的问题。 1. 整体部署的挑战 传统上&#xff0c;大多数应用程序都是作为单个单元部署的。这样的应用程序被称为单体。这种将应用程序作为单个单元部署的一般方法&#xff08;即使它们由多个模块或程序集组成&#xff09;称为单体架构&…