OOP-实验1
实验1
实验任务1
task 1.cpp
#include <iostream>
#include<string>
#include<vector>
#include<algorithm>template <typename T>
void output(const T &c);
void test1();
void test2();
void test3();int main()
{std::cout <<"测试1:\n";test1();std::cout <<"\n测试2:\n";test2();std::cout <<"\n测试3:\n";test3();return 0;
}template <typename T>
void output (const T &c)
{for (auto &i :c)std::cout << i <<' ';std::cout <<'\n';
}void test1()
{using namespace std;string s0{"013456789"};cout << "s0 = " << s0 << endl;string s1(s0);reverse(s1.begin(),s1.end());cout << "s1 = " << s1 << endl;string s2(s0.size(),' ');reverse_copy(s0.begin(),s0.end(),s2.begin());cout << "s2 = " << s2 << endl;
}void test2()
{using namespace std;vector<int> v0{2,0,4,9};cout <<"v0: ";output(v0);vector<int>v1{v0};reverse(v1.begin(),v1.end());cout <<"v1: ";output(v1);vector<int>v2{v0};reverse_copy(v0.begin(),v0.end(),v2.begin());cout <<"v2: ";output(v2);}void test3()
{using namespace std;vector<int> v0{0,1,2,3,4,5,6,7,8,9};cout <<"v0: ";output(v0);vector<int>v1{v0};rotate(v1.begin(),v1.begin()+1,v1.end());cout <<"v1: ";output(v1);vector<int>v2{v0};rotate(v2.begin(),v2.begin()+2,v2.end());cout <<"v2: ";output(v2);vector<int>v3{v0};rotate(v3.begin(),v3.end()-1,v3.end());cout <<"v3: ";output(v3);vector<int>v4{v0};rotate(v4.begin(),v4.end()-2,v4.end());cout <<"v4: ";output(v4);
}
运行测试截图

问题1:reverse和reverse_copy有什么区别?
reverse原地翻转,直接修改了原容器;reverse_copy先复制再翻转,不会修改原容器的值,需要另一个容器来存放结果。
问题2:rotate算法是如何改变元素顺序的?它的三个参数分别代表什么?
通过循环改变元素顺序。参数1:指向需要旋转的序列第一个元素的迭代器;参数2:指向旋转后新序列第一个元素的迭代器;参数3:指向需要旋转的序列最后一个元素的迭代器。
实验任务2
task2.cpp
#include<iostream>
#include<vector>
#include<algorithm>
#include<numeric>
#include<iomanip>
#include<cstdlib>
#include<ctime>template<typename T>
void output (const T &c);
int generate_random_number();
void test1();
void test2();int main()
{std::srand(std::time(0));std::cout << "测试1: \n";test1();std::cout << "\n测试2: \n";test2();
}template <typename T>
void output(const T &c)
{for(auto &i:c)std::cout << i <<' ';std::cout << '\n';
}int generate_random_number()
{return std::rand()%101;
}void test1()
{using namespace std;vector<int>v0(10);generate(v0.begin(),v0.end(),generate_random_number);cout << "v0: ";output(v0);vector<int>v1(v0);sort(v1.begin(),v1.end());cout << "v1: ";output(v1);vector<int>v2(v0);sort(v2.begin()+1,v2.end()-1);cout << "v2: ";output(v2);
}void test2()
{using namespace std;vector<int>v0(10);generate(v0.begin(),v0.end(),generate_random_number);cout << "v0: ";output(v0);auto min_iter=min_element(v0.begin(),v0.end());auto max_iter=max_element(v0.begin(),v0.end());cout <<"最小值: " << *min_iter << endl; cout <<"最大值: " << *max_iter << endl; auto ans=minmax_element(v0.begin(),v0.end());cout << "最小值:" << *(ans.first) << endl;cout << "最大值:" << *(ans.second) << endl;double avg1=accumulate(v0.begin(),v0.end(),0.0)/v0.size();cout <<"均值:" << fixed <<setprecision(2) << avg1 << endl;sort(v0.begin(),v0.end());double avg2=accumulate(v0.begin()+1,v0.end()-1,0.0)/(v0.size()-2);cout << "去掉最大值、最小值之后,均值:" << avg2 << endl;}
运行测试结果

问题1:generate算法的作用是什么?
生成数据并填入迭代器。
问题2:minmax_element和分别调用min_element、max_element相比,有什么优势?
minmax_element的时间复杂度为O(n),min_element、max_element的时间复杂度也是O(n),但操作次数是前者的两倍。同时minmax_element的代码也更加简洁。
问题3:查询generate第3个参数[](){return std::rand()%101;}用法,与使用自定义函数generate_random_number相比lambda表达式适用场景是什么?
[]:捕获列表,为空时不捕获外部变量;():参数列表,无参数;{return std::rand()%101;):函数功能,生成1-100的随机整数。lambda表达式适用场景是:逻辑简单,临时需要捕获外部变量。
实验任务3
task3.cpp
#include<iostream>
#include<string>
#include<algorithm>
#include<cctype>unsigned char func(unsigned char c);
void test1();
void test2();int main()
{std::cout << "测试1:字符串大小写转换\n";test1();std::cout << "\n测试2:字符变换\n";test2();
}unsigned char func(unsigned char c)
{if(c=='z')return 'a';if(c=='Z')return 'A';if(std::isalpha(c))return static_cast<unsigned char>(c+1);return c;}void test1()
{std::string s1{"Hello World 2049!"};std::cout << "s1 = " << s1 <<'\n';std::string s2;for(auto c:s1)s2+=std::tolower(c);std::cout << "s2 = " << s2 <<'\n';std::string s3;for(auto c:s1)s3+=std::toupper(c);std::cout << "s3 = " << s3 <<'\n';
}void test2()
{std::string s1{"I Love cosmos!"};std::cout << "s1 = " << s1 << '\n';std::string s2(s1.size(),' ');std::transform(s1.begin(),s1.end(),s2.begin(),func);std::cout << "s2 = " << s2 << '\n';
}
运行测试结果

问题1:自定义函数func功能是什么?
将字母进行递增转换。小写字母转换为字母表中下一个小写字母,大写字母同理,Zz则转换为Aa。非字母的数字字母等返回”c“。
问题2:tolower和toupper功能分别是什么?
tolower将大写字母转换为小写字母,toupper将小写字母转换为大写字母。
问题3:transform的4个参数意义分别是什么?如果把第3个参数s2.begin()改成s1.begin(),有何区别?
参数1:需要转换的起始字符;参数2:需要转换的末尾字符;参数3:转换后的起始字符位置;参数4:转换字符的逻辑要求。如果把第3个参数s2.begin()改成s1.begin(),转换将原地进行,s1将变为转换后的字符而不是原来的字符。
实验任务4
task4.cpp
#include<iostream>
#include<string>
#include<algorithm>bool is_palindrome(const std::string &s);
bool is_palindrome_ignore_case(const std::string &s);int main()
{using namespace std;string s;while (cin>>s){cout << boolalpha << "区分大小写:" << is_palindrome(s) << "\n"<< "不区分大小写:" << is_palindrome_ignore_case(s) << "\n\n"; }
} bool is_palindrome(const std::string &s)
{int left=0;int right=s.size()-1;while(left<right){if(s[left]!=s[right])return false; left++;right--;}return true;
}bool is_palindrome_ignore_case(const std::string &s)
{std::string s0;for(auto c:s)s0+=toupper(c) ;int left=0;int right=s0.size()-1;while(left<right){if(s0[left]!=s0[right])return false; left++;right--;}return true;
}
运行测试结果

问题:使用 cin >> s 输入时,输入的字符串中不能包含空格。如果希望测试字符串包含空格(如 hello oop ),代码应如何调整?
可以使用std::getline。while (getline(cin, s))可以读取整行输入,直到换行为止。
实验任务5
task5.cpp
#include<iostream>
#include<string>
#include<algorithm>
std::string dec2n(int x, int n=2);int main()
{int x;while (std::cin>>x){std::cout<< "十进制:" << x << "\n"<< "二进制:" << dec2n(x) << "\n"<< "八进制:" << dec2n(x,8) << "\n"<< "十二进制:" << dec2n(x,12) << "\n"<< "十六进制:" << dec2n(x,16) << "\n"<< "三十二进制:" << dec2n(x,32) << "\n";}
}std::string dec2n(int x, int n)
{if (x==0)return "0";std::string s;if(x>0){while(x>0){int yushu=x%n;//取余char asc;//0-9->'0'-'9' 10-31->'A'-'V'if(yushu<10){asc='0'+yushu;} else{asc='A'+(yushu-10);}s.push_back(asc);x/=n;}std::reverse(s.begin(),s.end());//翻转 return s;}else{x=-x;while(x>0){int yushu=x%n;//取余char asc;//0-9->'0'-'9' 10-31->'A'-'V'if(yushu<10){asc='0'+yushu;} else{asc='A'+(yushu-10);}s.push_back(asc);x/=n;}s+="-";std::reverse(s.begin(),s.end());return s;}
}
运行测试结果

实验任务6
task6.cpp
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>using namespace std;void print_row(int row);
int main()
{cout<<" ";string s="abcdefghijklmnopqrstuvwxyz";for(char c:s){cout<<" "<<c;}cout<<endl;for(int row=0;row<26;row++){print_row(row);}return 0;
}void print_row(int row)
{cout<< row+1;string s="ABCDEFGHIJKLMNOPQRSTUVWXYZ";rotate(s.begin(),s.begin()+row+1,s.end()) ;for(char c:s){cout<<" "<<c;}cout<<endl;
}
运行测试结果

实验任务7
task7.cpp
#include<iostream>
#include<ctime>
#include<cstdlib>
using namespace std;
void randnum_calculations(int &n1,int &n2,int &cal);int main()
{srand(time(0));int count=0;for(int i=0;i<10;i++){int n1,n2,cal;randnum_calculations(n1,n2,cal);int result,user;switch(cal){case 0:result=n1+n2;cout<<n1<<"+"<<n2<<"=";break;case 1:result=n1-n2;cout<<n1<<"-"<<n2<<"=";break;case 2:result=n1*n2;cout<<n1<<"*"<<n2<<"=";break;case 3:while (n2 == 0 || n1 % n2 != 0){n1 = rand() % 10 + 1;n2 = rand() % 10 + 1;}result = n1 / n2;cout << n1 << "/" << n2 << "=";break;}cin>>user;if(user==result){count++;}}double right=(double)count/10*100;cout.setf(ios::fixed);cout.precision(2);cout<<"正确率:"<<right<<"%"<<endl;return 0;
}void randnum_calculations(int &n1,int &n2,int &cal)
{n1=rand()%10+1;n2=rand()%10+1;cal=rand()%4;//加减乘除if(cal==1){if(n1<n2){swap(n1,n2);}} }
运行测试结果
