ZSL_String
模仿STL标准库,无单独空间配置器alloc,无萃取机traits,无反向迭代器,end_of_storage配置不同于标准库,
空间配置用了placement new,new,delete
部分函数还没写,还未测试完全,后面会慢慢修改
#ifndef __ZSL_String__ #define __ZSL_String__ #include <iostream> #include <algorithm> using namespace std; template<typename CharT> class ZSL_String; using String = ZSL_String<char>; template<typename CharT> class ZSL_String { public: using value_type = CharT; using pointer = value_type*; using const_pointer = const value_type*; using iterator = value_type*; using const_iterator = const value_type*; using reference = value_type&; using const_reference = const value_type&; using difference_type = ptrdiff_t; using size_type = size_t; private: iterator start; iterator finish; iterator end_of_storage; static size_type nops; public://text void print() const { iterator it = start; while(it != finish) cout << *it; } private: iterator allocator(size_type n) { iterator it = new value_type[n]; return it; } void fill(iterator first1, iterator last1, iterator first2, iterator last2){ while(first1 != last1 && first2 != last2){ *first1 = *first2; ++first1, ++first2; } } void fill_c(size_type n, const CharT& c){ iterator it = start; while(it != finish) *it = c; } void destroy(pointer p) { p->~CharT(); } void construct(pointer p, value_type value) { new(p)CharT(value); } void deallocate() { delete []start; } void insert_aux(size_type pos, size_type count, iterator it); int compare_aux(iterator first1, iterator last1, iterator first2, iterator last2); void assign_aux(iterator first, iterator last); public: ZSL_String() : start(0), finish(0), end_of_storage(0) {} ZSL_String(const CharT* s){ start = allocator(strlen(s)); finish = start + strlen(s); end_of_storage = finish; for(int i = 0; i < strlen(s); ++i) start[i] = s[i]; } ZSL_String(size_type count, const CharT& c){ start = allocator(count); finish = start + count; end_of_storage = finish; fill_c(count, c); } ZSL_String(iterator first, iterator last){ start = allocator(last - first); finish = start + (last - first); end_of_storage = finish; fill(start, finish, first, last); } ZSL_String(initializer_list<CharT> ilist){ start = allocator(ilist.size()); finish = start + ilist.size(); end_of_storage = finish; fill(start, finish, ilist.begin(), ilist.end()); } ZSL_String(ZSL_String<CharT>&& other) noexcept : start(other.start), finish(other.finish), end_of_storage(other.end_of_storage) { other.start = other.finish = other.end_of_storage = nullptr; } ZSL_String(const ZSL_String<CharT>& str) { start = allocator(str.size()); finish = start + str.size(); end_of_storage = finish; for(int i = 0; i < str.size(); ++i) start[i] = str[i]; } ZSL_String<CharT>& operator= (const ZSL_String<CharT>& str) { if(this != &str) { deallocate(); start = allocator(str.size()); finish = start + str.size(); end_of_storage = finish; for(int i = 0; i < str.size(); ++i) start[i] = str[i]; } return *this; } ZSL_String<CharT>& operator= (const CharT* s) { if(start != s) { deallocate(); start = allocator(strlen(s)); finish = start + strlen(s); end_of_storage = finish; for(int i = 0; i < strlen(s); ++i) start[i] = s[i]; } return *this; } ZSL_String<CharT>& operator= (ZSL_String<CharT>&& str) noexcept { if(this != &str) { deallocate(); start = str.start; finish = str.finish; end_of_storage = str.end_of_storage; str.start = str.finish = str.end_of_storage = nullptr; } return *this; } ~ZSL_String(){ deallocate(); } ZSL_String<CharT>& assign(size_type count, CharT c) { if(count < capacity()) { clear(start, finish); while(count--) construct(finish++, c); } else { deallocate(); start = allocator(count); finish = start; while(count--) coustruct(finish++, c); end_of_storage = finish; } return *this; } ZSL_String<CharT>& assign(const ZSL_String<CharT>& str) { assign_aux(str.begin(), str.end()); return *this; } ZSL_String<CharT>& assign(const ZSL_String<CharT>& str, size_type pos, size_type count) { if(pos + count > str.size()) { deallocate(); throw "out of range"; } assign_aux(str.begin() + pos, str.begin() + pos + count); return *this; } ZSL_String<CharT>& assign(const CharT *s, size_type count) { if(count > strlen(s)) { deallocate(); throw "out of range"; } assign_aux(s, s + count); return *this; } ZSL_String<CharT>& assign(const CharT *s) { assign_aux(s, s + strlen(s)); return *this; } ZSL_String<CharT>& assign(iterator first, iterator last) { assign_aux(first, last); return *this; } ZSL_String<CharT>& assign(initializer_list<CharT> ilist) { assign_aux(ilist.begin(), ilist.end()); return *this; } const_reference operator[] (size_type pos) const { return *(start + pos); } reference operator[] (size_type pos) { return *(start + pos); } const_reference at(size_type pos) const { if(pos > size()) { deallocate(); throw "out_of_range"; } return *(start + pos); } reference at(size_type pos){ return const_cast<CharT&>(static_cast<const ZSL_String&>(*this).at(pos)); } reference front() { return *start; } const_reference front() const { return *start; } const_reference back() const { if(size() == 0) return *finish; return *(finish - 1); } reference back() { return const_cast<CharT&>(static_cast<const ZSL_String&>(*this).back()); } const_iterator cbegin() const { return start; } iterator begin() { return start; } const_iterator cend() const { return finish; } iterator end(){ return finish; } pointer data() { return start; } const_pointer data() const { return start; } const_pointer c_str() const { return start; } bool empty() const { return finish == start; } size_type size() const { return finish - start; } size_type length() const { return finish - start; } size_type capacity() const { return end_of_storage - start; } size_type max_size() const { return size_type(-1)/sizeof(CharT); } void clear() { while(finish != start) { --finish; destroy(finish); } } ZSL_String<CharT>& insert(size_type index, size_type count, const CharT& c) { iterator it = &c; insert_aux(index, count, it); return *this; } ZSL_String<CharT>& insert(size_type index, const CharT* str) { insert_aux(index, strlen(str), str); return *this; } ZSL_String<CharT>& insert(size_type index, const ZSL_String<CharT>& str) { insert_aux(index, str.size(), str.start); return *this; } ZSL_String<CharT>& erase(size_type pos, size_type count) { if(pos + count > size()) { deallocate(); throw "out of range"; } else { for(int i = pos; i < pos + count; ++i) *(start + i) = *(start + i + count); for(int i = pos + count; i < size(); ++i) { --finish; destroy(finish); } while(--count) { --end_of_storage; iterator tmp = end_of_storage; --tmp; end_of_storage = tmp; } } return *this; } iterator erase(iterator pos) { for(int i = pos; i < size() - 1; ++i) start[i] = start[i + 1]; --finish; destroy(finish); return pos; } iterator erase(const_iterator pos) { return static_cast<ZSL_String<CharT>&>(*this).erase(pos); } iterator erase(iterator first, iterator last) { if((last - first) > size()) { deallocate(); throw "out of range"; } size_type len = last - first; while(first != last) { *first = *(first + len); ++first; } while(len--) { --finish; destroy(finish); } return first; } iterator erase(const_iterator first, const_iterator last) { return static_cast<ZSL_String<CharT>&>(*this).erase(first, last); } void push_back(const CharT& c) { ////////////////////////////////////////////////////// ZSL_String<CharT> tmp(1, c); insert_aux(size(), 1, tmp.start); } void pop_back() { --finish; destroy(finish); } ZSL_String<CharT>& append(size_type count, const CharT& c) { insert(size(), count, c); return *this; } ZSL_String<CharT>& append(const ZSL_String<CharT>& str) { insert(size(), str.size(), str.start); return *this; } ZSL_String<CharT>& append(const ZSL_String& str, size_type pos, size_type count) { if(pos + count > str.size()) { deallocate(); throw "out of range"; } insert(size(), count, str.start + pos); return *this; } ZSL_String<CharT>& append(const CharT* str, size_type count) { ////////////////////////////////////////////////////// ZSL_String<CharT> tmp(str); insert(tmp, 0, count); return *this; } ZSL_String<CharT>& append(const CharT* str) { append(str, strlen(str)); return *this; } ZSL_String<CharT>& operator+= (const ZSL_String<CharT>& str) { append(str); return *this; } ZSL_String<CharT>& operator+= (const CharT& c) { push_back(c); return *this; } ZSL_String<CharT>& operator+= (const CharT* str) { append(str); return *this; } int compare(const ZSL_String<CharT>& str) const { return compare_aux(start, finish, str.start, str.finish); } int compare(size_type pos, size_type count, const ZSL_String<CharT>& str) const { if(count + pos > size()) { deallocate(); throw "out_of_range"; } return compare_aux(start + pos, start + pos + count, str.start, str.finish); } int compare(size_type pos1, size_type count1, const ZSL_String<CharT>& str, size_type pos2, size_type count2) { if((pos1 + count1 > size()) || (pos2 + count2 > str.size())) { deallocate(); throw "out_of_range"; } return compare_aux(start + pos1, start + pos1 + count1, str.start + pos2, str.start + pos2 + count2); } int compare(const CharT* str) const { ////////// ZSL_String<CharT> tmp(str); return compare_aux(start, finish, tmp.start, tmp.finish); } int compare(size_type pos, size_type count, const CharT* str) const { ////////// ZSL_String<CharT> tmp(str); return compare_aux(start + pos, start + pos + count, tmp.start, tmp.finish); } int compare(size_type pos1, size_type count1, const CharT* str, size_type count2) const { ///////// ZSL_String<CharT> tmp(str); return compare_aux(start + pos1, start + pos1 + count1, tmp.start, tmp.start + count2); } ZSL_String<CharT>& replace(size_type pos, size_type count, const ZSL_String<CharT>& str) { return replace(pos, count, str, 0, str.size()); } ZSL_String<CharT>& replace(size_type pos1, size_type count1, const ZSL_String<CharT>& str, size_type pos2, size_type count2) { size_type len = size(); if((pos1 + count1 > len) || (pos2 + count2) > str.size()) { deallocate(); throw "out of range"; } size_type pos = pos1 + count1; iterator new_start = allocator(len + count2 - count1); for(int i = 0; i < pos1; ++i) new_start[i] = start[i]; for(int i = pos1; i < pos1 + count2; ++i) new_start[i] = str[pos2++]; for(int i = pos1 + count2; i < len + count2 - count1; ++i) new_start[i] = start[pos++]; deallocate(); start = new_start; finish = start + len + count2 - count1; end_of_storage = finish; return *this; } ZSL_String<CharT> substr(size_type pos, size_type count) const { if(pos + count > size()) { deallocate(); throw "out of range"; } return new ZSL_String<CharT>(start + pos, start + pos + count); } size_type copy(CharT* dest, size_type pos, size_type count) const { if(pos + count > size()) { deallocate(); throw "out of range"; } for(int i = pos; i < pos + count; ++i) *dest++ = start[i]; return count; } void resize(size_type count); void resize(size_type count, const CharT& c); void swap(ZSL_String& other) { using std::swap; swap(start, other.start); swap(finish, other.finish); } size_type find(const ZSL_String& str, size_type pos = 0) const { if(pos > size()) { deallocate(); throw "out of range"; } while((start + pos) != finish) { if(compare_aux(start + pos, start + pos + str.size(), str.start, str.finish) == 0) return pos; ++pos; } return -1; } size_type find(const CharT* str, size_type pos, size_type count) const { if(pos + count > size()) { deallocate(); throw "out of range"; } while((start + pos + count) != finish) { if(compare(start + pos, start + pos + count, str) == 0) return pos; ++pos; } return -1; } size_type find(const CharT* str, size_type pos = 0) const { if(pos > size()) { deallocate(); throw "out of range"; } while((start + pos) != finish) { if(compare(start + pos, start + pos + strlen(str), str) == 0) return pos; ++pos; } return -1; } size_type find(const CharT& c, size_type pos = 0) const { if(pos > size()) { deallocate(); throw "out of range"; } while(*(start + pos) != c) ++pos; return pos; } }; template<typename CharT> size_t ZSL_String<CharT>::nops = -1; template<typename CharT> void ZSL_String<CharT>::insert_aux(size_type pos, size_type count, iterator it) { if(pos + count < capacity()) { iterator new_finish = start + pos + count; while(count) { --new_finish; construct(new_finish, *(--finish)); } while((start + pos) != new_finish) *(start + pos) = *it++; finish = start + pos + count; } else { iterator new_start = allocator(size() + count); for (int i = 0; i < pos; ++i, ++start) new_start[i] = *start; for (int i = pos; i < pos + count; ++i, ++it) new_start[i] = *it; for (int i = pos + count; i < size() + count; ++i, ++start) new_start[i] = *start; deallocate(); start = new_start; finish = start + size() + count; end_of_storage = finish; } } template<typename CharT> int ZSL_String<CharT>::compare_aux(iterator first1, iterator last1, iterator first2, iterator last2) { int comp; while(first1 != last1 && first2 != last2) { if(strcmp(*first1, *first2) == 0) { comp = 0; continue; } else return strcmp(*first1, *first2); } if(comp == 0 && first1 != last1) return 1; if(comp == 0 && first2 != last2) return -1; } template<typename CharT> void ZSL_String<CharT>::assign_aux(iterator first, iterator last) { size_type s = last - first; if(s <= capacity()) { clear(start, finish); while(s--) construct(finish, *first++); } else { deallocate(); start = allocator(s); finish = start; while(s--) construct(finish, *first++); end_of_storage = finish; } } template<typename CharT> void ZSL_String<CharT>::resize(size_type count) { if(count <= size()) { while(finish != (start + count)) { --finish; destroy(finish); } } if(count > capacity()) { iterator new_start = allocator(count); finish = new_start; for(int i = 0; i < size(); ++i) *finish++ = start[i]; deallocate(); start = new_start; end_of_storage = start + count; } } template<typename CharT> void ZSL_String<CharT>::resize(size_type count, const CharT& c) { if(count <= size()) { while(finish != (start + count)) { --finish; destroy(finish); } } else if(count <= capacity()) { while(finish != (start + count)) { *finish = c; ++finish; } } else { iterator new_start = allocator(count); finish = new_start; for(int i = 0; i < size(); ++i) *finish++ = start[i]; for(int i = size(); i < count; ++i) *finish++ = c; deallocate(); start = new_start; end_of_storage = finish; } } template<typename CharT> ZSL_String<CharT> operator+ (ZSL_String<CharT>& str1, ZSL_String<CharT>& str2) { str1.append(str2); return str1; } template<typename CharT> ZSL_String<CharT> operator+ (CharT& c, ZSL_String<CharT>& str) { ZSL_String<CharT> tmp(c); tmp.append(str); return tmp; } template<typename CharT> ZSL_String<CharT> operator+ (ZSL_String<CharT>& str, CharT& c) { str.push_back(c); return str; } template<typename CharT> ZSL_String<CharT> operator+ (CharT* str1, ZSL_String<CharT>& str2) { ZSL_String<CharT> newStr(str1); newStr.append(str2); return newStr; } template<typename CharT> ZSL_String<CharT> operator+ (ZSL_String<CharT>& str1, CharT* str2) { str1.append(str2); return str1; } template<typename CharT> bool operator== (const ZSL_String<CharT>& str1, const ZSL_String<CharT>& str2) { return str1.compare(str2) == 0; } template<typename CharT> bool operator!= (const ZSL_String<CharT>& str1, const ZSL_String<CharT>& str2) { return !(str1 == str2); } template<typename CharT> bool operator< (const ZSL_String<CharT>& str1, const ZSL_String<CharT>& str2) { return str1.compare(str2) == -1; } template<typename CharT> bool operator> (const ZSL_String<CharT>& str1, const ZSL_String<CharT>& str2) { return str1.compare(str2) == 1; } template<typename CharT> bool operator<= (const ZSL_String<CharT>& str1, const ZSL_String<CharT>& str2) { return (str1.compare(str2) == -1) || (str1.compare(str2) == 0); } template<typename CharT> bool operator>= (const ZSL_String<CharT>& str1, const ZSL_String<CharT>& str2) { return !(str1 <= str2); } #endif //__ZSL_String__