实验1 现代C++编程初体验
#实验任务1
##代码
```c++

1 #include<iostream> 2 #include<vector> 3 #include<string> 4 #include<algorithm>//提供各类通用算法,涵盖排序、查找、修改、比较等操作 5 6 template<typename T> 7 void output(const T &c); 8 9 void test1(); 10 void test2(); 11 void test3(); 12 13 int main(){ 14 using std::cout; 15 using std::endl; 16 17 cout<<"测试1:"<<endl; 18 test1(); 19 cout<<"\n测试2:"<<endl; 20 test2(); 21 cout<<"\n测试3:" <<endl; 22 test3(); 23 } 24 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 32 void test1(){ 33 using namespace std; 34 35 string s0{"0123456789"}; 36 cout<<"s0 = "<<s0<<endl; 37 38 string s1(s0); 39 reverse(s1.begin(),s1.end()); 40 cout<<"s1 = "<<s1<<endl; 41 42 string s2(s0.size(),' '); 43 reverse_copy(s0.begin(),s0.end(),s2.begin()); 44 cout<<"s2 = "<<s2<<endl; 45 } 46 47 void test2(){ 48 using namespace std; 49 50 vector<int> v0{2,0,4,9}; 51 cout<<"v0: "; 52 output(v0); 53 54 vector<int> v1{v0}; 55 reverse(v1.begin(),v1.end()); 56 cout<<"v1: "; 57 output(v1); 58 59 vector<int> v2{v0}; 60 reverse_copy(v0.begin(),v0.end(),v2.begin()); 61 cout<<"v2: "; 62 output(v2); 63 } 64 65 void test3(){ 66 using namespace std; 67 68 vector<int> v0{0,1,2,3,4,5,6,7,8,9}; 69 cout<<"v0: "; 70 output(v0); 71 72 vector<int> v1{v0}; 73 rotate(v1.begin(),v1.begin()+1,v1.end()); 74 cout<<"v1: "; 75 output(v1); 76 77 vector<int> v2{v0}; 78 rotate(v2.begin(),v2.begin()+2,v2.end()); 79 cout<<"v2: "; 80 output(v2); 81 82 vector<int> v3{v0}; 83 rotate(v3.begin(),v3.end()-1,v3.end()); 84 cout<<"v3: "; 85 output(v3); 86 87 vector<int> v4{v0}; 88 rotate(v4.begin(),v4.end()-2,v4.end()); 89 cout<<"v4: "; 90 output(v4); 91 92 }
##运行测试截图
##问题回答
1、reverse直接在原容器内反转元素,会修改原数据;reverse_copy则将反转后的元素复制到新容器,原容器数据保持不变。
2、rotate原理:将容器中[first, middle)区间的元素,整体“旋转”到[middle, last)区间的末尾,最终形成[middle, last) + [first, middle)的新顺序。
参数:
• first:指向旋转范围的起始位置,是整个操作区间的左边界;
• middle:指向“旋转轴”位置,即[first, middle)区间的最后一个元素的下一位;
• last:指向旋转范围的结束位置的下一位,是整个操作区间的右边界。
#实验任务2
##代码
```c++

1 #include<iostream> 2 #include<vector> 3 #include<algorithm> 4 #include<numeric>//提供数值计算相关的算法 5 #include<iomanip>//通过一系列操作符实现格式化输入输出 6 #include<cstdlib>//实现内存管理、数值转换、生成随机数、程序控制等,相当于c语言中的<stdlib> 7 #include<ctime> //处理时间和日期的核心时刻 8 9 template<typename T> 10 void output(const T &c); 11 12 //int generate_random_number(); 13 void test1(); 14 void test2(); 15 16 int main(){ 17 std::srand(std::time(0)); 18 std::cout<<"测试1:\n"; 19 test1(); 20 21 std::cout<<"测试2:\n"; 22 test2(); 23 } 24 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 32 //int generate_random_number(){ 33 // return std::rand()%101; 34 //} 35 36 void test1(){ 37 using namespace std; 38 39 vector<int> v0(10); 40 generate(v0.begin(),v0.end(),[](){return std::rand()%101;}); 41 cout<<"v0: "; 42 output(v0); 43 44 vector<int> v1{v0}; 45 sort(v1.begin(),v1.end()); 46 cout<<"v1: "; 47 output(v1); 48 49 vector<int> v2{v0}; 50 sort(v2.begin()+1,v2.end()-1); 51 cout<<"v2: "; 52 output(v2); 53 } 54 55 void test2(){ 56 using namespace std; 57 58 vector<int> v0(10); 59 generate(v0.begin(),v0.end(),[](){return std::rand()%101;}); 60 cout<<"v0: "; 61 output(v0); 62 63 auto min_iter=min_element(v0.begin(),v0.end()); 64 auto max_iter=max_element(v0.begin(),v0.end()); 65 cout<<"最小值:"<<*min_iter<<endl; 66 cout<<"最大值:"<<*max_iter<<endl; 67 68 auto ans=minmax_element(v0.begin(),v0.end()); 69 cout<<"最小值:"<<*(ans.first)<<endl; 70 cout<<"最大值:"<<*(ans.second)<<endl; 71 72 double avg1=accumulate(v0.begin(),v0.end(),0.0)/v0.size(); 73 cout<<"均值:"<<fixed<<setprecision(2)<<avg1<<endl; 74 75 sort(v0.begin(),v0.end()); 76 double avg2=accumulate(v0.begin()+1,v0.end()-1,0.0)/(v0.size()-2); 77 cout<<"去掉最大值、最小值之后,均值:"<<avg2<<endl; 78 }
```
##运行测试截图
##问题回答
1、generate算法的核心作用:按指定规则(由函数/函数对象提供),为容器中[first, last)区间的每个元素生成新值,直接覆盖容器中原有的元素。
2、minmax_element只需遍历容器一次即可同时找到最小值和最大值的迭代器;而分别调用min_element和max_element需要遍历两次容器,效率更低。
3、ambda表达式核心用法:是匿名函数,可直接定义在需要调用函数的地方(如算法参数中),无需单独声明函数,核心用于简化代码、传递简短逻辑。
基础结构:[捕获列表](参数列表) mutable noexcept -> 返回值类型 { 函数体 }。
#实验任务3
##代码
```c++

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 std::cout << "\n测试2: 字符变换\n"; 14 test2(); 15 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 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 }
```
##运行测试截图
##问题回答
1、实现输入字符与输出字符之间的转换。
2、tolower功能是将所有字符以小写形式输出;toupper功能是将所有字符以大写形式输出。
3、
参数:
s1.begin():指向输入区间的起始位置,是待转换元素的第一个元素;
s1.end():指向输入区间的结束位置的下一位,标记输入区间的边界([first1, last1)),确定要转换的元素范围;
s2.begin():指向输出区间的起始位置,转换后的元素会从这个位置开始依次存放,需确保输出区间有足够空间;
func:一元转换函数/函数对象/lambda表达式,定义单个元素的转换规则(如取绝对值、加1、转小写等),接收输入区间的一个元素,返回转换后的结果。
区别:元素转换后结果的保存位置由原来的s2变成s1。
#实验任务4
##代码
```c++

1 #include<iostream> 2 #include<string> 3 #include<algorithm> 4 5 char func(char c); 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 while(cin>>s){ 14 cout<<boolalpha<<"区分大小写:"<<is_palindrome(s)<<"\n"<<"不区分大小写:"<<is_palindrome_ignore_case(s)<<"\n\n"; 15 } 16 } 17 18 char func(char c) { 19 if(c>='A'&&c<='Z') 20 return c+32; 21 } 22 23 bool is_palindrome(const std::string &s){ 24 int length=s.size(); 25 int left=0; 26 int right=length-1; 27 while(left<right){ 28 if(s[left]!=s[right]){ 29 return false; 30 } 31 left++; 32 right--; 33 } 34 return true; 35 } 36 37 bool is_palindrome_ignore_case(const std::string &s){ 38 int length=s.size(); 39 int left=0; 40 int right=length-1; 41 while(left<right){ 42 if(func(s[left])!=func(s[right])){ 43 return false; 44 } 45 left++; 46 right--; 47 } 48 return true; 49 }
```
##运行测试截图
##问题回答
1、需要将 "cin>>s" 替换为 "getline(cin,s)" 。
#实验任务5
##代码
```c++

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 std::cout<<"请输入一个大于0的数:"<<std::endl; 10 while(std::cin >> x) { 11 std::cout << "十进制: " << x << '\n' 12 << "二进制: " << dec2n(x) << '\n' 13 << "八进制: " << dec2n(x, 8) << '\n' 14 << "十二进制: " << dec2n(x, 12) << '\n' 15 << "十六进制: " << dec2n(x, 16) << '\n' 16 << "三十二进制: " << dec2n(x, 32) << "\n\n"; 17 } 18 return 0; 19 } 20 21 std::string dec2n(int x, int n ){ 22 std::string result; 23 int remainder; 24 25 do{ 26 remainder=x%n; 27 if(remainder>9){ 28 result+=static_cast<char>(remainder+55); 29 }else{ 30 result+=static_cast<char>(remainder+'0'); 31 } 32 x=x/n; 33 }while(x>0); 34 35 std::reverse(result.begin(),result.end()); 36 return result; 37 38 }
```
##运行测试截图
#实验任务6
##代码
```c++

1 #include<iostream> 2 #include<iomanip> 3 using namespace std; 4 5 void generateCaesarTable(); 6 int main(){ 7 generateCaesarTable(); 8 return 0; 9 } 10 11 void generateCaesarTable(){ 12 cout<<" "; 13 for(char c='a';c<='z';++c){ 14 cout<<c<<" "; 15 } 16 cout<<endl; 17 18 for(int shift=1;shift<=26;++shift){ 19 cout<<setw(2)<<shift<<" "; 20 21 for(char plain='a';plain<='z';++plain){ 22 char cipher=(plain-'a'+shift)%26+'A'; 23 cout<<cipher<<" "; 24 } 25 cout<<endl; 26 } 27 }
```
##运行测试截图
#实验任务7
##代码
```c++

1 #include <iostream> 2 #include <cstdlib> 3 #include <ctime> 4 #include <iomanip> 5 6 using namespace std; 7 8 int main() { 9 srand(time(0)); 10 int correct = 0; 11 12 13 for (int i = 0; i < 10; i++) { 14 int num1, num2, result; 15 char op; 16 num1 = rand() % 10 + 1; 17 num2 = rand() % 10 + 1; 18 int opType = rand() % 4; 19 20 switch (opType) { 21 case 0: 22 op = '+'; 23 result = num1 + num2; 24 break; 25 case 1: 26 op = '-'; 27 if (num1 < num2) { 28 swap(num1, num2); 29 } 30 result = num1 - num2; 31 break; 32 case 2: 33 op = '*'; 34 result = num1 * num2; 35 break; 36 case 3: 37 op = '/'; 38 num1 = (rand() % 10 + 1) * num2; 39 if (num1 > 10) { 40 num1 = num2; 41 } 42 result = num1 / num2; 43 break; 44 } 45 46 cout << num1 << " " << op << " " << num2 << " = "; 47 int userAnswer; 48 cin >> userAnswer; 49 50 if (userAnswer == result) { 51 correct++; 52 } 53 } 54 55 double accuracy = (correct / 10.0) * 100; 56 cout << fixed << setprecision(2) << "正确率: " << accuracy << "%" << endl; 57 58 return 0; 59 }
```
##运行测试截图