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

问题:
(1)reverse:原地反转,直接修改原容器. reverse(v.begin(), v.end() ),v 本身被反转。
reverse_copy:拷贝反转,原容器不变,结果存到另一个容器。 reverse_copy(v.begin(), v.end() ,result.begin() ),v 不变,result 是反转后的副本。
任务二:
源代码:
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 std::srand(std::time(0)); // 添加随机种子 19 std::cout << "测试1: \n"; 20 test1(); 21 22 std::cout << "\n测试2: \n"; 23 test2(); 24 } 25 26 // 输出容器对象c中的元素 27 template <typename T> 28 void output(const T &c) { 29 for(auto &i: c) 30 std::cout << i << ' '; 31 std::cout << '\n'; 32 } 33 34 // 返回[0, 100]区间内的一个随机整数 35 int generate_random_number() { 36 return std::rand() % 101; 37 } 38 39 // 测试1:对容器类对象指定迭代器区间赋值、排序 40 void test1() { 41 using namespace std; 42 43 vector<int> v0(10); // 创建一个动态数组对象v0, 对象大小为10 44 generate(v0.begin(), v0.end(), generate_random_number); // 生成随机数填充v0 45 cout << "v0: "; output(v0); 46 47 vector<int> v1{v0}; 48 sort(v1.begin(), v1.end()); // 对整个vector排序 49 cout << "v1: "; output(v1); 50 51 vector<int> v2{v0}; 52 sort(v2.begin()+1, v2.end()-1); // 只对中间部分排序,不包含首尾元素 53 cout << "v2: "; output(v2); 54 } 55 56 // 测试2:对容器类对象指定迭代器区间赋值、计算最大值/最小值/均值 57 void test2() { 58 using namespace std; 59 60 vector<int> v0(10); 61 generate(v0.begin(), v0.end(), generate_random_number); 62 cout << "v0: "; output(v0); 63 64 // 求最大值和最小值 65 auto min_iter = min_element(v0.begin(), v0.end()); 66 auto max_iter = max_element(v0.begin(), v0.end()); 67 cout << "最小值: " << *min_iter << endl; 68 cout << "最大值: " << *max_iter << endl; 69 70 // 同时求最大值和最小值 71 auto ans = minmax_element(v0.begin(), v0.end()); 72 cout << "最小值: " << *(ans.first) << endl; 73 cout << "最大值: " << *(ans.second) << endl; 74 75 // 求平均值 76 double avg1 = accumulate(v0.begin(), v0.end(), 0.0) / v0.size(); 77 cout << "均值: " << fixed << setprecision(2) << avg1 << endl; 78 79 sort(v0.begin(), v0.end()); 80 double avg2 = accumulate(v0.begin()+1, v0.end()-1, 0.0) / (v0.size()-2); 81 cout << "去掉最大值、最小值之后,均值: " << avg2 << endl; 82 }
运行结果:
问题:
(1)generate:用指定的生成器函数(或函数对象)的结果,填充一个范围内的所有元素
(2)minmax_element 的优势
效率更高:只需一次遍历就能同时找到最小和最大值。
保证一致性:返回的迭代器指向的是同一时刻容器中的最小和最大值(对于可能变化的容器很重要)。
(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 if(c == 'Z') 23 return 'A'; 24 25 if(std::isalpha(c)) 26 return static_cast<unsigned char>(c+1); 27 28 return c; 29 } 30 31 void test1() { 32 std::string s1{"Hello World 2049!"}; 33 std::cout << "s1 = " << s1 << '\n'; 34 35 std::string s2; 36 for(auto c: s1) 37 s2 += std::tolower(c); 38 std::cout << "s2 = " << s2 << '\n'; 39 40 std::string s3; 41 for(auto c: s1) 42 s3 += std::toupper(c); 43 std::cout << "s3 = " << s3 << '\n'; 44 } 45 46 void test2() { 47 std::string s1{"I love cosmos!"}; 48 std::cout << "s1 = " << s1 << '\n'; 49 50 std::string s2(s1.size(), ' '); 51 std::transform(s1.begin(), s1.end(), 52 s2.begin(), 53 func); 54 std::cout << "s2 = " << s2 << '\n'; 55 }
运行结果:

问题:
(1)func函数功能:字母循环后移一位
(2)tolower:大写字母转小写,其他字符不变
toupper:小写字母转大写,其他字符不变
(3)s1.begin() - 输入范围起点
s1.end() - 输入范围终点
s2.begin() - 输出位置起点
func-转换函数
(4)结果会直接覆盖s1的内容,s2无效
任务四:
源代码:
1 #include <iostream> 2 #include <string> 3 #include <algorithm> 4 #include <cctype> 5 6 bool is_palindrome(const std::string &s); 7 bool is_palindrome_ignore_case(const std::string &s); 8 9 int main() { 10 using namespace std; 11 string s; 12 13 // 多组输入,直到按下Ctrl+Z结束测试 14 while(cin >> s) { 15 cout << boolalpha 16 << "区分大小写: " << is_palindrome(s) << "\n" 17 << "不区分大小写: " << is_palindrome_ignore_case(s) << "\n\n"; 18 } 19 } 20 21 // 严格区分大小写的回文判断 22 bool is_palindrome(const std::string &s) { 23 int left = 0; 24 int right = s.length() - 1; 25 26 while (left < right) { 27 if (s[left] != s[right]) { 28 return false; 29 } 30 left++; 31 right--; 32 } 33 return true; 34 } 35 36 // 不区分大小写的回文判断 37 bool is_palindrome_ignore_case(const std::string &s) { 38 int left = 0; 39 int right = s.length() - 1; 40 41 while (left < right) { 42 // 转换为小写后比较 43 if (std::tolower(s[left]) != std::tolower(s[right])) { 44 return false; 45 } 46 left++; 47 right--; 48 } 49 return true; 50 }
运行结果:

问题:
用std::getline()代替cin>>s
任务五:
源代码:
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 20 // 十进制转n进制函数(x >= 0, 2 <= n <= 36) 21 std::string dec2n(int x, int n) { 22 if (x == 0) return "0"; 23 24 std::string result; 25 const char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 26 27 // 不断除以n取余数 28 while (x > 0) { 29 int remainder = x % n; 30 result += digits[remainder]; 31 x /= n; 32 } 33 34 std::reverse(result.begin(), result.end()); 35 36 return result; 37 }
运行结果:

任务六:
源代码:
1 #include <iostream> 2 #include <string> 3 #include <vector> 4 #include <algorithm> 5 using namespace std; 6 template <typename T> 7 void output(const T &c){ 8 for(auto &i:c) 9 cout<<i<<" "; 10 cout<<endl; 11 } 12 int main(){ 13 vector <char> m{'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'} ; 14 cout<<" ";output(m); 15 vector <char> v{'B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','A'}; 16 cout<<1<<" ";output(v); 17 for(int i=2;i<=26;i++){ 18 rotate(v.begin(),v.begin()+1,v.end()); 19 cout<<i<<" ";output(v); 20 } 21 return 0; 22 }
运行结果:

任务七:
1 #include <iostream> 2 #include <ctime> 3 using namespace std; 4 5 // 检查题目 6 bool check(int op) { 7 int a, b; 8 char opChar; 9 int ans; 10 int user; 11 12 switch (op) { 13 case 0: // 加法 14 a = rand() % 10 + 1; 15 b = rand() % 10 + 1; 16 opChar = '+'; 17 ans = a + b; 18 break; 19 20 case 1: // 减法 21 b = rand() % 10 + 1; 22 a = rand() % (10 - b + 1) + b; 23 opChar = '-'; 24 ans = a - b; 25 break; 26 27 case 2: // 乘法 28 a = rand() % 10 + 1; 29 b = rand() % 10 + 1; 30 opChar = '*'; 31 ans = a * b; 32 break; 33 34 case 3: // 除法 35 do { 36 b = rand() % 10 + 1; 37 a = rand() % 10 + 1; 38 } while (a % b != 0 || a / b > 10); 39 opChar = '/'; 40 ans = a / b; 41 break; 42 } 43 44 cout << a << " " << opChar << " " << b << " = "; 45 cin >> user; 46 47 return user == ans; 48 } 49 50 // 计算正确率 51 double rate(int correct, int total) { 52 return (correct * 100.0) / total; 53 } 54 55 int main() { 56 srand(time(0)); // 使用时间作为随机种子,确保每次运行题目不同 57 58 int correct = 0; 59 const int total = 10; 60 61 for (int i = 0; i < total; i++) { 62 int op = rand() % 4; 63 64 if (check(op)) { 65 correct++; 66 } 67 } 68 69 double accuracy = rate(correct, total); 70 cout << "\n正确率:" << accuracy << "%" << endl; 71 72 return 0; 73 }
运行结果:


浙公网安备 33010602011771号