C++中的string模拟实现

 上一章讲了库中的string函数,这次我们来讲一讲模拟实现

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<assert.h>
using namespace std;
//域名
namespace zzj {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 = "")//这里不能赋值为nullptr,因为如果用的缺省值,下面的strlen解引用空指针就崩了,我们用一个空串,空串不是什么也没有,空串会自动生成一个"\0".:_size(strlen(str)){_capacity = _size;_str = new char[_capacity + 1];std::strcpy(_str, str);}s2(s1)//String(const String& s) {//	_str = new char[s._capacity + 1];//	strcpy(_str, s._str);//	_size = s._size;//	_capacity = s._capacity;//}//拷贝构造,此方法是先构造再交换String(const String& s) {String tmp(s._str);swap(tmp);}// s1 = s3/*String& operator=(const String& s){char* tmp = new char[_capacity + 1];strcpy(tmp, s._str);delete[] _str;_str = tmp;_size = s._size;_capacity = s._capacity;return *this;}*///先构造再交换String& operator=(String tmp){// 现代写法swap(tmp);return *this;}//返回字符串地址const char* c_str() const { return _str;}//析构函数~String() {delete[] _str;_str = nullptr;_size = _capacity = 0;}//扩容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 (_size == _capacity) {reserve(_capacity == 0 ? 4 : 2 * _capacity);}_str[_size] = ch;_size++;_str[_size] = '\0';*/insert(_size, ch);}//追加字符串void append(const char* str) {/*size_t len = strlen(str);if (_size + len > _capacity) {reserve(len + _size);}strcpy(_str + _size, str);_size += len;*/insert(_size, str);}//重载+=运算符(+=字符串)String& operator+= (const char* str) {append(str);return *this;}//重载+=运算符(+=字符)String& operator+= (char ch) {push_back(ch);return *this;}//插入(字符)void insert(size_t pos , char ch) {assert(pos <= _size);if (_size == _capacity) {reserve(_capacity == 0 ? 4 : 2 * _capacity);}/*int end = _size;while (end >= (int)pos) {_str[end + 1] = _str[end];--end;}*/size_t end = _size + 1;while (end > pos) {_str[end] = _str[end - 1];--end;}_str[pos] = ch;++_size;}//插入(字符串)void insert(size_t pos, const char* str) {assert(pos <= _size);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;} //删除void erase(size_t pos, size_t len = npos) {assert(pos <= _size);if (len == npos || len > _size - pos) {_str[pos] = '\0';_size = pos;}else {strcpy(_str + pos, _str + pos + len);_size -= len;}}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;}_str[n] = '\0';_size = n;}}//交换两个字符串void swap(String& s) {std::swap(_str, s._str);std::swap(_size, s._size);std::swap(_capacity, s._capacity);}//字符查找size_t find(char ch,size_t pos = 0) const {assert(pos < _size);for (size_t 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* p = strstr(_str + pos, sub);if (p) {return p - _str;}else {return npos;}}//字符串切割String substr(size_t pos = 0, size_t len = npos) {String sub;if (len >= _size - pos) {for (size_t i = pos; i < _size; i++) {sub += _str[i];}}else {for (size_t i = pos; i < pos + len; i++) {sub += _str[i];}}return sub;}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 clear() {_size = 0;_str[_size] = '\0';}static const int npos;private:char* _str;size_t _size;size_t _capacity;};
}
//npos赋值为-1
const int zzj::String::npos = -1;
//为了将x.swap(y)转变成swap(x,y)方便理解
void swap(zzj::String& x,zzj::String& y) {x.swap(y);
}//赋值运算符重载
bool operator==(const zzj::String& s1, const zzj::String& s2) {int ret = strcmp(s1.c_str(), s2.c_str());return ret == 0;
}bool operator<(const zzj::String& s1, const zzj::String& s2) {int ret = strcmp(s1.c_str(), s2.c_str());return ret < 0;
}bool operator<=(const zzj::String& s1, const zzj::String& s2) {return s1 < s2 || s1 == s2;
}bool operator>(const zzj::String& s1, const zzj::String& s2) {return !(s1 < s2);
}bool operator>=(const zzj::String& s1, const zzj::String& s2) {return s1 > s2 || s1 == s2;
}bool operator!=(const zzj::String& s1, const zzj::String& s2) {return !(s1 == s2);
}
//输入流
istream& operator>>(istream& in, zzj::String& s)
{s.clear();char ch;//in >> ch;ch = in.get();char buff[128];size_t i = 0;while (ch != ' ' && ch != '\n'){buff[i++] = ch;// [0,126]if (i == 127){buff[127] = '\0';s += buff;i = 0;}ch = in.get();}if (i > 0){buff[i] = '\0';s += buff;}return in;
}istream& getline(istream& in, zzj::String& s)
{s.clear();char ch;//in >> ch;ch = in.get();char buff[128];size_t i = 0;while (ch != '\n'){buff[i++] = ch;// [0,126]if (i == 127){buff[127] = '\0';s += buff;i = 0;}ch = in.get();}if (i > 0){buff[i] = '\0';s += buff;}return in;
}
//输出流
ostream& operator<<(ostream& out, const zzj::String& s) {for (auto ch : s) {out << ch;}return out;
}void test1() {zzj::String s1;zzj::String s2("Hello world");zzj::String const s3("xxxxxx");for (int i = 0; i < s2.size(); i++) {cout << s2[i] << " ";}cout << endl;for (int i = 0; i < s2.size(); i++) {s2[i]++;}for (int i = 0; i < s2.size(); i++) {cout << s2[i] << " ";}cout << endl;for (int i = 0; i < s3.size(); i++) {//const对象不能被修改//s3[i]++;cout << s3[i] << " ";}}void test2() {zzj::String s3("hello world");zzj::String::iterator it3 = s3.begin();while (it3 != s3.end()) {*it3 -= 3;++ it3;}cout << endl;/*for (auto ch : s3) {cout << ch << " ";}cout << endl;*/zzj::String const s4("hello world");zzj::String::const_iterator it4 = s4.begin();while (it4 != s4.end()) {cout << *it4++ ;}cout << endl;
}void test3() {zzj::String s4("hello world");zzj::String ss4("abc");s4.push_back('x');cout << s4.c_str() << endl;s4.append(ss4.c_str());cout << s4.c_str() << endl;s4 += ss4.c_str();cout << s4.c_str() << endl;
}void test4() {zzj::String s4("hello world");s4.insert(5,'x');cout << s4.c_str() << endl;zzj::String s5("apple");s4.insert(5,s5.c_str());cout << s4.c_str() << endl;s4.erase(5, 6);cout << s4.c_str() << endl;}void test5() {zzj::String s5("hello world");zzj::String s6("apple");cout << "s5:" << s5.c_str() << endl;cout << "s6:" << s6.c_str() << endl;swap(s5, s6);s5.swap(s6);cout << "s5:" << s5.c_str() << endl;cout << "s6:" << s6.c_str() << endl;
}void test6() {zzj::String s6("hello world");size_t pos = s6.find('w', 0);cout << pos << endl;size_t findstr = s6.find("wor", 3);cout << findstr << endl;zzj::String url2("https://legacy.cplusplus.com/reference/string/string/substr/");zzj::String url1("http://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=1&rsv_idx=1&tn=65081411_1_oem_dg&wd=%E5%90%8E%E7%BC%80%20%E8%8B%B1%E6%96%87&fenlei=256&rsv_pq=0xc17a6c03003ede72&rsv_t=7f6eqaxivkivsW9Zwc41K2mIRleeNXjmiMjOgoAC0UgwLzPyVm%2FtSOeppDv%2F&rqlang=en&rsv_dl=ib&rsv_enter=1&rsv_sug3=4&rsv_sug1=3&rsv_sug7=100&rsv_sug2=0&rsv_btype=i&inputT=1588&rsv_sug4=6786");zzj::String protocol, domain, uri;size_t i1 = url1.find(':');if (i1 != zzj::String::npos){protocol = url1.substr(0, i1 - 0);cout << protocol.c_str() << endl;}// strcharsize_t i2 = url1.find('/', i1 + 3);if (i2 != zzj::String::npos){domain = url1.substr(i1 + 3, i2 - (i1 + 3));cout << domain.c_str() << endl;uri = url1.substr(i2 + 1);cout << uri.c_str() << endl;}}void test7() {zzj::String s7("hello world");zzj::String ss7("apple");cout << (s7 == ss7) << endl;cout << (s7 < ss7) << endl;cout << (s7 <= ss7) << endl;cout << (s7 > ss7) << endl;cout << (s7 >= ss7) << endl;cout << (s7 != ss7) << endl;cout << (s7 == "hello world") << endl;cout << ("apple" == ss7) << endl;}void test8() {zzj::String s8;cin >> s8;cout << s8 << endl;zzj::String ss8("hello world");cout << ss8 << endl;getline(cin,s8);cout << s8 << endl;
}int main() {//test1();//测试构造,拷贝构造,访问//test2();//测试iterator//test3();//测试尾插、追加、+=//test4();//测试插入和删除函数//test5();//测试交换函数//test6();//测试字符串查找和字符串分割//test7();//测试判断大小函数重载test8();//测试输出输入函数
}

我简写了解释,水一篇

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1544137.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

【Java 问题】基础——Java 概述

Java 概述 1. 什么是 Java ?2. Java 语言有哪些特点3. JVM、JDK 和 JRE 有什么区别&#xff1f;4. 说说什么是跨平台性&#xff1f;原理是什么&#xff1f;5. 什么是字节码&#xff1f;采用字节码的好处是什么&#xff1f;6. 为什么说 Java 语言 "编译与解释并存"?…

将 Go 作为脚本语言用及一些好用的包

前言 Go 作为一种可用于创建高性能网络和并发系统的编程语言&#xff0c;它的生态应用变得越来越广泛&#xff0c;同时&#xff0c;这也激发了开发人员使用 Go 作为脚本语言的兴趣。虽然目前 Go 还未准备好作为脚本语言 “开箱即用” 的特性&#xff0c;用来替代 Python 和 Ba…

OpenHarmony(鸿蒙南向开发)——小型系统内核(LiteOS-A)【Perf调测】

往期知识点记录&#xff1a; 鸿蒙&#xff08;HarmonyOS&#xff09;应用层开发&#xff08;北向&#xff09;知识点汇总 鸿蒙&#xff08;OpenHarmony&#xff09;南向开发保姆级知识点汇总~ 持续更新中…… 基本概念 Perf为性能分析工具&#xff0c;依赖PMU&#xff08;Per…

HTML讲解(三)通用部分

目录 1.空格标记 2.特殊文字的标记 3.注释语句 4.对文字字体的设置 5.修改文字形态 6.换行标记 7.居中标记 8.水平线标记 9.设置滚动弹幕 1.空格标记 在HTML中&#xff0c;我们想打印空格并不能直接敲一个空格键&#xff0c;因为如果是敲空格键&#xff0c;那无论你敲…

2万字长文超全详解!深度学习时代阴影检测、去除与生成在图像与视频中的全面综述

论文链接&#xff1a;https://arxiv.org/pdf/2409.02108 Github链接&#xff1a;https://github.com/xw-hu/Unveiling-Deep-Shadows 亮点直击 深度学习时代阴影分析的全面综述。本文对阴影分析进行了深入的综述&#xff0c;涵盖了任务、监督级别和学习范式等各个方面。本文的分…

SpringBoot整合ELK实现日志监控(保姆级教程)

新建SpringBoot项目 pom依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.…

虚幻引擎的三种输入模式和将控件显示到屏幕上

首先要知道一个概念 , HUD 和 Input 都是由 PlayerController 来控制的 而虚幻的Input控制模式有三种 Set Input Mode Game Only (设置输入模式仅限游戏): 视角会跟着鼠标旋转 , 就是正常游戏的模式 , 这也是游戏默认输入模式 Set Input Mode UI Only (设置输入模式仅限UI): …

231. 2 的幂 简单递归 python除法的类型

已解答 简单 相关标签 相关企业 给你一个整数 n&#xff0c;请你判断该整数是否是 2 的幂次方。如果是&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 如果存在一个整数 x 使得 n 2x &#xff0c;则认为 n 是 2 的幂次方。 示例 1&#xff1a; 输入&…

傅里叶变换(对称美)

傅里叶变换&#xff08;对称美&#xff09; 冲浪时发现的有趣文章&#xff0c;学习自https://zhuanlan.zhihu.com/p/718139299 摘下来的内容&#xff1a; 傅里叶变换之所以“怪美的嘞”&#xff0c;根本在于它有一种内在的对称性&#xff0c;这一点在上面的图并没有表现出来…

保障电气安全的电气火灾监控系统主要组成有哪些?

电气火灾是什么&#xff1f; 电气火灾一般是指由于电气线路、用电设备、器具以及供配电设备出现故障性释放的热能&#xff1a;如高温、电弧、电火花以及非故障性释放的能量&#xff1b;如电热器具的炽热表面&#xff0c;在具备燃烧条件下引燃本体或其他可燃物而造成的火灾&…

移动端列表筛选封装

适合场景&#xff1a;Vue2vant 移动端项目&#xff0c;数据填充添加全部选项及相关逻辑处理&#xff0c;支持多选、单选以及筛选状态返回 效果图 选中交互 使用说明 <filter-box ref"filterBox" :isMultiple"true" //是否多选:params"waitData&q…

为什么无线物联网通信技术是智能家居的首选

无线物联网通信技术成为智能家居的首选&#xff0c;主要基于以下几个方面的原因&#xff1a; 一、便捷性与灵活性 无需布线&#xff1a;无线物联网通信技术最大的优势在于其无需复杂的布线工作。在智能家居系统中&#xff0c;这意味着用户无需在墙壁中开凿线路&#xff0c;也无…

夜间红外图宠物检测系统源码分享

夜间红外图宠物检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Comput…

如何使用VM中win10搭建Hfish蜜罐(危险感知平台)。从下载到部署详细教程

得而不惜就该死。 -----古月方源 引言&#xff1a;最近跟一个老师做东西&#xff0c;叫我搞清楚蜜罐的搭建和一些底层逻辑&#xff0c;所以记录一下。 一、实验准备 &#xff08;一&#xff09;win10虚拟机 &#xff08;若有需要可以后台私信&#xff09; &#xff08;二&…

库仑定律-库仑力-两个电荷之间静电力的计算公式

图中&#xff1a; q1&#xff0c;q2 为两个电荷r 为电荷间的距离 r ^ 1 , 2 \widehat{r}_{1,2} r 1,2​ 为从 q1 指向 q2 的单位向量 F ⃗ 1 , 2 \vec{F}_{1,2} F 1,2​ 为 q1 施加到 q2 上的静电力 公式&#xff1a; F ⃗ 1 , 2 q 1 q 2 K r 2 r ^ 1 , 2 \vec{F}_{1,2} \f…

WordPress精选文章如何添加侧边栏和页面?

WordPress精选帖子是一项功能&#xff0c;可让用户在其网站主页或其他值得注意的部分突出显示特定帖子。这些精选帖子通常以视觉上独特的方式显示&#xff0c;例如以滑块、网格或轮播格式显示&#xff0c;以提高其可见性和对访问者的吸引力。 网站所有者可以手动选择他们想要推…

合规性强化:等保测评中的政策与标准遵循

在信息化高速发展的今天&#xff0c;信息安全已成为国家安全的重要组成部分&#xff0c;而等级保护测评&#xff08;简称“等保测评”&#xff09;作为确保信息系统安全的重要手段&#xff0c;其合规性强化显得尤为重要。等保测评不仅是对信息系统安全性能的全面评估&#xff0…

并发编程工具集——Fork/Join-上(三十六)

简述 前面提到的线程池、Future、CompletableFuture 和 CompletionService&#xff0c;这些工具类都是在帮助我们站在任务的视角来解决并发问题&#xff0c;而不是让我们纠缠在线程之间如何协作的细节上&#xff08;比如线程之间如何实现等待、通知等&#xff09;。精髓&#x…

Angular由一个bug说起之十:npm Unsupported engine

我们在用npm下载包的时候&#xff0c;有时候会碰到这样的提示 这是npm的警告&#xff0c;说我们使用的nodejs版本与下载的包所要求的nodejs版本不一致。 这是因为有些包它对nodejs的版本有要求&#xff0c;然后就会在package.json文件里的engines字段里声明它所要求的nodejs版本…

【SemeDrive】【X9HP】【PTG4.3】解决Partition Flash Error及PTG4.3二级分区烧录与升级问题

前言&#xff1a;PTG4.1 之前的版本使用的都是普通 emmc 和 一级分区表&#xff0c;PTG4.3 新增了 virtio-eMMC 功能和二级分区表的设置&#xff0c;因此关于 PTG4.3 的烧录和升级有以下几个疑问和解答。 一、名词解释 virtio-eMMC&#xff1a;基于 Virtio 框架的虚拟化 EMMC…