前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【C++】string类初步介绍

【C++】string类初步介绍

作者头像
zxctscl
发布2024-03-13 08:58:08
1060
发布2024-03-13 08:58:08
举报
文章被收录于专栏:zxctscl个人专栏

个人主页zxctscl 如有转载请先通知

1. 为什么学习string类

1.1 C语言中的字符串

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

1.2 推荐学习网站

string的学习离不开“看”,这里推荐两个网站:一个是:https://legacy.cplusplus.com/

还有一个C++文档的官网是: https://en.cppreference.com/w/

更喜欢第一个网站,这里面还有c的库。在之后的博客中也是以第一个网站。

2. 标准库中的string类

2.1 string类

在第一个网站里面直接搜索就会看到:

它是一个字符顺序表:

它底层也是模板是basic_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)的序列,这个类的所有成员(如长度或大小)以及它的迭代器,将仍然按照字节(而不是实际编码的字符)来操作。

总结: 1、string是表示字符串的字符串类 2、 该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。 3、string在底层实际是:basic_string模板类的别名,typedef basic_string<char, char_traits, allocator> string; 4、不能操作多字节或者变长字符的序列。

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

2.2 string类的常用接口说明

  1. string类对象的常见构造

(constructor)函数名称

功能说明

string()(重点)

构造空的string类对象,即空字符串

string(const char* s)(重点)

用C-string来构造string类对象

string(size_t n, char c)

string类对象中包含n个字符

string(const string&s)(重点)

拷贝构造函数

2.2.1 constructor

查看string类的Member functions

点constructor就会看见7个构造函数:

其他的构造函数看说明就很简单了解,但是来看看substring (3) ,它当中的size_t len = npos是什么意思呢?

如果len这个参数给的超过了这个字符串从pos位置开始给的长度,举个例子:从pos位置开始,剩余的长度是10,那么它超过了10,有多少就给多少,直接取到结尾。 如果len超过了剩余的长度,或者给npos缺省参数,那么这个就是从pos位置开始,直接取到结尾,有多少就取多少。

点开来看看npos: npos是string里面的一个静态成员常量。

为什么给的是负一就取到字符的结尾?size_t无符号整形这里虽然存的是-1,但底层存的是补码,无符号整形原码和补码是一样的,这里反而变成了整形的最大值,也就是2^32-1。

来实现一下:

代码语言:javascript
复制
#include<iostream>
using namespace std;

#include<string>
void test_string1()
{
	string s0;
	string s1("hello world");
	string s2(s1);
	string s3(s1, 5, 3);
	string s4(s1, 5, 10);
	string s5(s1, 5);

	cout << s0 << endl;
	cout << s1 << endl;
	cout << s2 << endl;
	cout << s3 << endl;
	cout << s4 << endl;
	cout << s5 << endl;
}
int main()
{
	test_string1();

	return 0;
}

来看看s3:从第5个位置开始,那就是从空格开始,拷贝3个字符就是到o的位置。

2. string类对象的容量操作

函数名称

功能说明

size(重点)

返回字符串有效字符长度

length

返回字符串有效字符长度

capacity

返回空间总大小

empty (重点)

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

clear (重点)

清空有效字符

reserve (重点)

为字符串预留空间**

resize (重点)

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

注意:

  1. **size()**与length()方法底层实现原理完全相同,引入size()的原因是为了与其他容器的接口保持一致,一般情况下基本都是用size(),它的长度不包括\0。
  2. clear()只是将string中有效字符清空,不改变底层空间大小。
  3. resize(size_t n) 与 resize(size_t n, char c)都是将字符串中有效字符个数改变到n个,不同的是当字符个数增多时:resize(n)用0来填充多出的元素空间,resize(size_t n, char c)用字符c来填充多出的元素空间。注意:resize在改变元素个数时,如果是将元素个数增多,可能会改变底层容量的大小,如果是将元素个数减少,底层空间总大小不变。
  4. reserve(size_t res_arg=0):为string预留空间,不改变有效元素个数,当reserve的参数小于string的底层空间总大小时,reserver不会改变容量大小。
2.2.2 遍历string

那么要用什么样方式遍历呢?

2.2.2.1 下标加[]遍历
代码语言:javascript
复制
void test_string2()
{
	string s1("hello world");
	for (size_t i = 0; i < s1.size(); i++)
	{
		cout << s1[i] << " ";
	}
	cout << endl;
}

string是私有的,不能拿到它的下标,想要获取它的长度,就用size,返回它有多少个字符。

std::string::operator[]这里模拟的是数组。 a[i]就相当于*a(a+i),就是返回它的第i个字符。

它的底层简单来实现一下: 获取pos位置那个字符

代码语言:javascript
复制
class string
{
public:
	char& operator[](size_t pos)
	{
		return _str[pos];
	}
private:
	char* _str;
	size_t _size;
	size_t _capacity;
};

来试试修改pos位置的字符:

代码语言:javascript
复制
void test_string2()
{
	string s1("hello world");
	for (size_t i = 0; i < s1.size(); i++)
	{
		cout << s1[i] << " ";
	}
	cout << endl;

	for (size_t i = 0; i < s1.size(); i++)
	{
		s1[i] ++;
	}
	cout << endl;

	for (size_t i = 0; i < s1.size(); i++)
	{
		cout << s1[i] << " ";
	}
	cout << endl;
}

如果给的是const对象就不能修改。

在这里插入图片描述
在这里插入图片描述
2.2.2.2 迭代器(iterator)遍历

iterator是一个类型定义在string里面,所以它要指定类域,才能取到。

代码语言:javascript
复制
string::iterator it3 = s3.begin();
	while (it3 !=s3.end())
	{
		cout << *it3 << " ";
		++it3;
	}
	cout << endl;

迭代器行为像指针一样的类型对象,这个区间是一个左闭右开。

迭代器像指针,但不是指针,可以来一下它的类型。

用迭代器也可以实现string的修改:

代码语言:javascript
复制
it3 = s3.begin();
	while (it3 != s3.end())
	{
		 *it3-=3 ;
		++it3;
	}
	cout << endl;

这两种方式其实没有什么区别,那为什么会有迭代器呢? 迭代器是主流,它屏蔽了底层的细节,它才是容器的核心访问方式。链表不会用下标访问。 来看个例子:

代码语言:javascript
复制
#include<iostream>
using namespace std;

#include<string>
#include<vector>
#include<list>
void test_string2()
{
    vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);

	vector<int>::iterator it = v.begin();
	while (it != v.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;

	list<int> lt;
	lt.push_back(1);
	lt.push_back(2);
	lt.push_back(3);
	lt.push_back(4);

	list<int>::iterator itt = lt.begin();
	while (itt != lt.end())
	{
		cout << *itt << " ";
		++itt;
	}
	cout << endl;
}

范围for 自动取容器中的数据,赋值给e,自动迭代,自动往后走,自动结束。

代码语言:javascript
复制
for (auto e : s3)
	{
		cout << e << " ";
	}
	cout << endl;

范围for底层就是迭代器。

有问题请指出,大家一起进步!!!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-03-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 为什么学习string类
    • 1.1 C语言中的字符串
      • 1.2 推荐学习网站
      • 2. 标准库中的string类
        • 2.1 string类
          • 2.2 string类的常用接口说明
            • 2.2.1 constructor
            • 2.2.2 遍历string
        相关产品与服务
        容器服务
        腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档