实验一
实验一
task1
(1)
task1代码

1 // 现代C++标准库、算法库体验 2 // 本例用到以下内容: 3 // 1.字符串string, 动态数组容器类vector、迭代器 4 // 2.算法库:反转元素次序、旋转元素 5 // 3.函数模板、const引用作为形参 6 7 #include<iostream> 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 template<typename T> 31 void output(const T &c){ 32 for(auto &i:c) 33 std::cout<<i<<' '; 34 std::cout<<'\n'; 35 } 36 //测试1:组合使用算法库、迭代器、string反转字符串 37 void test1(){ 38 using namespace std; 39 40 string s0{"0123456789"}; 41 cout<<"s0="<<s0<<endl; 42 43 string s1(s0); 44 //反转s1自身 45 reverse(s1.begin(),s1.end()); 46 cout<<"s1="<<s1<<endl; 47 48 string s2(s0.size(),' '); 49 //将s0反转后结果拷贝到s2,s0自身不变 50 reverse_copy(s0.begin(),s0.end(),s2.begin()); 51 cout<<"s2="<<s2<<endl; 52 } 53 //测试2:组合使用算法库、迭代器、vector反转动态数组对象vector内数据 54 void test2(){ 55 using namespace std; 56 57 vector<int>v0{2,0,4,9}; 58 cout<<"v0:";output(v0); 59 vector<int>v1{v0}; 60 reverse(v1.begin(),v1.end()); 61 cout<<"v1:";output(v1); 62 63 vector<int>v2{v0}; 64 reverse_copy(v0.begin(),v0.end(),v2.begin()); 65 cout<<"v2:";output(v2); 66 67 } 68 //测试3:组合使用算法库、迭代器、vector实现元素旋转移位 69 void test3(){ 70 using namespace std; 71 72 vector<int>v0{0,1,2,3,4,5,6,7,8,9}; 73 cout<<"v0:";output(v0); 74 75 vector<int>v1{v0}; 76 //将[v1.begin(),v1.end())区间内元素循环左移1位 77 rotate(v1.begin(),v1.begin()+1,v1.end()); 78 cout<<"v1:";output(v1); 79 80 vector<int>v2{v0}; 81 // 将[v1.begin(), v1.end())区间内元素循环左移2位 82 rotate(v2.begin(),v2.begin()+2,v2.end()); 83 cout<<"v2:";output(v2); 84 85 vector<int> v3{v0}; 86 // 将[v1.begin(), v1.end())区间内元素循环右移1位 87 rotate(v3.begin(),v3.end()-1,v3.end()); 88 cout<<"v3:";output(v3); 89 90 vector<int> v4{v0}; 91 // 将[v1.begin(), v1.end())区间内元素循环右移2位 92 rotate(v4.begin(),v4.end()-2,v4.end()); 93 cout<<"v4:";output(v4); 94 95 }
(2)运行结果截图
(3)回答问题
问题1:reverse是原地反转容器(v1)中的元素顺序,而reverse_copy是将反转后的结果复制到另一个容器(v2)中,不会修改原来的容器。
问题2:rotate算法将容器中的元素进行循环左移,使得中间参数指向的元素成为新的首元素。
第一个参数是范围的起始位置,第二个参数是新范围起始位置的元素,第三个元素是范围的结束位置。
task2
(1)
task2代码

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<<"\n测试2:\n"; 23 test2(); 24 } 25 // 输出容器对象c中的元素 26 template<typename T> 27 void output(const T &c){ 28 for(auto &i:c) 29 std::cout<<i<<' '; 30 std::cout<<'\n'; 31 } 32 // 返回[0, 100]区间内的一个随机整数 33 int generate_random_number(){ 34 return std::rand()%101; 35 } 36 37 // 测试1:对容器类对象指定迭代器区间赋值、排序 38 void test1(){ 39 using namespace std; 40 41 vector<int>v0(10);// 创建一个动态数组对象v0, 对象大小为10 42 generate(v0.begin(),v0.end(),generate_random_number); // 生成随机数填充v0 43 cout<<"v0:";output(v0); 44 45 vector<int>v1{v0}; 46 sort(v1.begin(),v1.end());//对整个vector排序 47 cout<<"v1:";output(v1); 48 49 vector<int>v2{v0}; 50 sort(v2.begin()+1,v2.end()-1);// 只对中间部分排序,不包含首尾元素 51 cout<<"v2:";output(v2); 52 53 } 54 55 // 测试2:对容器类对象指定迭代器区间赋值、计算最大值/最小值/均值 56 void test2(){ 57 using namespace std; 58 59 vector<int>v0(10); 60 generate(v0.begin(),v0.end(),generate_random_number); 61 cout<<"v0:";output(v0); 62 63 // 求最大值和最小值 64 auto min_iter=min_element(v0.begin(),v0.end()); 65 auto max_iter=max_element(v0.begin(),v0.end()); 66 cout<<"最小值:"<<*min_iter<<endl; 67 cout<<"最大值:"<<*max_iter<<endl; 68 69 // 同时求最大值和最小值 70 auto ans=minmax_element(v0.begin(),v0.end()); 71 cout<<"最小值:"<<*(ans.first)<<endl; 72 cout<<"最大值:"<<*(ans.second)<<endl; 73 //求平均值 74 double avg1=accumulate(v0.begin(),v0.end(),0.0)/v0.size(); 75 cout<<"均值:"<<fixed<<setprecision(2)<<avg1<<endl; 76 77 sort(v0.begin(),v0.end()); 78 double avg2=accumulate(v0.begin()+1,v0.end()-1,0.0)/(v0.size()-2); 79 cout<<"去掉最大值、最小值之后,均值:"<<avg2<<endl; 80 }
(2)运行测试截图
(3)回答问题
问题1:generate算法用指定的生成函数填充容器的元素范围。用以在0~100中生成随机数字。
问题2:①效率高:只需要一次遍历就能同时找到最小值和最大值。
②代码简洁,代码行数减少
问题3:效果等同,都是生成0~100的随机数。
task3
(1)
task3代码

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 if(std::isalpha(c)) 24 return static_cast<unsigned char>(c+1); 25 26 return c; 27 } 28 29 void test1(){ 30 std::string s1{"Hello World 2049!"}; 31 std::cout<<"s1="<<s1<<'\n'; 32 33 std::string s2; 34 for(auto c:s1) 35 s2+=std::tolower(c); 36 std::cout<<"s2="<<s2<<'\n'; 37 38 std::string s3; 39 for(auto c:s1) 40 s3+=std::toupper(c); 41 std::cout<<"s3="<<s3<<'\n'; 42 } 43 44 void test2(){ 45 std::string s1{"I love cosmos!"}; 46 std::cout<<"s1="<<s1<<'\n'; 47 48 std::string s2(s1.size(),' '); 49 std::transform(s1.begin(),s1.end(),s2.begin(),func); 50 std::cout<<"s2="<<s2<<'\n'; 51 }
(2)运行测试截图
(3)回答问题
问题1:func的功能是将字母按顺序向左移一位。
问题2:tolower是将字符串中的所有字符中的字母大写转换成小写;toupper是将字符串中的所有字符中的字母小写转换成大写写。
问题3:transform第一个参数是作用范围的起点,第二个参数是作用范围的结束,第三个参数是把作用后的元素输出的起点,第四个参数是转换函数。
使用s1.begin()的结果是直接覆盖原字符串s1,会破坏原始数据。而使用s2.begin()对原始数据无影响。
task4:
(1)

1 #include <iostream> 2 #include <string> 3 #include <algorithm> 4 std::string dec2n(int x, int n = 2); 5 int main() { 6 int x; 7 while(std::cin >> x) { 8 std::cout << "十进制: " << x << '\n' 9 << "二进制: " << dec2n(x) << '\n' 10 << "八进制: " << dec2n(x, 8) << '\n' 11 << "十二进制: " << dec2n(x, 12) << '\n' 12 << "十六进制: " << dec2n(x, 16) << '\n' 13 << "三十二进制: " << dec2n(x, 32) << "\n\n"; 14 } 15 } 16 std::string dec2n(int x, int n){ 17 using namespace std; 18 if(x==0)return "0"; 19 string result=""; 20 21 while(x>0){ 22 int remainder=x%n; 23 x=x/n; 24 if(remainder<10){ 25 result+='0'+remainder; 26 } 27 else{ 28 result='A'+(remainder-10); 29 } 30 } 31 reverse(result.begin(), result.end()); 32 return result; 33 }
(2)运行测试截图
(3)思考: 可以使用getline(cin,s),这个读取整行内容,包括空格。也可以使用cin.getline()。
task5
(1)

1 std::string dec2n(int x, int n = 2); 2 int main() { 3 int x; 4 while(std::cin >> x) { 5 std::cout << "十进制: " << x << '\n' 6 << "二进制: " << dec2n(x) << '\n' 7 << "八进制: " << dec2n(x, 8) << '\n' 8 << "十二进制: " << dec2n(x, 12) << '\n' 9 << "十六进制: " << dec2n(x, 16) << '\n' 10 << "三十二进制: " << dec2n(x, 32) << "\n\n"; 11 } 12 } 13 std::string dec2n(int x, int n){ 14 using namespace std; 15 if(x==0)return "0"; 16 string result=""; 17 18 while(x>0){ 19 int remainder=x%n; 20 x=x/n; 21 if(remainder<10){ 22 result+='0'+remainder; 23 } 24 else{ 25 result='A'+(remainder-10); 26 } 27 } 28 reverse(result.begin(), result.end()); 29 return result; 30 }
(2)运行测试截图
task6
(1)

1 #include <iostream> 2 #include<iomanip> 3 #include <string> 4 #include <algorithm> 5 using namespace std; 6 unsigned char func(unsigned char c) { 7 8 if(c == 'Z') 9 return 'A'; 10 if(isalpha(c)) 11 return static_cast<unsigned char>(c+1); 12 return c; 13 } 14 int main() { 15 int i=1; 16 string v{"a b c d e f g h i j k l m n o p q r s t u v w x y z"}; 17 cout<<" "<<v<<endl; 18 string s; 19 for(auto c: v) 20 s+=toupper(c); 21 string s1(s.size(),' '); 22 while(i!=27){ 23 transform(s.begin(), s.end(),s1.begin(),func); 24 cout<<setw(3)<<left<<i++; 25 cout<<s1<<endl; 26 s=s1; 27 } 28 }
(2)运行测试截图
task7
(1)

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