实验1 现代C++编程初体验

实验任务1:

源代码:

 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  }
View Code

运行测试截图:

 

2e5f6b5b-d0dc-4d5c-81c5-936600e75e82

 

观察与思考:

1.reverse 和 reverse_copy 有什么区别?

答:

reverse 会直接在原序列上进行反转操作,修改原容器内容。

reverse_copy 则会把反转后的结果复制到另一个容器中,原容器保持不变。

 

2.rotate 算法是如何改变元素顺序的?它的三个参数分别代表什么?

答:rotate 通过“旋转”区间内的元素实现整体左移或右移。

 

实验任务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  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  // 添加随机种子
19     std::cout << "\n测试2: \n";
20     test2();
21  }
22  // 输出容器对象c中的元素
23 template <typename T>
24  void output(const T &c) {
25     for(auto &i: c)
26         std::cout << i << ' ';
27     std::cout << '\n';
28  }
29  // 返回[0, 100]区间内的一个随机整数
30 int generate_random_number() {
31     return std::rand() % 101;
32  }
33  // 测试1:对容器类对象指定迭代器区间赋值、排序
34 void test1() {
35     using namespace std;
36     vector<int> v0(10);  // 创建一个动态数组对象v0, 对象大小为10
37     generate(v0.begin(), v0.end(), generate_random_number); // 生成随机数填充v0
38     cout << "v0: "; output(v0);
39     vector<int> v1{v0};
40     sort(v1.begin(), v1.end()); // 对整个vector排序
41     cout << "v1: "; output(v1);
42     vector<int> v2{v0};
43     sort(v2.begin()+1, v2.end()-1); // 只对中间部分排序,不包含首尾元素
44     cout << "v2: "; output(v2);
45  }
46  // 测试2:对容器类对象指定迭代器区间赋值、计算最大值/最小值/均值
47 void test2() {
48     using namespace std;
49     vector<int> v0(10);  
50     generate(v0.begin(), v0.end(), generate_random_number); 
51     cout << "v0: "; output(v0);
52     // 求最大值和最小值
53     auto min_iter = min_element(v0.begin(), v0.end());
54     auto max_iter = max_element(v0.begin(), v0.end());
55     cout << "最小值: " << *min_iter << endl;
56     cout << "最大值: " << *max_iter << endl;
57     // 同时求最大值和最小值
58     auto ans = minmax_element(v0.begin(), v0.end());
59     cout << "最小值: " << *(ans.first) << endl;
60     cout << "最大值: " << *(ans.second) << endl;
61 
62  // 求平均值
63     double avg1 = accumulate(v0.begin(), v0.end(), 0.0) / v0.size();
64      cout << "均值: " << fixed << setprecision(2) << avg1 << endl;
65      sort(v0.begin(), v0.end());
66      double avg2 = accumulate(v0.begin()+1, v0.end()-1, 0.0) / (v0.size()-2);
67      cout << "去掉最大值、最小值之后,均值: " << avg2 << endl;
68  }
View Code

运行测试截图:

 

887c01e8-f153-43b5-bb1e-92c945bb452f

 

观察与思考:

1.generate 算法的作用是什么?

答:generate 可以批量为区间中的每个元素赋值,通过调用一个生成函数(或 lambda 表达式)产生数据。

2.minmax_element 和分别调用 min_element 、 max_element 相比,有什么优势?

答:minmax_element 只需一次遍历即可同时找到最小值与最大值,效率更高,而单独调用 min_element 与 max_element 需要遍历两次。

3.把代码中函数generate_random_number 的声明(line13)和定义(line35-37)注释起来,把两处调用改成如下写法,观察效果是否等同?查阅c++中lambda表达式用法。

1  // test1()模块和test2()模块:
2   generate(v0.begin(), v0.end(), generate_random_number); 
3 ---->改成
4   generate(v0.begin(), v0.end(), [](){return std::rand()%101;}); 

答:不等同。

 

实验任务3:

源代码:

 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  if(c == 'Z')
18  return 'A';
19  if(std::isalpha(c))
20  return static_cast<unsigned char>(c+1);
21  return c;
22  }
23  void test1() {
24  std::string s1{"Hello World 2049!"};
25  std::cout << "s1 = " << s1 << '\n';
26  std::string s2;
27  for(auto c: s1)
28  s2 += std::tolower(c);
29  std::cout << "s2 = " << s2 << '\n'; 
30 std::string s3;
31  for(auto c: s1)
32  s3 += std::toupper(c);
33  std::cout << "s3 = " << s3 << '\n'; 
34 }
35  void test2() {
36  std::string s1{"I love cosmos!"};
37  std::cout << "s1 = " << s1 << '\n';
38  std::string s2(s1.size(), ' ');
39  std::transform(s1.begin(), s1.end(),
40  s2.begin(),
41  func);
42  std::cout << "s2 = " << s2 << '\n';
43  }
View Code

运行测试截图:

 

46afe00b-7408-45cf-b015-1fe6f2c7d25c

 

观察与思考:

1.自定义函数func功能是什么?

答:func 用于将输入字符循环加一。

若是 'z' → 'a','Z' → 'A';

若是字母则顺序加一(如 'b'→'c');

其他字符(空格、符号等)保持不变。

2.tolower和toupper功能分别是什么?

答:tolower 将大写字母转换为小写字母,toupper 将小写字母转换为大写字母。

3.transform的4个参数意义分别是什么?如果把第3个参数s2.begin()改成s1.begin(),有何区别?

答:

参数依次为:
① 输入区间起点;② 输入区间终点;③ 输出区间起点;④ 转换函数。

若将第 3 个参数改为 s1.begin(),则会在原字符串上原地修改,而不是将结果写入新的字符串。

 

实验任务4

 源代码:

 1 #include <iostream>
 2 #include <string>
 3 #include <algorithm>
 4 #include <cctype>
 5 using namespace std;
 6 
 7 bool is_palindrome(const string &s) {
 8     string t = s;
 9     reverse(t.begin(), t.end());
10     return s == t;
11 }
12 
13 bool is_palindrome_ignore_case(const string &s) {
14     string t1 = s, t2 = s;
15     transform(t1.begin(), t1.end(), t1.begin(),
16               [](unsigned char c){ return tolower(c); });
17     reverse(t2.begin(), t2.end());
18     transform(t2.begin(), t2.end(), t2.begin(),
19               [](unsigned char c){ return tolower(c); });
20     return t1 == t2;
21 }
22 
23 int main() {
24     using namespace std;
25     string s;
26     // 多组输入,直到按下Ctrl+Z结束测试
27     while(cin >> s) {
28         cout << boolalpha
29              << "区分大小写: " << is_palindrome(s) << "\n"
30              << "不区分大小写: " << is_palindrome_ignore_case(s) << "\n\n";
31     }
32 }

 

运行测试截图:

 

6f758390-00a0-4e5a-86a5-edaf6e1c3962

 

观察与思考:
使用cin >> s输入时,输入的字符串中不能包含空格。如果希望测试字符串包含空格(如hello oop),代码应如何调整?

答:使用getline(cin, s); 这样可以读取整行内容,包括空格。

 

实验任务5

源代码:

 1 #include <iostream>
 2 #include <string>
 3 #include <algorithm>
 4 using namespace std;
 5 
 6 string dec2n(int x, int n = 2) {
 7     const string digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
 8     if (x == 0) return "0";
 9     string result;
10     while (x > 0) {
11         result += digits[x % n];
12         x /= n;
13     }
14     reverse(result.begin(), result.end());
15     return result;
16 }
17 
18 int main() {
19     int x;
20     while (cin >> x) {
21         cout << "十进制: " << x << '\n'
22              << "二进制: " << dec2n(x) << '\n'
23              << "八进制: " << dec2n(x, 8) << '\n'
24              << "十二进制: " << dec2n(x, 12) << '\n'
25              << "十六进制: " << dec2n(x, 16) << '\n'
26              << "三十二进制: " << dec2n(x, 32) << "\n\n";
27     }
28 }

 

运行测试截图:

5eed72f9-4e1d-49a5-abf3-9ed2b460a9ba

 

实验任务6

源代码:

 1 #include <iostream>
 2 #include <iomanip>
 3 using namespace std;
 4 
 5 int main() {
 6     // 打印表头(小写 a-z)
 7     cout << "    ";
 8     for (char c = 'a'; c <= 'z'; ++c) {
 9         cout << setw(2) << c;
10     }
11     cout << '\n';
12 
13     
14     for (int i = 1; i <= 26; ++i) {
15         cout << setw(2) << i << " ";
16         for (int j = 0; j < 26; ++j) {
17             // 列索引 j 对应字母 'a'+j
18             // 移位为 i,所以使用 (j + i) % 26
19             char ch = 'A' + ( (j + i) % 26 );
20             cout << setw(2) << ch;
21         }
22         cout << '\n';
23     }
24 
25     return 0;
26 }

 

运行测试截图:

 

eb56aa0c-4018-4d50-9893-ab7d483886ae

 

实验任务7

源代码:

 1 #include <iostream>
 2 #include <cstdlib>
 3 #include <ctime>
 4 #include <iomanip>
 5 
 6 // 生成[min, max]区间的随机整数
 7 int getRandomInt(int min, int max) {
 8     return rand() % (max - min + 1) + min;
 9 }
10 
11 int main() {
12     // 设置随机种子,确保每次题目不同
13     srand(static_cast<unsigned int>(time(0)));
14     const int totalQuestions = 10;
15     int correctCount = 0;
16 
17     std::cout << "===== 小学生算术测试(共" << totalQuestions << "题)=====\n";
18     for (int i = 1; i <= totalQuestions; ++i) {
19         int a, b, correctAns, userAns;
20         char op;
21 
22         // 循环生成合法题目
23         while (true) {
24             a = getRandomInt(1, 10);
25             b = getRandomInt(1, 10);
26             int opType = rand() % 4; // 0:加, 1:减, 2:乘, 3:除
27 
28             if (opType == 0) {
29                 op = '+';
30                 correctAns = a + b;
31                 break;
32             } else if (opType == 1) {
33                 op = '-';
34                 if (a >= b) {
35                     correctAns = a - b;
36                     break;
37                 }
38             } else if (opType == 2) {
39                 op = '*';
40                 correctAns = a * b;
41                 break;
42             } else {
43                 op = '/';
44                 if (a % b == 0) {
45                     correctAns = a / b;
46                     break;
47                 }
48             }
49         }
50 
51         // 输出题目并获取用户答案
52         std::cout << a << " " << op << " " << b << " = ";
53         std::cin >> userAns;
54 
55         // 判断答案并统计正确数
56         if (userAns == correctAns) {
57             correctCount++;
58         }
59     }
60 
61     // 计算并输出正确率
62     double accuracy = static_cast<double>(correctCount) / totalQuestions * 100;
63     std::cout << "\n===== 测试结束 =====\n";
64     std::cout << "正确率: " << std::fixed << std::setprecision(2) << accuracy << "%\n";
65 
66     return 0;
67 }

 

运行测试截图:

 

7aa47ae8-ca06-40fa-9f77-490d4c8640eb

 

posted @ 2025-10-16 22:14  溯溪而上  阅读(17)  评论(1)    收藏  举报