模拟实现string类

在c++中,string其实就是将字符串封装起来的类,调用类中的成员函数可以完成对类内的字符串进行增删查改,并且将操作符重载,可以更直观的操作字符串,省去了c语言中很多麻烦的操作,有现成的成员函数供我们使用。

举一个简单的例子:在c语言中要在一串字符串的尾部拼接另一个字符串,我们需要做的事情就是定义两个字符串,要使用malloc,然后自己书写拼接逻辑。而在c++中只需要构造出lian两个string对象s1,s2, 使用 s1+=s2,就可以使s2拼接到s1的后面,我们不用关心底层怎么实现,不用写拼接逻辑,并且代码更加直观。

String.h 

#include <iostream>
#include <unistd.h>
#include <string.h>
#include <assert.h>

class String
{
  public:
      String(const char* str = "")
          :_size(strlen(str))
          ,_capacity(_size + 1)
          {
              _str = new char[_size + 1];
              memcpy(_str, str, _size + 1);
          }
    // s1.Swap(s2);
    void Swap(String& s);

    // String s2(s1)
    String(const String& s)
        :_size(s._size)
        ,_capacity(_size + 1)
    {
        _str = new char[_size + 1];
        memcpy(_str, s._str, _size + 1);
    }

    // s1 = s2
    String& operator=(String s);

    ~String() {
        if(_str) {
            delete[] _str;
            _str = NULL;
        }
    }

    void Show();

    const char* c_str();        //获取String类中的c风格字符串
    void Expand(size_t n);        //扩容
    void PushBack(char ch);        //尾部插入一个字符
    void PushBack(const char* str);    //尾部插入一个字符串
    void PopBack();        //尾部删除一个字符
    void Insert(size_t pos, char ch);     //在pos位置插入一个字符
    void Insert(size_t pos, const char* str);    //在pos位置插入一个字符串
    void Erase(size_t pos, size_t n = 1);        //在pos位置删除n个字符串


    size_t Find(char ch);      //返回String对象中第一次出现ch的下标
    size_t Find(const char* str); // //返回String对象中第一次出现str的下标

    // s1 + 'a'
    String operator+(char ch);
    String& operator+=(char ch);
    String operator+(const char* str);
    String& operator+=(const char* str);

    bool operator>(const String& s);
    bool operator>=(const String& s);
    bool operator<(const String& s);
    bool operator<=(const String& s);
    bool operator==(const String& s);
    bool operator!=(const String& s);

  private:
    char* _str;
    size_t _size;
    size_t _capacity;
};
#include "String.h"
using namespace std;


void String::Show() {
    std::cout<<"_str :"<<_str<<std::endl;
    std::cout<<"_szie :"<<_size<<std::endl;
    std::cout<<"_capacity :"<<_capacity<<std::endl<<endl;
}

void String::Swap(String& s) {
    _size = s._size;
    _capacity = s._capacity;
    delete[] _str;
    _str = s._str;
    s._str = new char[1];
}

String& String::operator= (String s) {
    Swap(s);
    return *this;
}

const char* String::c_str(){
    return _str;
}

void String::Expand(size_t n) {
    char* tmp = new char[n];
    memcpy(tmp, _str, _size + 1);
    delete[] _str;
    _str = tmp;
    _capacity = n;
}


void String::PushBack(char ch) {
    Insert(_size, ch);
}

void String::PushBack(const char* str) {
    Insert(_size, str);
}

void String::Insert(size_t pos, char ch) {
    assert(pos <= _size);

    if(_size >= _capacity - 1) {
        Expand(2 * _capacity + 1);
    }
    
    for(int i = (int)_size; i > (int)pos; i--) {
        _str[i] = _str[i-1];
    }
    _str[pos] = ch;
    ++_size;
}

void String::Insert(size_t pos, const char* str) {
    assert(pos <= _size);

    const char* tmp = str;
    size_t size = 0;
    for(; *tmp != '\0'; ++tmp) {
        ++size;
    }

    if(_capacity < (_size + size)) {
        Expand(_capacity + size);
    }

    for(int i = (int)_size; i >= (int)pos; --i) {
        _str[i+size] = _str[i];
    }
    
    int i = 0;
    while(*(str+i) != '\0') {
        _str[pos + i] = *(str + i);
        ++i;
    }
    _size += size;
}

void String::PopBack() {
    Erase(_size - 1, 1);
}

void String::Erase(size_t pos, size_t n) {
    if(_size == 0) {
        return;
    }
    if(n == 0) {
        return;
    }
    
    assert(pos <= _size);

    while((pos + n) <= _capacity) {
        _str[pos] = _str[pos+n];
        ++pos;
    }

    if(((int)_size - (int)n) > 0) {
        _size = _size - n;
    }  else {
        _size = 0;
    }

    _str[_size] = 0;
}

size_t String::Find(char ch) {
    for(size_t i = 0; i<_size; ++i) {
        if(_str[i] == ch) {
            return i;
        }
    }
    return (size_t)-1;
}

size_t String::Find(const char* str) {
    const char* _fast = _str;
    const char* _slow = _str;
    const char* cur = str;
    while(_slow < (_str + _size)) {
        _fast = _slow;
        if(*_fast == *cur) {
            while(*_fast == *cur) {
                if(*_fast == '\0') {
                    break;
                }
                _fast++, cur++;
            }
            if(*cur == '\0') {
                return _slow - _str;
            }
        }
        _slow++;
        cur = str;
    }

    return (size_t) -1;
}

String String::operator+(char ch) {
    String tmp(*this);
    tmp.PushBack(ch);
    return tmp;
}

String& String::operator+=(char ch) {
    this->PushBack(ch);
    return *this;
}

String String::operator+(const char* str) {
    String tmp(*this);
    tmp.PushBack(str);
    return tmp;
}

String& String::operator+=(const char* str) {
    this->PushBack(str);
    return *this;
}

bool String::operator>(const String& s) {
    const char* _tmp = _str;
    const char* tmp = s._str;
    while(*tmp != '\0' && *_tmp != '\0' && *_tmp == *tmp) {
        _tmp++, tmp++;
    }
    if(*_tmp > *tmp) {
        return true;
    }  
    return false;
}

bool String::operator>=(const String& s) {
    if(*this > s || *this == s) {
        return true;
    }
    return false;
}

bool String::operator<(const String& s) {
    const char* _tmp = _str;
    const char* tmp = s._str;
    while(*tmp != '\0' && *_tmp != '\0' && *_tmp == *tmp) {
        _tmp++, tmp++;
    }
    if(*_tmp < *tmp) {
        return true;
    }  
    return false;
}

bool String::operator<=(const String& s) {
    if(!(*this > s)) {
        return true;
    }
    return false;
}

bool String::operator==(const String& s) {
    const char* _tmp = _str;
    const char* tmp = s._str;
    while(*_tmp == *tmp) {
        if(*_tmp == '\0' && *tmp == '\0') {
            return true;
        }
        _tmp++, tmp++;
    }
    return false;
}

bool String::operator!=(const String& s) {
    if(!(*this == s)) {
        return true;
    }
    return false;
}

void Test(){
//    String s1("12345");
//    s1.Show();
//    
//    String s2(s1);
//    s2.Show();
//
//    String s3 = s2;
//    s3.Show();
//    
//    cout<<"test c_str:"<<s3.c_str()<<endl;
//
//    s3.Expand(20);
//    s3.Show();
//

//    String s4("abc");
//    s4.Show();
//    s4.PushBack('1');
//    s4.Show();
//    s4.PushBack("2345");
//    s4.Show();
//    s4.Insert(8, 'A');
//    s4.Show();
//    s4.Insert(3, 'd');
//    s4.Show();
//    s4.Insert(4, "ABCD");
//    s4.Show();
//    s4.Insert(14, "HHHH");
//    s4.Show();
//    
//    s4.PopBack();
//    s4.PopBack();
//    s4.PopBack();
//    s4.PopBack();
//    s4.PopBack();
//    s4.Show();
//    s4.Erase(0, 4);
//    s4.Show();
//    s4.Erase(0, 0);
//    s4.Show();
//    s4.Erase(0, 20);
//    s4.Show();

//    String s5("abacadabcdaaa");
//    cout<<s5.Find('a')<<endl;
//    cout<<s5.Find('b')<<endl;
//    cout<<(int)s5.Find('A')<<endl<<endl;
//
//    cout<<(int)s5.Find("")<<endl;
//    cout<<(int)s5.Find("abcd")<<endl;
//    cout<<(int)s5.Find("aaa")<<endl;
//    cout<<(int)s5.Find("ab")<<endl;
//    cout<<(int)s5.Find("abaa")<<endl;

//    String s6("a");
//    s6 = s6 + 'b';
//    s6 += 'c';
//    s6 = s6 + "123";
//    s6 += "456";
//    s6.Show();
    
//    String s7("abcdefg");
//    String s8("abcdef");
//    cout<<(s7==s7)<<endl;
//    cout<<(s7==s8)<<endl;
//    cout<<(s7!=s7)<<endl;
//    cout<<(s7!=s8)<<endl;


    String s7("abcdefg");
    String s8("abcdef");
    cout<<(s7>=s7)<<endl;   //1
    cout<<(s7<=s7)<<endl;   //1
    cout<<(s7>=s8)<<endl;   //1
    cout<<(s7<=s8)<<endl;   //0
    cout<<(s7>s7)<<endl;    //0
    cout<<(s7<s7)<<endl;    //0
    cout<<(s7>s8)<<endl;    //1
    cout<<(s7<s8)<<endl;    //0
}

int main()
{
    Test();

  return 0;
}

猜你喜欢

转载自blog.csdn.net/luhaowei0066/article/details/81262963