首页 > 作文

关于C++STL string类的介绍及模拟实现

更新时间:2023-04-07 20:36:50 阅读: 评论:0

目录

一、标准库中的string类

1.string类

字符串的表示字符序列的类
标准的字符串类提供了对此类对象的支持,其接口类似于标准字符容器的接口,但添加了专门用于操作
单字节字符字符串的设计特性。
string类是使用char(即作为它的字符类型,使用它的默认char_traits和分配器类型(关于模板的更多信
息,请参阅basic_string)。
string类是basic_string模板类的一个实例,它使用char来实例化basic_string模板类,并用char_traits
和allocator作为basic_string的默认参数(根于更多的模板信息请参考basic_string)。
注意,这个类独立于所使用的编码来处理字节:如果用来处理多字节或变长字符(如utf-8)的序列,这个
类的所有成员(如长度或大小)以及它的迭代器,将仍然按照字节(而不是实际编码的字符)来操作。

2.string类中的常用接口说明+模拟实现

2.1 string类对象的常见构造+模拟实现

代码演示:

#include<iostream>#include<string>using namespace std;int main(){ string s1; string s4("hello world"); string s5("hello world", 7); string s6(10, 'x'); string s2(s4); string s3(s4, 6, 3); cout << "s1:"<< s1.c_str() << endl; cout << "s4:" << s4.c_str() << endl; cout << "s5:" << s5.c_str() << endl; cout << "s6:" << s6.c_str() << endl; cout << "s2:" << s2.c_str() << endl; cout << "s3:" << s3.c_str() << endl; }

运行结果:

模拟实现

由于上面有些接口不常用,所以我就模拟实现了一部分常用的接口

string (const char* s)

namespace cxy{ class string { public:  string(const char*s = "")  {   if (s==nullptr)    return;   _size = strlen(s);   _capacity = _size;   _str = new char[_capacity + 1];   strcpy(_str, s);  }    const char* c_str()  {   return _str;  } private:  size_t _size;  size_t _capacity;  char* _str; };}

string (const string& str)
void swap (string& str)

namespace cxy{ class string { public:  void swap(string& str)  {  //下面的swap会调用库里面的接口   ::swap(_size, str._size);   ::swap(_capacity, st爱图片r._capacity);   ::swap(_str, str._str);  }  string(const char*s = "")  {   if (s==nullptr)    return;   _size = strlen(s);   _capacity = _size;   _str = new char[_capacity + 1];   strcpy(_str, s);  }  string(const string& str)   :_str(nullptr), _size(0), _capacity(0)  {   string tmp(str._str);   swap(tmp);  }  char* c_str()  {   return _str;  } private:  size_t _size;  size_t _capacity;  char* _str; };}

2.2 string类对象的容量操作+模拟实现

代码演示:

int main(){ string s1("hello world"); cout <<"s1.size(): " <<s1.size() << endl; cout <<"s1.length(): "<< s1.length() << endl; cout <<"s1.capacity(): "<<s1.capacity() << endl; cout <<"s1:"<< s1 << endl; cout << endl; s1.clear(); cout <<"s1:"<< s1 << endl; cout << "s1.size(): " << s1.size() << endl; cout << "s1.capacity(): " << s1.capacity() << endl; cout << endl; s1 = "hello world"; cout << "s1:" << s1 << endl; cout << "s1.size(): " << s1.size() << endl; cout << "s1.capacity(): " << s1.capacity() << endl; s1.resize(17,'x'); //当n>capacity,则扩容,并且把0~27上位置的空余位置填充‘字符' cout << "s1:" << s1 << endl; cout << "s1.size(): " << s1.size() << endl; cout << "s1.capacity(): " << s1.capacity() << endl; s1.resize(27, 'x'); //当size<n<capacity,则把0~27上位置的空余位置填充‘字符' cout << "s1:" << s1 << endl; cout << "s1.size(): " << s1.size() << endl; cout << "s1.capacity(): " << s1.capacity() << endl; s1.resize(5, 'x'); //当n<size,则只保留n个‘字符',空间大小不变 cout << "s1:" << s1 << endl; cout << "s1.size(): " << s1.size() << endl; cout << "s1.capacity(): " << s1.capacity() << endl; cout << endl; string s2("hello world"); s2.rerve(5); //当n<=capacity时,空间大小不变,且不改变数据内容 cout << "s2:" << s2 << endl; cout << "s2.size(): " << s2.size() << endl; cout << "s2.capacity(): " << s2.capacity() << endl; s2.rerve(100); //当n>capacity时,空间会增大 cout << "s2:" << s2 << endl; cout << "s2.size(): " << s2.size() << endl; cout << "s2.capacity(): " << s2.capacity() << endl;}

运行结果:

得知:

rerve和resize的区别:rerve不会影响内容,resize会影响内容。

模拟实现

size_t size() const
返回字符串的有效长度

namespace cxy{ class string { public:  size_t size()const  {   return _size;  } private:  size_t _size;  size_t _capacity;  char* _str; };}

size_t capacity() const
返回空间的大小

namespace cxy{ class string { public:  size_t capacity()const  {   return _capacity;  } private:  size_t _size;  size_t _capacity;  char* _str; };}

bool empty() const
检测字符串优师助手释放为空串,是返回true,否则返回fal

namespace cxy{ class string { public:  bool empty()const  {   return _str == 0;  } private:  size_t _size;  size_t _capacity;  char* _str; };}

void clear()
清空有效字符 ,不会改变容量

namespace cxy{ class string { public:  void clear()  {   _size = 0;   _str[_size] = '
namespace cxy{class string{public:void clear(){_size = 0;_str[_size] = '\0';}private:size_t _size;size_t _capacity;char* _str;};}
'; } private: size_t _size; size_t _capacity; char* _str; };}

void rerve (size_t n = 0)
请求改变容量 ,此功能对字符串长度没有影响,无法改变其内容

如果 n 大于当前字符串容量,则该金刚藤的功效与作用函数会导致容器将其容量增加到 n 字符(或更大)
n小于当前字符串容量时,不会发生改变

namespace cxy{ class string { public:  void rerve(size_t n=0)  {   if (n > _capacity)   {    char *tmp = new char[n + 1];    st北京八中少年班rncpy(tmp,_str,_size+1);    delete[]_str;    _str = tmp;    _capacity = n;   } private:  size_t _size;  size_t _capacity;  char* _str; };}

补充:strncpy是c语言中的函数

char * strncpy ( char * destination, const char * source, size_t num )

功能:

将source中的字符串复制到destination中,且复制num个字符个数,如果在没有复制完num个字符之前,找到了source的末尾,则目标填充零,直到向其编写了总共num字符。如果来source中的字符有效长度大于数字,则目的地末尾不会隐含任何空字符(’\0’)。因此,在这种情况下,目的地不应被视为无效终止的 c 字符串(因此读取它将溢出,所以这种时候记得要在末尾添加’\0’)。

void resize (size_t n, char c)
void resize (size_t n)
将有效字符的个数该成n个,多出的空间用字符c填充

将字符串大小重新变为n字符的长度。如果 n 小于当前字符串长度,则当前值将缩短为其第一个 n 字符,从而删除 n 之外的字符。如果 n 大于当前字符串长度,则通过在末尾插入尽可能多的字符c以达到 n 的大小来扩展当前内容。如果指定c,则新元素初始化为c的副本,否则,它们是值初始化字符(空字符)。
namespace cxy{ class string { public:  void resize(size_t n,char c='
namespace cxy{class string{public:void resize(size_t n,char c='\0'){if (n<_size){_size = n;_str[_size] = '\0';}el{  if (n > _capacity){rerve(n);}memt(_str + _size, c, n - _size);   _size = n;_str[_size] = '\0';}private:size_t _size;size_t _capacity;char* _str;};}
') { if (n<_size) { _size = n; _str[_size] = '
namespace cxy{class string{public:void resize(size_t n,char c='\0'){if (n<_size){_size = n;_str[_size] = '\0';}el{  if (n > _capacity){rerve(n);}memt(_str + _size, c, n - _size);   _size = n;_str[_size] = '\0';}private:size_t _size;size_t _capacity;char* _str;};}
'; } el { if (n > _capacity) { rerve(n); } memt(_str + _size, c, n - _size); _size = n; _str[_size] = '
namespace cxy{class string{public:void resize(size_t n,char c='\0'){if (n<_size){_size = n;_str[_size] = '\0';}el{  if (n > _capacity){rerve(n);}memt(_str + _size, c, n - _size);   _size = n;_str[_size] = '\0';}private:size_t _size;size_t _capacity;char* _str;};}
'; } private: size_t _size; size_t _capacity; char* _str; };}

补充:memt是c语言中的函数

void * memt ( void * ptr, int value, size_t num )

功能:

将value传到prt中,以第一个位置开始传,传num个,传完为止。

总结

size()与length()方法底层实现原理完全相同,引入size()的原因是为了与其他容器的接口保持一致,一般情况下基本都是用size()。clear()只是将string中有效字符清空,不改变底层空间大小。resize(size_t n) 与 resize(size_t n, char c)都是将字符串中有效字符个数改变到n个,不同的是当字符个数增多时:resize(n)用0来填充多出的元素空间,resize(size_t n, char c)用字符c来填充多出的元素空间。注意:resize在改变元素个数时,如果是将元素个数增多,可能会改变底层容量的大rerve(size_t res_arg=0):为string预留空间,不改变有效元素个数,当rerve的参数小于string的底层空间总大小时,rerver不会改变容量大小。

2.3 string类对象的访问及遍历操作+模拟实现

代码演示:

int main(){ string s("hello world"); cout << "operator[] :"; for (size_t i = 0; i < s.size(); i++)  cout << s[i] ; cout << endl; //迭代器 string::iterator it = s.begin(); cout << "iterator :"; while (it != s.end()) {  cout << *it ;  ++it; } cout << endl; //范围for cout << "范围for :"; for (auto ch : s) {  cout << ch ; } cout << endl;}

模拟实现

const char& operator[] (size_t pos) const

namespace cxy{ class string { public:  const char& operator[](size_t pos)const  {   asrt(pos < _size);   return _str[pos];  } private:  size_t _size;  size_t _capacity;  char* _str; };}

iterator begin() iterator end()

namespace cxy{ class string { public:  typedef char* iterator;    iterator begin()  {   return _str;  }  iterator end()  {   return _str+_size;  } private:  size_t _size;  size_t _capacity;  char* _str; };}

c++11:范围for

在这里不实现,知道怎么用就行

2.4 string类对象的修改操作+模拟实现

代码演示:

int main(){ string s("hello world"); s.push_back('k'); cout << s << endl; s.append("sssss"); cout << s << endl; s += "ff"; cout << s << endl; cout << s.find("kss") << endl; s.era(11, 8); cout << s << endl;}

运行结果:

模拟实现:只实现了一些常用的接口

void push_back (char c)
在字符串后面插入字符c

namespace cxy{ class string { public:  void push_back(char c)  {   if (_size == _capacity)   {    rerve(_capacity * 2);   }   _str[_size] = c;   _str[_size+1] = '
namespace cxy{class string{public:void push_back(char c){if (_size == _capacity){rerve(_capacity * 2);}_str[_size] = c;_str[_size+1] = '\0';_size++;}private:size_t _size;size_t _capacity;char* _str;};}
'; _size++; } private: size_t _size; size_t _capacity; char* _str; };}

string& append (const char*s)
在字符串后面追加字符串s

namespace cxy{ class string { public:  string &append(const char*s)  {   size_t len = strlen(s)+_size;   if (len > _capacity)   {    rerve(len);   }   strncpy(_str + _size, s, len - _size+1);   _size = len;   return *this;  } private:  size_t _size;  size_t _capacity;  char* _str; };}

string& operator+= (const char* s)
在字符串后面追加字符串s

namespace cxy{ class string { public:  string& operator+=(const char*s)  {   append(s);   return *this;  } private:  size_t _size;  size_t _capacity;  char* _str; };}

const char* c_str() const
返回c格式的字符串

namespace cxy{ class string { public:  const char* c_str()const  {   return _str;  } private:  size_t _size;  size_t _capacity;  char* _str; };}

size_t find (const char* s, size_t pos = 0) const
从字符串pos位置开始往后找字符串s,返回该字符串s在字符串中的位置

namespace cxy{ class string { public:  size_t find(const char*s,size_t pos=0)const  {   char *str = _str+pos;   while (*str)   {    char* str_s = str;    const char* tmp = s;    while (*str_s&&*tmp==*str_s)    {     tmp++;     str_s++;    }    if (*tmp=='
namespace cxy{class string{public:size_t find(const char*s,size_t pos=0)const{char *str = _str+pos;while (*str){char* str_s = str;const char* tmp = s;while (*str_s&&*tmp==*str_s){tmp++;str_s++;}if (*tmp=='\0')return str - _str;elstr++;}return -1;}private:size_t _size;size_t _capacity;char* _str;};}
') return str - _str; el str++; } return -1; } private: size_t _size; size_t _capacity; char* _str; };}

string& era (size_t pos = 0, size_t len = npos)
擦除字符串的一部分,减少其长度

static const size_t npos = 0;namespace cxy{ class string { public:  string &era(size_t pos = 0, size_t len = npos)  {   asrt(pos < _size);   if (len+pos >= _size)   {    _str[pos] = '
static const size_t npos = 0;namespace cxy{class string{public:清华大学专业string &era(size_t pos = 0, size_t len = npos){asrt(pos < _size);if (len+pos >= _size){_str[pos] = '\0';_size = pos;}el{strcpy(_str + pos, _str + pos + len);_size -= len;}return *this;}private:size_t _size;size_t _capacity;char* _str;};}
'; _size = pos; } el { strcpy(_str + pos, _str + pos + len); _size -= len; } return *this; } private: size_t _size; size_t _capacity; char* _str; };}

2.5 string类非成员函数+模拟实现

模拟实现

istream& operator>> (istream& is, string& str)

namespace cxy{ class string { public:   private:  size_t _size;  size_t _capacity;  char* _str; };  istream& operator >> (istream& is, string& str) {  str.clear();  char ch;  ch = is.get();  while (ch != ' '&&ch != '
namespace cxy{class string{public:private:size_t _size;size_t _capacity;char* _str;};istream& operator >> (istream& is, string& str){str.clear();char ch;ch = is.get();while (ch != ' '&&ch != '\0'){str += ch;ch = is.get();}return is;}}
') { str += ch; ch = is.get(); } return is; }}

说明一下:这个函数实现放在全局,是因为他的is要和对象str抢第一个位置,如果放在string类里面实现,那么第一个位置是this指针,也就是str对象,在用这个函数的时候就会很变扭。

ostream& operator<< (ostream& os, const string& str);

namespace cxy{ class string { public:   private:  size_t _size;  size_t _capacity;  char* _str; };  ostream& operator<< (ostream& os, string& str) {  for (auto ch:str)  {   os << ch;  }  return os; } }

istream& getline (istream& is, string& str)
获取一行字符串

namespace cxy{ class string { public:   private:  size_t _size;  size_t _capacity;  char* _str; };  istream&getline(istream&is ,string&s) {  s.clear();  char ch;  ch = is.get();  while (ch != '
namespace cxy{class string{public:private:size_t _size;size_t _capacity;char* _str;}; istream&getline(istream&is ,string&s){s.clear();char ch;ch = is.get();while (ch != '\0'){s += ch;ch = is.get();}return is;}}
') { s += ch; ch = is.get(); } return is; }}

到此这篇关于 关于c++stl string类的介绍及模拟实现的文章就介绍到这了,更多相关c++stl string类介绍及模拟实现内容请搜索www.887551.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持www.887551.com!

本文发布于:2023-04-07 20:36:48,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/zuowen/6cef93c4c2d989fedc64c1ec2044f39f.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

本文word下载地址:关于C++STL string类的介绍及模拟实现.doc

本文 PDF 下载地址:关于C++STL string类的介绍及模拟实现.pdf

下一篇:返回列表
标签:字符串   字符   位置   长度
相关文章
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图