当前位置: 首页 > ai >正文

C++STL-sting类的模拟实现

默认成员函数

构造函数

string(const char* str = "")
{_size = strlen(str);_capacity = _size;_str = new char[_capacity + 1];//开辟容量加1空间,用于存放"\0"strcpy(_str, str);//将空字符串拷贝到新开的空间中
}

拷贝构造函数

要注意写成深拷贝

传统写法

开辟一块能容纳原字符串的空间,在把原字符串拷贝过去,成员变量也赋值过去即可

string(const string& s):_str(new char[s._capacity + 1]),_size(0),_capacity(0)
{strcpy(_str, s._str);_size = s._size;_capacity = s._capacity;
}

现代写法

构造出的tmp对象与要被拷贝的对象数据交换即可

string(const string& s):_str(nullptr), _size(0), _capacity(0)
{string tmp(s._str);//调用构造函数构造tmpswap(tmp);
}

赋值运算符重载函数

传统写法

string& operator=(const string& s)
{if (this != &s)//防止自己给自己赋值{delete[] _str;_str = new char[s._capacity + 1];strcpy(_str, s._str);_size = s._size;_capacity = s._capacity;}return *this;//返回左值,支持连续赋值
}

现代写法1

string& operator=(string s)//编译器接受右值自动调用拷贝构造
{swap(s);return *this;
}

现代写法2

多了一个防止自己给自己赋值

string& operator=(const string& s)
{if (this != &s){string tmp(s);swap(tmp);}return *this;}

析构函数

~string()
{delete[] _str;//释放指向的空间_str = nullptr;_size = 0;_capacity = 0;
}

迭代器相关函数

起别名

typedef char* iterator;
typedef const char* const_iterator;

begin和end

iterator begin()
{return _str;//返回字符第一个地址
}const_iterator begin()const
{return _str;
}
iterator end()
{return _str + _size;//返回最后一个字符后一个字符的地址
}const_iterator end()const
{return _str + _size;
}

容量和大小相关函数

用成员函数来获取成员变量

size

size_t size()const
{return _size;//返回字符串有效长度(不包括"/0")
}

capacity

size_t capacity()const
{return _capacity;//返回字符串容量
}

reserve和resize

reserve规则:

1.n>capacity,capacity扩大到n倍;

2.n<capacity,不操作

void reserve(size_t n)
{if (n > _capacity){char* tmp = new char[n + 1];//多开一个空间存放"/0"strncpy(tmp, _str, _size + 1);//将原字符串拷贝过去,包括"\0"delete[] _str;//释放原来空间_str = tmp;//新开辟的空间改名_capacity = n;//capacity更新为n}
}

resize规则:

1.n>size,将size扩大到n

2.n<size,将size减小到n

	void resize(size_t n,char ch='\0'){if (n <= _size){_size = n;_str[_size] = '\0';}else{if (n > _capacity){reserve(n);}for (size_t i = _size; i < n; i++)//将size扩大到n,扩大的字符为ch{_str[i] = ch;}_size = n;_str[_size] = '\0';}}

empty

strcmp函数用来比较两个字符串大小,相等返回0

bool empty()
{return strcmp(_str, "") == 0;
}

修改字符串相关函数

push_back

尾插字符

void push_back(char ch)//追加字符
{if (_size == _capacity)//判断是否需要扩容{reserve(_capacity == 0 ? 4 : _capacity * 2);}_str[_size] = ch;_str[_size+1] = '\0';_size++;//字符串大小加1
}

或者复用insert函数

void push_back(char ch)
{insert(_size, ch);}

append

追加字符串

void append(const char* str)
{size_t len = _size + strlen(str);if (len > _capacity)//判断是否需要扩容{reserve(len);}strcpy(_str + _size, str);//尾插字符串_size = len;//更新_size
}

也能复用insert函数

void append(const char* str)
{insert(_size,str);
}

operator+=

实现字符串与字符之间的尾插调用push_back即可

string& operator+=(char ch)
{push_back(ch);return *this;
}

实现字符串与字符串之间的尾插调用append即可

string& operator+=(const char*str)
{append(str);return *this;
}

insert

在pos位置插入字符

string& insert(size_t pos, char ch)
{assert(pos <= _size);//检查下标是否合法性if (_size == _capacity)//判断是否要扩容{reserve(_capacity == 0 ? 4 : _capacity * 2);}char* end = _str + _size;while (end >= _str + pos)//pos位置之后向后移动一位{*(end + 1) = *end;}_str[pos] = ch;//在pos位置放置字符_size++;//更新sizereturn *this;
}

在pos位置插入字符串

erase

string& erase(size_t pos, size_t len = npos)
{assert(pos < _size);size_t n = _size - pos;if (len >= n)//pos位置之后都要被删掉{_size = pos;_str[_size] = '\0';}else{strcpy(_str + pos, _str + pos + len);//需要保留的字符往前覆盖_size -= len;}return *this;//支持链式调用
}

clear

	void clear(){_size = 0;_str[_size] = '\0';}

swap

void swap(string& s)
{::swap(_str, s._str);::swap(_size, s._size);::swap(_capacity, s._capacity);
}

c_str

返回c类型的字符串

const char* c_str()const
{return _str;
}

访问字符串相关函数

operator[]

char& operator[](size_t i)//可读可写
{assert(i < _size);return _str[i];}const char& operator[](size_t i)const//只读
{assert(i < _size);return _str[i];
}

find

正向查找第一个字符

size_t find(char ch, size_t pos = 0)
{assert(pos < _size);for (size_t i = pos;i<_size; i++){if (ch == _str[i]){return i;}}return npos;
}

正向查找第一个字符串

size_t find(const char* str, size_t pos = 0)
{assert(pos < _size);const char* ret = strstr(_str + pos, str);if (ret){return ret - _str;}else{return npos;}
}

 refind(调用find函数实现)

反向查找第一个匹配到的字符

size_t rfind(char ch, size_t pos = npos)
{string tmp(*this);//拷贝构造对象tmpreverse(tmp.begin(), tmp.end());if (pos >= _size){pos = _size - 1;}pos = _size - 1 - pos;//镜像对称possize_t ret =tmp.find(ch, pos);if (ret != npos)return _size - 1 - ret;elsereturn npos;
}

反向查找第一个匹配到的字符串

size_t rfind(const char* str, size_t pos = npos)
{string tmp(*this);//逆置字符串reverse(tmp.begin(), tmp.end());//逆置要查找的字符size_t len = strlen(str);char* arr = new char[len + 1];strcpy(arr, str);size_t left = 0,right = len - 1;while (left < right){::swap(arr[left], arr[right]);left++;right--;}if (pos >=_size){pos = _size - 1;}pos = _size - 1 - pos;size_t ret = tmp.find(arr, pos);delete[] arr;if (ret != npos)return _size - len - ret;elsereturn npos;}

关系运算符重载函数

//>运算符重载
bool operator>(const string& s)const
{return strcmp(_str, s._str)>0;
}//==运算符重载
bool operator=(const string& s)const
{return strcmp(_str, s._str) == 0;
}

 复用以上两个函数

	//>=bool operator>=(const string& s)const{return (*this > s) || (*this == s);}//<bool operator<(const string& s)const{return !(*this >= s);}//<=bool operator<=(const string& s)const{return !(*this > s);}//!=bool operator!=(const string& s)const{return !(*this ==s);}

>>和<<运算符重载以及getline函数

istream& operator>>(istream& in, string& s)
{s.clear();//清空字符串char ch = in.get();while (ch != ' ' && ch != '\n'){s += ch;追加字符ch = in.get();}return in;//支持连续输入
}ostream& operator<<(ostream& out, const string& s)
{for (auto e : s){cout << e;}return out;
}

getline

读取一行含有空格的字符串

istream& getline(istream& in, string& s)
{s.clear();char ch = in.get();while (ch != '\n'){s += ch;ch = in.get();}return in;
}

http://www.xdnf.cn/news/12124.html

相关文章:

  • nginx.conf配置详解:从(413 Request Entity Too Large)说起
  • Scrum基础知识以及Scrum和传统瀑布式开发的区别
  • 计算机磁盘旁黄色警示标志消除|BitLocker关闭方法
  • <论文>(微软)WINA:用于加速大语言模型推理的权重感知神经元激活
  • 众趣科技与我爱我家达成战略合作:AI空间计算技术赋能重塑房产服务新范式
  • 服务器安装软件失败或缺依赖怎么办?
  • 使用vue3+ts+input封装上传组件,上传文件显示文件图标
  • 【试卷篇】Spring面试试卷题
  • POP3、IMAP、SMTP:三大邮件协议核心差异与应用场景解析
  • IO流听不懂?如何快速上手
  • 解读《网络安全法》最新修订,把握网络安全新趋势
  • 理解电池的极化:极化内阻与欧姆内阻解析
  • 在NLP文本处理中,将字符映射到阿拉伯数字(构建词汇表vocab)的核心目的和意义
  • 网络原理3—TCP 2
  • 数据驱动的智驾十年 特斯拉、Momenta合流闯进Robotaxi卫冕之战
  • 使用 Docker Compose 安装 PostgreSQL 16
  • css实现文字颜色渐变
  • 直线导轨微型化技术难点在哪里?
  • python项目中,。 __all__ = [‘StorageConfig‘] 这个__all__ 代表什么含义
  • uboot移植之GPIO上电初始状态的调整
  • HarmonyOS-ArkUI 自定义弹窗
  • 企业im,为企业设计的私有化即时通讯工具
  • [蓝桥杯]修改数组
  • 智慧充电:新能源汽车智慧充电桩的发展前景受哪些因素影响?
  • 塑料回收新突破!Nature 重磅:2 小时解聚碳纤维废料
  • 筑牢企业网管域安全防线,守护数字核心——联软网管域安全建设解决方案
  • SEO长尾关键词优化实战解析
  • AMFCNN-RKD:齿轮故障诊断的轻量级多传感器融合模型详解(python代码复现)
  • pbootcms文章加了浏览权限后出现404错误
  • 【芯片仿真中的X值:隐藏的陷阱与应对之道】