声明
题解包含以下内容:
- (相对)高级的 C++ 模板及语法技巧
- 仅适用于 C++20 标准的代码
- 强烈的个人代码风格和 Modern C++ 范式追求
- 泛滥的标准库函数
换句话说就是(相较于其他公开题解)更低的查重率和更高的使用门槛;请酌情使用。
【id:56】【20分】A. 距离计算(友元函数)
题目描述
Point类的基本形式如下:
class Point
{
private:
double x, y;
public:
Point(double xx, double yy); // 构造函数
};
请完成如下要求:
1.实现Point类;
2.为Point类增加一个友元函数double Distance(Point &a, Point &b),用于计算两点之间的距离。直接访问Point对象的私有数据进行计算。
3.编写main函数,输入两点坐标值,计算两点之间的距离。
输入
第1行:输入需计算距离的点对的数目
第2行开始,每行依次输入两个点的x和y坐标
输出
每行依次输出一组点对之间的距离(结果直接取整数部分,不四舍五入 )
样例
输入样例1 | 输出样例1 |
---|---|
3 1 0 2 1 2 3 2 4 2 2 4 4 | 1 1 2 |
Answer
#include <bits/stdc++.h>
using namespace std;
class Point {
double x, y;
public:
explicit Point( double xx = 0, double yy = 0)
: x { xx }, y { yy } {}
friend double Distance( const Point& p1, const Point& p2 ) {
return sqrt( pow( abs( p1.x - p2.x ), 2 ) + pow( abs( p1.y - p2.y ), 2 ) );
}
friend istream& operator>>( istream& is, Point& p ) {
return is >> p.x >> p.y;
}
};
int main()
{
size_t t = 0;
cin >> t;
while ( t-- ) {
Point p1, p2;
cin >> p1 >> p2;
cout << static_cast<int>(Distance( p1, p2 )) << endl;
}
}
【id:57】【20分】B. 银行账户(静态成员与友元函数)
题目描述
银行账户类的基本描述如下:
class Account
{
private:
static float count; // 账户总余额
static float interestRate;
string accno, accname;
float balance;
public:
Account(string ac, string na, float ba);
~Account();
void deposit(float amount); // 存款
void withdraw(float amount); // 取款
float getBalance(); // 获取账户余额
void show(); // 显示账户所有基本信息
static float getCount(); // 获取账户总余额
static void setInterestRate(float rate); // 设置利率
static float getInterestRate(); // 获取利率
};
要求如下:
实现该银行账户类
为账户类Account增加一个友元函数,实现账户结息,要求输出结息后的余额(结息余额=账户余额+账户余额*利率)。友元函数声明形式为 friend void update(Account& a);
在main函数中,定义一个Account类型的指针数组,让每个指针指向动态分配的Account对象,并调用成员函数测试存款、取款、显示等函数,再调用友元函数测试进行结息。
大家可以根据实际需求在类内添加其他方法,也可以修改成员函数的参数设置
输入
第1行:利率
第2行:账户数目n
第3行开始,每行依次输入一个账户的“账号”、“姓名”、“余额”、存款数,取款数。
输出
第1行开始,每行输出一个账户的相关信息,包括账号、姓名、存款后的余额、存款后结息余额、取款后余额。
最后一行输出所有账户的余额。
样例
输入样例1 | 输出样例1 |
---|---|
0.01 3 201501 张三 10000 1000 2000 201502 李四 20000 2000 4000 201503 王二 80000 4000 6000 | 201501 张三 11000 11110 9110 201502 李四 22000 22220 18220 201503 王二 84000 84840 78840 106170 |
Answer
#include <bits/stdc++.h>
using namespace std;
class Account {
static float count; // 账户总余额
static float interestRate;
string accno, accname;
float balance;
public:
Account( string ac, string na, float ba )
: accno { move( ac ) }, accname { move( na ) }, balance { ba } {}
Account() : Account( {}, {}, 0.0f ) {}
~Account() {}
void deposit( float amount ) {
if ( amount < 0 )
return;
balance += amount;
}
void withdraw( float amount ) {
if ( amount < 0 || amount > balance )
return;
balance -= amount;
}
float getBalance() const { return balance; }
void show() {
cout << fixed << setprecision( 0 ) << balance << endl;
count += balance;
}
static float getCount() { return count; }
static void setInterestRate( float rate ) { interestRate = rate; }
static float getInterestRate() { return interestRate; }
friend istream& operator>>( istream& is, Account& acc ) {
return is >> acc.accno >> acc.accname >> acc.balance;
}
friend ostream& operator<<( ostream& os, const Account& acc ) {
return os << fixed << setprecision( 0 ) << acc.accno << ' ' << acc.accname << ' ' << acc.balance << ' ';
}
friend void update( Account& a ) {
a.balance = a.balance + a.balance * Account::interestRate;
cout << fixed << setprecision(0) << a.balance << ' ';
}
};
float Account::count = {};
float Account::interestRate = {};
int main()
{
int num {}; float rate;
cin >> rate >> num;
Account::setInterestRate( rate );
auto arr = new Account[num];
for ( int i = 0; i < num; ++i ) {
double cash_save {}, cash_withdraw {};
cin >> arr[i] >> cash_save >> cash_withdraw;
arr[i].deposit( cash_save );
cout << arr[i];
update( arr[i] );
arr[i].withdraw( cash_withdraw );
arr[i].show();
}
cout << fixed << setprecision( 0 ) << Account::getCount();
}
【id:58】【20分】C. 复数运算(友元函数)
题目描述
复数类的声明如下:
class Complex
{
private:
double real; // 实部
double imag; // 虚部
public:
Complex();
Complex(double r, double i);
// 友元函数,复数c1 + c2(二参数对象相加)
friend Complex addCom(const Complex& c1, const Complex& c2);
// 友元函数,输出类对象c的有关数据(c为参数对象)
friend void outCom(const Complex& c);
};
要求如下:
- 实现复数类和友元函数addCom和outCom。
- 参考addCom函数为复数类增加一个友元函数minusCom,用于实现两个复数的减法
- 在main函数中,通过友元函数,实现复数的加减法和复数的输出。
输入
第1行:第1个复数的实部和虚部
第2行:需进行运算的次数,注意:是连续运算。具体结果可参考样例
第3行开始,每行输入运算类型,以及参与运算的复数的实部与虚部。“+”表示复数相加,“-”表示复数相减。
输出
每行输出复数运算后的结果,复数输出格式为“(实部,虚部)”。
样例
输入样例1 | 输出样例1 |
---|---|
10 10 3 + 20 10 - 15 5 + 5 25 | (30,20) (15,15) (20,40) |
Answer
#include <bits/stdc++.h>
using namespace std;
class Complex {
double real; // 实部
double imag; // 虚部
public:
Complex( double r, double i )
: real { r }, imag { i } {}
Complex() : Complex( {}, {} ) {}
// 友元函数,复数c1 + c2(二参数对象相加)
friend Complex addCom( const Complex& c1, const Complex& c2 ) {
Complex ret = c1;
ret.real += c2.real;
ret.imag += c2.imag;
return ret;
}
friend Complex minusCom( const Complex& c1, const Complex& c2 ) {
Complex ret = c1;
ret.real -= c2.real;
ret.imag -= c2.imag;
return ret;
}
// 友元函数,输出类对象c的有关数据(c为参数对象)
friend void outCom( const Complex& c ) {
cout << fixed << setprecision( 0 ) << '(' << c.real << ',' << c.imag << ')' << endl;
}
friend istream& operator>>( istream& is, Complex& c ) {
return is >> c.real >> c.imag;
}
};
int main()
{
Complex c1; cin >> c1;
size_t cal_time {};
cin >> cal_time;
while ( cal_time-- ) {
char op {}; Complex c2;
cin >> op >> c2;
if ( op == '+' )
outCom( (c1 = addCom( c1, c2 )) );
else outCom( (c1 = minusCom( c1, c2 )) );
}
}
【id:59】【20分】D. 旅馆顾客统计(静态成员)
题目描述
编写程序,统计某旅馆住宿客人的总数和收入总额。要求输入客人的姓名,输出客人编号(2015+顺序号,顺序号4位,如第1位为0001,第2位为0002,依此类推)、姓名、总人数以及收入总额。总人数和收入总额用静态成员,其他属性采用普通的数据成员。旅馆类声明如下:
class Hotel
{
private:
static int totalCustNum; // 顾客总人数
static float totalEarning; // 旅店总收入
static float rent; // 每个顾客的房租
char *customerName; // 顾客姓名
int customerId; // 顾客编号
public:
// totalCustNum++,customerId按照totalCustNum生成
Hotel(char* customer);
~Hotel(); //记得delete customerName
void Display(); //相应输出顾客姓名、顾客编号、总人数、总收入
};
输入
第1行:输入旅馆单个顾客房租
第2行开始,依次输入顾客姓名,0表示输入结束, 姓名的最大字符长度为20
输出
每行依次输出顾客信息和当前旅馆信息。包括顾客姓名,顾客编号,旅馆当前总人数,旅馆当前总收入。
样例
输入样例1 | 输出样例1 |
---|---|
150 张三 李四 王五 0 | 张三 20150001 1 150 李四 20150002 2 300 王五 20150003 3 450 |
Answer
#include <bits/stdc++.h>
using namespace std;
class Hotel {
static int totalCustNum; // 顾客总人数
static float totalEarning; // 旅店总收入
static float rent; // 每个顾客的房租
char* customerName; // 顾客姓名
int customerId; // 顾客编号
public:
// totalCustNum++,customerId按照totalCustNum生成
explicit Hotel( const char* customer = nullptr ) {
customerName = new char[strlen( customer ) + 1] {};
strcpy(customerName, customer);
customerId = (++totalCustNum) + 20150000;
totalEarning += rent;
}
Hotel( Hotel&& _rhs ) {
customerName = _rhs.customerName;
_rhs.customerName = nullptr;
customerId = _rhs.customerId;
++totalCustNum;
}
Hotel( const Hotel& ) = delete;
~Hotel() { delete[] customerName; --totalCustNum; }
static void setRent( float _rent ) {
rent = _rent;
}
void Display() {
string_view name = customerName;
cout << name << ' ' << customerId << ' ' << totalCustNum << ' ' << totalEarning << endl;
}
};
int Hotel::totalCustNum = 0;
float Hotel::totalEarning = 0;
float Hotel::rent = 0;
int main()
{
float hotel_rent = 0;
cin >> hotel_rent;
cin.ignore((numeric_limits<streamsize>::max)(), '\n');
Hotel::setRent( hotel_rent );
string input; getline( cin, input );
list<Hotel> customers;
for ( auto head = input.begin(), tail = head++; *head != '0'; ) {
if ( head == input.end() )
break;
while ( *head != ' ' )
++head;
*head = '\0';
string_view name { tail, ++head };
while ( *head == ' ' )
++head;
tail = head++;
customers.emplace_back( name.data() );
customers.back().Display();
}
}
【id:62】【20分】E. 日期时间合并输出(友元函数)
题目描述
已知日期类Date,有属性:年、月、日,其他成员函数根据需要自行编写,注意该类没有输出的成员函数
已知时间类Time,有属性:时、分、秒,其他成员函数根据需要自行编写,注意该类没有输出的成员函数
现在编写一个全局函数把时间和日期的对象合并起来一起输出,
函数原型为:void display(const Date &d, const Time &t)
函数输出要求为:
1、时分秒输出长度固定2位,不足2位补0
2、年份输出长度固定为4位,月和日的输出长度固定2位,不足2位补0
例如2017年3月3日19时5分18秒
则输出为:2017-03-03 19:05:18
程序要求
1、把函数display作为时间类、日期类的友元
2、分别创建一个日期对象和时间对象,保存日期的输入和时间的输入
3、调用display函数实现日期和时间的合并输出
输入
第一行输入t表示有t组示例
接着一行输入三个整数,表示年月日
再接着一行输入三个整数,表示时分秒
依次输入t组示例
输出
每行输出一个日期和时间合并输出结果
输出t行
样例
输入样例1 | 输出样例1 |
---|---|
2 2017 3 3 19 5 18 1988 12 8 5 16 4 | 2017-03-03 19:05:18 1988-12-08 05:16:04 |
Answer
#include <bits/stdc++.h>
using namespace std;
class Date {
int year, month, day;
public:
explicit Date( int yy = 1970, int mm = 1, int dd = 1 )
: year { yy }, month { mm }, day { dd } {}
int getYear() const { return year; }
int getMonth() const { return month; }
int getDay() const { return day; }
friend istream& operator>>( istream& is, Date& d ) {
return is >> d.year >> d.month >> d.day;
}
};
class Time {
int hour, minute, second;
public:
explicit Time( int hh = 0, int mm = 0, int ss = 0 )
: hour { hh }, minute { mm }, second { ss } {}
int getHour() const { return hour; }
int getMinute() const { return minute; }
int getSecond() const { return second; }
friend istream& operator>>( istream& is, Time& t ) {
return is >> t.hour >> t.minute >> t.second;
}
};
void display( const Date& d, const Time& t )
{
cout << setw( 4 ) << d.getYear() << '-'
<< setw( 2 ) << setfill( '0' ) << d.getMonth() << '-'
<< setw( 2 ) << setfill( '0' ) << d.getDay() << ' '
<< setw( 2 ) << setfill( '0' ) << t.getHour() << ':'
<< setw( 2 ) << setfill( '0' ) << t.getMinute() << ':'
<< setw( 2 ) << setfill( '0' ) << t.getSecond()
<< endl;
}
int main()
{
size_t t {}; cin >> t;
while ( t-- ) {
Date d; cin >> d;
Time t; cin >> t;
display( d, t );
}
}