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++知识库 -> C++ string类模拟实现 -> 正文阅读

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

目录

1.创建string类

2.默认成员函数的模拟实现

2.1 Constructor(构造函数)

函数实现:

2.2 Destructor(析构函数)

函数实现:

2.3 拷贝构造函数

函数实现:

2.4 Operator=(赋值运算符的重载)

函数实现:

测试代码:

3.Capacity(容量)

函数实现:

测试代码:

?

4.Element access(元素访问)

测试代码:

5.Iterators?(迭代器)

函数实现:

测试代码:

?6.Madifiers(修改器)

函数实现:

?测试代码:

7.比较运算符重载?

函数实现:

测试代码:?

8.Non-member function overloads(非函数成员重载)?

函数实现:

测试代码:

9.String operators(字符串操作)

函数实现:

测试代码:

?


1.创建string类

类的结构:

?
namespace stl
{
	class string
	{
//成员函数
public:

//成员变量
private:
		char* _str;
		size_t _size;
		size_t _capacity;
public:
		const static size_t npos = -1;
	};

?

  • _str:字符数组
  • _size:有效元素个数
  • _capacity:数组容量

2.默认成员函数的模拟实现

2.1 Constructor(构造函数)

功能:完成对象的初始化工作

函数实现:

string()//无参的默认构造函数
			:_str(new char[1]),//开一个空间用来存储\0
			_size(0),
			_capacity(0)
		{
			_str[0]='\0';
		}

string(const char* str)//参数是字符串的构造函数
		{
			_size = strlen(str);//有效字节和容量设置为不带\n的长度
			_capacity = _size;
			_str = new char[_capacity+1];//开空间的时候要包含\0
			strcpy(_str,str);//strcpy会把原串中的\0也拷贝过来
		}

注意:

首先我们用STL的string类创建一个对象,可以发现尽管size是5,但在size之后的位置被初始化为了\0,所以模拟实现的string的字符数组下表size的位置为\0

环境:vs2022

2.2 Destructor(析构函数)

?功能:完成对象的清理工作

函数实现:

~string()//析构函数
		{
			delete[] _str;
			_size = 0;
			_capacity = 0;
		}

注意:new/delete 和 new[]/delete[]配套使用,不然会发生难以预料的事情

2.3 拷贝构造函数

功能:用已存在的类类型对象创建新的对象

函数实现:

void swap(string& tmp)//这是自己定义的交换函数,第一个参数是隐含的this指针,交换两个类的成员变量
		{
			::swap(_str, tmp._str);//加::操作符表示调用的是全局的swap函数
			//_str和tmp._str都是指针,交换指向的空间的地址
			::swap(_size, tmp._size);
			::swap(_capacity, tmp._capacity);
		}

		string(const string& s)
			:_str(nullptr),//初始化列表这里是被交换到tmp临时类中的值,当该函数调用结束时,由tmp自动调用析构函数
			_size(0),
			_capacity(0)
		{
			string tmp(s._str);//调用写好的析构函数创建临时类
			swap(tmp);//交换它们
		}

注意:

拷贝构造涉及到内存申请的操作,需要使用深拷贝来进行拷贝构造

2.4 Operator=(赋值运算符的重载)

功能:两个已存在的类对象之间可以像内置类型一样赋值

函数实现:

void swap(string& tmp)//这是自己定义的交换函数,第一个参数是隐含的this指针,交换两个类的成员变量
		{
			::swap(_str, tmp._str);//加::操作符表示调用的是全局的swap函数
			//_str和tmp._str都是指针,交换指向的空间的地址
			::swap(_size, tmp._size);
			::swap(_capacity, tmp._capacity);
		}

string& operator=(string s)//使用传值传参,调用拷贝构造创建临时类s接收需要赋值的string类
		{
			swap(s);//交换它们
			return *this;//返回this指向的类
		}//结束时临时类s销毁,自动调用析构函数

注意:

赋值重载是默认成员函数,不显示定义在类里面会生成一个默认的赋值重载,不可在类外定义


测试代码:

?
void test_string1()//测试完成
{
	cout << "构造、拷贝构造、赋值" << endl;
	string s;
	cout << s << endl;
	string s2("hello");
	cout << s2 << endl;
	s = s2;
	cout << s2 << endl;
}

3.Capacity(容量)

功能:操作字符串容量

函数实现:

size_t size()const
	{
		return _size;//返回有效元素数
	}
size_t capacity()const//返回容量
	{
		return _capacity;
	}
void reserve(size_t n)//设置数组容量
{
	开新空间,拷贝旧空间数据,释放旧空间
	if (n > _capacity)
	{
		char* tmp = new char[n + 1];
		strcpy(tmp, _str);

		delete[] _str;
		_str = tmp;
		_capacity = n;
	}
}

void resize(size_t n, char ch)//设置有效字符个数
		{
			if (n > _size)//插入数据
			{
				reserve(n);
				for (size_t i = _size; i < n; i++)
				{
					_str[i] = ch;
				}
				_str[n] = '\0';
				_size = n;

			}
			else//删除数据
			{
				_str[n] = '\0';
				_size = n;
			}
		}

测试代码:

void test_string2()//测试完成
{
	cout << "capacity(容量测试) " << endl;
	string s1("hello");
	cout << "size->  " << s1.size() << endl;
	cout << "capacity->  " << s1.capacity() << endl;
	s1.reserve(100);
	cout << "reserve(100)扩容后的capacity->  " <<s1.capacity() << endl;
	s1.resize(20, 'h');
	cout << "resize(20)后的->size  " << s1.size() <<"   "<< s1 << endl;
	s1.resize(10, 'h');
	cout << "resize(10)后的->size  " << s1.size() << "   " << s1 << endl;
	cout << s1 << endl;
}

?

4.Element 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];
	}

测试代码:

void test_string3()//测试完成
{
	cout << "函数访问测试" << endl;
	string s("hello world!");
	for (size_t i = 0; i < s.size(); i++)
	{
		s[i]++;
		cout << s[i] << "-";
	}
	cout << " " << endl;
	cout << s << endl;

	const string s1("hello world!");
	for (size_t i = 0; i < s1.size(); i++)
	{
		cout << s1[i] << "-";
	}
	cout << " " << endl;
	cout << s1 << endl;
}

5.Iterators?(迭代器)

功能:访问数组元素

函数实现:

typedef char* iterator;//string迭代器其实就是原生指针
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;
	}

测试代码:

void test_string4()//测试完成
{
	cout << "Iterators(迭代器)测试" << endl;
	string s("hello world");
	string::iterator it = s.begin();
	while (it != s.end())
	{
		(* it)++;
		cout << *it << "-";
		it++;
	}
	cout << endl;

	const string s1("hello world");
	string::const_iterator it2 = s1.begin();
	while (it2 != s1.end())
	{
		cout << *it2 << "-";
		it2++;
	}
	cout << endl << endl;;
	for (auto ch : s1)
	{
		cout << ch << "-";
	}
	cout << endl;
}

?6.Madifiers(修改器)

功能:对数组元素进行增删查改

函数实现:

void push_back(char ch)//复用instert就行
    {
		instert(_size, ch);
	}
void append(const char* str)//复用instert就行
	{
		instert(_size, str);
	}
string& instert(size_t pos,char ch)//pos位置插入单个字符
	{
		if (_size == _capacity)//判断需不需要扩容
		{
			reserve(_capacity == 0 ? 4 : _capacity * 2);
		}
        size_t end = _size+1;//从结尾开始,前面的数据挪到后面
		while (end >= pos)
		{
			_str[end] = _str[end-1];//从后往前挪,避免0下表位置出错
			end--;//end是size_t类型,0减一就成了整型的最大值
		}
		_str[pos] = ch;
		_size++;

		return *this;
	}

string& instert(size_t pos, const char* ch)//pos位置插入一个字符串
	{
		assert(pos < _size);
		size_t len = strlen(ch);
		if (len + _size > _capacity)
		{
			reserve(_size+len);
		}
		size_t end = _size + len;
		while (end >= pos+_size)
		{
			_str[end] = _str[end - len];
			end--;
		}
		strncpy(_str + pos, ch, len);
		_size+=len;

		return *this;
	}

string& operator+=(const char* str)//复用
    {
		append(str);
		return *this;
	}
string& operator+=(char c)//复用
	{
		push_back(c);
		return *this;
	}
void erase(size_t pos, size_t len=npos)//pos位置删除len个字符
{
	assert(pos < _size);
    if (len == npos || pos + len > _size)//不传参数和参数大于有效元素个数直接删除pos后所有字符
    {
	    _str[pos] = '/0';
	    _size = pos;
    }
	else
	{
		strcpy(_str + pos, _str + pos + len);//strcpy支持对原字符串的覆盖拷贝
		_size = _size - len;
	}
}

?测试代码:

	
void test_string5()//测试完成
{
	cout << "madifiers(修改器)测试 " << endl << endl;
	string s("hello world");
	s.push_back('-');
	s.push_back('-');
	s.push_back('-');
	cout << s << endl;

	s.append("&test&");
	cout << s << endl<<endl;

	s.resize(11,'0');
	cout << "resize重置字符串->"<< s << endl;

	s += '-';
	s += '-';
	s += '-';
	cout << s << endl;
	s += "test";
	cout << s << endl;

	string s1("123456789");
	s1.erase(3, 5);
	cout << s1 << endl;
	s1.erase(3);
	cout << s1 << endl;
}

7.比较运算符重载?

功能:实现两个string对象之间的运算符操作

函数实现:

bool operator<(const string& s)//实现一个小于和等于,其他运算符可以复用
	{
		size_t i = 0;
		while (_str[i] == s._str[i])
		{
			if (i == _size || i == s._size)
				break;
			++i;
		}
		return _str[i] < s._str[i];
	}

	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 || *this == s;
	}

	bool operator==(const string& s)
	{
		size_t i = 0;
		while (_str[i] == s._str[i])
		{
			if (i == _size || i == s._size)
				break;
			++i;
		}
		if (i == _size && i == s._size)
			return true;
		return false;
	}

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

测试代码:?

void test_string6()//测试成功
{
	cout << "运算符重载的测试" << endl;

	string s1("123");
	string s2("122");

	cout<<"123==122--" << (s1 == s2)<< endl;
	cout << "123>122--" << (s1 > s2) << endl;
	cout << "123>=122--" << (s1 >= s2) << endl;
	cout << "123 <= 122--" << (s1 <= s2) <<endl;
	cout << "123<122--" << (s1 < s2) << endl;
	cout << "123!=122--" << (s1 != s2) << endl;
}

8.Non-member function overloads(非函数成员重载)?

功能:略

函数实现:

ostream& operator<<(ostream& out, const string& s)//流插入重载
{
	out << s.c_str();
	return out;
}
istream& operator>>(istream& in, string& s)//流提取重载
{
	char ch;
	ch=in.get();
	const int N = 32;
	size_t i = 0;
	char buff[N];
	while (ch != ' ' && ch != '\n')
	{
		buff[i++] = ch;
		if (i == N - 1)
		{
			buff[i] = '\0';
			i = 0;
			s += buff;
		}
		ch = in.get();
	}
	buff[i] = '\0';
	s += buff;
	return in;
}

测试代码:

void test_string7()//测试成功
{
	cout << "Non-member function overloads(非函数成员重载)?的测试" << endl;

	string s("123456");
	cin >> s;
	cout << s << endl;
}

9.String operators(字符串操作)

功能:对字符串进行操作

函数实现:

	size_t find(char ch, size_t pos = 0)const//查找单个字符,从pos位置开始
	{
		for (size_t i = pos; i < _size; i++)
		{
			if (_str[pos] == ch)
			{
				return i;
			}
			else
				return npos;
		}
	}
		size_t find(char* sub, size_t pos = 0)const//查找字符串,从pos位置开始
		{
			const char* ptr = strstr(_str + pos, sub);
			if (ptr != nullptr)
			{
				return ptr - _str;
			}
			else
			{
				return npos;
			}
		}
char* c_str()const//返回C格式的字符串
		{
			return _str;//因为开空间时为数组预留了/0,直接返回数组即可
		}

string substr(size_t pos, size_t len = npos)//从pos截取字符串中某一段字符,不指定len就截取从pos                    
                                              //后的所有字符
		{
			size_t rallLen = len;
			if (rallLen == npos || rallLen + pos > _size)
			{
				rallLen = _size - pos;
			}
			string sub;
			for (size_t i = 0; i < rallLen; i++)
			{
				sub += _str[pos+i];
			}
			return sub;
		}

测试代码:

void test_string8()//测试成功
{
	cout << "String operators(字符串操作)测试"<< endl;
	string s("0123456789");
	cout << s.find('2') << endl;
	cout << s.find("123") << endl;

	cout << s.c_str() << endl;

	cout<<s.substr(2, 6)<<endl;
}

?

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-09-13 10:54:41  更:2022-09-13 10:58:57 
 
开发: 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年5日历 -2024/5/18 7:49:29-

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