09 string的实现
注意
实现仿cplus官网的的string类,对部分主要功能实现
实现
头文件
#pragma once
#include <iostream>
#include <assert.h>
#include <string>namespace mystring
{class string{friend std::ostream& operator<<(std::ostream& os, const string& str);public://迭代器typedef char* iterator;typedef const char* cosnt_iterator;iterator begin(){return _str;}iterator end(){return _str + _size;}cosnt_iterator begin() const{return _str;}cosnt_iterator end() const{return _str + _size;}//初始化string(const char* str = "");string(const string& obj);string& operator=(const string& obj);//增void PsuhBack(char ch);string& Append(const char* str);string& Insert(size_t pos, char ch);string& Insert(size_t pos, const char* str);string& operator+=(char ch);string& operator+=(const char* str);void Reserve(size_t capacity);void Resize(size_t capacity, char ch = '\0');//删string& Erase(size_t pos, size_t n = npos);void Clear();//查size_t Find(char ch, size_t pos = 0);size_t Find(char* str, size_t pos = 0);const char* c_str() const{return _str;}size_t size() const{return _size;}size_t capacity() const{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 Swap(string& obj);//不修改成员变量的,最好const//比较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 strcmp(_str, s._str) < 0;}bool operator>=(const string& s) const{return *this > s || s == *this;}bool operator<=(const string& s) const{return *this < s || *this == s;}bool operator!=(const string& s) const{return !(*this == s);}//析构~string(){delete[] _str;_str = nullptr;_size = _capacity = 0;}private:char* _str;size_t _size;size_t _capacity;static size_t npos;};std::ostream& operator<<(std::ostream& os, const string& str);std::istream& operator>>(std::istream& is, string& str);}
实现
#define _CRT_SECURE_NO_WARNINGS 1
#include "String.h"using namespace mystring;size_t string::npos = -1;mystring::string::string(const char* str):_size(strlen(str))
{_capacity = _size == 0 ? 3 : _size + 1;_str = new char[_capacity];strcpy(_str, str);
}mystring::string::string(const string& obj):_size(obj._size),_capacity(obj._capacity)
{_str = new char[_capacity];strcpy(_str, obj._str);
}void string::PsuhBack(char ch)
{if (_size + 1>= _capacity){//扩容Reserve(_capacity * 2);}_str[_size] = ch;_size++;_str[_size] = '\0';//insert(_size, ch);
}string& mystring::string::Append(const char* str)
{size_t len = strlen(str);if (_size + len >= _capacity){//扩容Reserve(_capacity + len);}strcpy(_str + _size, str);_size += len;return *this;
}string& mystring::string::Insert(size_t pos, char ch)
{assert(pos <= _size);if (_size + 1>= _capacity){//扩容Reserve(_capacity * 2);}int end = _size + 1;while (end > pos){_str[end] = _str[end - 1];end--;}_str[pos] = ch;_size++;return *this;
}string& mystring::string::Insert(size_t pos, const char* str)
{assert(pos <= _size);size_t len = strlen(str);if (_size + len >= _capacity){//扩容Reserve(_capacity + len);}size_t end = _size + len;while (end - len + 1> pos){_str[end] = _str[end - len];end--;}strncpy(_str + pos, str, len);_size += len;return *this;}string& mystring::string::operator+=(char ch)
{PsuhBack(ch);return *this;
}string& mystring::string::operator+=(const char* str)
{Append(str);return *this;
}void mystring::string::Reserve(size_t capacity)
{//比原空间小,不扩容,防止单独调用if (capacity > _capacity){char* tmp = new char[capacity];strcpy(tmp, _str);delete[] _str;_str = tmp;_capacity = capacity;}}void mystring::string::Resize(size_t capacity, char ch)
{//比元空间小,不缩容if (capacity > _capacity){Reserve(capacity + 1);memset(_str + _size, ch, capacity - _size);_size = capacity;_str[_size] = '\0';}else{_str[capacity] = '\0';_size = capacity;}
}string& mystring::string::Erase(size_t pos, size_t n)
{assert(pos < _size);//分三种情况,n全删和部分size_t end = pos;if (n == npos || pos + n >= _size){_str[pos] = '\0';//长度改为pos_size = pos;}else{/*while (end < _size - n){_str[end] = _str[end + n];end++;}_str[_size - n] = '\0';*/strcpy(_str + pos, _str + pos + n);_size -= n;}return *this;}void mystring::string::Clear()
{_size = 0;_str[_size] = '\0';
}size_t mystring::string::Find(char ch, size_t pos)
{assert(pos < _size);for (size_t i = pos; i < _size; i++){if (_str[i] == ch){return i;}}return npos;
}size_t mystring::string::Find(char* str, size_t pos)
{assert(pos < _size);char* p = strstr(_str + pos, str);if (p == nullptr){return npos;}else{return p - _str;}}void mystring::string::Swap(string& obj)
{std::swap(_str, obj._str);std::swap(_size, obj._size);std::swap(_capacity, obj._capacity);
}string& mystring::string::operator=(const string& obj)
{if (this != &obj){char* tmp = new char[obj._capacity];strcpy(tmp, obj._str);delete[] _str;_str = tmp;_size = obj._size;_capacity = obj._capacity;}return *this;
}std::ostream& mystring::operator<<(std::ostream& os, const string& str)
{for (auto ch : str){os << ch;}return os;
}std::istream& mystring::operator>>(std::istream& is, string& str)
{//cin遇到空格会退出str.Clear();char ch = is.get();//先存入临时数组,减少扩容次数char buff[128];size_t i = 0;while (ch != ' ' && ch != '\n'){buff[i++] = ch;if (i == 127){buff[127] = '\0';str += buff;i = 0;}ch = is.get();}//没有放入的if (i != 0){buff[i] = '\0';str += buff;}return is;/*str.Clear();char ch = is.get();char buff[128];size_t i = 0;while (ch != ' ' && ch != '\n'){buff[i++] = ch;if (i == 127){buff[127] = '\0';str += buff;i = 0;}ch = is.get();}if (i != 0){buff[i] = '\0';str += buff;}return is;*/}
测试
#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
#include <string>
#include "String.h"
using namespace mystring;//void printstring(const string& s)
//{
// string::cosnt_iterator it = s.begin();
// while (it != s.end())
// {
// printf("%c", *it);
// it++;
// }
//}int main()
{string s1("abcd");std::string s2("abcd");//string s2("hello nih");//string::iterator it = s1.begin();/*for (size_t i = 0; i < s1.size(); i++){printf("%c",s1[i]);}*//*while (it != s1.end()){printf("%c", *it);it++;}*///s1 += 'a';//s1 += 'b';// += 'c';/*s1.Insert(0, 'y');s1.Insert(0, 'x');s1.Insert(2, "hello");*///s1.Insert(2, "hello");//s1.reserve();//s1.Erase(2,1);//s1.resize(10, 'x');//printf("%zd\n", s1.Find('b'));//printf("%zd\n", s2.find('b'));/*s2 += '\0';s2 += " www.nihao";s2.clear();*///s1 += '\0';//s1 += " www.he";std::cin >> s1;//std::cin >> s2;//string s2("world");//s2 = s1;//printf("size = %d\n capacity = %d\n%s\n", s1.size(), s1.capacity(), s1.c_str());//printf("s1 = s2 %d", s1 >= s2);//printstring(s1);std::cout << s1;return 0;
}
注意事项
容量默认比长度多一个,存储的\0
构造函数采用缺省构造,如果无参,默认为空字符串,如果为空指针,strlen计算长度会报错。因为容量依赖于长度,所以初始化列表先对size初始化。长度0时容量初始化为3,存储\0
插入功能注意0位置的插入,从size处开始会出错,因为size_t不会小于0的问题.所以选择从\0下一个位置开始挪
resize和reserve不会缩小容量,只会改变长度,resize判断两种情况,容量小于和大于目前的容量
erase如果长度是npos,就从pos位置全部删除,也需要分全删和部分删的情况
为了适应const对象调用下标,重载一个[]运算符,常成员函数返回常对象
swap比std的函数好的地方在于不需要构造,只需要交换三个成员变量
<<输出和c_str的区别,遇到\0c_str会停下来,<<按照长度打印
>>功能里cin遇到空格和换行会自动停下来,不会获取这个字符,导致while无限循环.所以改用io的get函数,空格和换行也会读取,用一个临时数组存够后一起放入对象里,避免多次扩容的浪费
vs的容量是默认15,如果超出则1.5倍扩容。而g++2倍扩容
写时拷贝
在浅拷贝的基础上增加了引用计数的方式
写时拷贝
写时拷贝的缺陷
扩展
测试时string的正确写法
STL的string类怎么了
相关文章:
09 string的实现
注意 实现仿cplus官网的的string类,对部分主要功能实现 实现 头文件 #pragma once #include <iostream> #include <assert.h> #include <string>namespace mystring {class string{friend std::ostream& operator<<(std::ostream&a…...
Git 进行版本控制时,配置 user.name 和 user.email
在使用 Git 进行版本控制时,配置 user.name 和 user.email 是一个非常重要的初始步骤,但不是绝对必须的。这两个配置项定义了当你进行提交(commit)时用于标识提交者的信息。 为什么建议配置 user.name 和 user.email 标识提交者…...
传统开发读写优化与HBase
目录: 一、传统开发数据读写性能优化 1. Mysql 分表、主从复制与读写分离 2. Redis(缓存型数据库)主从复制与读写分离 二、HBase 一、传统开发数据读写性能优化 1、Mysql 分表、主从复制与读写分离 mysql分库分表方案 一种分表方案:设置表A 表B 表A 自增列从1开始…...

【OpenGL实现 03】纹理贴图原理和实现
目录 一、说明二、纹理贴图原理2.1 纹理融合原理2.2 UV坐标原理 三、生成纹理对象3.1 需要在VAO上绑定纹理坐标3.2 纹理传递3.3 纹理buffer生成 四、代码实现:五、着色器4.1 片段4.2 顶点 五、后记 一、说明 本篇叙述在画出图元的时候,如何贴图纹理图片…...

FDU 2021 | 二叉树关键节点的个数
文章目录 1. 题目描述2. 我的尝试 1. 题目描述 给定一颗二叉树,树的每个节点的值为一个正整数。如果从根节点到节点 N 的路径上不存在比节点 N 的值大的节点,那么节点 N 被认为是树上的关键节点。求树上所有的关键节点的个数。请写出程序,并…...

精读《React Conf 2019 - Day2》
1 引言 这是继 精读《React Conf 2019 - Day1》 之后的第二篇,补充了 React Conf 2019 第二天的内容。 2 概述 & 精读 第二天的内容更为精彩,笔者会重点介绍比较干货的部分。 Fast refresh Fast refresh 是更好的 react-hot-loader 替代方案&am…...
向ChatGPT高效提问模板
PS: ChatGPT无限次数,无需魔法,登录即可使用,网页打开下面 tj4.mnsfdx.net [点击跳转链接](http://tj4.mnsfdx.net/) 我想请你XXXX,请问我应该如何向你提问才能得到最满意的答案,请提供全面、详细的建议,针对每一个建…...
android metaRTC编译
参考文章: metaRTC3.0稳定版本编译指南_metartc 编译-CSDN博客 源码下载: Releases metartc/metaRTC GitHub 版本v6.0-b4即可...
HDFS面试重点
文章目录 1. HDFS的架构2. HDFS的读写流程3.HDFS中,文件为什么以block块的方式存储? 1. HDFS的架构 HDFS的架构可以分为以下几个主要组件: NameNode(名称节点): NameNode是HDFS的关键组件之一,…...
Java中的IO流是什么?
Java中的IO流(Input/Output Stream)是Java编程语言中用于处理输入和输出操作的一种重要机制。在Java中,IO流被用来读取和写入数据,这些数据可以来自各种来源,如文件、网络连接、内存缓冲区等。Java的IO流提供了丰富的类…...

Spring boot 集成netty实现websocket通信
一、netty介绍 Netty 是一个基于NIO的客户、服务器端的编程框架,使用Netty 可以确保你快速和简单的开发出一个网络应用,例如实现了某种协议的客户、服务端应用。Netty相当于简化和流线化了网络应用的编程开发过程,例如:基于TCP和U…...

数码管的动态显示(二)
1.原理 这个十六进制是右边的dp为高位。 数码管的动态显示,在第一个计数周期显示个位,在第二个周期显示十位,在第三个周期显示百位由于人眼的视觉和数码管的特性,感觉就是显示了234,每个数码管的显示需要从输入的数据里…...

【JavaScript】数据类型转换 ① ( 隐式转换 和 显式转换 | 常用的 数据类型转换 | 转为 字符串类型 方法 )
文章目录 一、 JavaScript 数据类型转换1、数据类型转换2、隐式转换 和 显式转换3、常用的 数据类型转换4、转为 字符串类型 方法 一、 JavaScript 数据类型转换 1、数据类型转换 在 网页端 使用 HTML 表单 和 浏览器输入框 prompt 函数 , 接收的数据 是 字符串类型 变量 , 该…...

git学习(创建项目提交代码)
操作步骤如下 git init //初始化git remote add origin https://gitee.com/aydvvs.git //建立连接git remote -v //查看git add . //添加到暂存区git push 返送到暂存区git status // 查看提交代码git commit -m初次提交git push -u origin "master"//提交远程分支 …...

Day36:安全开发-JavaEE应用第三方组件Log4j日志FastJson序列化JNDI注入
目录 Java-项目管理-工具配置 Java-三方组件-Log4J&JNDI Java-三方组件-FastJson&反射 思维导图 Java知识点: 功能:数据库操作,文件操作,序列化数据,身份验证,框架开发,第三方库使用…...

HTML5+CSS3+JS小实例:全屏范围滑块
实例:全屏范围滑块 技术栈:HTML+CSS+JS 效果: 源码: 【HTML】 <!DOCTYPE html> <html lang="zh-CN"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale…...

ctf杂项总结
1.文件无法打开 1.1.文件拓展名损坏/错误导致 方法: 1.使用kali当中的file命令查看,之后修改为正确的后缀即可 2.通过16进制编辑器打开查看文件头 3.文件头残缺/错误,可以先使用kail当中的file命令查看它的类型,之后再通过 16…...

openAI key 与ChatGPTPlus的关系,如何升级ChatGPTPLus
一、前言 先详细介绍一下Plus会员和Open API之间的区别: 实际上,这两者是相互独立的。举例来说,虽然您开通了Plus会员,并不意味着您就可以使用4.0版本的API。尽管这两个账户可以是同一个,但它们是完全独立的平台。 …...
KB5034441 0x80070643 reagentc.exe 无法更新引导配置数据
微软2024年1月的更新补丁正常更新会出现0x80070643错误,原因是正常安装系统默认的恢复分区留小了,通过压缩系统盘空间然后在diskgenius扩容恢复分区空间可以解决这个问题,但是笔者在进行上述操作时依旧出现了报错,按照网上的说法可…...

全网最最最详细“Jupyter command ‘jupyter-notebook‘ not found.“的解决方案
"Jupyter command jupyter-notebook not found."。这通常意味着 jupyter-notebook 命令在当前的虚拟环境中未安装或未正确安装,因此系统无法识别此命令。 原因分析 未安装 Jupyter Notebook: 可能你的虚拟环境中还没有安装 Jupyter Notebook。虽然 Jupyt…...
HTML 语义化
目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案: 语义化标签: <header>:页头<nav>:导航<main>:主要内容<article>&#x…...
内存分配函数malloc kmalloc vmalloc
内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...

Appium+python自动化(十六)- ADB命令
简介 Android 调试桥(adb)是多种用途的工具,该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具,其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利,如安装和调试…...
AtCoder 第409场初级竞赛 A~E题解
A Conflict 【题目链接】 原题链接:A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串,只有在同时为 o 时输出 Yes 并结束程序,否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...

转转集团旗下首家二手多品类循环仓店“超级转转”开业
6月9日,国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解,“超级…...

第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明
AI 领域的快速发展正在催生一个新时代,智能代理(agents)不再是孤立的个体,而是能够像一个数字团队一样协作。然而,当前 AI 生态系统的碎片化阻碍了这一愿景的实现,导致了“AI 巴别塔问题”——不同代理之间…...
【AI学习】三、AI算法中的向量
在人工智能(AI)算法中,向量(Vector)是一种将现实世界中的数据(如图像、文本、音频等)转化为计算机可处理的数值型特征表示的工具。它是连接人类认知(如语义、视觉特征)与…...
LLM基础1_语言模型如何处理文本
基于GitHub项目:https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken:OpenAI开发的专业"分词器" torch:Facebook开发的强力计算引擎,相当于超级计算器 理解词嵌入:给词语画"…...

招商蛇口 | 执笔CID,启幕低密生活新境
作为中国城市生长的力量,招商蛇口以“美好生活承载者”为使命,深耕全球111座城市,以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子,招商蛇口始终与城市发展同频共振,以建筑诠释对土地与生活的…...

《信号与系统》第 6 章 信号与系统的时域和频域特性
目录 6.0 引言 6.1 傅里叶变换的模和相位表示 6.2 线性时不变系统频率响应的模和相位表示 6.2.1 线性与非线性相位 6.2.2 群时延 6.2.3 对数模和相位图 6.3 理想频率选择性滤波器的时域特性 6.4 非理想滤波器的时域和频域特性讨论 6.5 一阶与二阶连续时间系统 6.5.1 …...