准备

博主:大大怪先森(记得关注哦!)
编程环境:vs2013
所示代码:码源


文章目录

  • 准备
  • 前言
  • 一、标准库中的tring类
    • 1.了解类
    • 2.string类的常见接口
      • 2.1 string类对象的构造
      • 2.2 string类容器的操作
  • 二、String类的模拟实现
    • 1.深浅拷贝
    • 2.1.1浅拷贝
    • 2.1.2深拷贝
    • 2.写时拷贝
    • 3.String实现代码
  • 总结
  • 结语

前言

本章讲解String容器的相关知识!!!


提示:以下是本篇文章正文内容

一、标准库中的tring类

1.了解类

  1. string是表示字符串的字符串类
    2.该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作.
  2. string在底层实际是:basic_string模板类的别名,typedef basic_string<char, char_traits, allocator>string;
  3. 不能操作多字节或者变长字符的序列。
    注意:在使用string类时,必须包含#include头文件以及using namespace std;

2.string类的常见接口

2.1 string类对象的构造

(constructor)函数名称 功能说明
string() (重点) 构造空的string类对象,即空字符串
string(const char* s) (重点) 用C-string来构造string类对象
string(size_t n, char c) string类对象中包含n个字符c
string(const string&s) (重点) 拷贝构造函数

2.2 string类容器的操作

函数名称 功能说明
size(重点) 返回字符串有效字符长度
reserve (重点) 为字符串预留空间**
resize (重点) 将有效字符的个数该成n个,多出的空间用字符c填充
operator[] (重点) 返回pos位置的字符,const string类对象调用
begin+ end begin获取第一个一个字符的迭代器 + end获取最后一个字符下一个位置的迭代器
rbegin + rend 反向迭代器begin/end的用法相反,rfind获得最后一个字符的迭代器,rend获得第一个字符的迭代器
push_back 在字符串后尾插字符c
append 在字符串后追加一个字符串
operator+= (重点) 在字符串后追加字符串str
c_str(重点) 返回C格式字符串
find + npos(重点) 从字符串pos位置开始往后找字符c,返回该字符在字符串中的位置
rfind 从字符串pos位置开始往前找字符c,返回该字符在字符串中的位置
substr 在str中从pos位置开始,截取n个字符,然后将其返回
getline (重点) 获取一行字符串
iinsert 头插字符

二、String类的模拟实现

1.深浅拷贝

2.1.1浅拷贝

浅拷贝:也称位拷贝,编译器只是将对象中的值拷贝过来。如果对象中管理资源,最后就会导致多个对象共享同一份资源,当一个对象销毁时就会将该资源释放掉,而此时另一些对象不知道该资源已经被释放,以为还有效,所以 当继续对资源进项操作时,就会发生发生了访问违规。

2.1.2深拷贝

如果一个类中涉及到资源的管理,其拷贝构造函数、赋值运算符重载以及析构函数必须要显式给出。一般情况都是按照深拷贝方式提供

深拷贝为每一个对象开辟一个空间不会出现多处析构同一块空间的现象

2.写时拷贝

写时拷贝就是一种拖延症,是在浅拷贝的基础之上增加了引用计数的方式来实现的。
引用计数:用来记录资源使用者的个数。在构造时,将资源的计数给成1,每增加一个对象使用该资源,就给增加1,当某个对象被销毁时,先给该计数减1,然后再检查是否需要释放资源,如果计数为1,说明该对象时资源的最后一个使用者,将该资源释放;否则就不能释放,因为还有其他对象在使用该资源。
简单来说就是只有在你真正需要这块空间的时候才会给你开辟这一块空间,而在不需要的时候用户以为编译器给你了,但是编译器并没有在内存中为你开辟这一块空间。

3.String实现代码

代码如下(示例):

#pragma once
#include<string.h>
#include<iostream>
#include<string>
#include<vector>
#include<list>
#include<assert.h>
using namespace std;
//string类模拟增删查改的全部实现
namespace wzd
{class string{public:typedef char* iterator;typedef const char* const_iterator;const_iterator begin()const{return _str;}const_iterator end()const{return _str + _size;}iterator begin(){return _str;}iterator end(){return _str + _size;}string(const char* str = ""):_size(strlen(str)), _capacity(_size){_str = new char[_capacity + 1];strcpy(_str, str);}//传统写法 -- 本本分分去完成深拷贝//s2(s1)/*  string(const string& s):_size(s._size), _capacity(s._capacity){_str = new char[_capacity + 1];strcpy(_str, s._str);}*///现代写法:灵活运用构造函数string(const string& s):_str(nullptr),_size(0), _capacity(0){string tmp(s._str);swap(_str, tmp._str);}//传统写法:赋值函数的重载/*string& opertor = (const string& s){if (this != &s){char* tmp = new char[s.capacity + 1];strcpy(tmp, s._str);delete[] _str;_str = tmp;_size = s._size;_capacity = s.capacity;}retunrn *this;}*///现代写法:利用拷贝构造函数/*string& opertor = (const string& s){if (this != &s){string tmp(s);swap(_str, tmp._str);}}*///现代写法更简单的一种方法:传参的时候实现拷贝构造string& operator=(string s){swap(_str, s._str);return *this;}~string(){delete[] _str;_str = nullptr;_size = _capacity = 0;}const char* c_str()const{return _str;}size_t size()const{return _size;}char& operator[](size_t pos){assert(pos < _size);retunr _str[pos];}const char& operator[](size_t pos)const{assert(pos < _size);retunr _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 resize(size_t n, char ch = '\0'){if (n <= _size){_size = n;_str[_size] = '\0';}else{if (n > _capacity){reverse(n);}memset(_str + _size, ch, n - _size);_size = n;_str[_size] = '\0';}}void Push_back(char ch){//if (_size == _capacity)//{// //自己写的,代码有点小菜,为啥不想办法把空间交换//   //菜鸡//  /*char* tmp = new char[_capacity + 1];//  strcpy(tmp._str, _str)//    _capacity = _capacity * 2;//   _str = new char[_capacity + 1];// strcpy(_str,tmp.str)//  delete[] tmp;*///   reserve(_capacity == 0 ? 4 : _capacity * 2);//}//_str[_size] = ch;//++_size;//_str[_size] = '\0';insert(_size, ch);}void append(const char* str){/*if (_size + strlen(str) > _capacity){reverse(_size + strlen(str));}strcpy(_str + _size, str);_size = _size + strlen(str);*/insert(_size, str);}string& opeator += (char ch){Push_back(ch);return *this;}string& opeator += (char ch)const{Push_back(ch);return *this;}size_t find(char ch){for (size_t = 0; i < _size; i++){if (ch == _str[i]){return i;}}return npos;}size_t find(const char* s, size_t pos = 0){const char* ptr = strstr(_str + pos, s);if (ptr == nullptr){return npos;}else{return ptr - _str;}}string& insert(size_t pos, char ch){assert(pos <= _size);if (_size == _capacity){reserve(_capacity == 0 ? 4 : _capacity * 2);}//头插第一个位置的时候出现问题//end - 1是-1的无符号整形中很大//越界访问/*size_t end = _size;while (end >= pos){_str[end + 1] = _str[end];--end;//pos是o这个地方end--是-1无穷大完蛋了!!!}*//*int end = _size;while (end >= (int)pos){_str[end + 1] = _str[end];--end;}*/size end = _size + 1;while (end > pos){_str[end] = _str[end - 1];--end;}_str[pos] = ch;++_size;return *this;}string& insert(size_t pos, const char* s){assert(pos <= _size);size_t len = strlen(s);if (_size + len > _capacity){reverse(_size + len);}size_t end = _size + len;whill(end > pos){_str[end] = _str[end - len];--end;}strncpy(_str + pos, s, len);return *this;}string& erase(size_t pos = 0, size_t len = npos){assert(pos < _size);if (len == npos || pos + len >= _size){_str[pos] = '\0';_size = pos;}else{strcp(_str + pos, _str + pos + len);_size -= len;}return *this;}private:char* _str;size_t _size;size_t _capacity;static const int npos;};
}
wzd::string::npos = -1;

总结

String作为c++语言中一个非常常见的容器,无论我们在刷题还是写项目的过程中一定会经常使用String这个容器,各位大大一定要能够熟练的掌握哦!!
其中还有许多String类中库函数这里没有讲解,各位可以参考cpulspuls这个官方的网站哦

结语

希望本篇文章能给各位带来帮助,如有不足还请指正!!!
码字不易,各位大大给个收藏点赞吧!!!

各位大大记得点赞,关注,一键三连哦!!!

【C++篇】STL常见容器String的模拟实现相关推荐

  1. [C++] STL介绍及string的模拟实现

    前言    学习C语言或者初阶数据结构的时候我们就会发现,C语言虽然简单易懂,但是很多的东西,比如栈.队列.树没有基本的模板进行套用,每次写题还得自己把东西写好才能做题,这太麻烦了!!!    所以在 ...

  2. 【c++篇】STL常见容器Stackqueue

    准备 博主:大大怪先森(记得关注哦!) 编程环境:vs2013 所示代码:码源 提示:写完文章后,目录可以自动生成, 文章目录 准备 前言 一.stack的介绍和使用 1.stack的介绍 2.sat ...

  3. C++ STL常见容器

    目录 1.array 1.1 介绍 1.1.1 头文件 1.1.2 定义 1.1.3 初始化 1.1.4 访问 1.1.5 遍历 1.2 方法函数 2.vector(动态数组) 2.1 介绍 2.1. ...

  4. 【STL】容器 - list的模拟实现

    目录 一.框架 二.list迭代器 1.list迭代器的特殊之处 2.iterator类的代码实现 3.const迭代器复用普通迭代器 三.反向迭代器 1.反向迭代器也称迭代器适配器(复用的思想) 2 ...

  5. C++基础--STL基本容器string,vector,list,deque,map

    在STL中基本容器有: string.vector.list.deque.set.map set 和map都是无序的保存元素,只能通过它提供的接口对里面的元素进行访问 set:集合, 用来判断某一个元 ...

  6. 【C++】STL常用容器总结之十二:string类

    13.string类 声明 string类本不是STL的容器,但是它与STL容器有着很多相似的操作,因此,把string放在这里一起进行介绍. 之所以抛弃char*的字符串而选用C++标准程序库中的s ...

  7. 学习笔记:C++初阶【C++入门、类和对象、C/C++内存管理、模板初阶、STL简介、string、vector、list、stack、queueu、模板进阶、C++的IO流】

    文章目录 前言 一.C++入门 1. C++关键字 2.命名空间 2.1 C语言缺点之一,没办法很好地解决命名冲突问题 2.2 C++提出了一个新语法--命名空间 2.2.1 命名空间概念 2.2.2 ...

  8. 【读书笔记】【Effective STL】容器

    第 1 条:慎重选择容器类型. C++ 中不同的容器分类如下:[标准 or 非标准][STL or 非 STL][序列 or 关联] 标准 STL 序列容器:vector.string.deque.l ...

  9. [C++ STL] 各容器简单介绍

    [C++ STL] 各容器简单介绍 目录 一.什么是STL? 二.容器(Containers) 2.1 vector 2.2 deque 2.3 list 2.4 set 2.5 map 2.6 容器 ...

最新文章

  1. MySQL数据库-操作基础
  2. 招程序员不要信中医的? | 极客视频
  3. 一加7t人脸识别_一加7T跑分及配置信息曝光;新款iPad Pro曝光增加3D ToF镜头
  4. mysql 字符串索引 优化_MySQL性能优化之索引调优实战
  5. mysql cookbook
  6. Anaconda简介:它是什么,以及如何安装
  7. 栈溢出脚本_漏洞练习之网络编程与堆栈溢出技术
  8. [AU3]Backup Switch Config - cisco,huawei,h3c ---by onepc 153785587
  9. Windows 8 DirectX 开发学习笔记(十六)使用Terragen生成自然环境贴图
  10. 使用Net::DNS CPAN模块模拟一个DNS CNAME应答记录
  11. 手机app界面及易用性测试点分析(通用)
  12. OPPO小布助手算法系统探索、实践与思考
  13. dnf体验服显示服务器爆满,DNF:体验服刚更新就爆满,官方临时加频道,100级真那么好玩?...
  14. 计算机初始《wps表格》教案,wps教案
  15. 【历史上的今天】1 月 1 日:惠普诞生;互联网的规范化;百度成立
  16. 构建高可用MYSQL主从复制集群
  17. c语言和java哪个好学_学java前要学C语言吗?java和C语言哪个好学?
  18. Android仿搜狗浏览器加载动画
  19. 矩阵小朋友,真是拿你没有办法
  20. 【CGAL_网格处理】坐标变换

热门文章

  1. 2022李永乐线性代数
  2. 信息隐藏 !!!!!!!!!!!!!
  3. CCS 3.3 创建DSP TMSC6726B工程
  4. 用python画篮球场_如何使用 Python 创建一个 NBA 得分图?
  5. 迅歌KTV服务器各型号,2017年ktv必点歌曲排行榜(4页)-原创力文档
  6. Springboot+POI通用Excel表格导出表头样式设置方法
  7. Java #JDK下载以及环境配置
  8. 台式计算机能不能安装蓝牙驱动,台式电脑没有蓝牙该怎么安装?安装台式电脑的蓝牙的方法...
  9. CSS 盒子模型box-sizing
  10. 浪涌保护器,SPD浪涌保护器的分类和选型标准