1. 程式人生 > >經典面試題—string類的詳細分析與實現

經典面試題—string類的詳細分析與實現

#define _CRT_SECURE_NO_WARNINGS -1

#include <new.h>
#include <iostream>
using namespace std;

class String
{
public:
    //建構函式
    String(const char* str = "")
        :_str(new char[strlen(str) + 1])
    {
        strcpy(_str, str);
        _size = strlen(str);
        _capacity = _size;
    }

    ////拷貝建構函式
    //String(const String& s)//傳統寫法
    //  :_str(new char[s._capacity])
    //{
    //  strcpy(_str, s._str);
    //  _size = s._size;
    //  _capacity = s._capacity;
    //}

    ////賦值操作符過載
    //String& operator=(String s)//傳統寫法
    //{
    //  if (this != &s)
    //  {
    //      char* tmp = new char[strlen(s._str) + 1];
    //      delete[] _str;
    //      strcpy(_str, s._str);
    //      _size = s._size;
    //      _capacity = s._capacity;
    //  }

    //  return *this;
    //}

    // s1.Swap(s2); 
    void Swap(String& s)
    {
        char* tmp = _str;
        _str = s._str;
        s._str = tmp;
    }
    // 拷貝建構函式
    // String s2(s1) 
    String(const String& s)//現代寫法
        :_str(NULL)
    {
        String tmp(s._str);
        this->Swap(tmp);
        _size = s._size;
        _capacity = s._capacity;
    }
    //賦值操作符過載
    // s1 = s2 
    String& operator=(String s)//現代寫法
    {
        if (this != &s)
        {
            String tmp(s._str);
            this->Swap(s);
            _size = s._size;
            _capacity = s._capacity;
        }
        return *this;   
    }
    //解構函式
    ~String()
    {
        if (_str != NULL)
        {
            delete[] _str;
            _str = NULL;
            _size = 0;
            _capacity = 0;
        }
    }
    //獲取類中的字串成員變數
    const char* c_str()
    {
        return _str;
    }

    //擴容
    void Expand(size_t n)
    {
        if (n > _capacity)
        {
            char* tmp = new char[n + 1];
            strcpy(tmp, _str);
            delete[] _str;
            _str = tmp;
            _capacity = n;
        }
    }
    //尾插一個字元
    void PushBack(char ch)
    {
        if (_size >= _capacity)
        {
            Expand(_capacity * 2);
        }
        _str[_size++] = ch;
        _str[_size] = '\0';
    }
    //尾插一個字串
    void PushBack(const char* str)
    {
        if (str == NULL)
        {
            return;
        }
        int len = strlen(str);
        if (_size + len > _capacity)
        {
            Expand(_size + len);
        }
        strcpy(_str + _size, str);
        _size += len;
    }
    //+操作符過載,+一個字元
    String operator+(char ch)
    {
        String tmp(*this);
        tmp.PushBack(ch);
        return tmp;
    }
    //+=操作符過載,+=一個字元
    String& operator+=(char ch)
    {
        //this->PushBack(ch);
        PushBack(ch);
        return *this;
    }

    //+操作符過載,+一個字串
    String operator+(const char* str)
    {
        String tmp(*this);
        tmp.PushBack(str);
        return tmp;
    }
    //+=操作符過載,+=一個字串
    String& operator+=(const char* str)
    {
        //this->PushBack(str);
        PushBack(str);
        return *this;
    }
    //尾刪一個字元
    void PopBack()
    {
        _str[_size] = '\0';
        _size--;
    }
    //指定位置插入一個字元
    void Insert(size_t pos, char ch)
    {
        if (pos > _size)//插入位置不合法
        {
            return;
        }
        if (_size >= _capacity)//擴容
        {
            Expand(_capacity * 2);
        }
        if (pos == _size)
        {
            _str[_size++] = ch;
        }
        else
        {
            char* tmp = new char[_size - pos + 1];
            strcpy(tmp, _str + pos);
            _str[pos] = ch;
            strcpy(_str + pos + 1, tmp);
            _size++;
            delete[] tmp;
        }
    }
    //指定位置插入一個字串
    void Insert(size_t pos, const char* str)
    {
        if (pos > _size || str == NULL)
        {
            return;
        }
        int len = strlen(str);
        if (_size + len > _capacity)//擴容
        {
            Expand(_size + len);
        }
        if (pos == _size)
        {
            strcat(_str, str);
        }
        else
        {
            char* tmp = new char[_size - pos + 1];
            strcpy(tmp, _str + pos);
            strcpy(_str + pos,str);
            strcpy(_str + pos + len, tmp);
            ////或直接使用strcat
            //strcat(_str, tmp);
            delete[] tmp;
        }
    }
    //刪除pos下標開始往後n個元素
    void Erase(size_t pos, size_t n = 1)
    {
        if (pos > _size)
        {
            return;
        }
        char* str = _str + pos;
        while (*str != '\0' && n > 0)
        {
            *str = '\0';
            str++;
            n--;
            _size--;
        }
        strcpy(_str + pos, str);
    }
    //查詢字串中的某個字元
    size_t Find(char ch)
    {
        char* str = _str;
        while (*str != '\0')
        {
            if (*str == ch)
            {
                return (int)(str - _str);
            }
            str++;
        }
        return -1;
    }
    //查詢第一個子串的的位置
    size_t Find(const char* str)
    {
        if (str == NULL)
        {
            return -1;
        }
        char* tmp = strstr(_str, str);
        if (tmp != NULL)
        {
            return (size_t)(tmp - _str);
        }
        return -1;
    }
    //更改字串中的某個字元
    void Replace(char ch1, char ch2)
    {
        char* str = _str;
        while (*str != '\0')
        {
            if (*str == ch1)
            {
                *str = ch2;
            }
            str++;
        }
    }
    //替換字串中的某個字串
    void Replace(const char* sub1, const char* sub2)
    {
        if (sub1 == NULL || sub2 == NULL || strcmp(sub1, sub2) == 0)
        {
            return;
        }
        size_t pos = Find(sub1);
        if (pos != -1)
        {
            char* str = _str;
            int len = strlen(_str);
            int len1 = strlen(sub1);
            int len2 = strlen(sub2);

            if (len1 == len2)
            {
                while (pos != -1)
                {
                    _str = _str + pos;
                    int i = 0;
                    while (i < len1)
                    {
                        _str[i] = sub2[i];
                        i++;
                    }
                    pos = Find(sub1);
                }
                _str = str;
            }
            else
            {
                int count = 0;
                char** arr = new char*[len];
                memset(arr, 0, sizeof(char*)*len);
                while (pos != -1)
                {
                    _str =_str + pos + 1;
                    arr[count] = _str - 1;
                    count++;
                    pos = Find(sub1);
                }
                _str = str;
                int capacity = len + count*(len2 - len1);
                char* newStr = new char[capacity + 1];
                memset(newStr, 0, capacity + 1);
                count = 0;
                char* cur = newStr;
                while (*_str != '\0')
                {
                    if (_str == arr[count])
                    {
                        for (int i = 0; i < len2; i++)
                        {
                            cur[i] = sub2[i];
                        }
                        _str += len1;
                        cur += len2;
                        count++;
                    }
                    else
                    {
                        *cur++ = *_str++;
                    }   
                }
                _str = newStr;
                _size = capacity;
                _capacity = capacity;
                newStr = str;
                delete[] newStr;
            }
        }
        else
        {
            return;
        }
    }

    // >操作符過載,比較字串大小
    bool operator>(const String& s)
    {
        if (this == &s || strcmp(_str, s._str) > 0)
        {
            return true;
        }
        return false;
    }
    // =操作符過載,判斷字串是否相等
    bool operator==(const String& s)
    {
        if (this == &s || strcmp(_str, s._str) == 0)
        {
            return true;
        }
        return false;
    }
    bool operator>=(const String& s)
    {
        if (*this > s && *this == s)
        {
            return true;
        }
        return false;
    }
    bool operator<(const String& s)
    {
        if (!(*this >= s))
        {
            return true;
        }
        return false;
    }
    bool operator<=(const String& s)
    {
        if (!(*this > s))
        {
            return true;
        }
        return false;
    }
    bool operator!=(const String& s)
    {
        if (!(*this == s))
        {
            return true;
        }
        return false;
    }

private:
    //char _buffer[16];
    char* _str;
    size_t _size;
    size_t _capacity;
};

int main()
{   
    //String s1("abc");
    //String s2(s1);
    //String s3("123abc");
    //s3 = s1;
    //cout << (s3 + 'd').c_str() << endl;
    //cout << (s3 + 'e').c_str() << endl;
    //cout << (s3 + 'f').c_str() << endl;
    //cout << (s3 + 'g').c_str() << endl;
    //cout << (s3 + 'h').c_str() << endl;
    //s3 += "123456";
    //s3.Insert(1, 'x');
    //s3.Insert(2, 'y');
    //s3.Insert(3, 'z');
    //s3.Insert(1, '0');
    //s3.Insert(0, "789");
    //cout << s3.Find('a') << endl;
    //s3.Replace('a', '1');
    //cout << s3.Find('a') << endl;
    //s3.Erase(0, 3);
    ////string s="abc123abc";
    ////s = s.replace("abc", "xx");
    //cout << s3.Find('b') << endl;
    //cout << s3.Find('w') << endl;

    String s("abc123");
    s.Replace("xyz", "asd");
    s.Replace("a", "ddd");
    s.Replace("123", "f");
    s.Replace("dbc", "666");
    s.Replace("666", "6");
    cout << s.c_str() << endl;
    system("pause");
    return 0;
}