码迷,mamicode.com
首页 > 编程语言 > 详细

String类(C++练习二)

时间:2015-11-01 21:18:23      阅读:342      评论:0      收藏:0      [点我收藏+]

标签:

字符串类(String),熟悉内存管理与拷贝控制

  • 类定义
  • #include <iostream>
    //#include <cstring>
    using std::cout;
    using std::cin;
    
    class String{
        using iterator = char *;
        friend std::ostream &operator<< (std::ostream &, const String &);
        friend std::istream &operator>> (std::istream &, String &);
        friend String operator + (const String &, const String &);
        friend String operator + (const String &, const char *);        //对于非类内的函数,必须参数中存在类类型的参数;
        friend String operator + (const char *, const String &);        //否则会与默认类型的操作符冲突
        friend unsigned int getline(std::istream &, String &);
    public:
        String(const char *rhs = "hello, world");    //构造函数,默认为"hello, world" 通常我们可以默认为NULL
        String(const String &);            //拷贝构造函数
        String &operator= (const String&);    //拷贝赋值运算符
        String &operator= (const char *);    //拷贝赋值运算符
        String & operator += (const String&);
        String & operator += (const char *);
        char operator[] (int);
        iterator begin();
        iterator end();
        String & push_back(const char);
        String & clear();
    
        ~String() { delete [] data; }    //析构函数    
    private:
        char *data;
    };
    std::ostream & operator<< (std::ostream &, const String &);
    std::istream &operator>> (std::istream &, String &);
    
    inline String::String(const char *rhs)
    {
        if (!rhs)                    //必须先检查rhs是否为NULL;对于NULL的拷贝,会去读取未知地址
            data = new char[1]{0};    //因为我们的析构函数调用了delete,所以必须开辟一个空间,
                                    //否则代码在调用析构函数时会delete一个错误空间
        else {
            data = new char[strlen(rhs) + 1];
            strcpy(data, rhs);
        }
    }
    
    inline String& String::operator= (const String& rhs)    //拷贝赋值运算
    {
        this->data = new char[strlen(rhs.data) + 1];
        strcpy(this->data, rhs.data);
        return *this;
    }
    
    inline String & String::operator= (const char *rhs)    //拷贝赋值运算符
    {
        this->data = new char[strlen(rhs) + 1];
        strcpy(this->data, rhs);
        return *this;
    }
  • 类方法实现
  • #include "String.h"
    
    inline String::String(const String &rhs)            //拷贝构造函数
    {
        data = new char[strlen(rhs.data) + 1];        //每次都要 +1 的原因是strlen不包含最后的‘\0‘
        strcpy(data, rhs.data);
    }
    
    std::ostream &operator<< (std::ostream &os, const String &rhs)
    {
        os << rhs.data;
        return os;
    }
    
    std::istream& operator >> (std::istream &is, String &rhs)
    {
        is >> rhs.data;
        return is;
    }
    
    String & String::operator += (const String &rhs)
    {
        if (!rhs.data)            //如果要加的类的数据为NULL,则不需要处理了
            return *this;
        else if (!data)            //如果原来的数据为NULL,则直接把后来的数据拷贝过来;由于上面的判断,所以rhs.data != NULL;
        {
            this->data = new char[strlen(rhs.data) + 1];
            strcpy(this->data, rhs.data);
            return *this;
        }
        else                    //data != NULL && rhs.data != NULL
        {
            char *tmp = new char[strlen(this->data) + 1];
            strcpy(tmp, this->data);
            this->data = new char[strlen(data) + strlen(rhs.data) + 1];
            strcpy(data, tmp);
            strcat(data, rhs.data);
            free(tmp);
            return *this;
        }    
    }
    
    String & String::operator += (const char * rhs)
    {
        if (!rhs)            //如果要加的类的数据为NULL,则不需要处理了
            return *this;
        else if (!data)            //如果原来的数据为NULL,则直接把后来的数据拷贝过来;由于上面的判断,所以rhs.data != NULL;
        {
            this->data = new char[strlen(rhs) + 1];
            strcpy(this->data, rhs);
            return *this;
        }
        else                    //data != NULL && rhs.data != NULL
        {
            char *tmp = new char[strlen(this->data) + 1];
            strcpy(tmp, this->data);
            this->data = new char[strlen(data) + strlen(rhs) + 1];
            strcpy(data, tmp);
            strcat(data, rhs);
            free(tmp);
            return *this;
        }
    }
    
    String operator + (const String &lhs, const String &rhs)
    {
        String tmp(lhs);
        tmp += rhs;
        return tmp;
    }
    
    String operator + (const String &lhs, const char *rhs)
    {
        String tmp(lhs);
        tmp += rhs;
        return tmp;
    }
    
    String operator + (const char *lhs, const String &rhs)
    {
        String tmp(lhs);
        tmp += rhs;
        return tmp;
    }
    
    String::iterator String::begin()
    {
        return data;
    }
    
    String::iterator String::end()
    {
        return data + strlen(data);
    }
    
    char String::operator[] (int index)
    {
        if (index > strlen(data) - 1 || index < 0)
        {
            cout << "index error";
            return 0;
        }
        else
        return *(data + index);
    }
    
    String & String::push_back(const char ch)
    {
        char *tmp = new char[strlen(data) + 2];
        strcpy(tmp, data);    
        *(tmp + strlen(data)) = ch;            //data + strlen(data)是原来的‘\0‘处
        *(tmp + strlen(data) + 1) = \0;
        data = new char[strlen(data) + 2];
        strcpy(data, tmp);
        //free(tmp);
        delete[] tmp;    //delete [] tmp = free(tmp) : 怀疑delete就是把free封装了
        return *this;
    }
    
    String & String::clear()
    {
        delete[] data;
        data = new char[]{0};
        return *this;
    }
    unsigned int getline(std::istream &is, String & rhs)
    {
        char tmp;
        rhs.clear();
        while (is.get(tmp))
        {       
            if (tmp && tmp != \n)
                rhs.push_back(tmp);
            else
                break;
        }
        return strlen(rhs.data);
    }
  • 先把开始的写好了,后面可以一直重用它,比如 += 和 +;
  • 析构函数中需要使用delete [] data,是因为很多操作中都需要开辟空间,所以在默认构造函数中虽然里面不放东西但是还需要开辟一个空间,因为当这个类由于某些原因调用析构函数时,需要有一块空间给delete使用
  • 使用智能指针应该也是可以的,这样的话就不需要delete了

String类(C++练习二)

标签:

原文地址:http://www.cnblogs.com/dylqt/p/4928577.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!