当前位置:   article > 正文

模拟实现string类_模拟实现stringfy

模拟实现stringfy

string类的模拟实现

本文只是对部分函数进行分析和代码展示,具体代码我已经上传到GitHub上面了

GitHub链接:https://github.com/Sveter/CPlusPlus

  • string类
  1. string是表示字符串的字符串类
  2. 该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。
  3. string在底层实际是:basic_string模板类的别名,typedef basic_string<char, char_traits, allocator>string;
  4. 不能操作多字节或者变长字符的序列。
模拟实现
  • String.h
#ifndef __STRING_H__
#define __STRING_H__

#include <iostream>
#include <string.h>
unsig namespace std;

class String
{
//为了实现迭代器
public:
	typedef char* Iterator;
public:
    //默认成员函数
    //构造函数以及构造函数的重载
    String()
    {}
    String(const char* str)
	{
		if (nullptr == str)
		{
			str = "";
		}
		_size = strlen(str);
		_str = new char[_size + 1];
		_capacity = _size;

		strcpy(_str, str);
	}
	String(const char* str, size_t size)
	{
		if (size < 0)
		{
			cout << "size error" <<endl;
			exit(EXIT_SUCCESS);
		}
		_size = size;
		_str = new char[_size + 1];
		_capacity = _size;
		strncpy(_str, str, size);
		if (size < strlen(str))
		{
			_str[_size] = 0;
		}
	}
    //拷贝构造函数
	//采用深拷贝的传统写法
	String(const String& s)
		:_str(new char[s._capacity+1])
		,_capacity(s._capacity)
		,_size(s._size)
	{
		strcpy(_str, s._str);
	}
	//深拷贝的现代版写法
	//String(const String& s)
	//{
	//	String strTmp(s._str);
	//	swap(_str, strTmp);
	//}
	//赋值运算符的重载
	String& operator=(const String& s)
	{
		if (&s != this)
		{
			char* pStr = new char[s._capacity + 1];
			strcpy(pStr, s._str);
			delete[] _str;
			_str = pStr;
			_size = s._size;
			_capacity = s._capacity;
		}
		return *this;
	}
	//析构函数
	~String()
	{
		if (_str)
		{
			delete[] _str;
			_str = nullptr;
			_capacity = 0;
			_size = 0;
		}
	}
    //成员函数
    //1. 迭代器
    Iterator Begin();
	Iterator End();
	  //反向查找
	Iterator RBegin();
	Iterator REnd();
	
	//2. 增删改查
	void PushBack(char c); //尾插字符
	void Append(const char* str); //追加字符串
	String& Insert(size_t pos, char c); //在指定位置插入字符
	String& Insert(size_t pos, const char* str); //在指定位置插入字符串
	String& Erase(size_t pos, size_t len); 	//删除指定位置,指定长度的内容
	void Resize(size_t newSize, char c = '0'); //调整大小
	void Reserve(size_t newCapacity); //扩容
	int Size()const; //查询字符串大小
	int Capacity()const; //查询容量
	bool Empty()const; //判断是否为空
	void Clear(); //清空
	int Find(char c, size_t pos = 0); //查找字符第一次出现的位置
	int rFind(char c); //从后往前查找字符第一次出现的位置
	void Swap(String& s); //字符串交换
	String SubStr(size_t pos, size_t size); //截取字符串
	const char* C_Str()const; //以C的形式输出
	
	//3. []的重载
	char& operator[](size_t index);
	const char& operator[](size_t index)const;
	
	//4. 运算符的重载
	bool operator<(const String& s);
	bool operator<=(const String& s);
	bool operator>(const String& s);
	bool operator>=(const String& s);
	bool operator==(const String& s);
	bool operator!=(const String& s);
	String operator+(char c); //+符号的重载
	String operator+(const char* str)
	String operator+=(char c) 	//+=符号的重载
	String operator+=(const char* str)
	
	//<<&>>的重载
	friend ostream& operator<<(ostream& _cout, const String& s)
	friend istream& operator>>(istream& _cin, String& s)
private:
    char* _str;
	size_t _capacity;
	size_t _size;
    //find函数没找到的返回值
    const static int npos;
};

const int String::npos = -1;

#endif //!__STRING_H__
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 在这里我仅对部分成员函数分析

  • 1. 构造函数和拷贝构造函数

  1. 构造函数是创建一个对象,然后给_str变量申请内存,再设置好_size和_capacity变量
  2. 拷贝构造函数这里分为浅拷贝和深拷贝,我们用深拷贝,在编译器中默认是浅拷贝,最终导致的问题是,共用同一块内存空间,在释放时同一块空间被释放多次而引起程序崩溃

浅拷贝和深拷贝

在这里插入图片描述

  • 2. 赋值运算符重载

赋值运算符重载和拷贝构造函数存在同样的问题,在这里我们用的也是深拷贝的方式

  • Insert()
  1. 先判断是否需要扩容
  2. 把pos位置之后的字符都向后挪一位,在pos位置插入指定字符
String& Insert(size_t pos, char c)
	{
		if (_size + 1 >= _capacity)
		{
			Reserve(_capacity * 2);
		}
		_str[_size + 1] = '\0';
		for (int i = _size; i > pos; i--)
		{
			_str[i] = _str[i - 1];
		}
		_str[pos] = c;
		++_size;
		return *this;
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • Erase()

第一种,pos位置之后的字符个数大于n,pos之后全删

第二种,pos位置之后的字符个数小于n,则我们需要在pos之后删除n个元素

String& Erase(size_t pos, size_t len)
	{
		//删除的数据未超过字符串长度
		if (pos + len <= _size)
		{
			while (_str[pos + len] != '\0')
			{
				_str[pos] = _str[pos + len];
				pos++;
			}
			_str[pos] = _str[pos + len];
			_size = strlen(_str);
		}
		else
		{
			_str[pos] = _str[_size];
			_size = strlen(_str);
		}
		return *this;
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
测试
void TestString1()
{
	String s1;
	String s2("hello world");
	String s3(s2);
	s1 = s3;
	cout << s1 << endl;
	cout << s2 << endl;
	cout << s3 << endl;
}
void TestString2()
{
	String s1("hello");
	s1.PushBack(' ');
	s1.PushBack('1');
	s1.Append("31");
	s1 += '4';
	cout << s1 << endl;
	cout << s1.Size() << endl;
	cout << s1.Capacity() << endl;
	// 利用迭代器打印string中的元素
	auto it = s1.Begin();
	while (it != s1.End())
	{
		cout << *it++;
	}
	cout << endl;
	String s2("hello world!!!");
	s1.Swap(s2);
	cout << s1 << endl;
	cout << s2 << endl;
}

void TestString3()
{
	String s("hello");
	cout << s << endl;
	cout << s.Size() << endl;
	cout << s.Capacity() << endl;
	s.Resize(10, 'a');
	cout << s << endl;
	cout << s.Size() << endl;
	cout << s.Capacity() << endl;
	s.Resize(20);
	cout << s << endl;
	cout << s.Size() << endl;
	cout << s.Capacity() << endl;
	s.Resize(5);
	cout << s << endl;
	cout << s.Size() << endl;
	cout << s.Capacity() << endl;
	s.Reserve(50);
	cout << s << endl;
	cout << s.Size() << endl;
	cout << s.Capacity() << endl;
}

void TestString4()
{
	String s1("abcdefg");
	String s2 = s1;
	cout << s1 << endl;
	s1.Insert(2, 'h');
	cout << s1 << endl;
	s1.Insert(2, "123");
	cout << s1 << endl;
	s2.Erase(2, 5);
	cout << s2 << endl;
}

void TestString5()
{
	String s1 = "abcdef";
	String s2 = "abcdh";
	cout << (s1 < s2) << endl;
	cout << (s1 > s2) << endl;
	cout << (s1 == s2) << endl;
	cout << (s1 != s2) << endl;
	cout << (s1 >= s2) << endl;
	cout << (s1 <= s2) << endl;
}

int main()
{
	cout << "Test1: 默认成员函数" << endl;
	TestString1();
	cout  << endl;
	cout << "Test2: Iterators + Modifiers" << endl;
	TestString2();
	cout << endl;
	cout << "Test3: Capacity" << endl;
	TestString3();
	cout << endl;
	cout << "Test4: Modifiers" << endl;
	TestString4();
	cout << endl;
	cout << "Test5: 比较" << endl;
	TestString5();
	cout << endl;

	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102

在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/490442
推荐阅读
相关标签
  

闽ICP备14008679号