1.点圆运算(构造与析构)
题目描述
设计一个点类Point,包含私有属性x坐标和y坐标,操作包括
1、构造函数,要求满足两个条件:1.能够使用类Point去创建一个对象数组(缺省构造方法!);2.能够接收外来输入的x和坐标做初始化,提示:构造函数重载
2、析构函数,把x坐标和y坐标都清0,并输出信息“point clear”
3、设置(setXY),接受外来输入,并设置x坐标和y坐标
4、获取x坐标,直接返回x值
5、获取y坐标,直接返回y值
设计一个圆类Circle,包含私有属性:圆心坐标x和y、半径r;操作包括:
1、构造函数,接受外来输入,设置圆心x坐标、y坐标和半径
2、析构函数,将圆心坐标x和y以及半径都清零,并输出"circle clear"
3、包含(Contain),判断一个圆是否包含一个点,计算圆心到这个点的距离,然后和半径做比较,大于则不包含,小于等于则包含。提示:用点对象做参数不一定符合输出
输入
第一行输入一个点的x坐标和y坐标,用Point类去创建一个点对象,并且自动通过构造函数来初始化
第二行输入n,用Point类去创建一个点对象数组,包含n个点
第三行起输入n行,每行输入一个点的x和y坐标,使用设置(setXY)来设置每个点的x和y坐标
接着一行输入三个参数,表示一个圆的圆心坐标x和y,以及半径,使用Circle类去创建一个圆对象,并自动通过构造函数来初始化
输出
通过调用圆的包含(Contain)方法,判断每个点是否在圆内。
按照点的输入顺序,每行输出一个点的判断结果,如果包含则输出in,不包含则输出out
说明:当一个对象数组是动态创建的,那么在程序结束时,这个数组是不会被回收。只有增加代码delete []p,才会回收数组。
本题不要求收回数组.
输入样例
5 2
3
4 7
9 9
2 4
3 3 3
输出样例
in
out
out
in
circle clear
point clear
AC代码
#include<iostream>
using namespace std;
class Point
{
public:
Point()//只有加上初始才能用动态开类对象数组的方式
{
x = 0;
y = 0;
}
Point(int xx,int yy)
{
x =xx;
y = yy;
}
~Point()
{
x = 0;
y = 0;
cout << "point clear" << endl;
}
void setXY(int xx, int yy)
{
x = xx;
y = yy;
}
int getX()
{
return x;
}
int getY()
{
return y;
}
private:
int x, y, r;
};
class Circle
{
public:
Circle()
{
cx = 0;
cy = 0;
cr = 0;
}
Circle(int cxx,int cyy,int crr)
{
cx = cxx;
cy = cyy;
cr = crr;
}
~Circle()
{
cx = 0;
cy = 0;
cr = 0;
cout << "circle clear" << endl;
}
void contain(int a, int b)
{
//cout << a << " " << b << endl;
//cout << cx << " " << cy << " " << cr << endl;
if (((cx - a) * (cx - a) + (cy - b) * (cy - b)) > cr * cr)
cout << "out" << endl;
else cout << "in" << endl;
}
private:
int cx, cy, cr;
};
int main()
{
int a, b;
cin >> a >> b;
Point p1(a, b);
int n;
cin >> n;
Point* pp = new Point[n+1];
Circle* cc = new Circle[n + 1];
for (int i = 1; i <= n; i++)
{
int a, b;
cin >> a >> b;
pp[i].setXY(a, b);
}
int cx, cy, cr;
cin >> cx >> cy >> cr;
Circle c(cx, cy, cr);//圆心是不变的,不能定义类对象为Circle的,不然圆心及半径会被置为0
c.contain(p1.getX(),p1.getY());
for (int i = 1; i <= n; i++)
{
c.contain(pp[i].getX(), pp[i].getY());
}
return 0;
}
2.分数类(类与构造)
题目描述
完成下列分数类的实现:
class CFraction
{
private:
int fz, fm;
public:
CFraction(int fz_val, int fm_val) ;
CFraction add(const CFraction &r);
CFraction sub(const CFraction &r);
CFraction mul(const CFraction &r);
CFraction div(const CFraction &r);
int getGCD(); // 求对象的分子和分母的最大公约数
void print();
};
求两数a、b的最大公约数可采用辗转相除法,又称欧几里得算法,其步骤为:
1. 交换a, b使a > b;
2. 用a除b得到余数r,若r=0,则b为最大公约数,退出.
3. 若r不为0,则用b代替a, r代替b,此时a,b都比上一次的小,问题规模缩小了;
4. 继续第2步。
输入
测试数据的组数 t
第一组第一个分数
第一组第二个分数
第二组第一个分数
第二组第二个分数
......
输出
第一组两个分数的和
第一组两个分数的差
第一组两个分数的积
第一组两个分数的商
第二组两个分数的和
第二组两个分数的差
第二组两个分数的积
第二组两个分数的商
......
输入样例
3
1/2
2/3
3/4
5/8
21/23
8/13
输出样例
7/6
-1/6
1/3
3/4
11/8
1/8
15/32
6/5
457/299
89/299
168/299
273/184
AC代码
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class CFraction
{
private:
int fz, fm;
public:
CFraction()
{
};
CFraction(int fz_val, int fm_val)
{
fz = fz_val;
fm = fm_val;
}
int getGCD()//求最大公约数,不需要考虑正负,全为正
{
int r = 0, a, b;
a = fz;
b = fm;
if (a < 0)a = -a;
if (b < 0)b = -b;
if (b > a)swap(a, b);
r = a % b;
while (r != 0)
{
a = b;
b = r;
r = a % b;
}
return b;
}
CFraction add(const CFraction& r)
{
CFraction a;
int t;
a.fz = fz * r.fm + r.fz * fm;
a.fm = fm * r.fm;
t = a.getGCD();
a.fz = a.fz / t;
a.fm = a.fm / t;
return a;
}
CFraction sub(const CFraction& r)
{
CFraction a;
int t;
a.fz = fz * r.fm - r.fz * fm;
a.fm = fm * r.fm;
t = a.getGCD();
a.fz = a.fz / t;
a.fm = a.fm / t;
return a;
}
CFraction mul(const CFraction& r)
{
CFraction a;
int t;
a.fz = fz * r.fz ;
a.fm = fm * r.fm;
t = a.getGCD();
a.fz = a.fz / t;
a.fm = a.fm / t;
return a;
}
CFraction div(const CFraction& r)
{
CFraction a;
int t;
a.fz = fz * r.fm ;
a.fm = fm * r.fz;
t = a.getGCD();
a.fz = a.fz / t;
a.fm = a.fm / t;
return a;
}
void print()
{
cout << fz << "/" << fm << endl;
}
};
int main()
{
int t;
cin >> t;
while (t--)
{
int a, b, c, d;
scanf("%d/%d\n%d/%d", &a, &b, &c, &d);
CFraction t1(a, b);
CFraction t2(c, d);
CFraction add1 = t1.add(t2);
CFraction sub1 = t1.sub(t2);
CFraction mul1 = t1.mul(t2);
CFraction div = t1.div(t2);
add1.print();
sub1.print();
mul1.print();
div.print();
cout << endl;
}
return 0;
}
3.Point_Array(类+构造+对象数组)
题目描述
输入
测试数据的组数 t
第一组点的个数
第一个点的 x 坐标 y坐标
第二个点的 x坐标 y坐标
............
输出
输出第一组距离最大的两个点以及其距离
...........
在C++中,输出指定精度的参考代码如下:
#include <iostream>
#include <iomanip> //必须包含这个头文件
using namespace std;
void main( )
{ double a =3.141596;
cout<<fixed<<setprecision(3)<<a<<endl; //输出小数点后3位
输入样例
2
4
0 0
5 0
5 5
2 10
3
-1 -8
0 9
5 0
输出样例
Constructor.
Constructor.
Constructor.
Constructor.
The longeset distance is 10.44,between p[1] and p[3].
Distructor.
Distructor.
Distructor.
Distructor.
Constructor.
Constructor.
Constructor.
The longeset distance is 17.03,between p[0] and p[1].
Distructor.
Distructor.
Distructor.
AC代码
#include<iostream>
#include<cmath>
#include<iomanip>
using namespace std;
class Point
{
double x, y;
public:
Point()
{
x = 0; y = 0;
cout << "Constructor." << endl;
}
Point(double xx, double yy)
{
x = xx;
y = yy;
}
~Point()
{
x = 0; y = 0;
cout << "Distructor." << endl;
}
double getX()
{
return x;
}
double getY()
{
return y;
}
void setXY(double x1, double y1)
{
x = x1;
y = y1;
}
void setX(double x1)
{
x = x1;
}
void setY(double y1)
{
y = y1;
}
double getDisTo(Point& p)
{
double d;
d = sqrt((p.x - x) * (p.x - x) + (p.y - y) * (p.y - y));
return d;
}
};
int main()
{
int t;
cin >> t;
while (t--)
{
int k1 = 0,k2=0;
double ans = 0;
int n;
cin >> n;
Point* pp = new Point[n];
for (int i = 0; i < n; i++)
{
double x, y;
cin >> x >> y;
pp[i].setXY(x, y);
}
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
if (i == j)continue;
double tmp = pp[i].getDisTo(pp[j]);
if (tmp > ans)
{
ans = tmp;
k1 = i;
k2 = j;
}
}
}
if (k1 > k2)swap(k1, k2);
cout << "The longeset distance is " << fixed << setprecision(2) << ans << ",between p[" << k1 << "] and p[" << k2 << "]." << endl;
delete []pp;//注意每次测试后要delete之后才能distructor,因为类的生存域结束后才会执行析构函数里的输出
}
return 0;
}
4.身份证扩展(类构造与析构)
题目描述
定义一个身份证类,将 15 位的旧版身份证号扩充为 18 位。
在 15 位身份证号中,第 7、8 两位为出生年份,例如,1980 年出生的人,身份证号码的第 7、8 位的值是 80,在 18 位身份证号中,将 7~10 四位的值改为 1980,并将原身份证号码第 9 位开始以后的所有数字依次向右平移 2 位。在 18 位身份证号中, 最后增加一位校验码,校验码的计算方法如下(只考虑 20 世纪出生的公民):
(1)将已扩展出的 17 位身份证号按各位上的数字进行加权求和,结果为 S。自左到右各位上的数字的权值依次为:{7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2}。
(2)将 S 对 11 取余运算,结果为 Y。
(3)根据 Y 的取值大小顺序{0,1,2,3,4,5,6,7,8,9,10}取对应的校验码{1,0,X,9,8,7,6,5,4,3,2}。
例如,当 15 位身份证号为 340524800101001 时,扩展年份后成 17 位:34052419800101001,各位上的数字的加权和 S=3*7+4*9+0*10+5*5+2*8+4*4+1*2+9*1+8*6+0*3+0*7+1*9+0*10+1*5+0*8+0*4+1*2=189,S对11取余,即 S%11=189%11=2,则校验码为“X”。
要求类定义中包含完整的含参构造函数,默认构造函数,以及析构函数。
输入
测试组数t
以下t行,输入15位身份证号
输出
每个实例包含三行输出
第1行,在构造函数输出原身份证号,看样例
第2行,调用类方法输出扩展后的身份证号,看样例
第3行,在析构函数输出提示信息,包含扩展后身份号末4位,看样例
输入样例
2
340524800101001
310001000101452
输出样例
construct ID=340524800101001
upgrade ID=34052419800101001X
destruct ID=001X
construct ID=310001000101452
upgrade ID=310001190001014527
destruct ID=4527
AC代码:
#include<iostream>
using namespace std;
class Person
{
string id;
string idd;
public:
Person(string idd)
{
id = idd;
cout << "construct ID=" << id << endl;
}
~Person()
{
idd = id.substr(14, 4);//从字符串的第14个位置开始包括本身后4位(从1开始的字符串下标)
cout << "destruct ID=" <<idd << endl;
}
void Up()
{
id.insert(6, "19");//在第6个位置插入“19”(从1开始的字符串下标)
int s = 0;
int xx[17] = { 7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2 };
for (int i = 0; i < 17; i++)
{
s = s + xx[i] * (id[i] - '0');
}
int y = s % 11;
string codelist = "10X98765432";
char code = codelist[y];//字符找到对应
id.insert(id.end(), code);//在尾部插入code(可插字符和字符串)
cout << "upgrade ID=" << id << endl;
}
};
int main()
{
int t;
cin >> t;
while (t--)
{
string k;
cin >> k;
Person kk(k);
kk.Up();
}
return 0;
}
5.【程序填空】日期比较(构造与析构)
题目描述
下面是一个日期类的定义,请在类外实现它的函数,
在主函数中先创建一个默认日期对象(无参构造)
然后输入一个日期数据年月日,创建一个日期对象(有参构造)
把输入的日期和默认日期进行比较,调用方法Before,根据比较结果输出相应的信息
注意:
凡是带"*********** constructed"的信息必定是由构造函数输出的信息
凡是带"*********** destructed"的信息必定是由析构函数输出的信息
不能在主函数或者其他区域显式地输出这些信息
输入
测试数据的组数t
输入t行年月日
输出
看样例
输入样例
3
2021 8 8
2023 1 1
2022 6 30
输出样例
Date 2022-4-1 default constructed
Date 2021-8-8 constructed
2021-8-8 before 2022-4-1
Date 2021-8-8 destructed
Date 2023-1-1 constructed
2022-4-1 before 2023-1-1
Date 2023-1-1 destructed
Date 2022-6-30 constructed
2022-4-1 before 2022-6-30
Date 2022-6-30 destructed
AC代码:
//头文件和类声明
#include <iostream>
using namespace std;
class MyDate {
private:
int year;
int month;
int day;
public:
MyDate(); //无参构造,默认日期2022-4-1,输出相关构造信息
MyDate(int ty, int tm, int td); //有参构造,根据参数初始化,输出相关构造信息
~MyDate();
bool Before(MyDate& rd);
void print()
{
cout << year << "-" << month << "-" << day;
}
};
//下面填写类实现和主函数
/********** Write your code here! **********/
MyDate::MyDate()
{
year = 2022;
month = 4;
day = 1;
cout << "Date ";
print();
cout<< " default constructed" << endl;
}
MyDate::MyDate(int yy, int mm, int dd)
{
year = yy;
month = mm;
day = dd;
cout << "Date ";
print();
cout<< " constructed" << endl;
}
MyDate::~MyDate()
{
cout << "Date ";
print();
cout<< " destructed" << endl;
}
bool MyDate::Before(MyDate& aa)
{
if (year > aa.year)
return 1;
else if (year == aa.year && month > aa.month)
return 1;
else if (year == aa.year && month == aa.month && day > aa.day)
return 1;
else
return 0;
}
int main()
{
int t;
cin >> t;
MyDate p;
while (t--)
{
int y, m, d;
cin >> y >> m >> d;
MyDate a(y, m, d);
if (p.Before(a))
{
a.print();
cout << " before ";
p.print();
cout << endl;
}
else
{
p.print();
cout << " before ";
a.print();
cout << endl;
}
}
return 0;
}
/*******************************************/
//main end
6.矩阵的右旋(类构造与析构)
题目描述
定义一个矩阵类,其中包含了矩阵的维数,矩阵,以及需要的方法
输入一个m*n的矩阵,将这个矩阵向右旋转90度后输出
比如现在有2*3矩阵 :
1 2 3
4 5 6
向右旋转90度后的矩阵变为:
4 1
5 2
6 3
要求:矩阵需要使用new方法,动态生成,并且在调用结束后使用析构函数释放空间。
输入
第一行输入t表示有t个测试实例
连续m行输入一个m*n的矩阵的数据
依次输入t个实例
输出
依次输出右转后的矩阵结果
在输出的每行中,每个数据之间都用空格隔开
输入样例
2
2 3
1 2 3
4 5 6
4 4
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
输出样例
4 1
5 2
6 3
13 9 5 1
14 10 6 2
15 11 7 3
16 12 8 4
AC代码:
#include<iostream>
using namespace std;
class Fan
{
int m;
int n;
int** p;
public:
Fan(int mm, int nn)
{
m = mm;
n = nn;
p = new int* [m];//动态开二维数组一定要会
for (int i = 0; i < m; i++)
{
p[i] = new int[n];
for (int j = 0; j < n; j++)
{
cin >> p[i][j];
}
}
}
~Fan()
{
delete p;
}
int** get()
{
return p;
}
};
int main()
{
int t;
cin >> t;
while (t--)
{
int a, b;
cin >> a >> b;
Fan aa(a, b);
int **q=aa.get();
for (int j = 0; j < b; j++)
{
for (int i = a- 1; i >= 0; i--)
{
cout << q[i][j];
if (i == 0)cout << endl;
else cout << " ";
}
}
cout << endl;
}
return 0;
}
7.身体评估(类与对象)
题目描述
评估成年人身体健康有多个指标,包括BMI、体脂率BFR等
设计一个身体健康类,包含私有成员:姓名、身高(米)、体重(公斤),腰围(厘米),实现两个公有方法如下:
BMI方法,返回BMI数值(整数),计算公式BMI= 体重 / 身高的平方
体脂率方法,返回体脂率数值(浮点数),计算过程如下:
1)参数a=腰围(cm)×0.74
2)参数b=体重(kg)×0.082+34.89
3)体脂肪重量(kg)=a-b
4)体脂率 = 体脂肪重量÷体重
其它方法根据需要自行定义
输入
第一行输入t表示有t个测试实例
第二行起,每行输入四个参数:姓名、身高、体重,腰围
依次输入t行
输出
输出t行,每行输入一个实例的BMI和体脂率,小数数值精确到小数点后2位,用空格隔开
样例查看模式
正常显示查看格式
输入样例
2
David 1.85 78.5 85.2
Sara 1.55 67.6 77.3
输出样例
David's BMI: 23--BFR: 0.28
Sara's BMI: 28--BFR: 0.25
AC代码:
#include<iostream>
#include<cmath>
#include<iomanip>
using namespace std;
class Body
{
string name;
double height;
double weight;
double waist;
int bmi;
double tti;
public:
Body(string n, double a, double c, double d)
{
name = n;
height=a;
weight=c;
waist=d;
}
void BMI()
{
bmi= weight / (height * height);
double t= weight / (height * height);
if (t - (double)bmi >= 0.5)bmi++;//注意判断四舍五入
}
void ti()
{
double t = waist * 0.74 - (weight * 0.082 + 34.89);
tti= t / weight;
}
void print()
{
cout << name << "'s BMI: " << bmi << "--BFR: " << fixed << setprecision(2) << tti << endl;
}
};
int main()
{
int t;
cin >> t;
while (t--)
{
string aa;
double bb, cc, dd;
cin >> aa >> bb >> cc >> dd;
Body t1(aa, bb, cc, dd);
t1.BMI();
t1.ti();
t1.print();
}
return 0;
}
8.Complex(类与对象+构造)
题目描述
编写一个复数类,能实现加、减运算,能输出复数的信息。 要求至少包含以下方法:
1、缺省(无参)构造函数,设置实部与虚部为1;
2、有参构造函数,给实部与虚部赋值;
3、加法运算,计算两个复数的和;
4、减法运算,计算两个复数的差;
5、输出方法,输出当前复数的值
输入
测试数据的组数t 第一组的两个复数的实部 虚部 实部 虚部 第二组的两个复数的实部 虚部 实部 虚部 ......
输出
第一组两个复数的和 第一组两个复数的差
输入样例
4
2 1 2 1
2 1 2 -1
3 1 2 -6
3 3 2 2
输出样例
sum:4+2i
remainder:0
sum:4
remainder:2i
sum:5-5i
remainder:1+7i
sum:5+5i
remainder:1+i
AC代码:
#include<iostream>
using namespace std;
class Number
{
int shi;
int xv;
public:
Number()
{
shi = 1;
xv = 1;
}
void set(int s, int x)
{
shi = s;
xv = x;
}
//注意输出+/-/i(当虚部为1)时
void add(Number& a)
{
cout << "sum:";
if (shi + a.shi != 0)
{
cout << shi + a.shi;
if (xv + a.xv > 0)
{
if (xv + a.xv != 1)cout << "+" << xv + a.xv << "i" << endl;
else cout << "+" << "i" << endl;
}
else if (xv + a.xv < 0)
{
if (xv + a.xv != -1)cout << xv + a.xv << "i" << endl;
else cout << "-" << "i" << endl;
}
else cout << endl;
}
else
{
if (xv + a.xv != 0)
{
if (xv + a.xv == -1)
cout << "-i" << endl;
else if (xv + a.xv == 1)
cout << "i" << endl;
else
cout << xv + a.xv << "i" << endl;
}
else cout<<0 << endl;
}
}
void sub(Number& a)
{
cout << "remainder:";
if (shi - a.shi != 0)
{
cout << shi - a.shi;
if (xv - a.xv > 0)
{
if(xv-a.xv!=1)cout << "+" << xv - a.xv << "i" << endl;
else cout << "+" << "i" << endl;
}
else if (xv - a.xv < 0)
{
if (xv - a.xv != -1)cout << xv - a.xv << "i" << endl;
else cout << "-" << "i" << endl;
}
else cout << endl;
}
else
{
if (xv - a.xv != 0)
{
if (xv -a.xv == -1)
cout << "-i" << endl;
else if (xv -a.xv == 1)
cout << "i" << endl;
else
cout << xv - a.xv << "i" << endl;
}
else cout << 0 << endl;
}
}
};
int main()
{
int t;
cin >> t;
while (t--)
{
int a, b, c, d;
cin>>a>>b>>c>>d;
Number t1;
t1.set(a, b);
Number t2;
t2.set(c, d);
t1.add(t2);
t1.sub(t2);
}
return 0;
}