OOP-实验1
任务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 void test1(); 9 void test2(); 10 void test3(); 11 12 int main() { 13 std::cout<<"测试1: \n"; 14 test1(); 15 std::cout<<"\n测试2: \n"; 16 test2(); 17 std::cout<<"\n测试3: \n"; 18 test3(); 19 } 20 //输出c中的元素 21 template <typename T> 22 void output(const T &c) { 23 for(auto &i:c) 24 std::cout<<i<<' '; 25 std::cout<<'\n'; 26 } 27 28 void test1() { 29 using namespace std; 30 string s0{"0123456789"}; 31 cout<<"s0 = "<<s0<< endl; 32 string s1(s0); 33 //反转s1自身 34 reverse(s1.begin(),s1.end()); 35 cout<<"s1 = "<<s1<<endl; 36 string s2(s0.size(),' '); 37 //将s0反转后结果拷贝到s2, s0自身不变 38 reverse_copy(s0.begin(),s0.end(),s2.begin()); 39 cout<<"s2 = "<<s2<<endl; 40 } 41 42 void test2() { 43 using namespace std; 44 vector<int> v0{2,0,4,9}; 45 cout << "v0: "; output(v0); 46 vector<int> v1{v0}; 47 reverse(v1.begin(),v1.end()); 48 cout << "v1: "; output(v1); 49 vector<int> v2{v0}; 50 reverse_copy(v0.begin(),v0.end(),v2.begin()); 51 cout << "v2: "; output(v2); 52 } 53 54 void test3() { 55 using namespace std; 56 vector<int> v0{0,1,2,3,4,5,6,7,8,9}; 57 cout << "v0: "; output(v0); 58 vector<int> v1{v0}; 59 //循环左移1位 60 rotate(v1.begin(),v1.begin()+1,v1.end()); 61 cout << "v1: "; output(v1); 62 vector<int> v2{v0}; 63 //元素循环左移2位 64 rotate(v2.begin(),v2.begin()+2,v2.end()); 65 cout << "v2: "; output(v2); 66 vector<int> v3{v0}; 67 //循环右移1位 68 rotate(v3.begin(),v3.end()-1,v3.end()); 69 cout << "v3: "; output(v3); 70 vector<int> v4{v0}; 71 //循环右移2位 72 rotate(v4.begin(),v4.end()-2,v4.end()); 73 cout << "v4: "; output(v4); 74 }
运行测试截图
问题1 reverse 和 reverse_copy 有什么区别?
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 //模板函数 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)); //添加随机种子,time(0)每秒都不一样 19 std::cout<<"测试1: \n"; 20 test1(); 21 std::cout<<"测试2:\n"; 22 test2(); 23 return 0; 24 } 25 //输出c中元素 26 template<class 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 void test1(){ 38 using namespace std; 39 vector<int> v0(10); 40 generate(v0.begin(),v0.end(),generate_random_number); 41 cout<<"v0: "; 42 output(v0); 43 44 vector<int> v1{v0}; 45 sort(v1.begin(),v1.end()); //对v1排序 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 vector<int> v0(10); 58 generate(v0.begin(),v0.end(),generate_random_number); 59 cout<<"v0: "; 60 output(v0); 61 62 //求最大值和最小值 63 auto min_iter=min_element(v0.begin(),v0.end()); 64 auto max_iter=max_element(v0.begin(),v0.end()); 65 cout<<"min: "<<*min_iter<<endl; 66 cout<<"max: "<<*max_iter<<endl; 67 68 //同时求最大值和最小值 69 auto ans=minmax_element(v0.begin(),v0.end()); 70 cout<<"min: "<<*(ans.first)<<endl; 71 cout<<"max: "<<*(ans.second)<<endl; 72 73 //求平均值 74 double avg1=accumulate(v0.begin(),v0.end(),0.0)/v0.size(); 75 cout<<"average: "<<fixed<<setprecision(2)<<avg1<<endl; 76 sort(v0.begin(),v0.end()); 77 double avg2=accumulate(v0.begin()+1,v0.end()-1,0.0)/(v0.size()-2); 78 cout<<"去掉最大、最小值之后average: "<<avg2<<endl; 79 80 }
运行结果截图
问题1: generate 算法的作用是什么?
生成一系列值填充到指定的迭代器范围(所给的参数)中。
问题2: minmax_element 和分别调用 min_element 、 max_element 相比,有什么优势?
只需要调用一次既可获得最小和最大值,更便捷。
问题3:查询 generate 第3个参数 [](){return std::rand()%101;} 用法,与使用自定义函数
generate_random_number 相比,lambda表达式适用场景是什么?
适用场景:代码逻辑非常简单;只需要临时使用一次而不需要重复用;需要捕获外部变量。
任务3
task3.cpp
1 #include<iostream> 2 #include<string> 3 #include<algorithm> 4 #include<cctype> 5 6 unsigned char func(unsigned char c); 7 8 void test1(); 9 void test2(); 10 11 int main(){ 12 std::cout<<"测试1:字符串的大小写转换\n"; 13 test1(); 14 std::cout<<"\n测试2:字符变换\n"; 15 test2(); 16 return 0; 17 } 18 19 unsigned char func(unsigned char c){ 20 if(c=='z') return 'a'; 21 if(c=='Z') return 'A'; 22 23 if(std::isalpha(c)) return static_cast<unsigned char>(c+1); 24 25 return c; 26 } 27 28 void test1(){ 29 std::string s1{"Hello World 2049!"}; 30 std::cout<<"s1="<<s1<<std::endl; 31 32 std::string s2; 33 for(auto c:s1) s2+=std::tolower(c); 34 std::cout<<"s2="<<s2<<std::endl; 35 36 std::string s3; 37 for(auto c:s1) s3+=std::toupper(c); 38 std::cout<<"s3="<<s3<<"\n"; 39 } 40 41 void test2(){ 42 std::string s1{"I love cosmos!"}; 43 std::cout<<"s1="<<s1<<"\n"; 44 45 std::string s2(s1.size(),' '); 46 std::transform(s1.begin(),s1.end(),s2.begin(),func); 47 std::cout<<"s2="<<s2<<"\n"; 48 }
运行结果截图
1 自定义函数 func 功能是什么?
如果输入的是字符z/Z 返回字符a/A,如果输入其他字母,返回它的下一个字母,如果输入的不是字母,就返回本身。
2 tolower 和 toupper 功能分别是什么?
分别将字母转化成小/大写
3 transform 的4个参数意义分别是什么?如果把第3个参数 s2.begin() 改成 s1.begin() ,有何区别?
前两个参数是需要用到的容器内元素的起始迭代器和末尾迭代器,第四个参数是一个转换函数,将前两个迭代器范围的元素转换后写入第三个参数迭代器位置。
如果把第三个参数s2.begin()改成s1.begin(),将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( std::string s); 7 8 int main(){ 9 using namespace std; 10 string s; 11 while(cin >> s) { 12 cout << boolalpha //流操纵符控制bool输出为true/false,而不是1/0 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 for(int i=0;i<s.size()/2;i++){ 20 if(s[i]!=s[s.size()-1-i]) return false; 21 } 22 return true; 23 } 24 25 bool is_palindrome_ignore_case( std::string s){ 26 transform(s.begin(),s.end(),s.begin(),[](char c){ 27 return static_cast<char>(std::toupper(static_cast<unsigned char>(c))); 28 }); 29 for(int i=0;i<s.size()/2;i++){ 30 if(s[i]!=s[s.size()-1-i]) return false; 31 } 32 return true; 33 }
运行结果截图:
1 使用 cin >> s 输入时,输入的字符串中不能包含空格。如果希望测试字符串包含空格(如 hello oop ),代码应如何调整?
改为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,2)<<"\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 std::string res; 21 if(!x) return "0"; 22 while(x>0){ 23 int temp=x%n; 24 x/=n; 25 if(temp<10){ 26 res.insert(0,1,temp+'0'); 27 }else{ 28 res.insert(0,1,(temp-10)+'A'); 29 } 30 } 31 return res; 32 }
运行截图
任务6
task6.cpp
1 #include<iostream> 2 #include<algorithm> 3 #include<iomanip> 4 using namespace std; 5 int main(){ 6 cout<<fixed<<setw(2)<<" "; 7 vector<char> a; //字母表 8 for(int i=0;i<26;i++){ 9 cout<<fixed<<setw(2)<<static_cast<char>(i+'a'); 10 a.push_back(i+'A'); 11 } 12 cout<<"\n"; 13 for(int i=1;i<=26;i++){ 14 rotate(a.begin(), a.begin()+1, a.end()); //移位 15 cout<<fixed<<setw(2)<<i; 16 for(auto i:a) 17 cout<<fixed<<setw(2)<<i; 18 cout<<"\n"; 19 } 20 return 0; 21 }
运行截图
任务7
task7.cpp
1 #include<iostream> 2 #include<vector> 3 #include<cstdlib> 4 #include<ctime> 5 #include<iomanip> 6 using namespace std; 7 int main(){ 8 srand(time(0)); 9 vector<char> v={'+','-','*','/'}; //四个运算符数组 10 int n=10; //记录答对的题目数量 11 int count=0; 12 while(n--){ 13 char c=v[rand()%4]; //本题的运算符号 14 int ans,right_ans; 15 //a,b两个随机生成的运算数字 16 switch (c){ 17 case '+':{ 18 int a=rand()%10+1,b=rand()%10+1; 19 right_ans=a+b; 20 cout<<a<<" + "<<b<<" = "; break; 21 }case '*':{ 22 int a=rand()%10+1,b=rand()%10+1; 23 right_ans=a*b; 24 cout<<a<<" * "<<b<<" = "; break; 25 }case '-':{ 26 int a=rand()%10+1,b=rand()%(a+1); 27 right_ans=a-b; 28 cout<<a<<" - "<<b<<" = "; break; 29 }case '/':{ 30 int a=rand()%10+1,b=rand()%a+1; 31 while(a%b!=0) b=rand()%a+1; //如果不是整除关系,重新生成b 32 cout<<(int)a<<" / "<<(int)b<<" = "; 33 right_ans=a/b ;break; 34 } 35 } 36 cin>>ans; 37 //cout<<"\n"<<"right_ans:"<<right_ans<<" ans:"<<ans<<"\n"; 38 if(ans==right_ans) count++; 39 } 40 cout<<"正确率:"<<fixed<<setprecision(2)<<count*10.0<<"%"<<endl; 41 }
运行结果: