C++实现String类

字符串匹配的地方都是用都暴力法,有空了再优化

#include<iostream>
using namespace std;

class String {
    friend ostream &operator<<(ostream &m_cout, String &s);
    friend istream &operator>>(istream &m_cin, String &s);

public:
    // 构造函数
    String(const char *str = nullptr) {
        if (str == nullptr) {
            m_data = new char[1];
            m_data[0] = '\0';
            size = 0;

        } else {
            size = strlen(str);
            m_data = new char[size + 1];
            strcpy(m_data, str);
        }
    }

    // 拷贝构造函数
    String(const String &other) {
        size = other.length();
        m_data = new char[size + 1];
        strcpy(m_data, other.getData());
    }

    // 析构函数
    ~String() {
        delete[] m_data;
    }

    char *getData() const {
        return m_data;
    }

    // 获取字符串长度
    int length() const {
        return size;
    }


    // =运算符重载
    String &operator=(const String &other) {
        if (this != &other) {
            delete[] m_data;
            size = other.length();
            m_data = new char[size + 1];
            strcpy(m_data, other.getData());
        }
        return *this;
    }

    // 实现用c类型字符串s的赋值
    String &assign(const char *s) {
        if (m_data != nullptr) {
            delete[] m_data;
            size = strlen(s);
            m_data = new char[size + 1];
            strcpy(m_data, s);
        }
        return *this;
    }

    // 实现c类型字符串s开始的第n个字符的赋值
    String &assign(const char *s, int n) {
        // 指针偏移
        s += (n - 1);
        size = strlen(s);
        strcpy(m_data, s);
        return *this;
    }

    // 重载以上方法,实现将n个字符c赋值给当前字符串。
    String &assign(int n, char c) {
        size = n;
        delete[] m_data;
        m_data = new char[n + 1];
        for (int i = 0; i < n; i++) {
            m_data[i] = c;
        }
        m_data[n] = '\0';

        return *this;
    }

    // 重载运算符,实现把字符串s连接到当前字符串的结尾
    String &operator+=(const String &s) {
        String temp1 = *this;
        delete[] m_data;
        size = s.length() + temp1.length();

        m_data = new char[size + 1];

        for (int i = 0; i < size; i++) {

            if (i < temp1.length()) {
                m_data[i] = temp1.m_data[i];
            } else {
                m_data[i] = s.m_data[i - temp1.length()];
            }
        }
        return temp1;
    }

    bool operator==(const String &s) {
        if (this->length() != s.length()) return false;

        // 扫描两个字符串只要有一个字符不同则返回false
        for (int i = 0; i < s.length(); i++) {
            if (this->m_data[i] != s.m_data[i]) return false;
        }
        return true;
    }


    // 编写一个方法,实现把c类型字符串s连接到当前字符串结尾
    String &append(const char *s) {
        String temp1 = *this;
        delete[] m_data;
        size = strlen(s) + temp1.length();

        m_data = new char[size + 1];

        for (int i = 0; i < size; i++) {

            if (i < temp1.length()) {
                m_data[i] = temp1.m_data[i];
            } else {
                m_data[i] = s[i - temp1.length()];
            }
        }
        return *this;
    }

    // 比较两个指定的字符串对象,并返回一个指示二者在排序顺序中的相对位置的整数
    static int compare(String strA, String strB) {
        for (int i = 0; i < min(strA.length(), strB.length()); i++) {
            if (strA.m_data[i] < strB.m_data[i]) return -1;
            else if (strA.m_data[i] > strB.m_data[i]) return 1;
        }

        if (strA.length() > strB.length()) return 1;
        else if (strA.length() < strB.length()) return -1;
        else return 0;
    }

    // 忽略字符串大小写进行比较
    static int compare(String strA, String strB, bool ignoreCase) {
        if (!ignoreCase) return compare(strA, strB);

        for (int i = 0; i < min(strA.length(), strB.length()); i++) {
            if (tolower(strA.m_data[i]) < tolower(strB.m_data[i])) return -1;
            else if (tolower(strA.m_data[i]) > tolower(strB.m_data[i])) return 1;
        }

        if (strA.length() > strB.length()) return 1;
        else if (strA.length() < strB.length()) return -1;
        else return 0;
    }


    int indexOf(String value) {
        for (int start = 0; start < size; start++) {
            int mark = 0;
            int index = 0;
            int end;
            if ((end = start + value.length() - 1) > size - 1) break;

            for (int i = start; i <= end; i++) {
                if (m_data[i] != value.m_data[index++]) {
                    mark = 1;
                    break;
                }
            }

            if (mark == 0) return start;
        }
        return -1;
    }

    // 返回从指定位置开始的匹配索引结果
    int indexOf(String value, int startIndex) {
        for (int start = startIndex; start < size; start++) {
            int mark = 0;
            int index = 0;
            int end;
            if ((end = start + value.length() - 1) > size - 1) break;

            for (int i = start; i <= end; i++) {
                if (m_data[i] != value.m_data[index++]) {
                    mark = 1;
                    break;
                }
            }

            if (mark == 0) return start;
        }
        return -1;
    }


    // 返回从指定位置开始的匹配索引结果,并只检查指定数量的字符位
    int indexOf(String value, int startIndex, int count) {
        int endIndex = count + startIndex - 1;

        for (int start = startIndex; start <= endIndex; start++) {
            int mark = 0;
            int index = 0;
            int end;
            if ((end = start + value.length() - 1) > size - 1) break;

            for (int i = start; i <= end; i++) {
                if (m_data[i] != value.m_data[index++]) {
                    mark = 1;
                    break;
                }
            }

            if (mark == 0) return start;
        }
        return -1;
    }


    // 返回一个新的字符串,其中当前实例中的所有指定字符串都被替换为另外一个指定的字符串
    String replace(String oldValue, String newValue) {

        // 先备份当前字符串
        String backup = *this;

        // 映射当前字符串中匹配oldValue字符的下标,1表示匹配,0表示不匹配
        int *flag = new int[this->size];

        // 记录备份串中有几个子串与oldValue匹配
        int cnt = 0;

        // 遍历一遍当前字符串,查看其哪些字符匹配oldValue,并记录相应下标到flag中
        for (int start = 0; start < this->size; start++) {
            int end;
            if ((end = start + oldValue.length() - 1) > this->length() - 1) break;

            bool a = this->substring(start, end) == oldValue;
            if (this->substring(start, end) == oldValue) {
                // 标记flag
                for (int i = start; i <= end; i++) {
                    flag[i] = 1;
                }
                cnt++;
            }
        }

        // 给备份串修改容量
        int newSize = 0;
        // 计数flag中有几个被标记1
        int cnt2 = 0;
        for (int i = 0; i < this->length(); i++) {
            if (flag[i] == 1) cnt2++;
        }

        // 新容量= 备份串的原容量 - cnt2 + cnt * newValue.size
        newSize = this->size - cnt2 + cnt * newValue.size;

        // 释放备份串的原堆内存
        delete[] backup.m_data;
        for (int i = 0; i < size; i++) {
            backup.m_data[i] = 0;
        }

        backup.m_data = new char[newSize + 1];

        // 扫描一遍原串
        int index = 0;

        for (int i = 0; i < size; i++) {
            // 先把不修改的那些字符放入新的backup中
            if (flag[i] != 1) {
                backup.m_data[index++] = m_data[i];
            } else {
                // 遇到需要修改的字符
                // i 跳过oldValue这个长度
                i += (oldValue.size - 1);
                // 用newValue给backup赋值
                for (int k = 0; k < newValue.size; k++) {
                    backup.m_data[index++] = newValue.m_data[k];
                }
            }
        }

        delete[] flag;
        return backup;
    }


    // 将当前字符串的开头和结尾的所有空白字符都去除,并返回去除后剩余的字符串
    static String trim(String value) {
        String backup = value;
        int cnt = 0;

        // 记录字符串除去两头空白字符后的边界下标
        int start = 0, end = 0;
        // 计数字符串开头的空白数
        for (int i = 0; i < value.size; i++) {
            if (value.m_data[i] == ' ') cnt++;
            else {
                start = i;
                break;
            }
        }
        // 计数字符串尾部的空白数
        for (int i = value.size - 1; i >= 0; i--) {
            if (value.m_data[i] == ' ') cnt++;
            else {
                end = i;
                break;
            }
        }

        delete[] backup.m_data;
        for (int i = 0; i < backup.size; i++) {
            backup.m_data[i] = 0;
        }

        backup.size = value.size - cnt;
        backup.m_data = new char[value.size + 1];
        int index = 0;

        // 在字符串除去两头空白字符后的边界下标范围内遍历原字符串
        for (int i = start; i <= end; i++) {
            backup.m_data[index++] = value.m_data[i];
        }

        return backup;
    }


    // 重载以上方法,加入第二个参数(string trimString),返回去除指定的字符后的结果
    static String trim(String value, String trimString) {

        // 先备份value
        String backup = value;

        // 映射value中要删除的字符的下标,1表示要删除,0表示不删除
        int *flag = new int[value.size];
        // 计数要删除的字符个数
        int cnt = 0;

        // 遍历一遍value字符串,查看其哪些字符匹配trimString,并记录相应下标到flag中
        for (int start = 0; start < value.size; start++) {
            int end;
            if ((end = start + trimString.length() - 1) > value.length() - 1) break;

            if (value.substring(start, end) == trimString) {
                // 标记flag
                for (int i = start; i <= end; i++) {
                    flag[i] = 1;
                    cnt++;
                }
            }
        }

        // 释放backup原来的堆内存
        delete[] backup.m_data;
        for (int i = 0; i < backup.length(); i++) {
            backup.m_data[i] = 0;
        }

        // backup新的长度
        backup.m_data = new char[value.length() - cnt + 1];
        backup.size = value.length() - cnt;

        int index = 0;
        // 遍历一遍原字符串
        for (int i = 0; i < value.size; i++) {
            // 只要没被标记要删除的字符则放入backup中
            if (flag[i] != 1) {
                backup.m_data[index++] = value.m_data[i];
            }
        }

        delete[] flag;

        return backup;
    }

    String substring(int start, int end) {
        int len = end - start + 1;
        char *c = new char[len + 1];
        String temp(c);

        int index = 0;
        for (int i = start; i <= end; i++) {
            temp.m_data[index++] = m_data[i];
        }
        return temp;
    }

    // 从当前字符串中去除指定的前导匹配字符串,并返回去除后的结果
    static String trimStart(String value, String trimString) {
        // 先备份value
        String backup = value;

        // 映射value中要删除的字符的下标,1表示要删除,0表示不删除
        int *flag = new int[value.size];
        // 计数要删除的字符个数
        int cnt = 0;

        // 遍历一遍value字符串,查看其哪些字符匹配trimString,并记录相应下标到flag中
        for (int start = 0; start < value.size; start++) {
            int end;
            if ((end = start + trimString.length() - 1) > value.length() - 1) break;

            if (value.substring(start, end) == trimString) {
                // 标记flag
                for (int i = start; i <= end; i++) {
                    flag[i] = 1;
                    cnt++;
                }
                break;
            }
        }

        // 释放backup原来的堆内存
        delete[] backup.m_data;
        for (int i = 0; i < backup.length(); i++) {
            backup.m_data[i] = 0;
        }

        // backup新的长度
        backup.m_data = new char[value.length() - cnt + 1];

        int index = 0;
        // 遍历一遍原字符串
        for (int i = 0; i < value.size; i++) {
            // 只要没被标记要删除的字符则放入backup中
            if (flag[i] != 1) {
                backup.m_data[index++] = value.m_data[i];
            }
        }

        delete[] flag;

        return backup;
    }

    // 从当前字符串中去除指定的尾部匹配字符串,并返回去除后的结果
    static String trimEnd(String value, String trimString) {

        // 先备份value
        String backup = value;

        // 映射value中要删除的字符的下标,1表示要删除,0表示不删除
        int *flag = new int[value.size];
        // 计数要删除的字符个数
        int cnt = 0;

        // 从后遍历一遍value字符串,查看其哪些字符匹配trimString,并记录相应下标到flag中
        for (int end = value.size - 1; end >= 0; end--) {
            int start;
            if ((start = end - trimString.size + 1) < 0) break;

            if (value.substring(start, end) == trimString) {
                // 标记flag
                for (int i = start; i <= end; i++) {
                    flag[i] = 1;
                    cnt++;
                }
                break;
            }
        }

        // 释放backup原来的堆内存
        delete[] backup.m_data;
        for (int i = 0; i < backup.length(); i++) {
            backup.m_data[i] = 0;
        }

        // backup新的长度
        backup.m_data = new char[value.length() - cnt + 1];

        int index = 0;
        // 遍历一遍原字符串
        for (int i = 0; i < value.size; i++) {
            // 只要没被标记要删除的字符则放入backup中
            if (flag[i] != 1) {
                backup.m_data[index++] = value.m_data[i];
            }
        }

        delete[] flag;

        return backup;
    }

    // 返回当前字符串的长度
    static int getLength(String value) {
        return value.length();
    }

    // 重载以上方法,加入第二个参数(string insertString),返回插入新的字符串后,当前字符串的长度
    static int getLength(String &value, String insertString) {
        value += insertString;
        return value.length();
    }

    // 重载以上方法,加入第三个参数(string trimString),返回插入新的字符串之后,去除掉指定字符串后的当前字符串长度
    static int getLength(String &value, String insertString, String trimString) {
        value += insertString;
        value = trim(value, trimString);
        return value.length();
    }


private:
    char *m_data;
    int size;
};

ostream &operator<<(ostream &m_cout, String &s) {
    m_cout << s.m_data << endl;
    return m_cout;
}

istream &operator>>(istream &m_cin, String &s) {
    m_cin >> s.m_data;
    s.size = strlen(s.m_data);
    return m_cin;
}


int main() {
    // 对比"Hello World"和"HELLO WORLD"并返回结果
    String s1("Hello World");
    String s2("HELLO WORLD");
    cout << String::compare(s1, s2) << endl;

    // 对比"Hello World"和"HELLO WORLD",忽略大小写后返回结果
    cout << String::compare(s1, s2, true) << endl;

    // 获取"China stocks extend rally on positive policy outlook"的长度
    String s3("China stocks extend rally on positive policy outlook");
    cout << String::getLength(s3) << endl;

    //在上述字符串后面加上
    // "Chinese shares remained in positive territory
    // for the second-consecutive day on Wednesday following
    // the government's fresh fiscal stimulus measures"并获取新字符串的长度
    char *c = "Chinese shares remained in positive territory for the second-consecutive day on Wednesday following the government's fresh fiscal stimulus measures";
    String backup = s3;
    backup.append(c);
    cout << backup << endl;
    cout << String::getLength(backup) << endl;

    // 将上述新字符串中的"o"去掉并获取长度
    String s4 = String::trim(backup, "o");
    cout << s4 << endl;
    cout << String::getLength(s4) << endl;

    // 查询"China"和"Chinese"在上述字符串中的索引结果
    cout << backup.indexOf("China") << endl;
    cout << backup.indexOf("Chinese") << endl;

    // 查询"China"和"Chinese"在上述字符串中索引40开始的结果
    cout << backup.indexOf("China", 40) << endl;
    cout << backup.indexOf("Chinese", 40) << endl;


    // 查询"day"在上述字符串中索引35开始到索引60的结果
    int count = 60 - 35 + 1;
    cout << backup.indexOf("day", 35, count) << endl;


    // 将该字符串中的"positive"全部替换为"negative"并获取字符串长度
    String k("China stocks extend rally on positive policy outlook");
    String s5 = k.replace("positive", "negative");
    cout << s5 << endl;


    // 将字符串
    // "  CCCentral bank defends measures taken to regulate forex markettt  "
    // 中的空格全部去除并获取字符串长度
    String s6 = String::trim("  CCCentral bank defends measures taken to regulate forex markettt  ");
    cout << s6 << endl;
    cout << s6.length() << endl;


    // 将字符串中多余的C和t去掉,变为"Central bank defends measures taken to regulate forex market"
    String s7 = s6.replace("CCC", "C");
    s7 = s7.replace("ttt", "t");
    cout << s7 << endl;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值