【C++】深入理解string类

一、熟悉string类

1.1 string类的由来:

        C语音中的字符串需要我们自己管理底层空间,容易内存泄露。而C++是面向对象语音,所以它把字符串封装成一个string类。

        C++中对于string的定义为:typedef basic_string string; 也就是说C++中的string类是一个泛型类,由模板而实例化的一个标准类,本质上不是一个标准数据类型。

至于我们为什么不直接用String标准数据类型而用类是因为一个叫做编码的东西

        我们每个国家的语言不同 比如说英语使用26个英文字母基本就能表述所有的单词 但是对于中文的字符呢?是不是就要用其他编码方式啊(比如说UTF-8或者GB2312)

1.2  string类的函数接口:


二、string类的写入:

2.1  string类的构造函数:

 我们一般都是用无参的构造,拷贝构造和有参数的构造。

string s1;

string s2(s1);

string s3("hello C++");

string s4="hello C++";//s3 s4都是会把"hello C++"字符数组隐式转换成const char*类型,然后再调用这个构造函数,对s4进行构造

不需要担心空间不够问题,这些构造函数内部都会实现自动扩容的操作。

2.2  string类的数据读取:

方法一:string类里面对运算符[ ] 进行了重载,可以像使用数组一样使用。

for(int i=0;i<s1.size(),i++)
{
    cout<<s1[i]<<" ";
}

这里的s1.size()是统计字符串长度(不包括\0)。如hello world的size是11 

方法二:调用at函数

for(int i=0;i<s1.size(),i++)
{
    cout<<s1.at(i)<<" ";
}

operator[ ]和at两种方法的区别:

    下标访问报断言错误 at访问报异常

方法三:迭代器的方法。

迭代器的写法:首先写个string类名 后面跟上iterator(迭代器) 再后面加上一个it变量(可以是其他名字)

只时候就体现了auto的好处了  auto it = s1.begin(); //自动转换类型

string::iterator it=s1.begin();
while(it!=s1.end)
{
    cout<<*it<<" ";
    it++;
}

 注意点:1.   begin是指向开始位置,而end是指向\0位置---->左闭右开

                2.不要写成it<s1.end,因为物理空间中不一定begin的就比end的小,如链表,树等是靠指针指向下一个节点。(而且底层不一定就是指针,这个后面讲)

                3.为啥需要迭代器?统一操作,关心效果,不关心底层原理(C++面向对象思维)

这个代码的意思是,it指向字符串的第一个元素

      (目前阶段可以理解为it就是一个指针)

      (s1.begin()就是指向字符串第一个字符的指针)

在循环当中,如果it不等于最后一个字符所在的位置,就打印并且it++; 

 迭代器包括正向迭代器和反向迭代器,还有有无const修饰的迭代器

这里简单介绍一下 反向迭代器 const修饰的反向迭代器

string::reverse_iterator it = s1.rbegin();
while(it!=s1.rend)
{
    cout<<*it<<' ';
    it++;
}

顾名思义,就是反向的,it++时是从后往前走的。 


 const修饰的反向迭代器

string::const_reverse_iterator it = s1.rbegin();
while (it != s1.rend())
{
	cout << *it << " ";
	it++;
}

方法四:范围for(底层原理是迭代器)

for(auto u:s1)
{
    cout<<u<<" ";
}

auto 是实现自动识别类型,    如  char ch = ‘a’;      auto i = ch;   则i的类型是char

 这个代码的意思是   依次把s1中的字符串变量中的字符拷贝给u变量,然后打印u变量

如果想要对里面的值进行修改,就需要用引用传参。 

for(auto& u:s1)
{
    u++;
    cout<<u<<" ";
}

其他:还有两个成员函数back和front,分别访问最后一个字符和第一个字符。 

cout<<s1.back();

cout<<s1.front();


 三、string类的容量接口:

3.1 size  和  length
s1="hello world";
cout<<s1.size()<<endl;
cout<<s1.length()<<endl;

两者没有区别,一开始是length先出来的,然后为了和后面的STL中的其他容器保持一致,就多了一个size函数。我们一般用size

3.2 capacity

capacity返回的容量不包括\0,就是本来开了16的空间,但是前人认为\0不能算有效容量,就会返回15

3.3 empty
string s1;
string s2="hello world";
cout<<s1<<endl;
cout<<s2<<endl;

 

3.4 clear

将size变为0,相当于清理数据,下一次是从size==0的位置开始插入数据。 

string s2="hello world";
s2.clear();
s2 = "C++";
cout << s2;

 

3.5  reserve 预留空间   和    resize  调整size的大小,其间用\0来填充
string s1="hello world";
string s2="hello world";
s2.reserve(100);
cout<<s2.size()<<" "<<s2.capacity() << endl;

s1.resize(100);
cout << s1.size() <<" "<< s1.capacity() << endl;

这样子的结果是如果是resize出来的,那么前面的11--100的空间都被\0填充,我们只能从100号位置开始填充,中间的空间都浪费掉了。

而reserve出来的没有改变size的大小,就扩容。(这个函数就很nice,当你提前知道你想要开多大的空间,就可以使用这个函数。

看resize函数的代码

string s1="hello world";
s1.resize(15);
s1 += "hi";
cout << endl;
cout << s1 << endl;
cout << s1.size() <<" "<< s1.capacity() << endl;

\0是不打印出来的,所以最后的结果是

world和hi中间是没有空格的

四、String类对象修改接口

 4.1 这里就operator+=这个函数重要

可以实现尾插字符,也可以实现尾插字符串

第四个是C++11之后添加的(我还不知道是什么,等我学了再谈) 现在我们就用前三种。

string s1 = "hello world";
s1 += ' ';
s1 += "hello C++";
cout << s1;

4.2  insert和earse

都是需要挪动数据,所以时间复杂度高,少用。

string s1 = "hello world";
s1.insert(5,"         ");
cout << s1;

 从下标为5位置开始插入

string s1 = "hello world";
s1.insert(5,"         ");
s1.erase(0,5);
cout << s1;

 从下标为0的位置,开始删除5个元素

string类里面的erase函数是有缺省值的。

       当不传参的时候是从0号位置开始删除到末尾。

         传一个参数是指从n号位置开始一直删除到末尾。

4.3 replace

函数的参数分别是替换的起始位置,删除的数据大小,替换的字符串(不能是字符)

 

把含有a b c的字符都替换成 字符 *

其他   reverse(这个不是string类里面的,而是迭代器中的)

逆置字符串,参数是迭代器s1.begin()和s1.end()

s1="hello world";
reverse(s1.begin(),s1.end());
cout<<s1;

就可以把s1中的字符串逆转,当然,也适用于其他的迭代器。 

五、 String对象字符串运算相关接口

5.1 c_str 

 两者的类型不同。

一个是string对象

一个是字符指针(也就是字符串)

5.2 find

第一种:

        string s1 = "hello world";
        string s2 = "world";
        size_t posn=s1.find(s2, 1);   
        cout << posn;

// 从s1这个对象中查找s2这个对象,从下标为1这个位置查找(默认从0开始查找)

返回  匹配的第一个字符的下标

第二种:

        string s1 = "hello world";
        string s2 = "world";
        size_t posn = s1.find("hello");     //第一个参数是输入字符串       第二个参数默认为0
        cout << posn;

第三种:

 参数1、查找的字符串   参数2、从第几个位置开始查找   参数3、要匹配的字符序列的长度。

 string str("There are two needles in this haystack with needles.");
 found = str.find("needles are small", 15, 6);
 if (found != std::string::npos)
 cout << "second 'needle' found at: " << found << '\n';

 

从下标为15的位置开始查找,找到needle这个字符串(查找这个字符串的前6个字符)

第四种:

查找字符

    string str("There are two needles in this haystack with needles.");
    found = str.find('.');
    if (found != std::string::npos)
    cout << "Period found at: " << found << '\n';

5.3 rfind   

        就是倒着找,从后往前找 

        同样是四个重载 

5.4 substr

 从第pos位置开始截取len长度的字符串。参数2没有时,取到结尾。

#include <iostream>       // std::cout
#include <string>         // std::string

int main()
{
    std::string str = "We think in generalities, but we live in details.";
    // (quoting Alfred N. Whitehead)

    std::string str2 = str.substr(3, 5);     // "think"

    std::size_t pos = str.find("live");      // position of "live" in str

    std::string str3 = str.substr(pos);     // get from "live" to the end

    std::cout << str2 << std::endl << str3 << '\n';

    return 0;
}

5.5 getline(string)

两种重载,第一种需要自己手动设置结束符    第二种是以\n为结束符

//第一种
int main()
{
	std::string name;
	std::cout << "Please, enter your full name: ";
	std::getline(std::cin, name,'a');
	std::cout << name;
	return 0;
}

 以‘a’字符为结束标志


//第二种
#include <iostream>
#include <string>
int main()
{
	std::string name;
	std::cout << "Please, enter your full name: ";
	std::getline(std::cin, name);
	std::cout << name;
	return 0;
}


好了,到这里本篇文章就结束了,如果有什么错误的地方,还请各位大佬指明,相互学习。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux 进程间通信之匿名管道

&#x1f493;博主CSDN主页:麻辣韭菜&#x1f493;   ⏩专栏分类&#xff1a;Linux知识分享⏪   &#x1f69a;代码仓库:Linux代码练习&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学习更多Linux知识   &#x1f51d; 目录 前言 一. 进程间通信介绍 1.进程间通…

富唯智能案例|双3D相机引导衔架抓取铝型材

随着制造业的快速发展和自动化水平的不断提升&#xff0c;铝型材的自动化抓取和加工成为行业内的一大技术难题。铝型材因其轻便、耐腐蚀、易加工等特点&#xff0c;广泛应用于建筑、汽车、电子等领域。然而&#xff0c;铝型材的形状多样、尺寸不一&#xff0c;以及生产线上的高…

4G小车的公网直播推流

一直想做一个小车, 可以通过4G推流, 没想到现在很多云服务提供商, SRS云服务器已经可以一键搭建了. 硬件方面, 就是一个1126驮着一个3516, 1126负责4G连接, 转流到Intenet, 3516负责vi_venc_rtsp 思路如下, 我的1126的摄像头一直没能横过来, 所以就不用1126的摄像头了, 先用35…

SpringBoot配置HTTPS及开发调试

前言 在实际开发过程中&#xff0c;如果后端需要启用https访问&#xff0c;通常项目启动后配置nginx代理再配置https&#xff0c;前端调用时高版本的chrome还会因为证书未信任导致调用失败&#xff0c;通过摸索整理一套开发调试下的https方案&#xff0c;特此分享 后端配置 …

项目管理-项目管理科学基础

项目管理&#xff1a;每天进步一点点~ 活到老&#xff0c;学到老 ヾ(◍∇◍)&#xff89;&#xff9e; 何时学习都不晚&#xff0c;加油 1.项目管理科学基础--主要内容 项目管理科学基础&#xff0c;以下讲解两方面的内容&#xff1a;工程经济学、运筹学。 2.具体知识点 2…

使用Postman对@RequestPart和HttpServletRequest组合传参方式

使用Postman对RequestPart和HttpServletRequest组合传参方式 方法代码如下&#xff1a; /*** 发布*/ApiOperation("发布")ApiImplicitParams({ApiImplicitParam(name "req", value "json格式", dataType "Map", dataTypeClass Ma…

Docker-Compose概述与简单编排部署

目录 前言 一、Docker-Compose 概述 1、Docker-Compose 概念 2、Docker-Compose 优缺点 2.1 Docker-Compose 优点 2.2 Docker-Compose 缺点 3、Docker-Compose与Docker-Swarm的区别 二、两大文件格式 1、YAML 文件格式 2、JOSON 文件格式 3、YAML 与 JOSON 格式的区…

【C++】:const成员,取地址及const取地址操作符重载

目录 一&#xff0c;const成员二&#xff0c;取地址及const取地址操作符重载 一&#xff0c;const成员 将const修饰的“成员函数”称之为const成员函数&#xff0c;const修饰类成员函数&#xff0c;实际修饰该成员函数隐含的this指针&#xff0c;表明在该成员函数中不能对类的…

力扣刷题第0天:只出现一次的数字

目录 第一部分:题目描述 ​第二部分:题目分析 第三部分:解决方法 3.1思路1: 双指针暴力求解 3.2 思路2&#xff1a;异或运算 第四部分:总结收获 第一部分:题目描述 第二部分:题目分析 由图片分析可得&#xff0c;该题目对算法时间复杂度有一定的要求时间复杂度为O(N)&a…

Linux搭建mysql环境

搭建 MySQL 环境 1、使用 wget 下载安装包&#xff0c;下载到 opt 目录中 wget http://dev.mysql.com/get/mysql57-community-release-el7-10.noarch.rpm2、安装 MySQL 公钥 rpm -i mysql57-community-release-el7-10.noarch.rpmrpm --import https://repo.mysql.com/RPM-GP…

【算法刷题 | 动态规划02】5.02(不同路径、不同路径||、整数拆分、不同的二叉搜索树)

文章目录 5.不同路径5.1题目5.2解法一&#xff1a;深度搜索5.2.1深度搜索思路5.2.2代码实现 5.3解法二&#xff1a;动规5.3.1动规思路5.3.2代码实现 6.不同路径||6.1题目6.2解法&#xff1a;动规6.2.1动规思路&#xff08;1&#xff09;dp数组以及下标含义&#xff08;2&#x…

python学习笔记B-18:序列结构之集合--集合的创建、操作与删除

集合的创建、常用操作和删除方法&#xff1a; s {1,2,3,4,5,} print(s)s set() #创建了一个空集合 print(s,type(s))s {} #创建了一个空字典 print(s, type(s))s set("helloworld") print(s) #集合内容是无序的&#xff0c;不重复&#xff0c;所以顺序混乱…

VG做mirror引起的块偏移

事件起因 Oracle10.2环境 Aix操作系统使用aix的lvm技术。制作vg的mirror。以此来替换掉老的存储。 做mirror前&#xff0c;数据库已完全关闭 故障现象 在启动数据库时&#xff0c;发现IO错误。该系统的spfile&#xff0c;ctl&#xff0c;dbf均是用lv做的裸设备。其中dbf是使…

STM32项目设计:基于stm32f1的智能门锁(附项目视频全套教程)

最近假期比较闲,拿着之前剩下的模块做了一个小玩具, 先制定一下此次玩具的规划,也可以理解为简易项目书。 开发软件&#xff1a;keil 硬件选型&#xff1a;STM32F103C8T6、RFID读卡器、oled屏幕、按键模块、蓝牙通信模块、蜂鸣器、舵机; 上位机&#xff1a; 1.上位机可以对密…

pkpmbs 建设工程质量监督系统 Ajax_operaFile.aspx 文件读取漏洞复现

0x01 产品简介 pkpmbs 建设工程质量监督系统是湖南建研信息技术股份有限公司一个与工程质量检测管理系统相结合的,B/S架构的检测信息监管系统。 0x02 漏洞概述 pkpmbs 建设工程质量监督系统 Ajax_operaFile.aspx接口处存在文件读取漏洞,未经身份认证的攻击者可以利用漏洞读…

【C++】拷贝复制:拷贝构造函数的使用

欢迎来到CILMY23的博客 本篇主题为&#xff1a;拷贝复制&#xff1a;拷贝构造函数的使用 博客主页&#xff1a;CILMY23-CSDN博客 个人专栏&#xff1a;Python | C | C语言 | 数据结构与算法 感谢观看&#xff0c;支持的可以给个一键三连&#xff0c;点赞关注收藏。 写在前头…

【趣味实践】KataGo+Sabaki搭建Ai围棋助手

前言 最近和同门在比试围棋&#xff0c;结果被爆虐&#xff0c;于是想借助Ai治治“嚣张”的他。 KataGo简介 继2016年AlphaGo出圈以来&#xff0c;已有不少Ai模型&#xff0c;其中部分如下图[1]所示。 在线围棋对弈网站OGS上&#xff0c;使用KataGo(https://online-go.com/)这…

什么是限流?常见的限流算法

目录 1. 什么是限流 2. 常见限流算法 3. 固定窗口算法 4. 滑动窗口算法 5. 漏桶算法 6. 令牌桶算法 7. 限流算法选择 1. 什么是限流 限流&#xff08;Rate Limiting&#xff09;是一种应用程序或系统资源管理的策略&#xff0c;用于控制对某个服务、接口或功能的访问速…

硬件知识积累 DP 接口简单介绍以及 DP信号飞线到显示屏的问题

1. DP 接口的介绍 定义与起源&#xff1a; DP接口是由PC及芯片制造商联盟开发&#xff0c;并由视频电子标准协会&#xff08;VESA&#xff09;标准化的数字式视频接口标准。它的设计初衷是为了取代传统的VGA、DVI和FPD-Link&#xff08;LVDS&#xff09;接口&#xff0c;以满足…

QT-QTCreator环境配置

准备工作&#xff1a; 下载QT: 链接&#xff1a;https://pan.baidu.com/s/1prJcsC4DGqhKiXvLuPQFVA?pwd60b3 提取码&#xff1a;60b3下载WindowsKits&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1QNiS3HpbH5M5kXx5AhkqnQ?pwde2h8 提取码&#xff1a;e2h8安装的…