实验一
任务一:
实验源代码:
#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();
}
template<typename T>
void output(const T &c){
for(auto &i : c)//遍历容器 `c` 里面每一个元素,依次把元素引用给到变量 `i`
std::cout << i << ' ';
std::cout << '\n';
}
void test1(){
using namespace std;
string s0{"0123456789"};
cout << "s0 = " << s0 << endl;
string s1{s0}; // 拷贝构造函数
reverse(s1.begin(), s1.end()); // 反转字符串
cout << "s1 = " << s1 << endl;
string s2(s0.size(), '\0'); // 构造一个长度为 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 : ";// 输出容器 v0 的内容
output(v0);// 输出容器 v0 的内容
vector<int> v1{v0};
//将[v1.begin(),v1.end())区间内元素循环左移1位
std::rotate(v1.begin(), v1.begin() + 1, v1.end());
cout << "v1 : ";
output(v1);
vector<int> v2{v0};
//将[v2.begin(),v2.end())区间内元素循环左移2位
std::rotate(v2.begin(), v2.begin() + 2, v2.end());
cout << "v2 : ";
output(v2);
vector<int> v3{v0};
//将[v3.begin(),v3.end())区间内元素循环右移1位
std::rotate(v3.begin(), v3.end() - 1, v3.end());
cout << "v3 : ";
output(v3);
vector<int> v4{v0};
//将[v4.begin(),v4.end())区间内元素循环右移2位
std::rotate(v4.begin(), v4.end() - 2, v4.end());
cout << "v4 : ";
output(v4);
}
/*
问题一:reverse()和reverse_copy()的区别是什么?
reverse()的反转是直接在原有容器中进行的,
而reverse_copy()是反转后拷贝到另一个容器中,
在使用reverse_copy()时需要指定目标容器的起始位置,
还有目标容器的大小必须大于等于源容器的大小,否则会发生越界访问。
问题二:rotate算法是如何改变元素顺序的?它的三个参数分别代表什么?
rotate算法是将指定范围内的元素进行循环移动,改变元素的顺序。
rotate算法的三个参数分别是:
1. `first`:指向要旋转的范围的起始位置
2. `middle`:指向要移动到末尾的元素位置
3. `last`:指向要旋转的范围的结束位置
*/
运行截图如下:
任务二:
实验源代码:
#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(nullptr));//使用当前时间作为随机数种子,保证每次运行程序时生成的随机数序列不同
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; //生成0到100之间的随机整数
}
//测试1:对容器类对象指定迭代器区间赋值,排序
void test1(){
using namespace std;
vector<int> v0(10); //创建一个动态数组对象v0,对象大小为10
generate(v0.begin(),v0.end(),generate_random_number);//使用generate算法生成随机数填充v0容器
cout << "v0 : ";
output(v0);
vector<int> v1{v0}; //拷贝构造函数
sort(v1.begin(),v1.end());//使用sort算法对v1容器进行排序
cout << "v1 : ";
output(v1);
vector<int> v2{v0}; //拷贝构造函数
sort(v2.begin()+1,v2.end()-1);//使用sort算法对v2容器的部分元素进行排序
cout << "v2 : ";
output(v2);
}
//测试2:对容器类对象指定迭代器区间赋值,计算最大值/最小值/均值
void test2(){
using namespace std;
vector<int> v0(10); //创建一个动态数组对象v0,对象大小为10
generate(v0.begin(),v0.end(),generate_random_number);//使用generate算法生成随机数填充v0容器
cout << "v0 : ";
output(v0);
auto min_iter = min_element(v0.begin(),v0.end());//min_element算法返回的是位置,不是值
auto max_iter = max_element(v0.begin(),v0.end());//min_element算法返回的是位置,不是值
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;//fixed和setprecision是iomanip头文件中的函数,用于设置输出的格式,fixed表示以固定小数点形式输出,setprecision(2)表示保留两位小数
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返回的是两个的合集,包含最小值和最大值,
而min_element和max_element分别返回最小值和最大值。
使用minmax_element可以减少一次遍历,提高效率。
问题3:把代码中函数generate_random_number()的声明和定义注释起来,把两处调用改为
generate(v0.begin(),v0.end(),[](){return std::rand()%101;});
观察效果是否等同?
答:等同
c++中lambda表达式用法
答:lambda表达式是一种匿名函数对象,可以在需要函数对象的地方使用。它的基本语法是:
[捕获列表](参数列表) mutable -> 返回类型 { 函数体 }
最小可用形式:[]{} 一个什么都不做,不接受参数的lambda
*/
运行截图如下:
任务三:
实验源代码:
#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);//将字符的ASCII码值加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::towlower(c);//将字符串s1中的每个字符转换为小写字母,并将结果存储在字符串s2中
std::cout << "s2 = " << s2 << '\n';
std::string s3;
for(auto c: s1)
s3 += std::towupper(c);//将字符串s1中的每个字符转换为大写字母,并将结果存储在字符串s3中
std::cout << "s3 = " << s3 << '\n';
}
void test2(){
std::string s1{"I love cosmos!"};
std::cout << "s1 = " << s1 << '\n';
std::string s2(s1.size(),' ');//创建一个与s1大小相同的空字符串s2
std::transform(s1.begin(),s1.end(),s2.begin(),func);//使用transform算法将字符串s1中的每个字符通过func函数进行变换,并将结果存储在字符串s2中
std::cout << "s2 = " << s2 << '\n';
}
/*
问题1:自定义函数func功能是什么?
答:自定义函数func的功能是将输入的字符进行变换
如果字符是字母
则将其转换为下一个字母(例如'a'变为'b','z'变为'a','A'变为'B','Z'变为'A')
如果字符不是字母,则保持不变。
前两个if确定边界
后一个if执行转换
问题2:tolower和toupper函数的功能是什么?
答:tolower函数的功能是将输入的字符转换为小写字母,如果输入的字符不是字母,则保持不变。
toupper函数的功能是将输入的字符转换为大写字母,如果输入的字符不是字母,则保持不变。
问题2:transform的4个参数分别是什么?如果把第三个参数s2.begin()改为s1.begin()有何区别?
答:transform的4个参数分别是:
1. 输入范围的起始迭代器(s1.begin())
2. 输入范围的结束迭代器(s1.end())
3. 输出范围的起始迭代器(s2.begin())
4. 要应用的函数(func)
如果把第三个参数s2.begin()改为s1.begin()
则会将变换后的结果直接写回到原字符串s1中
这样会覆盖原有的字符。
*/
实验截图如下
任务四:
实验源代码:
#include <iostream>
#include <string>
#include <algorithm>
#include <cctype>
#include <iterator> // 提供了迭代器相关的功能,如反向迭代器、插入迭代器等。
bool is_palindrome(const std::string &s);
bool is_palindrome_ignore_case(const std::string &s);
int main() {
using namespace std;
string s;
// 多组输入,直到按下 Ctrl+Z 结束测试
while(cin >> s) {
cout << boolalpha
<< "区分大小写: " << is_palindrome(s) << "\n"
<< "不区分大小写: " << is_palindrome_ignore_case(s) << "\n\n";
}
}
// 函数is_palindrome定义
// 待补足
// xxx
bool is_palindrome(const std::string &s){
std::string reversed_s(s.rbegin(), s.rend()); // 创建一个反转的字符串
return s == reversed_s;
}
// 函数is_palindrome_ignore_case定义
// 待补足
// xxx
bool is_palindrome_ignore_case(const std::string &s){
std::string lower_s;
lower_s.reserve(s.size()); // 预分配空间以提高效率
std::transform(s.begin(),s.end(),std::back_inserter(lower_s),[](unsigned char c){ return std::tolower(c); }); // 将字符串转换为小写
std::string reversed_lower(lower_s.rbegin(),lower_s.rend()); // 创建一个反转的小写字符串
return lower_s == reversed_lower;
}
实验截图如下
任务五:
实验源代码:
#include <iostream>
#include <algorithm>
#include <string>
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\n";
}
}
// 函数dec2n定义
// 待补足
// xxx
std::string dec2n(int x, int n)
{
const std::string table = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
if (x == 0)
{
return "0";
}
std::string res;
while (x > 0)
{
int rem = x % n;
res += table[rem];
x = x / n;
}
std::reverse(res.begin(), res.end());
return res;
}
实验截图如下

任务六:
实验源代码:
#include <iostream>
using namespace std;
int main()
{
// 第一行:明文 a~z
cout << " 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\n";
// 26行密文,偏移量 1~26
for (int k = 1; k <= 26; ++k)
{
cout << k;
if(k < 10) cout << " ";
else cout << "";
for (int i = 0; i < 26; ++i)
{
char ch = 'A' + (i + k) % 26;
cout << ch << " ";
}
cout << endl;
}
return 0;
}
实验截图如下

任务七:
实验源代码:
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <iomanip>
using namespace std;
int main()
{
srand((unsigned)time(0));
int right = 0;
const int total = 10;
for (int i = 0; i < total; i++)
{
int a, b, op;
char opc;
int ans;
// 随机生成合法题目
while (true)
{
a = rand() % 10 + 1;
b = rand() % 10 + 1;
op = rand() % 4; // 0+,1-,2*,3/
if (op == 0)
{
opc = '+';
ans = a + b;
break;
}
else if (op == 1)
{
if (a >= b)
{
opc = '-';
ans = a - b;
break;
}
}
else if (op == 2)
{
opc = '*';
ans = a * b;
break;
}
else if (op == 3)
{
if (b != 0 && a % b == 0)
{
opc = '/';
ans = a / b;
break;
}
}
}
int userIn;
cout << a << " " << opc << " " << b << " = ";
cin >> userIn;
if (userIn == ans)
{
right++;
}
}
double rate = 100.0 * right / total;
cout << fixed << setprecision(2) << "正确率: " << rate << "%" << endl;
return 0;
}
实验截图如下


浙公网安备 33010602011771号