string接口[小白理解篇]

作文目的

本文是为了加深对string底层函数的一点理解(请勿与底层源码混为一谈),下面从模拟与注意项出发。

一.string 功能化模拟

1.迭代器模拟

迭代器,为实现简单便理解故使用指针的方式(非说明迭代器使用该方法实现)。其中的begin、end都是为了给迭代器提供范围。迭代器也只认该俩函数(不可使用其他名称)。

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;}char& operator[](size_t pos)const{assert(pos<_size);return _str[pos]; }const char operator[](size_t pos)const{assert(pos<_size);return _str[pos];}

2.reserve模拟

该模拟块的实现在于空间的扩展,该处的空间扩展方案并不受限制 可自行选择。切记释放空间,防止空间浪费(好习惯)。

void reserve(size_t sub){if(sub>_capacity){char* ret=new char[sub+1];delete []_str;_str=ret;_capacity=sub;}}

3.resize模拟实现块

该模块的实现需要分清情况,他是要扩大有效值范围,还是缩小范围,如果扩大是否有填充值,最大空间是否能够容纳,如:在不定义填充值时补充缺省值 \0,即不改变数据也扩大了空间,也能在需要时不必重构函数接口。

void resize(size_t size,char ch='\0'){if(size<_size){_str[size]='\0';}else{//可省略判断if(size>_capacity){reserve(size);}for(int i =_size;i<size;i++){_str[i]=ch;    }_str[size]='\0';}_size=size;}

4.insert 模拟实现块

在insert接口,不仅仅要实现单字符的插入,还要可插入字符串的能力;同时不管_str中是否有值

都要追加值,但是如果指定插入点超出实际有效值长时,也必须处理。其次空间不足时也得先扩充空间,不然会出现错误访问。

 void insert(size_t pos, char ch) {assert(pos <= _size);if (_size == _capacity) {reserve(_capacity == 0 ? 4 : 2 * _capacity);}//腾出一块空间,将pos之后的数据后移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);int size = strlen(str);if (size + _size > _capacity) {reserve(size + _size);}int end = _size + size;//下标while (end > _size + size-1) {_str[end] = _str[end - size];end--;}//在pos位置开始拷贝插入size个strncpy(_str + pos, str,size);_size += size;}

5.erase模拟实现块

该接口主在优化,当len大于_size,则一定是全删,不必浪费时间去处理,只有有值得有效调动是 才前移数据。

void erase (size_t pos = 0, size_t len = npos)
{assert (pos <_size);if(len>=_size-pos){  _str[pos]='\0';}else{while (_size>pos+len){_str[pos]=_str[pos+len];pos++;}}_size-=pos
}

6.find模拟实现块

find查找函数,与平时写的查找函数没什么区别,无非就是别越界。

size_t find (char c, size_t pos = 0) const;
{assert(pos<_size);for(int i=pos;i<_size;i++){if(_s[i]==c){return i;}}return npos;
}
size_t find (const char* c, size_t pos = 0) const;
{assert(pos<_size);const char*p=strstr(_str+pos,c);if(p)return p-_str;elsereturn npos;
}

7.substr模拟实现块

截取函数,顾名思义就是截取指定长度中有的效数据,当指定截取范围远大于有效范围是就只截取有效范围内的数据。

string substr (size_t pos = 0, size_t len = npos) const
{assert(pos<_size);string st="";if(len>=_size-pos){for(int i=pos;i<_size;i++){st+=_str[i];      }    }else{for(int i=pos;i<pos+len;i++){st+=_str[i];      }       }return st;
}

8.输入流

第一个代码并非有错误,但是他不太胜任这份工作,他对接口的调用太过于频繁,产生极大且不必要的浪费,故代码二采用模拟缓冲区的办法减轻对接口的调用浪费。

ps: in.get()是输入流提供的一个接收缓冲区单字符的接口,弥补cin不能读储空字符与换行符的缺点

ps: clear每次插入数据,都是一个新值,故清空空间。

/*istream& operator>> (istream& is, string& str){str.clear();char ch;ch=is.get();while(ch!=' '&&ch!='\n'){ch=is.get();str+=ch;}
return str;
}
*/
istream& operator>> (istream& is, string& str){str.clear();int i=0;char ch;char buff[128]="";ch=is.get();while(ch!=' '&&ch!='\n'){buff[i]=ch;i++;if(i==127){buff[127]='\0';i=0;str+=buff;         }ch=is.get();}buff[i]='\0';str+=buff;return is;}istream& getlien(istream& is, string& str){str.clear();int i=0;char ch;char buff[128]="";ch=is.get();while(ch!='\n'){buff[i]=ch;i++;if(i==127){buff[127]='\0';i=0;str+=buff;         }ch=is.get();}buff[i]='\0';str+=buff;return is;}

9.拷贝函数

两种方法都是按同一个方向指向,仅方法实现不同。

// s2(s1)
/*string(const string& s)
{_str = new char[s._capacity + 1];strcpy(_str, s._str);_size = s._size;_capacity = s._capacity;
}*/// s1 = s3;
/*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;
}*/string(string &str){string tmp(str);swap(str);}string& operator+(string str){swap(str);return *this;
}

二.完整版

#pragma once
#define  _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<assert.h>
using namespace std;
namespace bit {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)){_str = new char[_size + 1];strcpy(_str, str);_capacity = _size;}string(const string &str){string tmp(str._str);swap(tmp);}string& operator=( string str){swap(str);return *this;}~string(){delete[] _str;_str= nullptr;_size = _capacity = 0;}size_t size()const {return _size;}const char* c_str()const {return _str;}size_t capacity() {return _capacity;}void clear() {_str[0] = '\0';_size = 0;}const char& operator[](size_t i)const {assert(i < _size);return _str[i];}char& operator[](size_t i) {assert(i < _size);return _str[i];}void reserve(size_t sub) {if (sub > _capacity) {char* ret = new char[sub + 1];strcpy(ret, _str);delete[] _str;_str = ret;_capacity = sub;}}void resize(size_t size, char ch = '\0') {if (size <= _size) {_str[size] = '\0';_size = size;}else {if (size > _capacity) {reserve(size);}for (int i = _size; i < size; i++){_str[i] = ch;}_str[size] = '\0';_size = size;}}void insert(size_t pos, char ch) {assert(pos <= _size);if (_size == _capacity) {reserve(_capacity == 0 ? 4 : 2 * _capacity);}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);int size = strlen(str);if (size + _size > _capacity) {reserve(size + _size);}int end = _size + size;while (end > pos+size-1) {_str[end] = _str[end - size];end--;}strncpy(_str + pos, str, size);_size += size;}void append(const char* str) {insert(_size, str);}void push_back(const char ch) {insert(_size, ch);}string& operator+= (const char* s) {append(s);return *this;}string& operator+= (const char s) {push_back(s);return *this;}void erase(size_t pos = 0, size_t len = npos) {assert(pos < _size);if (len >= _size) {_str[pos]= '\0';}else {while (_size > pos + len){_str[pos]=_str[pos + len];pos++;}_str[pos]= '\0';}_size -= pos;}void swap(string& str) {std::swap(_str, str._str);std::swap(_size, str._size);std::swap(_capacity, str._capacity);}size_t find(char c,size_t pos=0)const{assert(pos < _size);for (int i = pos; i < _size; i++) {if (_str[i]== c) {return i;}}return npos;}size_t find(const char* c, size_t pos = 0) const{assert(pos <= _size);const char* p = strstr(_str + pos, c);if (p)return p - _str;elsereturn npos;}string substr(size_t pos = 0, size_t len = npos) const{string st = " ";assert(pos <= _size);if (len >= _size- pos){for (size_t i = pos; i< _size;i++){st+=_str[i];}}else{for (size_t i = pos; i< pos + len;i++){st+=_str[i];}}return st;}static const int npos;private:char* _str = nullptr;size_t _size = 0;size_t _capacity = 0;};const int string::npos = -1;void swap(string& rhs, string& lhs) {rhs.swap(lhs);}bool operator==(const string& rhs, const string& lhs) {return !strcmp(rhs.c_str(), lhs.c_str());}bool operator!=(const string& rhs, const string& lhs) {return !(rhs == lhs);}bool operator>(const string& rhs, const string& lhs) {return strcmp(rhs.c_str(), lhs.c_str());}bool operator>=(const string& rhs, const string& lhs) {return rhs == lhs || rhs > lhs;}bool operator<(const string& rhs, const string& lhs) {return !(rhs >= lhs);}bool operator<=(const string& rhs, const string& lhs) {return (rhs == lhs) || (rhs < lhs);}ostream& operator<<(ostream& os, const string& str){for (auto ret :str){os << ret;}return os;}istream& operator>> (istream& is, string& str){str.clear();int i = 0; char ch;char buff[128] = "";ch = is.get();while (ch != ' ' && ch != '\n') {buff[i]=ch;i++;if (i == 127){buff[128]='\0';i = 0;str+=buff;}ch = is.get();}buff[i]= '\0';str+=buff;return is;}istream& getline(istream& is, string& str){str.clear();size_t i = 0; char ch;char buff[128] = "";ch = is.get();while (ch != '\n') {buff[i] = ch;i++;if (i == 127){buff[127] = '\0';str += buff;i = 0;}ch = is.get();}if (i > 0) {buff[i] = '\0';str += buff;}return is;}
}

 本文多在理解,感谢观看!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LVGL移植到ARM开发板(GEC6818开发板)

LVGL移植到ARM开发板&#xff08;GEC6818开发板&#xff09; 一、LVGL概述 LVGL&#xff08;Light and Versatile Graphics Library&#xff09;是一个开源的图形用户界面库&#xff0c;旨在提供轻量级、可移植、灵活和易于使用的图形用户界面解决方案。 它适用于嵌入式系统…

MySQL 系统变量查看与设置(System Variables Configuration)

MySQL中有大量的系统变量控制服务器的行为&#xff0c;大部分的系统变量是不需要我们调整的&#xff0c;保持默认即可。但为了获得更高的性能和稳定性&#xff0c;有时需要适当对部分变量进行调整&#xff0c;本文总结了MySQL中系统变量的查看与设置方法。 目录 一、变量的类型…

整数序列删除指定数字,其他数顺序不变

#include <stdio.h>//整数序列删除一个数&#xff0c;其他数顺序不变 int main() {int arr[50] {0};//int arr[50] {1,2,3,4,5};int n 0;int del 0;int i 0;int j 0;scanf("%d",&n);for(i 0;i < n;i)scanf("%d",&arr[i]);scanf(&q…

未来城市:数字孪生技术助力智慧城市构建

目录 一、数字孪生技术的兴起与定义 二、数字孪生技术在智慧城市构建中的应用 1、城市规划与管理 2、智慧交通 3、智慧能源 4、智慧环保 三、数字孪生技术助力智慧城市构建的挑战与对策 四、结语 随着科技的飞速发展&#xff0c;未来城市正在经历一场前所未有的变革。数…

Maven简单入门

Maven 一&#xff1a;什么是Maven&#xff1a; Maven是一个项目管理工具&#xff0c;用于构建和管理Java项目。它可以帮助开发人员自动化构建过程&#xff0c;管理项目依赖关系&#xff0c;并协助项目的发布和部署。通过Maven&#xff0c;开发人员可以定义项目的结构、依赖关…

C语言例3-11:使用算术运算符的例子。

代码如下&#xff1a; int main(void) {int a12, b10;float c2.0, d0.5;double e6.5, f13.0;printf("-a %d\n",-a);printf("ab %d\n",ab);printf("a-b %d\n",a-b);printf("a*b %d\n",a*b);printf("a/b %d\n"…

SE园区综合实验(未补齐版)

实验要求&#xff1a; 1.局域网存在vlan10和vlan20两个业务vlan&#xff0c;ip网段分别对应192.168.1.0/24和192.168.2.0/24 2.业务vlan可以在所有链路上传输数据 3.sw1和sw2之间的直连链路上配置静态链路聚合实现链路冗余&#xff0c;并提高链路带宽 4.sw3为某接入点二次交…

SpringBoot 项目整合xxl-job

一、简介 XXL-JOB是一个分布式任务调度平台&#xff0c;其核心设计目标是开发迅速、学习简单、轻量级、易扩展。要想在SpringBoot 项目中接入到XXL-JOB中进行分布式定时任务处理&#xff0c;可以参考官方文档: https://www.xuxueli.com/xxl-job/ 二、下载并部署调度中心 2.1…

【LeetCode】84. 柱状图中最大的矩形(困难)——代码随想录算法训练营Day60

题目链接&#xff1a;84. 柱状图中最大的矩形 题目描述 给定 n 个非负整数&#xff0c;用来表示柱状图中各个柱子的高度。每个柱子彼此相邻&#xff0c;且宽度为 1 。 求在该柱状图中&#xff0c;能够勾勒出来的矩形的最大面积。 示例 1: 输入&#xff1a;heights [2,1,5,…

msfconsole数据库连接不了的问题【已解决】

msfconsole数据库连接 1.msf数据库端口 msf使用的是postgresql&#xff0c;这个数据库默认端口是5432 单个模块的使用可以不需要数据库&#xff0c;但是模块与模块之间需要沟通的时候就会用到数据库。 2.查看msf数据库连接状态 db_status #msf内部查看systemctl status p…

HTML视频笔记

学习arm开发板&#xff0c;涉及到网页HTML PHP什么的&#xff0c;简单看个视频学习下 HTML&#xff5c;超简单HTML入门教程 https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element ​​​​​​vscode需要的libc6等需要的版本高​​​​​​ 为了安装vscode&#xff0c;将…

Spring Cloud Alibaba微服务从入门到进阶(四)(服务发现-Nacos )

Nacos是服务发现组件和配置服务器 作为服务发现注册组件Nacos Server 搭建Nacos Server 下载、启动 访问nacos,默认 用户/密码 nacos/nacos 将应用注册到nacos 加依赖 在SpringCloud子项目中&#xff0c;Feign是属于OpenFeign&#xff0c;Sentinel、Nacos是属于alibaba的&…

FX110网:1月美国零售货币资金环比上升2.61%,嘉盛环比上升1.86%

美国商品期货交易委员会&#xff08;CFTC&#xff09;发布的最新月度报告显示&#xff0c;2024年1月零售货币存款与上月相比上升2.61%。 这份报告涵盖在美国运营的注册零售货币对交易商&#xff08;RFED&#xff09;和经纪自营商。包括嘉信理财&#xff08;CHARLES SCHWAB Futu…

【安装mysql】centos7 安装mysql

文章目录 1.卸载不用的环境2.获取mysql官方yum源3.开始安装4.常规登录4.1方法一&#xff1a;【博主可以】4.2方法二&#xff1a;直接用client登录4.3方法三&#xff1a;修改配置文件 5.设置配置文件5.1配置my .cnf5.2开机自启动 1.卸载不用的环境 查看有无mysql/mariadb ps ax…

天地图全国幼儿园数据下载与处理分析

概述 在看天地图服务资源的时候看到有个“幼儿园”的数据&#xff0c;好奇点开看了下&#xff0c;下载下来数据差看了下&#xff0c;数据质量还不错。本篇文章给大家分享一下这个数据的处理以及一些简单的统计分析结果。 数据下载 通过地址https://service.tianditu.gov.cn/…

嵌入式方向还有希望吗?

我刚开始学习&#xff0c;也不知道我定位的是单片机工程师&#xff0c;嵌入式工程师职位的。 我只知道电子工程师&#xff0c;这个职位其实偏硬件&#xff0c;很多岗位需求是硬件设计&#xff0c;PCB设计&#xff0c;还要懂焊接、各种仪器仪表使用&#xff0c;还有些需要懂单片…

Git提交代码进入coding

安装Git后建一个文件在文件里右键点击Git Bash使用命令配置用户名和邮箱git config --global user.name "你的用户名"和git config --global user.email "你的邮箱"命令git init来初始化&#xff0c;自动将当前仓库设置为master创建一个项目&#xff08;一…

C#操作像素替换图片中的指定颜色

待处理的图片&#xff0c;其特征是包含有限数量颜色&#xff0c;不同的颜色相互交叉使用&#xff0c;相同颜色并未完全连贯&#xff0c;需要将图片中的指定颜色替换为另一颜色。虽然很多图片处理工具都支持类似操作&#xff0c;最后还是自己动手编写简单的处理程序。   程序的…

4种小众的能力,帮你更好地适应未来

新年伊始&#xff0c;又是一个全新的开始。 未来的社会究竟需要什么样的能力&#xff1f;这已经是一个很老的话题&#xff0c;已经有许许多多讨论了。但这其中&#xff0c;可能有一些是容易被人忽略的&#xff0c;或者不容易被注意到的。 我想跟你一起分享&#xff0c;我对这个…

Live800:企业如何与客户建立长期、稳定关系,实现双赢

在当今的商业环境中&#xff0c;企业不仅需要吸引新客户&#xff0c;更需要与现有客户建立长期、稳定的关系。这样的关系可以带来持续的收入&#xff0c;提高企业的利润性。然而&#xff0c;如何建立和维护这样的关系呢&#xff1f;文章将从三个方面进行深入探讨&#xff1a;提…