自己来实现一个String类?干货!!!!详细!!!!

本文详细介绍了如何实现一个String类,包括迭代器获取元素、构造函数、赋值运算符、析构函数以及各种操作功能,如pushBack、reserve、resize、append和print。通过实例代码展示了String类与其他String对象、字符串和单个字符的相加操作。通过逐步理解并分模块实现,帮助读者掌握自定义类的基本构建过程。
摘要由CSDN通过智能技术生成

在这里插入图片描述

对于如何来实现一个String类,大多数人都会觉得很难,这个时候就有人要问了:

在这里插入图片描述
其实是很简单的,对于类这一部分的结构,都有着固定的结构,首先我们将一个简单的结构先敲出来,然后将就像在类的外部写函数一样,挨个的写就行了,首先我们先写一个大致的结构就像下面:

class String{
	
public:
	
	//==构造函数
	String()
	{}
	
	//==析构函数
	~String()
	{}

	//==拷贝构造函数

	//==拷贝复制函数
		
private:	
	//==成员变量
						
	//size:有效字符个数		//这里我们就直接把成员变量直接写入,比较简单,后面也不用单独分出来进行写
	size_t _size;
	//容量:最大存放字符的个数
	size_t _capacity;
	char* _data;
};

我上面写出的就是自己写一个类最最最基础的结构,首先你把这个结构记住了,再将你理解到的成员函数填充进去不就完了,一个板块一个板块的进行学习,最后拼接不就完了.这个只适用于String类哦,别记成万能模板了.

下面我们就进行分版块代码学习,最终拼接就可以了.

1.迭代器获取对应元素

关于迭代器我们在之前已经详细的讲过了,其中的接口也好多都进行了实现,有兴趣的可以看之前写的迭代器那一个,其实在这里我们完全没必要使用迭代器,使用就是为了提高我们的效率,再对之前使用迭代器的方式进行一个复习,让我们掌握的多一点.

1.我们在这里使用迭代器,就要先进行一个声明
2.写出利用迭代器的一些简单的函数,方便我们后面的利用

typedef char* iterator;		//先进行声明
typedef const char* const_iterator;

	iterator begin(){		//迭代器找到首元素

		//首元素的位置
		return _data;
	}

	const_iterator begin() const{	//迭代器找到首元素的位置

		//第一个元素的位置
		return _data;
	}

	iterator end(){

		//最后一个元素的下一个位置
		return _data + _size;
	}

	const_iterator end() const{

		//最后一个元素的下一个位置
		return _data + _size;
	}

2.构造函数

在构造函数这里我们运用了两种方式来进行构造,主要就是让我们能通过多个方法写一个相关的函数,不可能都是同一个把.

	//1
	String(const char* str = "")
		:_size(strlen(str))
		, _capacity(_size)
		, _data(new char[_size + 1])	//以上都是对于构造函数的一个初始化
		
	{
		strcpy(_data, str);		//将要输入的字符串拷贝在相关的内存里面
	}

//======================================
	//2
	String(const String& str)
		:_size(0)
		, _capacity(0)
		, _data(nullptr)		//以上为初始化
		
	{
		String tmp(str._data);	//创建一个新的_data
		Swap(tmp);				//调用Swap函数
	}

	//交换函数
	void Swap(String& str){		//引用的使用
		
		//对原来内部的大小,容量,以及内存全部进行交换,完全交换成一个新的
		swap(_size, str._size);
		swap(_capacity, str._capacity);
		swap(_data, str._data);		
	}

上面两种方法都是可以的,主要理解其中的意思就可以了

3.赋值运算符

对于被赋值有不同的接口,我们挨个进行书写.(里面有用多种方法实现的)

1) =
String& operator=(String str){

		Swap(str);		//直接将上面的函数进行调用即可
		return *this;
}
2) [ ]
char& operator[](size_t pos){

		assert(pos < _size);	//assert 函数相当于不满足条件,发现错误直接中断
		return _data[pos];		//返回对应的位置
}
3) [ ]

const型的直接无法改变

const char& operator[](size_t pos) const{

		assert(pos < _size);
		return _data[pos];
}
4) +=
String& operator+=(const String& str){	//String类类型

		append(str._data);		//对于+=的操作就相当于进行了一个尾插的作用,直接对你写好的进行调用就可以了
		return *this;
}
5) +=
String& operator+=(const char* str){	//字符串类型

		append(str);
		return *this;
}
6) +=
	String& operator+=(const char ch){	//单个字符的类型

		pushBack(ch);
		return *this;
}

这个版块并不是很难,但是主要你要区分String类的对象/字符串/和单个字符三种的对应方式

4.析构函数

析构函数这就没有什么多说的,进行挨个的删除就可以了

~String(){

		if (_data){

			delete[] _data;		//删除操作
			_data = nullptr;	//指针为空
			_size = _capacity = 0;	//内存全部变为0
		}
	}

5.相关的操作功能的实现

这里对于String类的部分常用接口进行实现

1)pushBack

在一个字符串的尾部添加上对应得数据

void pushBack(const char& ch){

		if (_size == _capacity){		//先判断其内存的容量是否够用

			size_t newC = _capacity == 0 ? 15 : 2 * _capacity;	//不够用则按照对应方式来进行扩容
			reserve(newC);	//调用已经写好的容量修改函数
		}

		_data[_size] = ch;	//在之前的字符后main进行添加,挨个进行++
		++_size;

		_data[_size] = '\0';	//进行++后将最后一位变成\0
	}

2)reserve

修改容量:只进行容量的增加,不能减小

void reserve(size_t n){

		if (n > _capacity){	//当需要扩容的内存大于现有内存的时候再进行扩容

			char* tmp = new char[n + 1];	//定义新的字符串

			strcpy(tmp, _data);	//进行拷贝

			delete[] _data;		//删除原来的字符串

			_data = tmp;	//指向新创建的
			_capacity = n;	//容量变大
		}
	}

3)resize

用来修改有效字符的个数

void resize(size_t n, const char& ch = '\0'){	

		if (n > _capacity){		//容量小于N的时候

			reserve(n);		//调用reserve函数
		}

		if (n > _size)		//当要增大有效复个数的时候
			memset(_data + _size, ch, sizeof(char)*(n - _size));	//执行memset操作

		_size = n;		//更新
		_data[_size] = '\0';	//最后一位要指向\0这样字符串才能结束
	}

4)append

类似于合并的操作,将两个字符串进行合并

void append(const char* str){

		int len = strlen(str);		//先确定长度
		if (_size + len > _capacity){	//在所需要的内存比较小的时候

			reserve(_size + len);		//进行扩容操作
		}

		memcpy(_data + _size, str, sizeof(char)* len);		//将需要合并的字符串拷贝进来

		_size += len;		//更新长度
		_data[_size] = '\0';	//最后一位必须是\0,确保字符串的结束
	}

5)print

三种不同的打印函数:
普通打印:

void printString(const String& str){		//简单引用操作

	for (int i = 0; i < str.size(); ++i){		//for循环

		cout << str[i] << " ";	//挨个进行输出
	}
	cout << endl;
}

字符串类进行打印:

void printFor(const String& str){

	for (const char& ch : str){		//范围确定

		cout << ch << " ";		//打印
	}
	cout << endl;
}

迭代器进行打印:

void printIterator(const String& str){

	String::const_iterator it = str.begin();	//迭代器确认开始位置
	while (it != str.end()){		//在没有遍历到最后一位的时候

		cout << *it << " ";		//进行解引用输出

		++it;		//依次++
	}
	cout << endl;
}

6)String类与String类/字符串/单个字符相加

String类+String类

String operator+(const String& str1, const String& str2){

	//这里的=和+=都是调用了之前我们写的赋值运算符
	String str = str1;	
	str += str2;			//String类之间直接相等使用
	return str;
}

String类+字符串

String operator+(const char* str1, const String& str2){

	String str(str1);
	str += str2;		//字符串就需要将其包裹在一个类里面
	return str;
}

String类+单个字符

String operator+(const char ch, const String& str2){

	String str = str2;
	str += ch;			//也需要将单个字符包裹在新的String类里面才能使用
	return str;
}

就这样分区域的样子进行分布代码的书写,多敲几次,理清自己的思路,你也就是大佬了!加油!

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值