C++string的模拟实现

本文详细介绍了如何手动实现一个string类,涵盖了构造、拷贝构造、赋值运算符重载、析构函数等功能,并实现了+=、+、<<运算符重载,以及append、insert、erase、find、popback、pushback、resize、reserve等方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

模拟实现string类

包括string类的构造,拷贝构造,赋值运算符重载,析构函数。还有+=,+,<< 运算符重载,append函数,insert函数,erase函数,find函数,popback函数,pushback函数,resize函数,reserve函数等。

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<string>
using namespace std;

class String 
{
public:
	//迭代器:一种访问容器元素的机制, 体现封装的特性,
 //不需要关注容器的实现细节,就可以直接访问(可读可写)元素
 //使用方式: 类似于指针的操作
 //     1. 解引用--> 获取指向位置的内容
 //     2. 位置移动 --> 执向其他位置
 //string 迭代器: 通过指针实现
 typedef char* iterator;
 typedef const char* const_iterator;
 
 //const和非const都要有
 iterator begin()
 {
  //第一个元素的位置
  return _str;
 }
 
 iterator end()
 {
  //最后一个元素的下一个位置
  return _str + _size;
 }
 
 const_iterator begin() const
 {
  //第一个元素的位置
  return _str;
 }
 
 const_iterator end() const
 {
  //最后一个元素的下一个位置
  return _str + _size;
 }
 
 //默认无参构造
 String()
  :_str(new char[16])  //因为原本得string类默认构造就是15个字节,所以我们申请16字节,最后一个放\0
  , _size(0)
  , _capacity(0)
 {
  _str[_size] = '\0';
 }
 
 //有参数调用这个构造函数
 String(const char* str)
 {
  _size = strlen(str);
  _str = new char[_size + 1];//拷贝原来的字符串
  strcpy(_str, str);
  _capacity = _size;
 }

//返回c风格字符串,也就是字符串首地址
 const char* c_str() const {
  return _str;
 }
 
 ////深拷贝构造
 //String(const String& str)
 // :_str(new char[str._capacity + 1])
 // , _size(str._size)
 // , _capacity(str._capacity)
 //{
 // //深拷贝:资源拷贝
 // strcpy(_str, str._str);
 // cout << "String(const String&)" << endl;
 //}
 
 ////=运算符重载,给它加入深拷贝功能
 //String& operator=(const String& str)
 //{
 // if (this != &str)
 // {
 //  //开空间
 //  char* tmp = new char[str._capacity + 1];
 //  //内容拷贝
 //  strcpy(tmp, str._str);
 //  //释放原有空间
 //  delete[] _str;
 //  _str = tmp;
 //  _size = str._size;
 //  _capacity = str._capacity;
 // }
 // return *this;
 //}
 //以上的深拷贝构造和现代写法的深拷贝构造都可以
 
 //深拷贝构造:现代写法, 代码复用
 String(const String& str)
  :_str(nullptr)
  , _size(0)
  , _capacity(0)
 {
  //调用构造函数
  String tmp(str._str);
  Swap(tmp);
 }
 
 void Swap(String& str)
 {
  swap(_str, str._str);
  swap(_size, str._size);
  swap(_capacity, str._capacity);
 }
 
 //赋值运算符: 现代写法,深拷贝, 代码复用: 拷贝构造(传参进行拷贝构造)
 String& operator=(String str)
 {
  Swap(str);
  return *this;
 }
 
 //析构函数
 ~String()
 {
  if (_str)
  {
   delete[] _str;
   _size = _capacity = 0;
   _str = nullptr;
  }
  cout << "~String" << endl;
 }
 
 //[]运算符重载:可读可写
 char& operator[](size_t pos)
 {
  if (pos < _size)
   return _str[pos];
 }
 
 //[]运算符重载:可读不可写
 const char& operator[](size_t pos) const
 {
  if (pos < _size)
   return _str[pos];
 }
 
 //获取字符串有效长度_size
 size_t size() const
 {
  return _size;
 }
 
 //尾插一个字符
 void pushBack(const char& ch) {
  //检查容量
  if (_size == _capacity) {
   size_t newC = _capacity == 0 ? 15 : 2 * _capacity;
   reserve(newC);
  }
  
  //尾插
  _str[_size] = ch;
  ++_size;
  _str[_size] = '\0';
 }
 
 //重新开辟空间,只增不减
 void reserve(size_t n) {
  if (n > _capacity) {
   //开空间,多一位存\0
   char* tmp = new char[n + 1];
   //拷贝
   strcpy(tmp, _str);
   //释放原有空间
   delete[] _str;
   _str = tmp;
   //更新容量
   _capacity = n;
  }
 }
 
 //find函数
 size_t find(const char* str)
 {
  char* ptr = strstr(_str, str);
  if (ptr)
   return ptr - _str;
  else
   return npos;
 }
 
 //尾插字符串
 void Append(const char* str)
 {
  //int len = strlen(str);
  ////检查容量
  //if (_size + len > _capacity)
  //{
  // reserve(_size + len);
  //}
  ////尾插
  //strcpy(_str + _size, str);
  ////修改size
  //_size += len;
  
  //代码复用
  insert(_size, str);
 }
 
 //+=字符
 String& operator+=(const char& ch)
 {
  pushBack(ch);
  return *this;
 }
 
 //+=字符串
 String& operator+=(const char* str)
 {
  Append(str);
  return *this;
 }
 
 //指定位置插入字符
 void insert(size_t pos, const char& ch)
 {
  if (pos > _size)
   return;
  //检查容量
  if (_size == _capacity)
  {
   size_t newC = _capacity == 0 ? 15 : 2 * _capacity;
   reserve(newC);
  }
  //移动元素[pos, _size]: 从后向前移动,首先移动最右端的字符,防止覆盖
  size_t end = _size + 1;
  //end >= pos: 当pos = 0时, 死循环,访问越界
  while (end > pos)
  {
   _str[end] = _str[end - 1];
   --end;
  }
  //插入
  _str[pos] = ch;
  ++_size;
 }
 
 //指定位置插入字符串
 void insert(size_t pos, const char* str)
 {
  if (pos > _size)
   return;
  int len = strlen(str);
  if (_size + len > _capacity)
  {
   reserve(_size + len);
  }
  //移动元素[pos, _size]
  size_t end = _size + len;
  //size --> size + len,  pos ---> pos + len
  while (end > pos + len - 1)
  {
   _str[end] = _str[end - len];
   --end;
  }
  //插入
  for (int i = 0; i < len; ++i)
  {
   _str[i + pos] = str[i];
  }
  _size += len;
 }
 
 //重新设置有效长度的函数
 void resize(size_t n, const char& ch = '\0')
 {
  if (n > _capacity)
  {
   reserve(n);
  }
  if (n > _size)
  {
   memset(_str + _size, ch, n - _size);
  }
  _size = n;
  _str[_size] = '\0';
 }
 
 //尾删一个字符
 void popBack()
 {
  erase(_size - 1, 1);
 }
 
 //删除函数:从pos开始删除len个字符
 void erase(size_t pos, size_t len)
 {
  if (pos < _size)
  {
   //判断删除的长度是否大于从pos位置开始的剩余字符串的长度
   if (pos + len >= _size)
   {
    _size = pos;
    _str[_size] = '\0';
   }
   else
   {
    //移动元素[pos + len, size]  ---> [pos, size - len]: 从后往前移动
    for (int i = pos + len; i <= _size; ++i)
    {
     _str[pos++] = _str[i];
    }
    _size -= len;
   }
  }
 }
 
 private:
 char* _str;
 size_t _size;
 size_t _capacity;
public:
 static const size_t npos;
};

const size_t String::npos = -1;

//+string类对象
String operator+(const String& s, const String& str)
{
 String ret(s);
 ret += str.c_str();
 return ret;
}
//+字符串
String operator+(const String& s, const char* str)
{
 String ret(s);
 ret += str;
 return ret;
}
//+字符
String operator+(const String& s, const char& ch)
{
 String ret(s);
 ret += ch;
 return ret;
}

//<<运算符重载:返回值是ostream输出流是为了可以连续输出
ostream& operator<<(ostream& cout, const String& str)
{
 //需要输出的字符个数为size, 不能遇到\0就结束输出
 //cout << str.c_str();
 //1. 范围for
 for (const auto& ch : str)
  cout << ch;
  
  //方式2:用operator[]借助for循环遍历
 //for (int i = 0; i < str.size(); ++i)
 // cout << str[i];
 
 ////方式3:迭代器
 //String::const_iterator it = str.begin();
 //while (it != str.end())
 //{
 // cout << *it;
 // ++it;
 //}
 
 return cout;
}

//打印函数
void printString(const String& str)
{
 //迭代器遍历
 String::const_iterator it = str.begin();
 while (it != str.end())
 {
  cout << *it << " ";
  //只读迭代器不支持写操作
  //*it = '0';
  ++it;
 }
 cout << endl;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值