1. 程式人生 > >c++ string類的完整實現!!!

c++ string類的完整實現!!!

class sun double ref basic 更新 方便 iterator locate

本文實現了c++ STL中的basic_string模板類,當然。通過typedef也就實現了string類和wstring類。限於篇幅,實現代碼中用到了標準庫的char_traits模板類,本人自己也實現了

char_traits模板類,為此還寫了一篇博客,在我的博客裏能夠找到,那裏的代碼全然能夠用在這裏的basic_string類的實現中,當然,詳細加到代碼中要稍加修改,以和與basic_string類相關的全局模板函數兼容,如operator >> 模板函數的重載。

經過測試。這裏的是實如今效率上不輸標準庫(與vs2012比對),代碼凝視還算清晰,並且具有良好的擴充性。能夠以此量身打造自己的精簡版本號string。

好了。廢話不多說了!看代碼!

!!

還請高手們指教!!!


此文件我建議命名為local_string.h。還是我一慣的習慣,封裝於名字空間mystd中。

假設要測試代碼,直接復制以下的代碼就能夠了,都在一個文件裏。

標準庫有的功能。這裏基本上都有!




/*
*看完《STL源代碼剖析》後就有重寫STL的沖動,這個basic_string的實現還算完整。
標準庫有的功能,這裏基本都有,假設有須要,能夠在此基礎上擴展功能。!

大家如有發現bug,請與我聯系,以使代碼不斷地完好!!。 *大家交流交流,謝謝! * 郵箱:[email protected] */ // 建議此文件命名為 "local_string.h" // vs2012 調試通過 #pragma once #ifndef MYSTD_STRING_H_EX #define MYSTD_STRING_H_EX #include<cassert> // assert #include<cstddef> // std::size_t,std::ptrdiff_t #include<memory> // std::allocator #include<cstdlib> // rand() #include<exception> // std::out_of_range #include<iostream> //basic_istream, basic_ostream #define MYSTD_BEGIN namespace mystd { #define MYSTD_END } // mystd #ifdef __cplusplus MYSTD_BEGIN ///////////// //隨機訪問叠代器 template<class random_access_iterator, class Value_type, class Reference,class Difference_type> class reverse_random_access_iterator{ public: typedef Value_type value_type; typedef value_type* pointer; typedef Reference reference; typedef Difference_type difference_type; typedef std::size_t size_type; typedef std::random_access_iterator_tag reverse_iterator_category; public: random_access_iterator iterator; typedef reverse_random_access_iterator self; public: reverse_random_access_iterator() { //default constructor } explicit reverse_random_access_iterator(const random_access_iterator& tmp):iterator(tmp) { //constructor } reverse_random_access_iterator(const self& tmp):iterator(tmp.iterator) { // copy constructor } template<class random_access_iterator, class Value_type, class Reference,class Difference_type> reverse_random_access_iterator(const reverse_random_access_iterator<random_access_iterator,Value_type,Reference,Difference_type>& obj) :iterator(obj.iterator) { // 此構造函數主要為了進行轉換之用, //reverse_iterator轉換為 const_reverse_iterator } self& operator = (const self& tmp) // 能夠不定義。直接使用默認的函數 { iterator = tmp.iterator; return *this; } ~reverse_random_access_iterator() { // do nothing } self& operator ++ () { --iterator; return *this; } self operator ++ (int) { self tmp(*this); ++*this; return tmp; } self& operator -- () { ++iterator; return *this; } self operator -- (int) { self tmp(*this); --*this; return tmp; } self operator + (difference_type n) const { return self(iterator - n); } self operator - (difference_type n) const { return *this + (-n); } self& operator += (difference_type n) { iterator -= n; return *this; } self& operator -= (difference_type n) { iterator += n; return *this; } reference operator * () const { return *(iterator - 1); } bool operator == (const self& tmp) const { return iterator == tmp.iterator; } bool operator != (const self& tmp) const { return !(*this == tmp); } bool operator < (const self& tmp) const { return tmp.iterator < iterator; } bool operator <= (const self& tmp) const { return tmp.iterator <= iterator; } bool operator > (const self& tmp) const { return iterator < tmp.iterator; } bool operator >= (const self& tmp) const { return iterator <= tmp.iterator; } random_access_iterator base() const { return iterator; } friend difference_type operator - (const self& tmp_1,const self& tmp_2) { return tmp_2.iterator - tmp_1.iterator; } }; template<class T, class Reference,class Difference_type> class random_access_iterator{ // 反向隨機訪問叠代器 public: typedef T value_type; typedef value_type *pointer; typedef Reference reference; typedef Difference_type difference_type; typedef std::size_t size_type; typedef std::random_access_iterator_tag iterator_category; public: pointer ptr; typedef random_access_iterator self; public: random_access_iterator() { } explicit random_access_iterator(pointer tmp):ptr(tmp) { } random_access_iterator(const self& tmp):ptr(tmp.ptr) { } template<class T, class Reference,class Difference_type> random_access_iterator(const random_access_iterator<T,Reference,Difference_type>& obj) :ptr(obj.ptr) { // 此構造函數主要為了進行轉換之用, //iterator轉換為 const_iterator } self& operator = (const self& tmp) { ptr = tmp.ptr; return *this; } ~random_access_iterator() { } self& operator ++ () { ++ptr; return *this; } self operator ++ (int) { self tmp(*this); ++*this; return tmp; } self& operator -- () { --ptr; return *this; } self operator -- (int) { self tmp(*this); --*this; return tmp; } reference operator * () const // 足夠的自由度 { return *ptr; } bool operator == (const self& tmp) const { return ptr == tmp.ptr; } bool operator != (const self& tmp) const { return !(*this == tmp); } bool operator < (const self& tmp) const { return ptr < tmp.ptr; } bool operator <= (const self& tmp) const { return ptr <= tmp.ptr; } bool operator > (const self& tmp) const { return tmp.ptr < ptr; } bool operator >= (const self& tmp) const { return tmp.ptr <= ptr; } self operator + (difference_type n) const { return self(ptr + n); } self operator - (difference_type n) const { return *this + (-n); } self& operator += (difference_type n) { ptr += n; return *this; } self& operator -= (difference_type n) { ptr -= n; return *this; } friend difference_type operator - (const self& tmp_1,const self& tmp_2) { return tmp_1.ptr - tmp_2.ptr; } }; //////////////////////// //限於篇幅,這裏的char_traits模板類用的是標準庫的, //我的博客裏有一篇文章是關於char_traits模板類的實現的,全然能夠用在這裏。

// template<class charT,class traits_type = std::char_traits<charT>,class Alloc = std::allocator<charT> > class basic_string { public: typedef mystd::random_access_iterator<charT,charT&,std::ptrdiff_t> iterator; typedef mystd::random_access_iterator<const charT,const charT&,std::ptrdiff_t> const_iterator; typedef mystd::reverse_random_access_iterator<iterator,charT,charT&,std::ptrdiff_t> reverse_iterator; typedef mystd::reverse_random_access_iterator<const_iterator,const charT,const charT&,std::ptrdiff_t> const_reverse_iterator; typedef typename iterator::value_type value_type; typedef typename iterator::reference reference; typedef typename iterator::pointer pointer; typedef typename iterator::size_type size_type; typedef typename iterator::difference_type difference_type; typedef typename iterator::iterator_category iterator_category; typedef typename const_iterator::reference const_reference; typedef typename const_iterator::pointer const_pointer; typedef Alloc allocator_type; public: static const size_type npos = size_type(-1); private: pointer start,finish,end_of_storage; //數據成員 typedef basic_string self; //私有類型 allocator_type alloc; // 分配器 private: // 內部使用函數 size_type alloc_capacity(size_type old_size) const // 容量分配函數 { //這個函數主要是為了方便改動分配方案, //能夠依照須要改動。可是要確保返回值大於old_size,以此保證capacity()非空(看實現可知) // 提示:與c_str()的實現有關。 if(old_size < 10) return 10; //wstring else if(old_size < 100) return old_size * 2; else if(old_size < 1024) return old_size + old_size / 10; else return old_size + rand() % 1024 + 1; //返回值得大於old_size } void fill_n(pointer first,size_type n,value_type val) { assert(first != 0); while(n--) *first++ = val; } void fill(pointer first,pointer last,value_type val) { assert(first != 0 && last != 0); while(first != last) *first++ = val; } iterator insert_aux(size_type pos,const self& str) { //用於insert相關函數 assert(pos <= size()); if(str.empty()) return iterator(start+pos); if(size()+str.size() > capacity()) // 無論this是否等於&str { size_type str_size = str.size(); // size_type old_size = size(); size_type capacity_size = alloc_capacity(size()+str_size); pointer new_start = alloc.allocate(capacity_size); traits_type::copy(new_start,start,pos); traits_type::copy(new_start+pos,str.start,str_size); traits_type::copy(new_start+pos+str_size,start+pos,old_size-pos); alloc.deallocate(start,capacity()); start = new_start; finish = start + old_size+ + str_size; // end_of_storage = start + capacity_size; return iterator(start+pos); } else if(this != &str) { traits_type::move(start+pos+str.size(),start+pos,size()-pos); traits_type::copy(start+pos,str.start,str.size()); finish += str.size(); return iterator(start+pos); } else { size_type len_left = pos; size_type len_right = size() - pos; traits_type::copy(start+len_left*2+len_right,start+len_left,len_right); traits_type::copy(start+len_left,start,len_left); traits_type::copy(start+len_left*2,start+len_left*2+len_right,len_right); finish += str.size(); return iterator(start+len_left); } } iterator erase_aux(size_type first,size_type last) { //用於erase函數 assert(first <= last && last <= size()); if(first > size()) throw std::out_of_range("invalid string position"); if(first == last) return iterator(start+first); traits_type::copy(start+first,start+last,size()-last); finish -= last - first; return iterator(start+first); } void empty_init() { //用於初始化 size_type capacity_size = alloc_capacity(1); start = alloc.allocate(capacity_size); //分配一定的空間 finish = start; end_of_storage = start + capacity_size; } void swap(pointer& x,pointer& y) { assert(x != 0 && y != 0); pointer temp = x; x = y; y = temp; } bool is_inside(const self& str,value_type val) const { // 後面的查找功能的函數會用到,如find_first_of()函數 size_type n = str.size(); for(size_type i = 0; i < n; ++i) if(traits_type::eq(str[i],val)) return true; return false; } public: basic_string():start(0),finish(0),end_of_storage(0) { assert(sizeof(value_type) <= sizeof(wchar_t)); empty_init(); } basic_string(size_type n,value_type val):start(0),finish(0),end_of_storage(0) { assert(sizeof(value_type) <= sizeof(wchar_t)); size_type capacity_size = alloc_capacity(n); start = alloc.allocate(capacity_size); finish = start + n; end_of_storage = start + capacity_size; fill_n(start,n,val); } basic_string(const self& str,size_type pos,size_type len = npos) { assert(sizeof(value_type) <= sizeof(wchar_t)); assert(pos <= str.size()); if(str.empty()) empty_init(); else { if(len == npos || len > str.size()-pos) len = str.size() - pos; size_type capacity_size = alloc_capacity(len); start = alloc.allocate(capacity_size); traits_type::copy(start,str.start+pos,len); finish = start + len; end_of_storage = start + capacity_size; } } //這個構造函數不可用explicitkeyword。後面大量用到此構造函數做隱式轉換 basic_string(const_pointer str):start(0),finish(0),end_of_storage(0) { assert(sizeof(value_type) <= sizeof(wchar_t) && str != 0); size_type str_size = traits_type::length(str); size_type capacity_size = alloc_capacity(str_size); start = alloc.allocate(capacity_size); traits_type::copy(start,str,str_size); finish = start + str_size; end_of_storage = start + capacity_size; } basic_string(const_pointer str,size_type n):start(0),finish(0),end_of_storage(0) { assert(sizeof(value_type) <= sizeof(wchar_t) && str != 0); size_type len = traits_type::length(str); //標準庫沒有對長度進行調整(測試vs2012的執行結果可知),本人認為應該加上。這樣有更好的容錯性 //當然。在str非常大的時候,效率上會有點折扣(計算長度的時間花銷上) if(n > len) n = len; size_type capacity_size = alloc_capacity(n); start = alloc.allocate(capacity_size); traits_type::copy(start,str,n); finish = start + n; end_of_storage = start + capacity_size; } template <class InputIterator> basic_string(InputIterator first,InputIterator last):start(0),finish(0),end_of_storage(0) { assert(sizeof(value_type) <= sizeof(wchar_t)); size_type len = 0; InputIterator new_first = first; while(new_first != last) //用後自增測試時會出現一點問題 ++len, ++new_first; size_type capacity_size = alloc_capacity(len); start = alloc.allocate(capacity_size); finish = start + len; /*while(first != last) *start++ = *first++;*/ while(last != first) //用後自增測試時會出現一點問題 *--finish = *--last; finish = start + len; // 復位 end_of_storage = start + capacity_size; } basic_string(const self& tmp):start(0),finish(0),end_of_storage(0) { assert(sizeof(value_type) <= sizeof(wchar_t)); start = alloc.allocate(tmp.capacity()); finish = start + tmp.size(); end_of_storage = start + tmp.capacity(); traits_type::copy(start,tmp.start,tmp.size()); } self& operator = (const self& tmp) { if(this == &tmp) // 防止自身復制 return *this; clear(); if(tmp.empty()) return *this; if(capacity() >= tmp.capacity()) { traits_type::copy(start,tmp.start,tmp.size()); finish = start + tmp.size(); } else { size_type capacity_size = alloc_capacity(tmp.size()); alloc.deallocate(start,capacity()); // 釋放原有空間 start = alloc.allocate(capacity_size); traits_type::copy(start,tmp.start,tmp.size()); finish = start + tmp.size(); end_of_storage = start + capacity_size; } return *this; } self& operator = (value_type val) { clear(); // 不釋放內存,看代碼可知 insert_aux(0,self(1,val)); return *this; } ~basic_string() { //alloc.deallocate(start,capacity()); //由於capacity()實現上的緣故,這裏用end_of_storage - start(看capacity代碼可知) //當然,第二個參數其實沒實用。隨意寫一個數字都可 alloc.deallocate(start,end_of_storage - start); } public: size_type size() const throw() { //依照標準文檔的要求,不拋出異常,下面同理可得,不再贅述! return finish - start; } size_type length() const throw() { return size(); } size_type max_size() const throw() { return size_type(-1) / sizeof(value_type) - 1; } size_type capacity() const throw() { //這裏的計算本來不應該減 1 的,有意這樣做是為了確保留有一個字符的空間(包括寬字符),方便做 // C風格字符串的轉換,寫入空字符,用於成員函數c_str() return end_of_storage - start - 1; } bool empty() const throw() { return start == finish; } iterator begin() throw() { return iterator(start); } const_iterator begin() const throw() { return const_iterator(start); } iterator end() throw() { return iterator(finish); } const_iterator end() const throw() { return const_iterator(finish); } reverse_iterator rbegin() throw() { return reverse_iterator(end()); } const_reverse_iterator rbegin() const throw() { return const_reverse_iterator(end()); } reverse_iterator rend() throw() { return reverse_iterator(begin()); } const_reverse_iterator rend() const throw() { return const_reverse_iterator(begin()); } reference operator [] (size_type n) throw() { assert(n < size()); return *(start + n); } const_reference operator [] (size_type n) const throw() { assert(n < size()); return *(start + n); } reference at(size_type n) { if(n < size()) return *(start + n); else throw std::out_of_range("invalid string position"); } const_reference at(size_type n) const { if(n < size()) return *(start + n); else throw std::out_of_range("invalid string position"); } allocator_type get_allocator() const throw() { return allocator_type(); } void reserve(size_type n = 0) { if(n <= capacity()) ; else { size_type capacity_size = alloc_capacity(n); size_type old_size = size(); pointer new_start = alloc.allocate(capacity_size); traits_type::copy(new_start,start,size()); alloc.deallocate(start,capacity()); start = new_start; finish = start + old_size; end_of_storage = start + capacity_size; } } void clear() { finish = start; //並不釋放內存 } self substr(size_type pos = 0,size_type len = npos) const { assert(pos <= size()); return self(*this,pos,len); // 顯式調用構造函數 } self& insert(size_type pos,const self& str) { assert(pos <= size()); insert_aux(pos,str); return *this; } const_pointer c_str() const throw() { //構造函數保證capacity() != 0,或者說start,finish,end_of_storage不為空指針 //當然,這和詳細的實現有關,這是我的一個實現 *finish = 0; // 轉換成C風格的字符串 return start; } const_pointer data() const throw() { *finish = 0; // 也能夠直接返回start,標準文檔沒有強制要求為C風格字符串 return start; } self& insert(size_type pos,const self& str,size_type subpos,size_type sublen) { assert(pos <= size()); insert_aux(pos,str.substr(subpos,sublen)); return *this; } self& insert(size_type pos,const_pointer str) { assert(pos <= size() && str != 0); insert_aux(pos,self(str)); return *this; } self& insert(size_type pos,const_pointer str,size_type n) { assert(pos <= size() && str != 0); insert_aux(pos,self(str,n)); return *this; } self& insert(size_type pos,size_type n,value_type val) { assert(pos <= size()); insert_aux(pos,self(n,val)); return *this; } void insert(iterator itr,size_type n,value_type val) { assert(itr >= begin() && itr <= end()); insert_aux(itr-begin(),self(n,val)); } iterator insert(iterator itr,value_type val) { assert(itr >= begin() && itr <= end()); return insert_aux(itr-begin(),self(1,val)); } template <class InputIterator> void insert(iterator itr,InputIterator first,InputIterator last) { assert(itr >= begin() && itr <= end()); insert_aux(itr-begin(),self(first,last)); } self& erase(size_type pos = 0,size_type len = npos) { assert(pos <= size()); if(pos > size()) throw std::out_of_range("invalid string position"); if(len == npos || len > size()-pos) len = size() - pos; erase_aux(pos,pos+len); return *this; } iterator erase(iterator itr) { assert(itr >= begin() && itr < end()); return erase_aux(itr-begin(),itr-begin()+1); } iterator erase(iterator first,iterator last) { assert(first >= begin() && first <= last && last <= end()); return erase_aux(first-begin(),last-begin()); } void push_back(value_type val) { insert_aux(size(),self(1,val)); } self& append(const self& str) { return *this += str; } self& append(const self& str,size_type subpos,size_type sublen) { return *this += str.substr(subpos,sublen); } self& append(const_pointer str) { assert(str != 0); return *this += str; } self& append(const_pointer str,size_type n) { assert(str != 0); return *this += self(str,n); } self& append(size_type n,value_type val) { return *this += self(n,val); } template <class InputIterator> self& append(InputIterator first,InputIterator last) { return *this += self(first,last); } self& assign(const self& str) { return *this = str; } self& assign(const self& str,size_type subpos,size_type sublen) { return *this = self(str,subpos,sublen); } self& assign(const_pointer str) { assert(str != 0); return *this = self(str); } self& assign(const_pointer str,size_type n) { assert(str != 0); return *this = self(str,n); } self& assign(size_type n,value_type val) { return *this = self(n,val); } template <class InputIterator> self& assign(InputIterator first,InputIterator last) { return *this = self(first,last); } void resize(size_type n) { resize(n,0); //轉調 } void resize(size_type n,value_type val) { if(n <= size()) finish -= size() - n; else if(n <= capacity()) { fill(finish,finish+n,val); finish += n - size(); } else { size_type capacity_size = alloc_capacity(n); pointer new_start = alloc.allocate(capacity_size); traits_type::copy(new_start,start,size()); fill(new_start+size(),new_start+n,val); alloc.deallocate(start,capacity()); start = new_start; finish = start + n; end_of_storage = start + capacity_size; } } void swap(self& str) { if(this == &str) return ; swap(start,str.start); swap(finish,str.finish); swap(end_of_storage,str.end_of_storage); } self& replace(size_type pos,size_type len,const self& str) { assert(pos <= size()); if(pos > size()) throw std::out_of_range("invalid string position"); // 後面的replace重載函數就不用寫異常了,由於都會直接或間接地調用到這個函數 if(len > size() - pos) len = size() - pos; if(size() + str.size() - len > capacity()) { size_type new_size = size()+str.size()-len; size_type capacity_size = alloc_capacity(new_size); pointer new_start = alloc.allocate(capacity_size); traits_type::copy(new_start,start,pos); traits_type::copy(new_start+pos,str.start,str.size()); traits_type::copy(new_start+pos+str.size(),start+pos+len,size()-pos-len); alloc.deallocate(start,capacity()); start = new_start; finish = start + new_size; end_of_storage = start + capacity_size; } else if(this != &str) //假設不是自身的替換 { if(str.size() <= len) { traits_type::copy(start+pos,str.start,str.size()); erase(pos+str.size(),len-str.size()); // 長度len - str.size() // finish 已經更新 } else // size() + str.size() - len <= capacity() { traits_type::move(start+pos+str.size(),start+pos+len,size()-pos-len); traits_type::copy(start+pos,str.start,str.size()); finish += str.size() - len; } } else return replace(pos,len,self(str)); //遞歸調用,這次不會是自身了。 return *this; } self& replace(iterator itr_1,iterator itr_2,const self& str) { assert(itr_1 >= begin() && itr_2 <= end()); return replace(itr_1-begin(),itr_2-itr_1,str); // 轉調 } self& replace(size_type pos,size_type len,const self& str, size_type subpos,size_type sublen) { assert(pos <= size()); return replace(pos,len,str.substr(subpos,sublen)); } self& replace(size_type pos,size_type len,const_pointer str) { assert(pos <= size() && str != 0); return replace(pos,len,self(str)); } self& replace(iterator itr_1,iterator itr_2,const_pointer str) { assert(itr_1 >= begin() && itr_2 <= end()); return replace(itr_1,itr_2,self(str)); //轉調 } self& replace(size_type pos,size_type len,const_pointer str,size_type n) { assert(pos <= size() && str != 0); return replace(pos,len,self(str,n)); } self& replace(iterator itr_1,iterator itr_2,const_pointer str,size_type n) { assert(itr_1 >= begin() && itr_2 <= end() && str != 0); return replace(itr_1,itr_2,self(str,n)); } self& replace(size_type pos,size_type len,size_type n,value_type val) { assert(pos <= size()); return replace(pos,len,self(n,val)); } self& replace(iterator itr_1,iterator itr_2,size_type n,value_type val) { assert(itr_1 >= begin() && itr_2 <= end()); return replace(itr_1,itr_2,self(n,val)); } template <class InputIterator> self& replace(iterator itr_1,iterator itr_2,InputIterator first,InputIterator last) { assert(itr_1 >= begin() && itr_2 <= end()); return replace(itr_1,itr_2,self(first,last)); } int compare(const self& str) const { //後面的compare重載函數都間接調用此函數 if(this == &str) return 0; size_type num = size() >= str.size() ? size() : str.size(); return traits_type::compare(c_str(),str.c_str(),num); //須要轉換為C風格字符串 } int compare(size_type pos,size_type len,const self& str) const { assert(pos <= size()); if(pos > size()) // 後面的重載函數不用寫異常了。這裏寫了 throw std::out_of_range("invalid string position"); //size_type num = len >= str.size() ? len : str.size(); //return traits_type::compare(start+pos,str.start,num); return substr(pos,len).compare(str); //轉調 } int compare(size_type pos,size_type len,const self& str, size_type subpos,size_type sublen) const { assert(pos <= size()); return compare(pos,len,self(str,subpos,sublen)); //轉調 } int compare(const_pointer str) const { assert(str != 0); return compare(self(str)); } int compare(size_type pos,size_type len,const_pointer str) const { assert(pos <= size() && str != 0); return compare(pos,len,self(str)); } int compare(size_type pos,size_type len,const_pointer str,size_type n) const { assert(pos <= size() && str != 0); return compare(pos,len,self(str,n)); } size_type copy(pointer str,size_type len,size_type pos = 0) const { assert(pos <= size() && str != 0); if(len + pos > size()) len = size() - pos; // 調整一下長度 traits_type::copy(str,start+pos,len); return len; } size_type find(const self& str,size_type pos = 0) const throw() { //pos為搜索開始處,用數學區間表示為[pos,size() ) assert(pos <= size()); if(empty()) return npos; size_type len_str = str.size(); size_type len = size() - pos; if(len < len_str) return npos; size_type end_pos = size() - len_str; // 調整了一下有效長度,避免做無用功 while(pos <= end_pos) { if(compare(pos,len_str,str) == 0) // 轉調重載的成員函數 return pos; else ++pos; } return npos; } size_type find(const_pointer str,size_type pos = 0) const throw() { assert(pos <= size() && str != 0); if(empty()) return npos; return find(self(str),pos); // 轉調重載的成員函數 } size_type find(const_pointer str,size_type pos,size_type n) const throw() { //str中的n個字符,註意 n 的詳細所指 assert(pos <= size() && str != 0); if(empty()) return npos; return find(self(str,n),pos);// 轉調重載的成員函數 } size_type find(value_type val,size_type pos = 0) const throw() { assert(pos <= size()); if(empty()) return npos; return find(self(1,val),pos); // 轉調重載的成員函數 } size_type rfind(const self& str,size_type pos = npos) const throw() { // pos為搜索開始處,用數學區間表示為[0,pos] if(empty()) return npos; if(pos == npos || pos >= size()) //加上pos == npos的推斷並不是多此一舉 pos = size() - 1; if(size() < str.size()) return npos; size_type len_str = str.size(); if(pos > size() - len_str) pos = size() - len_str; // 調整位置,避免做沒用的搜索 while(pos >= 0 && pos != size_type(-1)) { if(compare(pos,len_str,str) == 0) // 轉調成員函數 return pos; else --pos; } return npos; } size_type rfind(const_pointer str,size_type pos = npos) const throw() { assert(str != 0); if(empty()) return npos; if(pos == npos || pos >= size()) //加上pos == npos的推斷並不是多此一舉 pos = size() - 1; return rfind(self(str),pos); // 轉調重載的成員函數 } size_type rfind(const_pointer str,size_type pos,size_type n) const throw() { // n為str須要搜索字符的個數,由於構造函數實現上的差異,我的n值在調用構造函數時會有調整, // 這樣是為了增強容錯性,可是測試vs2012可知此實現上沒有此功能, //因此。用標準庫時,依賴於用戶使用正確的n值,否則會得不到預期的結果。 // 用我的這個實現,當n值大於str的長度時。會匹配整個str字符串 //相似情況同理可知,不再贅述。 assert(str != 0); if(empty()) return npos; if(pos >= size()) pos = size() - 1; return rfind(self(str,n),pos); // 轉調重載的成員函數 } size_type rfind(value_type val,size_type pos = npos) const throw() { if(empty()) return npos; if(pos == npos || pos >= size()) pos = size() - 1; return rfind(self(1,val),pos); // 轉調重載的成員函數 } size_type find_first_of(const self& str,size_type pos = 0) const throw() { //pos為搜索開始處。用數學區間表示為[pos,size() ) assert(pos <= size()); if(empty()) return npos; size_type end_pos = size(); while(pos != end_pos && !is_inside(str,*(start+pos))) ++pos; if(pos == end_pos) return npos; else return pos; } size_type find_first_of(const_pointer str,size_type pos = 0) const throw() { //pos為搜索開始處,範圍為[pos,size() ) assert(pos <= size() && str != 0); if(empty()) return npos; return find_first_of(self(str),pos); // 轉調重載的成員函數 } size_type find_first_of(const_pointer str,size_type pos, size_type n) const throw() { //pos為搜索開始處,範圍為[pos,size() ) assert(pos <= size() && str != 0); if(empty()) return npos; return find_first_of(self(str,n),pos); // // 轉調重載的成員函數 } size_type find_first_of(value_type val,size_type pos = 0) const throw() { //pos為搜索開始處,範圍為[pos,size() ) assert(pos <= size()); if(empty()) return npos; return find_first_of(self(1,val),pos); // 轉調重載的成員函數 } size_type find_last_of(const self& str,size_type pos = npos) const throw() { //pos 搜索結束處。範圍[0,pos],包括pos if(empty()) return npos; if(pos == npos || pos >= size()) //加上pos == npos的推斷並不是多此一舉 pos = size() - 1; while(pos >= 0 && pos != size_type(-1) && !is_inside(str,*(start+pos))) --pos; if(pos != size_type(-1)) return pos; else return npos; } size_type find_last_of(const_pointer str,size_type pos = npos) const throw() { //pos 搜索結束處。範圍[0,pos],包括pos if(empty()) return npos; assert(str != 0); if(pos == npos || pos >= size()) pos = size() - 1; return find_last_of(self(str),pos); // 轉調重載的成員函數 } size_type find_last_of(const_pointer str,size_type pos,size_type n) const throw() { //pos 搜索結束處,範圍[0,pos],包括pos assert(str != 0); if(empty()) return npos; if(pos >= size()) pos = size() - 1; return find_last_of(self(str,n),pos); // 轉調重載的成員函數 } size_type find_last_of(value_type val,size_type pos = npos) const throw() { //pos 搜索結束處,範圍[0,pos],包括pos if(empty()) return npos; if(pos == npos || pos >= size()) pos = size() - 1; return find_last_of(self(1,val),pos); // 轉調重載的成員函數 } size_type find_first_not_of(const self& str,size_type pos = 0) const throw() { //pos 為搜索開始處,範圍[pos,size() ) assert(pos <= size()); if(empty()) return npos; size_type end_pos = size(); while(pos != end_pos && is_inside(str,*(start+pos))) ++pos; if(pos == end_pos) return npos; else return pos; } size_type find_first_not_of(const_pointer str,size_type pos = 0) const throw() { //pos 為搜索開始處,範圍[pos,size() ) assert(pos <= size() && str != 0); if(empty()) return npos; return find_first_not_of(self(str),pos); } size_type find_first_not_of(const_pointer str,size_type pos,size_type n) const throw() { //pos 為搜索開始處,範圍[pos,size() ) assert(pos <= size() && str != 0); if(empty()) return npos; return find_first_not_of(self(str,n),pos); // 轉調重載的成員函數 } size_type find_first_not_of(value_type val,size_type pos = 0) const throw() { //pos 為搜索開始處,範圍[pos,size() ) assert(pos <= size()); if(empty()) return npos; return find_first_not_of(self(1,val),pos); } size_type find_last_not_of(const self& str,size_type pos = npos) const throw() { //pos 搜索結束處,範圍[0,pos] if(empty()) return npos; if(pos == npos || pos >= size()) pos = size() - 1; while(pos >= 0 && pos != size_type(-1) && is_inside(str,*(start+pos))) --pos; if(pos != size_type(-1)) return pos; else return npos; } size_type find_last_not_of (const_pointer str,size_type pos = npos) const throw() { //pos 搜索結束處,範圍[0,pos] assert(str != 0); if(empty()) return npos; if(pos == npos || pos >= size()) //加上pos == npos的推斷並不是多此一舉 pos = size() - 1; return find_last_not_of(self(str),pos); // 轉調重載的成員函數 } size_type find_last_not_of (const_pointer str,size_type pos,size_type n) const throw() { //pos 搜索結束處,範圍[0,pos] assert(str != 0); if(empty()) return npos; if(pos >= size()) pos = size() - 1; return find_last_not_of(self(str,n),pos); // 轉調重載的成員函數 } size_type find_last_not_of (value_type val,size_type pos = npos) const throw() { //pos 搜索結束處,範圍[0,pos] if(empty()) return npos; if(pos == npos || pos >= size()) pos = size() - 1; return find_last_not_of(self(1,val),pos); // 轉調重載的成員函數 } self& operator += (const self& str) { insert_aux(size(),str); return *this; } self& operator += (value_type val) { insert_aux(size(),self(1,val)); return *this; } friend self operator + (const self& str1,const self& str2) { return self(str1) += str2; } friend self operator + (const self& str,value_type val) { return self(str) += self(1,val); } friend self operator + (value_type val,const self& str) { return self(1,val) += str; } friend void swap(self& str1,self& str2) { if(&str1 == &str2) return ; str1.swap(str2); } friend bool operator == (const self& str1,const self& str2) { return str1.compare(str2) == 0; } friend bool operator != (const self& str1,const self& str2) { return str1.compare(str2) != 0; } friend bool operator < (const self& str1,const self& str2) { return str1.compare(str2) < 0; } friend bool operator <= (const self& str1,const self& str2) { return str1.compare(str2) <= 0; } friend bool operator > (const self& str1,const self& str2) { return str1.compare(str2) > 0; } friend bool operator >= (const self& str1,const self& str2) { return str1.compare(str2) >= 0; } }; template <class charT, class traits, class Alloc> std::basic_istream<charT,traits>& operator >> (std::basic_istream<charT,traits>& is, mystd::basic_string<charT,traits,Alloc>& str) { str.clear(); //先清空str int chr = 0; //對wchar_t類型字符也適用 while((chr = is.get()) && chr != ‘ ‘ && chr != ‘\n‘) str.push_back(chr); return is; } template <class charT, class traits, class Alloc> std::basic_ostream<charT,traits>& operator<< (std::basic_ostream<charT,traits>& os, const mystd::basic_string<charT,traits,Alloc>& str) { typedef typename mystd::basic_string<charT,traits,Alloc>::size_type size_type; size_type size = str.size(); for(size_type i = 0; i < size; ++i) os<<str[i]; return os; } template <class charT, class traits, class Alloc> std::basic_istream<charT,traits>& getline(std::basic_istream<charT,traits>& is, mystd::basic_string<charT,traits,Alloc>& str, charT delim) { charT chr = 0; str.clear(); //先清空str while((chr = is.get()) && chr != delim && chr != ‘\n‘) str.push_back(chr); return is; } template <class charT, class traits, class Alloc> std::basic_istream<charT,traits>& getline(std::basic_istream<charT,traits>& is, mystd::basic_string<charT,traits,Alloc>& str) { charT chr = 0; str.clear(); //先清空str while((chr = is.get()) && chr != ‘\n‘) str.push_back(chr); return is; } typedef mystd::basic_string<char,std::char_traits<char>,std::allocator<char> > string; typedef mystd::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> > wstring; MYSTD_END // end of namespace mystd #endif // __cplusplus #endif // MYSTD_STRING_H_EX



以下是一個簡單的測試程序!

並和標準庫比對執行結果!以驗證正確性。


#include<iostream>
#include<string>
#include<ctime>  //clock
#include"local_string.h"
#define STD mystd   //改為std能夠執行標準庫版本號

//測試可知。結果與標準庫的執行結果一樣

using std::cout;
using std::wcout;
using std::cin;
using std::wcin;
using std::endl;

int main()
{  // 下面是一些測試代碼!
	STD::string str;
	str = "ABCDEFGHIJK";  //11 個字符長度

	clock_t start = clock();
	
	//之所以選擇在首部進行插入操作。是為了測試在極端條件下的執行效率。
    for(int i = 0; i < 25; ++i)
		str.insert(0,str);  
	//完畢循環後。str會變得非常大,大小為 11乘以2的25次方 ,結果為369,098,752個字符長度
	clock_t finish = clock();
/*
 在release版本號下的統計結果例如以下:(執行時間/S)
 mystd        |       std 
--------------|--------------------           
 0.348        |       0.435
 0.366        |       0.446
 0.359        |       0.47
 0.392        |       0.46
 0.374        |       0.445
 能夠看到,我的實現版本號比標準庫略快!
聲明:我的機器是win8系統,vs2012  
*/
	cout<<double(finish - start) / CLOCKS_PER_SEC << "秒"<<endl;
	//str.size()的結果與標準庫一樣,str.capacity()不一樣,
	//這個是正常的,capacity()的結果與詳細的實現有關
	cout<<str.size()<<"\t"<<str.capacity()<<endl;
	str.swap(STD::string()); //顯式釋放內存

	//我的郵箱,希望指教!
	str.insert(0,"[email protected]");

	//正確的輸出結果是sunkang2101024
	cout<<str.erase(str.find_first_of([email protected],0))<<endl;


	//寬字符版本號測試
	wcout<<STD::wstring(L"hello world").c_str()<<endl;
	STD::wstring wstr;
	wstr += L"ABCDEFGHIJKLMNOPQRSTUVWXYZ";

	//測試反向叠代器
	for(STD::wstring::const_reverse_iterator first = wstr.rbegin(); first != wstr.rend(); ++first)
		wcout<<*first<<"\t";
	cout<<endl;

	//間接測試compare函數
	if(STD::string("hello world") == "hello world")
		cout<<"相等"<<endl;
	else
		cout<<"不相等"<<endl;

	//測試一下replace函數
	cout<<str.assign("hello world").replace(6,5,str)<<endl;
	cout<<str.replace(str.begin(),str.end(),"[email protected]")<<endl;

	//測試重載的operator + 
	cout<<"HHHHHHH " + str + ‘A‘ + "ABCDEFG"<<endl;

	// 測試異常
	try
	{  
		str.clear();
		cout<<str.at(100)<<endl;
		//此時會拋出異常
	}
	catch(std::out_of_range& ex)
	{
		cout<<ex.what()<<endl;
	}

	// 測試rfind函數
	str = "ABCDEFG   RSTUVQXYZ";
	STD::string::size_type pos = str.rfind("EFG",str.size(),2);
	//能夠試著將函數的第三個參數取一個比較大的值。比方100。
	//在我的這個實現版本號下,仍然會取得正確的結果。vs2012測試不行
	if(pos != STD::string::npos)
		cout<<str.substr(pos)<<endl;

	cout<<endl;
	system("pause");
	return 0;
}



望高手批評指正!

!謝謝!

!。












c++ string類的完整實現!!!