实验1 现代C++编程初体验
实验任务1:
task1源代码:

1 #include<iostream> 2 #include<string> 3 #include<vector> 4 #include<algorithm> 5 6 //模板函数声明 7 template<typename T> 8 void output(const T &c); 9 10 void test1(); 11 void test2(); 12 void test3(); 13 14 int main() 15 { 16 std::cout << "测试1:\n"; 17 test1(); 18 19 std::cout << "\n测试2:\n"; 20 test2(); 21 22 std::cout << "\n测试3:\n"; 23 test3(); 24 } 25 26 //输出容器对象c中的元素 27 template <typename T> 28 void output(const T &c) 29 { 30 for(auto &i : c) 31 std::cout << i << ' '; 32 std::cout << '\n'; 33 } 34 35 //测试1:组合使用算法库、迭代器、string反转字符串 36 void test1() 37 { 38 using namespace std; 39 40 string s0{"0123456789"}; 41 cout << "s0 = " << s0 << endl; 42 43 string s1(s0); 44 //反转s1自身 45 reverse(s1.begin(),s1.end()); 46 cout << "s1 = " << s1 << endl; 47 48 string s2(s0.size(),' '); 49 //将s0反转后结果拷贝至s2,s0自身不变 50 reverse_copy(s0.begin(),s0.end(),s2.begin()); 51 cout << "s2 = " << s2 << endl; 52 } 53 54 //测试2:组合使用算法库、迭代器、vector反转动态数组对象vector内数据 55 void test2() 56 { 57 using namespace std; 58 59 vector<int> v0{2, 0, 4, 9}; 60 cout << "v0: ";output(v0); 61 vector<int> v1{v0}; 62 reverse(v1.begin(),v1.end()); 63 cout << "v1: ";output(v1); 64 65 vector<int> v2{v0}; 66 reverse_copy(v0.begin(),v0.end(),v2.begin()); 67 cout << "v2: ";output(v2); 68 } 69 70 //测试3:组合使用算法库、迭代器、vector实现元素旋转位 71 void test3() 72 { 73 using namespace std; 74 75 vector<int> v0{0, 1, 2, 3, 4, 5, 6, 7 ,8, 9}; 76 cout << "v0: ";output(v0); 77 78 vector<int> v1{v0}; 79 // 将[v1.begin(),v1.end()] 区间内元素循环左移1位 80 rotate(v1.begin(),v1.begin()+1,v1.end()); 81 cout << "v1: ";output(v1); 82 83 vector<int> v2{v0}; 84 // 将[v1.begin(),v1.end()] 区间内元素循环左移2位 85 rotate(v2.begin(),v2.begin()+2,v2.end()); 86 cout << "v2: ";output(v2); 87 88 vector<int> v3{v0}; 89 // 将[v1.begin(),v1.end()] 区间内元素循环右移1位 90 rotate(v3.begin(),v3.end()-1,v3.end()); 91 cout << "v3: ";output(v3); 92 93 vector<int> v4{v0}; 94 // 将[v1.begin(),v1.end()] 区间内元素循环右移2位 95 rotate(v4.begin(),v4.end()-2,v4.end()); 96 cout << "v4: ";output(v4); 97 } 98
运行测试截图:

1 #include<iostream> 2 #include<vector> 3 #include<algorithm> 4 #include<numeric> 5 #include<iomanip> 6 #include<cstdlib> 7 #include<ctime> 8 9 //模板函数声明 10 template<typename T> 11 void output(const T &c); 12 13 //int generate_random_number(); 14 void test1(); 15 void test2(); 16 17 int main() 18 { 19 std::srand(std::time(0)); // 添加随机种子 20 std::cout << "测试1:\n"; 21 test1(); 22 std::cout << "\n测试2:\n"; 23 test2(); 24 } 25 26 //输出容器c中的元素 27 template<typename T> 28 void output(const T &c) 29 { 30 for(auto &i: c) 31 std::cout << i << ' '; 32 std::cout << '\n'; 33 } 34 35 //返回[0,100]区间内的一个随机整数 36 //int generate_random_number() 37 //{ 38 // return std::rand() % 101; 39 //} 40 41 //测试1:对容器类对象指定迭代器区间赋值、排序 42 void test1() 43 { 44 using namespace std; 45 46 vector<int> v0(10); //创建一个动态数组对象v0,对象大小为10 47 generate(v0.begin(),v0.end(),[](){return std::rand()%101;}); //生成随机整数填充v0 48 cout << "v0:";output(v0); 49 50 vector<int> v1{v0}; 51 sort(v1.begin(),v1.end()); //对整个vector排序 52 cout << "v1:";output(v1); 53 54 vector<int> v2{v0}; 55 sort(v2.begin()+1,v2.end()-1); //只对中间部分排序,不包括首尾元素 56 cout << "v2:";output(v2); 57 } 58 59 //测试2:对容器类对象指定迭代器区间赋值、计算最大值/最小值/均值 60 void test2() 61 { 62 using namespace std; 63 64 vector<int> v0(10); //创建一个动态数组对象v0,对象大小为10 65 generate(v0.begin(),v0.end(),[](){return std::rand()%101;}); //生成随机整数填充v0 66 cout << "v0:";output(v0); 67 68 //求最大值和最小值 69 auto min_iter = min_element(v0.begin(),v0.end()); 70 auto max_iter = max_element(v0.begin(),v0.end()); 71 cout << "最小值:" << *min_iter << endl; 72 cout << "最大值:" << *max_iter << endl; 73 74 //同时求最大值和最小值 75 auto ans = minmax_element(v0.begin(),v0.end()); 76 cout << "最小值:" << *(ans.first) << endl; 77 cout << "最大值:" << *(ans.second) << endl; 78 79 //求平均值 80 double avg1 = accumulate(v0.begin(),v0.end(),0.0)/v0.size(); 81 cout << "均值:" << fixed << setprecision(2) << avg1 << endl; 82 83 sort(v0.begin(),v0.end()); 84 double avg2 = accumulate(v0.begin()+1,v0.end()-1,0.0)/(v0.size()-2); 85 cout << "去掉最大值、最小值之后,均值:" << avg2 << endl; 86 }
运行测试截图:
1.generate 算法的作用是什么?
generate的作用是给一个容器指定范围内进行赋值
2.minmax_element 和分别调用 min_element 、 max_element 相比,有什么优势?
只需要一行代码就可以求出最小值和最大值
3.把代码中函数 generate_random_number 的声明(line13)和定义(line35-37)注释起来,把两处调用改成如下写法,观察效果是否等同?

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 { 12 std::cout << "测试1:字符串大小写转换\n"; 13 test1(); 14 15 std::cout << "\n测试2:字符变换\n"; 16 test2(); 17 } 18 19 unsigned char func(unsigned char c) 20 { 21 if(c == 'z') 22 return 'a'; 23 24 if(c == 'Z') 25 return 'A'; 26 27 if(std::isalpha(c)) 28 return static_cast<unsigned char>(c+1); 29 30 return c; 31 } 32 33 void test1() 34 { 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 += std:: tolower(c); 41 std:: cout << "s2 = " << s2 << '\n'; 42 43 std:: string s3; 44 for(auto c: s1) 45 s3 += std:: toupper(c); 46 std:: cout << "s3 = " << s3 << '\n'; 47 } 48 49 void test2() 50 { 51 std:: string s1{"I love cosmos!"}; 52 std:: cout << "s1 = " << s1 << '\n'; 53 54 std:: string s2(s1.size(),' '); 55 std:: transform(s1.begin(),s1.end(),s2.begin(),func); 56 std:: cout << "s2 = " << s2 << '\n'; 57 }
运行测试截图:
1.自定义函数 func 功能是什么?
将字符串中的英文字母变成下一个英文字母
2.tolower 和 toupper 功能分别是什么?
tolower是将字符串中字母全变成小写,toupper是将字符串中字母全变成大写
3.transform 的4个参数意义分别是什么?如果把第3个参数 s2.begin() 改成 s1.begin() ,有何区别?
第一个是原字符串的起始位置,第二个是原字符串的终止位置,第三个是复制到的字符串的起始位置,第四个是使用的变化方法,如果修改会使输出变为s2 = 后面没有原先修改之后的字符串了,因为是覆盖了原先的值而不是复制到s2上导致s2没有被赋值。
实验任务4:
task4源代码:

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 { 10 using namespace std; 11 string s; 12 13 // 多组输入,直到按下Ctrl+Z结束测试 14 while(cin >> s) 15 { 16 cout << boolalpha 17 << "区分大小写: " << is_palindrome(s) << "\n" 18 << "不区分大小写: " << is_palindrome_ignore_case(s) << "\n\n"; 19 } 20 } 21 22 //区分大小写 23 bool is_palindrome(const std::string &s) 24 { 25 for(int i=0;i<s.size()/2;i++) 26 { 27 int back=s.size()-i-1; 28 if(s[i]!=s[back]) 29 { 30 return false; 31 } 32 } 33 return true; 34 } 35 36 //不区分大小写 37 bool is_palindrome_ignore_case(const std::string &s) 38 { 39 std:: string s1; 40 for(auto c: s) 41 s1 += std:: toupper(c); 42 for(int i=0;i<s1.size()/2;i++) 43 { 44 int back=s1.size()-i-1; 45 if(s1[i]!=s1[back]) 46 { 47 return false; 48 } 49 } 50 return true; 51 }
运行测试截图:
1.使用 cin >> s 输入时,输入的字符串中不能包含空格。如果希望测试字符串包含空格(如 hello oop ),代码应如何调整?
将原来的while(cin>>s)改为while(getline(cin,s)
实验任务5:
task5源代码:

1 #include<iostream> 2 #include<string> 3 #include<algorithm> 4 5 std::string dec2n(int x,int n=2); 6 7 int main() 8 { 9 int x; 10 while(std::cin >> x) 11 { 12 std::cout << "十进制: " << x << '\n' 13 << "二进制: " << dec2n(x) << '\n' 14 << "八进制: " << dec2n(x, 8) << '\n' 15 << "十二进制: " << dec2n(x, 12) << '\n' 16 << "十六进制: " << dec2n(x, 16) << '\n' 17 << "三十二进制: " << dec2n(x, 32) << "\n\n"; 18 } 19 } 20 21 std::string dec2n(int x,int n) 22 { 23 if(x == 0) 24 { 25 return "0"; 26 } 27 28 std::string s; 29 int t; 30 31 while(x > 0) 32 { 33 t = x % n; 34 if(t >= 10) 35 { 36 s += static_cast<char>('A' + t - 10); 37 } 38 else 39 { 40 s += static_cast<char>(t + '0'); 41 } 42 x = x / n; 43 } 44 std::reverse (s.begin(),s.end()); 45 46 return s; 47 }
运行测试截图:
实验任务6:
task6源代码:

1 #include<string> 2 #include<iostream> 3 #include<iomanip> 4 5 int main() 6 { 7 std::cout << " "; 8 for(int i = 0; i < 26; i++) 9 { 10 char c = static_cast<char>('a' + i); 11 std::cout << c << " "; 12 } 13 std::cout << "\n"; 14 15 for(int i = 1; i <= 26; i++) 16 { 17 char c1 = 'A' + i % 26; 18 std::cout << std::setw(2) << i << " "; 19 for(int j = 0; j < 26; j++) 20 { 21 char c2 = 'A' + (i + j) % 26; 22 std::cout << c2 << " "; 23 } 24 std::cout << "\n"; 25 } 26 return 0; 27 }
运行测试截图:
实验任务7:
task7源代码:

1 #include<iostream> 2 #include<cstdlib> 3 #include<ctime> 4 #include<iomanip> 5 6 int main() 7 { 8 //设置随机种子 9 std::srand(time(0)); 10 11 int correct = 0; 12 13 for(int i = 0; i < 10; i++) 14 { 15 int number1 , number2 , result , answer , sign; 16 char c; 17 18 number1 = rand() % 10 + 1; 19 number2 = rand() % 10 + 1; 20 sign = rand() % 4; 21 22 switch(sign) 23 { 24 case 0: 25 //加法 26 c = '+'; 27 result = number1 + number2; 28 break; 29 30 case 1: 31 //减法 32 c = '-'; 33 if(number2 > number1) 34 std::swap(number1 , number2); 35 result = number1 - number2; 36 break; 37 38 case 2: 39 //乘法 40 c = '*'; 41 result = number1 * number2; 42 break; 43 44 case 3: 45 //除法 46 c = '/'; 47 while(number1 % number2 !=0) 48 { 49 number1 = rand() % 10 + 1; 50 number2 = rand() % 10 + 1; 51 } 52 result = number1 / number2; 53 break; 54 } 55 56 std::cout << number1 << " " << c << " " << number2 << " " << "= "; 57 std::cin >> answer; 58 59 if(answer==result) 60 { 61 correct++; 62 } 63 std::cout << "\n"; 64 } 65 66 double accuracy = static_cast<double>(correct) / 10 * 100; 67 std::cout << "正确率: " << std::fixed << std::setprecision(2) << accuracy << "%" << "\n"; 68 return 0; 69 }
运行测试截图:
实验总结:
以下为部分我写代码过程中踩的坑,因为部分函数比如cin,endl忘记写std::频繁报错,使用iomanip来完成数字对齐以及按规定格式输出,字符串通过加就能实现赋值,这是我的一个新的体验