实验任务1:
源代码task1.cpp
1 #include<iostream> 2 #include<string> 3 #include<vector> 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 std::cout << "测试1:\n"; 15 test1(); 16 17 std::cout << "\n测试2:\n"; 18 test2(); 19 20 std::cout << "\n测试3:\n"; 21 test3(); 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 void test1(){ 32 using namespace std; 33 string s0{"0123456789"}; 34 cout << "s0=" << s0 << endl; 35 36 string s1(s0); 37 reverse(s1.begin(),s1.end()); 38 cout << "s1=" << s1 << endl; 39 40 string s2(s0.size(),' '); 41 reverse_copy(s0.begin(),s0.end(),s2.begin()); 42 cout << "s2=" << s2 << endl; 43 } 44 45 void test2(){ 46 using namespace std; 47 vector<int> v0{2,0,4,9}; 48 cout << "v0: ";output(v0); 49 50 vector<int> v1{v0}; 51 reverse(v1.begin(),v1.end()); 52 cout << "v1: ";output(v1); 53 54 vector<int> v2{v0}; 55 reverse_copy(v0.begin(),v0.end(),v2.begin()); 56 cout << "v2: ";output(v2); 57 } 58 59 void test3(){ 60 using namespace std; 61 vector<int> v0{0,1,2,3,4,5,6,7,8,9}; 62 cout << "v0: ";output(v0); 63 64 vector<int> v1{v0}; 65 rotate(v1.begin(),v1.begin()+1,1.end()); 66 cout << "v1: ";output(v1); 67 68 vector<int> v2{v0}; 69 rotate(v2.begin(),v2.begin()+2,v2.end()); 70 cout << "v2: ";output(v2); 71 72 vector<int> v3{v0}; 73 rotate(v3.begin(),v3.end()-1,v3.end()); 74 cout << "v3: ";output(v3); 75 76 vector<int> v4{v0}; 77 rotate(v4.begin(),v4.end()-2,v4.end()); 78 cout << "v4: ";output(v4); 79 }
运行结果截图:
观察与思考:
1.reverse直接对原容器的元素进行反转操作,会改变原容器中元素的顺序。reverse_copy将原容器中元素反转后拷贝到另一个容器中,不改变原容器中元素的顺序。
2.rotate算法用于将容器中的元素进行循环旋转,把容器中某一位置后的元素移动到容器开头,实现元素顺序的循环调整。第一个参数表示容器的起始迭代器,指定要进行旋转操作的范围起点。第二个参数表示新的起始元素的迭代器,旋转后,该迭代器指向的元素会成为容器的第一个元素,其之前的元素会被移动到容器的末尾。第三个参数表示容器的结束迭代器,指定要进行旋转操作的范围终点。
实验任务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 << "\n测试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 int generate_random_number(){ 32 return std::rand()%101; 33 } 34 35 void test1(){ 36 using namespace std; 37 38 vector<int> v0(10); 39 generate(v0.begin(),v0.end(),generate_random_number); 40 cout << "v0: ";output(v0); 41 42 vector<int> v1{v0}; 43 sort(v1.begin(),v1.end()); 44 cout << "v1: ";output(v1); 45 46 vector<int> v2{v0}; 47 sort(v2.begin()+1,v2.end()-1); 48 cout << "v2: ";output(v2); 49 } 50 51 void test2(){ 52 using namespace std; 53 54 vector<int> v0(10); 55 generate(v0.begin(),v0.end(),generate_random_number); 56 cout << "v0: ";output(v0); 57 58 auto min_iter=min_element(v0.begin(),v0.end()); 59 auto max_iter=max_element(v0.begin(),v0.end()); 60 cout << "最小值:" << *min_iter << endl; 61 cout << "最大值:" << *max_iter << endl; 62 63 auto ans=minmax_element(v0.begin(),v0.end()); 64 cout << "最小值:" << *(ans.first) << endl; 65 cout << "最大值:" << *(ans.second) << endl; 66 67 double avg1=accumulate(v0.begin(),v0.end(),0.0)/v0.size(); 68 cout << "均值:" << fixed << setprecision(2) << avg1 << endl; 69 70 sort(v0.begin(),v0.end()); 71 double avg2=accumulate(v0.begin()+1,v0.end()-1,0.0)/(v0.size()-2); 72 cout << "去掉最大值、最小值之后,均值:" << avg2 << endl; 73 74 75 }
运行结果截图:
观察与思考:
1.generate 算法用于将一个由函数或可调用对象生成的值,填充到指定范围内的所有元素中。它会遍历给定的迭代器区间,对每个位置调用指定的生成函数,将返回值赋给该位置的元素。
2.一次遍历,效率更高,只需要一个包含最小和最大元素的迭代器。
3.效果等同。C++ lambda表达式用法:lambda表达式是一种匿名函数,格式为 [捕获列表] (参数列表) -> 返回值类型 { 函数体 } 。其中捕获列表用于指定外部变量的访问方式(如 [] 空捕获、 [&] 引用捕获、 [=] 值捕获等);参数列表和普通函数类似;返回值类型可省略,由编译器自动推导。示例中的lambda [](){return std::rand()%101;} 属于无捕获、无参数、返回 int 类型的简单形式,用于替代原命名函数,使代码更简洁内聚。
实验任务3:
源代码task3.cpp
1 #include<iostream> 2 #include<string> 3 #include<algorithm> 4 #include<cctype> 5 6 unsigned char fun(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 return c; 26 } 27 28 void test1(){ 29 std::string s1{"Hello world 2049!"}; 30 std::cout << "s1 = " << s1 << '\n'; 31 32 std::string s2; 33 for(auto c:s1) 34 s2+=std::tolower(c); 35 std::cout << "s2 = " << s2 << '\n'; 36 37 std::string s3; 38 for(auto c:s1) 39 s3+=std::toupper(c); 40 std::cout << "s3 = " << s3 << '\n'; 41 } 42 43 void test2(){ 44 std::string s1{"I love cosmos!"}; 45 std::cout << "s1 = " << s1 << '\n'; 46 47 std::string s2(s1.size(),' '); 48 std::transform(s1.begin(),s1.end(),s2.begin(),func); 49 std::cout << "s2 = " << s2 << '\n'; 50 }
运行结果截图:
观察与思考:
1.func功能是对字符进行特定变换。
2.tolower功能是将大写字母转化为对应的小写字母,非大写字母字符不做转换。toupper功能是将小写字母转化为对应的大写字母,非小写字母字符不做转换。
3.第一个参数表示要进行变换的源数据的起始迭代器,第二个参数表示要进行变换的源数据的结束迭代器,第三个参数表示变换结果要存储的目标范围的起始迭代器,第四个参数用于定义对每个元素的变换操作。改成s1.begin()会覆盖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 while(cin >>s){ 12 cout << boolalpha 13 << "区分大小写: " << is_palindrome(s) << "\n" 14 << "不区分大小写: " << is_palindrome_ignore_case(s) << "\n\n"; 15 } 16 } 17 18 bool is_palindrome(const std::string &s){ 19 using namespace std; 20 for(int i=0;i<=(s.length()-1)/2;i++){ 21 if(s[i]==s[s.length()-i-1]) 22 i++; 23 else 24 return false; 25 } 26 return true; 27 } 28 29 bool is_palindrome_ignore_case(const std::string &s){ 30 using namespace std; 31 string s2; 32 for(auto c:s) 33 s2+=tolower(c); 34 for(int i=0;i<=(s2.length()-1)/2;i++){ 35 if(s2[i]==s2[s.length()-i-1]) 36 i++; 37 else 38 return false; 39 } 40 return true; 41 }
运行结果截图:
观察与思考:
将cin >> s替换为getline(cin,s).
实验任务5:
源代码task5.cpp
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 while(std::cin >> x){ 10 std::cout << "十进制:" << x << '\n' 11 << "二进制:" << dec2n(x) << '\n' 12 << "八进制:" << dec2n(x,8) << '\n' 13 << "十二进制:" << dec2n(x,12) << '\n' 14 << "十六进制:" << dec2n(x,16) << '\n' 15 << "三十二进制:" << dec2n(x,32) << "\n\n"; 16 } 17 } 18 19 std::string dec2n(int x,int n){ 20 if(x==0) 21 return "0"; 22 std::string result; 23 while(x>0){ 24 int y=x%n; 25 if(y<10) 26 result+=(char)('0'+y); 27 else 28 result+=(char)('A'+y-10); 29 x=x/n; 30 } 31 std::reverse(result.begin(),result.end()); 32 return result; 33 }
运行结果截图:
实验任务6:
源代码task6.cpp
1 #include<iostream> 2 #include<string> 3 #include<algorithm> 4 #include<cctype> 5 #include<iomanip> 6 7 unsigned char func(unsigned char c); 8 void test(); 9 10 int main(){ 11 test(); 12 } 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 24 void test(){ 25 using namespace std; 26 string s1{"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"}; 27 cout << right << setw(3) << ' '; 28 cout << s1 << '\n'; 29 30 string s2; 31 for(auto c:s1) 32 s2+=toupper(c); 33 34 string s3(s2.size(),' '); 35 for(int i=1;i<=26;i++){ 36 cout << right << setw(2) << i << ' '; 37 transform(s2.begin(),s2.end(),s3.begin(),func); 38 cout << s3 << '\n'; 39 s2=s3; 40 } 41 }
运行结果截图:
实验任务7:
源代码task7.cpp
1 #include<iostream> 2 #include<algorithm> 3 #include<ctime> 4 #include<cstdlib> 5 #include<iomanip> 6 7 void addition(int &num1,int &num2); 8 void subtraction(int &num1,int &num2); 9 void multip(int &num1,int &num2); 10 void division(int &num1,int &num2); 11 12 int main(){ 13 using namespace std; 14 srand(time(0)); 15 int count=0; 16 for(int i=1;i<=10;i++){ 17 int num1,num2,useranswer,correctanswer; 18 int op=rand()%4; 19 char opchar; 20 switch(op){ 21 case 0: 22 addition(num1,num2); 23 opchar='+'; 24 correctanswer=num1+num2; 25 break; 26 case 1: 27 subtraction(num1,num2); 28 opchar='-'; 29 correctanswer=num1-num2; 30 break; 31 case 2: 32 multip(num1,num2); 33 opchar='*'; 34 correctanswer=num1*num2; 35 break; 36 case 3: 37 division(num1,num2); 38 opchar='/'; 39 correctanswer=num1/num2; 40 break; 41 } 42 cout << num1 << " " << opchar << " " << num2 << "="; 43 cin >> useranswer; 44 if(useranswer==correctanswer) 45 count++; 46 } 47 double accuracy=static_cast<double>(count)/10*100; 48 cout << fixed << setprecision(2); 49 cout << "正确率:" << accuracy << "%" << endl; 50 return 0; 51 } 52 53 void addition(int &num1,int &num2){ 54 num1=rand()%11; 55 num2=rand()%11; 56 } 57 58 void subtraction(int &num1,int &num2){ 59 num1=rand()%11; 60 num2=rand()%(num1+1); 61 } 62 63 void multip(int &num1,int &num2){ 64 num1=rand()%11; 65 num2=rand()%11; 66 } 67 68 void division(int &num1,int &num2){ 69 num2=rand()%10+1; 70 int result=rand()%11; 71 num1=result*num2; 72 }
运行结果截图:
实验总结:
1.本次实验学习了string 反转字符串、vector反转动态数组、vector实现元素旋转移位;生成随机数以及对容器类对象指定迭代器区间赋值、排序、计算最大最小平均值;利用tolower、toupper实现对字符串大小写的转化、transform实现字符变换;实现把一个十进制数x转换成n进制;打印字母密文对照表;自动生成小学生算术运算题目并自动评测。
2.在完成实验过程中,对于实验6的输出格式,一开始使用了\t,但是没有成功,在查阅相关信息后使用setw成功完成;在进行实验7时,遇到实行次数不足10次的情况,在检查代码后发现是对于除法的定义中忽略了除数为零的情况,导致程序崩溃,无法完成十次循环。修改后成功运行。