SQL之string的使用与模拟实现

SQL之string的使用与模拟实现

  • 1.官方库中string类的使用接口
    • 1.1 工具网站搜索string类的使用
    • 2.2string类的常用接口说明
  • 2.模拟实现重要/常用的成员函数接口
    • 2.1 准备工作
      • 2.1.1. 解决命名冲突
      • 2.1.2. 成员变量
      • 2.1.3. 默认成员函数——构造函数/拷贝构造函数/析构函数
      • 2.1.4赋值运算符重载
    • 2.2成员函数模拟模拟实现
      • 2.2.1. string类对象的容量操作
      • 2.2.2. string类对象的访问及遍历操作
      • 2.2.3. string类对象的修改操作
      • 2.2.4. string类非成员函数——流插入,流输出
      • 2.2.5 swap交换

在这里插入图片描述

所属专栏:C“嘎嘎" 系统学习❤️
🚀 >博主首页:初阳785❤️
🚀 >代码托管:chuyang785❤️
🚀 >感谢大家的支持,您的点赞和关注是对我最大的支持!!!❤️
🚀 >博主也会更加的努力,创作出更优质的博文!!❤️

1.官方库中string类的使用接口

1.1 工具网站搜索string类的使用

  • 这里提供个大家一个查询官方库中各个函数的使用方法的网站链接: https://cplusplus.com/
    打开后是这个界面:
    在这里插入图片描述
  • 然后点击红色框框——切换老版本,因为新版本不支持查询搜索,老版本支持:
    在这里插入图片描述
  • 我们这里可以进行搜索string。
    在这里插入图片描述
    这里就会显示所有的string类中的成员函数,也可以点击进行详细的功能显示。

2.2string类的常用接口说明

  1. string类对象的常见构造
(constructor)函数名称功能说明
string() (重点)构造空的string类对象,即空字符串
string(const char* s) (重点)用C-string来构造string类对象
string(size_t n, char c)string类对象中包含n个字符c
string(const string&s)(重点) 拷贝构造函数
int main()
{string s1;//这种写法就等于string s1()这种写法,但是不能这样写,//因为编译器可能会把不能分辨他是一个函数还是一个对象string s2("hello world");string s3(4, 'a');string s4(s2);cout << s1 << endl;cout << s2 << endl;cout << s3 << endl;cout << s4 << endl;return 0;
}

在这里插入图片描述

  1. string类对象的容量操作
函数名称功能说明
size(重点)返回字符串有效字符长度
length返回字符串有效字符长度
capacity返回空间总大小
empty (重点)检测字符串释放为空串,是返回true,否则返回false
clear (重点)清空有效字符
reserve (重点)为字符串预留空间**
resize (重点)将有效字符的个数该成n个,多出的空间用字符c填充

注意:

  1. size()与length()方法底层实现原理完全相同,引入size()的原因是为了与其他容器的接口保持一
    致,一般情况下基本都是用size()。
  2. clear()只是将string中有效字符清空,不改变底层空间大小。
  3. resize(size_t n) 与 resize(size_t n, char c)都是将字符串中有效字符个数改变到n个,不同的是当字
    符个数增多时:resize(n)用0来填充多出的元素空间,resize(size_t n, char c)用字符c来填充多出的
    元素空间。注意:resize在改变元素个数时,如果是将元素个数增多,可能会改变底层容量的大
    小,如果是将元素个数减少,底层空间总大小不变。
  4. reserve(size_t res_arg=0):为string预留空间,不改变有效元素个数,当reserve的参数小于
    string的底层空间总大小时,reserver不会改变容量大小
int main()
{string s1("hello world");cout << "size:" << s1.size() << endl;//这个等同于lengthcout << "capacity:" << s1.capacity() << endl;s1.resize(13);cout << "size:" << s1.size() << endl;cout << "capacity:" << s1.capacity() << endl;s1.reserve(20);cout << "size:" << s1.size() << endl;//这个等同于lengthcout << "capacity:" << s1.capacity() << endl;s1.clear();if (s1.empty()){cout << "内容清空" << endl;}return 0;
}

在这里插入图片描述

  1. string类对象的访问及遍历操作
函数名称功能说明
operator[] (重点)返回pos位置的字符,const string类对象调用
begin+ endbegin获取一个字符的迭代器 + end获取最后一个字符下一个位置的迭代器
rbegin + rendrbegin获取最后一个字符下一个位置的迭代器 + rend获取第一个字符位置的迭代器
范围forC++11支持更简洁的范围for的新遍历方式
int main()
{string s1("hello world");for (int i = 0; i < s1.size(); i++){cout << s1[i];}cout << endl;string::iterator it = s1.begin();while (it != s1.end()){cout << *it;it++;}cout << endl;string::reverse_iterator ri = s1.rbegin();while (ri != s1.rend()){cout << *ri;ri++;}cout << endl;return 0;
}

在这里插入图片描述

  1. string类对象的修改操作
函数名称功能说明
push_back在字符串后尾插字符c
append在字符串后追加一个字符串
operator+= (重点)在字符串后追加字符串str
c_str(重点)返回C格式字符串
find + npos(重点)从字符串pos位置开始往后找字符c,返回该字符在字符串中的位置
rfind从字符串pos位置开始往前找字符c,返回该字符在字符串中的位置
substr在str中从pos位置开始,截取n个字符,然后将其返回
int main()
{string s1("hello world");cout << s1.c_str() << endl;s1.push_back('!');cout << s1 << endl;s1.append(" I am user");cout << s1 << endl;s1 += " !";cout << s1 << endl;int pos = s1.find('!');cout << pos << endl;pos = s1.rfind('!');cout << pos << endl;return 0;
}

在这里插入图片描述

  1. string类非成员函数
函数功能说明
operator+尽量少用,因为传值返回,导致深拷贝效率低
operator>>(重点) 输入运算符重载
operator<<(重点) 输出运算符重载
getline (重点)获取一行字符串
relational operators (重点)大小比较

这里说明一下getline,其他的在模拟实现里讲解。
我们正常输入一个字符串的时候大家可能都会想先想到cin输入流,但是cin遇到空格或者换行时停止输入。
所以如果我们要输入一个字符串,包含空格的化就要用到getline。

int main()
{string s1;getline(cin, s1);cout << s1 << endl;return 0;
}

2.模拟实现重要/常用的成员函数接口

2.1 准备工作

2.1.1. 解决命名冲突

首先要模拟string类,我们就要创建一个类,但是如果我们直接创建一个string类的话,会和库里面的string类相互冲突,于是就要用到我们前面的知识点——命名空间。我们可以把我们自己写的string类写在我们自己定义的一个命名空间里面,这样就避免了冲突。

namespace qfw
{class string{//……};
}

2.1.2. 成员变量

要模拟实现一个sting类,首要的是要弄明白string类的内部结构,最重要的就是它的成员变量有哪些。从上面的 使用情况来看,我们可以判断首先有存放字符串的一个指针_str,再就是string的容量_capacity,以及string的字符个数_size。这我们也可以结合之前的数据结构中的单链表来类比。

   private:char* _str = nullptr;size_t _capacity = 0;size_t _size = 0;const static size_t npos = -1;//全部变量,用来部分成员函数的默认参数

2.1.3. 默认成员函数——构造函数/拷贝构造函数/析构函数

  • 构造函数的设计
    上面的使用情况,我们可以知道,构造函数有四种情况1.空构造,2.字符串构造,3.n个字符构造,4.拷贝构造
    这里我们可以将其总结成两大类别:1.空构造,2.有参构造。
    所以这里要设计成缺省参数。
       string(const char* str = ""){_size = strlen(str);_capacity = _size;_str = new char[_capacity + 1];//这里多开一个空间给"\0"strcpy(_str, str);}

这里能不能吧默认参数写成const char* str = nullptr,答案是不能,因为如果时空构造的话,str=nullptr这个时候strlen()计算大小的时候就相当于对str进行解引用,也就是对nullptr进行解引用了。

  • 拷贝构造
    如果这里我们不自己写拷贝构造的话,编译器就会调用默认拷贝构造,就是浅拷贝。但是这里我们成员变量中有指针,而且这个指针是后续用来动态开辟内存的,也就是说涉及到了动态的资源管理。这个问题我们之前的章节也有讲过,如果是用浅拷贝的话就会出现野指针的问题,也就是所同一块空间被释放了两次,所以这里就不能使用浅拷贝,而是要用深拷贝。
     string(const string& s){_str = new char[s._capacity + 1];//这里多开一个空间给"\0"_size = s._size;_capacity = s._capacity;strcpy(_str, s._str);}

这里也有第二种写法:

string(const string& s)
{string tmp(s._str);swap(tmp);
}

注:swap函数后面模拟实现中有写到。
这种写法巧妙的服用了默认构造函数。
在这里插入图片描述

  • 析构函数
    析构函数就像对于比较简单,直接释放就行。
      ~string(){delete[] _str;_str = nullptr;_size = 0;_capacity = 0;}

2.1.4赋值运算符重载

string& operator=(const string& s)
{char* tmp = new char[s._capacity + 1];//先开辟一块新的空间delete[] _str;//释放原来的空间_str = tmp;//指向新的空间strcpy(_str, s._str);//将值拷贝到新的空间_size = s._size;_capacity = s._capacity;return *this;
}

这里也有第二种写法:

	string& operator=(string s)//注意这里是传值操作,并且不能别const修饰{swap(s);return *this;}

这里同样巧妙服用了拷贝构造。
在这里插入图片描述

2.2成员函数模拟模拟实现

2.2.1. string类对象的容量操作

	size_t size(){return _size;}size_t capacity(){return _capacity;}bool empty()const{return _size == 0;}void clear(){_str[0] = '\0';_size = 0;}void reserve(size_t n){if (n > _capacity){char* tmp = new char[n + 1];//这里多开一个空间给"\0"strcpy(tmp, _str);delete[] _str;_str = tmp;_capacity = n;}}void  resize(size_t n, char c = '\0){if (n > _capacity){reserve(n);}if (n <= _size){_str[n] = '\0';_size = n;}else{int cout = n - _size;for (int i = _size; i < n; i++){_str[i] = c;_size++;}_str[_size] = '\0';}}

2.2.2. string类对象的访问及遍历操作

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;
}
const char& operator[](size_t pos) const//引用返回的两个好处:1.减少拷贝。2.修改返回值 //只读
{assert(pos <= _size);return _str[pos];
}char& operator[](size_t pos)//引用返回的两个好处:1.减少拷贝。2.修改返回值 //可读可写
{assert(pos <= _size);return _str[pos];
}

2.2.3. string类对象的修改操作

void push_back(char ch)
{if (_size == _capacity){size_t newCapacity = _capacity == 0 ? 4 : _capacity * 2;reserve(newCapacity);}_str[_size] = ch;_size++;_str[_size] = '\0';
}void append(const char* str)
{size_t len = strlen(str);if (_size + len > _capacity){reserve(len + _size);}strcpy(_str + _size, str);_size += len;
}string& operator+=(char ch)
{push_back(ch);return *this;
}string& operator+=(const char* str)
{append(str);return *this;
}const char* c_str() const
{return _str;
}size_t find(char ch, size_t pos = 0) const
{assert(pos < _size);for (int i = pos; i < _size; i++){if (_str[i] == ch)return i;}return npos;
}size_t find(const char* str, size_t pos = 0) const
{assert(pos < _size);char* ret = strstr(_str, str);if (ret){return ret - _str;}return npos;
}string substr(size_t pos = 0, size_t len = npos) const
{string tmp;assert(pos < _size);size_t end = pos + len;if (len == npos || pos + len >= _size){end = _size;}tmp.reserve(end - pos);for (int i = pos; i < end; i++){tmp += _str[i];}return tmp;
}
void insert(size_t pos, char ch)
{assert(pos <= _size);if (_size == _capacity){size_t newCapacity = _capacity == 0 ? 4 : _capacity * 2;reserve(newCapacity);}size_t end = _size + 1;while (end != pos){_str[end] = _str[end - 1];--end;}_str[end] = ch;_size++;//return *this;
}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--;}_size += len;strncpy(_str + pos, str, len);//return *this;
}void erase(size_t pos = 0, size_t len = npos)
{assert(pos < _size);if (len == npos || pos + len >= _size){_str[pos] = '\0';_size = pos;}else{strcpy(_str + pos, _str + pos + len);_size -= len;}//return *this;
}

2.2.4. string类非成员函数——流插入,流输出

ostream& operator<<(ostream& out, const string& s)
{for (int i = 0; i < s.size(); i++){out << s[i];}return out;
}istream& operator>>(istream& in, string& s)
{s.clear();char ch;in.get(ch);while (ch != ' ' && ch != '\n'){s += ch;in.get(ch);}return in;
}

2.2.5 swap交换

void swap(string& s)
{std::swap(_str, s._str);std::swap(_size, s._size);std::swap(_capacity, s._capacity);
}

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

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

相关文章

12.9_黑马数据结构与算法笔记Java

目录 057 多路递归 e03 杨辉三角2 057 多路递归 e03 杨辉三角3 058 链表 e01 反转单向链表1 058 链表 e01 反转单向链表2 058 链表 e01 反转单向链表3 递归 058 链表 e01 反转单向链表4 058 链表 e01 反转单向链表5 058 链表 e02 根据值删除节点1 058 链表 e02 根据值…

【动手学深度学习】(十一)池化层+LeNet

文章目录 一、池化层1.理论知识2.代码 二、LeNet1.理论知识2.代码实现 【相关总结】nn.MaxPool2d() 卷积层对位置比较敏感 一、池化层 1.理论知识 二维最大池化 填充、步幅和多个通道 池化层与卷积层类似&#xff0c;都具有填充和步幅没有可学习的参数在每个输入通道应用池…

【Kubernetes】四层代理Service

Service四层代理 一、Service概念原理1.1、为什么要有Service1.2、Service概述1.3、工作原理1.4、三类IP地址【1】Node Network&#xff08;节点网络&#xff09;【2】Pod network&#xff08;pod 网络&#xff09;【3】Cluster Network&#xff08;服务网络&#xff09; 二、S…

基于Springboot的校园失物招领系统(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的校园失物招领系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构…

微信小程序 -- ios 底部小黑条样式问题

问题&#xff1a; 如图&#xff0c;ios有的机型底部伪home键会显示在按钮之上&#xff0c;导致点击按钮的时候误触 解决&#xff1a; App.vue <script>export default {wx.getSystemInfo({success: res > {let bottomHeight res.screenHeight - res.safeArea.bott…

准确!!!在 CentOS 8 上配置 PostgreSQL 14 的主从复制

在 CentOS 8 上配置 PostgreSQL 14 的主从复制&#xff0c;并设置 WAL 归档到特定路径 /home/postgres/archive 的步骤如下&#xff1a; 主服务器配置&#xff08;主机&#xff09; 配置 PostgreSQL&#xff1a; 编辑 postgresql.conf 文件&#xff1a; vim /data/postgres/p…

什么是呼叫中心的语音通道?呼叫中心语音线路有几种?

什么是呼叫中心的语音通道&#xff1f; 呼叫中心的语音通道是指在呼叫中心中使用的语音信号传输通道&#xff0c;它是呼叫中心中至关重要的一部分&#xff0c;负责将客户的语音信息传递给客服代表&#xff0c;以及将客服代表的语音信息传递给客户。在呼叫中心的运营中&#xf…

C语言——字符函数和字符串函数(一)

&#x1f4dd;前言&#xff1a; 这篇文章对我最近学习的有关字符串的函数做一个总结和整理&#xff0c;主要讲解字符函数和字符串函数&#xff08;strlen&#xff0c;strcpy和strncpy&#xff0c;strcat和strncat&#xff09;的使用方法&#xff0c;使用场景和一些注意事项&…

记录 | vscode pyhton c++调试launch.json配置

下面提供 vscode 中 python 和 c 调试配置的 launch.json (好用&#xff0c;已用好几年&#xff0c;建议收藏) {// 使用 IntelliSense 了解相关属性。 // 悬停以查看现有属性的描述。// 欲了解更多信息&#xff0c;请访问: https://go.microsoft.com/fwlink/?linkid830387&qu…

Python开发运维:Python垃圾回收机制

目录 一、理论 1.Python垃圾回收机制 一、理论 1.Python垃圾回收机制 &#xff08;1&#xff09;引⽤计数器 1&#xff09;环状双向链表 refchain 在python程序中创建的任何对象都会放在refchain链表中。 name "david" age 20 hobby ["篮球",游泳…

Ultimate VFX

Ultimate VFX 构建套件:

C.小苯的排列构造

C-小苯的排列构造_北京信息科技大学第十五届程序设计竞赛&#xff08;同步赛&#xff09; (nowcoder.com) 凑2很容易想出来&#xff0c;但是2 4 1 3 这个内核不好想&#xff0c;算是一种尝试和经验吧 #include<bits/stdc.h> using namespace std;int n;int main() {cin&g…

使用RSA工具进行对信息加解密

我们在开发中需要对用户敏感数据进行加解密&#xff0c;比如密码 这边科普一下RSA算法 RSA是非对称加密算法&#xff0c;与对称加密算法不同;在对称加密中&#xff0c;相同的密钥用于加密和解密数据,因此密钥的安全性至关重要;而在RSA非对称加密中&#xff0c;有两个密钥&…

P11 Linux进程编程exec族函数

前言 &#x1f3ac; 个人主页&#xff1a;ChenPi &#x1f43b;推荐专栏1: 《Linux C应用编程&#xff08;概念类&#xff09;_ChenPi的博客-CSDN博客》✨✨✨ &#x1f525; 推荐专栏2: 《C_ChenPi的博客-CSDN博客》✨✨✨ &#x1f6f8;推荐专栏3: ​​​​​​《链表_C…

蓝桥杯物联网竞赛_STM32L071_8_ADC扩展模块

原理图&#xff1a; 扩展模块原理图&#xff1a; RP1和RP2分别对应着AIN1和AIN2&#xff0c;扭动它们&#xff0c;其对应滑动变阻器阻值也会变化 实验板接口原理图&#xff1a; 对应实验板接口PB1和PB0 即AN1对应PB1, AN2对应PB0 CubMx配置&#xff1a; ADC通道IN8和IN9才对…

Python:核心知识点整理大全11-笔记

目录 ​编辑 6.2.4 修改字典中的值 6.2.5 删除键—值对 注意 删除的键—值对永远消失了。 6.2.6 由类似对象组成的字典 6.3 遍历字典 6.3.1 遍历所有的键—值对 6.3.2 遍历字典中的所有键 往期快速传送门&#x1f446;&#xff08;在文章最后&#xff09;&#xff1a; 6.…

Git的安装以及SSH配置

前言 近期工作需要&#xff0c;所以版本管理工具要用到Git&#xff0c;某些操作需要ssh进行操作&#xff0c;在某次操作中遇到&#xff1a;git bash报错&#xff1a;Permission denied, please try again。经排查是ssh没有配置我的key&#xff0c;所以就借着这篇文章整理了一下…

2024年网络安全竞赛-Web安全应用

Web安全应用 (一)拓扑图 任务环境说明: 1.获取PHP的版本号作为Flag值提交;(例如:5.2.14) 2.获取MySQL数据库的版本号作为Flag值提交;(例如:5.0.22) 3.获取系统的内核版本号作为Flag值提交;(例如:2.6.18) 4.获取网站后台管理员admin用户的密码作为Flag值提交…

redis 三主三从高可用集群docker swarm

由于数据量过大&#xff0c;单个Master复制集难以承担&#xff0c;因此需要对多个复制集进行集群&#xff0c;形成水平扩展每个复制集只负责存储整个数据集的一部分&#xff0c;这就是Redis的集群&#xff0c;其作用是提供在多个Redis节点间共享数据的程序集。 官网介绍地址 re…

根据java类名找出当前是哪个Excel中的sheet

pom.xml <?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.apache.org/POM/4.0.0 …