C++(string类)

news2024/11/27 21:43:17

本节目标:

1、为什么要学习string类

2.标准库中的string类

3.vs和g++下string结构说明


1.为什么学习string类

1.1 c语言中的字符串

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

1.2string类简介

  string是C++ 编程语言中的字符串。在C++中字符串处理可以使用c语言字符串形式char *,也可以使用string类格式。
  string 是一个类,类内有char *指针,通过容器方式管理字符串。使用string类型需要需要包含头文件string。

2.标准库中的string类

2.1 string类

需要了解的是:
1. string 是表示字符串的字符串类
2. 该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作 string 的常规操作。
3. string 在底层实际是: basic_string 模板类的别名:
typedef basic_string<char, char_traits, allocator> string;
4. 不能操作多字节或者变长字符的序列。
需要注意:在使用string类时,必须包含头文件#include,以及using namespace std

2.2string 类的常用接口说明(常用的,对于一些非常用的可以去官网查找手册)

1.string类的构造函数

  string常见的构造函数有:无参构造,用c_string构造string类对象,拷贝构造函数

无参构造:string()
c_string构造string类对象:string(const char *str);
拷贝构造:string(const string &str);
初始化字符串为count个c字符:string(int count,char c);

代码如下所示:

2 string类对象的容量操作 

 string 常用的容量操作如下表所示:

函数名称

功能说明

size(重点)

返回字符串有效字符长度

length

返回字符串有效字符长度

capacity

返回空间总大小

empty(重点)

检测字符串释放为空串,是返回true,否则返回false

clear(重点)

清空有效字符

reserve(重点)

为字符串预留空间**

resize(重点)

将有效字符的个数该成n个,多出的空间用字符c填充

 

1. size() length() 方法底层实现原理完全相同,引入 size() 的原因是为了与其他容器的接口保持一
致,一般情况下基本都是用 size()
#include <iostream>
#include <string>

int main()
{
	std::string str("Test string");
	std::cout << "The size of str is " << str.size() << " bytes.\n";
	return 0;
}

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

#include <iostream>
#include <string>

int main ()
{
  char c;
  std::string str;
  std::cout << "Please type some lines of text. Enter a dot (.) to finish:\n";
  do {
    c = std::cin.get();
    str += c;
    if (c=='\n')
    {
       std::cout << str;
       str.clear();
    }
  } while (c!='.');
  return 0;
}

 

 

 

4. reserve(size_t res_arg=0):为string预留空间,不改变有效元素个数,当reserve的参数小于 string的底层空间总大小时,reserver不会改变容量大小。

void TestPushBackReserve()
{
	string s;
	s.reserve(100);
	size_t sz = s.capacity();
	cout << "capacity changed: " << sz << '\n';


	cout << "making s grow:\n";
	for (int i = 0; i < 100; ++i)
	{
		s.push_back('c');
		if (sz != s.capacity())
		{
			sz = s.capacity();
			cout << "capacity changed: " << sz << '\n';
		}
	}

	s.clear();
	cout << "capacity changed: " << sz << '\n';

	s.reserve(10);
	sz = s.capacity();
	cout << "capacity changed: " << sz << '\n';
}

int main()
{
	TestPushBackReserve();

	return 0;
}

 

 

5. resize(size_t n) resize(size_t n, char c)都是将字符串中有效字符个数改变到n个,不同的是当字 符个数增多时:resize(n)0来填充多出的元素空间,resize(size_t n, char c)用字符c来填充多出的 元素空间。注意:resize在改变元素个数时,如果是将元素个数增多,可能会改变底层容量的大小,如果是将元素个数减少,底层空间总大小不变。

int main()
{
	string s1("hello world");

	// 开空间
	s1.reserve(100);
	cout << s1.size() << endl;
	cout << s1.capacity() << endl;

	// 开空间+填值初始化
	//s1.resize(200);
	s1.resize(200, 'x');
	cout << s1.size() << endl;
	cout << s1.capacity() << endl;

	s1.resize(20);
	cout << s1.size() << endl;
	cout << s1.capacity() << endl;

	s1.resize(0);
	cout << s1.size() << endl;
	cout << s1.capacity() << endl;

	return 0;
}

 

 

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

函数名称

功能说明

operator[](重点)

返回pos位置的字符,const string类对象调用

begin+ end

begin获取一个字符的迭代器 + end获取最后一个字符下一个位置的迭代器

rbegin + rend begin

获取一个字符的迭代器 + end获取最后一个字符下个位置迭代器

范围for

C++11支持更简洁的范围for的新遍历方式

1.operator[] 

#include <iostream>
#include <string>

int main()
{
    std::string str("Test string");
    for (int i = 0; i < str.length(); ++i)
    {
        std::cout << str[i];
    }
    return 0;
}

 

 2.迭代器和范围for

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

int main()
{
	std::string s1("Test string");

	// 迭代器
	string::iterator it = s1.begin();
	while (it != s1.end())
	{
		// 写
		(*it)--;

		++it;
	}
	cout << endl;

	it = s1.begin();
	while (it != s1.end())
	{
		// 读
		cout << *it << " ";
		++it;
	}
	cout << endl;

	// 范围for
	// 底层替换为迭代器
	//for (char& ch : s1)
	for (auto& ch : s1)
	{
		ch++;
	}
	cout << endl;

	for (char ch : s1)
	{
		cout << ch << " ";
	}
	cout << endl;

}

3.string类对象的修改操作

 

函数名称 

功能说明

push_back

在字符串后尾插字符c

append      

 在字符串后追加一个字符串

operator+= (重点)

在字符串后追加字符串str

c_str(重点)

返回C格式字符串

find + npos(重点)

从字符串pos位置开始往后找字符c,返回该字符在字符串中的位置

rfind

从字符串pos位置开始往前找字符c,返回该字符在字符串中的位置

substr

在str中从pos位置开始,截取n个字符,然后将其返回

 push_back 尾插字符,append尾插字符串字面就能理解,其实他们都可以用+=实现,

string的连接是通过加法操作符实现的,加号两边可以随意组合string或是字符串字面量。

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

//string的连接

int main()
{
	string s1 = "";
	string s2 = "";
	cout << "请输入两个用空格间隔的字符串:" << endl;
	cin >> s1 >> s2 ;
	string s3 = s1 + s2 ;
	cout << "字符串连接的结果为:" << s3 << endl;
	for (int i = 0;i < 3;i++)
	{
		string s4 = "";
		cout << "请输入字符串:" << endl;
		cin >> s4;
		s3 +=s4;
		cout << "字符连接的结果是: " << s3 << endl;
	}
	return 0;
}

字符串的查找与替换

string字符串查找有find、rfind函数。

  • find函数是从左往右查找,查找成功返回第一个出现的下标,失败返回-1。
  • rfind是查找最后一个出现的下标,失败返回-1。 replace函数实现字符串替换。

 //find函数:从左往右查找
返回值:查找成功返回出现的位置,失败返回-1
int find(const string&str,int pos=0)const;//形参pos表示开始查找的起始位置
int find(const char *str,int pos=0)const;
int find(const char *str,int pos=0,int n)const;//从str的第pos开始的前n个字符中str出现的位置
int find(const char c,int pos=0);//查找字符c
//rfind函数:从右往左查找
int rfind(const string &str,int pos=npos);从pos位置开始查找str最后一次出现的位置
int rfind(const char *str,int pos=npos);从pos位置开始查找str最后一次出现的位置
int rfind(const char *str,int pos=pos,int n);从pos开始的前n个字符中str最后一次出现的位置
int rfind(const char c,int pos=0);//查找c最后一次出现的位置
//字符串替换
string &replace(int pos,int n,const string &s);//将字符串的第pos位置开始的n个字符替换成s
string &replace(int pos,int n,const char *s);

 

#include < iostream >
#include < string >
using namespace std;
void test()
{
	string str = "1asd3as456asd4789asd";
	int pos = str.find("asd");//查找asd第一次出现的位置
	cout << "pos=" << pos << endl;
	string temp = "asd";
	pos = str.find(temp,7);//从第7个位置开始查找asd出现的位置
	cout << "pos=" << pos << endl;

	pos = str.rfind(temp);//查找最后一次出现的位置
	cout << "pos=" << pos < < endl;
	pos = str.rfind("asd",7,2);//从第3个位置开始往前查找,查找"asd"中的前2个字符在str中最后一次位置
	cout << "pos=" << pos << endl;
	//字符串替换
	str.replace(1, 7, "c++");//从第一个位值开始将str的7个字符替换为c++
	cout << "str=" << str << endl;
}
int main()
{
	test();
	system("pause");
}

 函数                                                                   功能说明
operator+                                            尽量少用,   因为传值返回,导致深拷贝效率低
operator>> (重点)                           输入运算符重载
operator<< (重点)                           输出运算符重载
getline (重点)                                  获取一行字符串
relational operators (重点)             大小比较

  4string的读写 

  利用cout可以打印string,即将string输出到标准输出端,也就是命令行窗口。类似的,c++也提供了一种方法从标准输入端,也就是键盘将数据写入string。

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

//string的读写

int main()
{
	string s1;
	string s2;
	cout << "请输入用两个空格隔开的字符串!" << endl;
	cin >> s1 >> s2;
	cout << "s1: " << s1 << endl;
	cout << "s2: " << s2 << endl;
	return 0 ;
}

5 字符串比较

  string类中字符串比较函compare数有多个重载版本,既可以和C语言风格const char *字符串进行比较,也可以和string类字符串进行比较。相等返回0,不相等返回!0值。

字符串比较:
int compare(const char *str);//相等返回0,否则返回非0值
//比较string的len个字符,从idx位置开始
int string::compare (size_type idx, size_type len, const string& str) const
//从指定位置指定长度开始比较
int string::compare (size_type idx, size_type len, const string&str, size_type str_idx, size_type str_len) const
 

#include < iostream >
using namespace std;
#include < string >
void test()
{
	string str1 = "hello,world";
	if (str1 == "hello,world")
	{
		cout << "[const char *]相等" << endl;
	}
	string str2 = "hello,world";
	if (str1 == str2)
	{
		cout << "[string]相等" << endl;
	}
	if (!str1.compare("hello,world"))
	{
		cout << "[compare]相等" << endl;
	}
	//比较str1的前6个字符
	int ret=str1.compare(0,6,"hello,");
	cout << "ret=" << ret << endl;
	//从str1的第0个开始开始取出6个字符,
	//从"c++,hello,"的第4个位置开始,取出6个字符进行比较
	ret = str1.compare(0, 6, "c++,hello,", 4, 6);
	cout << "ret=" << ret << endl;
}
int main()
{
	test();
	system("pause");
}

6字符串的插入与删除

string类中插入函数insert支持多种插入方式,有多个重载版本。
字符串删除可以使用erease函数实现。

 

c++插入:
string& insert(int pos,const char *s);//从第pos位置开始插入s
string& insert(int pos,const string &s);

string &insert(int p0, const char *s, int n);//从p0位置开始插入s,插入的s连续n个字符
string &insert(int p0,const string &s, int pos, int n);//从p0位置开始插入s,插入的s从pos开始,连续n个字符

string &insert(int p0, int n, char c);//从p0处插入n个字符c

c++删除字符串
string &erase(int pos,int n=npos);//从pos位置开始删除n个字符
 

#include < iostream >
#include < string >
using namespace std;
void test()
{
	string str = "hello,";
	str.insert(2,"aaa");//从第2个位置开始插入aaa
	cout < < "str=" << str << endl;
	str.insert(4, "1234", 1, 2);//从第4个位置插入,从"1234"的第1个位置开始,连续两个字符插入到str中
	cout << "str=" << str << endl;

	//字符串删除
	str.erase(2,4);//从第2个位置开始,删除4个字符
	cout << "str=" << str << endl;
	str.erase();//清空字符串
	cout < < "str=" << str <<"\t长度:"<< str.size()<<endl;

 3.vs和g++下string结构说明

  注意:下述结构是在32 位平台下进行验证, 32 位平台下指针占 4个字节。

3.1vs下string的结构:

string总共占28 个字节 ,内部结构稍微复杂一点,先是 有一个联合体,联合体用来定义string中字
符串的存储空间:
  • 当字符串长度小于16时,使用内部固定的字符数组来存放
  • 当字符串长度大于等于16时,从堆上开辟空间 

 

union _Bxty
{ // storage for small buffer or pointer to larger one
 value_type _Buf[_BUF_SIZE];
 pointer _Ptr;
 char _Alias[_BUF_SIZE]; // to permit aliasing
} _Bx;

      这种设计也是有一定道理的,大多数情况下字符串的长度都小于16,那string对象创建好之后,内 部已经有了16个字符数组的固定空间,不需要通过堆创建,效率高。  其次:还有一个size_t字段保存字符串长度,一个size_t字段保存从堆上开辟空间总的容量 最后:还有一个指针做一些其他事。  故总共占16+4+4+4=28个字节。   

3.2.g++string的结构

G++ 下, string 是通过写时拷贝实现的, string 对象总共占 4 个字节,内部只包含了一个指针,该指
针将来指向一块堆空间,内部包含了如下字段:
  • 空间总大小
  • 字符串有效长度
  • 引用计数
struct _Rep_base
{
 size_type _M_length;
 size_type _M_capacity;
 _Atomic_word _M_refcount;
};
  • 指向堆空间的指针,用来存储字符串。

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

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

相关文章

ROS2 库包设置和使用 Catch2 进行单元测试

说明 本文的目的是了解如何在 ROS2 中创建库&#xff0c;以供其他 ROS2 包使用。除此之外&#xff0c;本文还介绍了如何使用 catch2 框架编写单元测试。本文的第 1 部分将详细介绍如何创建库包。第 2 部分将介绍 ROS2 软件包如何利用创建的库 上篇 ROS2 库包设置和使用 Catch2…

postgresql-管理数据表

postgresql-管理数据表 创建表数据类型字段约束表级约束模式搜索路径 修改表添加字段删除字段添加约束删除约束修改字段默认值修改字段数据类型重命名字段重命名表 删除表 创建表 在 PostgreSQL 中&#xff0c;使用 CREATE TABLE 语句创建一个新表&#xff1a; CREATE TABLE …

二、BurpSuite Scan扫描

1.Scan details 解释&#xff1a;选择只是爬行还是爬行加代码审计 Scan Type&#xff1a;选择爬行或者代码审计URLs to scan&#xff1a;定义要扫描的网址。Burp将从这些网址开始进行爬行&#xff0c;并默认将包括指定网址文件夹下的所有内容。Protocol settings&#xff1a;使…

【Office】超简单,Excel快速完成不规则合并单元格排序

演示效果&#xff1a;将下图已经合并了的单元格按照单位名称排序并将同一个单位的数据合并在了一起。 Step 1&#xff1a;取消合并 选中所有的数据后&#xff0c;点击 “开始”-“合并单元格” &#xff0c;并且取消数据源的合并。 Step 2&#xff1a;填充数据 选中需要填…

宝塔反代openai官方API接口详细教程,502 Bad Gateway问题解决

一、前言 宝塔反代openai官方API接口详细教程&#xff0c;实现国内使用ChatGPT502 Bad Gateway问题解决&#xff0c; 此方法最简单快捷&#xff0c;没有复杂步骤&#xff0c;不容易出错&#xff0c;即最简单&#xff0c;零代码、零部署的方法。 二、实现前提 一台海外VPS服务…

Python Cartopy地图投影【3】

上两期文章见&#xff1a; Python Cartopy地图投影【1】 第一期文章内容纲要&#xff1a; step1: 开始地图投影 step2: GeoAxes 的常用方法 2.1 add_feature&#xff1a;添加海岸线、河流、湖泊等地理特征 2.2 gridlines&#xff1a;添加网格线以及相应标签等 Python Cartopy地…

最新AI智能创作系统ChatGPT商业源码+详细图文搭建部署教程+AI绘画系统

一、AI系统介绍 SparkAi创作系统是基于国外很火的ChatGPT进行开发的Ai智能问答系统。本期针对源码系统整体测试下来非常完美&#xff0c;可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如何搭建部署AI创作ChatGPT&#xff1f;小编这里写一个详细图文教程吧&am…

深度学习(2)---循环神经网络(RNN)

文章目录 一、序列数据和语言模型1.1 序列数据1.2 语言模型 二、循环神经网络(RNN)2.1 概述2.2 门控循环单元(GRU)2.3 长短期记忆网络(LSTM) 一、序列数据和语言模型 1.1 序列数据 1. 在深度学习中&#xff0c;序列数据&#xff08;Sequence data&#xff09;是指具有前后顺序…

华为:数据治理方法论

导读 本文先概要介绍了数据治理框架、数据治理组织架构和数据治理度量评估体系&#xff0c;然后结合华为数据治理案例和新冠疫情简单描述了数据治理的应用&#xff0c;最后描述了DAYU方法论在DataArts Studio产品上的落地以及详细的落地指导文档。 加gzh“大数据食铁兽”&am…

[题]欧拉函数 #欧拉函数

目录 欧拉函数一、用公式求代码 二、线性筛法求欧拉函数扩展欧拉定理 欧拉函数 AcWing 873. 欧拉函数 一、用公式求 定义&#xff1a;1 ~ N 中与 N 互质的数的个数被称为欧拉函数&#xff0c;记为ϕ(N)。 怎么求呢&#xff1f;&#xff1f; 有一个公式&#xff1a; N p1a1 X…

《Vue.js+Spring Boot全栈开发实战》简介

大家好&#xff0c;我是老卫。 恰逢中秋国庆双节&#xff0c;不想出门看人山&#xff0c;惟愿宅家阅书海&#xff01; 今天开箱的这本书是《Vue.jsSpring Boot全栈开发实战》。 外观 从书名故名思议&#xff0c;就是基于Vue.jsSpring Boot来实现企业级应用全栈开发。 该书由…

(2023,ControlNet,CFGRW,diffusion,控制组合)向文本到图像扩散模型添加条件控制

Adding Conditional Control to Text-to-Image Diffusion Models 公众号&#xff1a;EDPJ&#xff08;添加 VX&#xff1a;CV_EDPJ 或直接进 Q 交流群&#xff1a;922230617 获取资料&#xff09; 目录 0. 摘要 1. 简介 2.相关工作 2.1. 微调神经网络 2.2. 图像扩散 …

基于electron25+vite4创建多窗口|vue3+electron25新开模态窗体

在写这篇文章的时候&#xff0c;查看了下electron最新稳定版本由几天前24.4.0升级到了25了&#xff0c;不得不说electron团队迭代速度之快&#xff01; 前几天有分享一篇electron24整合vite4全家桶技术构建桌面端vue3应用示例程序。 https://www.cnblogs.com/xiaoyan2017/p/17…

【C++哈希应用】位图、布隆过滤器

【C哈希应用】位图、布隆过滤器 目录 【C哈希应用】位图、布隆过滤器位图概念位图的实现位图改造位图应用总结布隆过滤器布隆过滤器的提出布隆过滤器的概念布隆过滤器的查找布隆过滤器删除布隆过滤器优点布隆过滤器缺陷 作者&#xff1a;爱写代码的刚子 时间&#xff1a;2023.9…

【人物】知识就是金钱,程序员搞副业年入200万,各行各业的你也可以效仿

优秀的普通人 大家好&#xff0c;我是老李。一个专注于收集互联网有用信息的博主。 今天我们这一期要讲的是人物。讲什么人物呢&#xff1f; 首先我们不会讲一些特别知名和特别牛逼的人物&#xff0c;比如马云&#xff0c;雷军。刘强东。这些人固然很厉害很成功&#xff0c;…

【【萌新的RiscV学习之流水线控制-9】】

萌新的RiscV学习之流水线控制-9 我们按照在之前的单周期设计加入控制单元 那么我们能够在后续的设计中提供方便 我们也在流水线中加入一个control单元 我们先按照书上的指令op码值介绍一遍基本功能 接下来我们讲述control 的 控制效果 关于这些串口判别的使用 由于控制线从…

状态压缩dp,291. 蒙德里安的梦想

291. 蒙德里安的梦想 - AcWing题库 求把 NM 的棋盘分割成若干个 12 的长方形&#xff0c;有多少种方案。 例如当 N2&#xff0c;M4 时&#xff0c;共有 5 种方案。当 N2&#xff0c;M3 时&#xff0c;共有 3 种方案。 如下图所示&#xff1a; 输入格式 输入包含多组测试用例…

【yolov5】原理详解

一.模型框架 二.对Yolov5的描述 Yolov5的模型主要由 输入、Backbone、Neck、Head、输出 五部分组成。2.1 输入 输入 640x640x32.2 backbone Backbone&#xff1a;负责提取输入图像的特征。 在Yolov5中&#xff0c;常见的Backbone网络包括CSPDarknet53或ResNet。这些网络都是…

uniapp使用scroll-into-view实现锚点定位和滚动监听功能【楼层效果 / 侧边导航联动效果】

大佬网址&#xff1a; https://blog.csdn.net/weixin_47136265/article/details/132303570 效果 代码 <template><!-- 这里面有2个bug&#xff0c;已经解决&#xff0c;需要知道的地方1.methods里的scrollEvt(e)方法里面的 this.tabIndex index ! -1 ? index :…