【c/c++项目学习】写一个String

1、头文件

StringTest.h

#ifndef STRINGTEST_H
#define STRINGTEST_H
#include <iostream>
#include <cstring>
class StringTest
{
private:
    char* data_;
    size_t size_;

public:
    StringTest();                                   // 空构造
    StringTest(const char* str);                    // 普通构造
    StringTest(const StringTest& other);            // 拷贝构造
    ~StringTest();                                  // 析构函数

    char& operator[](size_t index);                 // 重载[]运算符
    bool operator==(const StringTest& other);       // 重载==
    StringTest operator+(const StringTest& other);  // 重载+
    const char* c_str() const;                      // 转换成c风格的字符串
    size_t length();                                // 获得字符串长度
    friend std::ostream& operator<<(std::ostream& out,const StringTest& str);    //友元的方式 重载<<
    friend std::istream& operator>>(std::istream& in,StringTest& str);           //友元的方式 重载>>

private:
  void __init(const char* str);                     // 分配内存
  void __clean();                                   // 清除内存
};
#endif

(1)这里使用char*字符串+size_的方式实现的;

(2)首先有空构造、普通构造、拷贝构造、析构函数(特别注意参数);

(3)接着是重载[]、==、+、<<、>>操作符(特别注意参数、返回值类型);

(4)为了减少代码的冗余,这里提供了_init(const char* str)和_clean()函数,用户分配内存和清除内存,主要用在构造函数和析构函数中。

2、实现

StringTest.cpp

#include "StringTest.h"

// 分配内存
void StringTest::__init(const char* str)
{
    //传入空字符串
    if(str == nullptr)
    {
        this->data_ = nullptr;
        this->size_ = 0;
    }
    else
    {
        this->size_ = std::strlen(str);
        this->data_ = new char[this->size_ + 1];
        strncpy(this->data_, str, this->size_ + 1);
    }
}

// 清除内存
void StringTest::__clean()
{
    if (this->data_ != nullptr)
    {
        delete[] this->data_;
    }
    this->size_ = 0;
}


//空构造
StringTest::StringTest():data_(nullptr),size_(0){}

//普通构造
StringTest::StringTest(const char* str)
{
    __init(str);
}

//拷贝构造
StringTest::StringTest(const StringTest& other)
{
    std::cout<<"copy construct"<<std::endl;
    __init(other.data_);
}

//析构函数
StringTest::~StringTest()
{
    __clean();
}

//重载[]运算符
char& StringTest::operator[](size_t index)
{
    //越界抛异常
    if(index >= this->size_)
    {
        throw"index out of range";

    }
    return this->data_[index];
}

//重载==运算符
bool StringTest::operator==(const StringTest& other)
{
    if(other.size_ != this->size_)
    {
        return false;
    }
    return 0 == std::strcmp(this->data_,other.data_);
}

//重载+运算符
StringTest StringTest::operator+(const StringTest& other)
{
    if (other.size_ == 0)
    {
        return *this;
    }
    else if (this->size_ == 0)
    {
        return other;
    }

    //存储加了之后的数据
    StringTest s;
    s.size_ = this->size_ + other.size_;
    s.data_ = new char[s.size_ + 1];

    strncpy(s.data_, this->data_, this->size_);
    strncpy(s.data_ + this->size_, other.data_, other.size_);
    s.data_[s.size_] = '\0';
    return s;
}

//转换成c风格的字符串
const char* StringTest::c_str() const
{
    return this->data_;
}

//获得字符串长度
size_t StringTest::length()
{
    return this->size_;
}

//重载<<
std::ostream& operator<<(std::ostream& out,const StringTest& str)
{
    if(str.data_ == nullptr)
    {
        out<<"";
    }
    else
    {
        out<<str.data_;
    }
    return out;
}

//重载>>
std::istream& operator>>(std::istream& in,StringTest& str)
{
    std::cout<<"Please input StringTest size:";
    in>>str.size_;
    str.data_ = new char[str.size_ + 1];
    std::cout<<"Please input StringTest data";
    in>>str.data_;

    int len = std::strlen(str.data_);
    if(len > str.size_)
    {
        std::cout<<"error! data len > size"<<std::endl;
        exit(1);
    }
    return in;
}

(1)首先是实现__init(const char* str)函数,即根据传入str指针分配内存;

(2)清除内存;

(3)空构造:data_ 指向空,size_等于0;

(4)普通构造:调用__init(const char* str)函数;

(5)拷贝构造:调用__init(const char* str)函数;

(6)析构函数:调用__clean()函数;

(7)重载[];

(8)重载==运算符;

(9)重载+运算符;

(10)重载<<;

(11)重载>>;

(12)这里需要特别注意的就是strncpy函数的使用。

函数原型char*strncpy(char*dest,char*src,size_t n);把src所指向的字符串中以src地址开始的前n个字节复制到dest所指的数组中,并返回dest。

主要代码段

this->size_ = std::strlen(str);
this->data_ = new char[this->size_ + 1];
strncpy(this->data_, str, this->size_ + 1);

先求出str的长度(不含'\0');

再申请this->size_ + 1的内存空间;

最后把src所指向的字符串中以src地址开始的前n个字节复制到dest所指的数组中,并返回dest。(包含'\0');

(13)还需要注意重载+运算符

StringTest StringTest::operator+(const StringTest& other)
{
    if (other.size_ == 0)
    {
        return *this;
    }
    else if (this->size_ == 0)
    {
        return other;
    }

    //存储加了之后的数据
    StringTest s;
    s.size_ = this->size_ + other.size_;
    s.data_ = new char[s.size_ + 1];

    strncpy(s.data_, this->data_, this->size_);
    strncpy(s.data_ + this->size_, other.data_, other.size_);
    s.data_[s.size_] = '\0';
    return s;
}

用s存储相加之后的数据,再申请空间,最后逐一拷贝进去。

3、test

test.cpp

#include "StringTest.h"

int main(int argc,char* argv[])
{
    std::cout << "copy constructor test" << std::endl;
    StringTest x("xxx");
    // 拷贝构造
    StringTest cop = x;

    std::cout << "copy assignment test" << std::endl;
    // copy assignment
    x = cop;

    std::cout << "operator<< test" << std::endl;
    StringTest c = StringTest("hello");
    std::cout << c << std::endl;

    std::cout << "operator>> test" << std::endl;
    StringTest in;
    std::cin >> in;
    std::cout << in << std::endl;

    std::cout << "operator == test" << std::endl;
    StringTest aa = "hello";
    StringTest bb = "hello";
    StringTest cc = "hello1";
    std::cout << (aa == bb) << "," << (aa == cc) << std::endl;

    std::cout << "operator+ test" << std::endl;
    StringTest ad;
    StringTest bd("lucy");
    StringTest cd = ad + bd;
    std::cout << cd << std::endl;

    std::cout << "c_str() test" << std::endl;
    std::cout << cd.c_str() << std::endl;

    std::cout << "legth() test" << std::endl;
    std::cout << cd.length() << std::endl;
    system("pause");
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值