C++におけるstringクラスのシミュレーション実装

58416 ワード

標準ライブラリのstringクラス
stringクラス
  • stringは文字列を表す文字列クラスである.
  • クラスのインタフェースは、コンテナの通常のインタフェースとほぼ同じであり、stringを操作するための通常の操作を追加する.
  • stringは最下位で実際にはbasic_stringクラステンプレートの別名、
  • typedef basic_string string;
  • では、マルチバイトまたは長くなる文字のシーケンスを操作できません.stringクラスを使用する場合は、#includeヘッダファイルとusing namespace std.
  • を含む必要があります.
    stringクラスの共通インタフェース
    stringクラスオブジェクトの一般的な構造
    関数名
    機能の説明
    string()
    空のstringクラス、すなわち空の文字列を構築する
    string(const char* s)
    C_でstringクラスstringクラスオブジェクトを構築する
    string(size_t n,char c)
    stringクラスオブジェクトにn文字cを含む
    string(const string& s)
    コピーコンストラクタ
    void teststring(){
        string s1;               //    string   s1;
        string s2("hello world");// C_string    string   s2;
        string s3(5,10);         //s3   5 10;
        string s4(s2);           //    s3;
    }
    

    stringクラスオブジェクトの容量操作
    関数名
    機能の説明
    size
    文字列の有効文字長を返します
    length
    文字列の有効文字長を返します
    capacity
    スペースの合計サイズを返す
    empty
    検出文字列は空の列に解放され、trueを返します.そうしないとfalseを返します.
    clear
    有効文字をクリア
    reserve
    文字列のスペースの予約
    resize
    有効文字の個数をn個に変更し、複数の空間を文字cで埋める
    void teststring(){
        string s(“hello world!”);
        
        cout<<s.size()<<endl;//10
        cout<<s.lenth()<<endl;//10
        cout<<s.capacity()<<endl;//15
        cout<<s<<endl;
        
        // s       ( size  0,          )
        s.clear();
        cout<<s.size()<<endl;//0
        cout<<s.capacity()<<endl;//15
        cout<<s<<endl;//     
        
        // s         10 ,      ‘a’  
        s. resize(10,'a');
        cout<<s.size()<<endl;//10
        cout<<s.capacity()<<endl;//15
        cout<<s<<endl;//aaaaaaaaaa
        
        // s         20 ,     ‘b’  
        s.resize(20,'b');  
        cout<<s.size()<<endl;//20
        cout<<s.capacity()<<endl;//31,     
        cout<<s<<endl;//aaaaaaaaaabbbbbbbbbb
        
        // s         5 
        s.resize(5);
        cout<<s.size()<<endl;//5
        cout<<s.capacity()<<endl;//31//      
        cout<<s<<endl;//aaaaa
        
        //     
        s.reserve(100);//           
        cout<<s.size()<<endl;//5
        cout<<s.capacity()<<endl;111
       
       //*****(  )
        s.reserve(50);//reserve    string        ,       
    	cout << s.size() << endl;//5
    	cout << s.capacity() << endl;//111 
    }
    

    stringクラスのシミュレーション実装
    深浅コピー
    class String{
    public:
    	/*String()
    		:_str(new char[1])
    	{
    	    	*_str = '\0';		
    	}
    
    	String(const char* str)
    		:_str(new char[strlen(str)+1])
    	{
    		strcpy(_str, str);
    	}*/
    
    	String(const char* str = "")
    		:_str(new char[strlen(str)+1])
    	{
    		strcpy(_str, str);
    	
    	}
    
    	~String(){
    		delete[] _str;
    		_str = nullptr;
    	}
    	//         ,          
    	String(const String& str)
    		:_str(new char[strlen(str._str)+1])
    	{
    		strcpy(_str, str._str);
    	}
    
    	String& operator=(const String& s){
    		if (this != &s){
    	        delete[] _str;
    		    _str = new char[strlen(s._str) + 1];
    			strcpy(_str, s._str);
    		}
    		return *this;
    	}
    
    	char& operator[](size_t pos){
    		return _str[pos];
    	}
    
    	const char* c_str(){
    		return _str;
    	}
    
    private:
    	char* _str;
    };
    
    int main(){
    	String s1("hello");
    	String s2;
    
    	cout << s1.c_str() << endl;//hello
    	s1[0] = ' ';
    	cout << s1.c_str() << endl;//ello
        cout << s2.c_str() << endl;
    
    	String c1(s1);
    	cout <<c1.c_str() << endl;// ello
    	c1[0] = 'h';
    	cout << c1.c_str() << endl;//hello
    	s2 = "world";
    	s1 = s2;
    	cout << s1.c_str() << endl;
    	system("pause");
    	return 0;
    }
    
    namespace cyy
    {
    	// string           
    	class string
    	{
    	public:
    		typedef const char* const_iterator;
    		typedef char* iterator;
    
    		const_iterator begin() const 
    		{
    			return _str;
    		}
    
    		iterator begin()
    		{
    			return _str;
    		}
    
    		iterator end()
    		{
    			return _str + _size;
    		}
    
    		string(const char* str = "")
    			:_str(new char[strlen(str) + 1])
    		{
    			//     '\0'
    			strcpy(_str, str);// while (*dst++ = *src++);
    			_size = strlen(str);
    			_capacity = _size;
    		}
    
    		~string()
    		{
    			delete[] _str;
    			_str = nullptr;
    			_size = _capacity = 0;
    		}
    
    		//string copy1(s1)
    		string(const string& s)
    			:_str(new char[s._size + 1])
    			, _size(s._size)
    			, _capacity(s._size)
    		{
    			strcpy(_str, s._str);
    		}
    
    		// s1 = s2;
    		// s1 = s1;
    		string& operator=(const string& s)
    		{
    			if (this != &s)
    			{
    				delete[] _str;
    				_str = new char[s._size + 1];
    				strcpy(_str, s._str);
    				_size = s._size;
    				_capacity = s._capacity;
    			}
    
    			return *this;
    		}
    
    		const char* c_str()
    		{
    			return _str;
    		}
    
    		char& operator[](size_t pos)
    		{
    			assert(pos < _size);
    			return _str[pos];
    		}
    
    		const char& operator[](size_t pos) const
    		{
    			assert(pos < _size);
    			return _str[pos];
    		}
    
    		size_t size()
    		{
    			return _size;
    		}
    
    		size_t capacity()
    		{
    			return _capacity;
    		}
    
    		//reverse
    		void reserve(size_t n)
    		{
    			if (n > _capacity)
    			{
    				char* tmp = new char[n+1];
    				strcpy(tmp, _str);
    				delete[] _str;
    				_str = tmp;
    				_capacity = n;
    			}
    		} 
    
    		void push_back(char ch)
    		{
    			//if (_size == _capacity)
    			//{
    			//	//   
    			//	reserve(_capacity * 2);
    			//}
    
    			//_str[_size] = ch;
    			//++_size;
    			//_str[_size] = '\0';
    			insert(_size, ch);
    		}
    
    		// s1.append("11111");
    		void append(const char* str)
    		{
    			//size_t len = strlen(str);
    			//if (_size+len > _capacity)
    			//{
    			//	//   
    			//	reserve(_size + len);
    			//}
    
    			//strcpy(_str + _size, str);
    			//_size += len;
    
    			insert(_size, str);
    		}
    
    		//s1 += ch
    		const string& operator+=(char ch)
    		{
    			push_back(ch);
    			return *this;
    		}
    
    		const string& operator+=(const char* str)
    		{
    			append(str);
    			return *this;
    		}
    
    		const string& operator+=(const string& s)
    		{
    			append(s._str);
    			return *this;
    		}
    
    		void insert(size_t pos, char ch)
    		{
    			assert(pos <= _size);
    			if (_size == _capacity)
    			{
    				reserve(_capacity * 2);
    			}
    
    			/*int end = _size;
    			while (end >= (int)pos)
    			{
    				_str[end + 1] = _str[end];
    				--end;
    			}*/
    
    			size_t end = _size+1;
    			while (end >= pos + 1)
    			{
    				_str[end] = _str[end - 1];
    				--end;
    			}
    
    			_str[pos] = ch;
    			++_size;
    		}
    
    		void insert(size_t pos, const char* str)
    		{
    			assert(pos <= _size);
    			size_t len = strlen(str);
    			if (_size + len > _capacity)
    			{
    				reserve(_size + len);
    			}
    
    			/*	int end = _size;
    				while (end >= (int)pos)
    				{
    				_str[end + len] = _str[end];
    				--end;
    				}*/
    
    			size_t end = _size + len;
    			while (end >= pos + len)
    			{
    				_str[end] = _str[end-len];
    				--end;
    			}
    
    			while (*str)
    			{
    				_str[pos++] = *str++;
    			}
    
    			_size += len;
    		}
    
    		// s1 > s2
    		// hello  hello!
    		bool operator>(const string& s) const
    		{
    			const char* str1 = _str;
    			const char* str2 = s._str;
    			while (*str1 && *str2)
    			{
    				if (*str1 > *str2)
    				{
    					return true;
    				}
    				else if (*str1 < *str2)
    				{
    					return false;
    				}
    				else
    				{
    					++str1;
    					++str2;
    				}
    			}
    
    			if (*str1)
    			{
    				return true;
    			}
    			else
    			{
    				return false;
    			}
    			/*else if (*str2)
    			{
    			return false;
    			}
    			else
    			{
    			return false;
    			}*/
    		}
    
    		bool operator==(const string& s) const
    		{
    			const char* str1 = _str;
    			const char* str2 = s._str;
    			while (*str1 && *str2)
    			{
    				if (*str1 != *str2)
    				{
    					return false;
    				}
    				else
    				{
    					++str1;
    					++str2;
    				}
    			}
    
    			if (*str1 || *str2)
    			{
    				return false;
    			}
    			else
    			{
    				return true;
    			}
    		}
    
    		bool operator>=(const string& s) const
    		{
    			return *this > s || *this == s;
    		}
    		// ...
    
    		size_t find(char ch)
    		{
    
    		}
    
    		size_t find(const char* str) // strstr ->kmp   
    		{
    
    		}
    
    		// operator+
    		// operator<<
    		// operator>>
    		// getline
    
    	private:
    		char* _str;
    		size_t _size;
    		size_t _capacity;
    	};
    }
    
    
    
    void test1()
    {
    	cyy::string s1("hello");
    	cout << s1.c_str() << endl;
    	cyy::string copy1(s1);
    	cout << copy1.c_str() << endl;
    
    	for (size_t i = 0; i < s1.size(); ++i)
    	{
    		// s1.operator[](i); -> s1.operator[](&s1, i);
    		s1[i] = 'a';
    		cout << s1[i] << " ";
    	}
    	cout << endl;
    
    	cyy::string::iterator it1 = s1.begin();
    	while (it1 != s1.end())
    	{
    		cout << *it1 << " ";
    		++it1;
    	}
    	cout << endl;
    
    	for (auto e : s1)
    	{
    		cout << e << " ";
    	}
    	cout << endl;
    }
    
    void test2()
    {
    	cyy::string s1("hello");
    	cout << s1.capacity() << endl;
    
    	s1 += "world";
    	cout << s1.capacity() << endl;
    
    	s1 += '!';
    	cout << s1.capacity() << endl;
    
    	cout << s1.c_str() << endl;
    
    	cyy::string s2("helloworld!");
    	s2.insert(5, ' ');
    	cout << s2.c_str() << endl;
    	s2.insert(0, '$');
    	cout << s2.c_str() << endl;
    	s2.insert(0, "bit");
    	cout << s2.c_str() << endl;
    }
    
    int main()
    {
        test1();
    	test2();
    
    	return 0;
    }