C++模板与运算符重载实战技巧
·

例题一:格式化输入输出
- 函数模板的语法:和类模板写法有区别,容易记混格式
- 手写排序算法:冒泡 / 插入排序的边界容易写错
- 自定义类 + 运算符重载:Point 类要重载
<做比较、重载<<做输出 - 格式化输入输出:点的输入是
(x,y)格式,要处理括号、逗号
编写一个对n个元素的数组升序排序的函数模板mysort,其中元素类型可以是基本数据类型,也可以是点对象(按点到原点的距离比较)。(要求不能用C++提供的sort函数模板)
输入
第一行输入测试次数
每次测试输入二行,第1行先输入一个大写字母表示数组类型,I表示整数类型,S表示字符串型,D表示双精度数类型,P表示点,最后输入n表示数组长度。第2行输入n个数据。
输出
每次测试输出一行排序后的结果
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
// 通用冒泡排序函数模板
template<typename T>
void mysort(T arr[], int n) {
for(int i = 0; i < n-1; ++i) {
bool flag = false;
for(int j = 0; j < n-1-i; ++j) {
if(arr[j] > arr[j+1]) {
T temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
flag = true;
}
}
if(!flag) break;
}
}
// 点类:重载比较运算符供排序使用
class Point {
double x, y;
public:
Point() : x(0), y(0) {}
Point(double x, double y) : x(x), y(y) {}
bool operator<(const Point& other) const {
double dist1 = x*x + y*y;
double dist2 = other.x*other.x + other.y*other.y;
return dist1 < dist2;
}
bool operator>(const Point& other) const {
return other < *this;
}
friend ostream& operator<<(ostream& out, const Point& p) {
ios old_fmt(NULL);//1.创建一个格式存档对象
//cout的所有格式设置:小数位数,对齐方式,进制都存在ios状态里面
//old_fmt存之前的格式
old_fmt.copyfmt(out);//2.把当前cout的所有格式设置,完整保存下来
//把传进来的流对象 out(也就是调用时的 cout)当前的全部格式设置,完整复制到 old_fmt 里
out << fixed << setprecision(1);
out << "(" << p.x << ", " << p.y << ")";//设置的新格式
out.copyfmt(old_fmt);//把保存的旧格式还原回去
return out;
}//如果不这样做就会改变全局输出格式,导致其他类型数据的输出格式也随之变化
friend istream& operator>>(istream& in, Point& p) {
in >> p.x >> p.y;
return in;
}
};
template<typename T>
void printArr(T arr[], int n) {
for(int i = 0; i < n; ++i) {
if(i != 0) cout << " ";
cout << arr[i];
}
cout << endl;
}
int main() {
int t;
cin >> t;
while(t--) {
char type;
int n;
cin >> type >> n;
if(type == 'I') {
int* arr = new int[n];
for(int i = 0; i < n; ++i) cin >> arr[i];
mysort(arr, n);
printArr(arr, n);
delete[] arr;
} else if(type == 'D') {
double* arr = new double[n];
for(int i = 0; i < n; ++i) cin >> arr[i];
mysort(arr, n);
printArr(arr, n);
delete[] arr;
} else if(type == 'S') {
string* arr = new string[n];
for(int i = 0; i < n; ++i) cin >> arr[i];
mysort(arr, n);
printArr(arr, n);
delete[] arr;
} else if(type == 'P') {
Point* arr = new Point[n];
for(int i = 0; i < n; ++i) cin >> arr[i];
mysort(arr, n);
printArr(arr, n);
delete[] arr;
}
}
return 0;
}
例题二:类模板 + 模板特化
Data 类不只是存数据,它把输入读取、区间越界裁剪、排序、格式化输出一整套业务流程全打包进了类里。
#include <bits/stdc++.h>
#include <iomanip>
using namespace std;
template<typename T>
class Data {
vector<T> data;
public:
Data(int n) : data(n) {
for(int i = 0; i < n; ++i) {
cin >> data[i];
}
}
void sortRange(int beg, int end) {
int left = max(beg, 0);
int right = min(end, (int)data.size());
if(left >= right) return;
sort(data.begin() + left, data.begin() + right);
}
void show() {
cout << "[";
for(int i = 0; i < data.size(); ++i) {
if(i != 0) cout << ", ";
cout << data[i];
}
cout << "]" << endl;
}
};
template<>
void Data<float>::show() {
cout << "[" << fixed << setprecision(1);
for(int i = 0; i < data.size(); ++i) {
if(i != 0) cout << ", ";
cout << data[i];
}
cout << "]" << endl;
}
int main() {
int t;
cin >> t;
while(t--) {
string type;
int n, x, y;
char c;
cin >> type >> n;
cin >> c;
cin >> x;
cin >> c;
cin >> y;
cin >> c;
cin >> c;
if(type == "int") {
Data<int> d(n);
d.sortRange(x, y);
d.show();
} else if(type == "string") {
Data<string> d(n);
d.sortRange(x, y);
d.show();
} else if(type == "float") {
Data<float> d(n);
d.sortRange(x, y);
d.show();
}
}
return 0;
}
template<>:空尖括号是全特化的标志,模板参数已经全部指定为具体类型,没有占位符了;Data<float>::show():明确说明:这是给T = float版本的Data类专属的show函数;
更多推荐



所有评论(0)