C++コンテナ--string


string
stringはC++STLの重要なコンテナであり、文字列を表す文字列クラスの中には文字列を操作するためのインタフェースが複数バイトまたは長くなる文字を操作できないシーケンスがある.
共通インタフェース:
構築:
string();	//     
string(const char* s);	//  C-string  string   
string(size_t n, char c);	// string      n   c
string(const string& s);	//     
string(const string& s, size_t n);	//  s  n     

容量:
size_t size() const;	//          
size_t length() const;	//          
size_t capacity() const; //       
bool empty() const;		//        
void clear();		//       
void resize(size_t n, char c); //        n ,   c  
void resize(size_t n);	//        n ,   0  
void reserve(size_t res_arg = 0);	//   

注意:
  • size()はlength()の下層実装原理と同様であり、size()は他の容器のインタフェースと一致する
  • を維持する.
  • clear()は有効データのみを空にし、下位空間サイズ
  • を変更しない.
  • reserve()はstring予約空間であり、有効空間の大きさを変更せず、reserveのパラメータが下位空間より小さい場合、容量
  • を変更しない.
    アクセス:
    char& operator[](size_t pos);	//  pos    
    const char& operator[](size_t pos) const;	// const   
    

    変更:
    void push_back(char c);	//     c
    string& append(const char* s);	//      
    string& operator+=(const string& str);	//   str  
    // +=        、   、     
    const char* c_str() const;	//   c     
    size_t find(char c, size_t pos = 0);	//     pos   c,        
    size_t rfind(char c, size_t pos = npos);
    string substr(size_t pos = 0, size_t n = npos);//  pos    ,  n   ,    string  
    

    stringクラス非メンバー関数:
    operator+();	//     
    operator>>();	//        
    operator<<();	//        
    getline();		//       , '
    '

    深浅コピー:
    浅いコピー(値コピー):数値のみコピー、リソースをコピーしない深いコピー:データのコピー、リソースのコピー
    浅いコピーによる問題:二次解放
    stringクラスを手書きで書きます.
    //     
    #include <iostream>
    #include <string.h>
    
    class String
    {
    public:
    	String(const char* str = "")
    		:_size(0)
    	{
    		if (str == nullptr)
    		{
    			_str = "";
    			return;
    		}
    		_size = strlen(str);
    		_str = new char[_size + 1];
    		strcpy(_str, str);
    	}
    	String(const String& s)
    	{
    		_str = new char[s.Size() + 1];
    		strcpy(_str, s._str);
    		_size = s.Size();
    	}
    	~String()
    	{
    		if (_str != nullptr)
    		{
    			delete[] _str;
    			_str = nullptr;
    			_size = -1;
    		}
    	}
    	String& operator=(String& s)
    	{
    
    		if (this != &s)
    		{
    			char* pstr = new char[s.Size() + 1];
    			strcpy(pstr, s._str);
    			delete[] _str;
    			_str = pstr;
    			_size = s.Size();
    		}
    		return *this;
    	}
    	const int Size() const
    	{
    		return _size;
    	}
    
    public:
    	//    ,           
    	friend std::ostream& operator<<(std::ostream& _cout, const String& s);
    	friend std::istream& operator>>(std::istream& _cin, String& s);
    private:
    	char* _str;
    	int _size;
    };
    
    std::ostream& operator<<(std::ostream& _cout, const String& s)
    {
    	_cout << s._str << std::endl;
    	return _cout;
    }
    
    std::istream& operator>>(std::istream& _cin, String& s)
    {
    	_cin >> s._str;
    	return _cin;
    }
    
    //     
    class String {
    public:
    	String(char* str = "") :_str(nullptr) {
    		if (_str == nullptr)
    		{
    			_str = "";
    		}
    		_str = new char[strlen(str) + 1];
    		strcpy(_str, str);
    	}
    	String(const String& s) :_str(nullptr) {
    		String tmp(s._str);
    		std::swap(_str, tmp._str);
    	}
    	~String() {
    		if (_str != nullptr)
    		{
    			delete[] _str;
    			_str = nullptr;
    		}
    	}
    	String& operator=(String s) {
    		std::swap(_str, s._str);
    		return *this;
    	}
    private:
    	friend std::ostream& operator<<(std::ostream& _cout, const String& s);
    	friend std::istream& operator>>(std::istream& _cin, String& s);
    private:
    	char* _str;
    };
    
    std::ostream& operator<<(std::ostream& _cout, const String& s)
    {
    	_cout << s._str << std::endl;
    	return _cout;
    }
    
    std::istream& operator>>(std::istream& _cin, String& s)
    {
    	_cin >> s._str;
    	return _cin;
    }
    

    stringクラスのシミュレーションの実装:
    //       ,           
    //       ,    
    
    #include <string.h>
    #include <assert.h>
    #include <string>
    #include <iostream>
    
    class String {
    public:
    	typedef char* Iterator;
    public:
    	//   
    	String(const char* str = "")
    	{            
    		//   string    ,    nullptr  ,      ,       
    		if (nullptr == str) 
    		{ 
    			assert(false);
    			return;   
    		}
    
    		_size = strlen(str); 
    		if (_size == 0)
    			_capacity = 1;
    		else
    			_capacity = _size;
    		
    		_str = new char[_capacity + 1];     
    		strcpy(_str, str);
    	}
    	String(const String& s) 
    		: _str(new char[s._capacity])
    		, _capacity(s._capacity)
    		, _size(s._size)
    	{
    		strcpy(_str, s._str);
    	}
    	~String() {
    		if (_str != nullptr)
    		{
    			// delete[] _str;
    			_str = nullptr;
    			_size = 0;
    		}
    	}
    	String& operator= (String s) {
    		if (this != &s)
    		{
    			std::swap(_str, s._str);
    			std::swap(_size, s._size);
    			std::swap(_capacity, s._capacity);
    		}
    		return *this;
    	}
    
    	//     Iterator
    	Iterator begin() {
    		return _str;
    	}
    	Iterator end() {
    		return _str + _size;
    	}
    	const Iterator begin() const {
    		return _str;
    	}
    	const Iterator end() const {
    		return _str + _size;
    	}
    
    	// modify
    	void push_back(char c) {
    		if (_size == _capacity)
    		{
    			reserve(_capacity * 2);
    		}
    		_str[_size] = c;
    		_str[++_size] = '\0';
    	}
    	void append(char c, size_t n) {
    		for (size_t i = 0; i < n; ++i)
    		{
    			push_back(c);
    		}
    	}
    	String& operator+=(char c) {
    		push_back(c);
    		return *this;
    	}
    	void append(const char* str) {
    		for (size_t i = 0; i < strlen(str); ++i)
    		{
    			push_back(*(str + i));
    		}
    		push_back('\0');
    	}
    	String& operator+= (const char* str) {
    		append(str);
    		return *this;
    	}
    	String& operator+= (const String& s) {
    		append(s._str);
    		return *this;
    	}
    	//   
    	void reserve(size_t new_capacity) {
    		if (new_capacity > _capacity)
    		{
    			char* new_str = new char[new_capacity + 1];
    			strcpy(new_str, _str);
    			
    			delete[] _str;
    			_str = new_str;
    			_capacity = new_capacity;
    		}
    	}
    
    	// capacity
    	int size() const {
    		return _size;
    	}
    	size_t capacity() const {
    		return _capacity;
    	}
    	bool empty() const {
    		return _size == 0 ? true : false;
    	}
    	void Resize(size_t newSize, char c = char()) {
    		if (newSize > _size)
    		{
    			if (newSize > _capacity)
    			{
    				reserve(newSize);
    			}
    			memset(_str + _size, c, newSize - _size);
    		}
    		_size = newSize;
    		_str[newSize] = '\0';
    	}
    
    	void clear()
    	{
    		_size = 0;
    		_str[_size] = '\0';
    	}
    	const char* c_str() const
    	{
    		return _str;
    	}
    	void Swap(String& s)
    	{
    		std::swap(_str, s._str);
    		std::swap(_size, s._size);
    		std::swap(_capacity, s._capacity);
    	}
    
    	// access
    	char& operator[] (size_t index) {
    		return _str[index];
    	}
    	const char& operator[] (size_t index) const {
    		return _str[index];
    	}
    
    	bool operator<(const String& s) {
    		int i = 0;
    		for (auto& e : s)
    		{
    			if (_str[i] < e)
    			{
    				return true;
    			}
    			else if (_str[i] > e)
    			{
    				return false;
    			}
    			++i;
    		}
    		return false;
    	}
    	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) {
    		int i = 0;
    		for (auto& e : s)
    		{
    			if (_str[i] != e)
    			{
    				return false;
    			}
    		}
    		return true;
    	}
    	bool operator!=(const String& s) {
    		return !(*this == s);
    	}
    
    	size_t find(char c, size_t pos = 0) const {
    		for (size_t i = pos; i < _size; ++i)
    		{
    			if (_str[i] == c)
    			{
    				return i;
    			}
    		}
    		return nops;
    	}
    
    	String substr(size_t pos, size_t n) {
    		String tmp;
    		for (size_t i = 0; i < n; ++i)
    		{
    			tmp.push_back(_str[pos + i]);
    		}
    		tmp[pos + n] = '\0';
    		return tmp;
    	}
    
    	String& insert(size_t pos, char c) {
    
    		//pos       
    		if (_size == _capacity)
    		{
    			reserve(_capacity * 2);
    		}
    		
    		for (size_t i = _size; i > pos; --i)
    		{
    			_str[i] = _str[i - 1];
    		}
    		++_size;
    		_str[pos] = c;
    
    		//             '\0',     
    		_str[_size] = '\0';
    		return *this;
    	}
    	String& insert(size_t pos, const char* str) {
    		size_t len = strlen(str);
    		if ((len + _size) >= _capacity)
    		{
    			reserve((_capacity + len) * 2);
    		}
    
    		for (size_t i = pos; i < pos + len; ++i)
    		{
    			_str[i + len] = _str[i];
    		}
    		for (size_t i = pos; i < pos + len; ++i)
    		{
    			_str[i] = str[i - pos];
    		}
    		_size += len;
    		return *this;
    	}
    
    	String& erase(size_t pos, size_t len) {
    		for (size_t i = pos; i < pos + len; ++i)
    		{
    			_str[i] = _str[i + len];
    		}
    		_size -= len;
    		return *this;
    	}
    
    
    
    private:
    	friend std::ostream& operator<< (std::ostream& _cout, const String& s);
    	friend std::istream& operator>> (std::istream& _cin, String& s);
    private:
    	char* _str;
    	size_t _size;
    	size_t _capacity;
    	static int nops;
    };
    
    int String::nops = -1;
    
    std::ostream& operator<< (std::ostream& _cout, const String& s) {
    	_cout << s._str << std::endl;
    	return _cout;
    }
    std::istream& operator>> (std::istream& _cin, String& s) {
    	_cin >> s._str;
    	return _cin;
    }