C++自己实现String类及其迭代器

3 篇文章 0 订阅

注意事项:

对于C语言字符串char*,必须在末尾置'\0';

对指针操作时,必须考虑指针为NULL的情况,对strcpy,strcat等库函数调用也一样;

对指针重新赋值前必须调用delete,同一块内存不能调用两次delete;

返回对象的成员函数要区分返回的是当前对象还是新对象,即函数返回类型是否要取地址(&)

 

关于迭代器更新一点:

String* sp = new String("hello,world!");

String::iterator it = sp;

迭代器begin()指向String类首字符'h',end()指向末尾字符'!'之后一位的空字符'\0'.

顺序迭代:

for (it = sp->begin(); it < sp->end(); it++)
        cout << *it;

逆序迭代不能使用for循环(for循环不能输出begin()位置的元素),而且必须用前缀运算--it:

it = sp->end();
while(it > sp->begin())
      cout << *--it;

再更新一下比较操作符“==”,见String.cpp具体实现

 

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 < 0)//越界
                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;

    //或者改成这几行
    //int i = 0; 
    //while (*(data + i) == *(str.data + i)) {
    //    i++;
    //    if (i == len)
    //       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';
    return *this;
}

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)//逆序迭代不能用for循环,应该用while
        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;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值