【C++--string模拟实现】

一、基本思路

新建一个项目,在项目中创建头文件string.h 源文件string.cpp

在头文件中,先定义一个新的命名空间(为了防止与库中的string发生冲突),命名空间的名字可以按照自己意愿来命名。

接下来就可以在命名空间中来模拟实现string类辣

在实现的过程中可以多查查string::operator+= - C++ Reference (cplusplus.com)

了解函数功能,然后再去实现 

【1】确定成员变量: size_t _size; size_t _capacity; char* _str;

【2】成员函数模拟实现

(1)构造和析构函数

		string(const char* str = "")
		{
			_size = strlen(str);
			_capacity = _size;
			_str = new char[_size + 1];
		    my_strcpy(_str, str);//完成初始化工作
		}
		~string()
		{
			delete[] _str;
			_str = nullptr;
			_size = _capacity = 0;
			std::cout << "~string()" << std::endl;
		}

(2)size()和capacity()

		size_t size()const
		{
			return _size;
		}
		size_t capacity()const
		{
			return _capacity;
		}

(3)operator[ ]重载

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

(4)reserve()

		void reserve(size_t n = 0)
		{
			char* tmp = new char[n];//在堆区开辟空间,出函数不会销毁
			my_strcpy(tmp, _str);//由于有的vs使用strcpy会报错,所以可以用自己实现的strcpy
			delete[] _str;
			_str = tmp;
			_capacity = n;
		}

(5)push_back()

		void push_back(char c)
		{
			if (_size == _capacity)
			{
				reserve(_capacity == 0 ? 6 : _capacity * 2);
			}
			_str[_size] = c;
			_size++;
			_str[_size] = '\0';
		}

(6)operator+=的实现

		string& operator+= (char c)
		{
			push_back(c);
			return *this;
		}
		string& operator+= (const char* s)
		{
			size_t len = strlen(s);
			if (_size + len > _capacity)
			{
				reserve(_size + len+10);
			}
			append(s);
			return *this;
		}

(7)append()

		string& append(const char* s)
		{
			size_t len = strlen(s);
			if (_size + len > _capacity)
			{
				reserve(_size + len + 10);
			}
			my_strcpy(_str + _size, s);
			return *this;
		}

(8)c_str()

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

(9)operator<<

这个函数得在类外实现,因为在类内实现的话,默认第一个参数是this,那么在实际使用的时候对象名就得写在ostream的左边,与我们常规写法不一样。

由于库中的_str是私有成员,因此可以通过调用函数c_str来获取_str

std::ostream& operator<<(std::ostream& os, const abl::string& str)
{
	os << str.c_str() ;
	return os;
}

(10)拷贝构造

		//现代写法
	string(const string& s)
		:_str(nullptr)
		,_size(0)
		,_capacity(0)
	{
		string tmp(s._str);//调用默认构造函数string(const char* str = "")
		swap(tmp);//this可能没有初始化,析构的时候就会报错,因此要写参数初始化列表
	}
		//string(const string& s)
		//{
		//	_str = new char[s._capacity + 1];
		//	memcpy(_str, s._str, s._size);
		//	_size = s._size;
		//	_capacity = s._capacity;
		//}

(11)insert

		string& insert(size_t pos, size_t n, char c)
		{
			assert(pos <= _size);
			if (_size + n > _capacity)
			{
				reserve(_size + n);
			}
			size_t end = _size+n;
			for (; end>=pos+n; end--)
			{
				//abcd  size==4   pp  n==2  end==6  end-n==4
				_str[end] = _str[end-n];
			}
			for (size_t i = 0; i < n; i++)
			{
				_str[pos + i] = c;
			}
			_size += n;
			return *this;

		}
		string& insert(size_t pos, const char* s, size_t n)
		{
			assert(pos <= _size);
			size_t len = strlen(s);
			if (_size + n > _capacity)
			{
				reserve(_size + n);
			}
			size_t end = _size + n;
			for (; end >= pos + n; end--)//当pos==0时,end>=pos恒成立,因为end为size_t类型,不可能是负数
			{
				//abcd  size==4   pp  n==2  end==6  end-n==4
				_str[end] = _str[end - n];
			}
			for (size_t i = 0; i < n; i++)
			{
				_str[pos + i] = s[i];
			}
			_size += n;
			return *this;
		}

二、完整代码

1、string.h
#pragma once
#include <assert.h>
#include <cstring>
#include <iostream>
#include <stdio.h>
//#include<string.h>
void my_strcpy(char* dest, const char* src) {
	while (*src != '\0') {
		*dest++ = *src++;
	}
	*dest = *src;   //拷贝\0
}

namespace abl
{

	class string
	{
		//这里暂时还用不到友元,因为在operator>>中并没有访问string的私有成员
	//friend std::istream& operator>>(std::istream& in, string& s);
	private:
		size_t _size;
		size_t _capacity;
		char* _str;
		static size_t npos;
	public:
		
		typedef char* iterator;
		typedef const char* const_iterator;
		iterator begin()
		{
			return _str;//指向首元素
		}
		iterator end()
		{
			return _str + _size;//指向'\0'
		}
		const_iterator begin()const
		{
			return _str;
		}
		const_iterator end()const
		{
			return _str + _size;
		}
		string(const char* str = "")
		{
			_size = strlen(str);
			_capacity = _size;
			_str = new char[_size + 1];
		    memcpy(_str, str,_size+1);//完成初始化工作
		}
		~string()
		{
			//std::cout <<"::"<< _str << std::endl;
			delete[] _str;
			_str = nullptr;
			_size = _capacity = 0;
			std::cout << "~string()" << std::endl;
		}
		//现代写法
	string(const string& s)
		:_str(nullptr)
		,_size(0)
		,_capacity(0)
	{
		string tmp(s._str);//调用默认构造函数string(const char* str = "")
		swap(tmp);//this可能没有初始化,析构的时候就会报错,因此要写参数初始化列表
	}
		//string(const string& s)
		//{
		//	_str = new char[s._capacity + 1];
		//	memcpy(_str, s._str, s._size);
		//	_size = s._size;
		//	_capacity = s._capacity;
		//}

		void swap(string& tmp)
		{
			std::swap(_str, tmp._str);
			std::swap(_size, tmp._size);
			std::swap(_capacity, tmp._capacity);
		}
		//现代写法
		string& operator= (string& s)
		{
			if (this != &s)
			{
				string tmp(s);//调用拷贝构造(深拷贝)
				swap(tmp);
			}
			return *this;
		}
		size_t size()const
		{
			return _size;
		}
		size_t capacity()const
		{
			return _capacity;
		}
		char& operator[](size_t pos)
		{
			assert(pos <= _size);
			return _str[pos];
		}
		void reserve(size_t n = 0)
		{
			//多留出一个空位给\0
			char* tmp = new char[n+1];//在堆区开辟空间,出函数不会销毁
			my_strcpy(tmp, _str);
			delete[] _str;
			_str = tmp;
			_capacity = n;
			//只改变了capacity,没有改变size,size不变
		}
		void push_back(char c)
		{
			if (_size == _capacity)
			{
				reserve(_capacity == 0 ? 6 : _capacity * 2);
			}
			_str[_size] = c;
			_size++;
			_str[_size] = '\0';
		}
		string& operator+= (char c)
		{
			push_back(c);
			return *this;
		}
		string& operator+= (const char* s)
		{
			size_t len = strlen(s);
			if (_size + len > _capacity)
			{
				reserve(_size + len+10);
			}
			append(s);
			return *this;
		}
		string& append(const char* s)
		{
			size_t len = strlen(s);
			if (_size + len > _capacity)
			{
				reserve(_size + len + 1);
			}
			memcpy(_str + _size, s,len+1);
			_size += len;
			return *this;
		}
		string& insert(size_t pos, size_t n, char c)
		{
			assert(pos <= _size);
			if (_size + n > _capacity)
			{
				reserve(_size + n);
			}
			size_t end = _size+n;
			for (; end>=pos+n; end--)
			{
				//abcd  size==4   pp  n==2  end==6  end-n==4
				_str[end] = _str[end-n];
			}
			for (size_t i = 0; i < n; i++)
			{
				_str[pos + i] = c;
			}
			_size += n;
			return *this;

		}
		string& insert(size_t pos, const char* s, size_t n)
		{
			assert(pos <= _size);
			size_t len = strlen(s);
			if (_size + n > _capacity)
			{
				reserve(_size + n);
			}
			size_t end = _size + n;
			for (; end >= pos + n; end--)//当pos==0时,end>=pos恒成立,因为end为size_t类型,不可能是负数
			{
				//abcd  size==4   pp  n==2  end==6  end-n==4
				_str[end] = _str[end - n];
			}
			for (size_t i = 0; i < n; i++)
			{
				_str[pos + i] = s[i];
			}
			_size += n;
			return *this;
		}
		//string& erase(size_t pos = 0, size_t len = npos)
		//{

		//}
		bool operator<(string& s)const
		{
			size_t i1 = 0, i2 = 0;//遍历两个字符串4
			while (i1 < _size && i2 < s._size)
			{
				if (_str[i1] < s._str[i2])
				{
					return true;
				}
				else if (_str[i1] > s._str[i2])
				{
					return false;
				}
				else
				{
					i1++;
					i2++;
				}
			}
			//若循环正常进行结束,可能出现的情况:
			//hello hello     return false
			//hellowwww hello return false
			//hello hellowww  return true
			if (_size < s._size)
			{
				return true;
			}
			return false;
		}
		bool operator==(string& s)const
		{
			//std::cout << s._size << std::endl;
			if (_size != s._size)
			{
				return false;
			}
			return memcmp(_str, s._str, _size) == 0;
		}
		bool operator>(string& s)const
		{
			return !((*this < s) || (*this == s));
		}
		bool operator<=(string& s)const
		{
			return !(*this > s);
		}
		bool operator>=(string& s)const
		{
			return !(*this < s);
		}
		//string& operator= (const string& s)
		//{
		//	//开辟新空间,进行拷贝
		//	if (this != &s)//如果两个对象不相同
		//	{
		//		char* tmp = new char[s._capacity + 1];
		//		memcpy(tmp, s._str, s._size);
		//		delete[] _str;
		//		_str = tmp;
		//		_size = s._size;
		//		_capacity = s._capacity;
		//	}
		//	return *this;
		//}
		//void swap(string& str)
		//{
		//	
		//}
		//template<class T>
		//void swap(T m)
		//{
		//	T tmp = m;
		//	m = *this;
		//	*this = tmp;
		//}

		const char* c_str()const
		{
			return _str;
		}
		void clear()
		{
			_str[0] = '\0';
			_size = 0;
		}
	};
}
//std::ostream& operator<<(std::ostream& os, const abl::string& str)
//{
//	os << str._str << std::endl;
//	return os;
//}
size_t abl::string::npos = -1;//静态成员变量必须初始化,并且只能在类体外进行初始化
std::ostream& operator<<(std::ostream& out,const abl::string& str)
{
	for (auto ch : str)
	{
		out << ch;
	}
	//out << str.c_str();
	return out;
}
std::istream& operator>>(std::istream& in, abl::string& s)
{
	s.clear();
	char bucket[128];//相当于一个桶,装满了再往s里边加,减少了开辟空间的次数,充分利用空间
	char c=in.get();
	int i = 0;
	while (c != ' ' && c != '\n')
	{
		bucket[i] = c;
		i++;
		
		if (i == 127)
		{
			bucket[i] = '\0';//operator+=中要计算bucket的长度,以'\0'为终止条件,因此要在最后加上
			s += bucket;
			i = 0;//重新往buckt里边放入数据
		}
		c = in.get();
	}
	if (i != 0)
	{
		bucket[i] = '\0';//...
		s += bucket;
	}

	return in;
}
2、string.cpp
#include <iostream>
#include <cstring>
#include "String.h"
using namespace std;

void test_string1()
{
    abl::string s1("hello world");
    abl::string s2("legacy.cplusplus.com");
    string s3("jdksanxkdsd");
    string s4;
    cout << s3.c_str() << endl;
    cout << s4.c_str() << endl;
    cout << s1.c_str() << endl;
    for (size_t i = 0; i < s1.size(); i++)
    {
        cout << s1[i] << " ";
    }
    cout << endl;
    cout << s2.c_str() << endl;
    abl::string::iterator it = s2.begin();
    while(it!=s2.end())
    {
        cout << *it << " ";
        ++it;
    }
    cout << endl;
    cout << s2 << endl;
}
void test_string2()
{
    //string s1("hello");
    //cout << s1 << endl;
    //cout << s1.capacity() << endl;

    //abl::string s2("world");
    cout << s2.capacity() << endl;
    //s2.push_back('c');
    //s2.push_back('c');
    //s2.push_back('c');
    //cout << s2 << endl;
    //s2 += 's';
    //cout << s2 << endl;
    //s2 += "good";
    //cout << s2 << endl;
    abl::string s3("hello");
    s3.append(" judy");
    cout << s3 << endl;
    //abl::string s4("helloooo");
    s4 += '\0';
    //cout << s4 << endl;
    //s4 += "wwwwwww";
    //s4.insert(2, 3, 'y');
    //cout << s4 << endl;
    //abl::string s5("hello");
    //s5.insert(2, 5, 'p');
    //cout << s5 << endl;
    //s5.insert(9, "world", 6);
    //cout << s5 << endl;
    //for (auto ch : s5)
    //{
    //    cout << ch;
    //}
    //cout << endl;

    //string s6;
    //cin >> s6;
    //cout << s6 << endl;
    //cin >> s6;
    //cout << s6;
   /* cout << s4.npos << endl;*/
}
void test_string3()
{
    abl::string s1("hello");
    abl::string s2("helloxxxxx");
    //cout << (s2 < s1) << endl;
    abl::string s3("hello");
    //cout << (s1 == s2) << endl;
    //cout << (s1 == s3) << endl;
    cout << (s2 >= s3) << endl;
    cout << (s1 >= s2) << endl;
    cout << (s1 >= s3) << endl;
}
void test_string4()
{
    abl::string s1("helloxxxxxxxxxxx");
    //abl::string s2;
    //s2 = s1;
    //cout << s1 << endl;
    //cout << s2 << endl;
    //s1.append(" world");
    abl::string s2("worldxxx");
    s1 = s2;
    cout << s1 << endl;
    cout << s2 << endl;
}
int main()
{
    //test_string4();
    string s("hello world");
    string::iterator it = s.begin();
    while (it != s.end())
    {
        *it = 'x';
        it++;
    }
    cout << s << endl;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

伱恏呀呀呀呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值