STL之string的详细介绍

坚强是说给别人听的谎言 提交于 2020-01-20 01:24:35

什么是STL?

STL(standard template libaray )标准模板库
是C++标准库的重要组成部分 不仅是一个可以复用的组件库 更是一个包罗数据结构算法的软件框架

以下是STL的六大组件 大概了解一下以后会详细介绍。
STL六大组件:

1.仿函数
如:greater less
2.算法
如:find swap reverse sort merge
3.迭代器
如:iterator const_iterator reverse_iterator const_reverse_iterator
4.空间配置器
如:allocator
5.容器
如:string vector list deque map set multimap
mutilset
6.配接器
如:stack queue priority_queue


什么是string?

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

接下来主要讲一些 string 类里所包含的一些常用的方法和函数 例如 构造 赋值 删除 插入、连接字符 获取字符 查询等等

一、string的常见构造方法

1. string (); 构造一个空的string对象 即空的字符串

例: string s1;
在这里插入图片描述

2. string(const char* s);用C-string来构造string类对象

例 :string s2("hello world");
在这里插入图片描述

3. string(const string&s); 用一个string类对象拷贝构造另一个string类对象

例:string s1(s2);
在这里插入图片描述

4. string(size_t n, char c); 用n个字符c来构造string类对象

例:string s1(10,'a');
在这里插入图片描述

5. string(const string&s, size_t n);用s中的前n个字符构造新的string类对象

例:string s2(s1,5);
在这里插入图片描述


二、string类对象的空间容量的操作

1. size_t size() const 返回string对象的有效字符的size 也就是长度

例:string s1("hello world") cout<<s1.size();<<endl;
在这里插入图片描述
与其同样可以计算string类对象的还有

2. size_t length() const 也是返回字符串有效字符长度

例:string s1("hello world"); cout<<s1.length()<<endl;
在这里插入图片描述
size()与length()方法底层实现原理完全相同,引入size()的原因是为了与其他容器的接口保持一 致,一般情况下基本都是用size()。

3. size_t capacity ( ) const 返回空间的总大小

例:string s1("hello world"); cout<<s1.capacity()<<endl;
在这里插入图片描述
这里可以看到 一个string类的对象的空间大小 并不是和字符串有效长度的同等大小的,那么string类对象在底层的空间到底是如何分配的呢?接下来看一段代码:

#include<iostream>
#include<string>
#include<stdlib.h>
using namespace std;
int main()
{
	string s1("hello world");
	int i=0;
	for(i=0; i<50; i++)
	{
		s1+='a';//尾插一个 char类型的字符'a' 观察有效字符串和容量的变化
	cout<<"s1.size()="<<s1.size();
	cout<<" ";
	cout<<"s1.capacity()="<<s1.capacity()<<endl;
	}
	system("pause");
	return 0;
}

在这里插入图片描述
可以发现其容量当不够时就会扩容,是由底层实现的,暂时不讲其原理,可以发现容量增长规律 大概是呈1.5倍增长

4. bool empty ( ) const 检测字符串释放为空串,是返回true,否则返回false。

例:

    string s1;
	string s2("a");
	cout<<s1.empty()<<endl;
	cout<<s2.empty()<<endl;

在这里插入图片描述
可以看到 s1 是一个空的字符串 因此返回1 即为true 而s2不是一个空字符串因此返回false 返回 0

5. void clear() 清空有效字符

例: string s1("hello world"); s1.clear(); cout<<s1<<endl;

注意:观察清空后其有效字符串、以及容量的变化:

#include<iostream>
#include<string>
#include<stdlib.h>
using namespace std;
int main()
{
    string s1("hello world");
	s1.clear();
	if(s1.empty())
	{
		cout<<"s1=NULL"<<endl;
	}
	else
	{
		cout<<s1<<endl;
	}
	cout<<"s1.size()"<<s1.size()<<endl;
	cout<<"s1.capacity()="<<s1.capacity()<<endl;
	system("pause");
	return 0;
}

在这里插入图片描述

观察可以发现 clear 只是清空了string 对象的内容 但并不是释放了这块地址空间 容量还是保持不变的。

6. void resize ( size_t n, char c ) 将有效字符的个数修改成n个,并且多出的空间用字符c填充。
7.void resize ( size_t n ) 将有效字符的个数改成n个,多出的空间用0填充

例:string s1 ("hello"); s1.resize(10,'a'); cout<<s1<<endl;
例:string s1("hello "); s1.resize(3); cout<<s1<<endl;

#include<iostream>
#include<string>
#include<stdlib.h>
using namespace std;
int main()
{
    string s1("hello ");
	s1.resize(10);
	cout<<s1<<endl;
	s1.resize(15,'a');
	cout<<s1<<endl;;
	s1.resize(4);
	cout<<s1<<endl;
	system("pause");
	return 0;
}

在这里插入图片描述
可以看到 resize 两个参数的区别就是 当只有一个是用0替代多余出来的空间 而而另一个是用 一个 char c 字符来替代。

注意:resize在改变元素个数时,如果是将元素个数增多,可能会改变底层容量的大 小,如果是将元素个数减少,底层空间总大小不变

8. void reserve ( size_t res_arg=0 ) 为字符串预留空间

例: string s1("hello"); s1.reserve(100); cout<<s1.capacity()<<endl;

这样做的目的是 当大概知道所需要的空间大小时 可以为string 对象预留一定的空间 减少底层扩容时所付出的代价:

代码演示:

#include<iostream>
#include<string>
#include<stdlib.h>
using namespace std;
int main()
{
	int i;
    string s1("hello ");
	s1.reserve(100);
	for(i=0; i<100; i++)
	{
		s1+='c';
		cout<<"s1.size():"<<s1.size();
		cout<<" ";
		cout<<"s1.capacity:"<<s1.capacity()<<endl;
	}
	system("pause");
	return 0;
}

在这里插入图片描述

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


三、string类对象的访问操作

即使用 " [ ] " 对string 类对象进行访问和操作 但要区分 是否是const 类型的string 类对象 以及他们之间的调用关系.

char& operator[] ( size_t pos ) 返回pos位置的字符,const string类对象调用
const char& operator[] ( size_t pos ) const 返回pos位置的字符,const string类对象调用

例:

int main()
{
    string s1("hello world");
	const string s2("change world");
	s1[0]='H';//s2[0]='C' 这里报错 显示表达式是必须可修改的左值
	//使用 方括号进行对string类对象访问
	cout<<s1[0]<<" "<<s2[0]<<endl;
	system("pause");
	return 0;
}

四、string类对象的修改操作

1. void push_back(char c) 在字符串后尾插字符c

另外与之对应的还有pop_back(char c) 功能是尾删一个字符;

例:string s1; s1.push_back('h');

int main()
{
    string s1;
	s1.push_back('h');
	s1.push_back('e');
	s1.push_back('l');
	s1.push_back('l');
	s1.push_back('o');
	cout<<s1<<endl;
	s1.pop_back();//尾删一个数据 
	s1.pop_back();
	cout<<s1<<endl;
	system("pause");
	return 0;
}

在这里插入图片描述

2. string& append (const char* s); 在字符串后追加一个字符串
3. string& operator+=(const string& str)在字符串后追加字符串str
4. string& operator+=(const char* s) 在字符串后追加C个数字符串
5. string& operator+=(char c) 在字符串后追加字符c

例如:代码

int main()
{
	string s1;
 //2. string& append (const char* s); 在字符串后追加一个字符串
	s1.append("hello ");
	cout<<s1<<endl;
 //3. string& operator+=(const string& str)在字符串后追加字符串str
	string s2("wo");
	s1+=s2;
	cout<<s2<<endl;
 //4. string& operator+=(const char* s) 在字符串后追加C个数字符串
	s1+="rl";
	cout<<s1<<endl;
 //5. string& operator+=(char c) 在字符串后追加字符c
	s1+='d';
	cout<<s1<<endl;
	system("pause");
	return 0;
}

运行结果:
在这里插入图片描述

注意: 在string尾部追加字符时,s.push_back ( c ) / s.append(1, c) / s += 'c’三种的实现方式差不多,一般 情况下string类的+=操作用的比较多,+=操作不仅可以连接单个字符,还可以连接字符串。

6. const char* c_str( )const 返回C格式字符串

例:以C语言的方式打印字符串
在这里插入图片描述

7.size_t find (char c, size_t pos = 0)const从字符串pos位置开始往后找字符c,返回该字符在 字符串中的位置
8.size_t rfind(char c, size_t pos = npos)从字符串pos位置开始往前找字符c,返回该字符在 字符串中的位置

代码演示:

int main()
{
	int tmp1,tmp2,tmp3;
    string s1("123456789");
	tmp1=s1.find('4',0);
	cout<<tmp1<<endl;
	tmp2=s1.rfind('4',8);
	cout<<tmp2<<endl;
	tmp3=s1.find('a',2);//当找不到时会返回-1
	cout<<tmp3<<endl;
	system("pause");
	return 0;
}

在这里插入图片描述

9.string substr(size_t pos = 0, size_t n = npos)const在str中从pos位置开始,截取n个字符,然后将其 返回

例如:
在这里插入图片描述


以上便是在构建string 类对象且对string 类对象进行一些访问、修改、查找等操作的比较常见的接口,另外还有很多的接口如下:

#include<iostream>
#include<string>
#include<stdlib.h>
using namespace std;
int main()
{
	int i=2;
    string s1("hello world");
	string s2("haha");
	cout<<s1.front()<<endl;//返回第一个字符
	cout<<s1.back()<<endl;//返回最后一个字符
	swap(s1,s2);//交换两个字符或字符串
	cout<<s1<<endl;
	cout<<s2<<endl;
	cout<<s1.compare(s2)<<endl;//比较两个字符串长度的大小
	string s3(s2,0,4); //拷贝构造 用S2 的字符串中 
	//pos的位置的开始后的n个字符串内容来构造 s3
	cout<<s3<<endl;
	cout<<s1.at(i)<<endl;//访问 i处的字符
	string s4;
	getline(cin,s4);// cin 以 空格 分割输入的字符串 
	//而 getline 以换行符来分割 获取一行输入的字符
	cout<<s4<<endl;
	s1.assign("change world");//赋予新值
	cout<<s1<<endl;
	system("pause");
	return 0;
}

结果如下:
在这里插入图片描述
还有一些string类的非成员函数 以及深浅拷贝问题 ,string的模拟实现会在以后的博客继续整理;

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!