本次上机涉及内容:模板,STL(1)(2)。
字符串排序
描述
请按照要求对输入的字符串进行排序。
|
|
输入
第一行是正整数 $T$ ,表示测试数据的组数,每组测试数据输入共两行。
第一行是正整数 $N$ ,表示字符串个数,第二行是 $N$ 个字符串, 字符串间用空格分离。
|
|
输出
对于每组测试数据,先输出一行:Case: n,如对第一组数据就输出Case: 1。
第二行按照字符串长度从小到大排序之后输出 $N$个字符串,字符串之间以空格间隔(不会出现字符串长度相同的情况)
第三行按照字符串首字符ASCII码序从小到大排序之后输出 $N$ 个字符串,字符串之间以空格间隔(不会出现字符串首字母相同的情况)
|
|
Solution
这里我们可以看到,题目中给了我们get_name和get_size两个函数,那就把它用起来吧
同时从友元看出,需要我们重载<这个运算符
同时,需要写出一个MyLarge的模板类
然后,还需要写出show和print两个函数
最大意的地方在于之前忘记模板类的对象可以通过重载()运算符来仿函数,所以卡了一会
|
|
按距离排序
描述
根据输出完善程序。
|
|
输入
多组数据,每组一行,是一个整数 $n$ 和一个字符串 $s$ 。
|
|
输出
定义两个整数的距离为两个整数差的绝对值,定义两个字符串的距离为两个字符串长度差的绝对值。
对每组数据:
对数组 $a$ 按和 $n$ 的距离从小到大排序后输出。距离相同的,值小的排在前面。
然后对数组 $b$ ,按照和 $s$ 的距离从小到大输出。距离相同的,字典序小的排在前面。
|
|
Solution
重题,见elainafan-从零开始的STL(1) 。
回调函数
描述
输入 $x_1,x_2,x_3,x_4,x_5$ ,输出 $y = x_5^5 + x_4^4 + x_3^3 + x_2^2 + x_1 + 1$ 的 $y$ 的值。
|
|
输入
多组数据。第一行是数据组数 $n$ 。
每组数据为一行,5个整数,$x_1,x_2,x_3,x_4,x_5$ 。数值不大,不必考虑溢出。
|
|
输出
对每组数据,输出一个整数 $y,y = x_5^5 + x_4^4 + x_3^3 + x_2^2 + x_1 + 1$ 。
|
|
Solution
很明显地,这题需要使用仿函数进行计算,观察到用于转换构造函数的整型变量为 $1 \sim 5$ ,也就是幂次。
于是只需要重载()运算符进行幂运算即可。
|
|
Printer
描述
完成以下程序,使得输入的整数 $x$ ,以及若干正整数,将大于 $x$ 的正整数输出。
然后输入若干字符串,将字符串长度大于 $x$ 的字符串输出。
|
|
输入
第一行是整数 $t$ ,表示一共 $t$ 组数据,每组数据有三行。
第一行是整数 $x$ 和整数 $n$ ,第二行是 $n$ 个整数,第三行是 $n$ 个不带空格的字符串。
|
|
输出
对每组数据,先按原序输出第一行中大于 $x$ 的正整数(数据保证会有输出)。
再按原序输出第二行中长度大于 $x$ 的字符串(数据保证会有输出)。
|
|
Solution
首先回想for_each行为,for_each(first,last,f)可以看成以下形式:
|
|
因此这里仍然是要重载()运算符让它称为仿函数形式。
这里可以使用模板类,只重载一个()运算符,但是比较麻烦。所以这里选择了使用普通类,重载两次()运算符,较为直观。
|
|
矩阵排序
描述
创建矩阵类,要求能够输入整数类型的 $m \times n$ 矩阵,并按照元素个数,矩阵中元素之和,创建矩阵顺序对矩阵类分别排序。
|
|
输入
前两行是一个 $2 \times 2$矩阵,之后三行是一个 $3 \times 4$矩阵,最后两行是一个 $2 \times 2$矩阵。
|
|
输出
先按照元素个数从小到大输出三个矩阵(大小相同时后创建的矩阵先输出)。
再按照元素之和从小到大输出三个矩阵(大小相同时后创建的矩阵先输出)。
再按照矩阵创建顺序从先到后输出三个矩阵(矩阵排列方式与输入相同,每个元素后用一个空格进行分隔)
|
|
Solution
其实是简单的矩阵题,观察主函数代码,发现需要实现传入长宽的转换构造函数,这个构造函数要干什么事?
首先就是要用一个指针表示二维数组,所以要向堆取空间,其次就是要记录整个矩阵大小,以及初始化矩阵和为0,还有要记录它输入的id。
至于输入id怎么来?维护一个静态成员变量就可以了。
再往下看,由于需要排序,因此需要重载小于运算符。
接着,由于需要输出和输入,因此需要重载输入输出运算符。
|
|
数组输出
描述
填写代码,创建Print模板类,要求对输入的字符串数组或整数数组,用模板类进行输出并自动换行。
|
|
输入
有多个输入样例。 每个样例的第一行为两个整数 $m,n(m,n \leq 20)$ 。
每个样例的第二行为 $m$ 个字符串。
每个样例的第三行为 $n$ 个整数。
|
|
输出
对每个样例输出两行。
第一行为输入的字符串(去除空格),第二行为输入的整数(去除空格)。
|
|
Solution
这里用到了accumulate,回忆一下它的用法,就是accumulate(begin,end,init),将从begin到end的元素都加到init上去。
那么,联想到之前实现过的链式加法,只需要重载加法运算符时返回Print<T>&型对象,也就是返回this指针。
而转换构造函数则传入需要加的数量x,完全可以通过链式调用模拟循环的形式,因为每次加完可以对成员变量x进行处理,以模拟每次循环。
|
|
正向与反向输出
描述
输入一个的序列,首先输出原序列,每个元素之间以"—“分开。
再将序列的每个元素翻倍,并逆序输出原序列,每个元素之间以”***“分开。
|
|
输入
第一行是测试数据组数 $k$ 。
测试数据共有 $k$ 组,每组首先输入序列长度 $n$ ,接下来 $n$ 个整数分别代表序列的 $n$ 个数。
|
|
输出
对于每组测试数据输出两行,分别是以”—“分割的原序列,和以”***“分割的翻倍后的逆序序列。
|
|
Solution
代码要求实现C1类,这里需要搞懂它在干啥。
先看主函数,它接受一个int和vector<int>变量作为转换构造函数的变量,同时还需要实现一个拷贝构造函数。
然后ostream_iterator这一行,它是一个输出迭代器,专门输出int类,输出到cout中,每输出一个数,后面跟---。
接下来看到copy,联想之前学过的,这里是将o1从头开始的size个元素,依次复制到cout,每个后面跟---。
也就是说,需要重载*运算符,而它直接返回vector<int>的起始迭代器即可,也就是.begin()。
随后,还需要重载[]运算符,由于有修改,应该返回int&类型对象,注意由于输出是逆序的,因此这里也要是逆序的,前面保留的数组大小就帮了大忙。
|
|
找第一个最小的
描述
写出 FindFirstLess 模板,用于寻找序列中小于某指定值的第一个元素。
|
|
输入
第一行是测试数据组数 $T$ ,接下来有 $2 \times T$ 行,每两行是一组测试数据。
每组数据第一行开始是一个整数,表示这组数据有 $n$ 项;接下来是一个字母,如果是’N’,表示这组数据都是整数,如果是’S’表示这组数据都是字符串。
第二行就是 $n$ 个整数,或者 $n$ 个字符串。
|
|
输出
对每组数据,输出第二行的前n-1项里面,第一个小于第n项的 。如果找不到,输出 “Not Found”。
|
|
Solution
这里观察到FindFirstLess传入了两个迭代器,一个参数,和一个判断函数。
因此需要使用模板函数,其中有三个模板类。
同时,注意到传入的两个判断函数都是less,因此不需要用它来判断,直接逐一比对即可,也不要想复杂去用二分啥的,这道题数据不会卡复杂度。
|
|
输出Fibonacci数列
描述
Fibonacci数列指的是数列第一项和第二项为1,之后每一项是之前两项的和所构成的数列。 现有多组数据,每组数据给出一个数字 $n$ ,请你输出Fibonacci数列的前 $n-1$项。
|
|
输入
每组数据一行,整数 $n$ ,输入以0结尾。
|
|
输出
对每组数据输出前 $n-1$ 项。
|
|
Solution
在正向和反向输出这道题里,已经解释过了Copy跟ostream_iterator的原理了,因此这里不再解释。
然后看到Copy函数,这里传入了f1和f2,需要重载它的!=、前自加、*运算符,这是很显然的。
随后,就要考虑for(int i=1;i<=n;i++)怎么在Copy的这个循环里体现。
一个很巧妙的思路是,用一个成员变量记录当前的项数,然后不等于就重载为比较两者的项数,这个成员变量也存在于转换构造函数中。
同时,前自加就是将当前项移到斐波那契数列的下一项,并且项数加一。
最后,重载解引用就很自然地返回当前项,而因为是斐波那契数列,类中还需要存储上一项。
|
|
改良过的CArray3d三维数组模板类
描述
根据输出完善程序。
|
|
输入
|
|
输出
|
|
Solution
唯一一个变化是,原本的memset(a[1], -1, 60 * sizeof(int));变为了memset(a, -1, 60 * sizeof(int));。
于是,使用上次的代码这里会报错,那么怎么办?
回想起memset传入的第一个参数通常是数组名,也就是一个指针,因此只需要实现CArray3D转换为T*类型的强制类型转换函数,即可。
关于本题其它部分的解析见elainafan-从零开始的STL(1) 。
|
|