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,一经查实,立即删除!

相关文章

日本韩国媒体宣发稿渠道平台怎么找?跨境出海推广新闻报道营销公司告诉你

【本篇由言同数字科技有限公司原创】随着全球化和互联网的快速发展&#xff0c;品牌出海已经成为众多企业的共同目标。在这个过程中&#xff0c;通过在日本和韩国的媒体上发表文章&#xff0c;可以带来许多重要的意义和益处。在本文中&#xff0c;我们将探讨一下这些意义。 首…

MySQL学习Day21-索引的创建与设计原则

一、索引的声明与使用 1.索引的分类: 功能逻辑:普通索引、全文索引、单列索引、多列索引和空间索引 物理实现:聚簇索引和非聚簇索引 作用字段个数:单列索引和联合索引 (1)普通索引:在创建普通索引时&#xff0c;不附加任何限制条件&#xff0c;只是用于提高查询效率&#…

关于跨链桥的访谈链接合集

想了解跨链桥&#xff0c;知名人士的访谈也很重要&#xff0c;下面是相关知名人士的访谈合计 1&#xff1a;Andre Cronje 专访Andre Cronje&#xff1a;99% 的项目都是垃圾&#xff0c;但是还有 1% 的真正价值存在 https://www.panewslab.com/zh/articledetails/g52p2lpbudmm.…

在Android中使用ActiveMQ通信应用MQTT

1.MQTT简介: MQTT 是一种基于发布订阅模型的即时通讯协议,它被设计为一个极其轻量级的发布/订阅消息传输协议。对于需要较小代码占用空间和/或网络带宽非常宝贵的远程连接非常有用,是专为受限设备和低带宽、高延迟或不可靠的网络而设计,所以主要应用于物联网设备中。 2.MQTT…

Element复选框只要框不要字

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

Java零基础-do-while循环语句

前言 Java作为一门高级编程语言&#xff0c;其强大的功能和应用广泛性备受程序员和开发者青睐。而在Java中&#xff0c;循环语句是程序开发中的重要组成部分&#xff0c;其中的do-while循环语句也是其中的一个必备知识点。 本文将以Java语言为例&#xff0c;详细介绍do-while…

Android 指南针校准进度计算实现

关于Android中指南针的实现&#xff0c;我们可以使用传感器来获取设备的方向信息&#xff0c;从而实现指南针功能。 Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);sensorManager (SensorManager) getSystemService(Conte…

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;求出它是几位…

Date时间 ,Calendar日历,Timer TimerTask定时任务

Date Date date new Date();System.out.println(date);//Tue Feb 27 10:00:58 CST 2024System.out.println(date.toString());//Tue Feb 27 10:01:42 CST 2024System.out.println(date.getTime());//1669617690850//规范化SimpleDateFormat simpleDateFormat new SimpleDateF…

A星寻路算法及拆解demo

关于自动寻路&#xff0c;在游戏中还是经常会遇到的。如角色如何代价最小(距离少&#xff0c;时间快&#xff0c;方式支持)移动到某个位置。本篇记录下A*寻路的流程与优化。 为了做一个可以方便展示在web的demo&#xff0c;更好拆解寻路的步骤&#xff0c;所以本篇用了cocos c…

React入门简介

React简介 react是Facebook用来创建用户界面的js库。React不是一个MVC框架&#xff0c;而是一个用于构建组件ui库&#xff0c;是一个前端界面开发工具&#xff0c;所以很多人认为React是MVC中的V&#xff08;视图&#xff09;。React的存在能够很好的解决‘构建随着时间数据不断…

WPF中如何使用HandyCotrol控件库

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

前端 实现 每5分钟遍历一次集控的数据接口,将多类型的统计结果insert到TD数据库的指标统

涉及点&#xff1a; setInterval 定时任务。axios 请求. env配置项。 // 引入所需模块 const axios require(axios); // 发送HTTP请求 const moment require(moment); // 处理日期时间 require(dotenv).config(); // 加载.env文件中的配置信息// TD数据库连接参数 const tdA…

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

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

LeetCode 刷题 [C++] 第438题.找到字符串中所有字母异位词

题目描述 给定两个字符串 s 和 p&#xff0c;找到 s 中所有 p 的 异位词 的子串&#xff0c;返回这些子串的起始索引。不考虑答案输出的顺序。 异位词 指由相同字母重排列形成的字符串&#xff08;包括相同的字符串&#xff09;。 题目分析 在字符串 s中使用同向双指针来查…

远程控制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;训练和推理需求…