C++(string类)

本节目标:

1、为什么要学习string类

2.标准库中的string类

3.vs和g++下string结构说明


1.为什么学习string类

1.1 c语言中的字符串

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

1.2string类简介

string是C++ 编程语言中的字符串。在C++中字符串处理可以使用c语言字符串形式char *,也可以使用string类格式。
  string 是一个类,类内有char *指针,通过容器方式管理字符串。使用string类型需要需要包含头文件string。

2.标准库中的string类

2.1 string类

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

2.2string 类的常用接口说明(常用的,对于一些非常用的可以去官网查找手册)

1.string类的构造函数

  string常见的构造函数有:无参构造,用c_string构造string类对象,拷贝构造函数

无参构造:string()
c_string构造string类对象:string(const char *str);
拷贝构造:string(const string &str);
初始化字符串为count个c字符:string(int count,char c);

代码如下所示:

2 string类对象的容量操作 

 string 常用的容量操作如下表所示:

函数名称

功能说明

size(重点)

返回字符串有效字符长度

length

返回字符串有效字符长度

capacity

返回空间总大小

empty(重点)

检测字符串释放为空串,是返回true,否则返回false

clear(重点)

清空有效字符

reserve(重点)

为字符串预留空间**

resize(重点)

将有效字符的个数该成n个,多出的空间用字符c填充

 

1. size() length() 方法底层实现原理完全相同,引入 size() 的原因是为了与其他容器的接口保持一
致,一般情况下基本都是用 size()
#include <iostream>
#include <string>int main()
{std::string str("Test string");std::cout << "The size of str is " << str.size() << " bytes.\n";return 0;
}

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

#include <iostream>
#include <string>int main ()
{char c;std::string str;std::cout << "Please type some lines of text. Enter a dot (.) to finish:\n";do {c = std::cin.get();str += c;if (c=='\n'){std::cout << str;str.clear();}} while (c!='.');return 0;
}

 

 

 

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

void TestPushBackReserve()
{string s;s.reserve(100);size_t sz = s.capacity();cout << "capacity changed: " << sz << '\n';cout << "making s grow:\n";for (int i = 0; i < 100; ++i){s.push_back('c');if (sz != s.capacity()){sz = s.capacity();cout << "capacity changed: " << sz << '\n';}}s.clear();cout << "capacity changed: " << sz << '\n';s.reserve(10);sz = s.capacity();cout << "capacity changed: " << sz << '\n';
}int main()
{TestPushBackReserve();return 0;
}

 

 

5. resize(size_t n) resize(size_t n, char c)都是将字符串中有效字符个数改变到n个,不同的是当字 符个数增多时:resize(n)0来填充多出的元素空间,resize(size_t n, char c)用字符c来填充多出的 元素空间。注意:resize在改变元素个数时,如果是将元素个数增多,可能会改变底层容量的大小,如果是将元素个数减少,底层空间总大小不变。

int main()
{string s1("hello world");// 开空间s1.reserve(100);cout << s1.size() << endl;cout << s1.capacity() << endl;// 开空间+填值初始化//s1.resize(200);s1.resize(200, 'x');cout << s1.size() << endl;cout << s1.capacity() << endl;s1.resize(20);cout << s1.size() << endl;cout << s1.capacity() << endl;s1.resize(0);cout << s1.size() << endl;cout << s1.capacity() << endl;return 0;
}

 

 

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

函数名称

功能说明

operator[](重点)

返回pos位置的字符,const string类对象调用

begin+ end

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

rbegin + rend begin

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

范围for

C++11支持更简洁的范围for的新遍历方式

1.operator[] 

#include <iostream>
#include <string>int main()
{std::string str("Test string");for (int i = 0; i < str.length(); ++i){std::cout << str[i];}return 0;
}

 

 2.迭代器和范围for

#include <iostream>
#include <iostream>
#include <string>
using namespace std;int main()
{std::string s1("Test string");// 迭代器string::iterator it = s1.begin();while (it != s1.end()){// 写(*it)--;++it;}cout << endl;it = s1.begin();while (it != s1.end()){// 读cout << *it << " ";++it;}cout << endl;// 范围for// 底层替换为迭代器//for (char& ch : s1)for (auto& ch : s1){ch++;}cout << endl;for (char ch : s1){cout << ch << " ";}cout << endl;}

3.string类对象的修改操作

 

函数名称 

功能说明

push_back

在字符串后尾插字符c

append      

 在字符串后追加一个字符串

operator+= (重点)

在字符串后追加字符串str

c_str(重点)

返回C格式字符串

find + npos(重点)

从字符串pos位置开始往后找字符c,返回该字符在字符串中的位置

rfind

从字符串pos位置开始往前找字符c,返回该字符在字符串中的位置

substr

在str中从pos位置开始,截取n个字符,然后将其返回

 push_back 尾插字符,append尾插字符串字面就能理解,其实他们都可以用+=实现,

string的连接是通过加法操作符实现的,加号两边可以随意组合string或是字符串字面量。

#include <iostream>
#include<string>
using namespace std;//string的连接int main()
{string s1 = "";string s2 = "";cout << "请输入两个用空格间隔的字符串:" << endl;cin >> s1 >> s2 ;string s3 = s1 + s2 ;cout << "字符串连接的结果为:" << s3 << endl;for (int i = 0;i < 3;i++){string s4 = "";cout << "请输入字符串:" << endl;cin >> s4;s3 +=s4;cout << "字符连接的结果是: " << s3 << endl;}return 0;
}

字符串的查找与替换

string字符串查找有find、rfind函数。

  • find函数是从左往右查找,查找成功返回第一个出现的下标,失败返回-1。
  • rfind是查找最后一个出现的下标,失败返回-1。 replace函数实现字符串替换。

 //find函数:从左往右查找
返回值:查找成功返回出现的位置,失败返回-1
int find(const string&str,int pos=0)const;//形参pos表示开始查找的起始位置
int find(const char *str,int pos=0)const;
int find(const char *str,int pos=0,int n)const;//从str的第pos开始的前n个字符中str出现的位置
int find(const char c,int pos=0);//查找字符c
//rfind函数:从右往左查找
int rfind(const string &str,int pos=npos);从pos位置开始查找str最后一次出现的位置
int rfind(const char *str,int pos=npos);从pos位置开始查找str最后一次出现的位置
int rfind(const char *str,int pos=pos,int n);从pos开始的前n个字符中str最后一次出现的位置
int rfind(const char c,int pos=0);//查找c最后一次出现的位置
//字符串替换
string &replace(int pos,int n,const string &s);//将字符串的第pos位置开始的n个字符替换成s
string &replace(int pos,int n,const char *s);

 

#include < iostream >
#include < string >
using namespace std;
void test()
{string str = "1asd3as456asd4789asd";int pos = str.find("asd");//查找asd第一次出现的位置cout << "pos=" << pos << endl;string temp = "asd";pos = str.find(temp,7);//从第7个位置开始查找asd出现的位置cout << "pos=" << pos << endl;pos = str.rfind(temp);//查找最后一次出现的位置cout << "pos=" << pos < < endl;pos = str.rfind("asd",7,2);//从第3个位置开始往前查找,查找"asd"中的前2个字符在str中最后一次位置cout << "pos=" << pos << endl;//字符串替换str.replace(1, 7, "c++");//从第一个位值开始将str的7个字符替换为c++cout << "str=" << str << endl;
}
int main()
{test();system("pause");
}

 函数                                                                   功能说明
operator+                                            尽量少用,   因为传值返回,导致深拷贝效率低
operator>> (重点)                           输入运算符重载
operator<< (重点)                           输出运算符重载
getline (重点)                                  获取一行字符串
relational operators (重点)             大小比较

  4string的读写 

  利用cout可以打印string,即将string输出到标准输出端,也就是命令行窗口。类似的,c++也提供了一种方法从标准输入端,也就是键盘将数据写入string。

#include<iostream>
#include<string>
using namespace std;//string的读写int main()
{string s1;string s2;cout << "请输入用两个空格隔开的字符串!" << endl;cin >> s1 >> s2;cout << "s1: " << s1 << endl;cout << "s2: " << s2 << endl;return 0 ;
}

5 字符串比较

  string类中字符串比较函compare数有多个重载版本,既可以和C语言风格const char *字符串进行比较,也可以和string类字符串进行比较。相等返回0,不相等返回!0值。

字符串比较:
int compare(const char *str);//相等返回0,否则返回非0值
//比较string的len个字符,从idx位置开始
int string::compare (size_type idx, size_type len, const string& str) const
//从指定位置指定长度开始比较
int string::compare (size_type idx, size_type len, const string&str, size_type str_idx, size_type str_len) const
 

#include < iostream >
using namespace std;
#include < string >
void test()
{string str1 = "hello,world";if (str1 == "hello,world"){cout << "[const char *]相等" << endl;}string str2 = "hello,world";if (str1 == str2){cout << "[string]相等" << endl;}if (!str1.compare("hello,world")){cout << "[compare]相等" << endl;}//比较str1的前6个字符int ret=str1.compare(0,6,"hello,");cout << "ret=" << ret << endl;//从str1的第0个开始开始取出6个字符,//从"c++,hello,"的第4个位置开始,取出6个字符进行比较ret = str1.compare(0, 6, "c++,hello,", 4, 6);cout << "ret=" << ret << endl;
}
int main()
{test();system("pause");
}

6字符串的插入与删除

string类中插入函数insert支持多种插入方式,有多个重载版本。
字符串删除可以使用erease函数实现。

 

c++插入:
string& insert(int pos,const char *s);//从第pos位置开始插入s
string& insert(int pos,const string &s);

string &insert(int p0, const char *s, int n);//从p0位置开始插入s,插入的s连续n个字符
string &insert(int p0,const string &s, int pos, int n);//从p0位置开始插入s,插入的s从pos开始,连续n个字符

string &insert(int p0, int n, char c);//从p0处插入n个字符c

c++删除字符串
string &erase(int pos,int n=npos);//从pos位置开始删除n个字符
 

#include < iostream >
#include < string >
using namespace std;
void test()
{string str = "hello,";str.insert(2,"aaa");//从第2个位置开始插入aaacout < < "str=" << str << endl;str.insert(4, "1234", 1, 2);//从第4个位置插入,从"1234"的第1个位置开始,连续两个字符插入到str中cout << "str=" << str << endl;//字符串删除str.erase(2,4);//从第2个位置开始,删除4个字符cout << "str=" << str << endl;str.erase();//清空字符串cout < < "str=" << str <<"\t长度:"<< str.size()<<endl;

 3.vs和g++下string结构说明

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

3.1vs下string的结构:

string总共占28 个字节 ,内部结构稍微复杂一点,先是 有一个联合体,联合体用来定义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;

      这种设计也是有一定道理的,大多数情况下字符串的长度都小于16,那string对象创建好之后,内 部已经有了16个字符数组的固定空间,不需要通过堆创建,效率高。  其次:还有一个size_t字段保存字符串长度,一个size_t字段保存从堆上开辟空间总的容量 最后:还有一个指针做一些其他事。  故总共占16+4+4+4=28个字节。   

3.2.g++string的结构

G++ 下, string 是通过写时拷贝实现的, string 对象总共占 4 个字节,内部只包含了一个指针,该指
针将来指向一块堆空间,内部包含了如下字段:
  • 空间总大小
  • 字符串有效长度
  • 引用计数
struct _Rep_base
{size_type _M_length;size_type _M_capacity;_Atomic_word _M_refcount;
};
  • 指向堆空间的指针,用来存储字符串。

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

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

相关文章

Python 内置函数详解 (3) 进制转换

近期在外旅游,本篇是出发前定时发布的,不完整,旅游回来后再补充。 Python 内置函数 Python3.11共有75个内置函数,其来历和分类请参考:Python 新版本有75个内置函数,你不会不知道吧_Hann Yang的博客-CSDN博客 函数列表 abs aiter all …

Android LiveData 介绍

Android LiveData 介绍 系列文章目录前言一、LiveData是什么&#xff1f;二、简单使用依赖测试数据准备1.创建可观察的livedata2.观察它3.更新它 总结 系列文章目录 Android LiveData 介绍&#xff08;本文&#xff09; 前言 本系列根据官网介绍Jetpack中的数据通信组件&…

Appium开发

特点 开源免费支持多个平台 IOS(苹果)、安卓App的自动化都支持 支持多种类型的自动化 支持苹果、安卓应用原生界面的自动化支持应用内嵌网络视图的自动化支持手机浏览器(Chrome)中的web网站自动化支持flutter应用的自动化 支持多种编程语言 像selenium一样&#xff0c;可以用多…

27、Flink 的SQL之SELECT (Pattern Recognition 模式检测)介绍及详细示例(7)

Flink 系列文章 1、Flink 部署、概念介绍、source、transformation、sink使用示例、四大基石介绍和示例等系列综合文章链接 13、Flink 的table api与sql的基本概念、通用api介绍及入门示例 14、Flink 的table api与sql之数据类型: 内置数据类型以及它们的属性 15、Flink 的ta…

最新AI智能创作系统ChatGPT商业源码+详细图文搭建部署教程+AI绘画系统

一、AI系统介绍 SparkAi创作系统是基于国外很火的ChatGPT进行开发的Ai智能问答系统。本期针对源码系统整体测试下来非常完美&#xff0c;可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如何搭建部署AI创作ChatGPT&#xff1f;小编这里写一个详细图文教程吧&am…

机器学习之广义增量规则(Generalized Delta Rule)

文章目录 广义增量规则的公式s型函数的增量规则 广义增量规则的公式 对于单层神经网络的增量规则&#xff0c;已经过时啦&#xff0c;现在存在一种更广义的增量规则形式。对于任意激活函数&#xff0c;增量规则表示如下式它与前一节的delta规则相同&#xff0c;只是ei被替换为…

ccf_csp第一题汇总

ccf_csp第一题汇总 printf()输出格式大全&#xff08;附 - 示例代码&#xff09;现值计算AcWing 4699. 如此编码AcWing 4509. 归一化处理(小数位数根号函数)AcWing 4454. 未初始化警告AcWing 4280. 序列查询AcWing 4006. 数组推导(小陷阱)AcWing 3292. 称检测点查询AcWing 3287…

Linux知识点 -- 网络基础 -- 传输层

Linux知识点 – 网络基础 – 传输层 文章目录 Linux知识点 -- 网络基础 -- 传输层一、传输层协议1.端口号2.网络相关bash命令 二、UDP协议1.UDP报文的解包与交付2.理解UDP报文3.UDP协议的特点4.UDP应用层IO类接口5.UDP的缓冲区6.UDP使用注意事项7.基于UDP的应用层协议 三、TCP协…

lv5 嵌入式开发-11 消息队列

掌握&#xff1a;消息队列机制、打开/创建消息队列、发送消息、接收消息 1 消息队列 消息队列是System V IPC对象的一种 消息队列由消息队列ID来唯一标识 消息队列就是一个消息的列表。用户可以在消息队列中添加消息、读取消息等 消息队列可以按照类型来发送/接收消息 消…

Spring Boot:利用JPA进行数据库的增改

目录 JPA介绍Service接口Service和Autowired示例代码 Dao数据库操作层Repository示例代码 控制器文件示例代码-增加增加成功示例代码-修改修改成功 JPA介绍 JPA&#xff08;Javaa Persistence API)一种用于持久化 Java 对象到关系型数据库的标准规范。它提供了一种统一的方式来…

Pytorch单机多卡分布式训练

Pytorch单机多卡分布式训练 数据并行&#xff1a; DP和DDP 这两个都是pytorch下实现多GPU训练的库&#xff0c;DP是pytorch以前实现的库&#xff0c;现在官方更推荐使用DDP&#xff0c;即使是单机训练也比DP快。 DataParallel&#xff08;DP&#xff09; 只支持单进程多线程…

openGauss学习笔记-83 openGauss 数据库管理-内存优化表MOT管理-内存表特性-MOT使用内存和存储规划

文章目录 openGauss学习笔记-83 openGauss 数据库管理-内存优化表MOT管理-内存表特性-MOT使用内存和存储规划83.1 MOT内存规划83.2 存储IO83.3 容量需求 openGauss学习笔记-83 openGauss 数据库管理-内存优化表MOT管理-内存表特性-MOT使用内存和存储规划 本节描述了为满足特定…

完整的 pixel 6a 刷入 AOSP 源码过程记录

基础环境 虚拟机&#xff1a;VMware Workstation 16 Pro 16.0.0 build-16894299 Linux版本&#xff1a;ubuntu-16.04.7-desktop-amd64 设备&#xff1a;pixel 6a&#xff1b;代号&#xff1a;bluejay&#xff1b; 基础软件安装 安装 Git 命令&#xff1a;sudo apt install git …

金融生产存储亚健康治理:升级亚健康 3.0 ,应对万盘规模的挑战

随着集群规模的不断扩大&#xff0c;硬盘数量指数级上升&#xff0c;信创 CPU 和操作系统、硬盘多年老化、物理搬迁等多种复杂因素叠加&#xff0c;为企业的存储亚健康管理增加了新的挑战。 在亚健康 2.0 的基础上&#xff0c;星辰天合在 XSKY SDS V6.2 实现了亚健康 3.0&#…

【C++入门到精通】C++入门 —— set multiset (STL)

阅读导航 前言一、set简介二、std::set1. std::set简介2. std::set的使用- 基本使用- std::set的模板参数列表- std::set的构造函数- std::set的迭代器- std::set容量与元素访问函数 3. set的所有函数&#xff08;表&#xff09; 三、std::multiset1. std::multiset简介 四、st…

嵌入式学习笔记(35)外部中断

6.9.1什么是外部中断 (1)内部中断就是指中断源来自于SoC内部&#xff08;一般是内部外设&#xff09;&#xff0c;譬如串口、定时器等部件产生的中断&#xff1b;外部中断是SoC外部的设备&#xff0c;通过外部中断对应的GPIO引脚产生的中断。 (2)按键在SoC中就使用了外部中断…

【每日一题】1498. 满足条件的子序列数目

1498. 满足条件的子序列数目 - 力扣&#xff08;LeetCode&#xff09; 给你一个整数数组 nums 和一个整数 target 。 请你统计并返回 nums 中能满足其最小元素与最大元素的 和 小于或等于 target 的 非空 子序列的数目。 由于答案可能很大&#xff0c;请将结果对 109 7 取余后…

stm32无人机-飞行力学原理

惯性导航&#xff0c;是一种无源导航&#xff0c;不需要向外部辐射或接收信号源&#xff0c;就能自主进行确定自己在什么地方的一种导航方法。 惯性导航主要由惯性器件计算实现&#xff0c;惯性器件包括陀螺仪和加速度计。一般来说&#xff0c;惯性器件与导航物体固连&#xf…

CTFSHOW SSTI

目录 web361 【无过滤】 subprocess.Popen os._wrap_close url_for lipsum cycler web362 【过滤数字】 第一个通过 计算长度来实现 第二个使用脚本输出另一个数字来绕过 使用没有数字的payload web363 【过滤引号】 使用getitem 自定义变量 web364 【过…

数据集笔记:OpenCelliD(手机基站开放数据库)

下载数据的方式可见&#xff1a;【数据获取】全球最大手机基站开源数据库 1 读取数据 import pandas as pdpd.read_csv(C:/Users/16000/Downloads/454.csv/454.csv,headerNone,names[Radio,MCC,MNC,LAC/TAC/NID,CID,Longitude,Latitude,Range,Samples,Changeable1,Changeable…