1. 程式人生 > >自己實現String類及其迭代器

自己實現String類及其迭代器

注意事項:

對於C語言字串char*,必須在末尾置'\0';

對指標操作時,必須考慮指標NULL的情況,對strcpy,strcat等庫函式呼叫也一樣;

對指標重新賦值前必須呼叫delete,同一塊記憶體不能呼叫兩次delete;

返回物件的成員函式要區分返回的是當前物件還是新物件,即函式返回型別是否要取地址(&)

String.h

#ifndef STRING_H
#define STRING_H

#include <iostream>

class String {
public:
    String();
    String(const char* str);
    ~String();

    int length()const;
    char* toString()const;
    char* c_str()const; //返回一個C風格字串
    String& insert(const char ch, const int n); //在下標n處插入字元
    String& remove(const int n); //刪除下標n處字元
    String& remove(const int start, const int nChars); //刪除start開始的nChars個字元

    char operator[](const int n) const;

    //必須對流用friend
    friend std::ostream & operator<<(std::ostream & os, const String & str); //友元函式過載<<操作符
    friend std::istream & operator>>(std::istream & is, const String & str); //友元函式過載>>操作符

    int compare(const String &lhs, const String &rhs)const; //比較
    bool operator==(const String &str)const;
    bool operator!=(const String &str)const;
    bool operator>(const String &str)const;
    bool operator<(const String &str)const;

    String& operator+=(const String &str);
    String operator+(const String &str)const;

    String& operator=(const String &str);
    String(const String &str); //複製建構函式

    //返回迭代器的成員函式要放在迭代器類定義後面
    //    iterator begin() const {
    //        return iterator(this, 0);
    //    }
    //
    //    iterator end() const {
    //        return iterator(this, len);
    //    }


private:
    int len;
    char* data;


    /**迭代器
     * 使用方法:
     * String* sp = new String(s);
     * 1.
     * String::iterator it;
     * it = sp;
     * 
     * 2.
     * String::iterator it1(sp);
     * 
     *迭代器範圍:
     * (it<=end()-1);
     * (it>=begin());
     * 對於+ -運算沒有檢查邊界
     */
public:

    class iterator {
    public:

        iterator() {
            it = NULL;
            index = 0;
        }

        iterator(const iterator &rhs) {
            it = rhs.it;
            index = rhs.index;
        }

        iterator(const String *sp) {
            it = sp;
            index = 0;
        }

        iterator(const String *sp, int n) {
            it = sp;
            index = n;
        }

        ~iterator() {
            //            delete it;//!!!!!!不能在迭代器呼叫delete
            it = NULL;
        }

        char operator*() {
            return *(it->data + index);
        }

        iterator operator++(int) {//注意字首運算子的&,字尾運算子無&(返回新的迭代器,即++之前的迭代器)
            iterator copy(*this);
            operator++();
            return copy;
        }

        iterator& operator++() {
            if (it == NULL) {
                std::cout << "迭代器未初始化!程式退出!\n";
                exit(1);
            }
            index++;
            if (index > it->len)
                it = NULL;
            return *this;
        }

        iterator operator--(int) {
            iterator copy(*this);
            operator--();
            return copy;
        }

        iterator& operator--() {
            if (it == NULL) {
                std::cout << "迭代器未初始化!程式退出!\n";
                exit(1);
            }
            index--;
            if (index > it->len || index < -1)//-1表示在begin之前一位
                it = NULL;
            return *this;
        }

        bool operator==(const iterator &rhs) {
            if (it != rhs.it) {
                std::cout << "不同String迭代器!程式退出!==\n";
                exit(1);
            }
            return (it == rhs.it && index == rhs.index);
        }

        bool operator!=(const iterator &rhs) {
            if (it != rhs.it) {
                std::cout << "不同String迭代器!程式退出!!=\n";
                exit(1);
            }
            return !(*this == rhs);
        }

        bool operator<(const iterator &rhs) {
            if (it != rhs.it) {
                std::cout << "不同String迭代器!程式退出!<\n";
                exit(1);
            }
            return (index < rhs.index);
        }

        bool operator<=(const iterator &rhs) {
            if (it != rhs.it) {
                std::cout << "不同String迭代器!程式退出!<=\n";
                exit(1);
            }
            return (index <= rhs.index);
        }

        bool operator>(const iterator &rhs) {
            if (it != rhs.it) {
                std::cout << "不同String迭代器!程式退出!>\n";
                exit(1);
            }
            return (index > rhs.index);
        }

        bool operator>=(const iterator &rhs) {
            if (it != rhs.it) {
                std::cout << "不同String迭代器!程式退出!>=\n";
                exit(1);
            }
            return (index >= rhs.index);
        }

        iterator operator+(const int k) {
            if (it == NULL) {
                std::cout << "迭代器未初始化!程式退出!\n";
                exit(1);
            }
            return iterator(it, index + k);
        }

        iterator operator-(const int k) {
            if (it == NULL) {
                std::cout << "迭代器未初始化!程式退出!\n";
                exit(1);
            }
            return iterator(it, index - k);
        }

        //        friend class String;
    private:
        const String* it;
        int index;
    };

    iterator begin() const {
        return iterator(this, 0);
    }

    iterator end() const {
        return iterator(this, len);
    }
};



#endif /* STRING_H */

String.cpp

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

#include "String.h"
#include <string.h>
#include <stdlib.h>

String::String() {
    data = NULL;
    len = 0;
}

String::String(const char* str) {
    if (str == NULL) {
        data = NULL;
        len = 0;
    } else {
        len = strlen(str);
        data = new char[len + 1];
        strcpy(data, str);
        data[len] = '\0';
    }
}

String::~String() {
    if (data != NULL) {
        delete []data;
        data = NULL;
    }
}

inline int String::length()const {
    return len;
}

char* String::toString()const {
    char* str = new char[len + 1];
    if (data != NULL)
        strcpy(str, data);
    str[len] = '\0';
    return str;
}

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

String& String::insert(const char ch, const int n) {
    int i;
    if (n < len)
        i = n;
    if (n > len - 1)
        i = len;
    if (n < 0)
        i = 0;
    len++;
    char* str = new char[len + 1];
    for (int j = 0; j < i; j++)
        str[j] = *(data + j);
    str[i] = ch;
    for (int j = i; j < len; j++)
        str[j + 1] = *(data + j);
    str[len] = '\0';
    delete []data;
    data = str;
    return *this;
}

String& String::remove(const int n) {
    return remove(n, 1);
}

String& String::remove(const int start, const int nChars) {
    if (start < 0 || nChars <= 0 || start > (len - 1))
        return *this;
    int i;
    if (start + nChars < len)
        i = nChars;
    else
        i = len - start;
    len -= i;
    for (int j = start; j < len; j++)
        *(data + j) = *(data + (j + i));
    *(data + len) = '\0';
    return *this;
}

char String::operator[](const int n) const {
    if (n > (len - 1) || n < 0) {
        std::cout << "超出邊界!程式結束\n";
        exit(1);
    }
    return *(data + n);
}

std::ostream & operator<<(std::ostream & os, const String & str) {
    os << str.toString();
    return os;
}

std::istream & operator>>(std::istream & is, const String & str) {
    is >> str.toString();
    return is;
}

int String::compare(const String& lhs, const String& rhs) const {
    int n = (lhs.len < rhs.len ? lhs.len : rhs.len);
    for (int i = 0; i < n; i++) {
        if (lhs[i] > rhs[i])
            return 1;
        if (lhs[i] < rhs[i])
            return 0;
    }
    if (lhs.len > rhs.len)
        return 1;
    if (lhs.len < rhs.len)
        return 0;
    return -1; //==
}

bool String::operator==(const String &str)const {
    if (len != str.length())
        return false;
    if (len == 0)
        return true;
    int i = 0;
    while (*(data + i) == *(str.data + i))
        i++;
    if (len == (i - 1))
        return true;
    return false;

    //    return (compare(*this, str) == -1);//低效
}

bool String::operator!=(const String &str)const {
    return !(*this == str);
}

bool String::operator>(const String &str)const {
    return (compare(*this, str) == 1);
}

bool String::operator<(const String &str)const {
    return (compare(*this, str) == 0);
}

String& String::operator+=(const String &str) {
    if (str.length() == 0)
        return *this;
    len = len + str.length();
    char* newstr = new char[len + 1];
    if (data != NULL) {
        strcpy(newstr, data);
        delete []data;
    }
    strcat(newstr, str.data);
    newstr[len] = '\0';
    data = newstr;
    return *this;
}

String String::operator+(const String &str)const {
    String s1;

    if (len == 0 && str.length() == 0)
        return s1;
    s1.len = len + str.length();
    s1.data = new char[s1.len + 1];
    if (data != NULL)
        strcpy(s1.data, data);
    if (str.data != NULL)
        strcat(s1.data, str.data);
    *(s1.data + s1.len) = '\0';
    return s1;

    //    s1 += *this;//低效
    //    s1 += str;
    //    return s1;
}

String& String::operator=(const String &str) {
    delete []data;

    data = new char[str.length() + 1];
    len = str.length();
    if (str.data != NULL)
        strcpy(data, str.data);
    data[len] = '\0';
}

String::String(const String& str) {
    data = new char[str.length() + 1];
    len = str.length();
    if (str.data != NULL)
        strcpy(data, str.data);
    data[len] = '\0';
}

測試程式

#include <cstdlib>
#include "String.h"
#include <vector>

using namespace std;

/*
 * 
 */
int main(int argc, char** argv) {
    String s("hello,world!");
    cout << s << endl;
    s.insert('t', 0);
    cout << s << endl;
    s.insert('t', 13);
    cout << s << endl;
    s.remove(0);
    cout << s << endl;
    s.remove(12);
    cout << "s:" << s << endl;
    cout << "s.c_str():" << s.c_str() << endl;
    cout << "s.toString():" << s.toString() << endl;
    cout << "s.length():" << s.length() << endl;
    cout << "s[11]:" << s[11] << endl;
    cout << "s[4]:" << s[4] << endl;

    String s1("hello,world!");
    cout << "s:" << s << endl;
    cout << "s1:" << s1 << endl;
    cout << "(s==s1):" << (s == s1) << endl;
    cout << "(s!=s1):" << (s != s1) << endl;
    cout << "(s>s1):" << (s > s1) << endl;
    cout << "(s<s1):" << (s < s1) << endl;

    String s2 = "sttt";
    String s3 = "ffffq";
    //    s3 = "sttt";
    cout << "s2:" << s2 << endl;
    cout << "s3:" << s3 << endl;
    cout << "(s2==s3):" << (s2 == s3) << endl;
    cout << "(s2!=s3):" << (s2 != s3) << endl;
    cout << "(s2>s3):" << (s2 > s3) << endl;
    cout << "(s2<s3):" << (s2 < s3) << endl;

    cout << "('a'<'b'):" << ('a' < 'b') << endl;
    s2 += s3;
    cout << "s2:" << s2 << endl;
    String s4;
    //    s4 += s2;
    //    s4 = s2;
    //    s4 = s3;
    cout << "s4:" << s4 << endl;
    cout << "s4.length():" << s4.length() << endl;
    cout << "s4+s2:" << s4 + s2 << endl;
    cout << "s2+s4:" << s2 + s4 << endl;
    cout << "s4+s2 len:" << (s4 + s2).length() << endl;

    String s5(s4);
    cout << "s4:" << s4 << endl;
    cout << "String (s5(s4)):" << s5 << endl;
    String s0(s4 + s);
    cout << "String s0(s4+s):" << s0 << endl;
    s4 = s4;
    s5 = s;
    cout << "s4 = s4:" << s4 << endl;
    cout << "s5 = s:" << s5 << endl;

    String* sp = new String;
    String* sp1 = new String(*sp);
    *sp = s0;
    cout << "sp:" << *sp << sp->length() << endl;
    cout << "sp1:" << *sp1 << sp1->length() << endl;
    delete sp1;
    sp1 = new String;
    delete sp1;
    delete sp;
    sp = NULL;
    sp1 = NULL;

    String s6;
    String s7 = "";
    cout << "s6:" << s6 << endl;
    cout << "s7:" << s7 << endl;
    cout << "(s6==s7):" << (s6 == s7) << endl;
    cout << "(s6>s7):" << (s6 > s7) << endl;
    cout << "(s6<s7):" << (s6 < s7) << endl;

    string str1;
    string str2 = "";
    str1.push_back('f');
    cout << "(str1 == str2):" << (str1 == str2) << endl;
    cout << "sizeof(string):" << sizeof (string) << endl;
    cout << "sizeof(String):" << sizeof (String) << endl;
    String sa[10];
    cout << "String sa[10];:" << sizeof (sa) << endl;

    String s8("hello,world!");
    cout << s8 << endl;
    s8.remove(5, 5);
    cout << s8 << endl;
    cout << s8.length() << endl;


    char* cp = new char[2];
    cp[0] = '\0';
    delete []cp;
    cp = NULL;
    cp = new char[2]; //要想再用此指標,此句不能少
    cp[0] = 'g';
    cp[1] = 'g';
    delete []cp;
    cp = NULL;
    delete []cp;
    delete cp;

    String* sp2 = new String(s);
    cout << "*sp2:" << *sp2 << endl;
    String::iterator it;
    it = sp2;
    cout << "*it:" << *it << endl;
    cout << "*++it:" << *++it << endl;
    for (; it < sp2->end(); it++)
        cout << *it;
    cout << endl;

    String::iterator it1(sp2);
    //    it1=sp2;
    for (it1 = sp2; it1 < sp2->end(); it1++)
        cout << *it1;
    cout << endl;
    for (it1 = sp2->end(); it1 >= sp2->begin(); it1--)
        cout << *it1;
    cout << endl;
    cout << *it1 << endl;
    cout << *++it1 << endl;
    cout << *++it1 << endl;
    it1++;
    cout << *it1 << endl;
    cout << *(it1++) << endl; //*(it1++)不能解析??需要去掉定義中的地址符&  !!
    cout << *(it1 + 1) << endl;
    cout << *(it1 - 1) << endl;
    cout << *(it1 - 1) << endl;
    cout << *(it1 + 1) << endl;
    for (it1 = sp2->begin(); it1 <= sp2->end()-1; it1++)
        cout << *it1;
    cout << endl;
    
    String::iterator it2(sp2);

    return 0;
}