C++中string类的模拟实现

3 篇文章 0 订阅

引言:本篇文章主要实现一个自定义字符串类string,包括了字符串的基本操作,如拷贝构造、赋值、添加、删除、查找等,还实现了迭代器,支持基本的 STL 算法。

1.  构造函数:

  • 默认构造函数
  • 从C字符串构造
  • 拷贝构造函数

2.  析构函数

  • 在析构函数中释放内存

3.  访问和修改元素函数:

  • c_str() 返回C字符串
  • size() 返回字符串大小
  • capacity() 返回容量
  • operator[] 访问单个字符

4  查找子串

  • find() 从某个位置查找字串

5.  迭代器相关:

  • begin()  返回开始迭代器
  • end()  返回结束迭代器

6.  修改容量相关:

  • push_back() 尾部插入字符
  • append() 尾部插入字符串
  • reserve() 预留空间
  • resize() 重新设置字串的大小

7.  重载运算符:

  • 实现+=操作符的重载,用于字符串拼接
  • 实现=操作符的重载,用于字符串赋值
  • 重载输出运算符 << 打印字符串

8.  insert()

  • 插入字符

9.  erase()

  • 删除从某个位置后面某长度的字符

10. swap()

  • 交换两个字符串的值

头文件“my_string.h”:

#include <iostream> 
#include <cstring>
#include <assert.h>

using std::cout; 
using std::endl;
using std::cin;

class string{
public:
  typedef char* iterator; // 定义迭代器类型
  
  // 构造函数
  string(const char* str ="");  
  string(const string& str);

  // 析构函数
  ~string();

  // 返回C风格字符串
  char* c_str();

  // 返回字符串长度
  int size()const;

  // 返回容量 
  int capacity()const;

  // 字符访问运算符
  char& operator[](int n);
  const char& operator[](int n)const;

  // 获取首尾迭代器
  iterator begin();
  iterator end();

  // 在尾部插入字符
  void push_back(char c);

  // 连接字符串
  string& append(const string& str);
  string& append(const char* s);
  
  // 扩容
  void reserve(size_t n = 0);

  // +=运算符重载
  string& operator+=(const char c);
  string& operator+=(const char* s);
  string& operator+=(const string& str);

  // 在pos位置插入字符串
  string& insert (size_t pos, const char* s); 
  string& insert (size_t pos, const string& str);

  // 在迭代器p位置插入字符 
  iterator insert (iterator p, char c);

  // 查找子串
  size_t find (const char* s, size_t pos = 0) const;
  size_t find (const string* str,size_t pos = 0) const;

  // 删除字符串的一部分
  string& erase (size_t pos = 0, size_t len = npos);

  // 赋值运算符重载
  string& operator= (const string& str);
  string& operator= (const char* s);
  string& operator= (char c);

  // 改变字符串长度  
  void resize (size_t n, char c='\0');

  // 交换两个字符串内容
  void swap(string& str);
  
private:
  char* _str; // 用于保存字符串
  int _size; // 字符串长度
  int _capacity; // 容量
  static const size_t npos = -1; // 表示找不到
};

// 输出运算符重载
std::ostream& operator<< (std::ostream& out,const string& s);

my_string.cpp

#include "my_string.h"
string::string(const char* str){
    _str = new char[strlen(str)+1];
    strcpy(_str,str);
    _size = strlen(str);
    _capacity = _size;
}
string::string(const string& str)
  :_str(nullptr)
{
  if(&str != this){
    char* tmp = new char[str._size+1];
    strcpy(tmp,str._str);
    delete []_str;
    _str = tmp;
    _size = str._size;
    _capacity = _size;
  }
}
string::~string(){
  delete []_str;
  _str = nullptr;
  _size = 0;
  _capacity = 0;
}
char* string::c_str(){
  return _str;
}
int string::size()const{
  return _size;
}
int string::capacity()const{
  return _capacity;
}
char& string::operator[](int n){
  assert(n<_size);
  return *(_str+n);
}
const char& string::operator[](int n)const{
  assert(n<_size);
  return *(_str+n);
}
string::iterator string::begin(){
  return _str;
}
string::iterator string::end(){
  return _str+_size;
}
void string::push_back(char c){
  if(_size == _capacity){//需要扩容
    _capacity++;
    char* tmp = new char[_capacity+1];
    strcpy(tmp,_str);
    delete [] _str;
    _str = tmp;
  }
  _str[_size] = c;//放入元素
  _size++;
  _str[_size] = '\0';//插入元素后放一个\0
}
string& string::append(const string& str){
  if(_size + str.size() > _capacity){//需要扩容
    reserve(str.size()+_size);//调用reserve,复用
  }
  for(int i = 0;i<str.size();i++){//也可以使用strcpy
    _str[_size++] = str[i];
  }
  _str[_size] ='\0';
  return *this;
}
string& string::append(const char* s){
  int s_size = strlen(s);
  if(s_size+_size > _capacity){
    reserve(s_size + _size);
  }
  strcpy(_str + _size,s);
  _size += s_size;
  return *this;
}
void string::reserve(size_t n ){
  char *tmp = new char[n+1];
  strcpy(tmp,_str);
  delete [] _str;
  _str = tmp;
  _capacity = n;
}
string& string::operator+=(const char c){
  push_back(c);
  return *this;
}
string& string::operator+=(const char* s){
  append(s);
  return *this;
}
string& string::operator+=(const string& str){
  append(str);
  return *this;
}
string::iterator string::insert(string::iterator p,char c){
  assert( p <= end());
  int pos = p - begin();
  if(_size+1>_capacity){//扩容
    reserve(_size+1);
  }
  p = _str + pos;
  for(string::iterator it = end()-1;it >=  p;it--){//往后面移
    *(it+1) = *it;
  }
  *p = c;
  _size ++;
  return p;
}
string& string::insert(size_t pos,const char* s){
  assert(pos<=_size);
  int s_len = strlen(s);
  if(s_len+_size>_capacity){
    reserve(_size+s_len);
  }
  for(int i = _size;i >= (int)pos;i--){
    _str[i+s_len] = _str[i];
  }
  for(int i = 0;i<s_len;i++){
    _str[pos++] = s[i];
  }
  _size = _size+s_len;
  return *this;
}
string& string::insert(size_t pos,const string&str){
  const char* s = str._str;
  return insert(pos,s);
}

size_t string::find (const char* s,size_t pos)const{
  assert(pos<=_size);
  int s_len = strlen(s);
  for(int i = pos;i<_size;i++){
    int flag = 0;//用于判断是否找到字串
    for(int j = 0;j<s_len;j++){
      if(i<_size && s[j] != _str[i+j]){
        flag =1; 
        break;
      }
    }
    if(flag == 0) return i;
  }
  return npos; 
}
size_t string::find (const string* str,size_t pos) const{
  char* s = str->_str;
  return find(s,pos);//复用
}
string& string::erase(size_t pos,size_t len){ 
  assert(pos<_size);//不能在'\0'位置之后的删除
  if(len>=(size_t)_size-pos){
    _size = pos;
    _str[_size] = '\0';
  }else{
  for(int i = pos;i<=_size-(int)len;i++){
     _str[i] = _str[i+len];
  }
  _size = _size - len;
}
return *this;

}
string& string::operator=(const char* s){
  assert(s);
  int s_len = strlen(s);
  reserve(s_len);
  strcpy(_str,s);
  _size = s_len;
  return *this;
}
string& string::operator=(const string& str){
  return operator=(str._str);
}
string& string::operator=(char c){
  reserve(1);
  _str[0] = c;
  _str[1] = '\0';
  _size = 1;
  return *this;
}
void string::resize(size_t n,char c){
  if((int)n>_size){
   reserve(n);
   for(int i = _size;i<(int)n;i++){
      _str[i] = c;
   }
   _size = n;
   _str[_size]='\0';
  }else if((int)n>=0&&(int)n<_size){
    erase(n);
  }
}
void string::swap(string& str){
  if(&str == this) return;//如果交换自己直接返回
  char* tmp = str._str;
  str._str = _str;
  _str = tmp;
  int tmp_s = str._size;
  int tmp_c = str._capacity;
  str._size = _size;
  _size = tmp_s;
  str._capacity = _capacity;
  _capacity = tmp_c;
}
std::ostream& operator<< (std::ostream& out,const string& s){
  for(int i = 0;i<s.size();i++){
    out<<s[i];
  }
  return out;
}

main.cpp

#include "my_string.h"
void test01(){
  string s1("ssssss");
  string s2;
  string s3(s1);
  cout<<s2<<endl;
  for(auto e: s1){
    cout<<e<<"  ";
  }
  cout<<endl;
  s1.push_back('a');
  s1.push_back(' ');
  s1.append("xiaomi ");
  s1.append(s3);
  cout<< s1<<endl;
  s1 +="hhhh";
  s1 +=' ';
  s1 += s3;
  cout<<s1<<endl;
  s1.insert(s1.begin()+2,'c');
  cout<<s1<<endl;
  s3.insert(s3.end()-1,'a');
  cout<<s3<<endl;
  s3.insert(7,"xiaomi");
  cout<<s3<<endl;
  s3.insert(1,s1);
  cout<<s3<<endl;
  int i = s3.find("xiwmi");
  cout<<i<<endl;
  string s4 = "xiaomi";
  cout<< s3.find(&s4)<<endl;
  s4.erase(3,3);
  cout<<s4<<endl;
  s4 = "hyper os";
  cout << s4 << endl;
  string s5;
  s5 = s4;
  cout<<s5<<endl;
  s5 = 'o';
  cout<<s5<<endl;
  s4.resize(11,'6');
  cout<<s4<<endl;
  s1.resize(6);
  cout<<s1<<endl;
  s1.swap(s4);
  cout<<s1<<endl;
  cout<<s4<<endl;
}
int main(){
    test01();
}

测试结果: 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值