面向对象程序设计-17-类模板

声明

题解包含以下内容:

  • (相对)高级的 C++ 模板及语法技巧
  • 仅适用于 C++20 标准的代码
  • 强烈的个人代码风格和 Modern C++ 范式追求
  • 泛滥的标准库函数

换句话说就是(相较于其他公开题解)更低的查重率和更高的使用门槛;请酌情使用。

【id:100】【20分】A. 倚天屠龙记(函数模板)

题目描述

江湖中有一个传言,只要倚天剑和屠龙刀中暗藏的秘密拼到一起,就能得到天下无敌的内功秘笈。设计一个函数模板,完成拼凑的功能(将倚天剑的秘密连接到屠龙刀的后面),并将秘笈输出. 其中每个秘密由n个元素组成,类型为T。

输入

第一行输入t表示有t个测试实例

第二行先输入一个大写字母表示数据类型,I表示整数类型,D表示双精度数类型,C表示字符型;然后输入n表示数据个数。

第三行输入倚天剑的n个数据

第四行输入屠龙刀的n个数据

依次输入t个实例

输出

每行输出一个结果

样例

输入样例1输出样例1
2
I 5
5 3 51 27 9
27 0 0 5 1
C 5
kitty
hello
2700515351279
hellokitty

Answer

#include<bits/stdc++.h>
using namespace std;

template<typename T>
vector<T> generate_arr( size_t size )
{
  vector<T> ret; ret.reserve( size );
  for ( size_t i = 0; i < size; ++i ) {
    T tmp; cin >> tmp;
    ret.push_back( move( tmp ) );
  }
  return ret;
}

template<typename T>
ostream& operator<<( ostream& os, const vector<T>& arr )
{
  for ( auto e : arr ) os << e;
  return os;
}

int main()
{
  size_t t; cin >> t;
  while ( t-- ) {
    char type_tag; size_t scale;
    cin >> type_tag >> scale;
    type_tag = toupper( type_tag );
    if ( type_tag == 'I' ) {
      auto sword = generate_arr<int>( scale ),
        knife = generate_arr<int>( scale );
      cout << knife << sword << endl;
    } else if ( type_tag == 'C' ) {
      auto sword = generate_arr<char>( scale ),
        knife = generate_arr<char>( scale );
      cout << knife << sword << endl;
    } else {
      auto sword = generate_arr<double>( scale ),
        knife = generate_arr<double>( scale );
      cout << knife << sword << endl;
    }
  }
}

【id:327】【20分】B. OOP 两点间距离(类模板+函数模板)

题目描述

写一个Point类模板,数据成员是两个相同类型的数(int或者double型),分别表示点的X和Y坐标。构造函数和成员函数根据需要添加。

写一个全局函数模板(function template),参数是2个Point类型的对象,函数返回两点之间的距离(浮点数)。

主函数中分别输入两组值,调用函数输出结果。

输入

一共有8个数字。

首先是四个浮点数dx1,dy1,dx2,dy2,分别表示两个浮点型点的坐标

然后是四个整数ix1,iy1,ix2,iy2分别表示两个整型点的坐标

输出

先输出点(dx1,dy1,)到点(dx2,dy2,)的距离,换行。

然后输出点(ix1,iy1)到点(ix2,iy2)的距离,换行。

样例

输入样例1输出样例1
1.5 3.5 5.5 7.5
3 4 5 6
5.65685
2.82843

Answer

#include <bits/stdc++.h>
using namespace std;

template<typename T>
  requires std::disjunction_v<
    std::is_same<T, int>,
    std::is_same<T, double>
  >
class Point {
  T x, y;

public:
  Point( T xx, T yy )
    : x { xx }, y { yy } {}
  Point() : Point( {}, {} ) {}
  T get_x() const noexcept { return x; }
  T get_y() const noexcept { return y; }

  friend istream& operator>>( istream& is, Point<T>& pt )
  {
    is >> pt.x >> pt.y;
    return is;
  }
};

template<typename T1, typename T2>
double point_distance( T1&& pt1, T2&& pt2 )
{
  return sqrt( (pt1.get_x() - pt2.get_x()) * (pt1.get_x() - pt2.get_x()) +
               (pt1.get_y() - pt2.get_y()) * (pt1.get_y() - pt2.get_y()) );
}

int main()
{
  Point<double> pt1, pt2;
  cin >> pt1 >> pt2;
  cout << point_distance( pt1, pt2 ) << endl;

  Point<int> pt11, pt22;
  cin >> pt11 >> pt22;
  cout << point_distance( pt11, pt22 ) << endl;
}

【id:101】【20分】C. 简单类模板(类模板)

题目描述

定义一个列表类,该列表包含属性:数值列表(用长度为100的数组表示),数据长度(实际的数据个数);包含的方法:初始化、插入、删除、打印,方法定义为:

1)初始化,接受外来参数,把数据保存在数值列表中,未使用的列表部分全部初始化为-1

2)插入,接受外来参数的插入位置和插入数值,插入位置从0开始计算,注意从插入位置开始,原有数据都要往后移动一位,且数据长度+1

3)删除,接受外来参数的删除位置,删除位置从0开始计算,注意从删除位置后一位开始,原有数据都要往前移动一位,且数据长度-1

4)打印,把包含的数据按位置顺序输出一行,数据之间单个空格隔开

使用类模板的方法,使得这个类支持整数int类型和浮点数double类型

输入

第一行先输入参数n表示有n个数据,接着输入n个整数

第二行输入两个参数,表示插入位置和插入数值,数值为整数

第三行输入删除位置

第四行先输入参数n表示有n个数据,接着输入n个浮点数

第五行输入两个参数,表示插入位置和插入数值,数值为浮点数

第六行输入删除位置

输出

针对头三行输入,分别执行初始化、插入操作和删除操作,调用打印方法输出列表包含的整数数据

针对接着的三行输入,分别执行初始化、插入操作和删除操作,调用打印方法输出列表包含的浮点数数据

样例

输入样例1输出样例1
5 11 22 33 44 55
2 888
4
5 1.1 2.2 3.3 4.4 5.5
2 88.8
3
11 22 888 33 55
1.1 2.2 88.8 4.4 5.5

Answer

#include <bits/stdc++.h>
using namespace std;

template<typename T, typename... Args>
concept AllSame = (same_as<T, Args> && ...);

template<typename T>
  requires is_arithmetic_v<T>
class myList {
  std::array<T, 100> arr_;
  size_t data_length_;

public:
  template<AllSame<T> ... Args>
  myList( Args&&... args ) {
    arr_ = { forward<Args>( args )... };
    data_length_ = sizeof...(args);
    fill( arr_.begin() + data_length_, arr_.end(), -1 );
  }

  void insert( size_t insert_pos, T value ) {
    if ( insert_pos >= 100 )
      return;
    memcpy( arr_.data() + insert_pos + 1, arr_.data() + insert_pos, sizeof( T ) * (data_length_ - insert_pos) );
    arr_[insert_pos] = value;
    data_length_++;
  }

  void erase( size_t erase_pos ) {
    if ( erase_pos >= 100 )
      return;
    memcpy( arr_.data() + erase_pos, arr_.data() + erase_pos + 1, sizeof( T ) * (data_length_ - erase_pos - 1) );
    arr_[data_length_ - 1] = -1;
    data_length_--;
  }

  void display() const {
    for ( size_t i = 0; i < data_length_; ++i )
      cout << arr_[i] << (i < data_length_ - 1 ? " " : "");
    cout << endl;
  }

  void input( size_t scale ) {
    for ( size_t i = 0; i < scale; ++i )
      cin >> arr_[data_length_++];
  }
};

template<typename T>
void foo()
{
  size_t n {}; cin >> n;
  myList<T> lis; lis.input( n );

  size_t insert_pos {}; T insert_val {};
  cin >> insert_pos >> insert_val;
  lis.insert( insert_pos, insert_val );

  size_t erase_pos {}; cin >> erase_pos;
  lis.erase( erase_pos );
  lis.display();
}

int main()
{
  foo<int>();
  foo<double>();
}

【id:103】【20分】D. 有界数组模板类(类模板)

题目描述

编写有界数组模板BoundArray(即检查对数组元素下标引用并在下标越界时终止程序的执行),能够存储各种类型的数据。要求实现对数组进行排序的方法sort,及对数组进行查找的方法search。

输入

第一行先输入t,表示有t个测试用例

从第二行开始输入每个测试用例的数据。

首先输入数据类型,I表示int,D表示double,C表示char,接着输入数组的元素个数

然后输入每个元素

最后输入要查找的元素

输出

首先输出从小到大排序的元素

然后输出查找元素的结果,找到则输出下标,没找到则输出-1

样例

输入样例1输出样例1
2
I 2
1 2
2
D 3
3.5 6.2 2.9
2.1
1 2
1
2.9 3.5 6.2
-1

Answer

#include <bits/stdc++.h>
using namespace std;

template<typename T>
  requires is_arithmetic_v<T>
class BoundArray {
  std::vector<T> arr_;

public:
  void my_sort() {
    std::sort( arr_.begin(), arr_.end() );
  }

  T search( const T& value ) const {
    auto iter = find( arr_.begin(), arr_.end(), value );
    return iter == arr_.end() ? -1 : distance( arr_.begin(), iter );
  }

  T& operator[](size_t pos) {
  	if ( pos >= arr_.size() )
      throw out_of_range( "out of range" );
    return arr_[pos];
  }

  friend istream& operator>>( istream& is, BoundArray<T>& arr ) {
    T tmp; is >> tmp;
    arr.arr_.push_back( move( tmp ) );
    return is;
  }

  friend ostream& operator<<( ostream& os, const BoundArray<T>& arr ) {
    for ( const auto& elem : arr.arr_ )
      os << elem << ' ';
    return os;
  }
};

template<typename T>
void foo( size_t scale )
{
  BoundArray<T> arr;
  for ( size_t i = 0; i < scale; ++i )
    cin >> arr;

  arr.my_sort();
  cout << arr << endl;
  T value {}; cin >> value;
  cout << arr.search( value ) << endl;
}

int main()
{
  size_t t {}; cin >> t;
  while ( t-- ) {
    char type_tag {}; cin >> type_tag;
    size_t scale {}; cin >> scale;

    if ( type_tag == 'I' )
      foo<int>( scale );
    else if ( type_tag == 'D' )
      foo<double>( scale );
    else foo<char>( scale );
  }
}

【id:102】【20分】E. 矩阵类模板(类模板)

题目描述

设计一个矩阵类模板Matrix,支持任意数据类型的数据。

要求至少包含2个成员函数:矩阵转置函数transport、以及打印输出函数print

编写main函数进行测试,调用类的成员函数完成转置和输出。

输入

第一行先输入t,表示有t个测试用例

从第二行开始输入每个测试用例的数据。

首先输入数据类型,I表示int,D表示double,C表示char,接着输入两个参数m和n,分别表示矩阵的行和列

接下来输入矩阵的元素,一共m行,每行n个数据

输出

输出转置后的矩阵

样例

输入样例1输出样例1
2
I 2 3
1 2 3
4 5 6
C 3 3
a b c
d e f
g h i
1 4
2 5
3 6
a d g
b e h
c f i

Answer

#include <bits/stdc++.h>
using namespace std;

template<typename T>
class Matrix {
  vector<vector<T>> mat_;

public:
  Matrix( vector<vector<T>>&& mat ) : mat_ { move( mat ) } {}
  Matrix() = default;
  ~Matrix() = default;

  Matrix& init( size_t m, size_t n ) {
    mat_.clear();

    for ( size_t i = 0; i < m; ++i ) {
      mat_.push_back( {} );
      for ( size_t ii = 0; ii < n; ++ii ) {
        T tmp {}; cin >> tmp;
        mat_[i].push_back( move( tmp ) );
      }
    }
    return *this;
  }

  Matrix& transport() {
    vector<vector<T>> transposed( mat_.front().size(), vector<T>( mat_.size() ) );
    for ( size_t i = 0; i < mat_.size(); ++i ) {
      for ( size_t ii = 0; ii < mat_.front().size(); ++ii )
        transposed[ii][i] = mat_[i][ii];
    }
    swap( mat_, transposed );

    return *this;
  }

  void print() const {
    for ( size_t i = 0; i < mat_.size(); ++i ) {
      for ( size_t ii = 0; ii < mat_[i].size(); ++ii )
        cout << mat_[i][ii] << (ii < mat_[i].size() - 1 ? " " : "");
      cout << endl;
    }
  }
};

int main()
{
  size_t t {}; cin >> t;
  while ( t-- ) {
    char type_tag {};
    size_t m {}, n {};
    cin >> type_tag >> m >> n;
    if ( type_tag == 'I' )
      Matrix<int>().init( m, n ).transport().print();
    else if ( type_tag == 'D' )
      Matrix<double>().init( m, n ).transport().print();
    else Matrix<char>().init( m, n ).transport().print();
  }
}
  • 17
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值