【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的默认处理…...
华为云AI开发平台ModelArts
华为云ModelArts:重塑AI开发流程的“智能引擎”与“创新加速器”! 在人工智能浪潮席卷全球的2025年,企业拥抱AI的意愿空前高涨,但技术门槛高、流程复杂、资源投入巨大的现实,却让许多创新构想止步于实验室。数据科学家…...
Ubuntu系统下交叉编译openssl
一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机:Ubuntu 20.04.6 LTSHost:ARM32位交叉编译器:arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...
AtCoder 第409场初级竞赛 A~E题解
A Conflict 【题目链接】 原题链接:A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串,只有在同时为 o 时输出 Yes 并结束程序,否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...
OkHttp 中实现断点续传 demo
在 OkHttp 中实现断点续传主要通过以下步骤完成,核心是利用 HTTP 协议的 Range 请求头指定下载范围: 实现原理 Range 请求头:向服务器请求文件的特定字节范围(如 Range: bytes1024-) 本地文件记录:保存已…...
【Java_EE】Spring MVC
目录 Spring Web MVC 编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 编辑参数重命名 RequestParam 编辑编辑传递集合 RequestParam 传递JSON数据 编辑RequestBody …...
鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/
使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题:docker pull 失败 网络不同,需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...
AI编程--插件对比分析:CodeRider、GitHub Copilot及其他
AI编程插件对比分析:CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展,AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者,分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...
关键领域软件测试的突围之路:如何破解安全与效率的平衡难题
在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件,这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下,实现高效测试与快速迭代?这一命题正考验着…...
sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!
简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求,并检查收到的响应。它以以下模式之一…...
【JavaSE】多线程基础学习笔记
多线程基础 -线程相关概念 程序(Program) 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序,比如我们使用QQ,就启动了一个进程,操作系统就会为该进程分配内存…...
