【c++】string模拟实现(2)

简介: 【c++】string模拟实现(2)

运算符重载比较函数

bool operator==(const string& s1, const string& s2)
  {
    return strcmp(s1.c_str(), s2.c_str())==0;
  }
  bool operator>(const string& s1, const string& s2)
  {
    return strcmp(s1.c_str(), s2.c_str());
  }
  bool operator<(const string& s1, const string& s2)
  {
    return  !(s1 > s2 && s1 == s2);
  }
  bool operator<=(const string& s1, const string& s2)
  {
    return  !(s1 > s2);
  }
  bool operator>=(const string& s1, const string& s2)
  {
    return  !(s1 < s2);
  }
  bool operator!=(const string& s1, const string& s2)
  {
    return  !(s1 == s2);
  }

注意这里为什么要搞成全局的呢??

void test10()
  {
    string str1;
    string str2;
    str1 += "abc";
    str2 += "aba";
    cout << (str1 == str2) << endl;
    cout << ("aba" == str2) << endl;//2
    cout << (str2== "aba") << endl;
  }

因为第二种的话不满足类成员做左操作数,全局的话就可以,而第三个是会搞一个类型转换.

void test10()
  {
    string str1;
    string str2;
    str1 += "abc";
    str2 += "aba";
    cout << (str1 == str2) << endl;
    cout << ("aba" == str2) << endl;
    cout << (str2== "aba") << endl;
     cout << (str1>str2) << endl;
     cout << (str1 >=str2) << endl;
     cout << (str1<str2) << endl;
     cout << (str1 <=str2) << endl;
     cout << (str1!=str2) << endl;
  }


运算符重载流插入

ostream& operator<<(ostream& out, const string& s)
  {
    for (auto e : s)//遍历一个一个输出
    {
      out << e;
    }
    return out;
  }

有返回值是为了可以连续流插入

运算符重载流提取

版本一:

istream& operator>>(istream& in, string& s)
  {
    
    char ch;
    
    in >> ch;//读取字符到ch
    while (ch != ' ' && ch != '\n')//读到‘ ’或‘\n’结束输入
    {s += ch;//将ch加进去
      in >> ch;//循环读取
    }
    
return in;
  }

这样写会有一个问题,就是cin和scanf一样默认‘\n’和‘ ’是分割符不会进行读取,所以ch不会是空格或换行,所以陷入死循环.

版本2:

c语言中可以用getchar来读取,而c++中存在get就可以读空格

istream& operator>>(istream& in, string& s)
  {
    
    char ch;
    
    in.get(ch);
    
    
    while (ch != ' ' && ch != '\n')
    {
    
    
      s += ch;
      in.get(ch);
    }
    
      
      
    
    return in;
  }
void test11()
  {
    string str1;
    string str2;
    cin >> str1;//>>str2;//>>str2;
    cout << str1;
    //cout << str1.capacity();
  }


版本3

由于我们在s+=ch,会出现频繁扩容,影响效率,我们应该怎么解决呢??

我们可以提前开好空间,但是不知道应该开多大.假如说我们开128个

istream& operator>>(istream& in, string& s)
  {
    
    char ch;
    
    in.get(ch);
    
    s.reserve(128);
    while (ch != ' ' && ch != '\n')
    {
    
    
      s += ch;
      in.get(ch);
    }
    
      
      
    
    return in;
  }
void test11()
  {
    string str1;
    string str2;
    cin >> str1;//>>str2;//>>str2;
    //cout << str1;
    cout << str1.capacity();
  }

两个数据开128就会有极大的浪费,多一点还好

版本4

istream& operator>>(istream& in, string& s)
  {
    s.clear();//可能我们s里面之前有数据,但是流提取是要覆盖的
    char ch;
    ch = in.get();
    
    char buff[128];
    int i = 0;
    while (ch != ' ' && ch != '\n')
    {
      buff[i++] = ch;
      if (i == 127)
      {
        buff[127] = '\0';
        s += buff;
        i = 0;
      }
      ch = in.get();
    }
    if (i > 0)
    {
      buff[i] = '\0';
      s += buff;
    }
    return in;
  }

这里感觉可以类比冯诺依曼体系,buff就相当于内存,先将输入的值放在内存buff里面,等到装满了,在一次性给s,减少搬运次数.避免了一次空间开的很大,而数据只有几个

clear

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

c_str

将const string* 转化为const char*

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

cout不能直接处理自定义类型string,但是可以使用c_str将string转成常量字符串,内置类型就可以直接打印


源码

.h

#pragma once
#define _CRT_SECURE_NO_WARNINGS
using namespace std;
#include<assert.h>
#include<iostream>
#include<algorithm>
namespace zjw
{
  class string
  {
  public:
    typedef char* iterator;
    typedef   const char* const_iterator;
    iterator begin()
    {
      return _str;
    }
    iterator end()
    {
      return _str + _size;
    }
    const_iterator begin() const
    {
      return _str;
    }
    const_iterator end() const
    {
      return _str + _size;
    }
    string(const char* str = "")
      :_size(strlen(str))
    {
      _capacity = _size;
      _str = new char[_capacity + 1];
      strcpy(_str, str);
    }
    ~string()
    {
      delete[]_str;
      _str = nullptr;
      _size = _capacity = 0;
    }
    size_t size()
    {
      return _size;
    }
    size_t capacity()
    {
      return _capacity;
    }
    char& operator[](size_t pos)
    {
      assert(pos < _size);
      return _str[pos];
    }
    const char& operator[](size_t pos) const
    {
      assert(pos < _size);
      return _str[pos];
    }
    void reserve(size_t n)
    {
      if (n > _capacity)
      {
        char* tmp = new char[n + 1];
        strcpy(tmp, _str);
        delete[]_str;
        _str = tmp;
        _capacity = n;
      }
    }
    void push_back(char ch)
    {
      if (_capacity == _size)
      {
        reserve(_capacity == 0 ? 4 : _capacity * 2);
      }
      _str[_size] = ch;
      _size++;
      _str[_size] = '\0';
    }
    void append(const char* str)
    {
      size_t len = strlen(str);
      if (_size + len > _capacity)
      {
        reserve(_size + len);
      }
      strcpy(_str + _size, str);
      _size += len;
      //_str[_size] = '\0';
    }
    string& operator+=(char ch)
    {
      push_back(ch);
      return *this;
    }
    string& operator+=(const char* str)
    {
      append(str);
      return *this;
    }
    void insert(size_t pos, char ch)
    {
      assert(pos <= _size);
      if (_capacity == _size)
      {
        reserve(_capacity == 0 ? 4 : _capacity * 2);
      }
      size_t end = _size + 1;
      while (end > pos)
      {
        _str[end] = _str[end - 1];
        end--;
      }
      _str[pos] = ch;
      _size++;
    }
    const char* c_str() const
    {
      return _str;
    }
    void earse(size_t pos, size_t len = npos)
    {
      assert(pos < _size);
      if (len == npos || pos > _size - len)
      {
        _str[pos] = '\0';
        _size = pos;
      }
      else
      {
        strcpy(_str + pos, _str + pos + len);
        _size -= len;
      }
    }
    bool empty()
    {
      return _size == 0;
    }
    void resize(size_t n, char ch = '\0')
    {
      if (n <= _size)
      {
        _str[n] = '\0';
        _size = n;
      }
      else
      {
        reserve(n);
        for (size_t i = _size; i < n; i++)
        {
          _str[i] = ch;
        }
        _size = n;
      }
    }
    void insert(size_t pos, const char* str)
    {
      size_t len = strlen(str);
      if (_size + len > _capacity)
      {
        reserve(_size + len);
      }
      size_t end = _size + len;
      while (end > pos + len - 1)
      {
        _str[end] = _str[end - len];
        end--;
      }
      strncpy(_str + pos, str, len);
      _size += len;
    }
    size_t find(char ch, size_t pos = 0)
    {
      for (int i = pos; i < _size; i++)
      {
        if (_str[i] == ch)
          return i;
      }
      return npos;
    }
    size_t find(const char* sub, size_t pos = 0) const
    {
      assert(pos < _size);
      const char* ptr = strstr(_str + pos, sub);
      if (ptr != nullptr)
      {
        return ptr - _str;
      }
      else
      {
        return npos;
      }
    }
    string substr(size_t pos = 0, size_t len = npos) const
    {
      string substr;
      if (pos > _size - len)
      {
        for (int i = pos; i <= _size; i++)
        {
          substr += _str[i];
        }
      }
      else
      {
        for (int i = pos; i < pos + len; i++)
        {
          substr += _str[i];
        }
        substr += '\0';
      }
      return substr;
    }
    void swap(string& str)
    {
      std::swap(_str, str._str);
      std::swap(_size, str._size);
      std::swap(_capacity, str._capacity);
    }
    string(const string& s)
    {
      string tmp(s._str);
      swap(tmp);
    
    
    
    
    }
    string& operator=(string tmp)
    {
      swap(tmp);
      return *this;
    }
    string& operator=(const string& s)
    {
      char* tmp = new char[s._capacity + 1];
      strcpy(tmp, s._str);
      delete[] _str;
      _str = tmp;
      _size = s._size;
      _capacity = s._capacity;
      return *this;
      
      
    }
    void clear()
    {
      _size = 0;
      _str[0] = '\0';
    }
    friend istream& operator>>(istream& in, string& s);
  public:
    static const int  npos;
  private:
    char* _str;
    int _size;
    int _capacity;
  };
  const int string::npos = -1;
  void swap(string& x, string& y)
  {
    x.swap(y);
    cout << "没使用库里的" << endl;
  
  }
  istream& operator>>(istream& in, string& s)
  {
    s.clear();
    char ch;
    ch = in.get();
    
    char buff[128];
    int i = 0;
    while (ch != ' ' && ch != '\n')
    {
      buff[i++] = ch;
      if (i == 127)
      {
        buff[127] = '\0';
        s += buff;
        i = 0;
      }
      ch = in.get();
    }
    if (i > 0)
    {
      buff[i] = '\0';
      s += buff;
    }
    return in;
  }
  //istream& operator>>(istream& in, string& s)
  //{
  //  
  //  char ch;
  //  
  //  in.get(ch);
  //  
  //  s.reserve(128);
  //  while (ch != ' ' && ch != '\n')
  //  {
  //  
  //  
  //    s += ch;
  //    in.get(ch);
  //  }
  //  
  //    
  //    
  //  
  //  return in;
  //}
  bool operator==(const string& s1, const string& s2)
  {
    return strcmp(s1.c_str(), s2.c_str())==0;
  }
  bool operator>(const string& s1, const string& s2)
  {
    return strcmp(s1.c_str(), s2.c_str());
  }
  bool operator<(const string& s1, const string& s2)
  {
    return  !(s1 > s2 && s1 == s2);
  }
  bool operator<=(const string& s1, const string& s2)
  {
    return  !(s1 > s2);
  }
  bool operator>=(const string& s1, const string& s2)
  {
    return  !(s1 < s2);
  }
  bool operator!=(const string& s1, const string& s2)
  {
    return  !(s1 == s2);
  }
  ostream& operator<<(ostream& out, const string& s)
  {
    for (auto e : s)
    {
      out << e;
    }
    return out;
  }
  //istream& operator>>(istream& in, string& s)
  //{
  //  s.clear();
  //  char ch;
  //  
  //  ch = in.get();
  //  //in >> ch;
  //  s.reserve(128);
  //  while (ch != ' ' && ch != '\n')
  //  {
  //    
  //    s += ch;
  //    ch = in.get();
  //    //in >> ch;
  //  }
  //  return in;
  //
  //
  //
  //
  //}
  void test1()
  {
    string str;
    str += 'a';
    str += 'b';
    str += "beijing";
    string::iterator it = str.begin();
    while (it != str.end())
    {
      cout << *it << " ";
      it++;
    }
  }
  void test2()
  {
    string str;
    str.push_back('a');
    str.push_back('a');
    str.push_back('b');
    str.push_back('a');
    str.push_back('a');
    string::iterator it = str.begin();
    while (it != str.end())
    {
      cout << *it << " ";
      it++;
    }
    cout << str[2];
  }
  void test3()
  {
    string str;
    str.append("stringbj");
    for (auto& e : str)
    {
      cout << e << " ";
    }
  }
  void print_string(const string it)
  {
    string::const_iterator res = it.begin();
    while (res != it.end())
    {
      cout << *res << " ";
      ++res;
    }
  }
  void test4()
  {
    string str;
    str += "abc";
    str.append("stringbj");
    string::iterator it = str.begin();
    while (it != str.end())
    {
      cout << *it << " ";
      it++;
    }
    //str.insert(0, 'g');
    for (auto& e : str)
    {
      cout << e << " ";
    }
    cout << endl;
    // str.earse(1,string::npos);*/
    /* for (auto e : str)
     {
       cout << e << " ";
     }*/
     // print_string(str);
  }
  void test5()
  {
    string str;
    str.push_back('a');
    str.push_back('a');
    str.push_back('b');
    str.resize(10);
    /* string::iterator it = str.begin();
     while (it != str.end())
     {
       cout << *it << " ";
       it++;
     }*/
    cout << str.c_str();
  }
  void test6()
  {
    string str;
    str.push_back('a');
    str.push_back('a');
    str.push_back('b');
    str.insert(2, "hello");
    cout << str.c_str();
  }
  void test7()
  {
    string str;
    str.push_back('a');
    str.push_back('a');
    str.push_back('b');
    str.insert(2, "hello");
    cout << endl;
    int ret = str.find('b', 0);
    cout << ret;
  }
  void test8()
  {
    string str;
    str += "beijing huanyingni zhangjiawang";
    int ret = str.find("zhangjiawang");
    cout << ret;
  }
  void test9()
  {
    string str;
    str += "beijing huanyingni zhangjiawang";
    string op = str.substr(0, 10);
    cout << op.c_str();
  }
  void test10()
  {
    string str1;
    string str2;
    str1 += "abc";
    str2 += "aba";
    cout << (str1 == str2) << endl;
    cout << ("aba" == str2) << endl;
    cout << (str2== "aba") << endl;
     cout << (str1>str2) << endl;
     cout << (str1 >=str2) << endl;
     cout << (str1<str2) << endl;
     cout << (str1 <=str2) << endl;
     cout << (str1!=str2) << endl;
  }
  void test11()
  {
    string str1;
    string str2;
    cin >> str1;//>>str2;//>>str2;
    //cout << str1;
    cout << str1.capacity();
  }
  void test12()
  {   string str1;
    string str2;
    str1 += "hello";
    str2+="nihao";
    cout << "str1:"<<str1 << endl;
    cout << "str2:"<<str2 << endl;
    str1.swap(str2);
    cout << "str1:" << str1 << endl;
    cout << "str2:" << str2 << endl;
  }
  void test13()
  {
    string str1;
    string str2;
    str1 += "hello";
    str2 += "nihao";
    cout << "str1:" << str1 << endl;
    cout << "str2:" << str2 << endl;
    swap(str1, str2);
    cout << "str1:" << str1 << endl;
    cout << "str2:" << str2 << endl;
  
  
  }
  void test14()
  {
    
    string str2;
    
    str2 += "nihao";
    string str1(str2);
  
  
  
  }
  
}

.cpp

#include"标头.h"
int main()
{
  zjw::test11();
}
目录
相关文章
|
1月前
|
C语言 C++ 容器
【c++丨STL】string模拟实现(附源码)
本文详细介绍了如何模拟实现C++ STL中的`string`类,包括其构造函数、拷贝构造、赋值重载、析构函数等基本功能,以及字符串的插入、删除、查找、比较等操作。文章还展示了如何实现输入输出流操作符,使自定义的`string`类能够方便地与`cin`和`cout`配合使用。通过这些实现,读者不仅能加深对`string`类的理解,还能提升对C++编程技巧的掌握。
72 5
|
1月前
|
存储 编译器 C语言
【c++丨STL】string类的使用
本文介绍了C++中`string`类的基本概念及其主要接口。`string`类在C++标准库中扮演着重要角色,它提供了比C语言中字符串处理函数更丰富、安全和便捷的功能。文章详细讲解了`string`类的构造函数、赋值运算符、容量管理接口、元素访问及遍历方法、字符串修改操作、字符串运算接口、常量成员和非成员函数等内容。通过实例演示了如何使用这些接口进行字符串的创建、修改、查找和比较等操作,帮助读者更好地理解和掌握`string`类的应用。
51 2
|
2月前
|
C++ 容器
|
2月前
|
存储 安全 C++
【C++打怪之路Lv8】-- string类
【C++打怪之路Lv8】-- string类
29 1
|
2月前
|
C++ 容器
|
2月前
|
C++ 容器
|
2月前
|
存储 C++ 容器
|
2月前
|
安全 C语言 C++
【C++篇】探寻C++ STL之美:从string类的基础到高级操作的全面解析
【C++篇】探寻C++ STL之美:从string类的基础到高级操作的全面解析
55 4
|
2月前
|
存储 编译器 程序员
【C++篇】手撕 C++ string 类:从零实现到深入剖析的模拟之路
【C++篇】手撕 C++ string 类:从零实现到深入剖析的模拟之路
81 2
|
2月前
|
编译器 C语言 C++
【C++】C++ STL 探索:String的使用与理解(三)
【C++】C++ STL 探索:String的使用与理解