【C++】string
【C++修炼秘籍】string
目录
【C++修炼秘籍】string
文章目录
前言
一、标准库里的string
二、string常用接口功能简介(具体使用和底层转到模拟实现)
1、string类的常见构造函数
2、string类对象的容量操作
3、string类对象的访问及遍历操作
4、 string类对象的修改操作
5、 string类非成员函数
三、string的模拟实现
1、string的构造函数
1.1string() //生成空字符串
1.2 string(const char* str) //用C - string来构造string类对象
1.3string(const string&s) //拷贝构造函数
2、string类对象的容量操作
2.1size //返回字符串有效长度
2.2capacity // 返回空间总大小
2.3empty //检测字符串释放为空串,是返回true,否则返回false
2.4clear //清空有效字符
2.5resver //为字符串预留空间
2.6resize //将有效字符的个数该成n个,多出的空间用字符c填充
3、string类对象的访问及遍历操作
3.1operator[] //返回pos位置的字符,const string类对象调用
3.2迭代器和范围for遍历
4、 string类对象的修改操作
4.1push_back //在字符串后尾插字符c
4.2append //在字符串后追加一个字符串
4.3operator+= //追加字符串
4.5c_str //返回C格式字符串
4.6find //从字符串pos位置开始往后找字符c,返回该字符在字符串中的位置
前言
C语言中,字符串是以'\0'结尾的一些字符的集合,为了操作方便,C标准库中提供了一些str系列的库函数,底层空间需要用户自己管理,稍不留神可能还会越界访问
而C++中的string类相比C语言的字符串使用更加简单、方便、快捷,基本很少有人去使用C库中的字符串操作函数
一、标准库里的string
1、字符串是表示字符序列的类
2. 标准的字符串类提供了对此类对象的支持,其接口类似于标准字符容器的接口,但添加了专门用于操作
单字节字符字符串的设计特性。
3. string类是使用char(即作为它的字符类型,使用它的默认char_traits和分配器类型(关于模板的更多信
息,请参阅basic_string)。
4. string类是basic_string模板类的一个实例,它使用char来实例化basic_string模板类,并用char_traits
和allocator作为basic_string的默认参数(根于更多的模板信息请参考basic_string)。
5. 注意,这个类独立于所使用的编码来处理字节:如果用来处理多字节或变长字符(如UTF-8)的序列,这个类的所有成员(如长度或大小)以及它的迭代器,将仍然按照字节(而不是实际编码的字符)来操作。
二、string常用接口功能简介(具体使用和底层转到模拟实现)
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) (重点) | 拷贝构造函数 |
2、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不会改变容量大小。
3、string类对象的访问及遍历操作
| 函数名称 | 功能说明 |
| operator[] (重 点) | 返回pos位置的字符,const string类对象调用 |
| begin+ end | begin获取一个字符的迭代器 + end获取最后一个字符下一个位置的迭 代器 |
| rbegin + rend | begin获取一个字符的迭代器 + end获取最后一个字符下一个位置的迭 代器 |
| 范围for | C++11支持更简洁的范围for的新遍历方式 |
4、 string类对象的修改操作
| 函数名称 | 功能说明 |
| push_back | 在字符串后尾插字符c |
| append | 在字符串后追加一个字符串 |
| operator+= (重点) | 在字符串后追加字符串str |
| c_str(重点) | 返回C格式字符串 |
| find + npos(重点) | 从字符串pos位置开始往后找字符c,返回该字符在字符串中的位置 |
| rfind | 从字符串pos位置开始往前找字符c,返回该字符在字符串中的位置 |
| substr | 在str中从pos位置开始,截取n个字符,然后将其返回 |
❗️ 注意:
- 在string尾部追加字符时,s.push_back(c) / s.append(1, c) / s += 'c'三种的实现方式差不多,一般情况下string类的+=操作用的比较多,+=操作不仅可以连接单个字符,还可以连接字符串。
- 对string操作时,如果能够大概预估到放多少字符,可以先通过reserve把空间预留好。
5、 string类非成员函数
| 函数 | 功能说明 |
| operator+ | 尽量少用,因为传值返回,导致深拷贝效率低 |
| operator>> (重点) | 输入运算符重载 |
| operator<< (重点) | 输出运算符重载 |
| getline (重点) | 获取一行字符串 |
| relational operators (重点) | 大小比较 |
三、string的模拟实现
模拟实现仅是简单地实现功能,主要是加深使用;所有接口均在如下类中实现;
#pragma once//防止冲突,设置命名空间
namespace my{class string{public:private:char* _str;size_t _size;//数据大小size_t _capacity//空间大小;};
}
1、string的构造函数
1.1string() //生成空字符串
//生成空字符串string(){_str = new char[1];_str[0] = '\0';_size = _capacity = 0;}
空的时候最少要开一个,本次模拟实现的底层是用C的字符串,必须存放一个"\0"标记字符串结尾;
1.2 string(const char* str) //用C - string来构造string类对象
//用C - string来构造string类对象string(const char* str){_size = strlen(str);_capacity = _size;_str = new char[_capacity + 1];strcpy(_str, str);}
1.3string(const string&s) //拷贝构造函数
//拷贝构造string(const string&s){ _str = new char[s._capacity + 1];_capacity = s._capacity;_size = s._size;strcpy(_str, s._str);}
2、string类对象的容量操作
2.1size //返回字符串有效长度
size_t size()const{return _size;}
2.2capacity // 返回空间总大小
size_t capacity()const{return _capacity;}
2.3empty //检测字符串释放为空串,是返回true,否则返回false
bool empty()const{return this->_size == 0;}
2.4clear //清空有效字符
void clear(){_size = 0;_str[0] = '\0';}
clear只是将string中有效字符清空,不改变底层空间大小
2.5resver //为字符串预留空间
void reserve(size_t n){if (n > _capacity){char* newCapacity = new char[n + 1];strcpy(newCapacity, _str);delete[] _str;_str = newCapacity;_capacity = n;}}
reserve():为string预留空间,不改变有效元素个数,当reserve的参数小于string的底层空间总大小时,reserver不会改变容量大小。
2.6resize //将有效字符的个数该成n个,多出的空间用字符c填充
void resize(size_t n, char ch = '\0'){if (n > _size){reserve(n);for (size_t i = _size; i < n; ++i){_str[i] = ch;}_size = n;_str[_size] = '\0';}else{_str[n] = '\0';_size = n;}}
resize(size_t n) 与 resize(size_t n, char c)都是将字符串中有效字符个数改变到n个,不同的是当字符个数增多时:resize(n)用0来填充多出的元素空间,resize(size_t n, char c)用字符c来填充多出的元素空间。
注意:resize在改变元素个数时,如果是将元素个数增多,可能会改变底层容量的大
小,如果是将元素个数减少,底层空间总大小不变。
3、string类对象的访问及遍历操作
3.1operator[] //返回pos位置的字符,const string类对象调用
模拟实现
char& operator[](size_t pos){return _str[pos];}
char& operator[](size_t pos)const{return _str[pos];}
使用示例:
void func(const string& s){for (size_t i = 0; i < s.size(); i++){s[i]++;}}
int main(){ string s1("hellow world");for (int i = 0; i < s1.size(); i++){s1[i]++;}func(s1);
}
为什么实现这个const版本呢,就是为了应对func函数所对应的使用情况;我们知道,const的权限不能放大只能缩小;

3.2迭代器和范围for遍历
模拟实现
在string中,我们可以把迭代器当作一个原生指针;
//迭代器typedef char* iterator;
iterator begin(){return _str;}iterator end(){return _str+size();}
使用示例:
string s1("hellow world");//迭代器打印string::iterator it = s1.begin();while (it != s1.end()){std::cout << *it;++it;}std::cout << std::endl;//范围for打印for (auto& e : s1){std::cout << e;}std::cout << std::endl;
其实范围for的迭代器的的底层就是替换成迭代器 ;
当把类中的begin()屏蔽后,范围for的报错是:

在反汇编中也清晰看到就是调用的迭代器

4、 string类对象的修改操作
4.1push_back //在字符串后尾插字符c
模拟实现
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';}
4.2append //在字符串后追加一个字符串
模拟实现
void append(const char* str){size_t len = strlen(str);if (_size+len > _capacity){reserve(_capacity+len);}strcat(_str+_size, str);_size += len;}
4.3operator+= //追加字符串
模拟实现
追加一个字符
string& operator+=(char ch){push_back(ch);return *this;}
追加一个字符串
string& operator+=(const char* str){append(str);return *this;}
4.5c_str //返回C格式字符串
模拟实现
const char* c_str() const{return _str;}
4.6find //从字符串pos位置开始往后找字符c,返回该字符在字符串中的位置
模拟实现
查找单个字符
size_t find(char ch, size_t pos = 0) const{assert(pos < _size);while (pos < _size){if (_str[pos] == ch){return pos;}++pos;}return npos;}
查找字符串
size_t find(const char* str, size_t pos = 0) const{assert(pos < _size);const char* ptr = strstr(_str + pos, str);if (ptr == nullptr){return npos;}else{return ptr - _str;}}
相关文章:
【C++】string
【C修炼秘籍】string 目录 【C修炼秘籍】string 文章目录 前言 一、标准库里的string 二、string常用接口功能简介(具体使用和底层转到模拟实现) 1、string类的常见构造函数 2、string类对象的容量操作 3、string类对象的访问及遍历操作 4、 string类对象…...
JVM详解——执行引擎
如果有兴趣了解更多相关内容,欢迎来我的个人网站看看:耶瞳空间 一:执行引擎介绍 “虚拟机”是一个相对于“物理机”的概念,这两种机器都有代码执行能力,其区别是物理机的执行引擎是直接建立在处理器、缓存、指令集和…...
python学习——【第二弹】
前言 上一篇文章 python学习——【第一弹】给大家介绍了python中的基本数据类型等,这篇文章接着学习python中的运算符的相关内容。 运算符 python中的运算符主要有:算术运算符,赋值运算符,比较运算符,布尔运算符以及…...
242. 有效的字母异位词 349. 两个数组的交集
给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。 注意: 若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。 示例 1: 输入: s “anagram”, t “nagaram” 输出: true 示例 2: 输入: s “rat…...
web网页设计——JavaScript一些语法
1、事件监听 语法: <1> 元素对象.addEventListener(‘事件类型’,要执行的函数) 三要素:(1)、事件源 (2)事件类型 (3)执行的函数 <2>元素对象.on事件类型 …...
php宝塔搭建部署实战CSM会议室预约系统源码
大家好啊,我是测评君,欢迎来到web测评。 本期给大家带来一套基于fastadmin开发的CSM会议室预约系统的源码。感兴趣的朋友可以自行下载学习。 技术架构 PHP7.2 nginx mysql5.7 JS CSS HTMLcnetos7以上 宝塔面板 文字搭建教程 下载源码࿰…...
嵌入式知识点-SPI通讯
该文原自 : 正点原子 01 SPI概述 SPI (Serial Peripheralinterface),顾名思义就是串行外围设备接口。SPI是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同…...
C#教程--01 简介
简介 C# 是一个简单的、现代的、通用的、面向对象的编程语言,它是由微软(Microsoft)开发的。 C#的特性 现代的、通用的编程语言。 面向对象。 面向组件。 容易学习。 结构化语言。 它产生高效率的程序。 它可以在多种计算机平台上编译。 .Net 框架的一部分。 C#强大的编程…...
【java基础】一篇文章彻底搞懂lambda表达式
文章目录lambda表达式是什么lambda表达式的语法函数式接口初次使用深入理解方法引用 :: 用法快速入门不同形式的::情况1 object::instanceMethod情况2 Class::instanceMethod情况3 Class::staticMethod对于 :: 的一些示例及其注意事项构造器引用变量作用域使用外部变量定义内部…...
通用SQL查询分析器
技术:Java、JSP等摘要:本文主要针对当前很多软件都无法实现跨数据库、跨平台来执行sql语句而用户又仅需做一些基本的增删改查操作的矛盾,设计了一个能够跨平台跨数据库的软件。此软件是一个通用SQL查询分析器,利用java语言本身的跨…...
机器学习100天(三十八):038 朴素贝斯-处理离散数据
《机器学习100天》完整目录:目录 机器学习100天,今天讲的是:朴素贝斯-处理离散数据! 打开 spyder,新建一个 naive_bayes_category.py 脚本。上一节我们引入了一批西瓜样本。并使用朴素贝叶斯公式计算出一个瓜蒂脱落、圆形、青色的西瓜是熟瓜的概率。下面我们来使用 pytho…...
【3.3】指针、二分、SSM项目
二分查找 class Solution {public int search(int[] nums, int target) {int n nums.length;int left 0;int right n - 1;while(left < right){int mid left (right - left) / 2;if(nums[mid] < target){left mid 1;}else if(nums[mid] > target){right mid …...
buu [INSHack2017]rsa16m 1
题目描述: 打开的 rsa_16m 文件 : (在此我只想说神人才找得到 c 的位置) ,这位置是真的难找啊 题目分析: 首先打开 description.md 文件,得到: 翻译下来: 当您需要真正…...
【数据结构起航】:衡量算法的好坏--时间空间复杂度
时间复杂度和空间复杂度 文章目录时间复杂度和空间复杂度1.算法效率1.1算法复杂度1.2复杂度在OJ里的应用2.时间复杂度2.1时间复杂度的概率2.2大O渐进表示法推导大O阶方法:2.3时间复杂度的举例计算3.空间复杂度3.1空间复杂度的举例计算4.复杂度各量级对比1.算法效率 …...
动手学深度学习【1】——线性回归
动手学深度学习网址:动手学深度学习 注:本部分只对基础知识进行简单的介绍并附上完整的代码实现,更多内容可参考上述网址。 简述 需要的准备知识 数学的偏导线性代数 线性模型 回归是能为一个或多个自变量与因变量之间关系建模的一类方…...
Html 相关知识
Html 相关知识 DOM 文档对象模型 (DOM) 是 HTML 和 XML 文档的编程接口。它提供了对文档的结构化的表述,并定义了一种方式可以使从程序中对该结构进行访问,从而改变文档的结构,样式和内容。DOM 将文档解析为一个由节点和对象(包…...
【冲刺蓝桥杯的最后30天】day1
大家好😃,我是想要慢慢变得优秀的向阳🌞同学👨💻,断更了整整一年,又开始恢复CSDN更新,从今天开始逐渐恢复更新状态,正在备战蓝桥杯的小伙伴可以支持一下哦!…...
c++泛型编程与模板-01函数模板
函数模板的定义 所谓函数模板,实际就是写一个通用函数,返回值和参数的类型都是可变的,用一个特定格式的变量来指定,然后调用此函数的时候,编译器会根据参数的数据类型自动推导出类型,从而达到函数再不同的…...
Golang http请求忘记调用resp.Body.Close()而导致的协程泄漏问题(含面试常见协程泄漏相关测试题)
参考: 知乎:别因为忘记close你的httpclient,造成goroutine泄漏 CSDN:resp.Body.Close() 引发的内存泄漏goroutine个数 先来看几道题,想一想最终的输出结果是多少呢? package mainimport ("fmt"…...
进程信号生命周期详解
信号和信号量半毛钱关系都没有! 每个信号都有一个编号和一个宏定义名称,这些宏定义可以在signal.h中找到,例如其中有定 义 #define SIGINT 2 查看信号的机制,如默认处理动作man 7 signal SIGINT的默认处理动作是终止进程,SIGQUIT的默认处理…...
国防科技大学计算机基础课程笔记02信息编码
1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制,因此这个了16进制的数据既可以翻译成为这个机器码,也可以翻译成为这个国标码,所以这个时候很容易会出现这个歧义的情况; 因此,我们的这个国…...
JavaSec-RCE
简介 RCE(Remote Code Execution),可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景:Groovy代码注入 Groovy是一种基于JVM的动态语言,语法简洁,支持闭包、动态类型和Java互操作性,…...
VB.net复制Ntag213卡写入UID
本示例使用的发卡器:https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...
基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容
基于 UniApp + WebSocket实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...
Nuxt.js 中的路由配置详解
Nuxt.js 通过其内置的路由系统简化了应用的路由配置,使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...
【python异步多线程】异步多线程爬虫代码示例
claude生成的python多线程、异步代码示例,模拟20个网页的爬取,每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程:允许程序同时执行多个任务,提高IO密集型任务(如网络请求)的效率…...
【JavaSE】绘图与事件入门学习笔记
-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角,以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向,距离坐标原点x个像素;第二个是y坐标,表示当前位置为垂直方向,距离坐标原点y个像素。 坐标体系-像素 …...
稳定币的深度剖析与展望
一、引言 在当今数字化浪潮席卷全球的时代,加密货币作为一种新兴的金融现象,正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而,加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下,稳定…...
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列,以便知晓哪些列包含有价值的数据,…...
用机器学习破解新能源领域的“弃风”难题
音乐发烧友深有体会,玩音乐的本质就是玩电网。火电声音偏暖,水电偏冷,风电偏空旷。至于太阳能发的电,则略显朦胧和单薄。 不知你是否有感觉,近两年家里的音响声音越来越冷,听起来越来越单薄? —…...
