IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 模拟实现string——下 -> 正文阅读

[C++知识库]模拟实现string——下

类对象的访问以及遍历操作

在这里插入图片描述

operator[]

由于string类的底层是连续的空间,因此可以实现使用[]+下标来访问并修改string对象的内容,需要注意一下的是最好需要重载一个const类型的成员函数,针对传入类型为const变量时使用。

		char& operator[](size_t pos)//模拟实现[]
		{
			assert(pos < _size);
			return _str[pos];
		}

		const char& operator[](size_t pos) const//模拟实现[]
		{
			assert(pos < _size);

			return _str[pos];
		}

访问和遍历string对象操作

for+[]下标访问

void Teststring()
{
	string s("hello Bit");
	// 3种遍历方式:
	// 需要注意的以下三种方式除了遍历string对象,还可以遍历是修改string中的字符,
	// 另外以下三种方式对于string而言,第一种使用最多
	// 1. for+operator[]
	for (size_t i = 0; i < s.size(); ++i)
	{
		cout << s[i] << " ";
	}
}

在这里插入图片描述

迭代器访问

void Teststring()
{
	string s("hello Bit");
	// 2.迭代器
	string::iterator it = s.begin();
	while (it != s.end())
	{
		cout << *it << " ";
		++it;
	}
	cout<<endl;
	string::reverse_iterator rit = s.rbegin();
	while (rit != s.rend())
	{
		cout << *rit << " ";
		rit++;
	}
}

可以使用反向迭代器进行逆序访问
在这里插入图片描述

范围for

void Teststring()
{
	string s("hello Bit");
	 //3.范围for
	for (auto ch : s)
	{
		cout << ch << " ";
	}
}

实际上范围for的底层还是由迭代器实现的,只有先实现了string类的迭代器才能正常使用范围for,下面会介绍如何实现string的迭代器。
在这里插入图片描述

at

at和[]功能类似,都是借助下标来访问string对象的内容,不同的是他们处理错误的方式不同,[]处理越界的方式是断言报错,at采用的方式是抛异常

void test_string5()
{
	string s1("hello wrold");
	cout<<s1.at(1)<<endl;
	cout << s1[1] << endl;
}

在这里插入图片描述

void test_string5()
{
	string s1("hello wrold");
	cout<<s1.at(1)<<endl;
	cout << s1[1] << endl;
	cout << s1.at(15) << endl;
	cout << s1[15] << endl;
}

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

string类的修改操作

在这里插入图片描述

push_back

push_back是给string尾插一个字符,需要考虑到扩容的问题,一般扩容是以2倍扩容,这边可以直接调用之前实现过的reserve函数来进行扩容

		void push_back(char ch)
		{
			if (_size == _capacity)
			{
				//增容
				reserve(_capacity * 2);
			}
			_str[_size] = ch;
			++_size;
			_str[_size] = '\0';
		}
void test_string6()
{
	hyx::string s1("hello wrold");
	cout << s1 << endl;
	s1.push_back('h');
	s1.push_back('h');
	s1.push_back('h');
	cout << s1 << endl;
}
		

在这里插入图片描述

append

append和push_back的区别在于append是在字符串后面加一个字符串。

void append(const char* str)
{
	size_t len = strlen(str);
	if (_size + len > _capacity)
	{
		reserve(_size + len);
	}
	strcpy(_str + _size, str);//从尾部开始拷贝
	_size += len;
	}
	void test_string7()
{
	hyx::string s1("hello wrold");
	cout << s1 << endl;
	s1.append("hello");
	cout << s1 << endl;
}

在这里插入图片描述

operator+=

这里运算符重载+=是结合了push_back和append的功能,既可以尾插字符也可以尾插字符串,通过函数重载即可实现。

		string& operator+=(char ch)
		{
			push_back(ch);
			return *this;
		}

		string& operator+=(const char* str)
		{
			append(str);
			return *this;
		}
	void test_string8()
{
	hyx::string s1("hello wrold");
	cout << s1 << endl;
	s1+='h';
	cout << s1 << endl;
	s1 += "hello ";
	cout << s1 << endl;
}

在这里插入图片描述

insert和erase

string类对象还支持中间位置的插入删除,使用insert和erase即可实现,但是需要注意的是string类对于中间位置的插入删除需要移动数据,消耗会比较大。

string& insert(size_t pos, char ch)
		{
			assert(pos <= _size);
			if (_size == _capacity)
			{
				reserve(_capacity == 0 ? 4 : _capacity * 2);
			}
			size_t end = _size + 1;
			while (end > pos)
			{
				_str[end] = _str[end - 1];
				end--;
			}
			_str[pos] = ch;
			_size++;
			return *this;

		}

		
		string& insert(size_t pos, const char* s)
		{
			assert(pos <= _size);
			size_t len = strlen(s);
			if (_size + len > _capacity)
			{
				reserve(_size + len);
			}
			size_t end = _size + len;
			while (end > pos + len)
			{
				_str[end] = _str[end - len];
				end--;
			}
			strncpy(_str, s, len);
			_size += len;
			return *this;
		}
		
		string& erase(size_t pos = 0, size_t len = npos)
		{
			assert(pos < _size);
			if (len == npos || pos + len >= _size)
			{
				_str[pos] = '\0';
				_size = pos;
			}
			else
			{
				strcpy(_str + pos, _str + pos + len);
				_size -= len;
			}
			return *this;
		}

string类操作

在这里插入图片描述

c_str

c_str是将string类转换为C类型的字符串

		const char* c_str() const//模拟实现c_str
		{
			return _str;
		}
		void test_string9()
{
	hyx::string s1("hello wrold");
	cout << s1.c_str() << endl;
}

在这里插入图片描述
这里需要注意的是之前能够直接使用流插入运算符来输出string对象是因为重载了流插入运算符,如果没有进行流插入运算符,则不能直接输出

find

find函数是用来查找string对象中的内容,既可以查找字符串,也可以查找单个字符,这里需要注意的是查找字符串可以从指定位置进行查找,默认从头进行查找

			size_t find(char ch)
		{
			for (size_t i = 0; i < _size; i++)
			{
				if (_str[i] == ch)
				{
					return i;
				}
			}
			return npos;
		}
				size_t find(char* s, size_t pos = 0)
		{
			const char* str = strstr(_str + pos, s);
			if (str == nullptr)
			{
				return npos;
			}
			else
			{
				return str - _str;
			}
		}
		void test_string10()
{
	hyx::string s1("hello wrold");
	cout << s1[s1.find('o')] << endl;
	cout << s1[s1.find("rol")] << endl;

}

在这里插入图片描述

npos

这里上面find,erase中都用到这个npos变量,这个变量是干什么的呢?实际上他是一个size_t 类型静态常量,大小定义为-1,由于是size_t类型,因此这个数可以用来代表整个字符串长度,他的定义如下:

//在类里面声明
static const size_t npos;
//在类外面定义
const size_t string::npos = -1;

<</>>

之前在友元函数一节中讲述过这种自定义类型,想要重载流插入、流提取运算符并且正常使用操作符和操作数,需要使用友元函数。

	std::ostream& operator<<(std::ostream& out, const string& s)
	{
		for (size_t i=0;i<s.size();i++)
		{
			out << s[i];
		}
		return out;
	}
		std::istream& operator>>(std::istream& in, string& s)
	{	
		s.clear();
		char ch = in.get();
		while (ch != ' ' && ch != '\n')
		{
			s += ch;
			ch = in.get();
		}
		return in;

	}

迭代器

string对象中的迭代器实际上是一个char*类型的指针。

typedef char* iterator;//迭代器
typedef const char* const_iterator;//迭代器
const_iterator begin() const//可以支持范围for 但是需要格式正确
{
	return _str;
}

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

iterator end()
{
	return _str + _size;
}

实现了迭代器后,可以使用迭代器访问string对象内容以及使用范围for,但是在string类中迭代器的优势并不明显,效率和方便性不如[]下标进行随机访问的方式,但是在后面的其他类中,会体现出他的价值。

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-04-18 17:22:53  更:2022-04-18 17:23:59 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 0:16:15-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码