1.这个容器的知识点比较杂
迭代器的理解:
1.erase()函数的返回值,它的迭代器在循环遍历中的奇特之处;
1 #define _CRT_SECURE_NO_WARNINGS 2 #include <iostream> 3 #include <vector> 4 #include <list> 5 #include <algorithm> 6 #include <numeric> 7 #include <functional> 8 9 using namespace std; 10 11 /* 12 int ia[] = { 0, 1, 1, 2, 3, 5, 8, 13, 21, 55, 99}; 13 要求: 14 (1)将ia复制到一个vector容器vec中和一个list容器中lst中。 15 (2)将vec容器中的奇数值元素删除。 16 (3)使用内置算法计算vec窗器所有元素的和。Accumulate 17 (4)使用内置算法计算lst容器中大于5的元素的个数 count_if 18 19 */ 20 21 //lambda 表达式 22 // [](参数列表)->返回值 {函数体} 23 24 25 void print(int val) //回调函数 26 { 27 cout << val << " "; 28 } 29 //打印的三种方式(回调函数、函数对象、兰巴达表达式) 30 struct PRINT 31 { 32 void operator()(int val) 33 { 34 cout << val << " "; 35 } 36 }; 37 void printVec(vector<int>& v) 38 { 39 for_each(v.begin(), v.end(), [](int val){cout << val << " "; }); //采用兰博打表达式 40 cout << endl; 41 } 42 43 void printList(list<int>& L) //这里采用了回调函数,函数对象 44 { 45 //for_each(L.begin(), L.end(), PRINT()); //回调函数对象 46 for_each(L.begin(), L.end(), print); //回调函数 47 cout << endl; 48 } 49 50 class isGreat 51 { 52 public: 53 bool operator()(int val) 54 { 55 if (val > 5) 56 return true; 57 else 58 return false; 59 } 60 }; 61 void test04(int* arr, int len) 62 { 63 vector<int> v1; 64 list<int> l1; 65 v1.assign(arr, arr + len - 1); //将数组中的元素拷贝进容器中(第一种方法) 66 //将一个容器中的元素拷贝进另一个容器(第二种方法) 67 for (int val : v1) //C++11的表达式;此处的v1可以是数组或容器 68 { 69 l1.push_back(val); 70 } 71 //打印 72 printVec(v1); 73 printList(l1); 74 75 //(2)将vec容器中的奇数值元素删除。 erase 76 vector<int>::iterator it = v1.begin(); 77 for (; it != v1.end(); ) 78 { 79 if (*it % 2 != 0) 80 { 81 it = v1.erase(it); //这里关注 erase 的返回值,是一个迭代器。 82 //it--; //这种方法不对,有bug;它是将迭代器的移动还放在for循环的位置(正常放置),但是当第一个元素符合条件时,这种方法就出错,因为迭代器减小后,就越界了。 83 } 84 else //同时还有这步,将迭代器的移动放到下面。(这种属于通用方法,但是我还没有想懂,它删除后迭代器是如何移动的)(现在搞懂了,在线面有详细描述) 85 { 86 it++; 87 } 88 } 89 printVec(v1); 90 91 //(3)使用内置算法计算vec窗器所有元素的和。Accumulate 92 auto it1 = v1.begin(); //auto可以自动推导变量的类型。 93 auto sum = accumulate(it1, v1.end(), 0); //第三个参数为:求和的基数;即容器中所有的元素的和加上它就是最后的总和。 94 95 //(4)使用内置算法计算lst容器中大于5的元素的个数 96 int num = count_if(l1.begin(), l1.end(), isGreat()); 97 cout << num << endl; 98 } 99 100 int main() 101 { 102 int ia[] = { 0, 1, 1, 2, 3, 5, 8, 13, 21, 55, 99 }; 103 int len = sizeof(ia) / sizeof(int); 104 test04(ia, len); 105 106 system("pause"); 107 return EXIT_SUCCESS; 108 }
1.这个题 的知识点:
1)vector容器在遍历的时候删除元素;这个和 erase()函数的返回值有关
2) erase()函数的返回值;(这个最重要)
3)一个容器中元素拷贝到不同类型的容器中(三种方法,一种没写,为普通的for循环遍历)
4)打印容器元素的三种方法:(回调函数,函数对象,兰巴达表达式)
5)STL的求和函数 accumulate(),第三个参数的作用;
6)auto类型;可以自动推导变量的类型
7)查找count_if()函数的使用,第三个参数的作用。
2.循环遍历,it++放置不同的位置;
1)在正常的for循环位置
1)符合条件时erase()容器中的某个元素,但是没有接返回值
2)符合条件时erase()容器中的某个元素,接了返回值;
3)符合条件时,接了返回值,同时在下面接着 it--;看容器首位元素符合条件和不符合条件的两种情况。
2)不放在正常位置
1)放在不符合条件的情况下it++;(即正确的情况,上面的那段代码)。
1 void test01(vector<int> v) 2 { //这段代码会报错,因为当进行 erase() 后, 当前迭代器就失效了。而这里对它进行了++操作,所以程序崩溃 3 for (vector<int>::iterator it = v.begin(); it != v.end(); it++) 4 { 5 if (*it % 2 != 0) 6 { 7 v.erase(it); 8 } 9 } 10 } 11 12 void test02(vector<int> v) 13 { 14 for (vector<int>::iterator it = v.begin(); it != v.end(); it++) 15 { //这段代码也会崩溃,erase()函数的返回值被接收,此时假如最后一个数据也符合条件,代码运行到最后的数据,也会崩溃。 16 if (*it % 2 != 0) 17 { 18 it = v.erase(it); 19 } 20 } 21 } 22 23 for (vector<int>::iterator it = v.begin(); it != v1.end(); it++) 24 { 25 cout << *it << " "; 26 if (*it % 2 != 0) 27 { 28 v1.erase(it); //这里关注 erase 的返回值,是一个迭代器。如果接受这个迭代器,那么此时它就指向删除元素的下一个元素。 29 it--; //这种方法不对,有bug;它是将迭代器的移动还放在for循环的位置(正常放置),但是当第一个元素符合条件时,这种方法就出错,因为迭代器减小后,就越界了。 30 } //但是假如第一个数据不符合条件就没有问题。 31 }
1 /* 2 vector<int> 容器 erase() 的返回值为"当前位置的"迭代器;它是这样理解的;假如你不接返回值,那么遍历循环时,删除后的当前迭代器 3 值失效,而你接下来还对它进行了操作,编译器马上段错误。 4 当你对它的返回值接收后,(就像紧密排列在一起的球,拿掉其中的一个,下一个立刻补上,);虽然返回的是同一个位置的迭代器,但是它 5 值已经发生变化,(相对于原来的容器来说,他就返回了属于后一个值得迭代器。)而这个迭代器是有效的,你可以对它进行操作。(但是此时 6 还有一些额外情况,例如:当容器最后一个数据符合条件,它的迭代器被删除,而又被接到返回值,此时这个迭代器就是尾部的 end()迭代器, 7 假如遍历的循环,第三个条件还写在与原来的位置,如(++操作),此时就会发生迭代器的越界,编译器出现段错误。(在下面有实例)。 8 9 */
3.sort算法排序【包含:函数对象(仿函数)】;
1 #define _CRT_SECURE_NO_WARNINGS 2 #include<iostream> 3 #include<vector> 4 #include<algorithm> 5 #include<functional> 6 #include<string> 7 using namespace std; 8 9 //sort排序算法 10 struct for_each_condition{ 11 void operator()(int val){ 12 cout << val << " "; 13 } 14 }; 15 void test01(){ 16 17 vector<int> v; 18 v.push_back(10); 19 v.push_back(20); 20 v.push_back(80); 21 v.push_back(90); 22 v.push_back(50); 23 v.push_back(40); 24 25 for_each(v.begin(), v.end(), for_each_condition()); cout << endl; 26 sort(v.begin(), v.end(), less<int>()); 27 for_each(v.begin(), v.end(), for_each_condition()); cout << endl; 28 sort(v.begin(), v.end(), greater<int>()); 29 for_each(v.begin(), v.end(), for_each_condition()); cout << endl; 30 } 31 32 class Person{ 33 public: 34 Person(string name, int age){ 35 this->mName = name; 36 this->mAge = age; 37 } 38 bool operator==(const Person& p){ 39 if (p.mName == this->mName && this->mAge == p.mAge){ 40 return true; 41 } 42 return false; 43 } 44 public: 45 string mName; 46 int mAge; 47 }; 48 49 //排序对象 50 struct for_each_condition_obj{ 51 void operator()(Person& val){ 52 cout << "Name:" << val.mName << " Age:" << val.mAge << endl; 53 } 54 }; 55 struct sort_condition{ 56 bool operator()(Person& p1, Person& p2){ 57 return p1.mAge > p2.mAge; 58 } 59 }; 60 void test02(){ 61 62 vector<Person> v; 63 v.push_back(Person("john01", 30)); 64 v.push_back(Person("john03", 32)); 65 v.push_back(Person("john05", 34)); 66 v.push_back(Person("john02", 31)); 67 v.push_back(Person("john06", 35)); 68 v.push_back(Person("john03", 32)); 69 70 for_each(v.begin(), v.end(), for_each_condition_obj()); cout << endl; 71 sort(v.begin(), v.end(), sort_condition()); 72 for_each(v.begin(), v.end(), for_each_condition_obj()); cout << endl; 73 } 74 int main(){ 75 76 //test01(); 77 test02(); 78 79 system("pause"); 80 return EXIT_SUCCESS; 81 }