1.实验任务一:
**reverse和reverse_copy有什么区别?**
答:reverse和reverse_copy都是将一个容器里的元素倒置,区别在于前者是将倒置后的新序列依旧存储在原来的容器中,而后者是将倒置后的序列放在一个新的容器中,并且保持元来的容器的序列顺序不变。
**rotate算法是如何改变元素顺序的?它的三个参数分别代表什么?**
答:rotate是将容器里的元素分成左右两部分,将左边部分的元素不改变原来的相对顺序地移到右边部分的后面,这样就实现了循环移动的效果。
rotate的三个参数依次分别代表:左边部分的起始元素的位置,右边部分起始元素的位置(也是左边部分最后一个元素的后一个元素的位置),以及右边部分的最后一个元素的后一个元素的位置。

1 // 现代C++标准库、算法库体验 2 // 本例用到以下内容: 3 // 1. 字符串string, 动态数组容器类vector、迭代器 4 // 2. 算法库:反转元素次序、旋转元素 5 // 3. 函数模板、const引用作为形参 6 #include <iostream> 7 #include <string> 8 #include <vector> 9 #include <algorithm> 10 // 模板函数声明 11 template<typename T> 12 void output(const T& c); 13 void test1(); 14 void test2(); 15 void test3(); 16 int main() { 17 std::cout << "测试1: \n"; 18 test1(); 19 std::cout << "\n测试2: \n"; 20 test2(); 21 std::cout << "\n测试3: \n"; 22 test3(); 23 } 24 // 输出容器对象c中的元素 25 template <typename T> 26 void output(const T& c) { 27 for (auto& i : c) 28 std::cout << i << ' '; 29 std::cout << '\n'; 30 } 31 // 测试1:组合使用算法库、迭代器、string反转字符串 32 void test1() { 33 using namespace std; 34 string s0{ "0123456789" }; 35 cout << "s0 = " << s0 << endl; 36 string s1(s0); 37 // 反转s1自身 38 reverse(s1.begin(), s1.end()); 39 cout << "s1 = " << s1 << endl; 40 string s2(s0.size(), ' '); 41 // 将s0反转后结果拷贝到s2, s0自身不变 42 reverse_copy(s0.begin(), s0.end(), s2.begin()); 43 cout << "s2 = " << s2 << endl; 44 } 45 // 测试2:组合使用算法库、迭代器、vector反转动态数组对象vector内数据 46 void test2() { 47 using namespace std; 48 vector<int> v0{ 2, 0, 4, 9 }; 49 cout << "v0: "; output(v0); 50 vector<int> v1{ v0 }; 51 reverse(v1.begin(), v1.end()); 52 cout << "v1: "; output(v1); 53 vector<int> v2{ v0 }; 54 reverse_copy(v0.begin(), v0.end(), v2.begin()); 55 cout << "v2: "; output(v2); 56 } 57 // 测试3:组合使用算法库、迭代器、vector实现元素旋转移位 58 void test3() { 59 using namespace std; 60 vector<int> v0{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 61 cout << "v0: "; output(v0); 62 vector<int> v1{ v0 }; 63 // 将[v1.begin(), v1.end())区间内元素循环左移1位 64 rotate(v1.begin(), v1.begin() + 1, v1.end()); 65 cout << "v1: "; output(v1); 66 vector<int> v2{ v0 }; 67 // 将[v1.begin(), v1.end())区间内元素循环左移2位 68 rotate(v2.begin(), v2.begin() + 2, v2.end()); 69 cout << "v2: "; output(v2); 70 vector<int> v3{ v0 }; 71 // 将[v1.begin(), v1.end())区间内元素循环右移1位 72 rotate(v3.begin(), v3.end() - 1, v3.end()); 73 cout << "v3: "; output(v3); 74 vector<int> v4{ v0 }; 75 // 将[v1.begin(), v1.end())区间内元素循环右移2位 76 rotate(v4.begin(), v4.end() - 2, v4.end()); 77 cout << "v4: "; output(v4); 78 }
2.实验任务二:
**generate算法的作用是什么?**
答:generate通过生成器函数可以将一个容器中指定范围内的元素进行赋值。
**minmax_element和分别调用min_element、max_element相比,有什么优势?**
答:(1)minmax_element将最小值和最大值的迭代器“打包”在一起,方便后续的管理和操作,不需要独立的管理两个本来关系紧密的两个变量。
(2)代码更简洁,而且只需要调用一个函数,减少了函数调用的开销
(3)一样的
**查询generate第3个参数[](){return std::rand()%101;}用法,与使用自定义函数generate_random_number相比,lambda表达式适用场景是什么?**
答:lamda表达式更加的轻量化,在只需要调用一次的场景中,使用lanmda表达式更方便简洁。二generate_random_number更适合需要多次调用的场景。

1 #include <iostream> 2 #include <vector> 3 #include <algorithm> 4 #include <numeric> 5 #include <iomanip> 6 #include <cstdlib> 7 #include <ctime> 8 // 模板函数声明 9 template<typename T> 10 void output(const T& c); 11 int generate_random_number(); 12 void test1(); 13 void test2(); 14 int main() { 15 std::srand(std::time(0));// 添加随机种子 16 std::cout << "测试1: \n"; 17 test1(); 18 std::cout << "\n测试2: \n"; 19 test2(); 20 } 21 // 输出容器对象c中的元素 22 template <typename T> 23 void output(const T& c) { 24 for (auto& i : c) 25 std::cout << i << ' '; 26 std::cout << '\n'; 27 } 28 // 返回[0, 100]区间内的一个随机整数 29 int generate_random_number() { 30 return std::rand() % 101; 31 } 32 // 测试1:对容器类对象指定迭代器区间赋值、排序 33 void test1() { 34 using namespace std; 35 vector<int> v0(10);//创建一个动态数组对象v0, 对象大小为10 36 generate(v0.begin(), v0.end(), generate_random_number); // 生成随机数填充v0 37 cout << "v0: "; output(v0); 38 vector<int> v1{ v0 }; 39 sort(v1.begin(), v1.end()); // 对整个vector排序 40 cout << "v1: "; output(v1); 41 vector<int> v2{ v0 }; 42 sort(v2.begin() + 1, v2.end() - 1); // 只对中间部分排序,不包含首尾元素 43 cout << "v2: "; output(v2); 44 } 45 // 测试2:对容器类对象指定迭代器区间赋值、计算最大值/最小值/均值 46 void test2() { 47 using namespace std; 48 vector<int> v0(10); 49 generate(v0.begin(), v0.end(), generate_random_number); 50 cout << "v0: "; output(v0); 51 // 求最大值和最小值 52 auto min_iter = min_element(v0.begin(), v0.end()); 53 auto max_iter = max_element(v0.begin(), v0.end()); 54 cout << "最小值: " << *min_iter << endl; 55 cout << "最大值: " << *max_iter << endl; 56 // 同时求最大值和最小值 57 auto ans = minmax_element(v0.begin(), v0.end()); 58 cout << "最小值: " << *(ans.first) << endl; 59 cout << "最大值: " << *(ans.second) << endl; 60 // 求平均值 61 double avg1 = accumulate(v0.begin(), v0.end(), 0.0) / v0.size(); 62 cout << "均值: " << fixed << setprecision(2) << avg1 << endl; 63 sort(v0.begin(), v0.end()); 64 double avg2 = accumulate(v0.begin() + 1, v0.end() - 1, 0.0) / (v0.size() - 2); 65 cout << "去掉最大值、最小值之后,均值: " << avg2 << endl; 66 }
3.实验任务三:
**自定义函数func功能是什么?**
答:将一个序列里的大写或小写字母变成它26个字母表中的下一个字母,其中z(z)变成a(A)。
**tolower和toupper功能分别是什么?**
答:tolower:将一个字母变成小写,toupper:将一个字母变成大学。
**transform的4个参数意义分别是什么?如果把第3个参数s2.begin()改成s1.s1.begin()**
答:参数一:需要改变的序列的起始位置;参数二:需要改变的序列的最后一个元素的后一个元素的位置,参数三:改变后的元素存放的首位置;参数四:函数对象,处理元素的函数。
改成s1.begin()之后改变的元素都依然存储在s1序列中,相当于s1被改变了
没改之前,就是s1的每个元素都通过函数对象发生改变后存储在了s2里,而s1本身没有发生任何变化。

1 #include <iostream> 2 #include <string> 3 #include <algorithm> 4 #include <cctype> 5 unsigned char func(unsigned char c); 6 void test1(); 7 void test2(); 8 int main() { 9 std::cout << "测试1: 字符串大小写转换\n"; 10 test1(); 11 std::cout << "\n测试2: 字符变换\n"; 12 test2(); 13 } 14 unsigned char func(unsigned char c) { 15 if (c == 'z') 16 return 'a'; 17 18 if (c == 'Z') 19 return 'A'; 20 21 if (std::isalpha(c)) 22 return static_cast<unsigned char>(c + 1); 23 24 return c; 25 } 26 void test1() { 27 std::string s1{ "Hello World 2049!" }; 28 std::cout << "s1 = " << s1 << '\n'; 29 std::string s2; 30 for (auto c : s1) 31 s2 += std::tolower(c); 32 std::cout << "s2 = " << s2 << '\n'; 33 std::string s3; 34 for (auto c : s1) 35 s3 += std::toupper(c); 36 std::cout << "s3 = " << s3 << '\n'; 37 } 38 void test2() { 39 std::string s1{ "I love cosmos!" }; 40 std::cout << "s1 = " << s1 << '\n'; 41 42 std::string s2(s1.size(), ' '); 43 std::transform(s1.begin(), s1.end(), 44 s2.begin(), 45 func); 46 std::cout << "s2 = " << s2 << '\n'; 47 }
4.实验任务四:

1 #include <iostream> 2 #include <string> 3 #include <algorithm> 4 using namespace std; 5 bool is_palindrome(const std::string& s); 6 bool is_palindrome_ignore_case(const std::string& s); 7 int main() { 8 using namespace std; 9 string s; 10 // 多组输入,直到按下Ctrl+Z结束测试 11 while (cin >> s) { 12 cout << boolalpha 13 << "区分大小写: " << is_palindrome(s) << "\n" 14 << "不区分大小写: " << is_palindrome_ignore_case(s) << "\n\n"; 15 } 16 } 17 // 函数is_palindrome定义 18 bool is_palindrome(const string& s) 19 { 20 string temp{ s }; 21 reverse_copy(s.begin(), s.end(), temp.begin()); 22 if (s == temp) 23 return true; 24 else 25 return false; 26 } 27 bool is_palindrome_ignore_case(const std::string& s) 28 { 29 string temp{ s }; 30 transform(s.begin(), s.end(), temp.begin(), toupper);//将传s全部变成大写 31 return is_palindrome(temp); 32 } 33 // ×××
**使用cin >> s输入时,输入的字符串中不能包含空格。如果希望测试字符串包含空格(如hello oop),代码应如何调整?
答:(1)可以使用getline(std::cin,s)来代替 cin <<s。
1 while (getline(cin,s)) { 2 cout << boolalpha 3 << "区分大小写: " << is_palindrome(s) << "\n" 4 << "不区分大小写: " << is_palindrome_ignore_case(s) << "\n\n"; 5 }
(2) 可以使用std::cin.get(c);s+=c;逐字符的输入。
5.实验任务五:
#include <iostream> #include <string> #include <algorithm> using namespace std; std::string dec2n(int x, int n = 2); int main() {int x;while (std::cin >> x) {std::cout << "十进制: " << x << '\n'<< "二进制: " << dec2n(x) << '\n'<< "八进制: " << dec2n(x, 8) << '\n'<< "十二进制: " << dec2n(x, 12) << '\n'<< "十六进制: " << dec2n(x, 16) << '\n'<< "三十二进制: " << dec2n(x, 32) << "\n\n";} } // 函数dec2n定义 std::string dec2n(int x, int n ) {string trans{ "0123456789abcdefghijklmnopqrstuvwxyz" };string result;while (x){result += trans[x % n];x = x / n;}if (result.empty())return "0";reverse(result.begin(), result.end());return result; } // ×××
6.实验任务六:
1 #include<iostream> 2 #include<algorithm> 3 #include<iomanip> 4 using namespace std; 5 int main() 6 { 7 string s{ "BCDEFGHIJKLMNOPQRSTUVWXYZA" }; 8 string t{ "abcdefghijklmnopqrstuvwxyz" }; 9 cout << " "; 10 for (char item : t) 11 cout << item << ' '; 12 cout << '\b' << '\n'; 13 for (int i = 1; i <= 26; i++) 14 { 15 cout <<setw(2)<<right<< i << ' '; 16 for (char item : s) 17 cout << item << ' '; 18 cout << '\b' << '\n'; 19 rotate(s.begin(), s.begin() + 1, s.end()); 20 } 21 return 0; 22 }
7.实验任务七:

1 #include<iostream> 2 #include<cstdlib> 3 #include<ctime> 4 #include<string> 5 #include<iomanip> 6 using namespace std; 7 int get_rand_range(int min, int max); 8 bool generate_rand_arith(); 9 int main() 10 { 11 srand(static_cast<unsigned int>(time(0))); 12 int sum = 10, num = 0; 13 double percent; 14 for (int i = 1; i <= sum; i++) 15 { 16 num+=generate_rand_arith(); 17 } 18 percent = double(num) / sum * 100; 19 cout << "正确率 :" << fixed << setprecision(2) << percent << "%" << '\n'; 20 return 0; 21 } 22 bool generate_rand_arith() 23 { 24 string s{ "=+-*/" }; 25 int k,m,n; 26 int result; 27 k = get_rand_range(1, 4); 28 m = get_rand_range(1, 10); 29 n = get_rand_range(1, 10); 30 if (k == 2) 31 { 32 if (m < n) 33 { 34 int temp = m; 35 m = n; 36 n = temp; 37 } 38 } 39 if(k == 4) 40 while (m % n != 0) 41 { 42 m = get_rand_range(1, 10); 43 n = get_rand_range(1, 10); 44 } 45 cout << m << ' ' << s[k] << ' ' << n << ' ' << s[0]; 46 cin >> result; 47 switch (k) 48 { 49 case 1: 50 if (result == m + n) 51 return true; 52 break; 53 case 2: 54 if (result == m - n) 55 return true; 56 break; 57 case 3: 58 if (result == m * n) 59 return true; 60 break; 61 case 4: 62 if (result == m / n) 63 return true; 64 } 65 return false; 66 } 67 int get_rand_range(int min,int max) 68 { 69 if (min > max) 70 { 71 int temp = max; 72 max = min; 73 min = temp; 74 } 75 return min + rand()%(max - min +1); 76 }