自学内容网 自学内容网

【STL】带你了解string类

为什么学习string类

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

什么是string

string 就是字符串的意思,是 C++ 用来代替 char 数组 的数据结构。里面封装了一些常用的方法,方便我们对其进行一些操作,而且string的空间大小是动态变化的,大大减小了不必要的花销

标准库中的string类

string底层本质上还是一个顺序表,我们可以理解为是一个封装了char*的容器。
只不过:

  • char* 是一个指针

  • string本质上是一个类,类的内部封装了char*,即**string是一个char***型的容器

  • **string管理char***所分配的内存,不用担心复制越界和取值越界等

typedef basic_string<char> string;

在这里插入图片描述

在使用string这个容器时,需要包含头文件

sting类的常用接口

构造接口

  1. 无参构造
  2. 字符串构造
  3. n个字符c构造
  4. 拷贝构造
    在这里插入图片描述
string s1;//无参构造
**************************
string s1("hello world");//字符串构造
stirng s2(s1);//拷贝构造
**************************
string s1(10,'c');//n个字符构造
  • 下面我会贴出运行图以便更好的理解:
    在这里插入图片描述
    在这里插入图片描述

string类对象的容量操作接口

  1. size();
  2. lenth();->与size()方法底层实现原理完全相同
  3. capacity()
  4. empty()
  5. clear()
  6. reserve()
  7. resize()
  • 下面我会对这些接口进行演示

① size(),lenth(),capacity()

string s2("hello world");
cout << s2.size() << endl;
cout << s2.length() << endl;
  • size()lenth()返回的是字符串有效字符个数,而capacity()返回的是当前对象空间大小
    在这里插入图片描述
  • 为什么size()lenth()这两个接口的功能是一样的呢?这是因为某些历史原因遗留下来的,原本string类使用的是lenth()接口,但是后面为了与其他STL容器保持统一,便有了size()接口,那c++为什么不删了lenth()这个接口呢?很简单,大白话讲就是:在size()接口出来前,很多项目使用的是lenth这个接口,如果删了这个接口,那些项目不就得全崩了吗?所以c++每次更新都是“向前兼容”,不会把之前不好的设定删除掉。

②empty()

  • 这个接口的作用是判断该对象是否为空,为空在返回真,否则返回假。
    在这里插入图片描述
  • 下面是接口演示
    在这里插入图片描述

③clear()

  • 这个接口的作用是清空存储的字符串。
    ->注意,是把字符清楚,不会影响到空间,也就是capacity()。
    在这里插入图片描述
  • 下面是接口演示
    在这里插入图片描述
    在这里插入图片描述
  • 它只是清空字符串,不会影响到空间
  • 咱们来看下是不是真的清空了字符串
    在这里插入图片描述

④reserve()

  • 调整空间,若大于原空间,则进行扩容,若小于原空间,则不进行操作
    在这里插入图片描述
  • 下面是接口演示
    . 当大于原空间时
    在vs平台下,string类初始空间是15(平台不同开辟的空间也不同)
    在这里插入图片描述
    . 当小于原空间时
    在这里插入图片描述

⑤resize()

  • 调整字符串的长度,这个接口不仅会影响到size(),还会影响到capacity()
  • 若大于原长度,但小于原空间,则会增加有效字符个数,直到达到给定的长度,多出来的部分则是用’\0’填充
  • 若大于原长度,并且大于原空间,则会增加有效字符个数,直到达到给定的长度,并进行扩容
  • 若小于原长度,则会减少有效字符个数,并且减去的部分可以理解为被删除了。

第一种情况
在这里插入图片描述
第二种情况
在这里插入图片描述
第三中情况
在这里插入图片描述

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

  • operator[]—>返回pos位置字符的引用
  • begin()+end()—>迭代器
  • rbegin()+rend()—>反向迭代器
  • 范围for—> C++11支持更简洁的范围for的新遍历方式

前面讲到string的底层本质是一个顺序表,既然是顺序表,那就能用下标引用操作符来访问与遍历。
operator[] ->下标引用操作符重载

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

  • 既然我们能通过下标引用来遍历string类的对象,那我们是不是也能借此来修改string类对象中存储的值呢?
    答案是“肯定的”
    在这里插入图片描述
  • 另外,我们还能单独的对某一位置进行自增操作
    在这里插入图片描述

begin()+end()迭代器
begin()获取第一个字符的迭代器 + end()获取最后一个字符下一个位置的迭代器
在这里插入图片描述

  • 下面是接口演示
    在这里插入图片描述

什么是迭代器
概念:迭代器是一种检查容器内元素并遍历元素的数据类型,通常用于对C++中各种容器内元素的访问,但不同的容器有不同的迭代器,初学者可以将迭代器理解为指针。但记住,它只是类似于指针,但不是指针

接下来,我就来具体的讲讲begin()end()

  • bengin(),返回指向容器第一个元素位置的迭代器
  • end(),返回容器最后一个元素的下一个位置的迭代器
    在这里插入图片描述
  • 现在来分析下前面的那段代码
string s1("hello world");
//string::iterator是迭代器类型,不同的容器,迭代器类型不同
string::iterator it1 = s1.begin();//it1存储s1.begin()返回的迭代器位置
while (it1!=s1.end())//当it1没到s1.end()位置时
{
//如前面所说,我们可以暂且把迭代器当作指针来理解。在这里输出迭代器位置的值时,用到了"*"
//和指针不同的是,这里的解引用操作符是被重载过的
cout << *it1 << " ";//输出迭代器当前位置的值
++it1;//然后迭代器后移
}

rbegin()+rend()反向迭代器
rbegin()返回指向容器最后一个元素的迭代器,rend()返回指向容器第一个元素的前一个位置的迭代器。
在这里插入图片描述
在这里插入图片描述

  • 接口演示以及代码讲解
    在这里插入图片描述
string s1("hello world");
//string::reverse_iterator是反向迭代器的类型
string::reverse_iterator it1 = s1.rbegin();//it1存储s1.rbegin()的位置
while (it1!=s1.rend())//当没到s1.rend()位置时
{
cout << *it1 << " ";//输出当前位置的值
++it1;//前移
}

范围for
范围for,又称“语法糖”,它是在c++11时才出来的。
范围for的底层本质也是迭代器。

  • 先演示下范围for的用法
    第一种,可以用auto让编译器来推导类型。
    关于auto,可以到这篇文章中进行了解
    在这里插入图片描述
    第二种,自己给出类型。
    在这里插入图片描述
    前面说了,范围for本质还是迭代器,上面代码中遍历s1,实际是将*it1的值赋值到x中。下面来看下底层
    在这里插入图片描述

string类对象的修改操作

接口使用说明
push_back()在字符串后尾插字符c
append()在字符串后追加一个字符串
operator+= (重点)在字符串末尾追加字符串str
c_str()(重点)返回c格式的字符串
find()从字符串pos位置开始往后找字符c,返回该字符在字符串中的位置
substr在str中从pos位置开始,截取n个字符,然后将其返回

push_back()
在字符串后尾插字符c
在这里插入图片描述

  • 接口演示
string s1("hello");
s1.push_back('w');
for (char x : s1)
{
cout << x;
}

在这里插入图片描述

append()
在字符串后追加一个字符串

string s1("hello");
s1.append("world");
for (char x : s1)
{
cout << x;
}

在这里插入图片描述
③operator+= (重点)
在字符串末尾追加字符串、字符或者一个对象
在这里插入图片描述

string s1("hello");
s1 += "world";
for (char x : s1)
{
cout << x;

在这里插入图片描述
④c_str()(重点)
返回c格式的字符串
在这里插入图片描述

string s1("hello");
cout << s1.c_str() << endl;

在这里插入图片描述
⑤find()
从字符串pos位置开始往后找字符c、字符串s或者一个对象,返回该字符在字符串中的位置
在这里插入图片描述

  • 代码演示
    在这里插入图片描述
    ⑥substr
    在str中从pos位置开始,截取n个字符,然后将其返回
    在这里插入图片描述
  • 接口演示
string s1("hello world");
string s2 = s1.substr(0,5);
for (auto x:s2)
{
cout << x;
}

在这里插入图片描述

string类非成员函数

接口使用说明
operator+尽量少用,因为传值返回,导致深拷贝效率低
operator>> (重点)流插入重载
operator<< (重点)流提取重载
getline (重点)获取一行字符串
relational operators (重点)大小比较

①operator+
在字符串后拼接字符、字符串或者对象
在这里插入图片描述
operator+与operator+=的区别是前者不会影响自身,后者会影响到自身
在这里插入图片描述
在这里插入图片描述

②operator>> 、operator<< (重点)(重点)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

**③getline **
从流中获取一行放到字符串中
在这里插入图片描述

  • 接口演示
    在这里插入图片描述

getline与流插入的区别
流插入遇到空格就会停止,也就是说,如果要输入hello world,那么它只会接收到hello这部分,但是getline则会全部都接收到
在这里插入图片描述

vs和g++下string结构的说明(了解即可)

vs下stirng的结构

1.当字符串长度小于16时,使用内部固定的字符数组来存放

2.当字符串长度大于等于16时,从堆上开辟空间

其次:还有一个size_t字段保存字符串长度,一个size_t字段保存从堆上开辟空间总的 容量 最后:还有一个指针做一些其他事情。 故总共占16+4+4+4=28个字节。

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;

g++下string的结构

G++下,string是通过写时拷贝实现的,string对象总共占4个字节,内部只包含了一个 指针,该指针将来指向一块堆空间,内部包含了如下字段:

  • 空间总大小

  • 字符串有效长度

  • 引用计数

  • 指向堆空间的指针,用来存储字符串。

struct _Rep_base
 {
 size_type               
size_type               
_Atomic_word            
};

原文地址:https://blog.csdn.net/yzqy_/article/details/143665073

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!