实验一
1.实验任务1
源代码task1.cpp
1 #include <iostream> 2 #include<string> 3 #include<vector> 4 #include<algorithm> 5 template<typename T> 6 void output(const T &c); 7 void test1(); 8 void test2(); 9 void test3(); 10 int main(){ 11 std::cout<<"测试1:\n"; 12 test1(); 13 std::cout << "\n测试2: \n"; 14 test2(); 15 std::cout << "\n测试3: \n"; 16 test3(); 17 } 18 template <typename T> 19 void output(const T &c) { 20 for(auto &i : c) 21 std::cout << i << ' '; 22 std::cout << '\n'; 23 } 24 // 测试1:组合使用算法库、迭代器、string反转字符串 25 void test1() { 26 using namespace std; 27 string s0{"0123456789"}; 28 cout << "s0 = " << s0 << endl; 29 string s1(s0); 30 // 反转s1自身 31 reverse(s1.begin(), s1.end()); 32 cout << "s1 = " << s1 << endl; 33 string s2(s0.size(), ' '); 34 // 将s0反转后结果拷贝到s2, s0自身不变 35 reverse_copy(s0.begin(), s0.end(), s2.begin()); 36 cout << "s2 = " << s2 << endl; 37 } 38 // 测试2:组合使用算法库、迭代器、vector反转动态数组对象vector内数据 39 void test2() { 40 using namespace std; 41 vector<int> v0{2, 0, 4, 9}; 42 cout << "v0: "; output(v0); 43 vector<int> v1{v0}; 44 reverse(v1.begin(), v1.end()); 45 cout << "v1: "; output(v1); 46 vector<int> v2{v0}; 47 reverse_copy(v0.begin(), v0.end(), v2.begin()); 48 cout << "v2: "; output(v2); 49 } 50 // 测试3:组合使用算法库、迭代器、vector实现元素旋转移位 51 void test3() { 52 using namespace std; 53 vector<int> v0{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; 54 cout << "v0: "; output(v0); 55 vector<int> v1{v0}; 56 // 将[v1.begin(), v1.end())区间内元素循环左移1位 57 rotate(v1.begin(), v1.begin()+1, v1.end()); 58 cout << "v1: "; output(v1); 59 vector<int> v2{v0}; 60 // 将[v1.begin(), v1.end())区间内元素循环左移2位 61 rotate(v2.begin(), v2.begin()+2, v2.end()); 62 cout << "v2: "; output(v2); 63 vector<int> v3{v0}; 64 // 将[v1.begin(), v1.end())区间内元素循环右移1位 65 rotate(v3.begin(), v3.end()-1, v3.end()); 66 cout << "v3: "; output(v3); 67 vector<int> v4{v0}; 68 // 将[v1.begin(), v1.end())区间内元素循环右移2位 69 rotate(v4.begin(), v4.end()-2, v4.end()); 70 cout << "v4: "; output(v4); 71 }
运行结果如下

问题一:test1中,reverse是将s1自身进行反转逆序,而reverse_copy是将s0逆序之后拷贝到s2里面去,同时s0不变;同理,test2中,reverse是将v1自身进行反转逆序,而reverse_copy是将v0逆序之后拷贝到v2里面去。所以reverse是反转自身,reverse_copy是把原来数据反转拷贝到新变量里。
问题二:rotate是通过将元素向左向右移动,而总长度不变,来实现顺序变换的。rotate中,第一个参数表示要改变顺序的起始元素,第三个参数表示要改变顺序的最后一个元素,第二个参数表示是从哪里往哪个方向移多少,例如v2.begin()+2,就是从v2.begin的位置开始向左移动2,v3.end()-1表示从v3.end向右移动1
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 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 std::cout<<"测试2:\n"; 21 test2(); 22 } 23 24 template <typename T> 25 void output(const T &c){ 26 for(auto &i: c) 27 std::cout<<i<<' '; 28 std::cout<<'\n'; 29 } 30 31 // 返回[0, 100]区间内的一个随机整数 32 int generate_random_number() { 33 return std::rand() % 101; 34 } 35 // 测试1:对容器类对象指定迭代器区间赋值、排序 36 void test1() { 37 using namespace std; 38 vector<int> v0(10); // 创建一个动态数组对象v0, 对象大小为10 39 generate(v0.begin(), v0.end(), generate_random_number); // 生成随机数填充v0 40 cout << "v0: "; output(v0); 41 vector<int> v1{v0}; 42 sort(v1.begin(), v1.end()); // 对整个vector排序 43 cout << "v1: "; output(v1); 44 vector<int> v2{v0}; 45 sort(v2.begin()+1, v2.end()-1); // 只对中间部分排序,不包含首尾元素 46 cout << "v2: "; output(v2); 47 } 48 // 测试2:对容器类对象指定迭代器区间赋值、计算最大值/最小值/均值 49 void test2() { 50 using namespace std; 51 vector<int> v0(10); 52 generate(v0.begin(), v0.end(), generate_random_number); 53 cout << "v0: "; output(v0); 54 // 求最大值和最小值 55 auto min_iter = min_element(v0.begin(), v0.end()); 56 auto max_iter = max_element(v0.begin(), v0.end()); 57 cout << "最小值: " << *min_iter << endl; 58 cout << "最大值: " << *max_iter << endl; 59 // 同时求最大值和最小值 60 auto ans = minmax_element(v0.begin(), v0.end()); 61 cout << "最小值: " << *(ans.first) << endl; 62 cout << "最大值: " << *(ans.second) << endl; 63 64 65 // 求平均值 66 double avg1 = accumulate(v0.begin(), v0.end(), 0.0) / v0.size(); 67 cout << "均值: " << fixed << setprecision(2) << avg1 << endl; 68 sort(v0.begin(), v0.end()); 69 double avg2 = accumulate(v0.begin()+1, v0.end()-1, 0.0) / (v0.size()-2); 70 cout << "去掉最大值、最小值之后,均值: " << avg2 << endl; 71 }
运行结果如下

问题一:generate是为了生成随机数填充v0
问题二:minmax_element 只需要历遍一次,就可以找出最大值和最小值,而分别调用 min_element 、 max_element 要历遍两次才能找到最值,使用minmax_element 时间更短,代码更简洁
问题三:修改后代码和运行如下,由图可见是等效的。C++中,lambda用于快速定义匿名函数,可以解决需要临时函数但用不想重新显式声明的问题。其语法格式为[捕获列表](参数){函数体}。在此代码中,它用return std::rand()%101函数体来实现生成随机数的操作。


3.实验任务三
源代码task3.cpp
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 }
运行结果如下

问题一:自定义函数 func 功能是将输入的字符串每个字母变成其后一个字母输出
问题二:tolower 的功能是把字符变成小写,toupper 功能是把字符变成大写
问题三:transform的第一个参数是要处理的数据的起始位置,第二个参数是要处理的数据的结束位置,第三个参数是新数据存储的起始位置,第四给参数是处理的方式,比如func函数。
如果把第3个参数 s2.begin() 改成 s1.begin(),运行结果如下,新数据存储位置为s1,即s1本身修改,不再存储在s2里面,所以s2为空

4.实验任务四
源代码task4.cpp
1 #include <iostream> 2 #include <string> 3 #include <algorithm> 4 #include<cctype> 5 bool is_palindrome(const std::string &s); 6 bool is_palindrome_ignore_case(const std::string &s); 7 int main() { 8 using namespace std; 9 string s; 10 // 多组输入,直到按下Ctrl+Z结束测试 11 while(cin >> s) { 12 cout << boolalpha 13 << "区分大小写: " << is_palindrome(s) << "\n" 14 << "不区分大小写: " << is_palindrome_ignore_case(s) << "\n\n"; 15 } 16 } 17 // 函数is_palindrome定义 18 bool is_palindrome(const std::string &s){ 19 int left=0,right=s.size()-1; 20 while(left<right){ 21 if(s[left]!=s[right]){ 22 return false; 23 } 24 left++; 25 right--; 26 } 27 return true; 28 } 29 // 函数is_palindrome_ignore_case定义 30 bool is_palindrome_ignore_case(const std::string &s){ 31 std::string s1; 32 for(auto c:s){ 33 s1+=std::tolower(c); 34 } 35 int left=0,right=s1.size()-1; 36 while(left<right){ 37 if(s1[left]!=s1[right]){ 38 return false; 39 } 40 left++; 41 right--; 42 } 43 return true; 44 }
运行结果如下

问题:如果希望输入的字符串可以包含空格,可以把while(cin>>s)改成while(getline(cin,s)),getline可以读取一整行的数据,因此不会碰到输入空格的时候就停止。运行如下


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 // 函数dec2n定义 18 std::string dec2n(int x,int n) 19 { 20 if(x==0){ 21 return "0"; 22 } 23 std::string s; 24 int r; 25 while(x>0){ 26 r=x%n; 27 if(r<10){ 28 s+=(char)('0'+r); 29 }else{ 30 s+=(char)('A'+r-10); 31 } 32 x=x/n; 33 } 34 std::reverse(s.begin(),s.end()); 35 return s; 36 }
运行结果如下

6.实验任务六
源代码task6.cpp
1 #include <iostream> 2 #include <string> 3 #include <algorithm> 4 using namespace std; 5 char transform(char c,int back); 6 int main(){ 7 cout<<' '<<' '<<' '; 8 for(char c='a';c<='z';c++){ 9 cout<<c<<' '; 10 } 11 cout<<'\n'<<endl; 12 for(int i=1;i<=26;i++){ 13 if(i<10){ 14 cout<<' '<<i<<' '; 15 }else{ 16 cout<<i<<' '; 17 } 18 for(char c='A';c<='Z';c++){ 19 cout<<transform(c,i)<<' '; 20 } 21 cout<<'\n'<<endl; 22 } 23 return 0; 24 } 25 26 char transform(char c,int back){ 27 if(isalpha(c)){ 28 return 'A'+(c-'A'+back)%26; 29 return c; 30 } 31 }
运行结果如下


7.实验任务七
源代码task7.cpp
1 #include<iostream> 2 #include<cstdlib> 3 #include<ctime> 4 #include<iomanip> 5 using namespace std; 6 int main(){ 7 srand(static_cast<unsigned int>(time(0))); 8 int correct=0; 9 for(int i=1;i<=10;i++){ 10 int n1=rand()%10+1; 11 int n2=rand()%10+1; 12 int calculate=rand()%4+1; 13 int right_answer,answer; 14 if(calculate==2){ 15 if(n1<n2){ 16 int m; 17 m=n2,n2=n1,n1=m; 18 } 19 } 20 if(calculate==4){ 21 while(n1%n2!=0){ 22 n1=rand()%10+1; 23 n2=rand()%10+1; 24 } 25 } 26 switch(calculate){ 27 case 1: 28 right_answer=n1+n2; 29 cout<<n1<<"+"<<n2<<"="; 30 break; 31 case 2: 32 right_answer=n1-n2; 33 cout<<n1<<"-"<<n2<<"="; 34 break; 35 case 3: 36 right_answer=n1*n2; 37 cout<<n1<<"*"<<n2<<"="; 38 break; 39 case 4: 40 right_answer=n1/n2; 41 cout<<n1<<"/"<<n2<<"="; 42 break; 43 } 44 cin>>answer; 45 cout<<'\n'; 46 if(right_answer==answer){ 47 correct++; 48 } 49 } 50 double accuracy; 51 accuracy=(double) correct/10*100; 52 cout<<"正确率:"<<accuracy<<"%"<<endl; 53 return 0; 54 }
运行结果如下


浙公网安备 33010602011771号