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

任务1:

task1.cpp

 


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

 

 

c++1

 

# reverse和reverse_copy有什么区别?

reverse 直接将动态数组反转;

reverse_copy 不能修改原动态数组,将反转的结果复制到另一个动态数组;

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

rotate(T first,T n_first,T last):将n_first到last之间的元素剪下来,贴到frist前面;

first代表范围的起始位置,n_first代表要旋转到前面的元素的位置,last代表范围的结束位置。

 

任务2:

task2.cpp

 

 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 << "测试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 }
 1 //返回[0,100]区间内的一个随机整数
 2 int generate_random_number() {
 3     return std::rand() % 101;
 4 }
 5 
 6 //测试1:对容器类对象指定迭代器区间赋值、排序
 7 void test1() {
 8     using namespace std;
 9     
10     vector<int> v0(10);  //创建一个动态数组对象v0,对象大小为10
11     generate(v0.begin(),v0.end(),generate_random_number);  //生成随机数填充v0
12     cout << "v0:";
13     output(v0);
14 
15     vector<int> v1{v0};
16     sort(v1.begin(),v1.end());  //对整个vector排序
17     cout << "v1:";
18     output(v1);
19 
20     vector<int> v2{v0};
21     sort(v2.begin()+1,v2.end()-1);  //只对中间部分排序,不包含首尾元素
22     cout << "v2:";
23     output(v2);
24 }
25 
26 //测试2:对容器对象指定迭代器区间赋值,计算最大值/最小值/均值
27 void test2() {
28     using namespace std;
29 
30     vector<int> v0(10);
31     generate(v0.begin(),v0.end(),generate_random_number);
32     cout << "v0:";
33     output(v0);
34     
35     //求最大值和最小值
36     auto min_iter = min_element(v0.begin(),v0.end());
37     auto max_iter = max_element(v0.begin(),v0.end());
38     cout << "最小值:" << *min_iter << endl;
39     cout << "最大值:" << *max_iter << endl;
40     
41     //求平均值
42     double avg1 = accumulate(v0.begin(),v0.end(),0.0) / v0.size();
43     cout << "均值:" << fixed << setprecision(2) << avg1 << endl;
44 
45     sort(v0.begin(),v0.end());
46     double avg2 = accumulate(v0.begin()+1,v0.end()-1,0.0) / (v0.size()-2);
47     cout << "去掉最大值、最小值之后,均值:" << avg2 << endl;
48 }

 

 

c++2

 

#generate算法的作用是什么?

用指定的随机生成函数generate_random_number填充区间(v0.begin(),v0.end())。

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

性能更好:分别调用需要遍历两次v0数组,而直接用minmax_element调用则只用遍历1次;

代码更简洁;

###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;});

效果相同;

Lambda基本语法:[捕获列表](参数列表) -> 返回类型{ 函数体 }

[ ]() {return rand() % 101;}  //无参数,无捕获

[ ](int x){ return x * 2;}  //带参数

[=]() {return external_var;}  //值捕获所有外部变量

[&]() {external_var++;}  //引用捕获所有外部变量

[var1,&var2]() {return var1 + var2;}  // 混合捕获

 

任务3:

task3.cpp

 

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

c++3

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

 

将字母字符变成它的下一个字母字符。

##tolower和toupper功能分别是什么?

tolower:将字符转换成小写;

toupper:将字符转换成大写;

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

第一个s1.begin()表示输入范围的开始,第二个s2.end()表示输入范围的结束,第三个s2.begin()表示输出位置的开始,第四个func表示对每个字符应用func函数;

若修改,则对字符应用func函数后,会覆盖s1的原位置,将处理结果存储在s1中。

 

任务4:

task4.cpp

 

 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     using namespace std;
10     string s;
11    
12     //多组输入,直到按下Ctrl+Z结束测试
13     while(cin >> s) {
14         cout << boolalpha
15         << "区分大小写:" << is_palindrome(s) << "\n"
16         << "不区分大小写:" << is_palindrome_ignore_case(s) << "\n\n";
17     }
18 }
19 
20 //函数is_palindrome的定义
21 bool is_palindrome(const std::string &s) {
22     std::string s1(s.size(),' ');
23     std::reverse_copy(s.begin(),s.end(),s1.begin());
24     if(s == s1)
25         return true;
26     else
27         return false;
28 }
29 #include<cctype>
30 //函数is_palindrome_ignore_case的定义
31 bool is_palindrome_ignore_case(const std::string &s) {
32     std::string s1(s.size(),' ');
33     std::string s2{s};
34     std::reverse_copy(s.begin(),s.end(),s1.begin());
35     for(auto &i:s1) {i = std::tolower(i);}
36     for(auto &i:s2) {i = std::tolower(i);}
37     if(s1 == s2)
38         return true;
39     else
40         return false;
41 }

QQ_1760695131314

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

可将while(cin >> s)换成while(getline(cin,s)),此时若s为空字符串或者读到'\n'结束。

 

任务5:

task5.cpp

 

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

 

c++5

 

任务6:

task6.cpp

 

 1 #include<iostream>
 2 #include<string>
 3 #include<iomanip>
 4 #include<algorithm>
 5 
 6 int main() {
 7     std::string s1{"abcdefghijklmnopqrstuvwxyz"};
 8     std::string s2{"ABCDEFGHIJKLMNOPQRSTUVWXYZ"};
 9     std::cout << "   ";
10     for(const auto &i:s1) 
11         std::cout << i << " ";
12     std::cout << "\n";  
13     for(int i=1;i<=26;i++) {
14         std::cout << std::setw(2) << i << " ";
15         rotate(s2.begin(),s2.begin()+1,s2.end());
16         for(const auto &j:s2)
17             std::cout << j << " ";
18         std::cout << "\n";
19     }
20 }

QQ_1760698681270

 

任务7:

task7.cpp

 

 1 #include<iostream>
 2 #include<ctime>
 3 #include<string>
 4 #include<algorithm>
 5 #include<iomanip>
 6 
 7 int generate_random_number();
 8 int random_number();
 9 
10 int main() {
11     std::srand(time(0));
12     std::string symbol{"+-*/"};
13     double count = 0.0;
14     
15     for(int i = 0;i < 10;i++) {
16         int number1 = generate_random_number();
17         int number2 = generate_random_number();
18         int number = random_number();
19         int answer;
20         
21         if(number == 0) {
22             std::cout << number1 << " " << symbol[number] <<
23             " " << number2 << " = ";
24             std::cin >> answer;
25             if(answer == number1 + number2)
26                 count++;
27             std::cout << "\n";
28         }
29         else if(number == 1) {
30             if(number1 < number2)
31                 std::swap(number1,number2);
32             std::cout << number1 << " " << symbol[number] <<
33             " " << number2 << " = ";
34             std::cin >> answer;
35             if(answer == number1 - number2)
36                 count++;
37             std::cout << "\n";
38         }
39         else if(number == 2) {
40             std::cout << number1 << " " << symbol[number] <<
41             " " << number2 << " = ";
42             std::cin >> answer;
43             if(answer == number1 * number2)
44                 count++;
45             std::cout << "\n";
46         }
47         if(number == 3) {
48             while(number1 % number2 != 0) {
49                 if(number2 % number1 != 0) {
50                     number1 = generate_random_number();
51                     number2 = generate_random_number();
52                     continue;
53                 }
54                 if(number1 < number2)
55                     std::swap(number1,number2);
56             }
57             std::cout << number1 << " " << symbol[number] <<
58             " " << number2 << " = ";
59             std::cin >> answer;
60             if(answer == number1 / number2)
61                 count++;
62             std::cout << "\n";
63         }
64     }
65     
66     std::cout << "正确率:" << std::fixed << std::setprecision(2)
67     << count*10 << "%" <<std::endl;
68 }
69 
70 int generate_random_number() {
71     return std::rand() % 11;
72 }
73 int random_number() {
74     return std::rand() % 4;
75 }

 

QQ_1760704895331

QQ_1760704938773

 

###实验总结###

通过这次实践,我对C++运用更加熟悉了一些,对于一些库函数的用法更加熟悉了,对于解决一些问题,我开始转变C语言思路,尽量尝试用我不熟悉的C++编写,通过这次实验,我也发现了C++语言的一些优势之处,例如数组元素的移动、求最大最小值。这些收获让我欣喜的同时,我也深刻体会到了C++内容的广阔,期待着以后进一步的学习。

 

posted @ 2025-10-17 20:51  艾拉i  阅读(8)  评论(1)    收藏  举报