string的认识和使用

news2025/1/10 23:03:06

目录

 一、网站上查看string类

1.网站

2.网站上的string类

二、string类的成员函数

1.默认成员函数

(1)构造函数、拷贝构造函数和析构函数

(2)赋值运算符重载

(3)容量操作

(4)迭代器(iterator)

(5)元素访问

(6)修改操作

(7)其他成员函数

三、string类的非成员函数


 一、网站上查看string类

1.网站

还记得在C语言中我推荐的两个查看库函数的工具吗?其中一个是一个网站叫cplusplus;另一个是一个应用程序叫MSDN。自此我们在学习C++的过程中要经常用到cplusplus这个网站。

网址是:https://cplusplus.com

打开后是这样的,最近这个网站改版了,新版的网站不好用,我们可以点击右上角的[legacy version]切换到旧版本。

切换到旧版本

2.网站上的string类

我们可以在上面搜索string,得到这样的一个类

下面还有各种成员函数,也都给出了各自的使用方法。

二、string类的成员函数

1.默认成员函数

在成员函数的第一部分就是string的三个默认成员函数,从上到下为构造函数、拷贝构造函数、析构函数和赋值运算符重载

(1)构造函数、拷贝构造函数和析构函数

string的构造与拷贝构造函数有很多,常用的有以下四个:

string();——————不传参的默认构造,构造空string对象,即空字符串

string(const string& str);——————用一个string变量初始化另一个string变量

string(const char* s);——————用一个C语言字符串初始化一个string变量

string(size_t n, char c);——————用一个字符初始化一个string变量让其包含n个字符c

这是官方库中实现的构造函数,在网站上我们可以看到它们的参数和使用,每个接口的使用都有详细的解释。

测试代码:

#include<iostream>
#include<string>
using namespace std;
void test()
{
    string s1;
    cout << s1 << endl;

    string s2("hello world");
    cout << s2 << endl;

    string s3(s2);
    cout << s3 << endl;

    string s4(10, 'x');
    cout << s4 << endl;
}

int main()
{
    test();
    return 0;
}

测试结果:

string类的底层组织形式与顺序表一样,由于析构函数不可重载的特性也只能有一个:~string(),负责释放字符串内容占用的空间。

(2)赋值运算符重载

string& operator= (const string& str);——————将str的内容赋值给左侧变量

string& operator= (const char* s);——————将字符串的内容赋值给左侧变量

string& operator= (char c);——————将字符赋值给左侧变量

测试代码:

#include<iostream>
#include<string>
using namespace std;
void test2()
{
    string s1("hello world");

    string s2;
    s2 = s1;
    cout << s2 << endl;

    string s3;
    s3 = "hello";
    cout << s3 << endl;

    string s4;
    s4 = 'x';
    cout << s4 << endl;
}

int main()
{
    test2();
    return 0;
}

测试结果:

(3)容量操作

容量操作包含以下内容,其中C++11标准中新出现的函数后面有标注

size_t size() const;——————返回string有效数据的长度

size_t length() const;——————返回string有效数据的长度

length和size在使用上没有区别,因为我们以后会知道STL的其他类和string是类似的,有些数据结构使用比如顺序表、链表为基础的类使用length表示元素个数更好理解,而对于书和图等数据结构使用size表示元素个数更好理解,所以这两个函数都被保留了下来。

size_t max_size() const;——————返回string可储存的字符串长度上限

就是无符号整形最大值,此接口在使用中没有意义

size_t capacity() const;——————返回开辟空间的大小

void reserve (size_t n = 0);——————如果n值大于当前的空间大小,便扩大空间到n个字符,小于则不做改变。但输入的改变后的空间大小不能小于字符串的长度

void clear();——————清除string的内容为空字符串,但不释放空间

bool empty() const;——————检测当前string是否是空字符串

void resize (size_t n, char c);——————改变空间大小,若新空间大于旧空间插入对应字符,小于则直接截断

void shrink_to_fit();——————将string的容量缩小到有效数据的大小

测试代码:

#include<iostream>
#include<string>
using namespace std;
void test2()
{
    string s1("hello world!");
    cout << "字符串长度:" << s1.size() << endl;
    cout << "空间可容纳元素的个数:" << s1.capacity() << endl;
    cout << "字符串空间最大值:" << s1.max_size() << endl;
    cout << "0为假,1为真:" <<s1.empty() << endl;

    s1.reserve(13);
    cout << "字符串长度:" << s1.size() << endl;
    cout << "空间可容纳元素的个数:" << s1.capacity() << endl;

    s1.reserve(18);
    cout << "字符串长度:" << s1.size() << endl;
    cout << "空间可容纳元素的个数:" << s1.capacity() << endl;

    s1.resize(20, 'x');
    cout << s1 << endl;

    s1.clear();
    cout << s1;
}

int main()
{
    test2();
    return 0;
}

测试结果:

(4)迭代器(iterator)

迭代器是一个类似于指针的东西,它的使用与指针非常类似。

我们看一段代码:

#include<iostream>
#include<string>
using namespace std;
void test2()
{
    string s1("hello world!");//s1初始化为hello world
    string::iterator it = s1.begin();
    //it是string类的迭代器变量s1.begin()表示s1字符串内容的首个字符位置
    while (it != s1.end())//s1.end()表示s1内字符串的末尾位置的后一位    
    {
        printf("%c", *it);
        it++;
    }
    cout << endl;
}

int main()
{
    test2();
    return 0;
}

 这个程序可以遍历string字符串的每一个字符,也就相当于遍历数组的每个元素,迭代器可以像指针一样进行加减,也可以通过解引用得到相应内容。但为什么说迭代器是一个类似于指针的东西呢?因为在string类中的迭代器使用与指针相同,但是在STL的链表中也存在list的迭代器,链表在遍历的时候也可以用加一的形式找下一个元素位置,指针加一的遍历方式就不对了,所以说很像但不是。

我们主要学习两个迭代器:正向和反向迭代器

string的正向迭代器

iterator begin();——————string字符串的头,可读可写

const_iterator begin() const;——————string字符串的头,只读

iterator end();——————string字符串的尾,可读可写

const_iterator end() const;——————string字符串的尾,只读

string的反向迭代器

reverse_iterator rbegin();——————string字符串逆向的头,可读可写

const_reverse_iterator rbegin() const;——————string字符串逆向的头,只读

reverse_iterator rend();——————string字符串逆向后的尾,可读可写

const_reverse_iterator rend() const;——————string字符串逆向的尾,只读

所有迭代器的头都是正向或反向的首元素,尾都是尾元素的位置。

  • 创建迭代器对象it1时,必须指明是哪个类的正向或反向迭代器。
  • 使用类成员函数的begin获得数据当前顺序的起始位置。
  • 使用类成员函数的end获得数据当前顺序的结束位置。
  • 将迭代器解引用可访问字符串中的特定元素。

测试代码:

#include<iostream>
#include<string>
using namespace std;
void test2()
{
    string s1("hello world!");
    string::iterator it1 = s1.begin();
    while (it1 != s1.end())
    {
        printf("%c", *it1);
        it1++;
    }
    cout << endl;
    string::reverse_iterator it2 = s1.rbegin();
    while (it2 != s1.rend())
    {
        printf("%c", *it2);
        it2++;
    }
    cout << endl;
    string::iterator it3 = s1.begin();
    while (it3 != s1.end())
    {
        *it3 = 'x';
        it3++;
    }
    cout << s1 << endl;
}

int main()
{
    test2();
    return 0;
}

 测试结果:

下面的cbegin、cend、crbegin、crend其实就是将只读的迭代器独立又实现了一遍,我们的使用中很少会用到它们。

(5)元素访问

operator[]——————直接重载[]使s[i]就可以直接访问对应下标元素,而且也加上了越界的检查,提高了程序的安全性。

char& operator[] (size_t pos);——————可读可写

const char& operator[] (size_t pos) const;——————只读

at函数——————与[]作用相同

char& at (size_t pos);——————可读可写

const char& at (size_t pos) const;——————只读

测试代码:

#include<iostream>
#include<string>
using namespace std;
void test2()
{
    string s1("hello world!");
    cout << s1[1] << endl;
    cout << s1.at(1) << endl;
    s1[1] = 'a';
    cout << s1 << endl;
    s1.at(1) = 'b';
    cout << s1 << endl;
}

int main()
{
    test2();
    return 0;
}

测试结果:

(6)修改操作

operator+=—————不同数据的尾插,这个用的最多

string& operator+= (const string& str);——————尾插string变量

string& operator+= (const char* s);——————尾插字符串

string& operator+= (char c);——————尾插字符

测试代码:

#include<iostream>
#include<string>
using namespace std;
void test2()
{
    string s1("hello");
    cout << s1 << endl;
    s1 += '_';
    cout << s1 << endl;
    string s2("wor");
    s1 += s2;
    cout << s1 << endl;
    s1 += "ld!";
    cout << s1 << endl;
}

int main()
{
    test2();
    return 0;
}

测试结果:

string& append(const char* s)——————尾插多个多个字符,内部重载函数很多

assign——————将原本的内容删除然后放入相应数据

string& assign (size_t n, char c);——————将对象赋值为n个c字符

string& assign (size_t n, char c);——————将对象赋值为n个c字符

string& assign (size_t n, char c);——————将对象赋值为n个c字符

测试代码:

#include<iostream>
#include<string>
using namespace std;
void test2()
{
    string s1("xxxxxxxxxxxxx");
    string s2("hello world!");
    s1.assign(s2);
    cout << s1 << endl;

    s1.assign("abcdef");
    cout << s1 << endl;

    s1.assign(5, 'x');
    cout << s1 << endl;
}

int main()
{
    test2();
    return 0;
}

测试结果:

void push_back(char c);——————尾插一个字符

测试代码:

#include<iostream>
#include<string>
using namespace std;
void test2()
{
    string s1("hello world");
    cout << s1 << endl;
    s1.push_back('!');
    cout << s1 << endl;
}

int main()
{
    test2();
    return 0;
}

测试结果:

insert——————在特定位置插入内容

string& insert (size_t pos, const string& str);——————在pos下标位置插入str变量的内容

string& insert (size_t pos, const char* s);——————在pos下标位置插入字符串

string& insert (size_t pos, size_t n, char c);——————在pos下标位置插入n个c字符

测试代码:

#include<iostream>
#include<string>
using namespace std;
void test2()
{
    string s1("to ");
    cout << s1 << endl;

    string s2("Welcome ");
    s1.insert(0, s2);
    cout << s1 << endl;

    s1.insert(11, "Tianjin,");
    cout << s1 << endl;

    s1.insert(19, 5, 'x');
    cout << s1 << endl;
}

int main()
{
    test2();
    return 0;
}

测试结果:

使用insert也能够实现头插,将指定位置的写为0即可,但是顺序表的头插需要移动数据,是一个O(N^2)的程序,效率低,所以能不用则不用。

erase——————清除内容

string& erase(size_t pos = 0; size_t len = npos);——————清除对应下标开始向后数n个字符,这两个参数都是缺省的,我们如果不输入pos,会默认从头开始删;如果我们不输入len,len就会被赋值为npos,也就是无符号整形的最大值。

npos是一个静态成员变量,是无符号整形的最大值

测试代码:

#include<iostream>
#include<string>
using namespace std;
void test2()
{
    string s1("Welcome to Shanghai!");
    cout << s1 << endl;

    s1.erase(11, 9);
    cout << s1 << endl;

    s1.erase();
    cout << s1 << endl;
}

int main()
{
    test2();
    return 0;
}

测试结果:

replace——————替换内容

string& replace (size_t pos, size_t len, const string& str);——————将长度为n的原字符串内容替换为str变量的内容

string& replace (size_t pos, size_t len, const char* s);——————将长度为n的原字符串内容替换为另一个字符串的内容

测试代码:

#include<iostream>
#include<string>
using namespace std;
void test2()
{
    string s1("Welcome to Shanghai!");
    cout << s1 << endl;

    string s2("Tientsin");
    s1.replace(11, 8, s2);
    cout << s1 << endl;

    s1.replace(11, 8, "Tianjin");
    cout << s1 << endl;
}

int main()
{
    test2();
    return 0;
}

测试结果:

(7)其他成员函数

const char* c_str() const;——————将string变量转换为C字符串返回

find——————在string变量中从头部开始找子串,pos是开始找字串的位置,返回第一次出现子串的头位置

size_t find (const string& str, size_t pos = 0) const;——————以string变量找子串

size_t find (const char* s, size_t pos = 0) const;——————以字符串找子串

rfind——————在string变量中从尾部开始找子串,pos是开始找字串的位置,返回第一次出现子串的头位置

size_t rfind (const string& str, size_t pos = npos) const;——————以string变量找子串

size_t rfind (const char* s, size_t pos = npos) const——————以字符串找子串

string substr (size_t pos = 0, size_t len = npos) const;——————取字符串pos下标开始的len个字符形成string对象,返回该对象。

测试代码:

#include<iostream>
#include<string>
using namespace std;
void test2()
{
    string s1("hello world1");
    char arr[20] = "hello world2";
    string s2("o");
    printf("%s\n", s1.c_str());
    printf("%d %d\n", s1.find("o"), s1.find(s2));
    printf("%d %d\n", s1.rfind("o"), s1.rfind(s2));
    cout << s1.substr(6, 5) << endl;
}

int main()
{
    test2();
    return 0;
}

测试结果:

三、string类的非成员函数

除了流插入和流提取的重载,我还想讲以下getline和流插入重载的区别

流插入和流提取一个是输入一个是输出,流插入类似于C语言中的scanf,scanf读取到空字符就会直接结束;C语言中也提供了一个gets函数,这样就可以继续读取空字符了,同样string中的getline也是一个道理

测试代码:

#include<iostream>
#include<string>
using namespace std;
void test2()
{
    string s1;
    cin >> s1;//我输入hello world
    cout << s1 << endl;//s1只读取到空格之前的部分,输出:hello

    string s2;
    getline(cin, s2);//getline可以读取空字符,将剩余的空格+world读取
    cout << s2 << endl;//输出: world
}

int main()
{
    test2();
    return 0;
}

测试结果:

string类历史悠久,在CTL出现之前string就已经存在了,所以它会有很多在我们看来重复冗余的内容,所以我们也可以在代码的使用过程中感受到C++的发展。

cplusplus网站上的string类:string - C++ Reference (cplusplus.com)

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

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

相关文章

JavaWeb用户信息查看的登录、增删改查案例

黑马JavaWeb案例整理记录 文章目录案例源码&#xff1a;一、需求二、设计1、技术选型2、数据库设计三、开发步骤四、详细过程1、创建web项目&#xff0c;部署tomcat&#xff0c;导入jar包2、编写首页index.jsp3、编写servlet、servie、daomain、dao五、案例升级实现1、实现内容…

成长任务|花式show爱心代码

❤️立即投稿❤️ &#x1f4cc;活动规则 最近#李峋同款爱心代码#词条上了热搜&#xff0c;作为程序员的你&#xff0c;可不能错过这个给意中人大展身手的时机 ❤️ 使用代码画一颗#爱心#&#xff0c;将你的代码文件通过本页面投稿&#xff0c;审核通过即可参与活动 ❤️ 可使…

速锐得猎奇与猜想:数字化工业互联网能否真的走进未来

前年的8月份&#xff0c;我们独立设计一款燃气报警器&#xff0c;包括设计产品图纸&#xff0c;嵌入式软件、LED显示、核心代码、CAN网络及485架构、云端SAAS框图&#xff0c;应用场景等&#xff0c;在去年的5月份直接进入到了量产&#xff0c;第一批数量是2000套&#xff0c;升…

详细介绍NLP文本摘要

文章目录文本生成文本摘要抽取式文本摘要抽取式文本摘要方法案例分析优点缺点生成式文本摘要指针生成网络文本摘要预训练模型与生成式摘要优点缺点TextRank文本摘要BertSum模型文本摘要文本生成 文本生成&#xff08;Text Generation&#xff09;&#xff1a;接收各种形式的文…

IT行业几大方向(外行人之误解)

有很多同学一说自己是搞计算机的&#xff0c;搞软件的&#xff0c;做IT的&#xff0c;是个程序员。外行人&#xff0c;就往往很惊奇&#xff0c;说我电脑卡怎么处理&#xff0c;怎么盗别人QQ密码&#xff0c;把谁谁网站黑了&#xff0c;甚至我的网络很慢可以帮我提速一下吗等等…

如何设计es的索引库结构

1、确定索引库的名称 建议和使用的数据库的表名相对应 比如&#xff1a;数据库的表名为 那么索引库的名称可以为&#xff1a;item 2、确定索引库需要的字段 1.根据前端界面来判断需要什么字段 例如&#xff1a; 上边这个界面需要的就是&#xff1a; 分类&#xff0c;品牌&…

使用ZPL控制Zebra打印机

ZPL简介: Zebra编程语言 (ZPL)是所有 ZPL 兼容打印机使用的命令语言。可用于绘制文本、形状、条形码和图像等元素&#xff0c;组合这些元素。打印机使用它作为指令来创建打印在标签上的图像。 想要打印一个标签&#xff0c;您可能需要告诉打印机&#xff1a; 产品名称是什么…

Python学习基础笔记三十四——爬虫小例子

一个爬虫小例子&#xff1a; import requestsimport re import jsondef getPage(url):responserequests.get(url)return response.textdef parsePage(s):comre.compile(<div class"item">.*?<div class"pic">.*?<em .*?>(?P<id&…

Nginx的access.log日志分析工具-goaccess

一、安装goaccess wget http://tar.goaccess.io/goaccess-1.3.tar.gz --no-check-certificate #下载tar包 tar -xzvf goaccess-1.3.tar.gz #解压tar包 cd goaccess-1.3/ #进入目录 ./configure --enable-utf8 --enable-geoiplegacy --prefix/opt/goaccess #检测环境&…

宝塔严重未知安全性漏洞(宝塔面板或Nginx异常)

问题简述 论坛上的帖子 https://www.bt.cn/bbs/thread-105054-1-1.html https://www.bt.cn/bbs/thread-105085-1-1.html https://hostloc.com/thread-1111691-1-1.html 数据库莫名被删 https://www.bt.cn/bbs/thread-105067-1-1.html 以下内容来自群友消息&#xff1a; 速报:宝…

大学生餐饮主题网页制作 美食网页设计模板 学生静态网页作业成品 dreamweaver美食甜品蛋糕HTML网站制作

&#x1f468;‍&#x1f393;静态网站的编写主要是用HTML DIVCSS JS等来完成页面的排版设计&#x1f469;‍&#x1f393;,常用的网页设计软件有Dreamweaver、EditPlus、HBuilderX、VScode 、Webstorm、Animate等等&#xff0c;用的最多的还是DW&#xff0c;当然不同软件写出的…

以太网 网线分类

1. 双绞线分类 一类线&#xff1a;主要用于传输语音&#xff08;一类标准主要用于八十年代初之前的电话线缆&#xff09;&#xff0c;不同于数据传输。 二类线&#xff1a;传输频率为1MHZ&#xff0c;用于语音传输和最高传输速率4Mbps的数据传输&#xff0c;常见于使用4MBPS规范…

【Android gradle】自定义一个android gradle插件,并发布到私有Artifactory仓库

1. 前言 最近工作部分内容涉及到gradle 插件的编写&#xff0c;在粗浅了解和编码之余来简单梳理下编写一个gradle 插件的相关用法。这里编写的插件还是发布到在前面两篇博客中的Artifactory仓库中。一共分为如下几步&#xff1a; 配置定义gradle插件、上传到 Artifactory仓库…

基于单片机的加热炉炉温控制系统设计

目 录 摘 要 I Abstract II 第1章 绪论 1 1.1课题背景及意义 1 1.2发展现状 2 1.3研究主要内容 3 第2章 加热炉炉温控制系统总体方案设计 4 2.1总体方案的确定 4 2.2加热炉炉温控制系统组成 5 第3章 加热炉炉温控制系统技术和算法介绍 6 3.1 AT89C51简介 6 3.1.1单片机的引脚介…

Crossover2023mac苹果电脑系统上运行Windows程序虚拟机工具模拟器

CrossOver是一款可以让Mac和Linux系统中正常运行Windows软件的应用程序。它不像虚拟机一样需要安装Windows系统之后才可以安装Windows的应用程序&#xff0c;这一方式给大多数用户带来了方便。通过CrossOver实现跨平台的文件复制粘贴&#xff0c;使Mac/Linux系统与Windows应用良…

海康视频回放,rtsp视频接口转换成.m3u8格式文件

通过海康接口返回的rtsp视频接口&#xff0c;转换成.m3u8格式文件&#xff0c;逻辑如下 1、采用ffmpeg实时转化rtsp链接视频&#xff0c;转化为m3u8&#xff0c;存放服务器固定地址 2、采用nginx代理视频成.m3u8视频 3、采用tokenredis方式处理视频播放和删除过程&#xff0…

太好玩了,我用 Python 做了一个 ChatGPT 机器人

大家好&#xff0c;我是早起。 毫无疑问&#xff0c;ChatGPT 已经是当下编程圈最火的话题之一&#xff0c;它不仅能够回答各类问题&#xff0c;甚至还能执行代码&#xff01; 或者是变成一只猫 因为它实在是太好玩&#xff0c;我使用Python将ChatGPT改造&#xff0c;可以实现在…

亚马逊黑五哑火,中国跨境电商高歌猛进!

黑五作为一个类似于中国双11的全球性购物狂欢节&#xff0c;在11月的最后一周拉开帷幕&#xff0c;据有关业内人士称&#xff0c;作为拥有众多全球站的亚马逊电子商务平台在此次黑色星期五的促销狂欢节中表现似乎稍显停滞&#xff0c;其作为电商领域的龙头企业&#xff0c;没能…

数据结构基础--图

一、图的基本概念 1.图的定义 图是由顶点集合V和边集合E组成的&#xff0c;记为G(G,V)。图可以只有点没有边&#xff0c;但不能只有边没有点。边&#xff1a;用&#xff08;x&#xff0c;y&#xff09;表示为xy之间的一条无向边&#xff1b;用<x,y>表示xy之间的一条有向…

大数据开发适合哪类人群?

有不少应届大学毕业生和0基础人群选择学大数据&#xff0c;但是要选择零基础的大数据培训班&#xff0c;从Java基础开始学习&#xff0c;由浅入深掌握离线数据分析、实时数据分析和内存数据计算等重要内容。 应届大学生缺乏工作经验和技能&#xff0c;对未来没有明确的规划&am…