C++库函数——string类

news2024/10/5 18:33:57

1. 简介

①什么是string类

源文档

译:

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

②string类的作用

string类是一个用于处理字符串的类,它可以存储任意数目的字符。它可以用来表示文本或其他字符串数据,例如:文本文件内容、网络传输的数据、数据库中的文本列、用户输入或输出等等。

string类的作用有以下几个方面:

  1. 存储和处理文本数据:string类可以存储和操作任意数目的字符,可以处理文本数据,如搜索、替换、截取子串等操作。

  2. 方便字符串操作:使用string类可以方便地进行字符串操作,如连接(concatenate)两个字符串、删除(erase)字符串中的一些字符、复制(copy)字符串等。

  3. 兼容性:string类是C++标准库的一部分,可用于在不同的计算机和操作系统之间进行可靠的代码交换。

2. string类的常见接口

①string类对象的常见构造

源文档

在这里我们只对部分作讲解 ,以如下代码为例

int main()
{
	string s1;// 创建一个没有初始值的字符串s1
	string s2("张三");// 创建一个以"张三"为初始值的字符串s2
	string s3("hello world");// 同上
	string s4(10, '*');// 创建一个s4字符串并以10个'*'初始化它
	string s5(s2);// 拷贝构造一个s5字符串

    string s6(s3, 6, 5);// 将s3中第6个位置的及之后的5个字符串拷贝构造到s6中

    string s7(s3, 6);// 将s3中第6个位置及之后的所有字符串(这里的nops为一个极大的无符号整形数,其为size_t nops = -1)拷贝构造到s7中

    string s8(s3, 6, 100);// 类似于s6,是将s3中第6个位置的及之后的100个字符串拷贝构造到s8中

    return 0;
}

分别打印它们有

②string类对象的容量操作

源文档

同样的这里只对部分函数作讲解

⑴size、length、 capacity

源文档如下

测试代码如下

int main()
{
	string s("hello, world");

	cout << s.size() << endl;// 显示字符串的有效长度
	cout << s.length() << endl;// 同上
	cout << s.capacity() << endl;// 显示字符串的容量
	cout << s << endl;
}

运行如下

⑵reserve、resize

原文档如下

测试代码如下

int main()
{
    string str = "hello world";
    cout << "Str: " << str << endl;
    cout << "Size: " << str.size() << endl;
    cout << "Capacity: " << str.capacity() << endl;
    cout << endl;

    str.resize(5);// 将str的长度改为5,超过5的部分全部被截断
    cout << "Resized: " << str << endl;
    cout << "Size: " << str.size() << endl;
    cout << "Capacity: " << str.capacity() << endl;
    cout << endl;

    str.resize(15,'*');// 将str的长度改为15,没有字符的部分全部用'*'填充
    cout << "Resized: " << str << endl;
    cout << "Size: " << str.size() << endl;
    cout << "Capacity: " << str.capacity() << endl;
    cout << endl;

    str.reserve(20);// 将capacity预置为20,不对size更改
    cout << "Reserved: " << str << endl;
    cout << "Size: " << str.size() << endl;
    cout << "Capacity: " << str.capacity() << endl;
    cout << endl;

    str.reserve(10);// 将capacity预置为小于size时,编译器可能不会对其作出更改
    cout << "Reserved: " << str << endl;
    cout << "Size: " << str.size() << endl;
    cout << "Capacity: " << str.capacity() << endl;
    cout << endl;

    return 0;
}

运行有

⑶clear、shrink_to_fit

测试代码

int main()
{
    string str = "hello world";
    cout << "Str: " << str << endl;
    cout << "Size: " << str.size() << endl;
    cout << "Capacity: " << str.capacity() << endl;
    cout << endl;

    // 清空字符串(将size置为0),但不改变容量大小
    str.clear();
    cout << "Cleared: " << str << endl;
    cout << "Size: " << str.size() << endl;
    cout << "Capacity: " << str.capacity() << endl;
    cout << endl;

    // 提出将capacity缩小到适应大小的请求,最后是否缩小由编译器确定(与resever类似)
    str.shrink_to_fit();
    cout << "Capacity after shrink: " << str.capacity() << endl;

    return 0;
}

 运行有

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

⑴使用[]

源文档

 我们使用以下代码进行举例

int main()
{
	string s1("hello world");
	const string s2("Hello World");
	cout << s1 << " " << s2 << endl;
	cout << s1[0] << " " << s2[0] << endl;

	s1[0] = 'H';
	cout << s1 << endl;

	// s2[0] = 'h';   代码编译失败,因为const类型对象不能修改

	//使用时,可以同时改变字符串的内容
	for (size_t i = 0; i < s1.size(); ++i)
	{
		cout << s1[i] << endl;
	}

	return 0;
}

 运行有

⑵使用迭代器iterator

迭代器是什么?

  C++迭代器(Iterator)是一种对象,它允许遍历容器中的元素。迭代器提供了对容器元素的访问和操作,使程序员能够对容器进行遍历、查找、修改等操作。

  而迭代器本质上是一个泛型指针,它实现了对指向容器元素的指针的抽象,使得我们可以在不了解容器内部细节的情况下对其进行访问和操作。当我们需要遍历、查找或修改容器中的元素时,迭代器为我们提供了一种统一的接口,使得我们可以将不同类型的容器当作同一类型来处理。

迭代器源文档

我们以如下代码举例

int main()
{
	string s("hello world");
	string::iterator it = s.begin();
	while (it != s.end())
	{
		//也可以通过解引用来改变字符串内容
		(*it)++;
		cout << *it << " ";
		++it;
	}

	cout << endl;

	// 倒着遍历字符串
	string::reverse_iterator rit = s.rbegin();
	// C++11之后,直接使用auto定义迭代器,让编译器推到迭代器的类型
	// 即可以使用auto rit = s.rbegin();
	while (rit != s.rend())
	{
		(*rit)--;
		cout << *rit << " ";
	}

	return 0;
}

 运行有

对于一些只读的字符串,需要使用const修饰,对应的begin()等也要对于更换为const形式,部分源文档如下

void func(const string& s)
{
    // 对于const常量字符串
    // 只能使用const修饰的迭代器,以防造成权限的放大
	string::const_iterator it = s.begin(); 
	while (it != s.end())
	{
		// it += 2;
		cout <<*it <<" ";
		++it;
	}
	cout <<endl;

	// string::const_reverse_iterator rit = s.rbegin( );
    // 可以使用auto来自动识别
	auto rit = s.rbegin();
	while (rit != s.rend( ))
	{
		// (*rit) += 3;
		cout <<*rit <<" ";
		++rit;
	}
}

⑶使用范围for

以如下代码为例

int main()
{
	string s = "hello world";
	for (auto& ch : s)
	{
		ch += 1;
		cout << ch << " ";
	}

	return 0;
}

运行有

④string类对象的修改操作

源文档

⑴+=、append、push_back与insert

测试代码

int main()
{
    string str = "hello ";
    cout << "str:" << str << endl;
    cout << "strSize: " << str.size() << endl;
    cout << "strCapacity: " << str.capacity() << endl;

    str += "world";// 向str追加"world"
    str += '!';
    cout << "str:" << str << endl;
    cout << "strSize: " << str.size() << endl;
    cout << "strCapacity: " << str.capacity() << endl;
    cout << endl;

    string str1 = "hello ";
    cout << "str1:" << str1 << endl;
    cout << "str1Size: " << str1.size() << endl;
    cout << "str1Capacity: " << str1.capacity() << endl;

    str1.append("world", 3);// 向str1后追加"world"的前3个字符
    cout << "str1:" << str1 << endl;

    str1.append(2, '!');// 向str1后追加两个'!'
    cout << "str1:" << str1 << endl;
    cout << "str1Size: " << str1.size() << endl;
    cout << "str1Capacity: " << str1.capacity() << endl;
    cout << endl;

    string str2 = "hello ";
    cout << "str2:" << str2 << endl;
    cout << "str2Size: " << str2.size() << endl;
    cout << "str2Capacity: " << str2.capacity() << endl;

    // 遍历字符串"world",并将每个字符尾插到str2中
    for (char c : "world")
    {
        str2.push_back(c);
    }
    cout << "str2:" << str2 << endl;
    cout << "str2Size: " << str2.size() << endl;
    cout << "str2Capacity: " << str2.capacity() << endl;
    cout << endl;

    string str3 = "hello ";
    cout << "str3:" << str3 << endl;
    cout << "str3Size: " << str3.size() << endl;
    cout << "str3Capacity: " << str3.capacity() << endl;

    // 在str3的第6个位置插入字符串"world"
    str3.insert(6, "world");
    cout << "str3:" << str3 << endl;

    // 在str3的最后的位置插入"!"
    str3.insert(str3.size(), "!");
    cout << "str3:" << str3 << endl;
    cout << "str3Size: " << str3.size() << endl;
    cout << "str3Capacity: " << str3.capacity() << endl;


    return 0;
}

运行有

在插入数据时,会设计到扩容的问题, 实际上在不同的环境下扩容的方式各不相同

int main()
{
	string s1("hello world"); 
	cout << s1.size() << endl;
	cout << "初始容量:" << s1.capacity() << endl;

	size_t old = s1.capacity();
	for (size_t i = 0; i < 100; i++) 
	{
		s1 += 'x';
		if (old != s1.capacity()) 
		{
			cout << "扩容:" << s1.capacity() << endl; old = s1.capacity();
		}
	}

	return 0;
}

对于这样一段代码,在g++和vs两种环境下有着不同的结果,即

g++:

vs:

通过观察我们发现在g++中string使用的是2倍扩容,在vs中使用的是1.5倍扩容 。

⑵assign、erase、replace与pop_back

源文档

测试代码

int main()
{
    string str = "hello world";
    string str1, str2, str3, str4;

    // 将str对象的从下标为0到下标为5的字符拷贝构造到str1上
    str1.assign(str, 0, 5);
    cout << "str1:" << str1 << endl;

    str2 = str;
    // 将str2对象的从下标为6的位置往后的5个字符删除
    str2.erase(6, 5);
    cout << "str2:" << str2 << endl;

    str3 = str;
    // 将str3对象的从下标为2的位置往后的5个字符替换为"*****"
    str3.replace(2, 5, "*****");
    cout << "str3:" << str3 << endl;

    str4 = str;
    // 尾删str4
    str4.pop_back();
    cout << "str4:" << str4 << endl;

    return 0;
}

运行有

⑶c_str、substr

源文档

测试代码

int main()
{
    string str = "hello world";

    // 将string类对象转化成const char* 的C语言字符类型
    const char* cstr = str.c_str();
    cout << "cstr:" << cstr << endl;

    // 将str从下标为6向后5个字符拷贝构造到sub中
    string sub = str.substr(6, 5);
    cout << "sub:" << sub << endl;

    return 0;
}

运行有

⑷find、rfind、find_first_of、find_last_of、find_first_not_of、find_last_not_of

源文档

测试代码

int main()
{
    string str = "hello world";

    // 从头开始查找字符 l
    size_t pos1 = str.find('l');
    cout << "pos1:" << pos1 << endl;

    // 从尾开始查找字符 l
    size_t pos2 = str.rfind('l');
    cout << "pos2:" << pos2 << endl;

    // 从前往后查找"world"中任意一个字符(即'w'、'o'、'r'、'l'、'd')第一次出现的位置
    size_t pos3 = str.find_first_of("world");
    cout << "pos3:" << pos3 << endl;

    // 从后往前查找"world"中任意一个字符(即'w'、'o'、'r'、'l'、'd')第一次出现的位置
    size_t pos4 = str.find_last_of("world");
    cout << "pos4:" << pos4 << endl;

    // 从前往后查找不在"helord"中任意一个字符(即'h'、'e'、'l'、'o'、'r'、'd')第一次出现的位置
    size_t pos5 = str.find_first_not_of("helord");
    cout << "pos5:" << pos5 << endl;

    // 从后往前查找不在"helord"中任意一个字符(即'h'、'e'、'l'、'o'、'r'、'd')第一次出现的位置
    size_t pos6 = str.find_last_not_of("helord");
    cout << "pos6:" << pos6 << endl;

    return 0;
}

运行有

 在这里再举一个实际运用的例子

int main()
{
	//分别获得网络的协议、域名和资源名
	// string url = "ftp://www.baidu.com/?tn=65081411_1_oem_dg";
	// https://gitee.com/xuanxuan-qujiu-pavilion
	string url = "https://zh.wikipedia.org/wiki/Wikipedia:%E9%A6%96%E9%A1%B5";
	// 协议  域名  资源名
	size_t pos1 = url.find("://");
	string protocol;
	if (pos1 != string::npos)
	{
		protocol = url.substr(0, pos1);
	}
	cout << protocol << endl;

	string domain;
	string uri;

	size_t pos2 = url.find('/', pos1 + 3);
	if (pos2 != string::npos)
	{
		domain = url.substr(pos1 + 3, pos2 - (pos1 + 3));
		uri = url.substr(pos2 + 1);
	}
	cout << domain << endl;
	cout << uri << endl;

	return 0;
}

⑤string类的非成员函数

源文档

依旧仅对部分函数举例

⑴operator+

源文档

测试代码

int main()
{
    string str1 = "hello";
    string str2 = " world";

    // 将str1和str2拼接起来拷贝构造给str3
    string str3 = str1 + str2;
    cout << "str3:" << str3 << endl;

    // 将一个字符串和str1拼接再拷贝构造给str4
    string str4 = "I am " + str1;
    cout << "str4:" << str4 << endl;

    return 0;
}

运行有

⑵relational operators

测试代码

int main()
{
    string str1 = "abc";
    string str2 = "Abc";
    string str3 = "xyz";

    if (str1 == str2)
        cout << "str1 == str2" << endl;
    else
        cout << "str1 != str2" << endl;

    if (str1 != str3)
        cout << "str1 != str3" << endl;
    else
        cout << "str1 == str3" << endl;

    if (str1 < str3)
        cout << "str1 < str3" << endl;
    else
        cout << "str1 >= str3" << endl;

    if (str2 > str3)
        cout << "str2 > str3" << endl;
    else
        cout << "str2 <= str3" << endl;

    return 0;
}

运行有

⑶operator<<、operator>>

 测试代码

int main()
{
    string str;

    cout << "Please enter a string: ";
    cin >> str;

    cout << "You entered: " << str << endl;

    return 0;
}

运行有

我们可以发现,输出的只有hello这一个字符串,这是因为cin是读取到' '或'\0'就算作读取一次,因此就需要下面这个函数 

⑷getline

测试代码

int main()
{
    string str;

    cout << "Please enter a string: ";
    getline(cin, str);

    cout << "You entered: " << str << endl;

    return 0;
}

运行有

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

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

相关文章

【六一】90后的你们还记得年少时的梦吗?还记得你们当初追的奥特曼吗?现在就让我们一起回味我们逝去的曾经吧!

迎面走来的是我们从未正式出过剧集&#xff0c;并附有“反派”盛名的大哥&#xff01;佐~~菲~~&#xff01; 还记得第一个登场&#xff0c;第一个进入我们的视野的那位吗&#xff1f;没错&#xff0c;那就是奥特曼 我的最爱~~~~~赛文&#xff01; 一度以为&#xff0c;曾经的那…

Bellhop 绘制传播损失

文章目录 前言一、相干传播损失&#xff08;TL&#xff09;基本算例1、环境文件2、绘制相干传播损失 二、相干、半相干和非相干传播损失&#xff08;TL&#xff09; 前言 上文我们讲述了 Bellhop 的使用以及使用 bellhop 绘制了声速剖面、声线轨迹及本证声线&#xff0c;本文我…

【SpringMVC】入门案例

前言: SpringMVC是隶属于Spring框架的一部分&#xff0c;主要是用来进行Web开发&#xff0c;是对Servlet进行了封装。 对于SpringMVC我们主要学习如下内容: SpringMVC简介请求与响应REST风格SSM整合(注解版)拦截器 SpringMVC是处于Web层的框架&#xff0c;所以其主要的作用…

用户验证FTP实验

用户FTP实验 目录 匿名用户验证&#xff1a; 本地用户验证&#xff1a; 本地用户访问控制&#xff1a; 匿名用户验证&#xff1a; 例&#xff1a;&#xff08;前提配置&#xff0c;防火墙关闭&#xff0c;yum安装&#xff0c;同模式vmware11&#xff09; 现有一台计算机huy…

数据结构算法-图技术点(图的算法实现)

先看 定义邻接表 //边 struct Edge {int AdjVertex;//邻接顶点int Weight;//权值Edge* next;//下一条边 };using VertexValue use define//顶点 struct Vertex {VertexValue value; // 顶点数据Edge* First;//获取第一条边 }; //邻接顶点 using AdjVertex Vertex*; //邻接…

自动驾驶嵌入式开发工程师:车载SOC开发修炼秘籍

声明&#xff1a;本文档是博主在开发学习过程中写的笔记&#xff0c;本意是便于以后开发复盘&#xff0c;参考《 ug1144-petalinux-tools-reference-guide》、《ug1085》、黑金Zynq UltraScale MPSoC 5EV开发板资料、英伟达官方资料。大佬勿喷 大佬勿喷 大佬勿喷&#xff01;&a…

【资料分享】RS-485 串行接口说明

面对大量可用的串行接口&#xff0c;可能很难理解它们之间的差异以及何时使用它们。正如我最喜欢的工程学教授经常说的那样&#xff0c;“标准的美妙之处在于有很多标准可供选择。” 今天的编码器比以往任何时候都更智能、更先进&#xff0c;要求工程师放弃更简单的正交增量传感…

智能网联环境下数据安全分析与建设思考

01安全概况 随着智能化程度不断提升&#xff0c;汽车正逐渐从传统意义上的交通工具演化为公路上的智能终端&#xff0c;核心部件也从发动机、变速箱、底盘上升为芯片、软件与数据。相关机构研究表明&#xff0c;目前全球市场搭载智能网联功能的新车渗透率约为45%&#xff0c;预…

160个CrackMe之001

吾爱中的逆向练习题 运行程序 有两个方式 一个是账号登入 一个是序列号输入 账号输入 方法一 爆破 我们先进行账号输入 这个是最简单的逆向 所以我们可以使用 字符串查找看看 先试用ollydbg打开 右键 ->查找 ->所有参考文本字符串 这里我们能发现有两个报错 我们还…

《C++ deque的介绍以及stackh和queue的模拟实现》

文章目录 一、容器适配器1.1 什么是适配器1.2 STL中stack和queue的底层结构1.3 deque的简单介绍1.3.1 deque的原理介绍1.3.2 deque的结构1.3.3 deque和vector以及list的对比1.3.4 为什么选择deque作为stack和queue的适配容器 二、stack的模拟实现三、queue的模拟实现 一、容器适…

5个超实用视频素材网站,免费下载~

推荐几个高清无水印的视频素材网站&#xff0c;重点是可以免费下载使用&#xff0c;建议收藏&#xff01; 菜鸟图库 https://www.sucai999.com/video.html?vNTYxMjky 可以称之为最大素材库&#xff0c;在这里你可以找到设计、办公、图片、视频、音频等各种素材。视频素材就有…

基于Nginx搭建LNMP

目录 一&#xff1a;安装 Nginx 服务 1、关闭防火墙、安装依赖包 2、创建运行用户 3、压缩包编译安装 4、优化路径 5、添加 Nginx 系统服务 二&#xff1a; 安装 MySQL 服务 1、安装Mysql环境依赖包 2、创建运行用户 3、编译安装 4、修改mysql 配置文件 5、更改mysql安装…

网络通信:http协议

虽然我们说, 应用层协议是我们程序猿自己定的. 但实际上, 已经有大佬们定义了一些现成的, 又非常好用的应用层协议, 供我们直接参考使用. HTTP(超文本传输协议) 就是其中之一. 认识URL 统一资源定位符(Uniform Resource Locator&#xff0c;缩写&#xff1a;URL)&#xff0c;…

springboot + vue3实现视频播放Demo(video.js Vue3-video-play视频播放器)

文章目录 学习链接前言ffmpeg安装ffmpeg配置环境变量分割视频文件 后台配置WebConfig 前端代码video.js示例安装依赖视频播放组件效果 Vue3-video-play示例安装依赖main.js中使用视频播放组件效果 学习链接 ffmpeg官网 长时长视频java存储及vue播放解决方法 【 攻城略地 】vue…

AKStream部署1:ZLMediaKit流媒体服务器(win)

环境准备&#xff1a; windows10/11 visual stadio 2022(.net 6) cmake 3.22.0 git bash 没讲究直接下最新的 ffmpeg &#xff1a; ffmpeg-5.1.2-full_build VLC播放器&#xff1a;VLC media player ZLMediaKit&#xff1a;gitee地址 1、安装上述软件 例ffmpeg下载解压至某自定…

图片转pdf怎么转?一分钟解决

在日常生活中&#xff0c;我们常常需要将一些图片转换成PDF格式&#xff0c;以便于在电子设备上查看和分享。今天&#xff0c;我们将分享一些关于如何将图片转换成PDF的方法。 以下是三种常用的将图片转换成PDF的方法&#xff1a; 我们可以借助转换工具将图片转成PDF 如PDF转…

用esp8266连网的一些互联网知识

参考太极创客的课程资料添加链接描述 TCP/IP协议簇 在网络系统中&#xff0c;为了保证通信设备之间能正确地进行通信&#xff0c;必须使用一种双方都能够理解的语言&#xff0c;这种语言被称为“协议”。 TCP/IP协议簇是Internet的基础&#xff0c;也是当今最流行的组网形式…

数据结构学习记录——树习题-Complete Binary Search Tree(题目描述、输入输出示例、数据结构的选择、核心算法、计算左子树的规模)

目录 题目描述 输入示例 输出示例 数据结构的选择 核心算法 计算左子树的规模 思路 总结 题目描述 现给定一系列不同的非负整数键&#xff0c;如果要求构造出一颗完全二叉树&#xff0c;则可以构造唯一的二叉搜索树。输出此二叉搜索树的层序遍历序列。 完全二叉树 有n…

复习之linux系统中的权限管理

1.权限的查看及读取 &#xff08;1&#xff09;权限的查看 # ls -l file : 查看文件的权限 # ls -ld dir :查看目录权限 &#xff08;2&#xff09;权限的读取 文件的属性叫做文件的元数据。 元数据&#xff08;Metadata&#xff09;&#xff0c;又称中介数据、中继…

chatgpt赋能python:Python为什么运行不出来?

Python为什么运行不出来&#xff1f; Python是一门高级编程语言&#xff0c;被广泛应用于科学计算、机器学习、Web开发等领域。但是&#xff0c;有时候我们在编写Python程序的过程中会遇到各种各样的问题&#xff0c;其中之一就是程序无法运行。那么&#xff0c;Python为什么会…