C/C++ 入门(7)string类(STL)

个人主页:仍有未知等待探索-CSDN博客

专题分栏:C++

                                                        请多多指教!

目录

一、标准库中的string

1、了解

2、string类常用接口说明

1、常见的构造函数

2、容量操作 ​编辑

3、访问及遍历操作

4、修改操作

5、非成员函数

 二、string类实现

1、string类的大体框架

2、构造和析构函数 

3、迭代器 

4、成员函数 

5、非成员函数

 三、问题

1、深拷贝和浅拷贝问题

2、strcpy,memcpy

四、总代码


一、标准库中的string

1、了解

1、string是表示字符串的字符串类
2、该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。

2、string类常用接口说明

下面的函数都可以去下面的网址进行查文档,来看函数的功能。(接下来我会实现这个string类)

string - C++ Reference

1、常见的构造函数

string类对象的常见构造
函数名称功能说明
string()        构造空的string类,即空字符串
string(const char*s)

用c_str()来构造string类对象

string(size_t n, char c)string类对象中包含n个字符c
string(const string& s)拷贝构造函数

2、容量操作
 

3、访问及遍历操作

4、修改操作

5、非成员函数

 二、string类实现

实现string类能让我们更好的明白模板的使用,函数重载等等。

1、string类的大体框架

#include <iostream>
#include <cstring>
#include <assert.h>
using namespace std;class string
{
public:private:char* _str; // string存的字符串size_t _size; // string中字符串的长度 size_t _capacity; // string的容量
};

2、构造和析构函数 

string():_str(nullptr),_size(0),_capacity(0)
{}
string(const char* str):_size(strlen(str)),_capacity(_size)
{_str = new char[_capacity + 1];strcpy(_str, str);
}
string(const string& str):_str(new char[str._capacity + 1]),_size(str._size),_capacity(str._capacity)
{strcpy(_str, str._str);
}
~string()
{delete[] _str;_str = nullptr;_size = 0;_capacity = 0;
}

3、迭代器 

typedef char* iterator;
iterator begin()
{return _str;
}
iterator end()
{return _str + _size;
}

4、成员函数 


string& operator=(const string& str)
{char* tmp = new char[str._capacity + 1];strcpy(tmp, str._str);delete[] _str;_str = tmp;_size = str._size;_capacity = str._capacity;return *this;
}
void reserve(int x)
{if (_capacity < x){char* tmp = new char[x + 1];strcpy(tmp, _str);delete[] _str;_str = tmp;_capacity = x;}
}
void swap(string& str)
{std::swap(_str, str._str);std::swap(_size, str._size);std::swap(_capacity, str._capacity);
}
const char* c_str() const
{return _str;
}
void clear()
{_str[0] = '\0';_size = 0;
}
void insert(int index, const string& str)
{int len = str._size;assert(index >= 0 && index < _size);if (_size + len >= _capacity){reserve(_capacity + len);}for (int i = _size - 1; i >= index; i -- ){_str[i + len] = _str[i];}for (int j = 0, i = index; j < str._size; j ++ ,i ++ ){_str[i] = str._str[j];}_size += len;
}
void insert(int index, char ch)
{assert(index >= 0 && index < _size);if (_size + 1 >= _capacity){reserve(2 * _capacity);_capacity *= 2;}for (int i = _size - 1; i >= index; i -- ){_str[i + 1] = _str[i];}_str[index] = ch;_size ++ ;}
void append(const string& str)
{int len = str._size;if (len + _size > _capacity){reserve(len + _size);_capacity = len * _size;}int end = _size;for (int i = 0; i < str._size; i ++ ,end ++ ){_str[end] = str._str[i];}_size += len;
}
string& operator+=(const string& str)
{append(str);return *this;
}
void push_back(const char ch)
{if (_size + 1 >= _capacity){reserve(2 * _capacity);}_capacity *= 2;_str[_size] = ch;_size ++ ;
}
int size() const
{return _size;
}
int capacity() const
{return _capacity;
}
bool empty() const
{return _size == 0;
}
void resize(int n, char ch = '\0')
{if (n < _size){for (int i = n; i < _size; i ++ ){_str[i] = '\0';}}else if (n + 1 < _capacity){for (int i = _size; i < n; i ++ ){_str[i] = ch;}}else{reserve(n);}
}
char& operator[](size_t index)
{assert(index < _size);return _str[index];
}
const char& operator[](size_t index)const
{assert(index < _size);return _str[index];
}
bool operator==(const string& str)
{int ret = strcmp(_str, str.c_str());return ret == 0;
}
bool operator!=(const string& str)
{return !(*this == str);
}
bool operator>(const string& str)
{int ret = strcmp(_str, str.c_str());return ret > 0;
}
bool operator<(const string& str)
{int ret = strcmp(_str, str.c_str());return ret < 0;
}
bool operator<=(const string& str)
{return *this < str || *this == str;
}
bool operator>=(const string& str)
{return *this > str || *this == str;
}
int 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;
}
int find (const char* s, size_t pos = 0) const
{char* p = strstr(_str + pos, s);if (p != nullptr){return p - _str;}return npos;
}
string& erase (size_t pos = 0, size_t len = npos)
{assert(pos < _size);if (len == npos || len >= _size - pos){_str[pos] = '\0';_size = pos;}else{int i = 0;for (i = pos + len; i < _size; i ++ ){_str[i - len] = _str[i];}_str[i] = '\0';_size -= len;}return *this;
}

5、非成员函数

    ostream& operator<<(ostream& out, const string& str){int len = str._size;for (int i = 0; i < len; i ++ ){out << str._str[i];}return out;}istream& operator>>(istream& in, string& str){str.clear();char ch = in.get();char buff[128];int i = 0;while (ch != ' ' && ch != '\n'){buff[i ++ ] = ch;if (i == 127){buff[i] = '\0';str += buff;i = 0;}ch = in.get();}if (i != 0){buff[i] = '\0';str += buff;}return in;}
}

 三、问题

1、深拷贝和浅拷贝问题

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


深拷贝:每个对象都有一份独立的资源,不要和其他对象共享。如果一个类中涉及到资源的管理,其拷贝构造函数、赋值运算符重载以及析构函数必须要显式给出。一般情况都是按照深拷贝方式提供。

2、strcpy,memcpy

通过下面的例子也能清晰的看出来,这两个拷贝函数都是浅拷贝。所以在用的时候需要小心谨慎。

四、总代码

#include <iostream>
#include <cstring>
#include <assert.h>
using namespace std;namespace my
{class string{public:string():_str(nullptr),_size(0),_capacity(0){}string(const char* str):_size(strlen(str)),_capacity(_size){_str = new char[_capacity + 1];strcpy(_str, str);}string(const string& str):_str(new char[str._capacity + 1]),_size(str._size),_capacity(str._capacity){strcpy(_str, str._str);}~string(){delete[] _str;_str = nullptr;_size = 0;_capacity = 0;}typedef char* iterator;iterator begin(){return _str;}iterator end(){return _str + _size;}string& operator=(const string& str){char* tmp = new char[str._capacity + 1];strcpy(tmp, str._str);delete[] _str;_str = tmp;_size = str._size;_capacity = str._capacity;return *this;}void reserve(int x){if (_capacity < x){char* tmp = new char[x + 1];strcpy(tmp, _str);delete[] _str;_str = tmp;_capacity = x;}}void swap(string& str){std::swap(_str, str._str);std::swap(_size, str._size);std::swap(_capacity, str._capacity);}const char* c_str() const{return _str;}void clear(){_str[0] = '\0';_size = 0;_capacity = 0;}void insert(int index, const string& str){int len = str._size;assert(index >= 0 && index < _size);if (_size + len >= _capacity){reserve(_capacity + len);}for (int i = _size - 1; i >= index; i -- ){_str[i + len] = _str[i];}for (int j = 0, i = index; j < str._size; j ++ ,i ++ ){_str[i] = str._str[j];}_size += len;}void insert(int index, char ch){assert(index >= 0 && index < _size);if (_size + 1 >= _capacity){reserve(2 * _capacity);_capacity *= 2;}for (int i = _size - 1; i >= index; i -- ){_str[i + 1] = _str[i];}_str[index] = ch;_size ++ ;}void append(const string& str){int len = str._size;if (len + _size > _capacity){reserve(len + _size);_capacity = len * _size;}int end = _size;for (int i = 0; i < str._size; i ++ ,end ++ ){_str[end] = str._str[i];}_size += len;}string& operator+=(const string& str){append(str);return *this;}void push_back(const char ch){if (_size + 1 >= _capacity){reserve(2 * _capacity);}_capacity *= 2;_str[_size] = ch;_size ++ ;}int size() const{return _size;}int capacity() const{return _capacity;}bool empty() const{return _size == 0;}void resize(int n, char ch = '\0'){if (n < _size){for (int i = n; i < _size; i ++ ){_str[i] = '\0';}}else if (n + 1 < _capacity){for (int i = _size; i < n; i ++ ){_str[i] = ch;}}else{reserve(n);}}char& operator[](size_t index){assert(index < _size);return _str[index];}const char& operator[](size_t index)const{assert(index < _size);return _str[index];}bool operator==(const string& str){int ret = strcmp(_str, str.c_str());return ret == 0;}bool operator!=(const string& str){return !(*this == str);}bool operator>(const string& str){int ret = strcmp(_str, str.c_str());return ret > 0;}bool operator<(const string& str){int ret = strcmp(_str, str.c_str());return ret < 0;}bool operator<=(const string& str){return *this < str || *this == str;}bool operator>=(const string& str){return *this > str || *this == str;}int 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;}int find (const char* s, size_t pos = 0) const{char* p = strstr(_str + pos, s);if (p != nullptr){return p - _str;}return npos;}string& erase (size_t pos = 0, size_t len = npos){assert(pos < _size);if (len == npos || len >= _size - pos){_str[pos] = '\0';_size = pos;}else{int i = 0;for (i = pos + len; i < _size; i ++ ){_str[i - len] = _str[i];}_str[i] = '\0';_size -= len;}return *this;}friend ostream& operator<<(ostream& out, const string& str);friend istream& operator>>(istream& in, string& str);private:char* _str; // string存的字符串size_t _size; // string中字符串的长度 size_t _capacity; // string的容量static const size_t npos = -1;};inline ostream& operator<<(ostream& out, const string& str){int len = str._size;for (int i = 0; i < len; i ++ ){out << str._str[i];}return out;}inline istream& operator>>(istream& in, string& str){str.clear();char ch = in.get();char buff[128];int i = 0;while (ch != ' ' && ch != '\n'){buff[i ++ ] = ch;if (i == 127){buff[i] = '\0';str += buff;i = 0;}ch = in.get();}if (i != 0){buff[i] = '\0';str += buff;}return in;}
}

谢谢大家! 

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

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

相关文章

如何训练一个大语言模型(LLMs)

目录 前言大语言模型 Vs机器学习模型训练过程步骤1&#xff1a;数据策划&#xff08;Data Curation)步骤2&#xff1a;格式化与预处理步骤3&#xff1a;训练模型步骤4&#xff1a;模型评估 LLM Leaderboard[LLM Leaderboard 2024](https://www.vellum.ai/llm-leaderboard)[Open…

软考 系统架构设计师系列知识点之大数据设计理论与实践(13)

接前一篇文章&#xff1a;软考 系统架构设计师系列知识点之大数据设计理论与实践&#xff08;12&#xff09; 所属章节&#xff1a; 第19章. 大数据架构设计理论与实践 第4节 Kappa架构 19.4.2 Kappa架构介绍 Kappa架构由Jay Kreps提出&#xff08;Lambda由Storm之父Nayhan M…

智慧水务是什么样的?如何打造智慧水务大屏?

在信息化和数字化快速发展的今天&#xff0c;智慧水务作为城市供水管理的重要组成部分&#xff0c;正变得越来越重要。智慧水务大屏作为智慧水务系统的可视化核心&#xff0c;不仅提升了水务管理的效率&#xff0c;而且通过数据的实时监控和分析&#xff0c;为决策者提供了强有…

持续发力新能源新材料产业,企企通 ×『瑞翔新材』SRM项目启动,积极推动企业发展新质生产力

近日&#xff0c;南通瑞翔新材料有限公司&#xff08;以下简称“瑞翔新材”&#xff09;与企企通达成战略合作&#xff0c;并成功召开SRM项目启动会&#xff0c;瑞翔新材与企企通高层领导、项目负责人及项目组成员共同出席此次启动会。 本次项目建设&#xff0c;企企通将助力瑞…

微服架构基础设施环境平台搭建 -(六)Kubesphere 部署Redis服务 设置访问Redis密码

微服架构基础设施环境平台搭建 -&#xff08;六&#xff09;Kubesphere 部署Redis服务 & 设置访问Redis密码 微服架构基础设施环境平台搭建 系列文章 微服架构基础设施环境平台搭建 -&#xff08;一&#xff09;基础环境准备 微服架构基础设施环境平台搭建 -&#xff08;二…

矿产资源管理系统:开启智慧矿业新篇章

项目背景 在全球经济发展的大背景下&#xff0c;矿产资源作为工业的“粮食”和“血液”&#xff0c;其合理开发与有效管理对于国家的经济发展、能源安全和工业稳定供应具有不可替代的作用。然而&#xff0c;随着资源的日益紧张和环境保护要求的提高&#xff0c;传统的矿产资源…

canvas 学习

最近的项目涉及到 canvas 相关的知识&#xff0c;就在网站上找资源先大概了解一下&#xff0c;然后再细细研究。 看到了一篇 “canvas详细教程” 的资源&#xff0c;感觉十分不错&#xff0c;就分享给大家&#xff1a; canvas详细教程! ( 近1万字吐血总结)这期是潘潘整理的万…

Recommended Azure Monitors

General This document describes the recommended Azure monitors which can be implemented in Azure cloud application subscriptions. SMT incident priority mapping The priority “Blocker” is mostly used by Developers to prioritize their tasks and its not a…

第二届阿里巴巴大数据智能云上编程大赛亚军比赛攻略_北方的郎队

关联比赛: 第二届阿里巴巴大数据智能云上编程大赛-智联招聘人岗智能匹配 查看更多内容&#xff0c;欢迎访问天池技术圈官方地址&#xff1a;第二届阿里巴巴大数据智能云上编程大赛亚军比赛攻略_北方的郎队_天池技术圈-阿里云天池

C#-使用Harmony库实现DLL文件反射调用

一. Harmony工作原理 利用C#运行时Runtime的反射机制,动态加载dll中的方法,字段,属性,实现对DLL方法的重写和代码注入。 二. Harmony下载及安装 1.下载Harmony_lib库lib.harmony.2.3.3.nupkg 霸王•吕布 / CSharpHarmonyLib GitCodehttps://gitcode.net/qq_35829452/csharph…

【黑马点评Redis——003优惠券秒杀】

1.优惠券秒杀 1.1 全局ID生成器 1.1.1 什么是全局ID生成器 全局ID生成器&#xff0c;是一种在分布式系统下用来生成全局唯一ID的工具。 需要满足以下特性&#xff1a; 唯一性高可用高性能递增性安全性 1.1.2 为什么需要全局ID生成器&#xff1f; 自增ID存在的问题&#…

字节跳动(社招)三面算法原题

TikTok 喘息 继上月通过强制剥离 TikTok 法案后&#xff0c;美国众议院在当地时间 20 日下午以 360 票赞成 58 票反对通过了新的法案&#xff1a;剥离 TikTok 的期限由生效后 165 天调整至 270 天之内&#xff0c;即今年 11 月的美国总统大选后。 之前我们讲过&#xff0c;TikT…

5款制作表格的软件,一键帮你实现数据可视化

数据可视化是许多企业决定未来方向、产品研发和用户研究的关键。只有大量的数据支持才能做出最明智的决定&#xff0c;因此表格在可视化中逐渐发挥着不可替代的作用。可以看出&#xff0c;掌握表格制作技巧是多么重要。然而&#xff0c;不能制作表格的小型合作伙伴不必担心。国…

Linux内核驱动开发-001字符设备开发-003独立按键杂项驱动

1驱动程序 /*************************************************************************> File Name: key_misc.c> Author: yas> Mail: rage_yashotmail.com> Created Time: 2024年04月22日 星期一 17时20分42秒**********************************************…

QT QZipReader改进,以支持大于2G的zip文件

QZipReader对ZIP文件读取非常方便好用。即使在最新版的QT 6.6.1里&#xff0c;仍然存在一些问题&#xff1a;对于大于2G的zip文件不支持。 虽然有标准zlib可调用&#xff0c;但包装成一个易用且功能成熟的zip解压功能库&#xff0c;还是有很大的工作量&#xff0c;也需要有一定…

交通工程绪论

一、交通工程 交通工程学定义交通工程学研究的内容交通工程学的产生与发展交通工程学在道路运输管理中的作用 1. 交通工程学定义 早在20世纪30年代&#xff0c;美国交通工程师协会(American Institute of Traffic Engineers)给交通工程学(Traffic Engineering)下了一个定义&a…

每日一题 — 二分查找

704. 二分查找 - 力扣&#xff08;LeetCode&#xff09; 朴素二分查找模板&#xff1a; while(.......){//防止溢出int mid left(right - left)/2;if(........){right mid-1;}else if(......){left mid1;}else{return mid;}} 代码&#xff1a; public int search(int[] num…

jdbc操作数据库 and 一个商品管理页面

文章目录 1. 介绍1.1 应用知识介绍1.2 项目介绍 2. 文件目录2.1 目录2.2 介绍以下&#xff08;从上到下&#xff09; 3. 相关代码3.1 DBConnection.java3.2 MysqlUtil.java3.3 AddServlet.java3.4 CommodityServlet.java3.5 DelectServlet.java3.6 SelectByIdServlet.java3.7 S…

揭秘Faiss:大规模相似性搜索与聚类的技术神器深度解析!

Faiss&#xff08;由Facebook AI Research开发&#xff09;是一个用于高效相似性搜索和密集向量聚类的库。它用C编写&#xff0c;并提供Python绑定&#xff0c;旨在帮助研究人员和工程师在大规模数据集上进行快速的相似性搜索和聚类操作。 一、介绍&#xff1a; Faiss的核心功…

双链向表专题

1.链表的分类 链表的种类非常多组合起来就有 2 2 8种 链表说明&#xff1a; 虽然有这么多的链表的结构&#xff0c;但是我们实际中最常⽤还是两种结构&#xff1a; 单链表 和 双向带头循环链表 1. 无头单向⾮循环链表&#xff1a;结构简单&#xff0c;⼀般不会单独⽤来存数…