• STL String类详解(上)


    作者:@小萌新
    专栏:@初阶C++
    作者简介:大二学生 希望能和大家一起进步
    本篇博客简介:介绍下String类的一部分用法
    在这里插入图片描述
    想不出来啥鸡汤了 学吧~

    本章目标

    1. 熟悉String类
    2. 熟悉各种String函数用法
    3. 能够熟练运用String类解决题目

    一. String类的介绍

    1.1 String类的由来

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

    oop思想: 指的是面向对象编程

    C++中对于string的定义为:typedef basic_string string; 也就是说C++中的string类是一个泛型类,由模板而实例化的一个标准类,本质上不是一个标准数据类型。

    至于我们为什么不直接用String标准数据类型而用类是因为一个叫做编码的东西

    我们每个国家的语言不同 比如说英语使用26个英文字母基本就能表述所有的单词 但是对于中文的字符呢?是不是就要用其他编码方式啊(比如说utf-8)

    1.2 String函数接口

    常用函数如下

    我们会讲解大部分重要的函数
    在这里插入图片描述

    二. String类读写

    2.1 访问两种方式

    我们这里有两种访问方式

    下标访问

    使用operator[]实现数组下标式的访问

    但是在这之前 我们首先来看看这一段代码

    	string s1("hello world");
    	cout << s1.size() << endl;
    
    • 1
    • 2

    这里第一行代码的意思是初始化构造一个string类 初始化赋值为 hello world

    s1.size()是表示的s1字符串的大小(这里使用s1.length())
    在这里插入图片描述
    之后我们开始使用下标进行访问 代码表示如下

    	string s1("hello world");
    	//cout << s1.size() << endl; // s1.length()
    
    	for (size_t i = 0; i < s1.size(); i++)
    	{
    		cout << s1[i] << ' ';
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    这里其实等价于这一行代码

    cout << s.operator[](i) << " ";
    
    • 1

    函数重载嘛
    在这里插入图片描述

    at访问

    代码表示如下

    	for (size_t i = 0; i < s1.size(); i++)
    	{
    		cout << s1.at(i) << ' ';
    	}
    
    • 1
    • 2
    • 3
    • 4

    运行结果如下

    在这里插入图片描述

    两种访问方式的区别

    唯一的区别就是报错的时候
    下标访问报断言错误
    at访问报异常

    在这里插入图片描述
    在这里插入图片描述

    2.2 迭代器读写

    正向迭代器

    老规矩 我们先来看迭代器的语法

        string::iterator it = s.begin();
    
    • 1

    我们首先写个String类名 后面跟上iterator(迭代器) 再后面加上一个it

    等于号的右边写上对象的begin() 或者 end()

    我们目前将它当作指针来看待 目前这个阶段这样子理解就好

    使用方式如下

    	string s("hello world");
    	string::iterator it = s.begin();
    	while (it != s.end())
    	{
    		cout << *it;
    		it++;
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    当然我们也可以来修改迭代器里面的内容

    在这里插入图片描述

    反向迭代器

    我们先来看语法格式

    string::reverse_iterator it = s.rbegin();
    
    • 1

    我们这里可以看到 其实变化的就是一个 reverse 还有最后的rbegin()

    代码表示如下

    	string s("hello world");
    	string::reverse_iterator it = s.rbegin();
    	while (it != s.rend())
    	{
    		cout << *it;
    		it++;
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在这里插入图片描述
    我们发现 这里是不是代码有很多啊 那么我们练习到之前的知识 是不是就能想起来一个auto关键字

    那么我们试试行不行

    在这里插入图片描述
    所以这里是不是更能明确一点了 知识之间不是相互孤立的

    const正向迭代器

    相比于迭代器 其实这里的改变就是不能写了 只能读(权限缩小)

    代码表示如下

    int main()
    {
    	const string s("hello world");
    	string::const_iterator it = s.begin();
    	while (it != s.end())
    	{
    		cout << *it;
    		it++;
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在这里插入图片描述

    这里肯定就不能修改啦 不然肯定会报错的

    在这里插入图片描述

    const反向迭代器

    和正向迭代器一样 这里就不多解释了

    代码跟运行图如下

    int main()
    {
    	const string s("hello world");
    	string::const_reverse_iterator it = s.rbegin();
    	while (it != s.rend())
    	{
    		cout << *it;
    		it++;
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在这里插入图片描述

    2.3 语法糖 范围for读写

    这个我们也是在之前的auto语法里面讲过了 代码表示如下

    	string s("hello world");
    	for (auto x : s)
    	{
    		cout << x << ' ';
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述

    那么我们想要修改呢?

    是不是也讲过 直接使用他们的引用就可以了(不引用肯定是不可以的 因为这里只是一个简单的赋值)

    在这里插入图片描述

    三. String类的构造函数

    构造函数几种重要的格式如下

    在这里插入图片描述
    这里只讲解三个重点构造函数

    无参构造

    代码表示如下

    string s;
    
    • 1

    我们debug来看看是什么效果

    在这里插入图片描述
    这里就是一个空字符串了

    有参构造

    和无参构造差不多 代码表示如下

    string s("hello world");
    
    • 1

    还是一样debug看看

    在这里插入图片描述
    这里可以发现 字符串的大小(size)变成了11 然后字符串里面的内容变成了 hello world

    拷贝构造

    代码表示如下

    	string s("hello world");
    	string s1(s);
    
    • 1
    • 2

    还是一样 debug看看

    在这里插入图片描述
    s1也变成了hello world捏

    四. String容量接口函数

    在这里插入图片描述
    还是一样捏 咱们挑重点的介绍

    size

    首先还是一样 上代码

    cout << s.size();
    
    • 1

    我们输出之后可以发现大小是11

    这里是不是有点眼熟 我们debug看到的size是不是也是11啊 所以说这里就是将debug的值返回而已

    empty

    这个也很简单 判断是否为空的

    比如说我们创建两个字符串 一个为空 一个不为空试试看

    在这里插入图片描述
    这里表示的很清楚了

    clear

    这里的clear函数可以和empty联动一下

    我们发现清除之后两个字符串就变成全空了

    在这里插入图片描述

    reserve

    这个函数用于预先开空间 因为每当字符串长度大于容量的时候都会扩容

    所以如果我们知道我们需要的空间是多少我们就可以使用这个函数了

    我们可以发现 这里的空间变成了1007 (因为是按照1.5倍开空间的)
    在这里插入图片描述

    resize

    我们这里使用resize可以改变size的大小 假如说我们size的大小大于字符串的size 后面就会以‘\0’结尾

    在这里插入图片描述

    假如我们resize的大小小于原来的大小 后面的字符就会截断

    在这里插入图片描述

    五. String类对象修改接口

    +=

    在这里插入图片描述
    这里比较重要的其实就是一个+=

    这里演示下

    在这里插入图片描述
    我们可以发现 后面确实连接上了一个字符串

    replase

    这个接口函数的用法也很简单 有三个参数 分别是要替换的位置 删除的数据大小 替换的数据

    #include 
    #include 
    #include 
     
    int main()
    {
    	string s1 = "The sixth sick sheik's sixth sheep's sick";
    	string key = "sixth";
    
    	int findpos = s1.find(key);
    	while (findpos!=string::npos)
    	{
    		s1.replace(findpos,key.size(),"seventh");
    		findpos = s1.find(key);
    	}
    
    	cout << s1 << endl;
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    在这里插入图片描述

    insert

    这里其实也不太常用

    我们记住几个用法 有印象就可以

    string str = "hello world";
    string str2 = "hard ";
    string str3 = "it is so happy wow";
    
    //s.insert(pos,n,ch)        在字符串s的pos位置上面插入n个字符ch
    str.insert(6,4,'z');        // str = "hello zzzzworld"
    
    //s.insert(pos,str)         在字符串s的pos位置插入字符串str
    str.insert(6,str2);         // str = "hello hard world"
    
    //s.insert(pos,str,a,n)     在字符串s的pos位置插入字符串str中位置a到后面的n个字符
    str.insert(6,str3,6,9);     // str = "hello so happy world"
    
    //s.insert(pos,cstr,n)      在字符串s的pos位置插入字符数组cstr从开始到后面的n个字符
    str.insert(6,"it is so happy wow",6);       // str = "hello it is world"
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    在这里插入图片描述

    assgin

    这里我们可以将这个操作符理解成 清空赋值 现在这三种赋值方式我们是不是也是轻车熟路了

    int main()
    {
    	string s1 = "hello world";
    	string s2 = "welcome to my world";
    
    	s1.assign("hello");
    	cout << s1 << endl;
    
    	s1.assign(s2);
    	cout << s1 << endl;
    
    	s1.assign(s2, 5, 5); // s2第五个位置 往后五个字符
    	cout << s1 << endl;
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    在这里插入图片描述

    earse

    它同样也有三种使用方式 (删除)

    int main()
    {
    	string s1 = "hello world";
    	string s2 = "welcome to my world";
    
    	s1.erase();         //  这里是全部删除
    	cout << s1 << endl;
    
    
    	s1 = "hello world";
    	s1.erase(0, 3);     // 删除0~3
    	cout << s1 << endl;
    
    	s1 = "hello world";
    	s1.erase(3);       //  删除3~后面全部 
    	cout << s1 << endl;
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    在这里插入图片描述

    reverse

    我们这里可以将整个字符串反转

    在这里插入图片描述

    六. String对象字符串运算相关接口

    在这里插入图片描述

    c_str

    我们使用这个函数的时候返回的是一个字符串

    在这里插入图片描述
    我们可以发现 这里两个的类型明显不同

    一个是string对象

    一个是字符指针(也就是字符串)

    find

    这里find有四种用法

    第一种 也是最常用的

    	string str = "The apple thinks apple is delicious";     //长度34
    	string key = "apple";
    
    	//s.find(str)            查找字符串str在当前字符串s中第一次出现的位置
    	int pos1 = str.find(key);                  // 4
    
    • 1
    • 2
    • 3
    • 4
    • 5

    我们这里可以发现 apple是在第四个位置出现的 所以说这里pos1会是4

    假如说我们要查找的是以一个字符‘a’ 那么它返回的值也会是4

    在这里插入图片描述
    那么如果说 我们要查找的是一个不存在的字符呢?

    在这里插入图片描述
    我们可以看到这里的pos5变成了26 实际上也就是字符串最后的值

    那么假设我们要找从某位置到某位置的值呢?

    只要在后面加上个范围就好

    在这里插入图片描述
    第二个这个是什么意思呢?

    就是让我们从第五个位置开始 找key值 并且返回它的下标

    那么我们来看看最后一个 其实唯一的区别就是查找变成字符了

    在这里插入图片描述
    我们这里查找一个字符使用的是这个pos4 后面的数字表示从多少位置开始查找

    这里是一种不常用的用法

    int main()
    {
    	string s1 = "The apple thinks apple is delicious";
    
    	int pos1 = s1.find("thi0ng", 0,4 );
    	cout << pos1 << endl;
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    查找前面这个字符串 从0这个位置开始 查找这个字符串的4个字符

    substr

    这个的用法也很简单

    得到pos位置后面n个字符组成的字符串

    在这里插入图片描述

    getline

    得到一整行的字符串
    使用格式如下

    getline(cin , s);
    
    • 1

    七. 题目巩固

    题目一

    https://legacy.cplusplus.com/reference/string/string/find/
    
    • 1

    现在给我们这样子的一串字符串

    要求我们查找三部分的内容

    1 前面的https

    2 查找域名

    3 查找地址

    首先我们来看前面的https

    我们来看看 是不是只要找到冒号就能找到前面的协议啊

    在这里插入图片描述
    这样子是不是很简单就找到了

    然后我们开始查找域名 观察下这个地址 是不是pos+3的位置往后面找 找到第一个‘/’ 这中间就是域名啊

    在这里插入图片描述
    写出这样子的代码就能够找到域名了

    接着我们来找找后面的内容

    这个时候直接从pos2查找到最后就可以了

    在这里插入图片描述

    题目二

    替换空格

    这个题目其实我们以前用双指针的做法做过

    但是我们现在学了string类 是不是能很简单的解决它啦
    在这里插入图片描述
    代码表示如下

    class Solution {
    public:
        string replaceSpace(string s)
        {
            // 首先查找空格的位置
            int pos = s.find(' ');
    
            // 之后我们开始替换
            while(pos != string::npos)
            {
                s.replace(pos,1,"%20");
                pos = s.find(' ');
            }
    
            return s;
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    我们来看看效果

    在这里插入图片描述
    可以完美运行

    题目三

    题目要求如下

    在这里插入图片描述
    代码表示如下

    int main()
    {
        string s;
        getline(cin,s); // 输入一行的字符串
    
        int pos = s.rfind(' ');
        string s2 = s.substr(pos+1);
        cout<<s2.size()<<endl;
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    经过了这几题是不是发现使用string类刷题特别方便啊

    这就是我们为什么学习STL的原因

    总结

    在这里插入图片描述

    本篇博客介绍了String类的基本使用方法以及使用String类刷一些题目
    由于作者水平有限 错误在所难免 出现了错误希望大佬能够及时指正啊
    如果这篇文章帮助到你别忘了一键三连啊
    阿尼亚 哇酷哇酷!

  • 相关阅读:
    C++ 与 QML 之间进行数据交互的几种方法
    基于Java毕业设计养老机构管理信息系统源码+系统+mysql+lw文档+部署软件
    2022年C等级考试九月二级真题B:全在其中
    易语言破解之绕VM思路
    【笔记】文献阅读[YOLOV3]-An Incremental Improvement
    【sim-storage-client】SpringBoot集成Minio与本地存储
    java进阶-Netty
    JS中内存泄漏的几种情况
    MWM触摸屏工控机维修TEM-EV0 EN00-Z312yy-xx
    【LeetCode】2319. 判断矩阵是否是一个X矩阵
  • 原文地址:https://blog.csdn.net/meihaoshy/article/details/127777146