String.h
#ifndef STRING_H #define STRING_H #define _CRT_SECURE_NO_WARNINGS #include<iostream> //String class String{ public: String(const char* str = NULL);//constructor String(const String& rhs);//copy constructor String& operator=(const String& rhs);//copy assignment ~String();//destructor String& operator+=(const String& rhs);//operator+= String operator+(const String& rhs);//operator+ bool operator==(const String& rhs);//operator== char& operator[](size_t index); //operator[] const char& operator[](size_t index)const;//const operator[] void copy(const String& rhs);//copy int compare(const String& rhs);//compare String substr(size_t pos, size_t len);//substring String& insert(size_t pos, String& rhs);//insert String& erase(size_t pos, size_t len);//erase bool empty();//whether String is empty or not size_t length();//get String length size_t get_ref_count();//get ref_count friend std::istream& operator>>(std::istream& is, const String& str);//operator>> friend std::ostream& operator<<(std::ostream& os, const String& str);//operator<< private: struct StringValue{ int ref_count; char* data; StringValue(const char* str);//StringValue constructor ~StringValue();//StringValue destructor }; StringValue* value; }; //StringValue constructor String::StringValue::StringValue(const char* str) :ref_count(1){ if (str == NULL){ data = new char[1]; data[0] = '\0'; } else{ data = new char[strlen(str) + 1]; strcpy(data, str); } } //StringValue destructor String::StringValue::~StringValue(){ delete[] data; data = NULL; } //constructor String::String(const char* str) :value(new StringValue(str)){} //copy constructor String::String(const String& rhs):value(rhs.value){ ++value->ref_count; } //copy assignment String& String::operator=(const String& rhs){ if (this->value == rhs.value) return *this; if (--this->value->ref_count == 0) delete this->value; this->value = rhs.value; ++this->value->ref_count; return *this; } //destructor String::~String(){ if (--this->value->ref_count == 0) delete this->value; } //operator+= String& String::operator+=(const String& rhs){ if (--this->value->ref_count == 0) delete this->value; if (rhs.value->data == NULL){ this->value = new StringValue(this->value->data); return *this; } if (this->value->data == NULL){ this->value = new StringValue(rhs.value->data); return *this; } char* temp = new char[strlen(this->value->data) + strlen(rhs.value->data) + 1]; strcpy(temp, this->value->data); strcat(temp, rhs.value->data); this->value = new StringValue(temp); return *this; } //operator+ String String::operator+(const String& rhs){ return String(*this) += rhs; } //operator== bool String::operator==(const String& rhs){ return compare(rhs) == 0 ? true : false; } //operator[] char& String::operator[](size_t index){ if (this->value->ref_count > 1){ --this->value->ref_count; this->value = new StringValue(this->value->data); } if (index < strlen(this->value->data)) return this->value->data[index]; } //const operator[] const char& String::operator[](size_t index)const{ if (index < strlen(this->value->data)) return this->value->data[index]; } //copy void String::copy(const String& rhs){ operator=(rhs); } //compare int String::compare(const String& rhs){ for (int i = 0; i < strlen(this->value->data) && i < strlen(rhs.value->data); i++){ if (this->value->data[i] != rhs.value->data[i]){ return this->value->data[i] - rhs.value->data[i]; } } return strlen(this->value->data) - strlen(rhs.value->data); } //substring String String::substr(size_t pos, size_t len){ if (pos>length()-len){ std::cout << "pos+len>String length" << std::endl; exit(1); } char* temp = new char[len + 1]; int i; for (i = 0; i < len; i++){ temp[i] = this->value->data[pos + i]; } temp[i] = '\0'; return String(temp); } //insert String& String::insert(size_t pos, String& rhs){ if (pos>this->length()){ std::cout << "pos>String length" << std::endl; exit(1); } if (--this->value->ref_count == 0) delete this->value; char* temp = new char[this->length() + rhs.length() + 1]; int i; for (i = 0; i < pos; i++){ temp[i] = this->value->data[i]; } for (; i < pos + rhs.length(); i++){ temp[i] = rhs.value->data[i - pos]; } for (; i < this->length() + rhs.length(); i++){ temp[i] = this->value->data[i - rhs.length()]; } temp[i] = '\0'; this->value = new StringValue(temp); return *this; } //erase String& String::erase(size_t pos, size_t len){ if (pos>this->length()-len){ std::cout << "pos+len>String length" << std::endl; exit(1); } if (--this->value->ref_count == 0) delete this->value; char* temp = new char[this->length() - len + 1]; int i; for (i = 0; i < pos; i++){ temp[i] = this->value->data[i]; } for (; i < this->length() - len + 1; i++){ temp[i] = this->value->data[i + len]; } temp[i] = '\0'; this->value = new StringValue(temp); return *this; } //whether String is empty or not bool String::empty(){ return this->value->data[0] == '\0' ? true : false; } //get String length size_t String::length(){ return strlen(this->value->data); } //get ref_count size_t String::get_ref_count(){ return this->value->ref_count; } //operator>> std::istream& operator>>(std::istream& is, const String& str){ is >> str.value->data; return is; } //operator<< std::ostream& operator<<(std::ostream& os, const String& str){ os << str.value->data; return os; } #endifmain.cpp
#include"String.h" using namespace std; int main(){ String str1("hello world");//call constructor String str2 = str1;//call copy constructor String str3;//call constructor cout << boolalpha << str1.empty() << endl;//false cout << boolalpha << str2.empty() << endl;//false cout << boolalpha << str3.empty() << endl;//true str3 = str2;//call copy assignment cout << "str1 reference count:" << str1.get_ref_count() << endl; // 3 cout << "str2 reference count:" << str2.get_ref_count() << endl; // 3 cout << "str3 reference count:" << str3.get_ref_count() << endl; // 3 str1[0] = 'H';//call operator[] cout << str1 << endl; //"Hello world" cout << str2 << endl;//"hello world" cout << str3 << endl;//"hello world" cout << "str1 reference count:" << str1.get_ref_count() << endl;//1 cout << "str2 reference count:" << str2.get_ref_count() << endl;//2 cout << "str3 reference count:" << str3.get_ref_count() << endl;//2 String str4("hello");//call constructor String str5 = str4;//call copy constructor String str6 = " world";//call constructor str5 = str5 + str6;//call operator+,copy constructor cout << str4 << endl; //"hello" cout << str5 << endl; //"hello world" cout << str6 << endl; //" world" cout << "str4 reference count:" << str4.get_ref_count() << endl;//1 cout << "str5 reference count:" << str5.get_ref_count() << endl;//1 cout << "str6 reference count:" << str6.get_ref_count() << endl;//1 String str7 = str5;//call copy constructor String str8;//call constructor str8 = str7;////call copy constructor cout << str7 << endl; //"hello world" cout << "str5 reference count:" << str5.get_ref_count() << endl;//3 cout << "str7 reference count:" << str7.get_ref_count() << endl;//3 cout << "str8 reference count:" << str8.get_ref_count() << endl;//3 str5 += str6;//call operator+= cout << str5 << endl; //"hello world world" cout << str6 << endl; //" world" cout << str7 << endl; //"hello world" cout << str8 << endl; //"hello world" cout << "str5 reference count:" << str5.get_ref_count() << endl; //1 cout << "str6 reference count:" << str6.get_ref_count() << endl;//1 cout << "str7 reference count:" << str7.get_ref_count() << endl;//2 cout << "str8 reference count:" << str8.get_ref_count() << endl;//2 String str9; //call constructor str9 = str8.substr(1, 3); cout << str9 << endl;//"ell" cout << "str8 reference count:" << str8.get_ref_count() << endl;//2 cout << "str9 reference count:" << str9.get_ref_count() << endl;//1 cout << "str9 length:" << str9.length() << endl;//3 String str10; str10.copy(str9); cout << str9 << endl;//"ell" cout << str10 << endl;//"ell" cout << "str9 reference count:" << str9.get_ref_count() << endl;//2 cout << "str10 reference count:" << str10.get_ref_count() << endl;//2 if (str9.compare(str10) == 0) cout << "equal" << endl; //equal else cout << " not equal" << endl; str10.insert(2, String("abc")); cout << str9 << endl;//"ell" cout << str10 << endl;//"elabcl" cout << "str9 reference count:" << str9.get_ref_count() << endl;//1 cout << "str10 reference count:" << str10.get_ref_count() << endl;//1 String str11 = str10; cout << str10 << endl;//"elabcl" cout << str11 << endl;//"elabcl" cout << "str10 reference count:" << str10.get_ref_count() << endl;//2 cout << "str11 reference count:" << str11.get_ref_count() << endl;//2 str11.erase(2, 2); cout << str10 << endl;//"elabcl" cout << str11 << endl;//"elcl" cout << "str10 reference count:" << str10.get_ref_count() << endl;//1 cout << "str11 reference count:" << str11.get_ref_count() << endl;//1 return 0; }