面向对象程序设计-16-函数模板

声明

题解包含以下内容:

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

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

【id:97】【20分】A. 数据排序(函数模板)

题目描述

编写一个进行升序排序的函数模板,其中数组为具有n个元素,类型为T。

注意:必须使用模板函数

输入

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

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

第三行输入n个数据

依次输入t个实例

输出

每行输出一个结果

样例

输入样例1输出样例1
4
I 10
15 3 51 27 9 35 78 14 65 8
D 3
-11.3 25.42 13.2
C 6
a b g e u q
S 4
sandy david eason cindy
3 8 9 14 15 27 35 51 65 78
-11.3 13.2 25.42
a b e g q u
cindy david eason sandy

Answer

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

template<typename T, typename _Pred>
T& my_sort( T& arr, _Pred p )
{
  std::sort( begin( arr ), end( arr ), move( p ) );
  return arr;
}

template<typename T>
vector<T> arr_generator( size_t __n ) {
  vector<T> arr; arr.reserve( __n );
  for ( size_t _ = 0; _ < __n; ++_ ) {
    T tmp {}; cin >> tmp;
    arr.push_back( move( tmp ) );
  }
  return arr;
}

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

template<typename T>
void foo()
{
  size_t scale {}; cin >> scale;
  auto arr = arr_generator<T>( scale );
  cout << my_sort( arr, less<T>() ) << endl;
}

int main()
{
  size_t t; cin >> t;
  while ( t-- ) {
    size_t scale {};
    switch ( char order; (cin >> order, order) ) {
    case 'D': {
      foo<double>();
    } break;

    case 'I': {
      foo<int>();
    } break;

    case 'C': {
      foo<char>();
    } break;

    case 'S': {
      foo<string>();
    } break;

    default:
      assert( false );
      break;
    }
  }
}

【id:98】【20分】B. 元素查找(函数模板)

题目描述

编写一个在数组中进行查找的函数模板,其中数组为具有n个元素,类型为T,要查找的元素为key。

注意:必须使用模板函数

输入

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

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

第三行输入n个数据

第四行输入key

依次输入t个实例

输出

每行输出一个结果,找到输出key是数组中的第几个元素(从1开始),找不到输出0

样例

输入样例1输出样例1
4
I 5
5 3 51 27 9
27
D 3
-11.3 25.42 13.2
2.7
C 6
a b g e u q
a
S 4
sandy david eason cindy
cindy
4
0
1
4

Answer

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

template<typename T, typename U>
  requires is_same_v<typename T::value_type, U>
size_t my_finder( const T& arr, U ele )
{
  auto iter = find( begin( arr ), end( arr ), move( ele ) );
  return iter == end( arr ) ? 0 : 1 + distance( begin( arr ), iter );
}

template<typename T>
vector<T> arr_generator( size_t __n ) {
  vector<T> arr; arr.reserve( __n );
  for ( size_t _ = 0; _ < __n; ++_ ) {
    T tmp {}; cin >> tmp;
    arr.push_back( move( tmp ) );
  }
  return arr;
}

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

template<typename T>
void foo()
{
  size_t scale {}; cin >> scale;
  auto arr = arr_generator<T>( scale );
  T target_ele {}; cin >> target_ele;
  cout << my_finder( arr, target_ele ) << endl;
}

int main()
{
  size_t t; cin >> t;
  while ( t-- ) {
    size_t scale {};
    switch ( char order; (cin >> order, order) ) {
    case 'D': {
      foo<double>();
    } break;

    case 'I': {
      foo<int>();
    } break;

    case 'C': {
      foo<char>();
    } break;

    case 'S': {
      foo<string>();
    } break;

    default:
      assert( false );
      break;
    }
  }
}

【id:99】【20分】C. 谁的票数最高(函数模板)

题目描述

某小镇要票选镇长,得票最高者当选。但由于投票机制不健全,导致每届投票时,候选人在投票系统的识别码类型不一致。请编写函数模板,能针对多种类型的数据,查找出得票最高的元素。其中,每届投票的选票有n张,识别码类型为T

注意:必须使用模板函数

输入

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

第二行先输入一个大写字母表示识别码类型,I表示整数类型,C表示字符型,S表示字符串型;然后输入n表示数组长度。

第三行输入n个数据

依次输入t个实例

输出

每行输出一个结果,分别输出当选者的识别码和得票数,以空格分开。

样例

输入样例1输出样例1
3
I 10
5 3 5 2 9 7 3 7 2 3
C 8
a b a e b e e q
S 5
sandy david eason cindy cindy
3 3
e 3
cindy 2

Answer

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

template<typename T>
pair<T, size_t> my_counter( const vector<T>& arr )
{
  unordered_map<T, size_t> counter_map;
  for ( const auto& e : arr )
    ++counter_map[e];

  auto iter = max_element(
    counter_map.begin(), counter_map.end(),
    []( auto&& a, auto&& b ) -> bool {
      return a.second < b.second;
    }
  );

  return *iter;
}

template<typename T>
ostream& operator<<( ostream& os, const pair<T, size_t> par )
{
  return os << par.first << " " << par.second;
}

template<typename T>
vector<T> arr_generator( size_t __n ) {
  vector<T> arr; arr.reserve( __n );
  for ( size_t _ = 0; _ < __n; ++_ ) {
    T tmp {}; cin >> tmp;
    arr.push_back( move( tmp ) );
  }
  return arr;
}

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

template<typename T>
void foo()
{
  size_t scale {}; cin >> scale;
  auto arr = arr_generator<T>( scale );
  cout << my_counter( arr ) << endl;
}

int main()
{
  size_t t; cin >> t;
  while ( t-- ) {
    size_t scale {};
    switch ( char order; (cin >> order, order) ) {
    case 'D': {
      foo<double>();
    } break;

    case 'I': {
      foo<int>();
    } break;

    case 'C': {
      foo<char>();
    } break;

    case 'S': {
      foo<string>();
    } break;

    default:
      assert( false );
      break;
    }
  }
}

【id:324】【20分】D. 指定类型与区间排序(函数模板)

题目描述

现在有int、string、float,3种类型的数据需要排序
每次输入数据类型及n个数据,并指定排序区间[beg, end),请你对该区间内的数据进行排序并输出
(可以使用系统排序函数)

输入

第1行:一个正整数t,表示测试次数
以下t行,每行输入:type n [beg,end) : n个数据(用空格分隔)…
(注意beg和end可以为任何值,且不一定有beg<=end成立。如果区间越界,则超出部分不进行排序:
比如n=10, 输入区间为[-10,5),则只对合法区间[0,5)排序)

输出

参见样例输出

样例

输入样例1输出样例1
3
int 5 [2,4) : 5 4 3 2 1
string 3 [-4,4) : b c a
float 3 [0,4) : 3.3 1.1 2.2
[5, 4, 2, 3, 1]
[a, b, c]
[1.1, 2.2, 3.3]

提示

排序区间[beg, end)指的是:从下标为beg的数据开始,到下标为end-1的数据截止(下标从0开始)

Answer

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

enum class DataType { Integer, String, Float };

struct DataInterval {
  DataType type;
  int range_start;
  int range_end;
  vector<string> values;
};

DataInterval parser( const string& line ) {
  regex pattern( R"((\w+)\s+(\d+)\s+\[(\-?\d+),(\-?\d+)\)\s+:\s+((\S+\s*)+))" );
  smatch match;
  DataInterval info;

  if ( regex_search( line, match, pattern ) ) {
    if ( auto type_str = match.str( 1 );
         type_str == "int" )
      info.type = DataType::Integer;
    else if ( type_str == "string" )
      info.type = DataType::String;
    else info.type = DataType::Float;
    info.range_start = stoi( match.str( 3 ) ); // 区间段
    info.range_end = stoi( match.str( 4 ) );

    string values_str = match.str( 5 );
    regex values_pattern( R"(\S+)" );

    // 数据区间
    for ( auto iter = sregex_iterator( values_str.begin(), values_str.end(), values_pattern ); iter != sregex_iterator {}; ++iter )
      info.values.push_back( iter->str() );
  }

  return info;
}

template<typename T>
ostream& operator<<( ostream& os, const vector<T>& arr )
{
  os << '[';
  for ( size_t i = 0; i < arr.size(); ++i )
    os << arr[i] << (i == arr.size() - 1 ? ""sv : ", "sv);
  return os << ']';
}

int main()
{
  size_t t {}; cin >> t;
  getchar(); // endline
  while ( t-- ) {
    string line; getline( cin, line );
    DataInterval info = parser( line );

    switch ( info.type ) {
    case DataType::Integer: {
      vector<int> values;
      transform( info.values.begin(), info.values.end(),
        back_inserter( values ), []( auto&& str ) { return stoi( str ); } );

      if ( info.range_start < 0 )
        info.range_start = 0;
      if ( info.range_end > info.range_start )
        sort( values.begin() + info.range_start,
              info.range_end > values.size() ? values.end() : values.begin() + info.range_end );

      cout << values << endl;
    } break;

    case DataType::String: {
      if ( info.range_start < 0 )
        info.range_start = 0;
      if ( info.range_end > info.range_start )
        sort( info.values.begin() + info.range_start,
              info.range_end > info.values.size() ? info.values.end() : info.values.begin() + info.range_end );

      cout << info.values << endl;
    } break;

    case DataType::Float: {
      vector<float> values;
      transform( info.values.begin(), info.values.end(),
        back_inserter( values ), []( auto&& str ) { return static_cast<float>(stod( str )); } );

      if ( info.range_start < 0 )
        info.range_start = 0;
      if ( info.range_end > info.range_start )
        sort( values.begin() + info.range_start,
              info.range_end > values.size() ? values.end() : values.begin() + info.range_end );

      cout << values << endl;
    } break;

    default:
      assert( false );
      break;
    }
  }
}

【id:331】【20分】E. 抢票验证码(函数模板)

题目描述

对于某抢票系统,存在一个长度为六的验证码,验证码可以为整形,字符型,浮点型,我们认为验证码是有效的当且仅当验证码是非递减序列(递增或者相等)。现请你利用函数模板,完成对验证码的检验

输入

测试数据有多组,每组测试数据给出验证码类型以及一串验证码

输出

输出验证的结果

样例

输入样例1输出样例1
c
a b c d e f
i
1 2 3 4 5 6
f
1.1 1.2 1.3 4 5 6
c
f e v a c s
Valid
Valid
Valid
Invalid

Answer

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

template<typename T>
bool verify_checker( const vector<T>& code )
{
  return is_sorted( code.begin(), code.end() );
}

vector<string> spliter( const string& str ) {
	regex pattern( "\\s+" );
  return { sregex_token_iterator( str.begin(), str.end(), pattern, -1 ), sregex_token_iterator() };
}

int main()
{
  char order {};
  while ( cin >> order ) {
    cin.ignore( (numeric_limits<streamsize>::max)(), '\n' );
    string line_input; getline( cin, line_input );
    vector<string> origin_code = spliter( line_input );
    order = tolower( order );

    if ( order == 'c' ) {
      vector<char> code;
      transform( origin_code.begin(), origin_code.end(),
        back_inserter( code ), []( auto&& e ) -> char { return e.front(); } );
      cout << (verify_checker( code ) ? "Valid\n"sv : "Invalid\n"sv);
    } else if ( order == 'i' ) {
      vector<int> code;
      transform( origin_code.begin(), origin_code.end(),
        back_inserter( code ), []( auto&& e ) -> int { return stoi( e ); } );
      cout << (verify_checker( code ) ? "Valid\n"sv : "Invalid\n"sv);
    } else {
      vector<float> code;
      transform( origin_code.begin(), origin_code.end(),
        back_inserter( code ), []( auto&& e ) -> float { return static_cast<float>(stod( e )); } );
      cout << (verify_checker( code ) ? "Valid\n"sv : "Invalid\n"sv);
    }
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值