1.实验任务1
程序源代码
1 #include <iostream> 2 #include <string> 3 #include <vector> 4 #include <algorithm> 5 6 template<typename T> 7 void output(const T& c); 8 9 void test1(); 10 void test2(); 11 void test3(); 12 13 int main() { 14 std::cout << "测试1: \n"; 15 test1(); 16 17 std::cout << "\n测试2: \n"; 18 test2(); 19 20 std::cout << "\n测试3: \n"; 21 test3(); 22 } 23 24 template<typename T> 25 void output(const T& c) { 26 for (auto &i : c) { 27 std::cout << i << ' '; 28 } 29 std::cout << '\n'; 30 } 31 32 void test1() { 33 std::string s0{ "0123456789" }; 34 std::cout << "s0 = " << s0 << std::endl; 35 36 std::string s1(s0); 37 std::reverse(s1.begin(), s1.end()); 38 std::cout << "s1 = " << s1 << std::endl; 39 40 std::string s2(s0.size(), ' '); 41 std::reverse_copy(s0.begin(), s0.end(), s2.begin()); 42 std::cout << "s2 = " << s2 << std::endl; 43 } 44 45 void test2() { 46 std::vector<int> v0{ 2,0,4,9 }; 47 std::cout << "v0: "; 48 output(v0); 49 50 std::vector<int> v1{ v0 }; 51 std::reverse(v1.begin(), v1.end()); 52 std::cout << "v1: "; 53 output(v1); 54 55 std::vector<int> v2{ v0 }; 56 std::reverse_copy(v0.begin(), v0.end(), v2.begin()); 57 std::cout << "v2: "; 58 output(v2); 59 } 60 61 void test3() { 62 std::vector<int> v0{ 0,1,2,3,4,5,6,7,8,9 }; 63 std::cout << "v0: "; 64 output(v0); 65 66 std::vector<int> v1{ v0 }; 67 std::rotate(v1.begin(), v1.begin() + 1, v1.end()); 68 std::cout << "v1: "; 69 output(v1); 70 71 std::vector<int> v2{ v0 }; 72 std::rotate(v2.begin(), v2.begin() + 2, v2.end()); 73 std::cout << "v2: "; 74 output(v2); 75 76 std::vector<int> v3{ v0 }; 77 std::rotate(v3.begin(), v3.end() - 1, v3.end()); 78 std::cout << "v3: "; 79 output(v3); 80 81 std::vector<int> v4{ v0 }; 82 std::rotate(v4.begin(), v4.end() - 2, v4.end()); 83 std::cout << "v4: "; 84 output(v4); 85 }
运行结果截图
问题1:reverse和reverse_copy有什么区别?
reverse用于直接修改原来容器中的元素使其倒序排列,而reverse_copy用于讲原容器中的元素反转后拷贝到另一容器中
问题2:rotate算法如何改变元素位置?他的三个参数分别代表什么?
rotate算法共有三个参数,rotate(first,middle,last),rotate算法将[first,middle)中的元素放置在[middle,last)区间中的元素后,同时保持两个范围内元素顺序,first和last是要旋转元素范围的迭代器对,middle是应出现在旋转范围开头的元素。
2.实验任务2
程序源代码
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 12 int generate_random_number(); 13 void test1(); 14 void test2(); 15 16 int main() { 17 std::srand(std::time(0)); 18 19 std::cout << "测试1: \n"; 20 test1(); 21 22 std::cout << "\n测试2: \n"; 23 test2(); 24 } 25 26 template<typename T> 27 void output(const T& c) { 28 for (auto& i : c) { 29 std::cout << i << ' '; 30 } 31 std::cout << '\n'; 32 } 33 34 int generate_random_number() { 35 return std::rand() % 101; 36 } 37 38 void test1() { 39 std::vector<int> v0(10); 40 std::generate(v0.begin(), v0.end(), generate_random_number); 41 std::cout << "v0: "; 42 output(v0); 43 44 std::vector<int> v1{ v0 }; 45 std::sort(v1.begin(), v1.end()); 46 std::cout << "v1: "; 47 output(v1); 48 49 std::vector<int> v2{ v0 }; 50 std::sort(v2.begin() + 1, v2.end() - 1); 51 std::cout << "v2: "; 52 output(v2); 53 } 54 55 void test2() { 56 std::vector<int> v0(10); 57 std::generate(v0.begin(), v0.end(), generate_random_number); 58 std::cout << "v0: "; 59 output(v0); 60 61 auto min_iter = std::min_element(v0.begin(), v0.end()); 62 auto max_iter = std::max_element(v0.begin(), v0.end()); 63 std::cout << "最小值: " << *min_iter << std::endl; 64 std::cout << "最大值: " << *max_iter << std::endl; 65 66 auto ans = std::minmax_element(v0.begin(), v0.end()); 67 std::cout << "最小值: " << *(ans.first) << std::endl; 68 std::cout << "最大值: " << *(ans.second) << std::endl; 69 70 double avg1 = std::accumulate(v0.begin(), v0.end(), 0.0) / v0.size(); 71 std::cout << "均值: " << std::fixed << std::setprecision(2) << avg1 << std::endl; 72 73 std::sort(v0.begin(), v0.end()); 74 double avg2 = std::accumulate(v0.begin() + 1, v0.end() - 1, 0.0) / (v0.size() - 2); 75 std::cout << "去掉最大值、最小值后均值: " << std::fixed << std::setprecision(2) << avg2 << std::endl; 76 }
运行结果截图
问题1:generate算法的作用是什么?
generate(first,last,g),将区间[first,last)内的每个元素赋值为给定函数对象g的生成值
问题2:minmax_element和分别调用min_element、max_element相比,有什么优势?
minmax_element只需遍历容器依次即可找出最小值和最大值,而分别调用min_element和max_element需要遍历两次,前者更加省时
问题3:观察不同写法效果是否等同
如图,能达到同样效果,lambda表达式可替代逻辑简单、代码量小的函数
3.实验任务3
程序源代码
1 #include <iostream> 2 #include <string> 3 #include <algorithm> 4 #include <cctype> 5 6 unsigned char func(unsigned char c); 7 void test1(); 8 void test2(); 9 10 int main() { 11 std::cout << "测试1:字符串大小写转换\n"; 12 test1(); 13 14 std::cout << "\n测试2:字符变换\n"; 15 test2(); 16 } 17 18 unsigned char func(unsigned char c) { 19 if (c == 'z') { 20 return 'a'; 21 } 22 23 if (c == 'Z') { 24 return 'Z'; 25 } 26 27 if (std::isalpha(c)) { 28 return static_cast<unsigned char>(c + 1); 29 } 30 31 return c; 32 } 33 34 void test1() { 35 std::string s1{ "Hello World 2049!" }; 36 std::cout << "s1 = " << s1 << '\n'; 37 38 std::string s2; 39 for (auto c : s1) { 40 s2 += tolower(c); 41 } 42 std::cout << "s2 = " << s2 << '\n'; 43 44 std::string s3; 45 for (auto c : s1) { 46 s3 += toupper(c); 47 } 48 std::cout << "s3 = " << s3 << '\n'; 49 } 50 51 void test2() { 52 std::string s1{ "I love cosmos!" }; 53 std::cout << "s1 = " << s1 << '\n'; 54 55 std::string s2(s1.size(), ' '); 56 std::transform( 57 s1.begin(), s1.end(), 58 s2.begin(), 59 func); 60 std::cout << "s2 = " << s2 << '\n'; 61 }
运行结果截图
问题1:func功能是什么?
功能是对所有字符进行循环后移一位的操作,如果是z和Z,分别变换为a和A
问题2:tolower和toupper的功能
tolower将字母转化成其对应的小写字母,toupper将字母转化成其对应的大写字母
问题3:transform参数含义及参数修改变化
transform(first1,last1,first2,unary_op),first1和last1是要转换元素源范围的迭代器对,first2是要转换的第二个元素范围的开头,unary_op是一元操作函数对象
把实验中s2.begin()改成s1.begin(),直接在原容器s1中进行元素覆盖存储,s1原元素丢失
4.实验任务4
程序源代码
1 #include <iostream> 2 #include <string> 3 #include <algorithm> 4 5 bool is_palindrome(const std::string& s); 6 bool is_palindrome_ignore_case(const std::string& s); 7 8 int main() { 9 std::string s; 10 while (std::cin >> s) { 11 std::cout << std::boolalpha 12 << "区分大小写: " << is_palindrome(s) << "\n" 13 << "不区分大小写: " << is_palindrome_ignore_case(s) << "\n\n"; 14 } 15 } 16 17 bool is_palindrome(const std::string& s) { 18 int i = 0; 19 int j = s.size()-1; 20 while (i < j) { 21 if (s[i] == s[j]) { 22 i++; 23 j--; 24 } 25 else { 26 return false; 27 } 28 } 29 return true; 30 } 31 32 bool is_palindrome_ignore_case(const std::string& s) { 33 std::string s1; 34 for (auto i : s) { 35 s1 += tolower(i); 36 } 37 return is_palindrome(s1); 38 }
运行结果截图
当输入的字符串中含有空格,可将std::cin>>n改为std::getline(std::cin,s),运行结果如下
5.实验任务5
程序源代码
1 #include <iostream> 2 #include <string> 3 #include <algorithm> 4 5 std::string dec2n(int x, int n = 2); 6 7 int main() { 8 int x; 9 while (std::cin >> x) { 10 std::cout << "十进制: " << x << '\n' 11 << "二进制: " << dec2n(x) << '\n' 12 << "八进制: " << dec2n(x, 8) << '\n' 13 << "十二进制: " << dec2n(x, 12) << '\n' 14 << "十六进制: " << dec2n(x, 16) << '\n' 15 << "三十二进制: " << dec2n(x, 32) << "\n\n"; 16 } 17 } 18 19 std::string dec2n(int x, int n) { 20 if (x == 0) { 21 return "0"; 22 } 23 24 std::string result; 25 std::string base{ "0123456789ABCDEFGHIGKLMNOPQRSTUVWXYZ" }; 26 while (x) { 27 int temp = x % n; 28 result += base[temp]; 29 x /= n; 30 } 31 std::reverse(result.begin(), result.end()); 32 return result; 33 }
运行结果截图
6.实验任务6
程序源代码
1 #include <iostream> 2 #include <string> 3 #include <algorithm> 4 #include <iomanip> 5 6 int main() { 7 std::string base; 8 for (int i = 0; i < 26; i++) { 9 base += static_cast<char>(97 + i); 10 } 11 12 std::cout << " "; 13 for (int i = 0; i < 26; i++) { 14 std::cout << base[i] << " "; 15 } 16 std::cout << std::endl; 17 18 for (int i = 1; i <= 26; i++) { 19 std::cout << std::setw(2) << i << " "; 20 std::rotate(base.begin(), base.begin() + 1, base.end()); 21 for (int j = 0; j < 26; j++) { 22 std::cout << static_cast<char>(toupper(base[j])) << " "; 23 } 24 std::cout << std::endl; 25 } 26 }
运行结果截图
7.实验任务7
程序源代码
1 #include <iostream> 2 #include <vector> 3 #include <ctime> 4 #include <cstdlib> 5 #include <iomanip> 6 7 int get_random_number(int left,int right); 8 char get_random_op(); 9 int calculate(int left,int right,char op); 10 11 int main() { 12 std::srand(std::time(0)); 13 int correct_count = 0; 14 int ans; 15 for (int i = 0; i < 10; i++) { 16 int left; 17 int right; 18 char op; 19 while (1) { 20 left = get_random_number(1, 10); 21 right = get_random_number(1, 10); 22 op = get_random_op(); 23 24 if (op == '+' || op == '*' || (op == '-' && left >= right) || (op == '/' && left % right == 0)) { 25 break; 26 } 27 } 28 std::cout << left << " " << op << " " << right << " ="; 29 30 std::cin >> ans; 31 if (ans == calculate(left, right, op)) { 32 correct_count++; 33 } 34 } 35 std::cout << "正确率:" << std::fixed << std::setprecision(2) << static_cast<double>(correct_count * 10) << "%"; 36 } 37 38 int get_random_number(int left, int right) { 39 return left + std::rand() % 10; 40 } 41 42 char get_random_op() { 43 std::vector<char> v{ '+','-','*','/' }; 44 return v[std::rand() % 4]; 45 } 46 47 int calculate(int left,int right,char op) { 48 if (op == '+') { 49 return left + right; 50 } 51 if (op == '-') { 52 return left - right; 53 } 54 if (op == '*') { 55 return left * right; 56 } 57 if (op == '/') { 58 return left / right; 59 } 60 }
运行结果截图
实验总结
本次实验中,我学会了一系列算法的运用,如rotate、accumulate、generate等,也学会了如何去分析问题,层层深入,理解需求、分析需求、解决需求。