对于字符串我们有时候很难向整型或其他变量那样进行比较和直接复制或定义,这都是C语言中遇到的问题,在C++ 中提供了一种类专门解决这种对于字符串的操作,叫做string类,我其实也想实现一下并且暂时浅浅的了解一下,以下是我简单的实现string类,我的string叫 String类注意大小写哦!!!!!!!!!
/*/**********************************************************************
* * Copyright (c)2015,WK Studio
* * Filename: String.h
* * Compiler: GCC vs2013
* * Author:WK
* * Time: 2015 14 6
* **********************************************************************/
#include<iostream>
#include<string.h>
using namespace std;
class String
{
public:
String(char * d) :data(d)
{}
//构造函数
String(const char *str = NULL);
~String();
String(const String &s);
String& operator=(const String &s);
friend String operator + (const String& str1, const String& str2);
String& operator+=(const String &str2);
friend String& operator+=(String &str1, String &str2);
friend bool operator!=(String &str1, String &str2);
friend bool operator==(String &str1, String &str2);
friend bool operator>(String &str1, String &str2);
friend bool operator<(String &str1, String &str2);
/*
对“ << ”和“ >> ”重载的函数形式如下:
istream & operator >> (istream &, 自定义类 &);
ostream & operator << (ostream &, 自定义类 &);
即重载运算符“ >> ”的函数的第一个参数和函数的类型都必须是istream&类型,第二个参数是要进行输入操作的类。重载“ << ”的函数的第一个参数和函数的类型都必须是ostream&类型,第二个参数是要进行输出操作的类。因此,只能将重载“ >> ”和“ << ”的函数作为友元函数或普通的函数,而不能将它们定义为成员函数。
*/
friend istream& operator>> (istream &is, String &str);//返回引用可以实现连续输入,并且返回值不存在与栈中所以可以返回引用
friend ostream& operator<< (ostream &out, String &str);
private:
char *data;
};
/*/**********************************************************************
* * Copyright (c)2015,WK Studio
* * Filename: main.cpp
* * Compiler: GCC vs2013
* * Author:WK
* * Time: 2015 14 6
* **********************************************************************/
void main()
{
String s1 = "Str";//调用构造
String s2("ing");//调用构造
String s3 = s1;//调用拷贝
String s4("String");//调用构造
s4 = s2;//调用赋值
String s5;//调用构造
s5 = s2;//调用赋值
String s6("String");//调用构造
s6 = s1 + s2;//调用+运算符重载函数返回临时无名对象通过临时无名对象调用赋值函数对s6进行赋值,之后临时无名对象被释放
String s7;
s7 = s1 + s2;//同上
String s8 = s1 + "123";//调用构造函数用"123"生成一个临时对象来和s1进行相加调用+运算符重载
String s9 = s1 + s2;//+运算符重载返回的临时无名对象直接用来拷贝构造s8对象
String s10;
s10+= s1;//如果+=运算符重载的友员和成员函数都存在调用的是友元函数
//s9.operator+=(s1);//调用成员函数
//operator+=(s9,s1);//可以直接调用友员函数,因为友员函数属于类无需对象来驱动
//String s10 += s2;
//上面这种不可以是因为在+=之前是s10对象还没有构造呢
//类似于int a = 10; int b+= a; int c+=1;
String ss("1");
String ss1("1");
cout << (s1 != s2) << "\n";
cout << (ss != ss1) << "\n";
cout << (ss == ss1) << "\n";
cout << (s1 == s2) << "\n";
cout << (s1 > s2) << "\n";
cout << (s1 < s2) << "\n";
String s11;
cin >> s11;
cout << s11;
getchar();
}
/*/**********************************************************************
* * Copyright (c)2015,WK Studio
* * Filename: String.cpp
* * Compiler: GCC vs2013
* * Author:WK
* * Time: 2015 14 6
* **********************************************************************/
#include"String.h"
//构造函数
String::String(const char *str)
{
cout << "Create String!" << this << "\n";
if (str == NULL)
{
data = new char[1];//至少有一个'\0'
data[0] = '\0';
}
else
{
data = new char[strlen(str) + 1]; //(char *)malloc(strlen(str)+1);
strcpy(data, str);
}
}
/*//构造函数1
String(const char *str = NULL)
{
if(str == NULL)
{
str=NULL; //不能满足当字符串为NULL时候
}
else
{
data = new char[strlen(str)+1];//(char *)malloc(strlen(str)+1);
strcpy(data,str);
}
}
//构造函数2
String(const char *str = "")//不能满足当字符串为NULL时候
{
data = new char[strlen(str)+1];//(char *)malloc(strlen(str)+1);
strcpy(data,str);
}
*/
//拷贝构造
String::String(const String &s)
{
cout << "Copy String!" << this << "\n";
data = new char[strlen(s.data) + 1];
strcpy(data, s.data);
}
//= 运算符重载
String& String:: operator=(const String &s)//返回引用可以实现连等
{
cout << "Assignment String!" << this << "\n";
if (this != &s) //(1) 检查自赋值
{
free(this->data); // (2) 释放原有的内存资源
this->data = NULL;
this->data = new char[strlen(s.data) + 1];// (3)分配新的内存资源,并复制内容
strcpy(this->data, s.data);
}
return *this; // (4)返回本对象的引用
}
/*
String& operator=(const String &s)
{
if(this==&s)//(1) 检查自赋值
{
return *this;
}
free(this->data); // (2) 释放原有的内存资源
data=NULL;
data=new char[strlen(s)+1];//(3)分配新的内存资源,并复制内容
strcpy(data,s.data);
return *this; // (4)返回本对象的引用
}
*/
//运算符+重载为友员函数
String operator + (const String& str1, const String& str2)//不可以返回引用,因为这里在函数栈中建立了一个临时的对象,具体讨论青参照我的这篇文章
{
String str;//临时对象调用构造函数
delete[] str.data;
str.data = NULL;
str.data = new char[strlen(str1.data)+strlen(str2.data) + 1];
strcpy(str.data, str1.data);
strcat(str.data, str2.data);
cout << "+ operator String!"<< "\n";
return str;//这里会调用拷贝构造函数用str对象拷贝构造临时无名对象,之后在栈中将临时对象释放
}
//+=运算符重载为成员函数
String& String:: operator+=(const String &str2)
{
*this = *this + str2;
cout << "+=运算符成员函数重载!\n";
return *this;
}
//+=运算符重载为友元函数
String& operator+=(String &str1, String &str2)//可以返回引用,因为这里的str1超过这个函数栈还存在
{
str1 = str1 + str2;
cout<< "+=运算符友员函数重载!\n";
return str1;
}
//!=重载函数
bool operator!=(String &str1, String &str2)
{
if (!strcmp(str1.data, str2.data))
{
cout << "These String is equal!\n";
return false;
}
cout << "These String is not equal!\n";
return true;
}
//==运算符重载
bool operator==(String &str1, String &str2)
{
if (!strcmp(str1.data, str2.data))
{
cout << "These String is equal!\n";
return true;
}
cout << "These String is not equal!\n";
return false;
}
//重载流提取运算符“>>”
istream& operator>> (istream &in, String &str)//in是cin的引用,cin是类istream的对象
{
cout << "Please input string:(end of 'ctrl+Z') ";
char c[101] = { 0 };//缓冲区为100byte大小
char ch = 0;
int i(0);//等价于 i=0;
while ( in>> ch )
{
c[i] = ch;
i++;
}
delete[]str.data;
str.data = new char[i + 1];
strcpy(str.data, c);
return in;
}
//重载流插入运算符“ << ”
ostream& operator<< (ostream &out, String &str)//out是cout的引用,cout是类ostream的对象
{
out<< str.data;
return out;
}
bool operator>(String &str1, String &str2)
{
if (strcmp(str1.data, str2.data) == 1)
{
cout << "First String is big!";
return true;
}
cout << "Second String is big!";
return false;
}
bool operator<(String &str1, String &str2)
{
if (strcmp(str1.data, str2.data) == 1)
{
cout << "First String is big!\n";
return false;
}
cout << "Second String is big!\n";
return true;
}
//析构函数
String::~String()
{
cout << "Free String!" << this << "\n";
}
加上一个运算符重载 []只能重载为成员函数
char& operator[](int index)
{
if(index<0 || index>strlen(this->m_data))
{
cout<<"Error!"<<endl;
exit(0);
}
return m_data[index];
}
补充一下字符串的赋值函数可以借助拷贝构造函数进行
void Swap( Str &str)
{
char *tmp =str.s;
str.s = s;
s = tmp;
}
Str& operator=( const Str &str)
{
Str tmp = str;
tmp.Swap(*this);
return *this;
}
Str& operator=( Str str)//可以在拷贝构造函数抛出异常的时候立即终止赋值操作,不会修改左值对象
{
str.Swap(*this);
return *this;
}