C++string类的模拟实现

还会慢慢测试找bug的

#pragma once
#include <cassert>
namespace YCB
{
    
    
	
	class string
	{
    
    
	public:
		typedef char* iterator;
		static size_t npos;
		iterator begin(){
    
    
			return _str;
		}

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

		//构造
		string(const char* s = "") 
			:_str(new char[strlen(s) + 1]),
			_size(0),
			_capacity(0)
		{
    
    
			strcpy(_str, s);
			_size = _capacity = strlen(s);
		}
		//拷贝构造(传统版本) s2(s1)
		/*string(const string& s) 
			:_str(new char[strlen(s._str)+1]) ///如果resize()加载了一大堆'\0',后面的'\0'不用他
		{
			strcpy(_str, s._str);///把'\0'也拷贝过来
		}*/

		//拷贝构造(现代版本)
		
		string(const string& s)
			:_str(nullptr)
		{
    
    
			string tmp(s);
			swap(_str,tmp._str);
			swap(_size,tmp._size);
			swap(_capacity,tmp._capacity);
		}
		

		//赋值(传统版本)  s3=s2
		// s2.resize(1e7); 全'\0' s3空间正常开 
		//string& operator=(const string& s) {
    
    
		//	if (this != &s) {
    
    
		//		reserve(strlen(s._str));//申请开空间
		//		_size = s._size;
		//	}
		//}

		//赋值(现代版本1)
		//string& operator=(const string& s) {
    
    
		//	string tmp(s);
		//	swap(_str, tmp._str);
		//	swap(_size, tmp._size);
		//	swap(_capacity, tmp._capacity);
		//	return *this;
		//}

		//赋值(现代版本2)
		string& operator=(string s){
    
    
			swap(_str, s._str);
			swap(_size, s._size);
			swap(_capacity, s._capacity);
			return *this;
		}
		
		

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

		string& append(const string& s){
    
    
			size_t len = strlen(s._str);
			if (s._size + len > s._capacity)
			{
    
    
				reserve(_size + len);
			}
			strcpy(end(), s._str);//0已经拷贝过来了
			_size += len;
			return *this;
		}	

		//reserve
		void reserve(size_t n){
    
    
			if (n < _capacity) return;	 //空间足够时不开辟
			char* tmp = new char[n + 1]; //多的1是给'\0'
			if (!tmp) perror("reserve");
			strcpy(tmp,_str);
			delete[] _str;
			_str = tmp;
			_capacity = n;
		}
		void insert(size_t pos, char ch) {
    
    
			if (_capacity == _size  )
			{
    
    
				reserve(_capacity + 1);
			}
			memmove( _str+pos + 1, _str+pos, (_size - pos + 1 )*sizeof(char)); //注意把'/0'拷过去
		}
		string& insert(size_t pos, const char* s){
    
    
			size_t len = strlen(s);
			if (_capacity < _size + len)
			{
    
    
				reserve(_size + len);
			}
			memmove(_str + pos + len, _str + pos, (_size - pos + 1) * sizeof(char));//注意拷贝'\0'
			for (int i = 0, j = pos; i < len; i++ , j++){
    
    
				_str[j] = s[i];
			}
			_size += len;
			return *this;
		}
		// If n is smaller than the current string length, the current value is shortened to its first n character, removing the characters beyond the nth.
		void resize(size_t n, char c='\0') {
    
    
			if (n < _size) {
    
    
				_str[n] = '\0';
				_size = n;
			}
			else {
    
    
				if (n > _capacity) reserve(n);
				int add = n - _size;
				for (int i = 0; i < add; i++) push_back(c);
			}
		}
		string& erase(size_t pos = 0, size_t len = npos) {
    
    
			if ( pos + len >= _size) {
    
    
				_size = 0;
				_str[_size] = '\0';
			}
			else {
    
    
				memmove( _str+pos, _str+pos + len, (_size -(pos+len) + 1 )*sizeof(char)); //把'\0'也拷贝过来
			}
		}
		size_t find(char c, size_t pos = 0) {
    
    
			for (int i = pos; i < _size; i++) {
    
    
				if (c == _str[i]) {
    
    
					return i;
				}
			}
			return npos;
		}
		///kmp在实现了vector之后再更新
		size_t find(const char* s, size_t pos = 0) {
    
    
			int j = 0; size_t ed = strlen(s);
			for (int i = pos; i < _size; i++) {
    
    
				if (s[j] == _str[i]) {
    
    
					j++;
					if (j > ed) return i;
				}
				else j = 0;
			}
			return npos;
		}

		string& operator+=(const string& s) {
    
    
			append(s);
			return *this;
		}
		string& operator+=(const char ch) {
    
    
			push_back(ch);
			return *this;
		}
		string& operator+= (const char* s) {
    
    
			insert(_size, s);
			return *this;
		}
		bool operator>(const string& s){
    
    
			return strcmp(_str,s._str) > 0;
		}
		bool operator==(const string& s) {
    
    
			return strcmp(_str, s._str) == 0;
		}
		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);
		}
		bool operator!=(const string& s) {
    
    
			return !(*this == s);
		}
		void clear() {
    
    
			_size = 0;
			_str[_size] = '\0';
		}
		size_t size() const {
    
    
			return _size;
		}
		size_t capacity() const {
    
    
			return _capacity;
		}
		char& front() const {
    
    
			return _str[0];
		}
		char& back() const {
    
    
			assert(_size > 0);
			return _str[_size - 1];
		}
		char* c_str(){
    
    
			return _str;
		}
		char& operator[](size_t pos) const {
    
    
			assert(pos < _size);
			return _str[pos];
		}
		bool empty() const {
    
    
			if (_size == 0) return true;
			return false;
		}
		//析构
		~string() {
    
    
			delete[] _str;
			_str = nullptr;
			_size = _capacity = 0;
		}
	private:
		char* _str;
		size_t _size;///已经用的有效字符
		size_t _capacity;//有效字符的空间大小
	};
	size_t string:: npos = -1;
	istream& operator>>(istream& in, string& s) {
    
    
		s.clear();
		while (1) {
    
    
			char ch;
			in.get(ch);
			if (ch == ' ' || ch == '\n')
			{
    
    
				break;
			}
			s += ch;
		}
		return in;
	}
	istream& getline(istream& in, string& s) {
    
    
		s.clear();
		while (1) {
    
    
			char ch;
			in.get(ch);
			if (ch == '\n')
			{
    
    
				break;
			}
			s += ch;
		}
		return in;
	}

	ostream& operator<<(ostream& out, const string& s) {
    
    
		for (int i = 0; i < s.size(); i++) {
    
    
			out << s[i];
		}
		return out;
	}

}


测试文件

void test_string1()
	{
    
    
		string s1;
		string s2("hello");
		cout << s1 << endl;
		cout << s2 << endl;
		cout << s1.c_str() << endl;
		cout << s2.c_str() << endl;

		///三种遍历方式
		for (size_t i = 0; i < s2.size(); i++)
		{
    
    
			s2[i] += 1;
			cout << s2[i] << " ";
		}cout << endl;

		string::iterator it2 = s2.begin();//s2.Begin()就不行,因为没得替换
		while (it2 != s2.end())
		{
    
    
			*it2 -= 1;
			cout << *it2 << " ";
			++it2;
		}cout << endl;
		//支持iterator begin end就可以
		for (auto e : s2)///范围for会被编译器替换成迭代器
		{
    
    
			cout << e << " ";
		}
		cout << endl;
	}
	void test_string2()
	{
    
    
		string s1("hello");
		s1.push_back(' ');
		s1.push_back('w');
		s1.push_back('o');
		s1.append(" xxxxxxxxxxxxxxxxxx");
		cout << s1 << endl;

		string s2;
		s2 += "hello";
		s2 += " ";
		s2 += "world";
		cout << s2 << endl;
	}

	void test_string3()
	{
    
    
		string s1("hello");
		s1.insert(1, "xy");
		s1.insert(1, "xyz");
		cout << s1 << endl;
	}

	void test_string4()
	{
    
    
		string s2("hello");
		s2.reserve(10);
		cout << s2 << endl;
		cout << s2.size() << endl;
		cout << s2.capacity() << endl;

		s2.resize(8, 'x');
		cout << s2.size() << endl;
		cout << s2.capacity() << endl;
		s2.resize(18, 'z');
		cout << s2.size() << endl;
		cout << s2.capacity() << endl;
		s2.resize(2);
		cout << s2.size() << endl;
		cout << s2.capacity() << endl;
	}
	void test_string5() {
    
    
		string s;
		cin >> s;
		cout << s << endl;
	}

	void test_string6() {
    
    
		string s2("hello world");
		s2.resize(20, 'x');
		s2 += "!!!";
		cout << s2 << endl;
		cout << s2.c_str() << endl;
	}

猜你喜欢

转载自blog.csdn.net/zstuyyyyccccbbbb/article/details/120455230