⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 str.cpp

📁 自编的一个String类
💻 CPP
📖 第 1 页 / 共 3 页
字号:
// character string manipulation library// Copyright (c) R B Davies 1996// The is a string library that is intended to be compatible with the// "class string" library in the April 1995 draft of the C++ standard.// Parts are based on Tony Hansen s "The C++ Answer Book"#define WANT_STREAM#define WANT_MATH#define WANT_STRING#include "include.h"#include "str.h"//******************************* globals ********************************uint String::npos = (uint)(-1);                        // also initialised to -1 by StringPackageInitialiseuint String::s_index;StrNull* String::ASN;// string bodiesconst char* String::StringType() const { return px->StringType(); }StrBase* String::Clone() const { return px->Clone(&(StrBase*&)px); }unsigned int String::refcount() const { return px->refcount(); }void String::CleanUp() { if (px) px->Drop(); px = ASN; }StrRep* String::GetStrRep() const   { return px->GetStrRep(&(StrBase*&)px); }StrRep* String::GetStrRepW() { return px->GetStrRepW(&px); }char* String::GetData() const { return GetStrRep()->s; }StrRep* String::Protect() const { return px->Protect(&(StrBase*&)px); }bool String::HasCapacity() const { return px->HasCapacity(); }String::String(StrBase* sb) : px(sb) {}String::String() : px(ASN) {}String::String(const String& str) { px = ASN; px = str.Clone(); }String::String(const String& str, uint pos, uint n){   px = ASN;                            // in case of later failure   StrRep* str_p = str.GetStrRep();   uint sz = str.size();   if (pos > sz) Throw(Out_of_range("string index error\n"));   sz -=  pos;                          // length of new string   if (n < sz) sz = n;   if (sz == 0) px = ASN;   else px = new StrRepMult(str_p->s+pos, sz);}String::String(const char* s, uint n){   px = ASN;                            // in case of later failure   if (!s) Throw(Invalid_argument("string constructor: char* s = 0\n"));   uint sz = 0; const char* S = s;   while (*S++) { if (sz >= n) break; sz++; }   if (sz == 0) px = ASN;   else px = new StrRepMult(s, sz);}String::String(const char* s){   px = ASN;                            // in case of later failure   if (!s) Throw(Invalid_argument("string constructor: char* s = 0\n"));   uint sz = strlen(s);   if (sz == 0) px = ASN;   else px = new StrRepMult(s, sz);}String::String(uint n, char c){   px = ASN;                            // in case of later failure   if (n == npos) Throw(Length_error("string length = npos\n"));   if (n == 0) px = ASN;   else if (n == 1) px = new CharSingle(c);   else px = new CharRepeated(n, c);}String::~String() { if (px) px->Drop(); }// do the operator= separately from assign because we do not ever// want to just copy into existing memory space. ie we do not// maintain capacity when we use operator= .String& String::operator=(const String& str)   { StrBase* p = px; px = str.Clone(); p->Drop(); return *this; }String& String::operator=(const char* s){   StrBase* p = px;   if (strlen(s) == 0) px = ASN;   else px = new StrRepMult(s);   p->Drop(); return *this;}String& String::operator=(const char c){   px->Drop(); px = new CharSingle(c);   return *this;}uint String::size() const { return px->size(); }uint String::length() const { return px->size(); }uint String::max_size() const { return npos-1; }void String::resize(uint n, char c){   if (n == npos) Throw(Length_error("string length = npos\n"));   if (n == 0) { px->Drop(); px = ASN; return; }   StrRep* p = GetStrRep();   if (n <= p->sz) px = new StrRepMult(p->s, n);   else px = new StrRepMult(p->s, p->sz, n, c);   p->Drop();}uint String::capacity() const { return px->capacity(); }void String::reserve(uint res_arg){   if (res_arg == 0)                        // remove capacity   {      StrRep* p = new StrRepMult(size());      char* target = p->s; px->Load(target); px->Drop(); px = p;   }   else if ( res_arg > size() || capacity() != size() )                                            // need to change storage   {      if (res_arg < size()) res_arg = size();      StrRep* p = new StrRepCap(size(), res_arg);      char* target = p->s; px->Load(target); px->Drop(); px = p;   }   else px->WithCapacity(&(StrBase*&)px);   // convert to string with capacity}void String::clear() { if (px) px->Drop(); px = ASN; }bool String::empty() const { return px->size() == 0; }char String::operator[](uint pos) const{   StrRep* p = GetStrRep();   if (pos >= p->size())   {      if (pos == p->size()) return 0;      else Throw(Out_of_range("string index error\n"));   }   return (p->s)[pos];}char& String::operator[](uint pos){   StrRep* p = GetStrRepW();   if (pos >= p->size()) Throw(Out_of_range("string index error\n"));   return p->s[pos];}char String::at(uint n) const{   StrRep* p = GetStrRep();   if (n >= p->size())   {      if (n == p->size()) return 0;      else Throw(Out_of_range("string index error\n"));   }   return p->s[n];}char& String::at(uint n){   StrRep* p = GetStrRepW();   if (n >= p->size()) Throw(Out_of_range("string index error\n"));   return p->s[n];}//******************** the line editing functions ************************String& String::operator+=(const String& rhs) { return append(rhs); }String& String::operator+=(const char* s) { return append(s); }String& String::operator+=(char c){   if (HasCapacity()) return my_append(CharSingle(c));   else   {      if (size() >= npos - 1) Throw(Length_error("string length >= npos\n"));      px = new StrSumRC(px ,c);      return *this;   }}String& String::my_append(const StrBase& sb){   StrRep* p = GetStrRep();   uint sz = size(); uint rlen =sb.size();   if (sz >= npos - rlen) Throw(Length_error("string length >= npos\n"));   rlen += sz;   if (rlen > capacity() || refcount() != 0)   {      // must make new string      StrRep* oldp = p; p = new StrRepMult(rlen);      memcpy(p->s, oldp->s, sz); oldp->Drop(); px = p;   }   char* target = p->s+sz; sb.Load(target); p->sz = rlen; return *this;}String& String::append(const String& str){   if (HasCapacity()) return my_append(CharSeq(str));   else   {      if (size() >= npos - str.size())         Throw(Length_error("string length >= npos\n"));      px = new StrSum(px, str.Clone());      return *this;   }}String& String::append(const String& str, uint pos, uint n){   if (HasCapacity()) return my_append(CharSeq(str, pos, n));   else   {      CharSeq CS(str, pos, n);      if (size() >= npos - CS.sz)         Throw(Length_error("string length >= npos\n"));      StrBase* rhs = new StrRep(CS.s, CS.sz);      px = new StrSum(px, rhs);      return *this;   }}String& String::append(const char* s, uint n){   if (HasCapacity()) return my_append(CharSeq((char*)s, n));   else   {      StrBase* rhs = new StrRep(s, n);      if (size() >= npos - rhs->size())      {         delete rhs;         Throw(Length_error("string length >= npos\n"));      }      px = new StrSum(px, rhs);      return *this;   }}String& String::append(const char* s){   if (HasCapacity()) return my_append(CharSeq((char*)s));   else   {      StrBase* rhs = new StrRep(s);      if (size() >= npos - rhs->size())      {         delete rhs;         Throw(Length_error("string length >= npos\n"));      }      px = new StrSum(px, rhs);      return *this;   }}String& String::append(uint n, char c){   if (size() >= npos - n)      Throw(Length_error("string length >= npos\n"));   if (HasCapacity()) return my_append(CharRepeated(n, c));   else if (n == 1)   {      px = new StrSumRC(px ,c);   }   else   {      StrBase* rhs = new CharRepeated(n, c);      px = new StrSum(px, rhs);   }   return *this;}// assign with argument being all or part of the target string// should not be a problem under HasCapacity since Load uses// memmove.String& String::assign(const String& str){   if (HasCapacity() && str.size() <= capacity())   {      StrRep* p = GetStrRep(); char* target = p->s;      str.px->Load(target); p->sz = str.size();   }   else if (px != str.px) { px->Drop(); px = str.Clone(); }   return *this;}String& String::my_assign(const StrBase& sb){   uint sz = sb.size(); StrRep* p;   if (HasCapacity() && sz <= capacity())   {      p = GetStrRep(); char* target = p->s;      sb.Load(target); p->sz = sz; return *this;   }   else if (sz == 0) p = ASN;   else   {      p = new StrRepMult(sb.size());      char* target = p->s; sb.Load(target);   }   px->Drop(); px = p; return *this;}String& String::assign(const String& str, uint pos, uint n)   { return my_assign(CharSeq(str, pos, n)); }String& String::assign(const char* s, uint n)   { return my_assign(CharSeq((char*)s, n)); }String& String::assign(const char* s)   { return my_assign(CharSeq((char*)s)); }String& String::assign(uint n, char c)   { return my_assign(CharRepeated(n, c)); }String& String::my_insert(uint pos, const StrBase& sb){   uint sz = size(); uint rlen =sb.size();   if (pos > sz) Throw(Out_of_range("string index error\n"));   if (sz >= npos - rlen) Throw(Length_error("string length >= npos\n"));   StrRep* oldp = GetStrRep();   if (HasCapacity() && sz + rlen <= capacity())   {      // must allow for possibility that sb is part of *this      char* target = oldp->s + pos;      StrRep tail(target, sz-pos);      sb.Load(target); tail.Load(target); oldp->sz = sz + rlen;   }   else   {      StrRep* p = new StrRepMult(sz + rlen); px = p;      char* target = p->s; memcpy(target, oldp->s, pos);      target += pos; sb.Load(target);      memcpy(target, oldp->s + pos, sz-pos);      oldp->Drop();   }   return *this;}String& String::insert(uint pos1, const String& str)   { return my_insert(pos1, *(str.px)); }String& String::insert(uint pos1, const String& str, uint pos2, uint n)   { return my_insert(pos1, CharSeq(str, pos2, n)); }String& String::insert(uint pos, const char* s, uint n)   { return my_insert(pos, CharSeq((char*)s, n)); }String& String::insert(uint pos, uint n, char c)   { return my_insert(pos, CharRepeated(n, c)); }String& String::erase(uint pos, uint n){

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -