• c++在string类源


    一:回想

    (1)c++中的string类是在面试中和笔试中常常考的题目; project代码免费下载 string类的自行实现

    (2)c++中的string类和fstream类合起来是处理外部数据的利器

    (3)string类经经常使用到find find_first_of find_first_not_of find_last_of find_last_not_of substr replace等,以及联合使用来达到java中的split和trim

      (4) 使用friend 不过在类中进行声明的非内部 却能够訪问内部成员的外部函数,并且在外部不再须要friendkeyword;它与成员函数的差别是,friend和外部函数不含有this对象指针;本文用到了const 定义的全局最大值最小值变量(取代#define)

     (5) 有些函数返回的是MyString& 、Char& 等(引用),MyString、Char 等(传值)这得看你返回的对象是函数的局部变量还是全局变量(或者类当前对象成员变量);前者仅仅能返回一个MyString、Char 等;后者强烈建议返回MyString& 、Char& 等(引用);

    (6)有些函数的參数是const MyString& ,有些是MyString& (引用);这是为什么?前者是把外部值传提到子函数内部,且不同意改变;后者是作为函数的返回值传递进去的,返回的结果为函数的处理结果(而不用函数自身返回值了)。

    二:以下是简单的实现了一下string类,參照的是STL源代码,可是自己理解的还是不够深,难免有一些错误,请各位不吝赐教

    (1)MyString.h文件

    #ifndef MYSTRING_H
    #define MYSTRING_H
    #include "MyExcept.h"
    #include <cstring>
    #include <iostream>
    const int INI_MAX = 0x7fffffff;//2^32npos
    const int INI_MIN = 0x80000000;// -2^32
    const int npos = 0xffffffff;// npos
    using namespace std;
    
    class MyString
    {
        public:
        // constructor
        MyString();//
        MyString(const MyString &);//
        MyString(const char *);
        MyString(const size_t,const char);
        // destructor
        ~MyString();
        // attributes
    
        size_t length();// 字符串长度
        bool isEmpty();// 返回字符串是否为空
        const char* c_str();// 返回c风格的trr的指针
        // friend funs
        // read writer operations
        friend ostream& operator<< (ostream&, const MyString&);
        friend istream& operator>> (istream&, MyString&);
        //add operation
        friend MyString operator+(const MyString&,const MyString&);
        // compare operations
        friend bool operator==(const MyString&,const MyString&);
        friend bool operator!=(const MyString&,const MyString&);
        friend bool operator<(const MyString&,const MyString&);
        friend bool operator<=(const MyString&,const MyString&);
        friend bool operator>(const MyString&,const MyString&);
        friend bool operator>=(const MyString&,const MyString&);
        // 成员函数实现运算符重载,事实上一般须要返回自身对象的,成员函数运算符重载会好一些
        // index operation
        char& operator[](const size_t);
        const char& operator[](const size_t)const;
        // =
        MyString& operator=(const MyString&);
        // +=
        MyString& operator+=(const MyString&);
        // +=
        //MyString operator+=(const MyString&); cannot be overloaded
        // 成员操作函数
        // substr
        MyString substr(size_t pos,const size_t n);
        // append
        MyString& append(const MyString&);
        //insert
        MyString& insert(size_t,const MyString&);
        //assign 替换
        MyString& assign(MyString&,size_t,size_t);
        // erase 删除
        MyString& erase(size_t,size_t);
        //find_first_of 查找某一个字符 size_t 是非符号数的,重载
        // 查找在字符串中第一个与str中的某个字符匹配的字符,返回它的位置。
        //搜索从index開始,假设没找到就返回string::npos
        int find_first_of(const char* str,size_t index=0);
        int find_first_of(const char ch,size_t index=0);
        int find_first_of(const MyString &,size_t index=0);
        // 在字符串中查找第一个与str中的字符都不匹配的字符,返回它的位置。搜索从index開始。假设没找到就返回string::nops
        int find_first_not_of(const char* str,size_t index=0);
        int find_first_not_of(const char ch,size_t index=0);
        int find_first_not_of(const MyString&,size_t index=0);
        // swap
        void swap(MyString& lhs,MyString& rhs);
        // replace_all
        MyString& replace_all(const char oldc,const char newc=NULL);
        MyString& replace(size_t index,size_t num1,size_t num2,const char ch);
        //find
        int find(const char* str,size_t index=0);
        int find(const MyString& str,size_t index=0);
        int find(const char ch,size_t index=0);
    
    
        //private
        private:
        char *p_str;
        size_t strLength;
    };
    
    
    #endif // MYSTRING_H

    (2)MyString.cpp文件

    #include "MyString.h"
    #include <cassert>
    
    // constructor
        MyString::MyString():p_str(NULL),strLength(0){}
    
        MyString::MyString(const MyString &str)//
        {
            if(NULL == str.p_str)
            {
                return;
            }
            strLength = str.strLength;
            p_str = new char[strLength+1];
            strcpy(p_str,str.p_str);
        }
        MyString::MyString(const char *str)
        {
            if(NULL == str)
            {
                return;
            }
            strLength = strlen(str);
            p_str = new char[strLength+1];
            strcpy(p_str,str);
        }
        MyString::MyString(const size_t len,const char ch)
        {
            if(NULL == ch)
            {
                return;
            }
            strLength = len;
            p_str = new char[strLength+1];
            for(size_t i=0;i<strLength;i++)
            {
                p_str[i] = ch;
            }
            p_str[strLength] = '';// 由于strset以''结束的
            cout << p_str << " &&" << endl;
            //strset(p_str,ch);
            //cout << p_str[0] << ",,,"<<strlen(p_str) << "," << strLength << endl;
        }
        // destructor
        MyString::~MyString()
        {
            delete[] p_str;
        }
    
        // attributes
        size_t MyString::length()// 字符串长度
        {
            return strLength;
        }
        bool MyString::isEmpty()// 返回字符串是否为空
        {
            return strLength==0?true:false;
        }
        const char* MyString::c_str()
        {
            return p_str;
        }
        // 为什么不是引用呢??? friend 使用在类里面进行声明的,外面就不须要了,并且友元函数不属于类的成员函数,所以不用MyString::
        // ostream
        ostream& operator<< (ostream& out,const MyString &str)
        {
            if(str.p_str != NULL)
            {
                out << str.p_str;
            }
            return out;
        }
        // istream,一个是const还有一个不是,依据变还是不变
        istream& operator>> (istream& in, MyString& str)
        {
            char tmp[100];// 暂时字符串
            if(in>>tmp)
            {
                delete[] str.p_str;
                str.strLength = strlen(tmp);
                str.p_str = new char[str.strLength+1];
                strcpy(str.p_str,tmp);
            }
            return in;
        }
        // + 加
        MyString operator+(const MyString& lhs,const MyString& rhs)
        {
            MyString ret;
            ret.strLength = lhs.strLength + rhs.strLength;
            ret.p_str = new char[ret.strLength+1];
            strcpy(ret.p_str,lhs.p_str);
            strcat(ret.p_str,rhs.p_str);
            return ret;
        }
        // compare operations
        bool operator==(const MyString& lhs,const MyString& rhs)
        {
            return strcmp(lhs.p_str,rhs.p_str)==0?true:false;
        }
        bool operator!=(const MyString& lhs,const MyString& rhs)
        {
            return strcmp(lhs.p_str,rhs.p_str)!=0?true:false;
        }
        bool operator<(const MyString& lhs,const MyString& rhs)
        {
            return strcmp(lhs.p_str,rhs.p_str)<0?true:false;
        }
        bool operator<=(const MyString& lhs,const MyString& rhs)
        {
            return strcmp(lhs.p_str,rhs.p_str)<=0?true:false;
        }
        bool operator>(const MyString& lhs,const MyString& rhs)
        {
            return strcmp(lhs.p_str,rhs.p_str)>0?true:false;
        }
        bool operator>=(const MyString& lhs,const MyString& rhs)
        {
            return strcmp(lhs.p_str,rhs.p_str)>=0?true:false;
        }
        // 成员函数实现运算符重载
        // index operation
        char& MyString::operator[](const size_t index)
        {
            if(index<0 || index>=strLength)
            {
                throw Outofbond() ;
            }
            return p_str[index];
        }
        const char& MyString::operator[](const size_t index)const
        {
            if(index<0 || index>=strLength)
            {
                throw Outofbond();
            }
            return p_str[index];
        }
         // = 赋值构造函数(推断是否是自身) 为什么要这样删除呢?
        MyString& MyString::operator=(const MyString& other)
        {
            if(this != &other)
            {
                if(strLength<other.strLength)
                {
                    delete[] p_str;
                    p_str = new char[other.strLength+1];
                }
                strLength = other.strLength;
                strcpy(p_str,other.p_str);
            }// 这样可能会产生多余的未释放的空间
            return *this;
        }
        // += 相当于返回的是备份的,内部对象的销毁,不影响的 和 以下的全然不一样的
    //    MyString MyString::operator+=(const MyString& other)
    //    {
    //        if(NULL == other.p_str)
    //        {
    //            return *this;
    //        }
    //        MyString ret;
    //        ret.strLength = strLength + other.strLength;
    //        ret.p_str = new char[ret.strLength+1];
    //        strcpy(ret.p_str,p_str);
    //        strcat(ret.p_str,other.p_str);
    //        return ret;
    //    }
        // 返回的是当前对象的引用,当前对象就在调用函数里,所以不会销毁的
        // 推断一下是否是自身相加
        MyString& MyString::operator+=(const MyString& other)
        {
            if(NULL == other.p_str)
            {
                return *this;
            }
            if(this == &other)
            {
                MyString copy(*this);
                return *this += copy;
            }// 必须推断是否相等的,并且要+=的,这样相当于调用了自身,可是这次直接以下去了,不进入if的
            strLength += other.strLength;
            //strLength *= 2;
            char *p_old = p_str;
            p_str = new char[strLength+1];
            strcpy(p_str,p_old);
            strcat(p_str,other.p_str);
            delete[] p_old;// 删除旧的空间
            return *this;
        }
        // 成员操作函数
        // substr  返回应用是不行的,错误的;取从pos開始的n个字符组成的子串
        //MyString& MyString::substr(size_t pos,const size_t n)
        MyString MyString::substr(size_t pos,const size_t n)
        {
            if((pos+n)>=strLength)
            {
                throw Outofbond();
            }
            MyString ret;
            ret.strLength = n;
            //ret.p_str = new char[n+1];
            ret.p_str = new char[ret.strLength+1]; //也能够
            for(size_t i=0;i<n;i++)
            {
                ret.p_str[i] = p_str[pos+i];
            }
            ret.p_str[n] = '';
    //        for(size_t i=0;i<ret.strLength;i++)
    //        {
    //            ret[i] = (*this)[pos+i];
    //            cout << ret[i] << ",,";
    //        }// 也行的,利用刚刚重载的【】,这样更好,不用再次推断越界了,不知道为什么,报错误的
    //        ret[ret.strLength] = '';
            return ret;
        }
        // append 同 += 追加到末尾
        MyString& MyString::append(const MyString& other)
        {
            *this += other;// 利用刚刚那重载的+=
            return *this;
        }
        //insert 从pos開始的插入other
        MyString& MyString::insert(size_t pos,const MyString& other)
        {
            if(pos<0 || pos>=strLength)
            {
                throw Outofbond();
            }
            char *p_old = p_str;
            strLength += other.strLength;
            p_str = new char[strLength+1];
            for(size_t i=0;i<pos;i++)
            {
                *(p_str+i) = *(p_old+i);
            }
            for(size_t i=pos;i<other.strLength+pos;i++)
            {
                *(p_str+i) = other.p_str[i-pos];
            }
            for(size_t i=other.strLength+pos;i<strLength;i++)
            {
                *(p_str+i) = p_old[i-other.strLength];
            }
            *(p_str+strLength) = '';
            return *this;
        }
        //assign 替换  用other的POS開始的n相应替换this的pos開始的
        MyString& MyString::assign(MyString&other,size_t pos,size_t n)
        {
    //        if(pos<0 || pos>=strLength)
    //        {
    //            throw Outofbond();
    //        }
            assert(pos>0 && pos<strLength);// assert 的优点
            assert(pos+n<other.strLength);
            if(strLength < pos + n)
            {
                char *p_old = p_str;
                strLength = pos + n;
                p_str = new char[strLength+1];
                for(size_t i=0;i<pos;i++)
                {
                    *(p_str+i) = *(p_old+i);
                }
                delete[] p_old;
            }
            for(size_t i=pos;i<pos+n;i++)
            {
                *(p_str+i) = other.p_str[i];
            }
            *(p_str+pos+n) = '';
            return *this;
        }
        // erase 删除 这种方法并非非常好的,并没有释放所erase的空间,请看以下的
    //    MyString& MyString::erase(size_t pos,size_t n)
    //    {
    //        if((pos+n)>strLength)
    //        {
    //            throw Outofbond();
    //        }
    //        size_t index = pos + n;
    //        while(*(p_str+index)!='')
    //        {
    //            *(p_str+index-n) = *(p_str+index);
    //            ++index;
    //        }
    //        *(p_str+index-n) = '';
    //        return *this;
    //    }
        // erase 删除 从pos開始的n个字符
        MyString& MyString::erase(size_t pos,size_t n)
        {
            if((pos+n)>strLength)
            {
                throw Outofbond();
            }
            char *p_old = p_str;
            strLength -= n;
            p_str = new char[strLength+1];
            for(size_t i=0;i<pos;i++)
            {
                p_str[i] = p_old[i];
            }
            for(size_t i=pos;i<strLength;i++)
            {
                p_str[i] = p_old[i+n];
            }
            *(p_str+strLength) = '';
            return *this;
        }
        //find_first_of 查找某一个字符 size_t 是非符号数的
        // 查找在字符串中第一个与str中的某个字符匹配的字符,返回它的位置。
        //搜索从index開始,假设没找到就返回string::npos
        int MyString::find_first_of(const char* str,size_t index)
        {
            if(NULL == str || index >=strLength)
                return npos;
            int tmp_len = strlen(str),j;
            size_t flag,min_index = INI_MAX;
            for(j=0;j<tmp_len;j++)
            {
                flag = npos;
                for(size_t i=index;i<strLength;i++)
                {
                    if(str[j] == p_str[i])
                    {
                        flag = i;
                        break;
                    }
                }
    //            indexs[j] = flag;
                if(flag != npos)
                {
                    min_index = min_index<flag?min_index:flag;
                }
            }
    //        for(j=0;j<tmp_len;j++)
    //        {
    //            if(indexs[j]!=npos)
    //                min = min<indexs[j]?min:indexs[j];
    //        }
            if(min_index == INI_MAX)
            {
                return npos;
    //            min_index = npos;
    //           cout << "---npos----" << min_index << ",,,,";
            }
            return min_index;
        }
        int MyString::find_first_of(const char ch,size_t index)
        {
            if(NULL == ch || index >=strLength)
                return npos;
            int j;
            size_t flag = npos;
            for(size_t i=index;i<strLength;i++)
            {
                if(ch == p_str[i])
                {
                    flag = i;
                    break;
                }
            }
            return flag;
        }
        int MyString::find_first_of(const MyString& str,size_t index)
        {
            if(NULL == str || index >=strLength)
                return npos;
            int j;
            size_t flag,min_index = INI_MAX;
            for(j=0;j<str.strLength;j++)
            {
                flag = npos;
                for(size_t i=index;i<strLength;i++)
                {
                    if(str[j] == p_str[i])
                    {
                        flag = i;
                        break;
                    }
                }
                if(flag != npos)
                {
                    min_index = min_index<flag?min_index:flag;
                }
            }
            if(min_index == INI_MAX)
            {
                return npos;
            }
            return min_index;
        }
        // 在字符串中查找第一个与str中的字符都不匹配的字符,返回它的位置。
        //搜索从index開始。假设没找到就返回string::nops O(N^2)
        int MyString::find_first_not_of(const char *str,size_t index)
        {
            if(NULL == str || index >=strLength)
                return npos;
            size_t i=0,j=0;
            size_t tmp_len = strlen(str);
            for(i=index;i<strLength;i++)
            {
                for(;j<tmp_len;j++)
                {
                    if(p_str[i]==str[j])
                        break;
                }
                if(j==tmp_len)
                    break;// 依据跳出的内层for的条件推断,找到即结束循环
            }
            if(i==strLength)
                return npos;// 未找到,// 依据跳出的内层for的条件推断,找到即结束循环
            return i;
        }
        int MyString::find_first_not_of(const MyString& str,size_t index)
        {
            if(NULL == str || index >=strLength)
                return npos;
            size_t i=0,j=0;
            for(i=index;i<strLength;i++)
            {
                for(;j<str.strLength;j++)
                {
                    if(p_str[i]==str[j])
                        break;// 假设相等 本轮i就无效了,进行下一轮
                }
                if(j==str.strLength)
                    break;// 依据跳出的内层for的条件推断,找到即结束循环
            }
            if(i==strLength)
                return npos;// 未找到,// 依据跳出的内层for的条件推断,找到即结束循环
            return i;
        }
        int MyString::find_first_not_of(const char ch,size_t index)
        {
            if(NULL == ch || index >=strLength)
                return npos;
            size_t i=0;
            for(i=index;i<strLength;i++)
            {
                if(p_str[i]!=ch)// 跟上面的稍微不同,找一个不等就能够了
                    break;
            }
            if(i==strLength)
                return npos;// 未找到,// 依据跳出的内层for的条件推断,找到即结束循环
            return i;
        }
        // swap  都得变得,所以非const
        void MyString::swap(MyString& lhs,MyString& rhs)
        {
            lhs.strLength ^= rhs.strLength;
            rhs.strLength ^= lhs.strLength;
            lhs.strLength ^= rhs.strLength;
            char *p_tmp = rhs.p_str;
            rhs.p_str = lhs.p_str;
            lhs.p_str = p_tmp;
        }
        // replace_all  这个东西还是不太好弄的啊,不是非常理想
        MyString& MyString::replace_all(const char oldc,const char newc)
        {
            if(NULL == oldc)
            {
                return *(this);
            }
            for(size_t i=0;i<strLength;i++)
            {
                if(p_str[i] == oldc)
                {
                    p_str[i] = newc;
                }
            }
            return *(this);
        }
        MyString& MyString::replace(size_t index,size_t num1,size_t num2,const char ch)
        {
    
        }
        // find 函数
        int MyString::find(const char* str,size_t index)
        {
            assert(str!=NULL&&index<strLength);
            // kmp 中的getnext函数
            size_t len = strlen(str);
            size_t next[len+1];
            size_t j,k;
            next[0] = npos;
            j = 0;
            k = npos;
            while(j<len)
            {
                if(k==npos || str[j]==str[k])
                {
                    j++;
                    k++;
                    next[j] = k;
                }
                else
                    k = next[k];
            }
            // kmp 算法
            k = index;
            j = 0;
            while(p_str[k]!='')
            {
                if(j==0 || p_str[k]==str[j])
                {
                    k++;
                    j++;
                }
                else
                {
                    j = next[j];// 消除指针回溯
                }
                if(str[j] == '')//匹配成功
                    return k-j;
            }
            return npos;
        }
        int MyString::find(const MyString& str,size_t index)
        {
    //        if(this == &str)
    //        {
    //            MyString other(*this);
    //            find(other,index);
    //        }
            assert(NULL!=str && index<strLength);
            // kmp 中的getnext函数
    
            size_t next[str.strLength+2];
            size_t j,k;
            next[0] = npos;
            j = 0;
            k = npos;
            while(j<str.strLength)
            {
                if(k==npos || str.p_str[j]==str.p_str[k])
                {
                    j++;
                    k++;
                    next[j] = k;
                }
                else
                    k = next[k];
            }
            int i;
            for(i=1;i<=j;i++)
                cout << next[i] << ",";
            // kmp 算法
            k = index;
            j = 0;
            while(p_str[k]!='')
            {
                if(j==0 || p_str[k]==str.p_str[j])
                {
                    k++;
                    j++;
                }
                else
                {
                    j = next[j];// 消除指针回溯
                }
                if(str.p_str[j] == '')//匹配成功,不知道为什么调用自身的str[]重载总是报错的
                    return k-j;
            }
            if(str.p_str[j] == '')// 同一个字符串
                return k-j;
            return npos;
        }
        int MyString::find(const char ch,size_t index)
        {
            assert(NULL!=ch && index<strLength);
            for(size_t i=index;i<strLength;i++)
            {
                if(p_str[i] == ch)
                    return i;
            }
            return npos;
        }
    


    (3)測试函数main.cpp

    #include "MyString.h"
    #include <iostream>
    using namespace std;
    
    int main()
    {
        int n;
        int choose = 1;
        int p,l;
        char cs[100];
        MyString s1;
        MyString s2("hello");
        MyString s3 = "HELLO";
        cout << "***** welcome *****
    ";
        cout << "******* MADE BY zyp **********
    ";
        cout << "s1= " << s1 << "s2= " << s2 << "s3= " << s3 << endl;
        cout << "请输入一个长度小于100的字符串:比如world
    ";
        cin >> s1;
        s1 = s1;
        //s1 = s1+s1;
        s1 += s1;
        MyString s4(s1);
        s4.append(s1);
        s2.insert(2,s3);
        s1.erase(4,4);
        s1.assign(s2,1,7);
        cout << "s1= " << s1 << "s2= " << s2 << "s3= " << s3 << "s4= " << s4 << endl;
        s2 = s4.substr(2,7);
        cout << "s4[3]= " << s4[3] << s4.length() << (s1>=s2) << "s4.substr() " << s2 << endl;
        cout << "s1.find_first_of(beLE,2):" << s1.find_first_of("beLE",2) << ",s1.find_first_of(a,3):" << s1.find_first_of('a',3) << ",s1.find_first_of(s3,2):" << s1.find_first_of(s3,2) << endl;
        MyString s5(5,'b');
        s5 += s5;
        //s5.append(s5);// 不知道为什就是不能append
        cout << "s5 = " << s5 << "s5.find_first_not_of(aeHLEOl,2):" << s5.find_first_not_of("aeHLEOl",2) << "s5.find_first_not_of(aeHLEOl,0):" << s5.find_first_not_of("aeHLEOl") << endl;
        cout << "s5.find_first_not_of(s1,2):" << s5.find_first_not_of(s1,2) << "s5.find_first_not_of(b,2):" << s5.find_first_not_of('b',2) << endl;
        swap(s1,s5);
        s5.replace_all('a','J');
        MyString s6("LLO");
        cout << s1 << "," << s5 << "s5.find(LLO,0) " << s5.find("LLO",0) << "s5.find(s6,0) " << s5.find(s5) << endl;
        cout << npos << endl;
        return 0;
    }
    


    三:感悟

    (1)耗时将近2天的实现了它,自己与其从中学到了非常多,倒不如说是又一次认识了string类;

    (2)自己知道这个简单的string类,距离string源码还差的非常远非常远;可是它帮助我更好的理解了string类,至少会简单的应用了。

    (3)简单的实现了一下string类,參照的是STL源代码,可是自己理解的还是不够深,难免有一些错误,请各位不吝赐教,万分感谢!

    (4)下一步进军list

  • 相关阅读:
    Overview | POCO C++ Libraries
    simple.c
    Classes for Writing HTTP Clients in C++ CodeProject
    APScheduler 2.0.3 : Python Package Index
    neon HTTP and WebDAV client library
    HTTP Client C API
    vi编辑器的学习使用(二十一)
    自由软件的定义
    vi编辑器的学习使用(二十三))
    vi编辑器的学习使用(二十二)
  • 原文地址:https://www.cnblogs.com/lcchuguo/p/4558533.html
Copyright © 2020-2023  润新知