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);
}
}
}
运行测试结果
