标签:string wstring basic_string stl c++
本文实现了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,请与我联系,以使代码不断地完善!!! *大家交流交流,谢谢! * 邮箱:sunkang2101024@foxmail.com */ // 建议此文件命名为 "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; } } //这个构造函数不可用explicit关键字,后面大量用到此构造函数做隐式转换 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,"sunkang2101024@foxmail.com"); //正确的输出结果是sunkang2101024 cout<<str.erase(str.find_first_of('@',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(),"sunkang2101024@foxmail.com")<<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; }
望高手批评指正!!!谢谢!!!
标签:string wstring basic_string stl c++
原文地址:http://blog.csdn.net/focusing_on_cpp/article/details/46678151