实验八 静态成员与友元函数
A. 距离计算(友元函数)
题目描述
Point类的基本形式如下:
请完成如下要求:
1.实现Point类;
2.为Point类增加一个友元函数double Distance(Point &a, Point &b),用于计算两点之间的距离。直接访问Point对象的私有数据进行计算。
3.编写main函数,输入两点坐标值,计算两点之间的距离。
输入
第1行:输入需计算距离的点对的数目
第2行开始,每行依次输入两个点的x和y坐标
输出
每行依次输出一组点对之间的距离(结果直接取整数部分,不四舍五入 )
输入样例
2
1 0 2 1
2 3 2 4
输出样例
1
1
参考代码
#include<iostream>
#include<cmath>
#include<iomanip>
using namespace std;
class Point
{
public:
Point(double xx,double yy):x(xx),y(yy){}//构造函数
friend double Distance(Point &a,Point &b);//计算两点之间的距离
private:
double x,y;
};
double Distance(Point &a,Point &b)
{
double dis;
dis=sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
return dis;
}
int main()
{
int t;//计算组数
cin>>t;
while(t--)
{
double x1,y1,x2,y2;
cin>>x1>>y1>>x2>>y2;
Point p1(x1,y1);
Point p2(x2,y2);
double res=Distance(p1,p2);
cout<<fixed<<setprecision(0)<<res<<endl;
}
}
B. 银行账户(静态成员与友元函数)
题目描述
银行账户类的基本描述如下:
要求如下:
实现该银行账户类
为账户类Account增加一个友元函数,实现账户结息,要求输出结息后的余额(结息余额=账户余额+账户余额*利率)。友元函数声明形式为 friend void Update(Account& a);
在main函数中,定义一个Account类型的指针数组,让每个指针指向动态分配的Account对象,并调用成员函数测试存款、取款、显示等函数,再调用友元函数测试进行结息。
大家可以根据实际需求在类内添加其他方法,也可以修改成员函数的参数设置
输入
第1行:利率
第2行:账户数目n
第3行开始,每行依次输入一个账户的“账号”、“姓名”、“余额”、存款数,取款数。
输出
第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
参考代码
#include<iostream>
#include<cstring>
using namespace std;
class Account//银行账户
{
public:
Account(){}
Account(string accno,string name,float balance)//构造函数
{
_accno=accno;
_accname=name;
_balance=balance;
}
void set(string accno,string name,float balance)//构造函数
{
_accno=accno;
_accname=name;
_balance=balance;
count++;//账户数目增加
}
~Account(){}
void Deposit(float amount)//存款
{
_balance+=amount;
}
void Withdraw(float amount)//取款
{
_balance-=amount;
}
float Getbalance()//返回账户余额
{
return _balance;
}
void show()//输出账户基本信息
{
cout<<_accno<<' '<<_accname<<' ';
}
static int Getcount()//静态成员函数:获得账户数
{
return count;
}
static float Getrate(float r1)//获取利率
{
InterestRate=r1;
}
friend void Update(Account &a); //友元函数
private:
static int count;//银行账户数量
static float InterestRate;//利率
string _accno,_accname;//表示账号和户名
float _balance;//账户余额
};
int Account::count=0;
float Account::InterestRate=0;//初始化
void Update(Account& a)//输出结息后的余额:还是余额值
{
a._balance=a._balance+a._balance*a.InterestRate;
}
int main()
{
float rate1;
cin>>rate1;
Account::Getrate(rate1);//静态成员函数前面是类名
int n;//账户数
cin>>n;
Account *p=new Account[n];
float sum=0;
for(int i=0;i<n;i++)
{
string accno1,name1;
float balance1,dep1,with1;
cin>>accno1>>name1>>balance1>>dep1>>with1;
p[i].set(accno1,name1,balance1);
p[i].show();
p[i].Deposit(dep1);//存款
cout<<p[i].Getbalance()<<' ';//存款后余额
Update(p[i]);
cout<<p[i].Getbalance()<<' ';//存款后结息余额
p[i].Withdraw(with1);//取款
cout<<p[i].Getbalance()<<endl;//取款后余额
sum+=p[i].Getbalance();
}
cout<<sum;
delete []p;
}
C. 电视机与遥控器(友元类)
题目描述
有如下的电视类和遥控器类,遥控器在电视开机的情况下可以控制电视。
要求如下:
1.实现并完善Tv类;其中构造函数需修改和完善。另:最大频道为100;
2.将Remote设为Tv的友元类,以支持在Remote类中对Tv方法的调用。
3.在main函数中,通过Remote实例对TV实例进行操作。
输入
第一行,电视初始状态,依次为state,volume,channel,mode,input的初始值。
第二行,利用遥控器对上述状态的操作指令,用对应的函数名表示,如增加音量为volup
输出
第一行,执行遥控器操作后的状态。
输入样例
off 10 19 Cable VCR
onoff volup chanup set_mode set_input
输出样例
on 11 20 Antenna TV
参考代码
#include<iostream>
#include<cstring>
using namespace std;
class TV
{
int state,volume,maxchannel;//电视开关状态,音量,最大频道
int channel,mode,input;//当前频道,信号接收模式,输入方式
public:
TV(int s,int v,int mc,int chan,int mo,int in):state(s),maxchannel(mc)
{
volume=v;
channel=chan;
mode=mo;
input=in;
}
void onoff() //切换电视开关状态
{
if(state==0) state=1;
else state=0;
}
bool ison()const//判断开关状态,on为true
{
return state;//由state决定
}
bool volup()//增加音量
{
if(state)//开机时才可以
{
if(volume<20)
{
volume++;
return 1;
}
}
return 0;
}
bool voldown()//降低音量
{
if(state)//开机时才可以
{
if(volume>0)
{
volume--;
return 1;
}
}
return 0;
}
void chanup()
{
if(state)//开机时才可以
{
if(channel<maxchannel)
{
channel++;
}
}
}
void chandown()
{
if(state)//开机时才可以
{
if(channel>0)
{
channel--;
}
}
}
void set_mode()
{
if(state)
{
if(mode) mode=0;
else mode=1;
}
}
void set_input()
{
if(input)
{
if(input) input=0;
else input=1;
}
}
void settings()const
{
if(state) cout<<"on"<<' ';
else cout<<"off"<<' ';
cout<<volume<<' '<<channel<<' ';
if(mode) cout<<"Cable"<<' ';
else cout<<"Antenna"<<' ';
if(input) cout<<"VCR";
else cout<<"TV";
cout<<endl;
}
friend class Remote;
};
class Remote{
int mode;
public:
Remote(int m):mode(m){}
bool volup(TV &t)
{
return t.volup();
}
bool voldown(TV &t)
{
return t.voldown();
}
void onoff(TV &t)
{
t.onoff();
}
void chanup(TV &t)
{
t.chanup();
}
void chandown(TV &t)
{
t.chandown();
}
void set_chan(TV &t,int c)
{
t.channel=c;
}
void set_mode(TV &t)
{
t.set_mode();
}
void set_input(TV &t)
{
t.set_input();
}
};
int main()
{
string s1,m1,in1;
int st1,vo1,chan1,mo1,inp1;
cin>>s1>>vo1>>chan1>>m1>>in1;
if(s1=="off") st1=0;
else st1=1;
if(m1=="Cable") mo1=1;
else mo1=0;
if(in1=="VCR") inp1=1;
else inp1=0;
TV tv1(st1,vo1,100,chan1,mo1,inp1);
Remote r(inp1);
string str;
while(cin>>str)
{
if(str=="volup") r.volup(tv1);
else if(str=="voldown") r.voldown(tv1);
else if(str=="onoff") r.onoff(tv1);
else if(str=="chanup") r.chanup(tv1);
else if(str=="chandown") r.chandown(tv1);
else if(str=="set_chan")
{
int temp;
cin>>temp;
r.set_chan(tv1,temp);
}
else if(str=="set_mode") r.set_mode(tv1);
else if(str=="set_input") r.set_input(tv1);
}
tv1.settings();
return 0;
}
D. 旅馆旅客管理(静态成员)
题目描述
编写程序,实现某旅馆的客人住宿记录功能。
定义一个Customer类,要求输入客人的姓名,创建一个Customer对象。类声明如下:
调用类的Display函数输出客人ID(输出顺序号占4位,如第1位为0001,第2位为0002,依此类推)、姓名、总人数。总人数和客人租金用静态成员,其他属性采用普通的数据成员。
输入
输入测试次数t
对于每次测试,首先输入当前年份,
接下来依次输入顾客姓名,0表示输入结束。
输出
每行依次输出顾客信息和旅馆信息。包括顾客姓名,顾客编号,旅馆入住总人数,旅馆当前总收入。
输入样例
2
2014
张三 李四 王五 0
2015
Cindy David 0
输出样例
张三 20140001 1 150
李四 20140002 2 300
王五 20140003 3 450
Cindy 20150004 4 600
David 20150005 5 750
参考代码
#include<iostream>
#include<cstring>
#include<iomanip>
using namespace std;
class Customer{
public:
Customer(char *name)
{
int len=strlen(name);
custname=new char[len+1];
strcpy(custname,name);
totalcusnum++;
custid=totalcusnum;
}
~Customer()
{
if(custname!=NULL) delete custname;
}
static void changeyear(int r)//更换年份
{
year=r;
}
void Display()
{
cout<<custname<<' '<<year<<setfill('0')<<setw(4)<<custid<<' '<<totalcusnum<<' ';
cout<<(rent*totalcusnum)<<endl;
}
private:
static int totalcusnum;//入住总人数
static int rent;//每位客人租金
static int year;//当前年份
int custid;//客人id
char *custname;//客人姓名
};
int Customer::totalcusnum=0;
int Customer::rent=150;
int Customer::year=2014;
int main()
{
int t;//测试组数
cin>>t;
while(t--)
{
int y;
cin>>y;//当前年份
Customer::changeyear(y);
char s[100];
while(1)
{
cin>>s;
if(!strcmp(s,"0")) break;
Customer s1(s);
s1.Display();
}
}
}
E. 判断矩形是否重叠(复合类+友元)
题目描述
用CPoint表示点,用两个CPoint对象表示矩形类CRect的对角线两点。分别实现CPoint类和CRect类,并在主函数用输入的坐标定义4个CPoint类对象,每2个CPoint对象再构造1个CRect对象,然后写个友元函数,判断2个矩形是否重叠。
输入
判断次数
矩形1的对角线顶点坐标x1, y1, x2, y2
矩形2的对角线顶点坐标x1, y1, x2, y2
…
输出
是否重叠
输入样例
3
1 5 2 9
1 3 2 4
5 6 7 8
5 7 7 7
2 5 1 0
9 4 2 9
输出样例
not overlapped
overlapped
overlapped
参考代码
#include<iostream>
using namespace std;
class CPoint;
class CRect;
class CPoint{
int x,y;
public:
CPoint(){}
CPoint(int x1,int y1):x(x1),y(y1){}
int getx()
{
return x;
}
int gety()
{
return y;
}
friend void isoverlapped(CRect &c1,CRect &c2);
};
class CRect{
CPoint a;
CPoint b;
public:
CRect(CPoint &a1,CPoint &b1)
{//保证a是横坐标小的那个
if(a1.getx()>b1.getx())
{
b=a1;
a=b1;
}
else
{
a=a1;
b=b1;
}
}
friend void isoverlapped(CRect &c1,CRect &c2);
};
void isoverlapped(CRect &c1,CRect &c2)
{
//主对角线
int flag;
if(c1.a.y<c1.b.y)
{
if(c2.a.y<c2.b.y)
{//左边~~右边 ~上边~下边
//不重叠的四种情况
if(c2.b.x<c1.a.x||c2.a.x>c1.b.x||c2.a.y>c1.b.y||c2.b.y<c1.a.y) flag=0;
else flag=1;
}
else
{
if(c2.b.x<c1.a.x||c2.a.x>c1.b.x||c2.b.y>c1.b.y||c2.a.y<c1.a.y) flag=0;
else flag=1;
}
}
//次对角线
else
{
if(c2.a.y<c2.b.y)
{//左边~~右边 ~上边~下边
//不重叠的四种情况
if(c2.b.x<c1.a.x||c2.a.x>c1.b.x||c2.a.y>c1.a.y||c2.b.y<c1.b.y) flag=0;
else flag=1;
}
else
{
if(c2.b.x<c1.a.x||c2.a.x>c1.b.x||c2.b.y>c1.a.y||c2.a.y<c1.b.y) flag=0;
else flag=1;
}
}
if(flag) cout<<"overlapped"<<endl;
else cout<<"not overlapped"<<endl;
}
int main()
{
int t;//测试组数
cin>>t;
while(t--)
{
int x1,y1,x2,y2,x3,y3,x4,y4;
cin>>x1>>y1>>x2>>y2>>x3>>y3>>x4>>y4;
CPoint p1(x1,y1),p2(x2,y2),p3(x3,y3),p4(x4,y4);
CRect r1(p1,p2),r2(p3,p4);
isoverlapped(r1,r2);
}
}