程序设计与算法(三)C++面向对象程序设计 第八周题解(仿函数)
001:goodcopy总时间限制:1000ms内存限制:65536kB// 在此处补充你的代码描述编写GoodCopy类模板,使得程序按指定方式输出#include <iostream>using namespace std;template <class T>struct GoodCopy {};int a[2...
001:goodcopy
总时间限制:
1000ms
内存限制:
65536kB
// 在此处补充你的代码
描述
编写GoodCopy类模板,使得程序按指定方式输出
#include <iostream>
using namespace std;
template <class T>
struct GoodCopy {
};
int a[200];
int b[200];
string c[200];
string d[200];
template <class T>
void Print(T s,T e) {
for(; s != e; ++s)
cout << * s << ",";
cout << endl;
}
int main()
{
int t;
cin >> t;
while( t -- ) {
int m ;
cin >> m;
for(int i = 0;i < m; ++i)
cin >> a[i];
GoodCopy<int>()(a,a+m,b);
Print(b,b+m);
GoodCopy<int>()(a,a+m,a+m/2);
Print(a+m/2,a+m/2 + m);
for(int i = 0;i < m; ++i)
cin >> c[i];
GoodCopy<string>()(c,c+m,d);
Print(c,c+m);
GoodCopy<string>()(c,c+m,c+m/2);
Print(c+m/2,c+m/2 + m);
}
return 0;
}
输入
第一行是整数 t,表示数据组数
每组数据:
第一行是整数 n , n < 50
第二行是 n 个整数
第三行是 n 个字符串
输出
将输入的整数原序输出两次,用","分隔
然后将输入的字符串原序输出两次,也用 ","分隔
样例输入
2
4
1 2 3 4
Tom Jack Marry Peking
1
0
Ted
样例输出
1,2,3,4,
1,2,3,4,
Tom,Jack,Marry,Peking,
Tom,Jack,Marry,Peking,
0,
0,
Ted,
Ted,
来源
Guo Wei
这是典型的C++ 仿函数和内存重叠拷贝问题。
仿函数(functor),就是使一个类的使用看上去像一个函数。其实现就是类中实现一个operator(),这个类就有了类似函数的行为,就是一个仿函数类了。
在我们写代码时有时会发现有些功能实现的代码,会不断的在不同的成员函数中用到,但是又不好将这些代码独立出来成为一个类的一个成员函数。但是又很想复用这些代码。写一个公共的函数,可以,这是一个解决方法,不过函数用到的一些变量,就可能成为公共的全局变量,再说为了复用这么一片代码,就要单立出一个函数,也不是很好维护。这时就可以用仿函数了,写一个简单类,除了那些维护一个类的成员函数外,就只是实现一个operator(),在类实例化时,就将要用的,非参数的元素传入类中。这样就免去了对一些公共变量的全局化的维护了。又可以使那些代码独立出来,以便下次复用。而且这些仿函数,还可以用关联,聚合,依赖的类之间的关系,与用到他们的类组合在一起,这样有利于资源的管理(这点可能是它相对于函数最显著的优点了)。如果在配合上模板技术和policy编程思想,那就更是威力无穷了,大家可以慢慢的体会。
#include <iostream>
using namespace std;
template <class T>
struct GoodCopy {
// 在此处补充你的代码
public:
void operator() (T* begin, T* end, T* another){
if (another < end) {
for (auto it = end - 1; it >= begin; it--) {
*(another +(it-begin))= *it;
}
}
else {
for (auto it = begin; it != end; ++it) {
*another++ = *it;
}
}
}
};
int a[200];
int b[200];
string c[200];
string d[200];
template <class T>
void Print(T s, T e) {
for (; s != e; ++s)
cout << *s << ",";
cout << endl;
}
int main()
{
int t;
cin >> t;
while (t--) {
int m;
cin >> m;
for (int i = 0; i < m; ++i)
cin >> a[i];
GoodCopy<int>()(a, a + m, b);
Print(b, b + m);
GoodCopy<int>()(a, a + m, a + m / 2);
Print(a + m / 2, a + m / 2 + m);
for (int i = 0; i < m; ++i)
cin >> c[i];
GoodCopy<string>()(c, c + m, d);
Print(c, c + m);
GoodCopy<string>()(c, c + m, c + m / 2);
Print(c + m / 2, c + m / 2 + m);
}
return 0;
}
函数指针
003:简单的Filter
总时间限制:
1000ms
内存限制:
65536kB
// 在此处补充你的代码
描述
编写Filter模板,使得程序产生指定输出 不得编写 Filter函数
#include <iostream>
#include <string>
using namespace std;
bool LargerThan2(int n)
{
return n > 2;
}
bool LongerThan3(string s)
{
return s.length() > 3;
}
string as1[5] = {"Tom","Mike","Jack","Ted","Lucy"};
string as2[5];
int a1[5] = { 1,2,3,4,5};
int a2[5];
int main() {
string * p = Filter(as1,as1+5,as2,LongerThan3);
for(int i = 0;i < p - as2; ++i)
cout << as2[i];
cout << endl;
int * p2 = Filter(a1,a1+5,a2,LargerThan2);
for(int i = 0;i < p2-a2; ++i)
cout << a2[i] << ",";
return 0;
}
输入
无
输出
MikeJackLucy
3,4,5,
样例输入
无
样例输出
MikeJackLucy
3,4,5,
来源
Guo Wei
#include <iostream>
#include <string>
using namespace std;
template<class T>
T* Filter(T* start, T* end, T* begin, bool(*func)(T))
{
for (auto it = start; it < end; ++it) {
if (func(*it)) {
*begin = *it;
begin++;
}
}
return begin;
}
bool LargerThan2(int n)
{
return n > 2;
}
bool LongerThan3(string s)
{
return s.length() > 3;
}
string as1[5] = {"Tom","Mike","Jack","Ted","Lucy"};
string as2[5];
int a1[5] = { 1,2,3,4,5};
int a2[5];
int main() {
string * p = Filter(as1,as1+5,as2,LongerThan3);
for(int i = 0;i < p - as2; ++i)
cout << as2[i];
cout << endl;
int * p2 = Filter(a1,a1+5,a2,LargerThan2);
for(int i = 0;i < p2-a2; ++i)
cout << a2[i] << ",";
return 0;
}
004:函数对象的过滤器
总时间限制:
1000ms
内存限制:
65536kB
// 在此处补充你的代码
描述
程序填空输出指定结果
#include <iostream> #include <vector> using namespace std; struct A { int v; A() { } A(int n):v(n) { }; bool operator<(const A & a) const { return v < a.v; } };
template <class T> void Print(T s,T e) { for(;s!=e; ++s) cout << *s << ","; cout << endl; } template <class T1, class T2,class T3> T2 Filter( T1 s,T1 e, T2 s2, T3 op) { for(;s != e; ++s) { if( op(*s)) { * s2 = * s; ++s2; } } return s2; } ostream & operator <<(ostream & o,A & a) { o << a.v; return o; } vector<int> ia; vector<A> aa; int main() { int m,n; while(cin >> m >> n) { ia.clear(); aa.clear(); int k,tmp; cin >> k; for(int i = 0;i < k; ++i) { cin >> tmp; ia.push_back(tmp); aa.push_back(tmp); } vector<int> ib(k); vector<A> ab(k); vector<int>::iterator p = Filter(ia.begin(),ia.end(),ib.begin(),FilterClass<int>(m,n)); Print(ib.begin(),p); vector<A>::iterator pp = Filter(aa.begin(),aa.end(),ab.begin(),FilterClass<A>(m,n)); Print(ab.begin(),pp); } return 0; }
输入
多组数据
每组数据两行
第一行是两个整数 m 和 n
第二行先是一个整数k ,然后后面跟着k个整数
输出
对每组数据,按原顺序输出第二行的后k个整数中,大于m且小于n的数
输出两遍
数据保证一定能找到符合要求的整数
样例输入
1 3 1 2 2 8 5 1 2 3 4 9
样例输出
2, 2, 3,4, 3,4,
来源
Guo Wei
这道题目有一点难度,注意先要看函数
template <class T1, class T2, class T3>
T2 Filter(T1 s, T1 e, T2 s2, T3 op)
{
for (; s != e; ++s) {
if (op(*s)) {
*s2 = *s;
++s2;
}
}
return s2;
}
三个模板参数,最后一个参数是一个仿函数
传进去的是一个类对象,执行的是运算符重载,这个类对象有一个构造函数
template <class T>
struct FilterClass {
T m, n;
FilterClass(T a, T b) :m(a), n(b) {}
bool operator()(T s) {
return (m < s) && (s < n);
}
};
005:白给的list排序
总时间限制:
1000ms
内存限制:
65536kB
// 在此处补充你的代码
描述
程序填空,产生指定输出
#include <cstdio> #include <iostream> #include <algorithm> #include <list> using namespace std; int main() { double a[] = {1.2,3.4,9.8,7.3,2.6}; list<double> lst(a,a+5); lst.sort(
); for(list<double>::iterator i = lst.begin(); i != lst.end(); ++i) cout << * i << "," ; return 0; }
输入
无
输出
9.8,7.3,3.4,2.6,1.2,
样例输入
无
样例输出
同输入
来源
Guo Wei
这里按降序排序,使用了一个仿函数,greater
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <list>
using namespace std;
int main()
{
double a[] = { 1.2,3.4,9.8,7.3,2.6 };
list<double> lst(a, a + 5);
lst.sort(greater<double>()
// 在此处补充你的代码
);
for (list<double>::iterator i = lst.begin(); i != lst.end(); ++i)
cout << *i << ",";
return 0;
}
002:按距离排序
总时间限制:
1000ms
内存限制:
65536kB
// 在此处补充你的代码
描述
程序填空,输出指定结果
#include <iostream> #include <cmath> #include <algorithm> #include <string> using namespace std; template <class T1,class T2> struct Closer {
}; int Distance1(int n1,int n2) { return abs(n1-n2); } int Distance2(const string & s1, const string & s2) { return abs((int)s1.length()- (int) s2.length()); } int a[10] = { 0,3,1,4,7,9,20,8,10,15}; string b[6] = {"American","Jack","To","Peking","abcdefghijklmnop","123456789"}; int main() { int n;string s; while( cin >> n >> s ) { sort(a,a+10,Closer<int ,int (*)(int ,int)> (n,Distance1)); for(int i = 0;i < 10; ++i) cout << a[i] << "," ; cout << endl; sort(b,b+6,Closer<string,int (*)(const string &,const string & )> (s,Distance2)); for(int i = 0;i < 6; ++i) cout << b[i] << "," ; cout << endl; } return 0; }
输入
多组数据,每组一行,是一个整数n和一个字符串s
输出
定义两个整数的距离为两个整数差的绝对值
定义两个字符串的距离为两个字符串长度差的绝对值
对每组数据:
对数组a按和n的距离从小到大排序后输出。距离相同的,值小的排在前面。
然后对数组b,按照和s的距离从小到大输出。距离相同的,字典序小的排在前面
样例输入
2 a123456 4 a12345
样例输出
1,3,0,4,7,8,9,10,15,20, American,Peking,123456789,Jack,To,abcdefghijklmnop, 4,3,1,7,0,8,9,10,15,20, Peking,American,Jack,123456789,To,abcdefghijklmnop,
这个也是标准的STL仿函数的例子练习
#include <iostream>
#include <cmath>
#include <algorithm>
#include <string>
using namespace std;
template <class T1, class T2>
struct Closer {
// 在此处补充你的代码
T1 a;
T2 func;
Closer(T1 a_, T2 func_):a(a_),func(func_){}
bool operator ()(T1 a1, T1 a2) {
if (func(a1, a) == func(a2, a)) {
return a1 < a2;
}
else return func(a1, a) < func(a2, a);
}
};
int Distance1(int n1, int n2) {
return abs(n1 - n2);
}
int Distance2(const string& s1, const string& s2)
{
return abs((int)s1.length() - (int)s2.length());
}
int a[10] = { 0,3,1,4,7,9,20,8,10,15 };
string b[6] = { "American","Jack","To","Peking","abcdefghijklmnop","123456789" };
int main()
{
int n; string s;
while (cin >> n >> s) {
sort(a, a + 10, Closer<int, int (*)(int, int)>(n, Distance1));
for (int i = 0; i < 10; ++i)
cout << a[i] << ",";
cout << endl;
sort(b, b + 6, Closer<string, int (*)(const string&, const string&)>(s, Distance2));
for (int i = 0; i < 6; ++i)
cout << b[i] << ",";
cout << endl;
}
return 0;
}
006:我自己的 ostream_iterator
总时间限制:
1000ms
内存限制:
65536kB
// 在此处补充你的代码
描述
程序填空输出指定结果
#include <iostream> #include <list> #include <string> using namespace std; template <class T1,class T2> void Copy(T1 s,T1 e, T2 x) { for(; s != e; ++s,++x) *x = *s; } template<class T> class myostream_iteraotr {
}; int main() { const int SIZE = 5; int a[SIZE] = {5,21,14,2,3}; double b[SIZE] = { 1.4, 5.56,3.2,98.3,3.3}; list<int> lst(a,a+SIZE); myostream_iteraotr<int> output(cout,","); Copy( lst.begin(),lst.end(),output); cout << endl; myostream_iteraotr<double> output2(cout,"--"); Copy(b,b+SIZE,output2); return 0; }
输入
无
输出
5,21,14,2,3,
1.4--5.56--3.2--98.3--3.3--
样例输入
无
样例输出
同输入
来源
Guo Wei
这个题目有点难,需要传入的是一个对象,其中实现了* ++ =运算的重载操作。
#include <iostream>
#include <list>
#include <string>
using namespace std;
template <class T1, class T2>
void Copy(T1 s, T1 e, T2 x)
{
for (; s != e; ++s, ++x)
* x = *s;
}
template<class T>
class myostream_iteraotr
{
T x;
string str;
// 在此处补充你的代码
ostream& os;
public:
myostream_iteraotr(ostream& os_, string s):os(os_),str(s){}
void operator++ (){}
myostream_iteraotr& operator * () { return *this; }
myostream_iteraotr& operator =(const T& t)
{
os << t << str;
return *this;
}
};
int main()
{
const int SIZE = 5;
int a[SIZE] = { 5,21,14,2,3 };
double b[SIZE] = { 1.4, 5.56,3.2,98.3,3.3 };
list<int> lst(a, a + SIZE);
myostream_iteraotr<int> output(cout, ",");
Copy(lst.begin(), lst.end(), output);
cout << endl;
myostream_iteraotr<double> output2(cout, "--");
Copy(b, b + SIZE, output2);
return 0;
}

GitCode 天启AI是一款由 GitCode 团队打造的智能助手,基于先进的LLM(大语言模型)与多智能体 Agent 技术构建,致力于为用户提供高效、智能、多模态的创作与开发支持。它不仅支持自然语言对话,还具备处理文件、生成 PPT、撰写分析报告、开发 Web 应用等多项能力,真正做到“一句话,让 Al帮你完成复杂任务”。
更多推荐
所有评论(0)