模擬實現String類(C++)

以下就是String類的模擬實現:
測試環境爲VS2013

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<stdlib.h>
#include<assert.h>

using namespace std;


class String
{
private:
	friend ostream& operator<<(ostream& _cout, const String& s);
	char* _str;
	size_t _size;
	size_t _capacity;
public:
	static const size_t npos;
	typedef char* iterator;
	typedef const char* const_iterator;
	
	//構造函數
	String(char* str = "")
		:_str(new char[strlen(str+1)])
	{
		assert(str != nullptr);
		_size = strlen(str);
		_str = new char[_size + 1];
		strcpy(_str, str); //包括'\0'
		_capacity = _size;
	}

	//拷貝構造函數
	String(const String& s)
		:_str(new char[strlen(s._str + 1)])
	{
		strcpy(_str, s._str);
	}

	//賦值運算符重載
	String& operator= (const String&s)
	{
		//先判斷是否給自己賦值
		if (this != &s)
		{
			delete[] _str;
			_str = nullptr;
			_str = new char[strlen(s._str + 1)];
			strcpy(_str, s._str);
		}
		return *this;
	}

	//operator[]重載,可讀可寫接口
	char& operator[](size_t pos)
	{
		assert(pos < _size);
		return _str[pos];
	}

	//const接口
	const char& operator[](size_t pos) const
	{
		assert(pos < _size);
		return _str[pos];
	}

	//迭代器
	iterator begin()
	{
		return _str;
	}

	iterator end()
	{
		return (_str + _size);
	}

	const iterator begin() const
	{
		return _str;
	}

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

	size_t Size() const
	{
		return _size;
	}

	//析構函數
	~String()
	{
		if (_str)
		{
			delete[] _str;
			_str = nullptr;
			_size = _capacity = 0;
		}
	}

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


	//只增容,不減少容量,拷貝原有內容,釋放原有空間
	void Reserve(size_t n)
	{
		if (n > _capacity)
		{
			char* tmp = new char[n + 1];
			strcpy(tmp, _str);
			//釋放原有空間
			delete _str;
			//指向新的空間
			_str = tmp;
			//更新容量
			_capacity = n;
		}
	}

	//尾插
	void PushBack(char c)
	{
		//驗容
		if (_size == _capacity)
		{
			size_t newC = (_capacity == 0 ? 15 : 2 * _capacity);
			Reserve(newC);
		}

		_str[_size] = c;
		_size++;
		_str[_size] = '\0';
	}

	
	//尾刪
	void PopBack()
	{
		if (_size > 0)
		{
			_size--;
			_str[_size] = '\0';
		}
	}
	

	void Resize(size_t n, char c)
	{
		if (n > _capacity)
		{
			Reserve(n);
		}

		if (n > _size)
			// _size < n <= _capacity
		{
			//按字節複製
			memset(_str + _size, c, n - _size);
		}
		_size = n;
		_str[_size] = '\0';
	}

	//刪除
	void Erase(size_t pos, size_t len)
	{ 
		//刪除的位置要合法
		assert(pos < _size);
		if (pos + len >= _size)
		{
			_size = pos;
			_str[_size] = '\0';
		}

		else
		{
			//從pos+len開始向前每次移動len 個字符
			for (size_t i = pos + len; i <= _size; i++)
			{
				_str[pos] = _str[i];
				pos++;
			}
			_size -= len;
		}
	}

	//追加
	void Append(const char* str)
	{
		size_t sz = strlen(str);
		if (_size + sz > _capacity)
		{
			Reserve(_size + sz);
		}
		strcpy(_str + _size, str);
		_size += sz;
	}

	//插入字符
	void Insert(size_t pos, char c)
	{
		assert(pos <= _size);
		//增容
		if (_size == _capacity)
		{
			size_t newCapacity = (_capacity == 0 ? 15 : 2 * _capacity);
			Reserve(newCapacity);
		}

		//元素依次向後移動,留出位置
		size_t end = _size;
		for (size_t i = end; i >= pos; i--)
		{
			_str[i] = _str[i - 1];
		}
		_str[pos] = c;

		_size++;
		_str[_size] = '\0';
	}

	//插入字符串
	void Insert(size_t pos, const char* str)
	{
		assert(pos <= _size);
		size_t len = strlen(str);
		//因爲要插入字符串,字符串的長度不確定,可短可長,所以增容不能只單單地增加2倍
		if (_size + len > _capacity)
		{
			Reserve(_size + len);
		}
		size_t end = _size + len;
		while (end > pos+len-1)
		{
			_str[end] = _str[end - len];
			--end;
		}

		while (*str)
		{
			_str[pos] = *str;
			pos++;
			str++;
		}
		_size += len;
	}


	//查找字符
	size_t Find_Ch(char c)
	{
		for (size_t i = 0; i < _size; i++)
		{
			if (_str[i] == c)
			{
				return i;
			}
		}
		return npos;
		//return -1;
	}

	//查找字符串
	size_t Find_Str(size_t pos, char* str)
	{
		char* posPtr = strstr(_str + pos, str);
		if (posPtr)
		{
			return posPtr - _str;
		}
		else
			return npos;
	}

	String& operator+=(char c)
	{
		PushBack(c);
		return *this;
	}

	String& operator+=(const char* str)
	{
		Append(str);
		return *this;
	}

	String& operator+=(const String&s)
	{
		Append(s._str);
		return *this;
	}



};


const  size_t String::npos = -1;


//輸出運算符重載
ostream& operator<<(ostream& _cout, const String&s)
{
	_cout << s.c_str() << endl;
	return _cout;
}

//普通打印
void Print_String(const String&s)
{
	for (size_t i = 0; i < s.Size(); i++)
	{
		//s.operator[](&s, i);
		cout << s[i];
	}
	cout << endl;
}

//用迭代器來打印
void Print_String_Iterator(const String& s)
{
	String :: const_iterator  sit = s.begin();
	while (sit != s.end())
	{
		cout << *sit;
		++sit;
	}
	cout << endl;
}


void Test1()
{
	String s1;
	
	//String s1("hello");
	//Print_String(s1);
	//cout << s1.Size() << endl;
	s1.PushBack('h');
	s1.PushBack('e');
	s1.PushBack('l');
	s1.PushBack('l');
	s1.PushBack('o');
	s1.PushBack(' ');
	s1.PushBack('C');
	s1.PushBack('+');
	s1.PushBack('+');
	s1.PushBack('!');
	Print_String(s1);  //hello C++!
	//修改一個值
	s1[0] = 'H';
	Print_String(s1); //Hello C++!
	//尾刪
	s1.PopBack();
	Print_String(s1); //Hello C++
	//測試Resize()
	s1.Resize(12, '!');
	Print_String(s1); //Hello C++!!!
	//測試Erase()
	s1.Erase(10, 2);
	Print_String(s1);//Hello C++!
	//測試Append()
	s1.Append("!!!!");
	Print_String(s1);// Hello C++!!!!!
	//測試Insert()
	s1.Insert(5, '!');
	Print_String(s1);//Hello! C++!!!!!
	//測試Insert()字符串
	s1.Insert(6, " I Love");
	Print_String(s1);
	//測試Find_Ch
	size_t ret = 0;
	ret = s1.Find_Ch('C');
	cout << "查找C" << endl << "查找結果:";
	cout << ret << endl;  //14
	//測試Find_Str()
	cout << "查找子串:C++" << endl;
	cout << s1.Find_Str(13, "C++") << endl;
	//測試迭代器打印
	cout << "用迭代器來打印:";
	Print_String_Iterator(s1);
	//測試operator+=(char)
	cout << "測試operator+= (char)";
	s1.operator+=('~');
	Print_String(s1);
	//測試operator+=(str)
	cout << "測試operator+= (str) ";
	s1.operator+=("~~~");
	Print_String(s1);
	//測試operator+=(String&s)
	String s2("Happy");
	cout << "測試operator+= (String&s) ";
	s1.operator+=(s2);
	Print_String(s1);

}

int main()
{
	Test1();
	system("pause");
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章