实验一

任务一:

实验源代码:

#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`:指向要旋转的范围的结束位置

*/

运行截图如下:89bd097469edf8460d3bf3499758546b

任务二:

实验源代码:

#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


*/

运行截图如下:e672a214de83a07b966af76dc56d2325

任务三:

实验源代码:

#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中
这样会覆盖原有的字符。
*/

实验截图如下862a8ae8abe1ccf6b63dfe438f23dda3

任务四:

实验源代码:

#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;
}

实验截图如下4ea1f1b6483e286951ebaaf4788ca3da

任务五:

实验源代码:

#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;
}

实验截图如下
4efec98f22ad11fa4e8db5652fc017df

任务六:

实验源代码:

#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;
}

实验截图如下
c3648fcdada6cc798486ef2f23c2935a

任务七:

实验源代码:

#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;
}

实验截图如下
be073ce8c34ca24e83472039c4e9ab0b

posted @ 2026-10-21 22:20  TDTTDT  阅读(6)  评论(0)    收藏  举报