STL库——string类的常见使用

news2024/7/5 0:00:31

一、基本介绍

1.string类是STL库里面比较常见的一个数据结构,string是表示字符串的字符串类 ,该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。

2.string在底层实际是:basic_string模板类的别名,typedef basic_string string;

3.不能操作多字节或者变长字符的序列。

4.在使用string类时,必须包含#include头文件以及using namespace std;

二、string类的常见接口

1.string类常见的构造

函数名称功能说明例子
string()构造空的string类对象,即空字符串string s1;
string(const char*s)用常量字符串类构造string类对象string s2("hello world");

string(size_t , char c)

string类对象中包含n个字符cstring s3(5,'*');
string(const string&s)拷贝构造函数string s4(s2);

2.string类对象的容量操作

函数名称功能说明
size()返回字符串有效字符长度
capacity()返回空间总大小
empty()检测字符串是否为空串,是返回true,否则返回false
clear()清空有效字符
reserve(size_t)可用于提前开辟空间,减少扩容,提高效率,在进行字符串修改操作时,如果能够预先知道要使用多大的空间,建议提前开好空间,避免扩容
resize(size_t n , const char c)将有效字符数改成n个,多出来的空间由字符c填充,不给c则默认为0

注意:

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

2.size决定有效长度,而不是‘\0’决定,capacity决定实际开辟空间的大小

3.关于resize的使用,resize改变的是有效长度,若改变后大于原本长度,可能会发生扩容,也可能不会,看size是否大于capacity,容是小于原本长度,有效长度缩减,但实际开辟的空间大小capacity不会缩减。在扩大有效长度后,多出来的空间,若是给了第二个参数,则根据第二个参数所给的字符进行初始化,若没给则是默认用'\0'初始化,缩小有效长度后,有效长度以外的同样按以上原则初始化

4.reserve改变的是实际大小,而不改变有效长度,若是给的参数小于原先的capacity,则不发生任何改变,当大于capacity时,则按照给定值进行扩容(至少会等于给定值,也有可能扩容后会大于给定值,根据编译器不同所不同)。

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

函数名称功能说明
operator[]返回pos位置的字符,const string类对象调用
begin + endbegin获取第一个字符的迭代器+end获取最后一个字符下一个位置的迭代器,迭代器对应的类型有const_iterator 和 iterator
rbegin + rend

反向迭代器,可以实现从字符串最后一个遍历到第一个

对应的类型是 reverse_iterator  和  const_reverse_iterator

为了方便,可以使用auto(自动识别类型)

范围forC++11支持更加简洁的范围for的遍历auto

例子:用迭代器遍历字符串(begin和end)

例子:用范围for去遍历字符串

for(auto ch: s1)
{
    cout << ch << '/';
}

例子:下标访问

for(int i=0;i<s1.size;i++)
{
    cout << s1[i] << '/';
}

4. string类对象的修改操作

函数名称功能说明
push_back在字符串后面尾插一个字符
append在字符串后面尾插一个字符串
operator+=可以用来直接代替上面两个的功能,推荐使用+=去实现尾插
c_str ( )返回c格式的字符串,此时有效长度按“\0”决定
find ( str,pos)第一个参数str是要查找的字符或者字符串,pos是查找的起始位置(默认从第一个开开始找),返回目标字符串第一次出现的下标,若是没找到则返回(size_t)string::npos
rfind从字符串最后一个字符往前开始查找,找到返回下标,没找到返回string::npos
substr(pos,nub)从pos位置开始截取nub个字符,若是不给nub,则默认截取到字符串结束,返回一个截取后的新字符串

例子:截取test.cpp的后缀

int main()
{
	string s1("test.cpp");//用substr和find去取出
	string suffix = s1.substr(s1.find('.'));
	cout << suffix << endl;
	system("pause");
	return 0;
}

5. string类非成员函数

函数名称功能说明
operator+尽量少用,因为存在拷贝构造,传值返回效率低
operator>>输入运算符重载
operator<<输出运算符重载
getline获取一行字符串,由于cin会将空格当作两段数据的分割,在一段字符串中有空格时,就需要用getline去获取字符串,例如:getline(cin, str);
relational operator比较类型的运算符重载

6.string类中find接口的归纳

函数名称功能介绍
find第一个参数给所要查找的字符串或者字符,第二个参数给查找的起点下标(默认从0开始),返回第一次找到时的下标位置,找不到则返回string::npos
rfind倒着往前找,找到返回起始下标,找不到返回string::npos
find_first_of第一个参数给一个字符串,当出现字符串当中的字符时,会返回对应位置的下标,第二个参数可以设置查找的起点,找不到返回string::npos
find_last_of从后往前找,出现第一个参数给的字符串中的字符时,返回对应位置的下标

例子:截取网址的域名

int main()
{
	// 取出url中的域名
	string url("http://www.cplusplus.com/reference/string/string/find/");
	int begin = url.find("://")+3;//找到域名开始的下标
	int end = url.find("/",begin);//域名结束的下标
	string address = url.substr(begin,end - begin);//用substr截取
	cout << address << endl;
	system("pause");
	return 0;
}

例子:指定替换

int main()
{
	//将其中所有a,b,c都替换成*
	string str ("Please, replace the vowels in this sentence by asterisks.");
	size_t found = str.find_first_of("abcs");
	cout << str << endl;
	while(found != string::npos)
	{
		str[found] = '*';
		found = str.find_first_of("abcs",found+1);
	}
	cout << str << endl;
	system("pause");
	return 0;
}

三、与string类相关的OJ练习

1.仅仅反转字母

题目链接:

917. 仅仅反转字母 - 力扣(LeetCode)

题目描述:

给定一串字符串,将其中的字母字符进行反转,其他字符相对位置不变

解题思路:

与快速排序的思路相似,用一个索引begin指向开头,一个end指向末尾,begin往后找字母,找到后停下,end往前找字母,找到后停下,然后进行交换,重复操作直到遍历完整个字符串

代码参考:

class Solution 
{
public:
    bool if_alphabet(char c)
    {
        if((c>='a' && c<='z') || (c>='A' && c<='Z'))
            return true;
        else
            return false;
    }

    string reverseOnlyLetters(string s) 
    {
        int begin = 0;
        int end = s.size()-1;
        while(begin<end)
        {
            while(!if_alphabet(s[begin]) && begin<end)
            {
                begin++;
            }
            while(!if_alphabet(s[end]) && begin<end )
            {
                end--;
            }
            swap(s[begin],s[end]);
            begin++;
            end--;
        }
        return s;
    }

};

2.找到第一个只出现过一次的字母字符

题目链接:

387. 字符串中的第一个唯一字符 - 力扣(LeetCode)

题目描述:

给定一个字符串,找到字符串中第一个字出现过一次的字母字符,返回对应位置的下标,如果没有只出现一次的字母,则返回-1。

解题思路:

用计数排序的思路,先将字符串遍历一遍,统计出每个字符出现的次数,得到该表格(数组),然后在遍历一次字符串,逐一查表得到每个字符出现的次数,第一个出现次数为1的字符时,返回下标,遍历结束后都没有返回则说明没找到,则返回-1。

参考代码:

class Solution 
{
public:

    
    int firstUniqChar(string s) 
    {
        //先进行计数排序,得到每个出现过的字母的一个出现次数表,再遍历一遍字符串,逐一查表即可得到第一个只出现一次的字符
        int CountSort[26] ={0};
        for(int i=0;i < s.size();i++)
        {
            CountSort[s[i]-'a']++;
        }
        for(int i=0;i < s.size();i++)
        {
            if(CountSort[s[i]-'a'] == 1)
                return i;
        }
        return -1;
    }
};

3.返回最后一个单词的长度

题目链接:

字符串最后一个单词的长度_牛客题霸_牛客网 (nowcoder.com)

题目描述:

给一串字符,单词间会用空格隔开,打印最后一个单词的长度

解题思路:

运用rfind找到空格位置即可算到最后一个单词的长度,需要注意的是,这里字符串的输入要用getline,而不能用cin。

参考代码:

#include <iostream>
#include <string>
using namespace std;


int main() 
{
    string str;
    getline(cin,str);
    size_t pos = str.rfind(" ");

    if(pos != string::npos)
    {
       cout << str.size() - pos - 1;
    }
    else 
    {
        cout << str.size();
    }

    return 0;
}

4.字符串相加

题目链接:

415. 字符串相加 - 力扣(LeetCode)

题目描述:

给两个数字相关的字符串,要求将两个字符串中的数字相加,其结果存到字符串中返回,该题目是为了解决一些特别大的数字相加时,int类型会溢出,用字符进行相加,自行设计规则,实现字符串相加

解题思路:

逐一将最后字符最后一个取出来进行相加,结果判断是否需要进位,从个位开始,一位位往前加,每次结果记录到字符串中当两个数字都从个位到最大位遍历结束后跳出循环,剩下的就是对一些细节和特殊情况进行特殊处理以及优化

特殊情况/需要注意的细节:

1.每次需要将进位进行更新

2.字符取出后需要减上字符0,而录入到字符串的结果需要加上字符0(类型转换)

3.可能存在其中一个数字已经遍历结束的情况,这个时候需要将其置成0,而不能直接结束循环,另一个数可能存在进位以及多次进位的情况。

4.可能存在两个数字同时结束遍历,但进位还没完成的情况,需要在循环外进行特殊处理

C++中若是使用string类解题,存在优化:

1.但凡使用string类都需要考虑下,是否可以提前开劈还足够的空间,避免扩容(扩容存在较大消耗)

2.根据题目要求以及设计思路,每次结果都会存入字符串中,每次存入一位,因此是头插操作,但头插消耗过大,可以采用尾插的方式,最终结果再进行逆置

代码参考:

class Solution 
{
public:
    string addStrings(string num1, string num2) 
    {
        int end1 = num1.size() -1;
        int end2 = num2.size() -1;
        int up = 0; //进位
        string str;
        //优化,提前开好空间,避免扩容消耗
        str.reserve(num1.size() > num2.size() ? num1.size()+1 : num2.size()+1);
        while(end1>=0 || end2>=0)//只要num1或者num2没结束就继续
        {
            int n1 = end1>=0? num1[end1]-'0' : 0;//取最后一位
            int n2 = end2>=0? num2[end2]-'0' : 0;
            int ret = n1+n2+up;
            up = ret/10;//重置进位
            ret = ret%10;
            str += (ret+'0');

            end1--;
            end2--;
        }
        if(up == 1)//避免两个同时走完,还没进位的情况
            str+='1';

        reverse(str.begin(),str.end());//优化,这里采用先存再逆置的方法,避免头插消耗过大
        return str;
    }
};

5.反转字符串2

题目链接:

541. 反转字符串 II - 力扣(LeetCode)

题目描述:

给一个字符串,每走2k长都需要反转前k个字符的字符串,长度不够k则全反转

解题思路:

估计题目画图分析发现,定义一个begin和end,每次往后走2k步,就是需要反转的区间,在判断下结束条件和末尾的各种情况即可。

代码参考:

class Solution {
public:

    void s_reverse(string& s,int begin,int end)
    {
        if(end > s.size()-1)
        {
            end = s.size() - 1;
        }
        while(begin < end)
        {
            swap(s[begin],s[end]);
            begin++;
            end--;
        }
    }

    string reverseStr(string s, int k) 
    {
        int begin = 0;
        int end = begin + k - 1;
        while(begin < s.size())
        {
            s_reverse(s,begin,end);
            begin+=2*k;
            end+=2*k;
        }

        return s;
    }
};

6.反转字符串中的单词

题目链接:

557. 反转字符串中的单词 III - 力扣(LeetCode)

题目描述:

在一段字符串中,找到单词部分进行反转,其余相对位置不变

解题思路:

用空格判断单词之间的间隔,用一个cur去遍历字符串,begin和end去进行逐段反转,最后是结束时的判断要注意

参考代码:

class Solution 
{
public:
    string reverseWords(string s) 
    {
        int cur = 0;
        int begin = 0;
        int end = 0;
        while(cur < s.size())
        {
            begin = cur;
            while(cur < s.size() && s[cur++]!=' ');
            if(cur == s.size())
            {
                end = cur - 1;
            }
            else
            {
                end = cur - 2;
            }
            while(begin < end)
            {
                swap(s[begin],s[end]);
                begin++;
                end--;
            }

        }
        return s;
    }
};

总结

本篇内容整理了关于string类的常用接口以及介绍,还整理了部分简单的Oj练习题可以用来巩固练习。

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

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

相关文章

全自动情感故事对话视频生成神器

搞笑聊天视频是近年来备受欢迎的一种娱乐形式&#xff0c;它能够快速、简单地制作出形象生动、幽默搞笑的对话视频&#xff0c;给人带来欢乐与笑声。而今天&#xff0c;我要向大家介绍的是一款功能强大、操作简单的搞笑聊天视频生成器。 这款聊天视频生成器具备多项令人惊叹的…

Linux内核之内存管理分段机制原理与实现(从无到有的过程)

1. 分段机制概述 对于分段机制&#xff0c;要从Intel的微处理器的8086开始说起&#xff0c;刚开始内存空间比较小&#xff0c;内存寻址采用的是直接访问物理地址的方式。由于技术的发展&#xff0c;计算机做的事情越来越多&#xff0c;程序也越来越大&#xff0c;为了更大的内…

重生奇迹MU游戏开店技巧

重生奇迹游戏开店攻略 在游戏之中有很多炫酷的玩法&#xff0c;而且还有存在很多奇怪的现象&#xff0c;很多玩家喜欢在游戏之中充当商人&#xff0c;然后在游戏之中开店卖一些东西&#xff0c;或者是倒卖一些物品。 从买卖物品之中赚取一定差价&#xff0c;的确这样可以为玩…

Jetsonnano B01 笔记8:屏幕分辨率的调整

最近我的jetson 被学弟借用学习了一阵子&#xff0c;他在一顿捯饬后&#xff0c;成功将我的屏幕分辨率改成了一个阴间的水平&#xff0c;十分影响操作学习。 终端命令更改分辨率&#xff1a; 我们可以打开终端&#xff0c;输入以下命令来更改分辨率&#xff0c;但这样做有一个…

6个基于DSPM组件的使用案例

在这个信息技术时代&#xff0c;企业必须应对日益增长的生成和保护大量数据的需求。这就是为什么制定广泛而有效的策略来处理和保护这些数据比以往任何时候都更加重要的原因。数据安全状况管理 &#xff08;DSPM&#xff09; 是一种解决方案&#xff0c;可帮助现代组织实施全面…

Unity 2021.x及以下全版本Crack

前言 最近Unity那档子事不出来了吗&#xff0c;搞得所有人都挺烦的&#xff0c;顺便在公司内网需要我完成一个游戏的项目&#xff0c;就研究了一下如何将Unity给Crack掉。 注意所有操作应有连接外网的权限 以我选择的版本为例&#xff0c;我使用的是Unity 2021.3.5f1与Unity…

【HarmonyOS】解决API6 WebView跳转外部浏览器问题、本地模拟器启动黑屏

【问题描述1】 HarmonyOS API6 Java开发中使用WebView组件&#xff0c;如果网页中有跳转链接&#xff0c;点击会跳转到手机系统浏览器。 【解决方案】 解决这个问题的方法就是给WebView这种自定义的WebAgent对象。具体代码如下&#xff1a; WebConfig webConfigthis.webView…

甲骨文创新中心与正初为职教集团达成人才培养合作,探索数实结合产教融合模式

2023年9月20日&#xff0c;甲骨文&#xff08;南京&#xff09;人工智能创新中心&#xff08;以下简称“甲骨文创新中心”&#xff09;与正初为职教集团在南京举行了战略合作签约仪式。甲骨文创新中心正式宣布和正初为职教集团达成职业教育数实结合产教融合合作协议&#xff0c…

数据集笔记:T-drive 北京出租车轨迹数据

数据地址&#xff1a;T-Drive trajectory data sample - Microsoft Research 1 数据描述 此数据集包含了2008年2月2日至2月8日在北京期间10,357辆出租车的GPS轨迹。此数据集中的总点数约为1500万&#xff0c;轨迹的总距离达到了900万公里。图1显示了两个连续点之间的时间间隔和…

java后端笔记

写在前面 节选自&#xff1a; 黑马程序员&#xff1a;新版Java面试专题视频教程&#xff1a;https://www.bilibili.com/video/BV1yT411H7YK?p1 javaguide&#xff1a;https://javaguide.cn/home.html 集合 ConcurrentHashMap JDK1.7&#xff1a;分段数组链表&#xff0c;用…

TCP 和 UDP哪个更好

传输控制协议 &#xff08;TCP&#xff09; 和用户数据报协议 &#xff08;UDP&#xff09; 是互联网的基础支柱&#xff0c;支持从网络源到目的地的不同类型的数据传输。TCP更可靠&#xff0c;而UDP优先考虑速度和效率。本文解释了两种协议的工作原理&#xff0c;并详细讨论了…

分享53个Python源码源代码总有一个是你想要的

分享53个Python源码源代码总有一个是你想要的 链接&#xff1a;https://pan.baidu.com/s/1ew3w2_DXlSBrK7Mybx3Ttg?pwd8888 提取码&#xff1a;8888 项目名称 100-Python ControlXiaomiDevices DRF-ADMIN 后台管理系统 FishC-Python3小甲鱼 Flask框架的api项目脚手架 …

LLM-TAP随笔——语言模型训练数据【深度学习】【PyTorch】【LLM】

文章目录 3、语言模型训练数据3.1、词元切分3.2、词元分析算法 3、语言模型训练数据 数据质量对模型影响非常大。 典型数据处理&#xff1a;质量过滤、冗余去除、隐私消除、词元切分等。 训练数据的构建时间、噪音或有害信息情况、数据重复率等因素都对模型性能有较大影响。训…

JavaScript系列从入门到精通系列第九篇:JavaScript中赋值运算符和关系运算符以及Unicode编码介绍

一&#xff1a;赋值运算符 1&#xff1a; 右侧的值可以赋值给左侧的变量。 var a 123; console.log(a);//123 2&#xff1a; var a 10; a a 5; a 5; 上边这两个写法是一样的。 3&#xff1a;- var a 10; a a-5; a - 5; 上边这两个写法是一样的。 4&#xff1a;* …

Cesium 展示——label 从十进制小数转度分秒

文章目录 需求分析 需求 Cesium 显示 坐标点label 从十进制小数转度分秒 分析 写一个转换方法 function decimalToDMS(decimal) {const degree Math.floor(decimal);const minute Math.floor((decimal - degree) * 60);const second ((decimal - degree) * 60 - minute) *…

ChunJun: 自定义插件

序言 Chunjun的版本兼容可能会有问题,在我们了解了自定义插件后,在修改源码以应对不同的场景就会得心应手了,针对Chunjun1.12.Release版本说明cuiyaonan2000163.com 自定义插件整体流程 从数据流的角度来看ChunJun&#xff0c;可以理解为不同数据源的数据流通过对应的ChunJu…

一文了解数据治理全知识体系!

在业界&#xff0c;大家都为如何做好数据治理而感到困惑。数据治理工作一定要先摸清楚数据的家底&#xff0c;规划好路线图&#xff0c;再进行决策。 本文从数据治理的误区、元数据管理、数据质量管理、数据资产管理等4个方面整理出数据治理的一套经验总结&#xff0c;给予数据…

python算法部署(通信篇)

1.dockerflask方式 # YOLOv5 &#x1f680; by Ultralytics, AGPL-3.0 license """ Run a Flask REST API exposing one or more YOLOv5s models """import argparse import io import jsonimport torch from flask import Flask, jsonify, req…

公司新来的实习生问我SpringBoot多个环境的配置方式

这是一篇写给新手的文章&#xff0c;老手可以绕行了。 起因是一个同学让我帮他看个问题&#xff0c;他说有两个环境&#xff0c;一个环境有问题&#xff0c;另一个环境没问题&#xff0c;但是一直找不到原因&#xff0c;假设一个环境是 dev&#xff0c;另一个环境是 test。 于…

2023 版 QQ 机器人运行部署文档

文章目录 1.前置说明2.机器人框架的下载与运行2.1 下载机器人框架2.2 下载可操作框架的静态页面2.3 运行机器人框架 3.登录QQ机器人3.1 前提说明3.2 扫码登录3.3 注意事项 4.后端程序处理消息4.1 下载 stater4.2 stater 基本说明4.3 运行后端程序4.4 测试消息处理4.5 关于扩展消…