实验1

任务1

源代码

// 现代C++标准库、算法库体验
// 本例用到以下内容:
// 1. 字符串string, 动态数组容器类vector、迭代器
// 2. 算法库:反转元素次序、旋转元素
// 3. 函数模板、const引用作为形参

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

// 输出容器对象c中的元素
template <typename T>
void output(const T &c) {
    for(auto &i : c)
        std::cout << i << ' ';
    std::cout << '\n';
}

// 测试1:组合使用算法库、迭代器、string反转字符串
void test1() {
    using namespace std;

    string s0{"0123456789"};
    cout << "s0 = " << s0 << endl;

    string s1(s0);
    // 反转s1自身
    reverse(s1.begin(), s1.end());  
    cout << "s1 = " << s1 << endl;

    string s2(s0.size(), ' ');
    // 将s0反转后结果拷贝到s2, s0自身不变
    reverse_copy(s0.begin(), s0.end(), s2.begin()); 
    cout << "s2 = " << s2 << endl;
}

// 测试2:组合使用算法库、迭代器、vector反转动态数组对象vector内数据
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);
}

// 测试3:组合使用算法库、迭代器、vector实现元素旋转移位
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};
    // 将[v1.begin(), v1.end())区间内元素循环左移1位
    rotate(v1.begin(), v1.begin()+1, v1.end());  
    cout << "v1: "; output(v1);

    vector<int> v2{v0}; 
    // 将[v1.begin(), v1.end())区间内元素循环左移2位
    rotate(v2.begin(), v2.begin()+2, v2.end());  
    cout << "v2: "; output(v2);

    vector<int> v3{v0};
    // 将[v1.begin(), v1.end())区间内元素循环右移1位
    rotate(v3.begin(), v3.end()-1, v3.end()); 
     cout << "v3: "; output(v3);

    vector<int> v4{v0};
    // 将[v1.begin(), v1.end())区间内元素循环右移2位
    rotate(v4.begin(), v4.end()-2, v4.end()); 
    cout << "v4: "; output(v4);
}

代码运行截图

捕获

问题回答

1、reverse(first, last):原地反转,直接修改区间本身,容器原来的数据被改写,没有新容器生成;

     reverse_copy(first, last, dest):不修改原容器,把[first, last) 反转之后的结果复制到目标迭代器dest指向的空间里,原序列保持原样不变。

 2、rotate(first, middle, last)中参数含义:first是区间起始迭代器,middle是新的起点位置迭代器,last是区间末尾迭代器;

      作用:把区间[first, last) 做循环移位,让middle指向的元素变成整个区间的第一个元素

 

任务2

源代码

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

// 输出容器对象c中的元素
template <typename T>
void output(const T &c) {
    for(auto &i : c)
        std::cout << i << ' ';
    std::cout << '\n';
}

// 测试1:组合使用算法库、迭代器、string反转字符串
void test1() {
    using namespace std;

    string s0{"0123456789"};
    cout << "s0 = " << s0 << endl;

    string s1(s0);
    // 反转s1自身
    reverse(s1.begin(), s1.end());  
    cout << "s1 = " << s1 << endl;

    string s2(s0.size(), ' ');
    // 将s0反转后结果拷贝到s2, s0自身不变
    reverse_copy(s0.begin(), s0.end(), s2.begin()); 
    cout << "s2 = " << s2 << endl;
}

// 测试2:组合使用算法库、迭代器、vector反转动态数组对象vector内数据
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);
}

// 测试3:组合使用算法库、迭代器、vector实现元素旋转移位
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};
    // 将[v1.begin(), v1.end())区间内元素循环左移1位
    rotate(v1.begin(), v1.begin()+1, v1.end());  
    cout << "v1: "; output(v1);

    vector<int> v2{v0}; 
    // 将[v1.begin(), v1.end())区间内元素循环左移2位
    rotate(v2.begin(), v2.begin()+2, v2.end());  
    cout << "v2: "; output(v2);

    vector<int> v3{v0};
    // 将[v1.begin(), v1.end())区间内元素循环右移1位
    rotate(v3.begin(), v3.end()-1, v3.end()); 
     cout << "v3: "; output(v3);

    vector<int> v4{v0};
    // 将[v1.begin(), v1.end())区间内元素循环右移2位
    rotate(v4.begin(), v4.end()-2, v4.end()); 
    cout << "v4: "; output(v4);
} 

代码运行截图

屏幕截图 2026-10-20 190856

问题回答

1、generate(first, last, func)遍历区间[first, last),对区间里每一个元素,调用一次func函数,把func返回的值赋值给当前元素,用来批量填充容器。

2、min_element、max_element分开写要扫描两组数据,一遍找最小,一遍找最大;minmax_element只扫描一遍区间,同时找出最小值和最大值,返回值是一个pair——first是最小值迭代器,second是最大值迭代器。优点是遍历次数更少,效率更高。

3、效果等同。lambda函数本质是编译器自动生成一个匿名函数类,该类重载了operator( ),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);
    
    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';
}

代码运行结果

屏幕截图 2026-10-20 190856

问题回答

1、自定义函数func功能:对字母做后移一位变换,非字母字符原样返回不改变。

2、std::tolower(c):把字母转为小写,非字母保持不变;std::toupper(c):把字母转为大写,非字母保持不变。

3、transform(first, last, dest, op)参数含义:first是原区间起始迭代器,last是原区间末尾迭代器,dest是目标写入位置的起始迭代器,op是变换函数或可调用对象,输入一个源元素,返回变换后的值。原写法dest = s2.begin( )是把变换结果写入另一个独立字符串s2,源字符串s1保持不变;改成dest = s1.begin( )后是原地变换,覆盖原来s1本身的内容,s1原始数据丢失。

 

任务四

源代码

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

    // 多组输入,直到按下Ctrl+Z结束测试
    while(cin >> s) {
        cout << boolalpha 
             << "区分大小写: " << is_palindrome(s) << "\n"
             << "不区分大小写: " << is_palindrome_ignore_case(s) << "\n\n";
    }     
}


// 函数is_palindrome定义
// 待补足
// ×××
bool is_palindrome(const std::string &s)
{
	int l = 0, r = s.size()-1;
	while(1<r)
	{
		if(s[1] != s[r])
		    return false;
		    l++;
		    r--;
	}
	return true;
}

// 函数is_palindrome_ignore_case定义
// 待补足
// ×××
bool is_palindrome_ignore_case(const std::string &s)
{
	int l = 0, r = s.size()-1;
	while(1<r)
	{
		unsigned char cl = static_cast<unsigned char>(s[l]);
		unsigned char cr = static_cast<unsigned char>(s[r]);
		if(tolower(cl) != tolower(cr))
		    return false;
		    l++;
		    r--;
	}
	return true;
}

代码运行结果

屏幕截图 2026-10-20 212415

问题回答

代码调整:将main函数中的while(cin >> s)改为while(getline(cin, s))

 

任务五

 源代码

#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\n";
    }
}

// 函数dec2n定义
std::string dec2n(int x, int n)
{
    if (x == 0)
    {
        return "0";
    }
    std::string table = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    std::string res;
    while (x > 0)
    {
        int rem = x % n;
        res += table[rem];
        x = x / n;
    }
    std::reverse(res.begin(), res.end());
    return res;
}

代码运行结果 

屏幕截图 2026-10-22 172132

 

任务六

源代码

#include <iostream>
#include <iomanip>
using namespace std;

int main()
{
    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" << endl;
    for(int i = 1; i <= 26; ++i)
    {
        cout << setw(2) << i;
        for(int j = 0; j < 26; ++j)
        {
            char ch = 'A' + (i - 1 + j) % 26;
            cout << " " << ch;
        }
        cout << endl;
    }
    return 0;
}

代码运行结果

屏幕截图 2026-10-20 190856

 

任务七

源代码

#include <iostream>
#include <cstdlib>
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <iomanip>
#include <utility>
using namespace std;

// pair:first是算式答案,second是题目字符串
pair<int, string> createQuestion()
{
    int op = rand() % 4;
    int a, b, res;
    string expr;
    if (op == 0)
    {
        a = rand()%10 + 1;
        b = rand()%10 + 1;
        res = a + b;
        expr = to_string(a) + " + " + to_string(b) + " = ";
    }
    else if (op == 1)
    {
        a = rand()%10 + 1;
        b = rand()%a + 1;
        res = a - b;
        expr = to_string(a) + " - " + to_string(b) + " = ";
    }
    else if (op == 2)
    {
        a = rand()%10 + 1;
        b = rand()%10 + 1;
        res = a * b;
        expr = to_string(a) + " * " + to_string(b) + " = ";
    }
    else
    {
        b = rand()%10 + 1;
        int k = rand()%10 + 1;
        a = b * k;
        res = a / b;
        expr = to_string(a) + " / " + to_string(b) + " = ";
    }
    return make_pair(res, expr);
}

int main()
{
    srand((unsigned)time(0));
    int right = 0;
    const int n = 10;
    for(int i = 0; i < n; i++)
    {
        auto q = createQuestion();
        cout << q.second;
        int ans;
        cin >> ans;
        if(ans == q.first)
            right++;
    }
    double rate = 100.0 * right / n;
    cout << "正确率:" << fixed << setprecision(2) << rate << "%" << endl;
    return 0;
}

代码运行结果

屏幕截图 2026-10-22 174004

 

实验总结

本次实验练习了lambda、pair以及字符串处理和随机数编程,我熟悉了循环分支的使用,同时也对输出格式、数据合法性等细节有了更深刻的认识。

posted @ 2026-10-22 18:05  黄君琴  阅读(4)  评论(0)    收藏  举报