C++ | string类学习 | string的常见接口使用方式

目录

为什么要学习string类?

C语言中的字符串

OOP面向对象编程

两个面试题

标准库中的string类

string类了解

string类的文档介绍

总结

string类的常用接口说明

string类对象的常见构造

string类对象的容量操作

size()和length()

clear()

resize(size_t n)与resize(size_t n,char c)

reserve(size_t res_arg=0)

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

operator[]

begin+end 

rbegin+rend

范围for

string类对象的修改操作

 push_back

​编辑append

​编辑 operator+=

find 

​编辑 注意

string类非成员函数

vs和g++下string结构的说明

vs下string的结构

vs下string的设计理念 

g++下string的结构

常见习题

HJ1 字符串最后一个单词的长度

 541. 反转字符串 II

557.翻转字符串III:翻转字符串中的单词

45.字符串相乘 


为什么要学习string类?

C语言中的字符串

C语言中,字符串是以‘\0’结尾的一些字符的合集,为了操作方便,C标准库提供了一些str系列的库函数,但是这些库函数与字符串是分离开的,不太符合OOP的思想,而且底层空间需要用户自己管理,稍有不慎可能会出现越界访问

OOP(Object-oriented programming):面向对象编程。

OOP面向对象编程

OOP面向对象编程是一种编程范式,是以对象为核心来组织和构建程序。

两个面试题

在OJ中,有关于字符串的题目基本均是以string类的形式出现的,而且在常规工作中,基本都是用string类,很少程序员会去使用C库中的字符串操作函数。

标准库中的string类

string类了解

string类的文档介绍

  1. string字符串是表示字符序列的类;
  2. 标准的字符串类提供了帮助对此类对象的支持,其接口类似于标准字符容器的接口,但添加了专门用于操作单字节字符字符串的设计特性;
  3. string类是使用char(即作为它的字符类型,使用它的默认char_traits和分配器类型);
  4. string类是basic_string的模板类的一个实例,它使用char来实例化basic_string模板类,并使用char_traits和allocator作为basic_string的默认参数;
  5. 注意,这个类独立于所使用的编码来处理字节:如果用来处理多字节或变长字符(UTF-8)的序列,这个类的所有成员(如长度或大小)以及它的迭代器,将任然按照字节(而不是实际编码的字符)来操作。

总结

  • string是表示字符串的字符串类。
  • 该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。
  • string在底层实际是:basic_string模板类的别名。
typedef basic_string<char,char_traits,allocator> string;
  • 不能操作多字节或者变长字符的序列。
  • 在使用string类时,必须包含#include头文件以及using namespace std。

string类的常用接口说明

string类对象的常见构造

string类对象的常见构造
constructor函数名称函数含义
string()构造空的string类对象,即空字符串
string(const char* s)用C-string来构造string类对象
string(size_t n,char c)string类对象中包含n个字符c
string(const string&s)拷贝构造函数
void Teststring()
{string s1;//构造空的string类对象string s2("hello bit");//用c格式字符串构造string类对象s2string s3(s2);//拷贝构造s3string s4(6, 'd');//string类对象中包含6个‘d’
}

string类对象的容量操作

string类对象的容量操作
函数名称函数含义
size返回字符串有效字符长度
length返回字符串有效字符长度
capacity返回空间总大小
empty检测字符串释放为空串,是返回true,否则返回false
clear清空有效字符
reserve为字符串预留空间
resize将有效字符的个数改为n个,多出的空间用字符c填充
size()和length()
  •  size()和length()方法底层实现原理完全相同,引入size()的原因是为了与其他容器的接口保持一致,一般情况下基本都是用size()。

clear()
  •  clear()只是将string中有效字符清空,不改变底层空间的大小。

resize(size_t n)与resize(size_t n,char c)
  •  resize(size_t n)与resize(size_t n,char c)都是将字符串中有效字符个数改变到n个,不同的是当字符个数增多时,resize(n)用0来填充多出的元素空间,resize(size_t n,char c)是用字符c来填充多出的元素空间,如果将元素个数减少,底层空间总大小不变。

reserve(size_t res_arg=0)
  •  reserve(size_t res_arg=0):为string预留空间,不改变有效元素个数,当reserve的参数小于string的底层空间总大小时,reserve不会改变容量大小。

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

string类对象的访问及遍历操作
函数名称函数含义
operator[]返回pos位置的字符,const string类对象调用
begin+end

begin获取第一个字符的迭代器;

end获取最后一个字符的下一个位置的迭代器;

rbegin+rend

begin获取逆置字符串的第一个字符的迭代器;

end获取逆置字符串的最后一个字符的下一个位置的迭代器;

范围forC++11支持更简洁的范围for的新遍历方式
operator[]

begin+end 

rbegin+rend

范围for

string类对象的修改操作

string类对象的修改操作
函数名称函数含义

push_back

尾插字符
append在字符串后追加一个字符串
operator+=在字符串后面追加一个字符串str
c_str

返回c格式字符串

find+npos从字符串pos位置开始往后找字符c,返回该字符在字符串中的位置
rfind从字符串pos位置开始往前找字符c,返回该字符在字符串中的位置
substr在str中从pos位置开始,截取n个字符,然后将其返回
 push_back
append
 operator+=

find 
 注意
  • 在string尾部追加字符时,s.push_back(c) / s.append(1,c) / s+='c'三种的实现方式差不多,一般情况下string类的+=操作用的比较多,+=操作不仅可以连接单个字符,也可以连接字符串。
  • 对string操作时,如果能大概预估到放多少字符,可以先通过reserve把空间预留好。

string类非成员函数

string类非成员函数
函数名称函数含义
operator+尽量少用,因为传值返回,导致深拷贝效率低
operator>>输入运算符重载
operator<<输出运算符重载
getline获取一行字符串
relational operators大小比较

vs和g++下string结构的说明

注意:下述情况是在32位平台下进行验证的,32位平台下指针占用4个字节。

vs下string的结构

string总共占用28个字节,内部结构稍微复杂一点,有一个union联合体,联合体用来定义string中字符串的存储空间

  • 当字符串长度小于16时,使用内部固定的字符数组来存放;
  • 当字符串长度大于等于16时,从堆上开辟空间
union _Bxty
{ // storage for small buffer or pointer to larger onevalue_type _Buf[_BUF_SIZE];pointer _Ptr;char _Alias[_BUF_SIZE]; // to permit aliasing
} _Bx;
vs下string的设计理念 

大多数情况下字符串的长度都小于16,那string对象创建好之后,内部已经有了16个字符数组的固定空间,不需要通过堆创建,效率高。

其次:还有一个size_t字段保存字符串长度一个size_t字段保存从堆上开辟空间总的容量

最后:还有一个指针做一些其他事情。

故总共占用16+4+4+4=28个字节。

g++下string的结构

G++下,string是通过写时拷贝实现的,string对象总共占4个字节,内部包含了一个指针,该指针指向一块堆空间,内部包含了如下字段:

  • 空间总大小
  • 字符串有效长度
  • 引用计数
  • 指向堆空间的指针,用来控制字符串。
struct _Rep_base
{size_type _M_length;size_type _M_capacity;_Atomic_word _M_refcount;
};

常见习题

HJ1 字符串最后一个单词的长度

#include <iostream>
using namespace std;int main() 
{string str;getline(cin,str);size_t pos=str.rfind(' ');cout<<str.size()-(pos+1)<<endl;return 0;
}

 541. 反转字符串 II

class Solution {
public:string reverseStr(string s, int k){int n = s.size();int start = 0;int end = n - 1;while (start < n)//确保在字符串中的这个范围里面{//剩余的字符>2K === >  反转前k个if (start + 2 * k < n)//一个数+固定数 < 另一个数【一个数<另一个数】【两者之间的距离也大于那个固定数】{reverse(s.begin() + start, s.begin() + start + k);//begin从0开始,加start就是反转起始位置//start = start += 2 * k;}//剩余的字符<K === >  全部反转else if (start + k > n)//剩余的数小于k{reverse(s.begin() + start, s.end());//全部反转就直接到endbreak;}//k<剩余的字符<2K === >  反转前k个else{reverse(s.begin() + start, s.begin() + start + k);break;}}return s;}
};

557.翻转字符串III:翻转字符串中的单词

class Solution {
public:string reverseWords(string s){int size = s.size();int i = 0;string ret;while (i < size){int start = i;//start记录的是每一个单词的开始//i是每个单词之后遍历找单词之后的空格while (i < size && s[i] != ' ')//要确保找空格是是在字符串的范围内的{//如果不是空格就说明这个单词没有完,就一直++i++;//如果i++之后的i对应的位置是空格,就说明此时找到了空格,这个单词结束了//那么就不进入这个循环里面}//找到一个单词的空格//此时开辟的新的string 的pos位置和旧的str的本单词的起始位置是一样的//因为空格为分割,一个单词各自进行反转,所以每个单词对应的起始位置是一致的for (int p = start; p < i; p++)//此时i是找到空格的位置,要确保空格不反转,所以就是小于空格的下标{//此时可以对新的字符串进行后插//后插开始的下标是:start的这个单词到空格下标的前一个下标【也就是旧str的单词的最后一个字符下标】//单词的个数【进行后插的次数】第一个字符开始到下空格前一个之间的个数ret.push_back(s[start + i - p - 1]);}//将单词进行插入之后,将最后一个的空格也进行后插在新的字符串里面while (i < size && s[i] == ' '){ret.push_back(' ');i++;//本单词反转结束,此时i++,让他去找下一个单词的空格}}return ret;}
};

45.字符串相乘 

class Solution {
public:string multiply(string num1, string num2){//如果两字符都是‘0’,那么相乘的结构也是0if (num1 == "0" || num2 == "0"){return "0";}string ans;//声明一个ret返回的结果字符串int m = num1.size(), n = num2.size();//其中m和n是两个字符串的个数for (int i = n - 1; i >= 0; i--)//i是下标,第二个字符串的下标遍历,从后往前 //也就是n个字符,就要进行n次的乘法{//声明一个临时的字符串curr,记录每次乘出来的值string curr;int add = 0;//目前进位为0//j的起始位置与i的下标一致,但是j>i,所以此时是插入了cur 插入了比第二个字符串个数少一个的0for (int j = n - 1; j > i; j--)//此时是为了保证在之后第n次相乘的时候,是保证进位一致{curr.push_back(0);}//y是第二个字符此时倒数第i个数字字符-‘0’=数字的值int y = num2.at(i) - '0';for (int j = m - 1; j >= 0; j--)//此时m是第一个字符的个数,也就是要这个多位数要和一位数乘以几遍{//x是第一个字符,每一次和不同的字符相乘,都要重新从右向左进行遍历int x = num1.at(j) - '0';//此时第一个字符串的倒数第一个值与第二个字符串的值相乘之后的值为product//除此之外还要加上上一次相乘之后遗留下来的进数int product = x * y + add;//此时在这个结果临时的字符串中后插了product的值的个位数,且保留进数,以便下一趟的使用curr.push_back(product % 10);//此时进制为addadd = product / 10;}//此时第二个字符已经遍历与第一个字符串的所有数字都已经相乘结束//但是此时的进位还是不等于0的,所以,此时就需要再在高位数+上while (add != 0)//此时进制不为0{//再向curr的字符串后插进制的余数curr.push_back(add % 10);//再一次更新进制add /= 10;//直到进制add==0,相乘结束}reverse(curr.begin(), curr.end());//cur一直是pushback,所以逆置一下for (auto& c : curr)//此时{c += '0';//此时将字符串中的数字都转化为字符}ans = addStrings(ans, curr);//此时第一趟相乘之后的结果已经得出,我们就得到了此时的第一个需要加起来的值//调用相加上一趟的结果值}return ans;}//                  ans             currstring addStrings(string& num1, string& num2){//此时i是结果值结尾的下标,curr是本堂的结果值的结尾的下标int i = num1.size() - 1, j = num2.size() - 1, add = 0;//此时的进制为0string ans;//结果值answhile (i >= 0 || j >= 0 || add != 0)//两个字符串相加进行:两个字符串都没有结束,且进位不是0{//x是结果值下标为i(起始在结尾)对应的数字int x = i >= 0 ? num1.at(i) - '0' : 0;//y是结果值下标为j(起始在结尾)对应的数字int y = j >= 0 ? num2.at(j) - '0' : 0;//两个数相加的的个位与个位相加、十位与十位相加、+进位int result = x + y + add;//此时向结尾值插入相加之后所得出的余数ans.push_back(result % 10);//重新更新余数add = result / 10;//两个字符串的遍历下标从右向左i--; j--;}//结果字符串是后插高位,将其逆置reverse(ans.begin(), ans.end());//就将数字改为字符串for (auto& c : ans){c += '0';}//返回相应的值return ans;}
};

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

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

相关文章

【JVM】关于JVM垃圾回收

文章目录 &#x1f334;死亡对象的判断算法&#x1f338;引用计数算法&#x1f338;可达性分析算法 &#x1f333;垃圾回收算法&#x1f338;标记-清除算法&#x1f338;复制算法&#x1f338;标记-整理算法&#x1f338;分代算法&#x1f338;哪些对象会进入新生代&#xff1f…

idea2023.2.1 java项目-web项目创建-servlet类得创建

如何创建Java项目 1.1 方式1&#xff1a; 1.2 方式&#xff1a; 1.3 方式 如何创建web项目 方式 ----- 推荐 如何创建servlet类 复制6 中得代码 给servlet 配置一个路径 启动tomcat 成功了

Netty进阶

三. Netty 进阶 1. 粘包与半包 1.1 粘包现象 服务端代码 public class HelloWorldServer {static final Logger log LoggerFactory.getLogger(HelloWorldServer.class);void start() {NioEventLoopGroup boss new NioEventLoopGroup(1);NioEventLoopGroup worker new Ni…

时序预测 | Python实现VMD-CNN-LSTM时间序列预测

时序预测 | Python实现VMD-CNN-LSTM时间序列预测 目录 时序预测 | Python实现VMD-CNN-LSTM时间序列预测预测效果基本介绍模型描述代码设计预测效果 基本介绍 VMD-CNN-LSTM 是一种混合深度学习模型,结合了变分模态分解(VMD)、卷积神经网络(CNN)和长短期记忆网络(LSTM)的…

C#,简单,精巧,实用的按类型删除指定文件的工具软件

点击下载本文软件&#xff08;积分&#xff09;&#xff1a; https://download.csdn.net/download/beijinghorn/89059141https://download.csdn.net/download/beijinghorn/89059141 下载审核通过之前&#xff0c;请从百度网盘下载&#xff08;无积分&#xff09;&#xff1a;…

7 X 24h智能安全运维再升级!Fortinet 全面集成全新 FortiGuard SOCaaS

数字化时代网络安全威胁层出不穷&#xff0c;网络犯罪分子的狡诈攻击手段不断翻新&#xff0c;传统安全防御手段亟需进化。更为棘手的是&#xff0c;网络安全专业人才的匮乏&#xff0c;让众多企业陷入安全运营的困境。为了有效应对这一挑战&#xff0c;Fortinet全新推出FortiG…

【Python如何使用requests+re库进行简单爬虫实例应用】

1、安装requests库 (1)直接winR输入cmd进入命令行界面&#xff0c;执行命令&#xff1a;pip install requests (2)再Pycharm中&#xff0c;’File’-’Settings’-’Python interpreter’-’’-搜索’requests’-’install package’下载&#xff0c;如下图所示 2、实例&…

UE4几个常用节点链接

UE4几个常用节点链接 2017-12-02 12:54 1. 流光材质(及uv平铺次数) 2. 跑九宫格 3.闪光3。1 粒子闪烁效果 4.图案重复5.平移扭曲 6.溶解 刀光的uv滚动图片源或采样节点属性里改成clamp无后期发光光晕anistropic 各向异性高光法线图 法线图叠加 blendangle orrectedNo…

ChatGPT 之百万富翁

原文&#xff1a;The ChatGPT Millionaire 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 介绍 当我写下这些文字时&#xff0c;ChatGPT 已经成为有史以来增长最快的技术平台 - 仅用 5 天就达到了一百万用户。相比之下&#xff0c;Netflix 用了 3 年&#xff0c;Twit…

【python】python新闻内容zhua取分析词云可视化(源码)【独一无二】

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;公众号&#x1f448;&#xff1a;测试开发自动化【获取源码商业合作】 &#x1f449;荣__誉&#x1f448;&#xff1a;阿里云博客专家博主、5…

echarts实现炫酷科技感的流光效果

前言&#xff1a; echarts实现炫酷科技感的流光效果 效果图&#xff1a; 实现步骤&#xff1a; 1、引入echarts,直接安装或者cdn引入 npm i echarts https://cdn.jsdelivr.net/npm/echarts5.4.3/dist/echarts.min.js 2、封装 option方法&#xff0c;第一个数据是折线数据&a…

在线生成占位图片工具:简便快捷的设计利器

title: 在线生成占位图片工具&#xff1a;简便快捷的设计利器 date: 2024/4/4 17:36:41 updated: 2024/4/4 17:36:41 tags: 占位图片网页设计开发工具图片生成页面布局效率提升预览调整 在网页开发或设计过程中&#xff0c;经常会遇到需要临时使用占位图片的情况。占位图片是指…

Linux------一篇博客了解Linux最常用的指令

&#x1f388;个人主页&#xff1a;靓仔很忙i &#x1f4bb;B 站主页&#xff1a;&#x1f449;B站&#x1f448; &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f917;收录专栏&#xff1a;Linux &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#…

语音芯片 SOP8、SOP16、SOP24脚在性能上有哪些不同呢?

随着语音识别技术的不断发展&#xff0c;人们对语音芯片的需求也越来越高。 其中&#xff0c;SOP8、SOP16和SOP24脚语音芯片是目前市面上应用比较广泛的芯片类型。这些芯片在性能上有什么区别&#xff1f;下面我们来具体分析一下。 首先&#xff0c;SOP8、SOP16、SOP24脚语音芯…

IP-guard WebServer 任意文件读取漏洞复现

0x01 产品简介 IP-guard是由溢信科技股份有限公司开发的一款终端安全管理软件,旨在帮助企业保护终端设备安全、数据安全、管理网络使用和简化IT系统管理。 0x02 漏洞概述 由于IP-guard WebServer /ipg/static/appr/lib/flexpaper/php/view.php接口处未对用户输入的数据进行严…

java Web 健身管理系统idea开发mysql数据库LayUI框架java编程计算机网页源码maven项目

一、源码特点 java Web健身管理系统是一套完善的信息管理系统&#xff0c;结合java 开发技术和bootstrap完成本系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。 前段主要技术 layUI bootst…

显示器and拓展坞PD底层协商

简介&#xff1a; PD显示器或者PD拓展坞方案中&#xff0c;连接显示设备的Type-C端口主要运行在DRP模式&#xff0c;在此模式下可以兼容Source&#xff08;显卡&#xff09;、Sink&#xff08;信号器&#xff09;、DRP&#xff08;手机、电脑&#xff09;模式的显示设备。 Sou…

在Linux系统上搭建Android、Linux和Chrome性能监控和Trace分析的系统

perfetto是知名的Android系统性能分析平台。我们还可以用它去分析Linux系统和Chrome&#xff08;需要装扩展&#xff09;。本文我们只介绍如何安装的验证。 部署 我们使用Docker部署perfetto ui系统。 FROM ubuntu:20.04 WORKDIR /perfetto-ui RUN apt-get update -y RUN ap…

C++初学者:优雅创建第一个窗口

我想学习C做一些实用的程序&#xff0c;但是我不想在软件界面上花太多的时间&#xff0c;可是每每就是界面影响我的思绪。 今天学习C类的包装知识&#xff0c;终于整出了一个我的界面类&#xff0c;虽然封装水平很弱&#xff0c; 这次就用这个类&#xff0c;写了自己工作上常用…

JavaEE初阶-线程3

文章目录 一、线程安全问题-内存可见性二、等待通知2.1 wait()方法2.2 notify()方法 一、线程安全问题-内存可见性 import java.util.Scanner;public class Demo27 {private static int count0;//下面这段代码会出现内存的可见性问题//将从内存中读取count值的操作称为load 判…