上一节我们提到了STL的一些基本的使用,本篇细说一下STL中的方法C++11中实用的用法,以及string的具体使用
第一篇我们已将初步的认识string这个类,现在具体看一看string类的详细用法
string类中提供许多的构造方法
构造函数 | 功能 |
---|---|
string(s) | 赋值为string |
string(s, beg) | 赋值为string下标为beg到结尾的字符串 |
string (s, beg, end) | 赋值为string下标为beg到下标为end的字符串 |
string(num, c) | 赋值string为num个’c’ |
string() | 空惨构造,string 字符串为空 |
#include
#include
using namespace std;
int main(){
string st, s = "hello world";
st = string(s); // hello world
st = string(s, 1); // ello world
st = string(s, 1 , 3); // ell
st = string(5, '9'); // 99999
return 0;
}
第一篇我们已经讲过了string的输入,本次提供了详细说明和 第三种方法
#include
#include
using namespace std;
int main(){
string st, s = "hello world";
//1.最常规的字符串的输入方法 遇到空格 TAB 回车分割
cin >> st;
//2.读一整行的字符,string版本
getchar();
getline(cin ,st);
cout << st;
//3.C风格的输入字符串 声明char数组和输入个数
char c[20];
// a 也可以使用二维数组来cin.getline(c[i], 10);
cin.getline(c, 10);
// b
//cin.get(c, 10);
cout << c;
return 0;
}
细谈cin.getline(c,num)
和getline(cin,s)
我们刚刚说了string的两种输入方式但是他们之间有什么异同呢?
相同点:都存在可选的参数,指定那个字符为输入的边界 如果不添加此参数的话 默认为’ ‘\n’, 这样就解释了回车的时候就输入了字符串
不同点:string版本的
getline()
不需要指定读入多少个字符的参数数值, ,即读取的字符不限定,而cin.getline()
限定输入字符的数量假设声明cin.getline(c,n)
的话输入的字符串就是 n - 1 原因就是它本身是C风格的输入, 在C中字符数组最后一个字符默认为\0
,最后的位置被\0
占用了.具体区别开如下代码的演示
#include
#include
using namespace std;
int main(){
string st ;
//如果输入 , 按回车没反应的 边界为 ,
getline(cin, st, ','); // in : 81,60
cout << st << endl; // out : 81
char c[5], c1[5], c2[5];
cin.getline(c, 10, ','); // in : 816,0
cout << c << endl; // out : 816
getchar();
//字符个数限制
cin.getline(c1, 5); // in : 816041
cout << c1 << endl; // out :8160
return 0;
}
函数名 | 功能 |
---|---|
size()/length() | 字符串的长度 |
capacity() | 当前string包含的最大字符数 |
insert() | 插入 |
push_back() | 末尾添加字符 |
append() | 追加字符串 |
erase() | 删除字符串 |
replace() | 字符串的替换 |
copy() | 字符串的复制 |
swap() | 字符串的交换 |
assign() | 字符串的赋值 |
find() | 查找 |
rfind() | 从末尾查找 |
find_first_of() | 查找第一次出现在字符串子字符的下标 |
find_last_of() | 查找最后一次出现在字符串子字符的下标 |
find_first_not_of() | 搜索第一个不在子字符串中字符的下标 |
find_last_not_of() | 搜索最后一个不在子字符串中字符的下标 |
front() | 返回字符串首个字符 |
back() | 返回末尾字符 |
#include
#include
using namespace std;
int main(){
//最常用的赋值方式
string s = "8160415";
//对每个字符串的的调用
st[6] = '3';
cout << s << ": " << s.length()<< " " << s.capacity() << endl;
//使用构造
string st ("hello");
cout << st << endl;
string t;
//t 赋值为s下标1到4
t.assign(s, 1, 4);
// 长度为6 s字符串
t.assign(6, 's');
cout << t;
return 0;
}
#include
#include
using namespace std;
int main(){
string s = "hell";
//用来在尾部插入单个字符
s.push_back('o'); // hello
//s.insert(s.end(), 'o');
//第五个字符串后插入
s.insert(5, " world"); // hello world
//第五个字符串后插入并指定字符个数为2
s.insert(11, " and", 2); // hello world a
cout<< s;
//字符串的追加
string st = "gorge";
st.append("ous");
st.append(3, '!');
cout << st;
//拼接方法
string st1 = "gorgeous" , st2 = " and brilliant", t;
t = st1 + st2;
cout << t;
return 0;
}
#include
#include
using namespace std;
int main(){
string s = "I believe whatever doesn't kill you simply makes you stranger stranger";
//1.起始位置开始查找 返回第一次的出现的首字母下标
cout << s.find("believe") << endl; // 6
// 下标为4开始查找
cout << s.find('e', 4) << endl; // 2
//搜索最后一次出现的位置,理解为从末尾查找
cout << s.rfind("stranger") << endl; // 62 第二个 stranger
//查找第一次出现在字符串"wl"字符的下标
cout << s.find_first_of("wl") << endl; // 4
//查找最后一次出现在字符串"wl"字符的下标
cout << s[s.find_last_of("str")] << s.find_last_of("str") <<endl; // r 69
// 搜索第一个不在子字符串"I be"中字符的下标
cout << s.find_first_not_of("I be") << endl; // 4
//搜索最后一个不在子字符串"str"中字符的下标
cout << s.find_last_not_of("str") << endl; // 68
//如果出现没找的情况返回 string::npos
if(s.find('za') == string::npos){
cout << "Not Exist";
}
return 0;
}
#include
#include
using namespace std;
int main(){
string s = "I believe ";
//删除起始位置1到末尾
//s.erase(s.begin() + 1);
s.erase(1);
//删除下标1到4
s.erase(1, 4);
cout << s;
//删除所有
s.clear();
return 0;
}
#include
#include
using namespace std;
int main(){
string s = "turn right and go straight ", t;
t = s.replace(5, 5, "left"); // turn left and go straight
t = s.replace(s.begin(), s.begin() + 5, "s");// sleft and go straight
cout << t << endl;
//replace 常常和find一起使用替换字符串
string s1 = "old", s2 = "mature", s3 = "The old man and the sea";
string::size_type pos = s3.find(s1);
if(pos != string::npos){
s3.replace(pos, s1.size(), s2);
}
cout << s3 << endl;
return 0;
}
#include
#include
#include
using namespace std;
int main(){
string s = "hello";
//1. 使用算法中的 transform 后续会将到算法
transform(s.begin(), s.end(), s.begin(), ::toupper);
cout << s << endl;
//2. 使用数组
for(int i = 0; i < s.size(); i++){
s[i] = tolower(s[i]);
}
cout << s <<endl;
return 0;
}
#include
#include
#include
using namespace std;
int main(){
string s = "hello";
for(int i = 0; i << s.size(); i++){
cout << s[i];
}
//正向迭代
for(string::iterator it = s.begin(); it != s.end(); it++){
cout << *it;
}
for(auto it = s.begin(); it != s.end(); it++){
cout << *it;
}
//反向迭代
for(string::reverse_iterator it = s.rbegin(); it != s.rend(); it++){
cout << *it;
}
return 0;
}
上节我们主要谈了STL中刷题中常常使用的 基本工具,本篇将STL分成三类全面讲述,分别是容器(container),迭代器(Iterator)和算法(algorithm)
容器(container):erator)。 STL容器是一些模板类,提供了多种组织数据的常用方法,例如vector(向量, 类似于数组)、list(列表,类似于链表)、deque(双向队列)、set(集合)、 map(映象)、stack(栈)、queue(队列)、priority_queue(优先队列)等等, 通过模板的参数我们可以指定容器中的元素类型。
迭代器(Iterator):迭代器是对C中的指针的一般化,用来将算法和容器联系起来。几乎所有 的STL算法都是通过迭代器来存取元素序列进行工作的,而STL中的每一个 容器也都定义了其本身所专有的迭代器,用以存取容器中的元素。
算法(algorithm):算法是一些模板函数,提供了相当多的有用算法和操作,如 for_each(遍历),stable_sort(稳定排序),search(搜索),swap(交换),copy(复制)等等。
序列式容器就是 vector list queue这样的容器 容器中的元素是有顺序的,按位置存储
vector中方法
函数名 | 功能 | 复杂度 |
---|---|---|
size() | 返回向量的个数 | O ( 1 ) {O(1)} O(1) |
push_back(n) | 在向量的末尾添加n | O ( 1 ) {O(1)} O(1) |
begin() | 返回指向向量开头的迭代器 | O ( 1 ) {O(1)} O(1) |
end() | 返回指向向量末尾的的后一个迭代器 | O ( 1 ) {O(1)} O(1) |
insert(p, x) | 在向量P的位置插入x | O ( n ) {O(n)} O(n) |
erase§ | 删除向量中位置p的元素 | O ( n ) {O(n)} O(n) |
clear() | 删除向量中所有的元素 | O ( n ) {O(n)} O(n) |
pop_back() | 删除向量的最后一个元素 | O ( 1 ) {O(1)} O(1) |
resize() | 给向量分配大小 | O ( 1 ) {O(1)} O(1) |
front() | 返回首元素 | O ( 1 ) {O(1)} O(1) |
back() | 返回尾元素 | O ( 1 ) {O(1)} O(1) |
empty() | 判断是否为空 | O ( 1 ) {O(1)} O(1) |
insert(it, n, x) | 向迭代器it指向的元素前插入n个x | O ( n ) {O(n)} O(n) |
erase(first, last) | 删除由迭代器first和last所指定的序列[first, last) | O ( n ) {O(n)} O(n) |
reserve(n) | 预分配缓冲空间,使存储空间至少可容纳n个元素 | O ( n ) {O(n)} O(n) |
swap(v) | 将s与另一个vector对象v进行交换 | O ( 1 ) {O(1)} O(1) |
assign(first, last) | 将序列替换成由迭代器first和last所指定的序列[first, last) | O ( n ) {O(n)} O(n) |
insert(it, first, last) | 将由迭代器first和last所指定的序列[first, last)插入到迭代器it 指向的元素前面 | O ( n ) {O(n)} O(n) |
resize(n, val) | 改变序列的长度,超出的元素将会被删除,如果序列需要扩展(原空间小于n), 将用val填满扩展出的空间 | O ( n ) {O(n)} O(n) |
使用,其他一些vector使用看上一节
#include
#include
using namespace std;
int main(){
vector<int> v1, v2;
for(int i = 0; i < 5; i++)
v1.push_back(i);
v1.insert(v1.begin() + 1, 2, 4); // 0 4 4 1 2 3 4
v1.erase(v1.begin() + 1, v1.begin() + 3);// 0 1 2 3 4
v1.insert(v1.begin(), v1.begin(), v1.end()); // 0 1 2 3 4 0 1 2 3 4
for(int i = 0; i < v1.size(); i++)
cout << v1[i] << " ";
cout << endl;
v2.assign(v1.begin(), v1.begin() + 5);
for(int i = 0; i < v2.size(); i++) // 0 1 2 3 4
cout << v2[i] << " ";
v1.swap(v2);
for(vector<int>::reverse_iterator rit = v1.rbegin(); rit != v1.rend(); rit++)
cout << *rit << " "; // 4 3 2 1 0
return 0;
}
list它就是个双向链表。每一个节点的内存都是独立的
list中的函数
函数 | 功能 | 复杂度 |
---|---|---|
size() | 返回大小 | O ( 1 ) {O(1)} O(1) |
begin() | 返回指开头的迭代器 | O ( 1 ) {O(1)} O(1) |
end() | 返回指末尾的迭代器 | O ( 1 ) {O(1)} O(1) |
push_back(e) | 尾部插入元素 | O ( 1 ) {O(1)} O(1) |
push_front(e) | 头部插入元素 | O ( 1 ) {O(1)} O(1) |
pop_front() | 头部删除元素 | O ( 1 ) {O(1)} O(1) |
pop_back() | 尾部删除元素 | O ( 1 ) {O(1)} O(1) |
insert(p, x) | p的位置插入x | O ( 1 ) {O(1)} O(1) |
insert(it, n, x) | 迭代器it位置插入n个x | O ( n ) {O(n)} O(n) |
clear() | 清楚所有 | O ( n ) {O(n)} O(n) |
erase§ | 删除p位置 | O ( n ) {O(n)} O(n) |
empty() | 判空 | O ( 1 ) {O(1)} O(1) |
sort() | 排序 | O ( n ) {O(n)} O(n) |
rbegin() | 上一个元素 | O ( n ) {O(n)} O(n) |
unique() | 删除重复重元素 | O ( n ) {O(n)} O(n) |
merge(l) | 合并 | O ( n ) {O(n)} O(n) |
使用
#include
#include
using namespace std;
int main(){
//初始化长度为2
list<int> ls(2);
//初始化为5个4
list<int> lst(5, 4);
//
list<int> ls1(ls.begin(), ls.end());
list<int> l1, l2, l3;
for(int i = 0; i < 5; i++){
l1.push_back(i);
}
for(int i = 0; i < 5; i++){
l2.push_back(i);
}
l1.merge(l2);
for(list<int>::iterator it = l1.begin(); it != l1.end(); it++){
cout << *it; //0011223344
}
l1.unique(); // 0 1 2 3 4
l1.reverse();// 4 3 2 1 0
l1.push_front(0);
// 反向迭代
for(list<int>::reverse_iterator rit= l1.rbegin(); rit != l1.rend(); rit++){
cout << *rit;
}
return 0;
}
deque是双端队列
deque中的函数
函数 | 功能 |
---|---|
size() | 返回大小 |
empty() | 判断是否为空 |
begin() | 返回首部 |
end() | 返回末尾 |
resize(n) | 重新分配大小 |
resize(n,val) | 改变序列的长度,超出的元素将会被删除,小于n 将用val填满 |
push_back(e) | 尾部插入元素 |
push_front(e) | 头部插入元素 |
pop_back() | 尾部删除元素 |
pop_front() | 头部删除元素 |
front() | 返回队头 |
back() | 返回队尾 |
insert(p,x) | p位置插入x |
insert(p, n, x) | p位置插入n个x |
insert(it, first, last) | 将由迭代器first和last所指定的序列[first, last)插入到迭代器it 指向的元素前面 |
erase§ | 删除 |
erase(begin, end) | 删除从begin到end位置的元素 |
使用
#include
#include
#include
using namespace std;
int main(){
deque<int> d;
for(int i = 0; i < 5; i++){
d.push_back(i);
}
d.push_front(2); // 2 0 1 2 3 4
d.insert(d.begin(), 1);// 1 2 0 1 2 3 4
d.insert(d.begin(), 3, 2); // 2 2 2 1 2 0 1 2 3 4
d.insert(d.begin(), d.begin(), d.end()); // 2 2 2 1 2 0 1 2 3 4 2 2 2 1 2 0 1 2 3 4
d.erase(d.begin(), d.begin() + 10); // 2 2 2 1 2 0 1 2 3 4
//遍历
for(deque<int>::iterator it = d.begin(); it != d.end(); it++){
cout << *it << " ";
}
cout << endl;
//反向迭代
for(deque<int>::reverse_iterator it = d.rbegin(); it != d.rend(); it++){
cout << *it << " ";
}
return 0;
}
关联式容器按元素的值来存储 包括 set 容器是保存关键字 map是保存键值对 但是一下的set, map容器有不同的特点
关键字有序无重复
- set
- map
关键字有序出现重复
- multiset
- multimap
关键字无序无重复
- unordered_set
- unordered_map
关键字无序有重复
- unordered_multiset
- unordered_multimap
他们的主要使用方法是一致的,只是对应的特性不同,通过
set
,map
的使用就能直到其他的使用方法,
set中的方法
函数名 | 功能 |
---|---|
clear() | 清空set |
end() | 返回指向末尾的迭代器最后一个元素的下一个 |
begin() | 返回指向开头的迭代器 |
erase(key) | 删除key |
find(key) | 搜索key返回指向key的迭代器 |
insert(key) | 向set中插入key |
rbegin() | 返回的是逆向的迭代器返回最后一个 |
rend() | 返回的是逆向的迭代器返回第一个的前一个 |
lower_bound(k) | 返回迭代器指向不小于k |
upper_bound(k) | 返回迭代器指向不大于k |
count() | 记数出现的次数 |
使用
#include
#include
#include
using namespace std;
int main(){
set<int> s;
for(int i = 0; i < 10; i++){
s.insert(i);
}
cout << s.size() << endl;
//找到2 - 6 之间的元素
set<int>::iterator lower = s.lower_bound(2);
set<int>::iterator upper = s.upper_bound(6);
//删除2 - 6 之间的元素
s.erase(lower, upper);
set<int>::iterator p = s.find(9);
if(p != s.end()) s.erase(p);
else cout << "Not exist";
for(set<int>::iterator it = s.begin(); it != s.end(); it++){
cout << *it << " "; // 1 7 8
}
for(set<int>::reverse_iterator rit = s.rbegin(); rit != s.rend(); rit++){
cout << *rit << " ";
}
s.clear();
if(s.empty()) cout << "Empty" << endl;
return 0;
}
map中的函数
函数名 | 功能 |
---|---|
clear() | 清空set |
end() | 返回指向末尾的迭代器最后一个元素的下一个 |
begin() | 返回指向开头的迭代器 |
erase(key) | 删除key |
find(key) | 搜索key返回指向key的迭代器 |
insert(key) | 向set中插入key |
rbegin() | 返回的是逆向的迭代器返回最后一个 |
rend() | 返回的是逆向的迭代器返回第一个的前一个 |
lower_bound(k) | 返回迭代器指向不小于k |
upper_bound(k) | 返回迭代器指向不大于k |
swap() | 两个map交换 |
count() | 指定元素出现的次数 |
使用
#include
#include
#include
using namespace std;
int main(){
map<int, string> m1;
//map的插入方法
m1[2] = "spring";
m1.insert(map<int, string>::value_type(3, "hi"));
m1.insert(pair<int, string>(4, "value"));
//遍历
for(map<int, string>::iterator it = m1.begin(); it !=m1.end(); it++){
cout << it->first << " "<< it->second << endl;
}
//查找key
map<int, string>::iterator pos = m1.find(2);
if(pos != m1.end()){
cout << pos->first << " " << pos->second << endl;
}else cout << "Not Exist";
map<int, string>::iterator lower = m1.lower_bound(2);
map<int, string>::iterator upper = m1.upper_bound(3);
m1.erase(lower, upper);
for(map<int, string>::iterator it = m1.begin(); it !=m1.end(); it++){
cout << it->first << " "<< it->second << endl;
}
// 反向迭代
for(auto rit = m1.rbegin(); rit != m1.rend(); rit++){
cout << rit->first << " " << rit->second << endl;
}
m1.clear();
return 0;
}
unordered_map于map的区别就是map 会按照键值对排序,所以 它是有序的, 同理set也会按照值的大小排序, unordered就是没有进行排序的,作题的时候如果出现超时的情况就考虑使用 unordered_map, unoredered_set,它们的速度更快
使用vector 、set 、 map等一系列容器时,注意begin
end
的位置 begin
指向的是第一个元素,而end
指向的是最后一个元素的后一位, 同理,rbegin
和 rend
如下图
iterator(迭代器)是用于访问容器中元素的指示器,从这个意义上说, iterator(迭代器)相当于数据结构中所说的“遍历指针”,也可以把 iterator(迭代器)看作是一种泛化的指针,STL中关于iterator(迭代器)实现是比骄傲复杂的,这里我们不去详细 讨论关于iterator(迭代器)的实现和使用,而只对iterator(迭代器)做一 点简单的介绍。
对迭代分类
- 输入iterator(迭代器),在容器的连续区间内向前移动,可以读取容器内任 意值; 输出iterator(迭代器),把值写进它所指向的容器中;
- 输出iterator(迭代器),把值写进它所指向的容器中
- 前向iterator(迭代器),读取队列中的值,并可以向前移动到下一位置
- 双向iterator(迭代器),读取队列中的值,并可以向前向后遍历容器;
- 随机访问iterator(迭代器), 可以直接以下标方式对容器进行访问, vector的iterator(迭代器)就是这种iterator(迭代器)
- 流iterator(迭代器),可以直接输出、输入流中的值;
#include
#include
#include
using namespace std;
int main(){
vector<int> v {1, 2, 3};
/**
vector的begin()和end()方法都会返回一个vector::iterator对象, 分别指向vector的
首元素位置和尾元素的下一个位置(我们可以称之为结束 标志位置)。 对一个
iterator(迭代器)对象的使用与一个指针变量的使用极为相似,或者 可以这样说,
指针就是一个非常标准的iterator(迭代器)。
**/
for(vector<int>::iterator it = v.begin(); it != v.end(); it++){
cout << *it << " ";
}
cout << endl;
/**
copy就是STL中定义的一个模板函数,copy(s.begin(), s.end(), ostream_iterator(cout, " "));
的意思是将由 s.begin()至s.end()(不含s.end())所指定的序列复制到标准输出流 cout
中,用" "作为每个元素的间隔。也就是说,这句话的作用其实就是将表 中的所有内
容依次输出
**/
copy(v.begin(), v.end(), ostream_iterator<int>(cout, " "));
return 0;
}
算法是一个非常使用的STL库 通过添加include
使用,C++中的算法库的功能是非常丰富的,我们选择常用的具体看看algorithm中有哪些使用的方法
sort这个方法在做题中常常用到,可以用来给数组或者容器排序
基本的使用
#include
#include
#include
using namespace std;
int main(){
int a[5] = {8, 1, 6, 0, 4};
// sort默认由小到大排序
sort(a, a + 5);
for(int i = 0; i < 5; i++){
cout << a[i] <<" ";
}
cout << endl;
vector<int> v = {3, 1, 6, 9, 4};
sort(v.begin(), v.end());
for(int i = 0; i < v.size(); i++){
cout << v[i] << " ";
}
return 0;
}
由大到小排序
#include
#include
#include
using namespace std;
//由大到小排序
bool cmp(int a, int b){
return a > b;
}
int main(){
vector<int> v = {3, 1, 6, 9, 4};
sort(v.begin(), v.end(), cmp);
for(int i = 0; i < v.size(); i++){
cout << v[i] << " ";
}
return 0;
}
比较结构体
如果让你排序成绩名单的成绩高的排名考前,如果出现成绩相同时, 按照姓排序 ,如果出现这种情况使用sort轻松解决
#include
#include
#include
using namespace std;
struct stu{
int score;
string name;
};
bool cmp(stu a, stu b){
return a.score == b.score ? a.name < b.name : a.score > b.score;
}
int main(){
vector<stu> v;
stu t;
for(int i = 0; i < 3; i++){
cin >> t.score >> t.name;
v.push_back(t);
}
sort(v.begin(), v.end(), cmp);
for(int i = 0; i < v.size(); i++){
cout << v[i].name << " " << v[i].score << endl;
}
return 0;
}
#include
#include
#include
using namespace std;
void display(vector<int> v){
for(int i = 0; i < v.size(); i++){
cout << v[i] << " ";
}
cout << endl;
}
int main(){
vector <int> v = {8, 2, 4, 5, 7};
sort(v.begin(), v.end());
reverse(v.begin(), v.end());
display(v); //8 7 5 4 2
string s = "81604284";
//反转字符串
reverse(s.begin(), s.begin() + 3); //61804284
cout << s;
}
fill用来给数组或者其他容器赋值
#include
#include
#include
#include
using namespace std;
void display(vector<int> v){
for(int i = 0; i < v.size(); i++){
cout << v[i] << " ";
}
cout << endl;
}
void display1(int* beg, int *en){
for(; beg != en; beg++){
cout << *beg << " ";
}
}
int main(){
vector <int> v(7); // 0 0 0 0 0 0 0
fill(v.begin(), v.begin() + 5, 2); // 2 2 2 2 2 0 0
int a[10];
//当你想给数组赋值的时候可以使用memset 但是这个方法只能赋值为 0
memset(a, 0, sizeof(a));
//使用fill赋值
fill(a, a + 10, 20);
display1(a, a + 10);
//如果是二维数组赋值时
int b[5][5];
fill(b[0], b[0] + 5 * 5, 2);
/* 2 2 2 2 2
2 2 2 2 2
2 2 2 2 2
2 2 2 2 2
*/
}
注意:二维数组的赋值正确方法是
fill(b[0], b[0] + 5 * 5, 2)
,而不是fill(b, b + 5 * 5, 2)
因为二维数组在内存里存储是线性的序列的一段从 b[0]的内存开始到n * n
的大小。
swap交换数值,手动写排序时用的还挺多的
#include
#include
#include
using namespace std;
int main(){
vector <int> v{8, 2, 1, 9, 3};
swap(v[1], v[3]);
cout << v[1] << " " << v[3]; // 9 2
}
返回两个值之间的最大值
cout << min(1, 2);
返回两个值之间的最大值
cout << max(3, 4);
#include
#include
#include
using namespace std;
int main(){
vector<int> v{10 ,2, 3, 4, 2, 3, 5, 2, 2};
replace(v.begin(), v.end(), 2, 50);
//将vector中等于2的值换成50
for(int i = 0; i < v.size(); i++) cout << v[i] << " ";// 10 50 3 4 50 3 5 50 50
return 0;
}
#include
#include
#include
using namespace std;
int main(){
vector<int> v{10 ,2, 3, 4, 2, 3, 5, 2, 2};
vector<int>::iterator it;
//查找2
it = find(v.begin(), v.end(), 2);
if(it != v.end()) cout << *it << endl;
else cout << "Not Exist" << endl;
return 0;
}
next_permutation
就是全排列的功能,这个功能非常的实用如果在数学问题中使用全排列就直接调用这个方法,比如这道题使用next_permutation
很快就解决啦
#include
#include
using namespace std;
int main(){
// 1. 全排列
string s1 = "1234", s2 = "8160";
do{
cout << s1 << endl;
}while(next_permutation(s1.begin(), s1.end()));
// 2.全排列
do{
cout << s2 << endl;
}while(prev_permutation(s2.begin(), s2.end()));
int a[3] = {0, 1, 2};
do{
cout << a[0] << a[1] << a[2] << endl;
}while(next_permutation(a, a + 3));
return 0;
}
#include
#include
#include // // std::plus
using namespace std;
int op_increase(int i) { return ++i;}
int main(){
string s ="hello";
/**
std::transform(first1, last1, result, op_increase);
first1, last1两个参数表示别改变的的是区间 [begin, end)
第三个指出变换后的结果存放的迭代器区间的首个元素的迭代器位置
第四个参数就是 对应的操作名称
**/
transform(s.begin() + 1, s.end(), s.begin(), ::toupper); // ELLOo
cout << s << endl;
vector<int> v1, v2 {10, 20, 30, 40};
v1.resize(v2.size());
transform(v2.begin(), v2.end(), v1.begin(), op_increase); // v1 : 11 21 31 41
/**
std::transform(first1, last1, first2, result, op);
其他参数意思一致
first2 要进行元素变换的第二个迭代器区间的首个元素的迭代器位置,
该区间的元素个数和第一个区间相等
**/
transform(v2.begin(), v2.end(), v1.begin(), v2.begin(), plus<int>()); //21 41 61 81
return 0;
}
algorithm
中包含许多其他功能的函数平时做题可能有的不是太多,具体使用可以参考官方文档
突然想起来,还有一个做题时用到的求gcd的方法
#include
using namespace std;
int gcd(int a, int b){
return b == 0 ? a : gcd(b, a % b);
}
int main(){
int a = 25, b = 50;
cout << gcd(a, b) << endl;
cout << __gcd(a, b) << endl;
}
C++11中添加 的实用的特性,做题时用的很多
int a;
cin >> a;
//包含在string类中
//将int类型转化为string类型
string s = to_string(a);
cout << s;
刚刚在使用容器的时候都可以使用auto
进行遍历 简化写法
#include
#include
#include
using namespace std;
int main(){
set<int> s;
s.insert(1);
s.insert(2);
//通过迭代器的方式进行遍历
for(set<int>::iterator it = s.begin(); it != s.end(); it++){
cout << *it;
}
// 实用auto的方式就是替代了迭代器中的类型声明,简化了写法
for(auto it = s.begin(); it != s.end(); it++){
cout << *it;
}
return 0;
}
#include
#include
#include
using namespace std;
int main(){
set<int> s;
s.insert(1);
s.insert(2);
//foreach
for(auto its : s){
cout << its;
}
//在数组中的使用方法
int a[5] = {8, 1, 6, 3, 2};
//遍历的元素的类型 别名 : 被遍历数组的名称
for(int i : a){
cout << i << " ";
}
//通过引用的方法可以改变数组中的值
for(int &i : a){
i *= 2;
}
return 0;
}
这种for循环通过不仅仅适用于数组,它也适用于STL中的容器,例如set map,使用C++ 11 中的
auto
,大大简化了容器的遍历写法.
stoi
的意思就是,string转化为int类型 ,类似于C中的atoi
, 同理还有
stod
——string to doublestof
——string to floatstold
——string to float doublestol
——string to longstoll
——string to long longstoul
——string to unsigned longstoull
——string to unsigned long long以上都是string类中的方法,string类看一会详细说道
#include
#include
using namespace std;
int main(){
string s = "008160";
int a = stoi(s);
cout << a; // 8160
string st = "1.32";
double b = stod(st);
cout << b; // 1.32
return 0;
}
注意 :
stoi
转化存在非法输入时, 例如stoi("0081.60")
- 截取前边的数字, 知道遇到的不是数字
- 如果前边不是数字,那么运行时出现错误
如果
stod
出现非法输入时,
- 自动截取去前面的浮点数,直到遇到的不满足浮点数为止
- 如果最前面是小数点,会自动转化前面添加0
- 如果前面不是数字或者小数点,那么运行时出现错误
把学的STL知识总结了一遍,还有不足的地方就日后补充在第三篇吧