OOP-实验1

实验任务1

源代码task1.cpp

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

 运行测试截图

task1

回答问题

问题1:reverse 和 reverse_copy 有什么区别?

reverse:直接反转容器内元素,因此要改变原容器内容

reverse_copy:将原容器元素反转后的结果复制到另一个新容器中,且原容器的内容不改变

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

rotate 即循环移位,第一个参数即循环移位区间的起始迭代器,第三个参数即循环移位区间的终止迭代器;

中间参数:左移k位即 起始迭代器+k ;右移k位即 终止迭代器-k

 

实验任务2

源代码task2.cpp

 1 // 体验使用C++标准库高效完成数据赋值、排序和基本统计
 2 
 3 #include <iostream>
 4 #include <vector>
 5 #include <algorithm>
 6 #include <numeric>
 7 #include <iomanip>
 8 #include <cstdlib>
 9 #include <ctime>
10 
11 // 函数模板声明
12 template <typename T>
13 void output(const T &c);
14 
15 int generate_random_number(); // 生成随机数
16 void test1();
17 void test2();
18 
19 int main()
20 {
21     std::srand(std::time(0)); // 设置随机数种子
22 
23     std::cout << "测试1: " << std::endl;
24     test1();
25 
26     std::cout << "测试2: " << std::endl;
27     test2();
28 }
29 
30 // 输出容器对象c中的元素
31 template <typename T>
32 void output(const T &c)
33 {
34     for (const auto &i : c)
35         std::cout << i << " ";
36     std::cout << std::endl;
37 }
38 
39 // 返回[0, 100]区间内的一个随机整数
40 int generate_random_number()
41 {
42     return std::rand() % 101;
43 }
44 
45 // generate(v0.begin(), v0.end(), []()
46 //          { return std::rand() % 101; });
47 
48 // 测试1: 对容器类对象指定迭代器区间赋值、排序
49 void test1()
50 {
51     using namespace std;
52 
53     vector<int> v0(10);                                     // 创建一个大小为10的动态数组v0
54     generate(v0.begin(), v0.end(), generate_random_number); // 生成随机数填充v0
55     cout << "v0: ";
56     output(v0);
57 
58     vector<int> v1{v0};
59     sort(v1.begin(), v1.end());
60     cout << "v1: ";
61     output(v1);
62 
63     vector<int> v2{v0};
64     sort(v2.begin() + 1, v2.end() - 1); // 只对除首尾元素外的元素排序
65     cout << "v2: ";
66     output(v2);
67 }
68 
69 // 测试2: 对容器类对象指定迭代器区间赋值、计算最大值/最小值/均值
70 void test2()
71 {
72     using namespace std;
73 
74     vector<int> v0(10);
75     generate(v0.begin(), v0.end(), generate_random_number);
76     cout << "v0: ";
77     output(v0);
78 
79     // 求v0的最大值和最小值 指针
80     auto min_iter = min_element(v0.begin(), v0.end());
81     cout << "最小值: " << *min_iter << endl;
82     auto max_iter = max_element(v0.begin(), v0.end());
83     cout << "最大值: " << *max_iter << endl;
84 
85     // 同时求v0的最大值和最小值 指针
86     auto ans = minmax_element(v0.begin(), v0.end());
87     cout << "最小值: " << *(ans.first) << endl;
88     cout << "最大值: " << *(ans.second) << endl;
89 
90     // 求v0平均值
91     double avg1 = accumulate(v0.begin(), v0.end(), 0.0) / v0.size();
92     cout << "平均值: " << fixed << setprecision(2) << avg1 << endl; // 格式控制,保留到小数点后两位
93 
94     // 求去掉最大值和最小值后,v0的平均值
95     sort(v0.begin(), v0.end());
96     double avg2 = accumulate(v0.begin() + 1, v0.end() - 1, 0.0) / (v0.size() - 2);
97     cout << "去掉最大值、最小值后, 平均值: " << avg2 << endl;
98 };
View Code

运行测试截图

task2

回答问题

问题1:generate 算法的作用是什么?

generate:对容器类对象指定迭代器区间内赋值

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

优势:只需要一次遍历即可同时求出容器类的最大值和最小值

问题3:generate 更改后效果是否相同?类比C++中 lambda 表达式用法。

generate 更改后效果依然相同,为无参的 lambda 表达式;C++中的 lambda 表达式是一种创建匿名函数对象的方式

 

实验任务3

源代码task3.cpp

 1 // 体验使用C++标准库高效完成字符串变换操作
 2 
 3 #include <iostream>
 4 #include <string>
 5 #include <algorithm>
 6 #include <cctype>
 7 
 8 unsigned char func(unsigned char c); // 返回无符号单字符
 9 void test1();
10 void test2();
11 
12 int main()
13 {
14     std::cout << "测试1: 字符串大小写转换" << std::endl;
15     test1();
16 
17     std::cout << std::endl;
18     std::cout << "测试2: 字符变换" << std::endl;
19     test2();
20 }
21 
22 // 字符后移
23 unsigned char func(unsigned char c)
24 {
25     // 单独对字符z和Z作处理
26     if (c == 'z')
27         return 'a';
28     else if (c == 'Z')
29         return 'A';
30     else if (std::isalpha(c))                     // 判断是否为字母
31         return static_cast<unsigned char>(c + 1); // 静态类型转换
32 
33     return c;
34 }
35 
36 // 字符串大小写转换
37 void test1()
38 {
39     using namespace std;
40     string s1{"Hello World 2049!"};
41     cout << "s1 = " << s1 << endl;
42 
43     string s2;
44     for (char &c : s1) // 遍历s1一个个作转换
45     {
46         s2 += tolower(c); // 将转换后的字符一个个拼接到s2
47     }
48     cout << "s2 = " << s2 << endl;
49 
50     string s3;
51     for (char &c : s1)
52     {
53         s3 += toupper(c);
54     }
55     cout << "s3 = " << s3 << endl;
56 }
57 
58 // 字符变换
59 void test2()
60 {
61     using namespace std;
62 
63     string s1{"I love cosmos!"};
64     cout << "s1 = " << s1 << endl;
65 
66     string s2(s1.size(), ' ');
67     transform(s1.begin(), s1.end(), s2.begin(), func);
68     cout << "s2 = " << s2 << endl;
69 }
View Code

运行测试截图

task3

回答问题

问题1:自定义函数 func 功能是什么?

若该字符为字母,则将其变换成它的下一个字母,其中 z 和 Z 分别变换成 a 和 A

若该字符不是字母,则不作任何处理

问题2:tolower 和 toupper 功能分别是什么?

tolower() 将单个字符转换成它的小写;toupper() 将单个字符转换成它的大写

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

transform() 作字符的变换操作,其中前两个参数表示执行操作的范围,第4个参数表示变换操作的具体方法,而第3个参数表示结果的起始存储地址;

若改成 s1.begin() , 则相当于直接对 s1 执行 func 操作,会更改原字符串 s1 的内容,而 s2.begin() 不会更改原字符串 s1 的内容

 

实验任务4

源代码task4.cpp

 1 // 判断回文串 返回true/false
 2 // 要求:支持多组输入
 3 // 严格区分大小写:bool is_palindrome(const std::string &s)
 4 // 不区分大小写:bool is_palindrome_ignore_case(const std::string &s)
 5 
 6 #include <iostream>
 7 #include <string>
 8 #include <algorithm>
 9 
10 bool is_palindrome(const std::string &s);
11 bool is_palindrome_ignore_case(const std::string &s);
12 unsigned char func(const char c);
13 
14 int main()
15 {
16     using namespace std;
17     string s;
18 
19     // 多组输入,直到按下Ctrl+Z结束测试
20     while (cin >> s)
21     {
22         cout << boolalpha
23              << "区分大小写: " << is_palindrome(s) << endl
24              << "不区分大小写: " << is_palindrome_ignore_case(s) << endl
25              << endl;
26     }
27 }
28 
29 // 函数is_palindrome()定义 严格区分大小写
30 bool is_palindrome(const std::string &s)
31 {
32     using namespace std;
33     string str(s.size(), ' ');
34     reverse_copy(s.begin(), s.end(), str.begin()); // 得到反转后的字符串str
35 
36     // 比较s和str
37     if (s == str)
38         return true;
39     return false;
40 }
41 
42 // 函数is_palindrome_ignore_case()定义 不区分大小写
43 bool is_palindrome_ignore_case(const std::string &s)
44 {
45     using namespace std;
46     string str(s.size(), ' ');
47     transform(s.begin(), s.end(), str.begin(), func);
48 
49     string str_reverse(s.size(), ' ');
50     reverse_copy(str.begin(), str.end(), str_reverse.begin());
51 
52     if (str == str_reverse)
53         return true;
54     return false;
55 }
56 
57 unsigned char func(const char c)
58 {
59     return tolower(c);
60 }
View Code

运行测试截图

task4

回答问题

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

 通过询问 AI,了解到:若希望读取包含空格的整行文本,应该使用 std::getline() 函数,而不是 cin >> s

 

实验任务5

源代码task5.cpp

 1 // 进制转换
 2 // std::string dec2n(x, n) 实现把一个十进制数x转换成n进制,结果以字符串形式返回
 3 // 若第2个参数n未指定,则默认转换成二进制
 4 // 本次实验限定参数n取值区间为[2,36],限定参数x>=0
 5 // 要求:支持多组输入
 6 
 7 #include <iostream>
 8 #include <string>
 9 #include <algorithm>
10 
11 std::string dec2n(int x, int n = 2);
12 
13 int main()
14 {
15     using namespace std;
16     int x;
17     while (cin >> x)
18     {
19         cout << "十进制: " << x << endl
20              << "二进制: " << dec2n(x) << endl
21              << "八进制: " << dec2n(x, 8) << endl
22              << "十二进制: " << dec2n(x, 12) << endl
23              << "十六进制: " << dec2n(x, 16) << endl
24              << "三十二进制: " << dec2n(x, 32) << endl
25              << endl;
26     }
27 }
28 
29 // 函数dec2n()定义
30 // 注意:带有默认形参的函数只需在声明处声明一次即可,在函数定义时不可再重复声明,会报错!!!
31 std::string dec2n(int x, int n)
32 {
33     using namespace std;
34 
35     string s;
36     char c;
37     int k;
38 
39     // 若出现 x = 0 的情况
40     // 必须添加,否则会返回空字符串
41     if (x == 0)
42     {
43         return "0"; // 返回字符串0
44     }
45 
46     while (x != 0)
47     {
48         k = x % n;
49         if (k > 9) // 字母范畴
50         {
51             c = 'A' + (k - 10);
52             s += c;
53         }
54         else // 数字范畴
55         {
56             c = '0' + k;
57             s += c;
58         }
59         x /= n;
60     }
61 
62     string str(s.size(), ' ');
63     reverse_copy(s.begin(), s.end(), str.begin()); // 反转后返回
64 
65     return str;
66 }
View Code

运行测试截图

task5

 

实验任务6

源代码task6.cpp

 1 // 打印字母密文对照表
 2 // 输出格式控制、大小写转换、循环移位
 3 
 4 #include <iostream>
 5 #include <vector>
 6 #include <iomanip>
 7 #include <algorithm>
 8 
 9 void output();
10 
11 int main()
12 {
13     output();
14     return 0;
15 }
16 
17 void output()
18 {
19     using namespace std;
20 
21     vector<char> v;
22 
23     // 添加元素
24     for (int i = 0; i < 26; i++)
25     {
26         char c;
27         c = 'a' + i;
28         v.push_back(c);
29     }
30 
31     // 第一行输出
32     cout << "  ";
33     for (auto &c : v)
34     {
35         cout << setw(2) << c;
36         c = toupper(c); // 小写转换成大写
37     }
38     cout << endl;
39 
40     for (int i = 1; i <= 26; i++)
41     {
42         // 循环左移1位
43         rotate(v.begin(), v.begin() + 1, v.end());
44         cout << setw(2) << i;
45         for (auto &c : v)
46         {
47             cout << setw(2) << c;
48         }
49         cout << endl;
50     }
51 }
View Code

运行测试截图

task6

 

实验任务7

源代码task7.cpp

 1 // 自动生成小学生算术运算题目并自动测评
 2 // 题目是减法运算时,要求第一个操作数>=第二个操作数
 3 // 题目是除法运算时,要求第一个操作数能整除第二个操作数整除
 4 // 给出正确率,要求以百分号形式输出,保留小数点后两位
 5 
 6 #include <iostream>
 7 #include <iomanip>
 8 #include <cstdlib>
 9 #include <ctime>
10 
11 char generate_random_operator();
12 void generate_random_number(int &m, int &n);
13 int calculate(const int m, const int n, char c);
14 
15 int main()
16 {
17     std::srand(std::time(0)); // 设置随机数种子
18 
19     int k = 0, ans, count = 0;
20     while (k < 10)
21     {
22         int m, n;
23         generate_random_number(m, n);
24         char c = generate_random_operator();
25 
26         // 判断减法是否合法
27         if (c == '-')
28         {
29             if (m < n)
30                 continue;
31         }
32 
33         // 判断除法是否合法
34         else if (c == '/')
35         {
36             if (m % n != 0)
37                 continue;
38         }
39 
40         k++;
41         std::cout << m << ' ' << c << ' ' << n << " = ";
42         std::cin >> ans;
43 
44         if (calculate(m, n, c) == ans)
45             count++;
46     }
47 
48     std::cout << "正确率: ";
49     double rate = count * 100.0 / 10.0;
50     std::cout << std::fixed << std::setprecision(2) << rate << '%' << std::endl;
51 
52     return 0;
53 }
54 
55 // 生成随机运算符
56 char generate_random_operator()
57 {
58     switch (rand() % 4)
59     {
60     case 0:
61         return '+';
62         break;
63     case 1:
64         return '-';
65         break;
66     case 2:
67         return '*';
68         break;
69     default:
70         return '/';
71     }
72 }
73 
74 // 生成随机运算数
75 void generate_random_number(int &m, int &n)
76 {
77     m = rand() % 10 + 1;
78     n = rand() % 10 + 1;
79 }
80 
81 // 计算正确结果
82 int calculate(const int m, const int n, char c)
83 {
84     if (c == '+')
85         return m + n;
86     else if (c == '-')
87         return m - n;
88     else if (c == '*')
89         return m * n;
90     else
91         return m / n;
92 }
View Code

运行测试截图

task7

实验总结

  1. 了解并实现了常见算法函数的使用:如 reverse_copy(),rotate(),tolower(),toupper() 以及生成随机数的方法等
  2. 注意:带有默认形参的函数只需在声明时声明一次即可,在定义时不可再声明,会导致报错
  3. tolower 和 toupper 的形参只能是字符型,若填入 string 类型会报错
  4. 用 std::getline() 读取包含空格的整行文本
posted @ 2025-10-12 17:41  FF-10086  阅读(19)  评论(1)    收藏  举报