08 string类的使用

为什么要学习string类

c语言中的字符串

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

标准库的string类

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

总结:
1.string是表示字符串的字符串类
2.该类的接口与常规容器的接口基本相同,再添加了一些专门操作string的常规操作
3.string再底层实际是: basic_string模板类的别名,typedef basic_string<char,char_traits,akkocator> string;
4.不能操作多字节或者变长字符的序列

string有四个版本,分别基于不同的编码,默认utf-8,根据字符第一个二进制是1还是0区分用ascii还是2字节一读,还有utf-16和utf-32,wstring
在这里插入图片描述

string类的常用接口

1.string类对象的构造

constructor函数名称功能说明
string() 重点构造空的类对象,空字符串
string(const char*s) 重点c-string构造string类对象
string(size_t, char c)n个字符c
string(const string& s) 重点拷贝构造函数

在这里插入图片描述

void Teststring()
{string s1; // 构造空的string类对象s1string s2("hello bit"); // 用C格式字符串构造string类对象s2string s3(s2); // 拷贝构造s3
}

2. 容量操作

函数名称功能说明
size 重点返回字符串有效字符长度
length返回字符串有效字符长度
capacity返回空间总大小
empty 重点检测字符串是否为空串
clear 重点清空有效字符
reserve 重点为字符串预留空间
resize 重点将有效字符的个数改成n个,多出的空间用字符c填充
void test2()
{string s1("hello");cout << s1.size() << "\n";cout << s1.length() << "\n";cout << s1.capacity() << "\n";/*s1.clear();cout << s1.size() << "\n";cout << s1.length() << "\n";cout << s1.capacity() << "\n";*//*s1.resize(10);cout << s1 << endl;*//*s1.resize(10, 'd');cout << s1 << endl;*//*s1.resize(3);cout << s1.size() << "\n";cout << s1.length() << "\n";cout << s1.capacity() << "\n";*/s1.reserve(20);cout << s1.size() << "\n";cout << s1.length() << "\n";cout << s1.capacity() << "\n";cout << s1 << endl;
}

注意:
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, char c)用字符c填充空间.注意: resize增多,可能会改变容量大小,减少时,空间大小不变
4.reserve(size_t res_art=0):为string预留空间,不改变有效元素个数,当reserve的参数小于string的底层空间总大小时,不会改变容量大小

3. 访问及遍历操作

函数名称功能说明
operator[] 重点返回pos位置的字符,const string类对象调用
begin+endbegin去第一个字符的迭代器,end取最后一个字符下一个位置的迭代器
rbegin+rendrbegin取最后一个字符的迭代器,rend取第一个字符
范围forc++11支持更简洁的for遍历方式
void test3()
{string s1("hello");//遍历1 下标访问for (size_t i = 0; i < s1.size(); i++){cout << s1[i];}cout << endl;//遍历2 迭代器string::iterator it = s1.begin();//string::const_iterator cit = s1.begin();  //const类型for (; it != s1.end(); it++){cout << *it;}cout << endl;//string::reverse_iterator rit = s1.rbegin();//string::const_reverse_iterator crit = s1.begin();auto it1 = s1.rbegin(); //自动推导迭代器类型while (it1 != s1.rend()){cout << *it1;it1++;}cout << endl;//遍历3 范围forfor (auto c:s1){cout << c ;}cout << endl;}

下标[]访问越界会报错,at访问则会抛异常

4. 修改操作

函数名称功能说明
push_back在字符串后面插入字符
append在字符串后追加一个字符串
operator+= 重点在字符串后追加字符串
c str 重点返回c格式字符串,遇\0结束
find+npos 重点从字符串pos位置开始往后找字符c,返回该字符的位置
rfind从字符串pos位置开始往前找字符c,返回该字符位置
substr在str中从pos位置开始,截取n个字符返回
void test4()
{string s1("hello");s1.push_back('c');s1.append("world");s1 += "ni";printf("%s\n",s1.c_str());int pos = s1.find('o');if (pos != string::npos){cout << "找到"<<pos << endl;}int pos2 = s1.rfind('o');if (pos2 != string::npos){cout << "找到" << pos << endl;}string s2 = s1.substr(pos, 2);cout << s2 << endl;
}

注意:
1.在string尾部追加字符时,pushback/append/+=三种实现方式差不多,一般+=用的比较多,不仅可以连接单个字符,还可以是字符串
2.string操作,如果能够预估到村多少字符,可以先通过reserve把空间预留好
3.insert往中间插入,但不推荐,效率不高
4.删除earse同中间插入,给一个位置,不给数量会将后面的全部删除
5.replace替换字符
6.npos的值是-1,size_t类型会变为int最大值

替换字符串指定字符

//	string s1("hello world i love you");
//	string newStr;
//	size_t num = 0;
//	for (auto ch : s1)
//	{
//		if (ch == ' ')
//			++num;
//	}
//	// 提前开空间,避免repalce时扩容
//	newStr.reserve(s1.size() + 2 * num);
//
//	for (auto ch : s1)
//	{
//		if (ch != ' ')
//			newStr += ch;
//		else
//			newStr += "%20";
//	}

两个swap功能一样,而针对类的交换函数更高效,只需要改变指针
在这里插入图片描述

转换c串用于调用c函数的接口,需要传入c字符串,例如打开文件fopen

substr取字符串指定内容,也可以查找任一字符

void test5()
{//string s1("hello");//size_t pos = s1.find('e');//if (pos != string::npos)//{//	string suffix = s1.substr(pos, s1.size() - pos);//第二个参数可以缺省//	cout << suffix;//}//取网址中间内容域名,xxxx.comstring url = "https://legacy.cplusplus.com/reference/string/string/";size_t pos = url.find("://");if (pos != string::npos){size_t finish = url.find('/',pos + 3);string suffix = url.substr(pos + 3, finish - (pos + 3));//第二个参数可以缺省cout << suffix;}url.find_first_of("abcd"); //找字符串中包含任一字符url.find_last_of("abcd"); //倒着找
}

非成员函数

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

6. msvc和g++string结构

下述结构式32位平台验证,32位平台指针占4字节

vs的string
共占28字节,内部先有一个联合体,定义string字符串的存储空间

  • 当字符串长度小于16时,使用内部固定的字符数组存放
  • 当字符串长度大于等于16时,从堆上开辟空间
  • 扩容时除第一次外都是1.5被扩容
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对象创建时需要的空间是固定空间,不用从堆申请,效率高
还有一个size_t保存字符串长度,一个size_t字段保存从对数开辟空间的总量
还有一个指针做其他事情

所以总共28个字节
在这里插入图片描述

*g++结构
string通过写时拷贝实现,string对象共4个字节,内部包含一个指针,指向一块堆空间,包含如下字段:
空间不够2倍扩容

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

练习

仅仅反转字母
https://leetcode.cn/problems/reverse-only-letters/submissions/
在这里插入图片描述

思路:
用两个下标,一个从头,一个从尾,找到是字母的就交换。交换完记得移动下标,不然还是换这两个

class Solution {
public:string reverseOnlyLetters(string s) {int begin = 0;int end = s.size() - 1;while (begin < end){while (begin < end && !isalpha(s[begin])){begin++;}while (begin < end && !isalpha(s[end])){end--;}swap(s[begin], s[end]);//交换后继续移动一步,防止再次交换begin++;end--;}return s;}
};

找出第一个只出现一次的字母
https://www.nowcoder.com/practice/e896d0f82f1246a3aa7b232ce38029d4?tpId=37&&tqId=21282&rp=1&ru=/activity/oj&qru=/ta/huawei/question-ranking

在这里插入图片描述

思路:
可以利用计数排序的思路,记录字符串内26个字母的数量,然后根据字符串每个字母查看计数,如果是1打印这个字符,如果不是就打印-1

#include <iostream>
using namespace std;int main() {string s;cin >> s;int ary[26] = {0};//计数,对应26个字母for (auto ch : s ) {ary[ch - 'a']++;}for (int  i = 0; i < s.size(); i++) {if (ary[s[i] - 'a'] == 1) {cout << s[i];return 0;}}cout << -1;
}

字符串最后一个单词长度
https://www.nowcoder.com/practice/8c949ea5f36f422594b306a2300315da?tpId=37&&tqId=21224&rp=5&ru=/activity/oj&qru=/ta/huawei/question-ranking

在这里插入图片描述

思路:
记录长度,下标从最后一个字母开始,如果不是空格就循环,统计完长度

也可以利用字符串倒着查找函数,找到第一个空格,用字符串长度减去找到的位置再减1就是最后一个单词的长度

#include <iostream>
using namespace std;int main() {string s;getline(cin, s);//记录下标和长度int length = 0;int sign = s.size() - 1;while (sign >=0 && s[sign] != ' '){length++;sign--;}cout<<length;
}
#include <iostream>
using namespace std;int main() {string s;getline(cin, s);//查找int pos = s.rfind(' ');if(pos != string::npos){cout<<s.size() - pos -1<<endl;}else {cout<<s.size()<<endl;}}

字符串相加
https://leetcode.cn/problems/add-strings/description/

在这里插入图片描述

思路:
两个字符串从最后一位开始,逐个相加,用一个新字符串保存结果。相加得到的数%10后得到存储的数,尾插到新字符串里。/10后得到进位,如果有进位,加到下一个位计算。哪个字符串空了,返回0来相加

注意相加时需要转换为整数,不是字符串ascii相加。最后有进位处理一次。将结果逆置

class Solution {
public:string addStrings(string num1, string num2) {int length1 = num1.size() - 1;int length2 = num2.size() - 1;string s;//预先开辟空间,节省消耗s.reserve( num1.size() >  num2.size()?  num1.size() + 1:num2.size() + 1);int carry = 0;while (length1 >= 0 || length2 >= 0) {//取需要相加的数int val1 = length1 >=0 ? num1[length1] - '0' : 0;int val2 = length2 >=0 ? num2[length2] - '0' : 0;//相加,包括进位int num = val1 +val2 +carry;char ret = num % 10 + '0';s += ret;carry = num / 10;length1--;length2--;}if (carry){s += '1';}reverse(s.begin(), s.end());cout << s;return s;}
};

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

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

相关文章

Element复选框只要框不要字

场景 复选框分别放在多个选项后&#xff0c;只需要勾选框&#xff0c;不要展现的文字。 实现 <el-checkbox-group v-model"checkList"><el-checkbox label"使用核武器"></el-checkbox> </el-checkbox-group> ... data() {retu…

Leetcode——hot3最长连续序列

最长连续序列 class Solution {public int longestConsecutive(int[] nums) {if(nums.length 0 || nums.length 1){return nums.length;}Arrays.sort(nums);int count 1;int max 1;for(int i 0; i < nums.length - 1; i){if(nums[i1] - nums[i] 1){count;if(count &…

2004-2020年全国及各省森林覆盖率、森林面积等数据

数据名称:中国及各省森林资源指标面板数据 数据来源:中国环境统计年鉴(2004-2020年) 森林覆盖率是指森林面积占土地总面积的比率,是反映一个国家(或地区)森林资源和林地占有的实际水平的重要指标,一般使用百分比表示。 林业用地面积是指生长乔木、竹类、灌木、沿海红…

逆序或者正序打印一个数的每一位数,递归实现(C语言)

从键盘上输入一个不多于5位&#xff08;包括5位&#xff09;的正整数&#xff0c;要求 &#xff08;1&#xff09;求出它是几位数&#xff1b;&#xff08;2&#xff09;分别输出每一位数字&#xff08;3&#xff09;按逆序输出各位数字 &#xff08;1&#xff09;求出它是几位…

WPF中如何使用HandyCotrol控件库

HandyControl介绍 HandyControl是一个开源的WPF&#xff08;Windows Presentation Foundation&#xff09;控件库&#xff0c;旨在简化WPF应用程序的开发过程并提高用户界面的美观程度和易用性。它提供了丰富的控件、样式和模板&#xff0c;可以帮助开发人员快速构建出现代化的…

早春女童氛围感穿搭~绝美的新中式

古典的山树绣花设计 精致典雅&#xff0c;上身立体又轻盈 做了粉绿两色&#xff0c;很适合春天的氛围 春天是个适合外出游玩的季节 穿上这件出游真的超美&#xff0c;日常穿也可 超出片很吸睛&#xff01;&#xff01;

远程控制APP,高效生活的秘诀!

在这个科技日新月异的时代&#xff0c;我们的生活被各种手机软件所包围。几乎每个人都有一个甚至多个手机&#xff0c;你是否也有遇到过需要远程操作自己某一台手机的场景呢&#xff1f;今天&#xff0c;我要向大家推荐一款神奇的手机远程操作神器&#xff0c;让你可以随时随地…

一文读懂 Python 值传递和引用传递

文章目录 版本前言形参和实参值传递和引用传递Python 变量存储值语义和引用语义值语义引用语义 探讨 Python 值传递和引用传递不可变&#xff08;immutable&#xff09;类型可变&#xff08;mutable&#xff09;类型案例一案例二 拓展&#xff1a;不可变类型真的不可变&#xf…

探索 Sora 背后的核心技术

2024年2月16日&#xff0c;OpenAI发布Sora文生视频模型&#xff0c;一石激起千层浪&#xff0c;迅速刷屏爆火于整个AI圈。一方面&#xff0c;Sora从文本、图像迈向视频大模型&#xff0c;这可以说是通向通用人工智能的里程碑事件&#xff1b;另一方面&#xff0c;训练和推理需求…

设计模式(三)建造者模式

相关文章设计模式系列 1.建造者模式简介 定义 建造者模式&#xff08;builder&#xff09;&#xff0c;将一个复杂对象的构建与它的表示分离&#xff0c;使得同样的构建过程可以创建不同的表示。 简介 建造者模式&#xff08;builder&#xff09;是创建一个复杂对象的创建型…

2024图像处理分析与信息工程国际学术会议(IACIPIE2024)

2024图像处理分析与信息工程国际学术会议(IACIPIE2024) 会议简介 2024图像处理分析与信息工程国际学术会议&#xff08;IACIPIE2024&#xff09;将在中国长沙举行。 IACIPIE2024是一个年度会议&#xff0c;探讨图像处理分析和信息工程相关领域的发展和影响&#xff0c;旨在介…

状态机-----

1.原理 同步的意思就是状态的跳转都是在时钟的作用下跳转的&#xff0c;有限是指状态机中状态的个数是有限的。两种状态机的共同点都是状态的跳转只和输入有关&#xff0c;区别就是如果最后的输出只和当前状态有关而与输入无关&#xff0c;则是moore型状态机。如果最后的输出不…

STM32学习3 寄存器映射和GPIO寄存器编程

STM32学习3 寄存器映射和GPIO寄存器编程 一、STM32外设内存空间1. 内存空间划分2. 区域功能说明&#xff08;1&#xff09;block0&#xff08;2&#xff09;block1&#xff08;3&#xff09;block2&#xff08;4&#xff09;block3~4&#xff08;5&#xff09;block5&#xff0…

猫咪挑食不吃猫粮怎么办?适口性高、可以改善猫咪挑食的主食冻干分享

猫咪挑食不吃猫粮怎么办&#xff1f;在现今社会&#xff0c;养猫的人越来越多&#xff0c;大家都把自家的小猫当作宝贝来宠爱。但宠爱过度有时也会导致猫咪养成挑食的坏习惯。面对这一问题&#xff0c;我们应该如何解决呢&#xff1f;今天&#xff0c;我要分享一个既能确保猫咪…

Adobe Illustrator 2022 for Mac/Win:设计的新篇章

在数字艺术和设计领域&#xff0c;Adobe Illustrator一直以其强大的功能和高效的工具受到专业人士的青睐。随着2022年的到来&#xff0c;Adobe Illustrator 2022&#xff08;简称AI 2022&#xff09;的发布无疑为设计师们带来了新的希望和期待。 一、强大的新功能 AI 2022引入…

什么是小红书品牌笔记,如何做好达人投放?

认认真真撰写了小红书品牌笔记&#xff0c;从各个方面确保了笔记的优质程度&#xff0c;却没能产生爆文。这很可能是笔记与用户之间的中间环节出了问题&#xff0c;也就是达人投放有问题。今天我们就为大家带来什么是小红书品牌笔记&#xff0c;如何做好达人投放&#xff1f; 一…

【c语言】if 选择语句

&#x1f388;个人主页&#xff1a;豌豆射手^ &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f917;收录专栏&#xff1a;C语言 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共同学习、交流进步&…

Navicat的使用

1. Navicat介绍 Navicat: 是一款流行的数据库管理和开发工具, 它支持多种数据库系统, 如: MySQL, MariaDB, MongoDB, SQL Server, Oracle, PostgreSQL 等. Navicat通过提供直观的图形用户界面(GUI), 使用户能够更轻松地执行各种数据库操作, 而无需记住复杂的SQL命令.以下是Nav…

PyQt5图片浏览器

PyQt5图片浏览器 实现方式功能实现具体代码 界面实现pillow源码修改ImageQt错误主页面布局 项目开源地址 分享一个图片浏览器 实现方式 qt本身有一个QGraphicsView类用来当做视图框架。 具体参考&#xff1a;如何在pyqt中使用 QGraphicsView 实现图片查看器 不过大佬给的例子…

聚集高速托盘类四向穿梭车ASRV|一车跑全仓可获得10000个货位的HEGERLS智能搬运机器人

随着国内外制造业加速转型升级&#xff0c;越来越多的企业需要进行物流智能化升级&#xff0c;但是往往受到仓库面积、高度、形状等现实条件的限制&#xff0c;以及市场不确定性因素的影响。因此&#xff0c;相对于投资传统的自动化立体库&#xff0c;企业更倾向于选择智能化、…