【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/587999.html

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

相关文章

【16-Ⅰ】Head First Java 学习笔记

HeadFirst Java 本人有C语言基础&#xff0c;通过阅读Java廖雪峰网站&#xff0c;简单速成了java&#xff0c;但对其中一些入门概念有所疏漏&#xff0c;阅读本书以弥补。 第一章 Java入门 第二章 面向对象 第三章 变量 第四章 方法操作实例变量 第五章 程序实战 第六章 Java…

QT:按钮类控件

文章目录 PushButton快捷键Radio Buttion PushButton 这个类继承自QAbstractButton&#xff0c;是所有按钮的父类 创建一个带有图标的按钮&#xff1a; 假设这个图片是这个 那么我们就可以创建按钮并进行设置了&#xff1a; #include "widget.h" #include "u…

继续有效通知发文,撤三的商标保住了!

今天普推知产老杨看到年前协助贵州一位朋友处理的撤三答辩有结果了&#xff0c;在商标局官网上检索到“继续有效通知发文”&#xff0c;说明这个已注册商标保住了。 现在商标已注册量突破4000万&#xff0c;可以想到的好点的名称基本让别人都注册了&#xff0c;所以会对已注册商…

Linux专栏06:Linux基本指令之文件处理指令

博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;Linux专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ Linux基本指令之文件处理指令 编号&#xff1a;06 文章目录 Linux基…

C 408—《数据结构》图、查找、排序专题考点(含解析)

目录 Δ前言 六、图 6.1 图的基本概念 6.2 图的存储及基本操作 6.3 图的遍历 6.4 图的应用 七、查找 7.2 顺序查找和折半查找 7.3 树型查找 7.4 B树和B树 7.5 散列表 八、排序 8.2 插入排序 8.3 交换排序 8.4 选择排序 8.5 归并排序和基数排序 8.6 各种内部排序算法的比较及…

Springboot+vue+小程序+基于微信小程序的在线学习平台

一、项目介绍    基于Spring BootVue小程序的在线学习平台从实际情况出发&#xff0c;结合当前年轻人的学习环境喜好来开发。基于Spring BootVue小程序的在线学习平台在语言上使用Java语言进行开发&#xff0c;在数据库存储方面使用的MySQL数据库&#xff0c;开发工具是IDEA。…

IDA pro动态调试so层初级教程

一、开启服务 adb push D:\MyApp\IDA_Pro_7.7\dbgsrv\android_server64 /data/local/tmpadb shell cd /data/local/tmp chmod 777 android_server64 ./android_server64二、IDA附加进程 十万个注意&#xff1a;IDA打开的so文件路径不能有中文 手机打开要调试的app 附加成功

【C++容器map】map的相关用法

&#x1f389;博主首页&#xff1a; 有趣的中国人 &#x1f389;专栏首页&#xff1a; C进阶 &#x1f389;其它专栏&#xff1a; C初阶 | 初阶数据结构 | Linux 本篇文章主要讲解 C容器之map相关用法 的相关内容 文章目录 1. map的介绍2. map的使用<font size5 color #…

【Docker】搭建一个媒体服务器插件后端API服务 - MetaTube

【Docker】搭建一个媒体服务器插件后端API服务 - MetaTube 前言 本教程基于群晖的NAS设备DS423的docker功能进行搭建&#xff0c;DSM版为 7.2.1-69057 Update 5。 简介 MetaTube 是一个媒体服务器插件&#xff0c;主要用于 Emby 和 Jellyfin 媒体服务器。它的主要功能是从互…

PS车票的两种方法

方法一&#xff1a;界面有需要的数字 1.使用矩形选框工具&#xff0c;对要修改的数字进行框选 2.使用修补工具&#xff0c;把选框拖到想要的数字 方法二&#xff1a; 1.先找到需要的字体&#xff0c;使用矩形选框工具对字进行框选&#xff0c;在菜单栏找到文字的匹配字体。 …

Pandas入门篇(二)-------Dataframe篇5(进阶)(Dataframe的时间序列Dataframe最终篇!!)(机器学习前置技术栈)

目录 概述一、pandas的日期类型&#xff08;一&#xff09;datetime64类型的特点&#xff08;二&#xff09; 时间序列的创建1.从字符串创建datetime64类型2. 整数&#xff08;Unix时间戳&#xff09;创建datetime64类型3.导入数据时直接转换 &#xff08;三&#xff09;dateti…

【MATLAB画图】如何绘制图像坐标系

首先我们需要图像坐标轴的原点在左上角&#xff1a; set(gca,ydir,reverse,xaxislocation,top); 然后我们需要坐标轴上加上箭头 quiver(0, 0, 0, 520); % 在(x1, y1)处绘制一个箭头&#xff0c;其方向和长度由(dx, dy)确定 quiver(0, 0, 700, 0); % 在(x1, y1)处绘制一个箭头…

C#技巧之窗体去鼠标化

简介 在窗体程序中不用鼠标&#xff0c;直接使用键盘完成想要的操作。 实现的方法有两种&#xff0c;一种是使用键盘上的Tab键使控件获得焦点&#xff0c;然后用enter键触发该控件上的事件&#xff08;一般为click事件&#xff09;。另一种是&#xff0c;为控件添加快捷键&am…

LeetCode热题100:双指针

283.移动零 题目链接&#xff1a;移动零 题目描述&#xff1a;给定一个数组 nums&#xff0c;编写一个函数将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序。 请注意 &#xff0c;必须在不复制数组的情况下原地对数组进行操作。 解题思路&#xff1a; 创建两…

VTK 的可视化方法:等值面

VTK 的可视化方法&#xff1a;等值面 VTK 的可视化方法&#xff1a;等值面VTK 中的数据表达VTK 等值面提取类实例1&#xff1a;模型数据的等值面提取空间函数数据的等值面提取参考 VTK 的可视化方法&#xff1a;等值面 等值面是指一组具有相同标量值的点所构成的表面。 等值面…

54.HarmonyOS鸿蒙系统 App(ArkTS)tcp socket套接字网络连接

54.HarmonyOS鸿蒙系统 App(ArkTS)tcp socket套接字网络连接 import socket from ohos.net.socket; import process from ohos.process; import wifiManager from ohos.wifiManager;import common from ohos.app.ability.common;let tcp socket.constructTCPSocketInstance();…

接收区块链的CCF会议--APSEC 2024 截止7.13 附录用率

会议名称&#xff1a;APSEC&#xff08;Asia-Pacific Software Engineering Conference&#xff09; CCF等级&#xff1a;CCF C类学术会议 类别&#xff1a;软件工程/系统软件/程序设计语言 录用率&#xff1a;2023年&#xff0c;90 submissions were recommended for accep…

智能指针解决多线程访问共享对象的线程安全问题

以下代码&#xff0c;在对象A被析构后&#xff0c;去访问A的成员对象&#xff0c;显然是不合理的。 class A { public:A() { cout << "A()" << endl; }~A() { cout << "~A()" << endl; }void testA() { cout << "非常…

OPA657运算放大器调研

运放是一种直流耦合&#xff0c;差模&#xff08;差动模式&#xff09;输入、通常为单端输出&#xff08;Differential-in, single-ended output&#xff09; [1] 的高增益&#xff08;gain&#xff09;电压放大器。运算放大器能产生一个比输入端电势差大数十万倍的输出电势&am…

Microsoft.NET 框架程序设计 —— 共享程序集

文件版本是一个很难解决的问题。实际上,如果仅仅在一个文件中将其某一位从0改变到1、或者从1改变到0,我们便不能绝对保证使用原来文件的代码和它使用新版文件时的行为一样。这是因为许多应用程序都会有意或者无意地引入bug。如果一个文件的后续版本修复了一个bug,应用程序便…