c++|string模拟实现

 

目录

一、string.h

二、string.cpp

三、Test.cpp


对string的各种接口进行一个简易版的模拟实现,在模拟实现完之后对string的底层实现有了进一步的理解,了解大佬的编程写法思路。也算是对string有了一个小总结。

一、string.h

接口的声明。放在.h文件中 

#include <iostream>
#include <string>
#include <assert.h>
using namespace std;namespace bit
{class string{public:typedef char* iterator;//迭代器本质上就是指针typedef const char* const_iterator;iterator begin() const{return _str;}iterator end(){return _str + _size;}const_iterator end() const{return _str + _size;}string(const char* s = "");string(const string& s);string& operator=(string s);~string();void push_back(char c);string& operator+=(char c);string& operator+=(const string& s);string& operator+=(const char* str);void append(const char* str);void clear();void swap(string& s);const char* c_str()const;//capacitysize_t size();size_t capacity();void resize(size_t n, char c = '\0');void reserve(size_t n);bool empty()const;bool operator<(const string& s);bool operator<=(const string& s);bool operator>(const string& s);bool operator>=(const string& s);bool operator==(const string& s);;bool operator!=(const string& s);char& operator[](size_t i);const char& operator[](size_t i) const;//返回字符第一次在字符串出现的位置size_t find(char c, size_t pos = 0) const;;//在pos位置插入字符cstring& insert(size_t pos, char c);//在pos位置插入字符串string& insert(size_t pos, const char* str);//返回子串在字符串中出现的位置size_t find(const char* str, size_t pos = 0);string substr(size_t pos = 0, size_t len = npos);//	删除pos位置上的元素,并返回该元素的下一个位置string& erase(size_t pos, size_t len = npos);private:size_t _size;size_t _capacity;char* _str;//静态变量可以赋值处理的前提是有const修饰,这个可以看作是编译器的特殊处理,只能适用于整形家族static const size_t npos = -1;};ostream& operator<<(ostream& out, const string& s);istream& operator>>(istream& in, string& s);
}

二、string.cpp

接口的各种实现。进行声明定义分离时,要注意格式上的变化,指定类域,声明和定义中,只有声明中可以给缺省值,定义中不能给。string的构造函数有传统写法和现代写法,现代写法更简洁,但和传统写法本质上没有太大的区别

#include "string.h"namespace bit
{//string()//	:_str(nullptr)//不能给空,析构时会对空指针解引用,从而报错//	,_size(0)//	,_capacity(0)//{}//string()//	:_size(0)//	,_capacity(_size)//	,_str(new char[_capacity + 1])//这样必须给定成员变量声明顺序。//{}string::string(const char* s){_size = strlen(s);_capacity = _size;_str = new char[_capacity + 1];strcpy(_str, s);}//传统写法/*	string(const string& s){_str = new char[s._capacity + 1];_size = s._size;_capacity = s._capacity;strcpy(_str, s._str);}*///现代写法string::string(const string& s){string tmp(s._str);swap(tmp);}//传统写法//string& operator=(const string& s)//{//	if (*this != s)//	{//		char* tmp = new char[s._capacity + 1];//		delete[] _str;//		strcpy(tmp, s._str);//		_str = tmp;//		_size = s._size;//		_capacity = s._capacity;//		return *this;//	}//	return *this;//	//}//现代写法/*string& operator=(const string s){string tmp(s._str);swap(tmp);return *this;}*/string& string::operator=(string s){swap(s);return *this;}string::~string(){delete[] _str;_str = nullptr;_size = 0;_capacity = 0;}//modifyvoid string::push_back(char c){if (_size == _capacity)//初始化容量以及判断容量是否满了{size_t newcapacity = _capacity == 0 ? 4 : _capacity * 2;/*		if (_str != ""){char* tmp = new char[newcapacity + 1];memcpy(tmp, _str, _size);delete[] _str;_str = tmp;_capacity = newcapacity;}*/reserve(newcapacity);}_str[_size] = c;_size++;_str[_size] = '\0';}string& string::operator+=(char c){push_back(c);return *this;}string& string::operator+=(const string& s){if (_size + s._size > _capacity){reserve(_size + s._size);}strcpy(_str + _size, s._str);_size += s._size;return *this;}string& string::operator+=(const char* str){append(str);return *this;}void string::append(const char* str){if (_size + strlen(str) > _capacity){reserve(_size + strlen(str));}strcpy(_str + _size, str);_size += strlen(str);}void string::clear(){_str[0] = '\0';_size = 0;_capacity = 0;}void string::swap(string& s){std::swap(_str, s._str);std::swap(this->_size, s._size);std::swap(this->_capacity, s._capacity);}const char* string::c_str()const{return _str;}//capacitysize_t string::size(){return _size;}size_t string::capacity(){return _capacity;}void string::resize(size_t n, char c){if (n > _capacity){reserve(n);for (int i = _capacity; i < n; i++)push_back(c);}else if (n > _size && n < _capacity){for (int i = _size; i < n; i++)push_back(c);}else if (n < _size){_str[n] = '\0';}}void string::reserve(size_t n){if (n > _capacity){char* tmp = new char[n + 1];strcpy(tmp, _str);delete[] _str;_str = tmp;//_size = strlen(tmp);_capacity = n;}}bool string::empty()const{return _str == "";}bool string::operator<(const string& s){return strcmp(_str, s._str) < 0;}bool string::operator<=(const string& s){return !(*this > s);}bool string::operator>(const string& s){return strcmp(_str, s._str) > 0;}bool string::operator>=(const string& s){return !(*this < s);}bool string::operator==(const string& s){return strcmp(_str, s._str) == 0;}bool string::operator!=(const string& s){return !(strcmp(_str, s._str) == 0);}char& string::operator[](size_t i){return _str[i];}const char& string::operator[](size_t i) const{return _str[i];}//返回字符第一次在字符串出现的位置size_t string::find(char c, size_t pos) const{assert(pos <= _size);for (int i = pos; i < _size; i++){if (_str[i] == c)return i;}return npos;}//在pos位置插入字符cstring& string::insert(size_t pos, char c){assert(pos <= _size);if (_size == _capacity){size_t newcapacity = _capacity == 0 ? 4 : _capacity * 2;reserve(newcapacity);}if (pos == _size)push_back(c);else{size_t len = _size - pos;while (len){_str[pos + len] = _str[pos + len - 1];len--;}_str[pos] = c;}_size++;_str[_size] = '\0';return *this;}//在pos位置插入字符串string& string::insert(size_t pos, const char* str){assert(pos <= _size);size_t len = strlen(str);if (len + _size >= _capacity){reserve(len + _size);}if (pos == _size){append(str);}else{size_t ilen = _size - pos;while (ilen){_str[pos + ilen + len] = _str[pos + ilen];ilen--;}for (int i = pos, j = 0; i < pos + len; i++, j++){_str[i] = str[j];}}_size += len;_str[_size] = '\0';return *this;}//返回子串在字符串中出现的位置size_t string::find(const char* str, size_t pos){assert(pos <= _size);size_t len = strlen(str);if (pos + len > _size)return npos;else{size_t fpos = find(str[0], pos);for (int i = fpos, j = 0; i < fpos + len; i++, j++){if (str[j] != _str[i])return npos;}return fpos;}}string string::substr(size_t pos, size_t len){assert(pos <= _size);string tmp;size_t end = pos + len;//if (len == npos || len >= _size - pos)//{//	tmp.reserve(_size - pos);//	strcpy(tmp._str, _str + pos);//	return tmp;//}//else//{//	memcpy(tmp._str, _str + pos, len);//	tmp[len] = '\0';//	return tmp;//}if (len == npos || len >= _size - pos){end = _size;}tmp.reserve(end - pos);for (int i = pos; i < end; i++){tmp += _str[i];}return tmp;}//	删除pos位置上的元素,并返回该元素的下一个位置string& string::erase(size_t pos, size_t len){assert(pos < _size);if (len == npos || len > _size){_str[pos] = '\0';}else{/*size_t length = len + pos;while (pos < length){_str[pos] = _str[pos + len];pos++;}_str[_size - len] = '\0';*/strcpy(_str + pos, _str + pos + len);_size -= len;}return *this;}ostream& operator<<(ostream& out, const string& s){for (auto e : s){out << e;}return out;}istream& operator>>(istream& in, string& s){s.clear();char buff[128];char ch = in.get();int i = 0;while (ch != ' ' && ch != '\n'){buff[i] = ch;i++;if (i == 127){buff[i] = '\0';s += buff;i = 0;}ch = in.get();}if (i > 0){buff[i] = '\0';s += buff;}return in;}}

三、Test.cpp

测试版本,对接口进行测试,写了三个测试版本,但并没有调用全部接口,进行一番演示,大致还行,可能还有错误,也是水平有限。 

#include "string.h"
namespace bit
{void stringtest1(){string s("hello world");string::iterator it = s.begin();while (it != s.end()){cout << *it;it++;}cout << endl;for (auto e : s){cout << e;}cout << endl;string s1(s);string s2 = s1;for (auto e : s1){cout << e;}cout << endl;for (auto e : s2){cout << e;}cout << endl;}void stringtest2(){string s("hello world");s += "hello world";for (auto e : s){cout << e;}cout << endl;string s1;s1.push_back('a');s1.push_back('b');s1.push_back('c');s1.push_back('d');for (auto e : s1){cout << e;}cout << endl;cout << (s < s1);cout << (s > s1);cout << (s == s1);cout << (s <= s1);cout << (s >= s1);cout << true;};void stringtest3(){string s("hello world");string s1 = "excuse me";/*s.swap(s1);cout << s.c_str() << " " << s1.c_str() << endl;cout << s.capacity() << endl;s.reserve(100);cout << s.capacity() << endl;s.resize(5);cout << s.capacity() << " " << s.c_str() << endl;;*///cout << s[0];size_t pos = s.find("world");cout << pos << endl;cout << s.substr().c_str() << endl;s.insert(0, 'w');cout << s.c_str() << endl;s.insert(6, 'e');cout << s.c_str() << endl;s1.insert(0, "hello");cout << s1.c_str() << endl;s1.insert(5, "hello");cout << s1.c_str() << endl;cin >> s1;cout << s1;}
}
int main()
{bit::stringtest1();bit::stringtest2();bit::stringtest3();return 0;
}

三个测试函数的输出结果 :

 

 

 

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

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

相关文章

实验7 内置对象response

编写代码&#xff0c;掌握request、response的用法。【参考课本4.6.2】 三、源代码以及执行结果截图&#xff1a; input.jsp <% page language"java" contentType"text/html; charsetutf-8" pageEncoding"utf-8"%> <!DOCTYPE html>…

【tensorflow框架神经网络实现鸢尾花分类】

文章目录 1、数据获取2、数据集构建3、模型的训练验证可视化训练过程 1、数据获取 从sklearn中获取鸢尾花数据&#xff0c;并合并处理 from sklearn.datasets import load_iris import pandas as pdx_data load_iris().data y_data load_iris().targetx_data pd.DataFrame…

Unbtun-arach64架构安装PySide2(python3.6)

aarch平台是无法通过pip安装PySide2的&#xff0c;同时利用源码下载一直报错 1. 我是python3.6.9&#xff0c;在官网上找到对应的PySide2版本 5.15.2.所以首先在官网下载Qt5.15.2的源码&#xff1a;https://download.qt.io/archive/qt/5.15/5.15.2/single/ 2. 编译qt环境 aar…

实验2-spark编程

实验目的 &#xff08;1&#xff09;通过实验掌握Spark的基本编程方法&#xff1b; &#xff08;2&#xff09;熟悉RDD到DataFrame的转化方法&#xff1b; &#xff08;3&#xff09;熟悉利用Spark管理来自不同数据源的数据。 实验内容 1&#xff0e;Spark基本操作 请参照…

Nginx官方镜像Dockerfile浅析

目录 Dockerfile获取 dfimage逆向获取 Nginx官网获取 Dockerfile分析 启动命令分析 Docker 容器入口点脚本分析 exec "$" exec 命令 "$" 参数 总结 在云原生技术快速发展的今天&#xff0c;Docker 作为容器技术的代表&#xff0c;为软件的打包、…

磐启/PAN7030/2.4GHz 无线收发SOC芯片/ESSOP10/SOP16

1 概述 PAN7030 是一款集成 8 位 OTP MCU 和 2.4GHz 无线收发电路芯片&#xff0c;适合应用于玩具小车、 遥控器等领域。 PAN7030 内置 8 位 OTP MCU&#xff0c;包括 1.25KW 的程序存储器、80 字节数据存储器、16 位定 时器和 8 位/11 位 PWM 定时器、看门狗、电压比较器等…

【QT入门】 QTabWidget各种常见用法详解

往期回顾&#xff1a; 【QT入门】 Qt代码创建布局之分裂器布局详解-CSDN博客 【QT入门】 Qt代码创建布局之setLayout使用-CSDN博客 【QT入门】 Qt代码创建布局之多重布局变换与布局删除技巧-CSDN博客 【QT入门】 QTabWidget各种常见用法详解 一般来说&#xff0c;学一个新的控…

出行在外,又想用微软远程桌面控制千里之外的电脑?

前言 说到远程控制&#xff0c;想必很多小伙伴都不陌生。毕竟向日葵软件都是各位所熟知的远程控制软件。 出行在外&#xff0c;使用向日葵远程控制家里或者办公室的电脑是很常见的做法。在各种远程维修电脑的场景下&#xff0c;客服都会要求客户先安装好远程控制软件。 但是向…

探索 2024 年 Web 开发最佳前端框架

前端框架通过简化和结构化的网站开发过程改变了 Web 开发人员设计和实现用户界面的方法。随着 Web 应用程序变得越来越复杂&#xff0c;交互和动画功能越来越多&#xff0c;这是开发前端框架的初衷之一。 在网络的早期&#xff0c;网页相当简单。它们主要以静态 HTML 为特色&a…

在scroll-view中使用input,input键盘弹出时,滚动页面,输入框内容会出现错位问题?

解决办法 <view classpages><view><scroll-view scroll-y"{{sysScroll}}" scroll-top"{{scrollTop}}" class"scroll-hei-2 bg-def">...<input bindfocus"onfocus" bindblur"onblur" placeholder&quo…

kprobe/kretprobe的介绍,原理图,运行情况,用户层代码+内核层代码+预编译代码(详细解释+语法介绍),修改.bpf.c入口处的函数

目录 kprobe/kretprobe 介绍 原理图 运行情况 代码解释 .bpf.c 源码 语法 / 函数接口 char LICENSE[] SEC("license") "Dual BSD/GPL" SEC do_unlinkat filename结构体 ​编辑 BPF_KPROBE bpf_get_current_pid_tgid(…

Vue 04 Vue 中的 Ajax、slot 插槽

Vue学习 Vue 0401 Vue中的Ajax服务器准备axios使用跨域问题解决Vue-CLI 配置代理1Vue-CLI 配置代理2案例: 用户搜索vue-resource 02 slot插槽默认插槽具名插槽作用域插槽slot总结 Vue 04 B站 Vue全家桶&#xff08;BV1Zy4y1K7SH&#xff09; 学习笔记 Vue 中的 ajax 01 Vue中的…

设计模式之原型模式讲解

原型模式本身就是一种很简单的模式&#xff0c;在Java当中&#xff0c;由于内置了Cloneable 接口&#xff0c;就使得原型模式在Java中的实现变得非常简单。UML图如下&#xff1a; 我们来举一个生成新员工的例子来帮助大家理解。 import java.util.Date; public class Employee…

SnapGene 5 for Mac 分子生物学软件

SnapGene 5 for Mac是一款专为Mac操作系统设计的分子生物学软件&#xff0c;以其强大的功能和用户友好的界面&#xff0c;为科研人员提供了高效、便捷的基因克隆和分子实验设计体验。 软件下载&#xff1a;SnapGene 5 for Mac v5.3.1中文激活版 这款软件支持DNA构建和克隆设计&…

python仿真报告自动化——excite TD齿轮角加速度级计算

python仿真报告自动化——excite TD齿轮角加速度级计算 1 、问题-燃油泵相位优化2、难点-excite TD结果文件的提取3、代码 1 、问题-燃油泵相位优化 用excite TD对齿轮系进行仿真&#xff0c;模拟不同燃油泵相位对齿轮传动振动的影响&#xff0c;用齿轮角加速度级作为评价指标…

Redis命令介绍

一、redis启动&#xff1a; 本地启动&#xff1a;redis-cli 远程启动&#xff1a;redis-cli -h host -p port -a password Redis 连接命令 1 AUTH password 验证密码是否正确 2 ECHO message 打印字符串 3 PING 查看服务是否运行 4 QUIT 关闭当前连接 5 SELECT index 切换…

Postman测试含有变量的接口的方法

1.在路径中用/&#xff1a;设置变量名 2.设置token验证 3.填写参数

Cisco Firepower FMCv修改管理Ip方法

FMCv 是部署在VMWARE虚拟平台上的FMC 部署完成后&#xff0c;如何修改管理IP 1 查看当前版本 show version 可以看到是for VMware 2 修改管理IP步骤 2.1 进入expert模式 expert2.2 进入超级用户 sudo su并输入密码 2.3 查看当前网卡Ip 2.4 修改Ip 命令&#xff1a; /…

前端基础知识html

一.基础标签 1.<h1>-<h6>:定义标题&#xff0c;h最大&#xff0c;h最小 2.<font>&#xff1a;定义文本的字体&#xff0c;尺寸&#xff0c;颜色 3.<b>&#xff1a;定义粗体文本 4.<i>&#xff1a;定义斜体文本 5.<u>&#xff1a;定义文本下…

基于js css的瀑布流demo

要实现照片按照瀑布流展示&#xff0c;写个小demo&#xff0c;记录下。 瀑布流实现思路如下&#xff1a; CSS 弹性布局对 3 列按横向排列&#xff0c;对每一列内部按纵向排列 html代码&#xff1a; <div class"content"></div> css代码&#xff1a; …