string类的实现

面试题目,好久没写代码,写下了下面的代码:

#pragma once
class AString
{
public:
AString(const char* pInput = NULL);
~AString(void);
AString(const AString &OtherString);//拷贝构造函数,开始没有想起
AString operator+(const AString &OtherString);
AString operator=(const AString &OtherString);//返回值是AString
bool operator==(AString &OtherString);//参数不用带const
int AstrLen(AString &InputString);




private:
char* m_pData;//不是数组,是指针
};

#include "StdAfx.h"
#include "AString.h"

AString::AString(const char* pInput)
{
if(!pInput)
{
int nSize = 0;
char* p = (char*)pInput;
while(p++)
nSize++;
m_pData = new char[nSize+1];
strcpy(m_pData,pInput); //不需要逐个赋值
}
else
{
m_pData = NULL;
}
}




AString::~AString(void)
{
if(NULL != m_pData)
{
delete[] m_pData;
m_pData = NULL;
}




}
AString::AString(const AString &OtherString)
{
if(NULL != OtherString)
{
stcpy(m_pData,OtherString->m_pData);
}

}
AString AString::operator+(const AString &OtherString)
{
if(OtherString->m_pData != NULL)
{
int nSize = strlen(OtherString->m_pData)+strlen(m_pData);
char tmpChar = new char[nSize];
stcpy(tmpChar,m_pData);
stcat(tmpChar,OtherString->m_pData);
AString tmpStr = new AString(const char*(tmpChar));
return tmpSrt;
}
else
{
return *this;
}
}
AString AString::operator=(const AString &OtherString)
{
if(OtherString->m_pData != NULL)
{
delete []m_pData;
int nSize = strlen(OtherString->m_pData);
char *tmpChar = new char[nSize];
stcpy(tmpChar,m_pData);
m_pData = tmpChar;

return *this;
}
else
{
return *this;
}
}

int AString::AstrLen(AString &InputString)
{
int nTmp = 0;
if(NULL == InputString)
{
return 0;
}
char*p = InputString->m_pData;
while('\0' != *p++)
{
nTmp++;
}
return nTmp;

               //下面即可

       return strlen(m_data);
}

 

下面是修改加注释

#pragma once

//应该加上下面三行

#include<iostream>

#include<iomanip> 

using namespace std;  

 

class AString
{
public:
AString(const char* pInput = NULL);          //赋值构造兼默认构造函数(char)  
~AString(void);
AString(const AString &OtherString); //赋值构造函数(String)  
AString operator+(const AString &OtherString);
AString& operator=(const AString &OtherString);//返回值应该是AString&,而不是AString
bool operator==(AString &OtherString);//应改为bool operator==(const AString &OtherString);
int AstrLen(AString &InputString);//改为size_t size(){return strle(m_pData):}




private:
char* m_pData;
};

#include "StdAfx.h"
#include "AString.h"

AString::AString(const char* pInput)  //应该改为inline AString::AString(const char* pInput)  
{

//声明为inline函数,则该函数在程序中被执行时是语句直接替换,而不是被调用  
if(pInput)
{
int nSize = 0;     
char* p = (char*)pInput;
while(p++)
nSize++;
m_pData = new char[nSize+1];//可以直接改为m_pData = new char[strlen(pInput)+1];
strcpy(m_pData,pInput);
}
else
{
m_pData = NULL;
}
}




AString::~AString(void)
{
if(NULL != m_pData)
{
delete []m_pData;
m_pData = NULL;
}




}
AString::AString(const AString &OtherString)//应该改为inline AString::AString(const AString &OtherString)
{
if(NULL != OtherString)
{

                       if(NULL != m_pData)

{

    delete m_pData;

                                m_pData = NULL;

}

                      m_pData =new char[strlen(OtherString.m_pData)+1];  
stcpy(m_pData,OtherString->m_pData);
}

}
AString AString::operator+(const AString &OtherString)//前面应该加inline
{
if(OtherString->m_pData != NULL)
{
int nSize = strlen(OtherString->m_pData)+strlen(m_pData);
char tmpChar = new char[nSize];
stcpy(tmpChar,m_pData);
stcat(tmpChar,OtherString->m_pData);//只有两个参数,不用管其它
AString tmpStr = new AString(const char*(tmpChar));//相加产生新的对象,所以要new
return tmpSrt;
}
else
{
return *this;
}

               //应改为下面

              

  1.     String newString;  
  2.     if(!other.m_data)  
  3.         newString = *this;  //直接赋值
  4.     else if(!m_data)  
  5.         newString = other;  
  6.     else  
  7.     {  
  8.         newString.m_data = new char[strlen(m_data)+strlen(other.m_data)+1];  
  9.         strcpy(newString.m_data,m_data);  
  10.         strcat(newString.m_data,other.m_data);  
  11.     }  
  12.     return newString; 


}
AString AString::operator=(const AString &OtherString) //前面应该加inline
{
if(OtherString->m_pData != NULL)
{
delete []m_pData;
int nSize = strlen(OtherString->m_pData);
char *tmpChar = new char[nSize];
stcpy(tmpChar,m_pData);
m_pData = tmpChar;

return *this;
}
else
{
return *this;
}

 

                //应该改为下面

               

  1.  if (this!=&other)  
  2.     {  
  3.         delete[] m_data;  
  4.         if(!other.m_data) m_data=0;  //容易忘掉
  5.         else  
  6.         {  
  7.             m_data = new char[strlen(other.m_data)+1];  
  8.             strcpy(m_data,other.m_data);  
  9.         }  
  10.     }  
  11.     return *this;  


}

int AString::AstrLen(AString &InputString)
{
int nTmp = 0;
if(NULL == InputString)
{
return 0;
}
char*p = InputString->m_pData;
while('\0' != *p++)
{
nTmp++;
}
return nTmp;
}

 

 

 

85 //等号运算符‘==’号重载
 86 bool StringRealize::operator==(const StringRealize& str)
 87 {
 88     if (strlen(this->m_data) != strlen(str.m_data)  )
 89     {
 90         return false;
 91     }
 92     else
 93     {
 94         return strcmp( this->m_data, str.m_data ) ? false : true;
 95     }
 96 
 97 }
 98 
 99 //获取字符串的长度
100 int StringRealize::getLength()
101 {
102     return strlen(this->m_data);
103 }

 

105 //输出符重载
106 std::ostream& operator<<(std::ostream& os, const StringRealize& str)
107 {
108     os<<str.m_data;
109     return os;
110 }
111 
112 //输入符重载
113 std::ostream& operator>>(std::ostream& os, const StringRealize& str)
114 {
115     os>>str.m_data;
116     return os;
117 }

完整版本

一 整体框架

除了以上四个必须的函数,这里还实现了一些附加的内容。

  • 若干个运算符重载,这里的几个是常见的运算符,可以加深对String的认识和运算符重载的理解。
  • 两个常用的函数,包括取字符串长度和取C类型的字符串。
  • 两个处理输入输出的运算符重载,为了使用的方便,这里把这两个运算符定义为友元函数。

整体的类的框架如下所示。

class String
{
public:
    String(const char *str = NULL);    //通用构造函数
    String(const String &str);        //拷贝构造函数
    ~String();                        //析构函数

    String operator+(const String &str) const;    //重载+
    String& operator=(const String &str);        //重载=
    String& operator+=(const String &str);        //重载+=
    bool operator==(const String &str) const;    //重载==
    char& operator[](int n) const;                //重载[]

    size_t size() const;        //获取长度
    const char* c_str() const;    //获取C字符串

    friend istream& operator>>(istream &is, String &str);//输入
    friend ostream& operator<<(ostream &os, String &str);//输出

private:
    char *data;        //字符串
    size_t length;    //长度
};
//注意,类的成员函数中,有一些是加了const修饰的,表示这个函数不会对类的成员进行任何修改。一些函数的输入参数也加了const修饰,表示该函数不会对改变这个参数的值。

 

 

二 具体实现

 

/*下面逐个进行成员函数的实现。
同样构造函数适用一个字符串数组进行String的初始化,默认的字符串数组为空。这里的函数定义中不需要再定义参数的默认值,因为在类中已经声明过了。
另外,适用C函数strlen的时候需要注意字符串参数是否为空,对空指针调用strlen会引发内存错误。*/
 String::String(const char *str)//通用构造函数
{
    if (!str)
    {
        length = 0;
        data = new char[1];
        *data = '\0';
    }
    else
    {
        length = strlen(str);
        data = new char[length + 1];
        strcpy(data, str);
    }
}
//拷贝构造函数需要进行深复制。
String::String(const String &str)//拷贝构造函数
{
    length = str.size();
    data = new char[length + 1];
    strcpy(data, str.c_str());
}
//析构函数需要进行内存的释放及长度的归零。
String::~String()//析构函数
{
    delete []data;
    length = 0;
}
//重载字符串连接运算,这个运算会返回一个新的字符串。
String String::operator+(const String &str) const//重载+
{
    String newString;
    newString.length = length + str.size();
    newString.data = new char[newString.length + 1];
    strcpy(newString.data, data);
    strcat(newString.data, str.data);
    return newString;
}
//重载字符串赋值运算,这个运算会改变原有字符串的值,为了避免内存泄露,这里释放了原先申请的内存再重新申请一块适当大小的内存存放新的字符串。
String& String::operator=(const String &str)//重载=
{
    if (this == &str)    return *this;

    delete []data;
    length = str.length;
    data = new char[length + 1];
    strcpy(data, str.c_str());
    return *this;
}
//重载字符串+=操作,总体上是以上两个操作的结合。
String& String::operator+=(const String &str)//重载+=
{
    length += str.length;
    char *newData = new char[length + 1];
    strcpy(newData, data);
    strcat(newData, str.data);
    delete []data;
    data = newData;
    return *this;
}
//重载相等关系运算,这里定义为内联函数加快运行速度。
inline bool String::operator==(const String &str) const//重载==
{
    if (length != str.length)    return false;
    return strcmp(data, str.data) ? false : true;
}
//重载字符串索引运算符,进行了一个简单的错误处理,当长度太大时自动读取最后一个字符。
inline char& String::operator[](int n) const//重载[]
{
    if (n >= length) return data[length-1]; //错误处理
    else return data[n];
}
//重载两个读取私有成员的函数,分别读取长度和C字符串。
inline size_t String::size() const//获取长度
{
    return length;
}
//重载输入运算符,先申请一块足够大的内存用来存放输入字符串,再进行新字符串的生成。这是一个比较简单朴素的实现,网上很多直接is>>str.data的方法是错误的,因为不能确定str.data的大小和即将输入的字符串的大小关系。
istream& operator>>(istream &is, String &str)//输入
{
    char tem[1000];  //简单的申请一块内存
    is >> tem;
    str.length = strlen(tem);
    str.data = new char[str.length + 1];
    strcpy(str.data, tem);
    return is;
}
//重载输出运算符,只需简单地输出字符串的内容即可。注意为了实现形如cout<<a<<b的连续输出,这里需要返回输出流。上面的输入也是类似。
ostream& operator<<(ostream &os, String &str)//输出
{
    os << str.data;
    return os;
}
inline const char* String::c_str() const//获取C字符串
{
    return data;
}

复制代码

 

三 功能测试

编码完成后需要对代码进行测试,以下是一个简单但不够严谨的测试。

int main()
{
    String s;    
    cin >> s;    
    cout << s << ": " << s.size() << endl;

    char a[] = "Hello", b[] = "World!";
    String s1(a), s2(b);    
    cout << s1 << " + " << s2 << " = " << s1 + s2 << endl;

    String s3 = s1 + s2;
    if (s1 == s3)    cout << "First: s1 == s3" << endl;
    s1 += s2;
    if (s1 == s3)    cout << "Second: s1 == s3" << endl;

    /*程序输入输出为:
    123456789: 9
    Hello + World! = HelloWorld!
    Second: s1 == s3
    Press any key to continue . . .
    */
}

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值