c++_STL-1_string_vector

1. stl基本概念

Standard Template Library,由惠普开发的一系列软件的统称,现在主要用在c++中,内嵌在编译器中,不需要安装。

熟练使用stl才算优秀的c++程序员。

stl从广义上分为3类:

  • algorithm
  • container,容器
  • iterator,迭代器

容器和算法通过迭代器进行无缝连接,比传统的函数和类组成的库提供了更好的代码重用机会。

在c++标准中,stl有以下主要的头文件:

  • <algorithm>,<numeric>,<functional>
  • <iterator>
  • <vector>,<stack>,<queue>,<dequeue>,<list>,<map>,<set>
graph LR
A[STL]-->B[string]
A-->C[iterator]
C-->D[algorithm]
C-->E[container]

stl的6大组件

  • Container,各种基本数据结构
  • Algorithm
  • Iterator,连接containers和algorithms
  • Adapter,适配器),可改变containers、Iterators或Function object接口的一种组件
  • Function object,函数对象
  • Allocator,分配器

stl的重要特点是数据结构和算法的分离。

1.1 容器

重复利用已有的实现构造自己的特定类型下的数据结构。

数据结构:研究结点之间的关系。

容器分为2类:

  • 序列式容器,sequence containers,每个元素有固定位置,与添加时机和地点有关,与值无关,如vector,deque,list
  • 关联式容器,associated containers,和添加顺序无关,节点组成红黑树,如set,multiset,map,multimap

1.2 c++标准库

分为10类。

语言支持相关:<cstddef>,<limits>,<climits>,<cfloat>,<cstdlib>,<new>,<typeinfo>,<exception>,<cstdarg>,<csetjmp>,<csignal>.

io流相关:<iostream>,<iomanip>,<ios>,<istream>,<ostream>,<sstream>,<fstream>,<iosfwd>,<streambuf>,<cstdio>,<cwchar>

诊断功能:<stdexcept>,<cassert>,<cerrno>

工具:<utility>,<functional>,<memory>,<ctime>

字符串处理:<string>,<cctype>,<cwctype>,<cstring>,<cwchar>,<cstdlib>

容器类的模板:<vector>,<list>,<deque>,<queue>,<stack>,<map>,<set>,<bitset>

迭代器:<iterator>

算法:<algorithm>,<cstdlib>,<ciso646>

数值操作:<complex>,<valarray>,<numeric>,<cmath>,<cstdlib>

本地化:<locale>,<clocale>

1.3 值拷贝

所有容器提供值语义value,而不是引用语义reference。所以执行添加操作时,要确保容器内的元素有拷贝构造函数,无参构造函数并重载赋值运算符。尤其是有指针成员时。

2. string

重点有初始化、遍历、连接、查找和替换、插入、反转和大小写转换。

而且,不用担心越界的问题。

2.1 初始化

//初始化
#include <iostream>
using namespace std;
#include "string"

int main()
{
	string s1  = "aaa";
	string s2("bbb");
	string s3 = s1; // copy constructor
	string s4(3,'c');
	
	cout<<s1<<endl;
	cout<<s2<<endl;
	cout<<s3<<endl;
	cout<<s4<<endl;
	
	printf("%p\n%p\n%p\n","aaa",&s1,&s3);
	
	cin.get();
	return 0;
}

/*
aaa
bbb
aaa
ccc
00445000
0066FF00
0066FEE0
*/

2.2 遍历

3种方法:数组,迭代器,at()

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


int main()
{
	string s = "abcdef";
	for(int i = 0; i < s.length(); i++)
	{
		cout<<s[i]<<" ";
	}
	cout<<endl;
	
	for(string::iterator it = s.begin(); it != s.end(); it++)
	{
		cout<<*it<<" ";
	}
	cout<<endl;
	
	for(int i = 0; i < s.length(); i++)
	{
		cout<<s.at(i)<<" ";
	}
	cout<<endl;
	
	cin.get();
	return 0;
}

/*
a b c d e f
a b c d e f
a b c d e f
*/

调试一下可以验证,s.end()指向s[s.size()],也就是最后一个元素之后。

相比于[]at()可以抛出异常。

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


int main()
{
	string s = "abcdef";
	
	try
	{
		for(int i = 0; i < s.length() + 3; i++)
		{
			cout<<s.at(i)<<" ";
		}
		cout<<endl;
	}
	catch(...)
	{
		cout<<"Exception.\n";
	}
	
	try
	{
		for(int i = 0; i < s.length() + 3; i++)
		{
			cout<<s[i]<<" ";
		}
		cout<<endl;
	}
	catch(...)
	{
		cout<<"Exception.\n";
	}
	
	cin.get();
	return 0;
}

//vs中第二次遍历会中断

2.3 转换为指针

初始化时可以实现char*-->string,通过const char* c_str() cosnt{},就能实现string-->char*

string拷贝到一段内存中,可以用int copy(char *s,int n,int pos=0) const;,返回值为拷贝数,该函数不保证不越界。

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

int main(int argc, char *argv[])
{
	string s = "abcdef";
	
	//string-->char*
	printf("%s\n",s.c_str());
	
	//string-->buf
	char buf[10] = {0};
	s.copy(buf,5);
	printf("%s\n",buf);
	
	cin.get();
	return 0;
}


/*
abcdef
abcde
*/

2.4 连接

可以用重载的加号运算符或者string &append();,第2个参数如下:

  • const char*
  • const char *s,int n
  • const string &s
  • const string &s,int pos,int n
  • int n,char c,添加n个c
#include<iostream>
using namespace std;
#include "string"

int main(int argc, char *argv[])
{
	string s1 = "abc";
	string s2 = "def";
	s1 = s1 + s2;
	cout<<s1<<endl;
	
	string s3 = "23";
	string s4 = "33";
	s3.append(s4);
	cout<<s3<<endl;
	
	cin.get();
	return 0;
}

2.5 查找和替换

string substr(int pos = 0,int n=npos) const;返回由pos开始的长度n的字符串。

int find(char c, int pos=0) const;

int find(const char*s,int pos=0) const;

int find(const string &s,int pos=0) const;

这3个find()也有对应的rfind(),从后往前查找,pos默认参数为string::npos

string:npos是个特殊值,说明查找没有匹配

string &replace(int pos,int n,const char*s),删除pos开始的n个字符,插入s。

void swap(string &s),交换当前字符串与s的值。

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

int main(int argc, char *argv[])
{
	string s = "aaa When I aaa was aaa.";
	int index = 0;
	index = s.find("When");
	cout<<index<<endl;
	index = s.find("When",index+1);
	cout<<index<<endl;
	
	index = s.find("aaa");
	int flag = 0;
	while(index != string::npos)
	{
		flag++;
		s.replace(index,3,"AAA");
		index = s.find("aaa",index+1);
	}
	cout<<flag<<endl;
	cout<<s<<endl;
	
	cin.get();
	return 0;
}


/*
4
-1
3
AAA When I AAA was AAA.
*/

2.6 删除和插入

string &erase(int pos=0, int n=npos);,删除pos处的n个字符。

iterator erase ( iterator first, iterator last );

string &insert(int pos,const char*s);

string &insert(int pos,const string &s);

string &insert(int pos, int n, int c);

#include<iostream>
using namespace std;

#include "string" 

int main(int argc, char *argv[])
{
	string s = "hello world.";
	string::iterator it = find(s.begin(),s.end(),'l');
	if(it != s.end())
	{
		s.erase(it);
	}
	cout<<"s: "<<s<<endl;
	
	s.erase(s.begin(),s.end());
	cout<<s<<endl;
	cout<<s.length()<<endl;
	
	s.insert(0,"new string.");
	cout<<"s: "<<s<<endl;
	
	cin.get();
	return 0;
}


/*
s: helo world.

0
s: new string.
*/

2.7 算法

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

int main(int argc, char *argv[])
{
	string s = "aaaBBB";
	transform(s.begin(), s.end(), s.begin(), toupper);
	cout << s << endl;
	transform(s.begin(), s.end(), s.begin(), tolower);
	cout << s << endl;

	cin.get();
	return 0;
}

3. vector容器

vector容器把元素存进动态数组,尾部添加或删除快,中间添加或删除需要移动后面的元素。vector可以随机存储元素,并支持[]at()

vector采用模板类实现,即vector<T> vecT;

存放自定义类时,由于需要值复制,所以必须提供拷贝构造函数。

3.1 构造、添加、删除

v.front()v.back()返回第一个和最后一个元素的引用。

void push_back()void pop_back是末尾插入和删除。

#include<iostream>
using namespace std;
#include "vector"

int main(int argc, char *argv[])
{
	vector<int> v1;
	v1.push_back(1);
	v1.push_back(2);
	v1.push_back(3);
	cout<<"len:"<<v1.size()<<endl;
	cout<<"the first element:"<<v1.front()<<endl;
	v1.front() = 11;
	v1.back() = 33;
	while(v1.size() > 0)
	{
		cout<<v1.back()<<endl; 
		v1.pop_back();
	}
	
	cin.get();
	return 0;
}
/*
len:3
the first element:1
33
2
11
*/

可以指定元素个数并初始化为0:vector<int> v1(3)

#include<iostream>
using namespace std;
#include "vector"

int main(int argc, char *argv[])
{
	vector<int> v1(3);  // vector<int> v1(3,0)
	v1.push_back(1);
	cout<<v1.size()<<endl;
	for(int i = 0; i < 4; i++)
	{
		cout<<v1[i];
		cout<< " ";
		cout<<v1.at(i)<<endl;
	}
	
	cin.get();
	return 0;
}
/*
4
0 0
0 0
0 0
1 1
*/

除了vector<int> v1 ,还有其它带参数构造方式:

  • vector(iterator begin,iterator end),拷贝左闭右开区间[begin,end)的元素
  • vector(n,elem),拷贝n个elem
  • vector(const vector &vec),拷贝构造函数
vector<int> v2 = v1;
vector<int> v3(v1.begin(),v2.end() + 2);

3.2 迭代遍历

#include<iostream>
using namespace std;
#include "vector"

int main(int argc, char *argv[])
{
	vector<int> v1;
	v1.push_back(1);
	v1.push_back(2);
	v1.push_back(3);
	
	for(vector<int>::iterator it = v1.begin(); it != v1.end(); it++)
	{
		cout<<*it<<" ";
	}
	cout<<endl;
	
	for(int i = 0; i < 3; i++)
	{
		printf("%p\n",&v1[i]);
	}
	printf("%p\n",&*v1.end());
	
	cin.get();
	return 0;
}

/*
1 2 3
006C2F88
006C2F8C
006C2F90
006C2F94
*/

v1.end()仍然指向最后一个元素+1.

反过来,还有rbegin(),rend()

#include<iostream>
using namespace std;
#include "vector"

int main(int argc, char *argv[])
{
	vector<int> v1;
	v1.push_back(1);
	v1.push_back(2);
	v1.push_back(3);
	
	for(vector<int>::reverse_iterator rit = v1.rbegin(); rit != v1.rend(); rit++)
	{
		cout<<*rit<<" ";
	}
	cout<<endl;
	
	
	cin.get();
	return 0;
}
/*
3 2 1
*/

迭代器

迭代器分为:

  • 输入迭代器,也叫只读迭代器,读取一个元素后移动,只能遍历一遍
  • 输出迭代器,也叫只写迭代器
  • 正向迭代器,相当于输入+输出迭代器,并能多次遍历
  • 双向迭代器,相当于正向迭代器+移动操作符
  • 随机访问迭代器,可以直接访问任何位置的双向迭代器

双向迭代器支持的操作:

  • it++,++it,
  • *it,
  • it1 = it2
  • it1 == it2, it1 != it2

支持的容器有list,set,multiset,map,multimap

随机访问迭代器在双向迭代器的基础上添加了以下操作:

  • it+=i,it[i]
  • it1<it2,it1<=it2
  • it1 = it2
  • it1 == it2, it1 != it2

支持的容器有vector,deque.

3.3 插入

vector.insert(iterator pos,elem);

vector.insert(iterator pos,int n,elem);

vector.insert(iterator pos,begin,end);,在pos插入[begin,end)区间的值。

3.4 删除

vector.erase(iterator pos)

vector.erase(iterator begin,iterator end),删除一个区间。

注意,发生插入和删除时,vector的元素会移动,但迭代器不会改变所指向的位置。

#include<iostream>
using namespace std;
#include "vector"

int main(int argc, char *argv[])
{
	vector<int> v1;
	v1.push_back(1);
	v1.push_back(2);
	v1.push_back(2);
	v1.push_back(3);
	
	vector<int>::iterator it = v1.begin(); 
	v1.erase(it);
	v1.erase(it);
	
	for(int i = 0; i < v1.size(); i++)
	{
		cout<<v1[i]<<" ";
	}
	cout<<endl;
	
	
	v1.insert(v1.begin(),2);
	v1.insert(v1.begin(),1);
	
	cout<<"after insert(),it still point to begin:";
	cout<<*it<<endl;
	
	cout<<"deleting..."<<endl;
	for(; it != v1.end();)	//delete 2
	{
		if(*it == 2)
		{
			v1.erase(it);
		}
		else
		{
			it++;
		}
	}
	
	for(int i = 0; i < v1.size(); i++)
	{
		cout<<v1[i]<<endl;
	}
	
	cin.get();
	return 0;
}
/*
2 3
after insert(),it still point to begin:1
deleting...
1
3
*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值