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;
}
#endif
main.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;
}