A. 对象是怎样构造的
题目描述
某个类包含一个整型数据成员.程序运行时若输入0表示用缺省方式定义一个类对象;输入1及一个整数表示用带一个参数的构造函数构造一个类对象;输入2及一个整数表示构造2个类对象,一个用输入的整数构造,另一个用前一个对象构造。试完成该类的定义和实现。
输入
测试数据的组数t
第一组数
第二组数
…
输出
第一个对象构造输出
第二个对象构造输出
…
输入样例1
3
0
1 10
2 20
输出样例1
Constructed by default, value = 0
Constructed using one argument constructor, value = 10
Constructed using one argument constructor, value = 20
Constructed using copy constructor, value = 20
AC代码
#include<bits/stdc++.h>
using namespace std;
class Class {
int value;
public:
Class(int value):value(value){
cout << "Constructed using one argument constructor, value = " << value << endl;
}
Class() {
value = 0;
cout << "Constructed by default, value = 0" << endl;
}
Class(const Class& c) {
value = c.value;
cout << "Constructed using copy constructor, value = " << value << endl;
}
};
int main() {
int t;
cin >> t;
while (t--) {
int n, n1;
cin >> n;
if (n == 0) {
Class c;
continue;
}
cin >> n1;
if (n == 1) {
Class c(n1);
continue;
}
if (n == 2) {
Class c(n1);
Class c1(c);
}
}
return 0;
}
B. 最胖的加菲(类与对象+数组)
题目描述
有一群猫猫,每只猫都有自己的名称和体重。
用类来描述猫,名称和体重都是私有属性,要求加入属性的get方法。其他函数根据需要自己定义
创建一个动态的猫对象数组,存储各只猫的名称和体重
根据猫的体重对数组做升序排序,并输出排序后每只猫的名称
题目涉及的数值均用整数处理
输入
第一行输入n表示有n只猫
第二行输入一只猫的名称和体重
依次输入n行
输出
输出一行,输出排序后的猫的名称
输入样例1
4
chocolate 1500
water 400
cheese 3000
vegetable 200
输出样例1
vegetable water chocolate cheese
AC代码
#include<bits/stdc++.h>
using namespace std;
class Cat {
string name;
int weight;
public:
Cat() {
cin >> name >> weight;
}
string getName() {
return name; }
int getWeight() {
return weight; }
};
int main() {
int n;
cin >> n;
Cat* p = new Cat[n];
sort(p, p + n, [](Cat& p1, Cat& p2) {
return p1.getWeight() < p2.getWeight(); });
for (int i = 0; i < n; i++) {
if (i)
cout << " ";
cout << p[i].getName();
}
cout << endl;
delete[]p;
return 0;
}
C. 点圆运算(构造与析构)
题目描述
设计一个点类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,才会回收数组。
本题不要求收回数组.
输入样例1
5 2
3
4 7
9 9
2 4
3 3 3
输出样例1
in
out
out
in
circle clear
point clear
AC代码
#include<bits/stdc++.h>
using namespace std;
class Point {
int x, y;
public:
Point() {
}
Point(int x, int y) :x(x), y(y) {
}
~Point() {
x = y = 0;
cout << "point clear" << endl;
}
void setXY() {
cin >> x >> y;
}
int getX() {
return x; }
int getY() {
return y; }
};
class Circle {
int x, y;
double r;
public:
Circle() {
cin >> x >> y >> r;
}
friend class Point;
~Circle() {
x = y = r = 0;
cout << "circle clear" << endl;
}
bool Contain(Point& p) {
double r = sqrt(pow(x -p.getX() , 2) + pow(y - p.getY(), 2));
return r <= this->r;
}
};
int main() {
int x, y, r;
cin >> x >> y;
Point p(x, y);
int n;
cin >> n;
Point* pp = new Point[n];
for (int i = 0; i < n; i++) {
(pp + i)->setXY();
}
Circle c;
if (c.Contain(p))
cout << "in" << endl;
else
cout << "out" << endl;
for (int i = 0; i < n; i++) {
if(c.Contain(pp[i]))
cout << "in" << endl;
else
cout << "out" << endl;
}
//delete[]pp;
return 0;
}
D. 手机取款(类与对象数组)
题目描述
采用面向对象思想实现手机取款的过程
假设银行账户有卡号、绑定手机号、动态密码、余额等属性,包含获取各种属性、校验动态密码、取款操作。属性全是整数数据。
使用对象数组来保存n个银行账户。
用户通过手机取款的步骤如下:(一般在主函数实现)
1、用户输入手机号,在n个银行账户中找到相应的银行账户。
如果查找成功则往下执行,否则输出信息“手机号不存在”,不再往下执行;
2、用户输入动态密码,然后校验动态密码的是否正确
如果密码正确则往下执行,否则输出信息“密码错误”,不再往下执行;
3、用户输入取款金额,然后执行取款操作
如果余额不足就拒绝取款并给出信息“卡号XXX–余额不足”;如果取款成功给出信息“卡号XXX–余额YYY”,其中XXX表示卡号,YYY表示余额
上述描述只是方便说明,可以一次输入所有数据再执行各个操作。
输入
第一行输入n,表示有n个账户
下一行输入第一个账户的信息:卡号、绑定手机号、动态密码、余额
连续输入n行
接着输入k,表示要执行k次取款操作
下一行输入手机号、动态密码、取款金额
连续输入k行
输出
输出k行,每行输出操作结果
输入样例1
5
1001 138111 111 1000
1002 135222 222 200
1003 136333 333 300
1004 133444 444 400
1005 132555 555 500
4
136333 333 600
133444 444 300
133555 555 200
138111 222 900
输出样例1
卡号1003–余额不足
卡号1004–余额100
手机号不存在
密码错误
AC代码
#include<bits/stdc++.h>
using namespace std;
class Account {
int id, phone, key, balance;
public:
Account() {
cin >> id >> phone >> key >> balance;
}
int getID() {
return id; }
int getPhone() {
return phone; }
int getKey() {
return key; }
int getBalance() {
return balance; }
bool checkKey(int _key) {
return key == _key; }
void withdraw(int _value) {
if (_value > balance) {
cout << "卡号" << id << "--余额不足" << endl;
return;
}
balance -= _value;
cout<< "卡号" << id << "--余额"<<balance << endl;
}
};
class Bank {
int n;
Account*account;
public:
Bank() {
cin >> n;
account = new Account[n];
}
~Bank(){
delete[]account;
}
int getAccountIndex(int _phone) {
for (int i = 0; i < n; i++)
if (_phone == account[i].getPhone())
return i;
return -1;
}
void withdraw() {
int _phone, _key, _value;
cin >> _phone >> _key >> _value;
int index = getAccountIndex(_phone);
if (index == -1) {
puts("手机号不存在");
return;
}
if (!account[index].checkKey(_key)) {
puts("密码错误");
return;
}
account[index].withdraw(_value);
}
};
int main() {
Bank b;
int n;
cin >> n;
while (n--){
b.withdraw();
}
return 0;
}
E. 分数类(类与构造)
题目描述
完成下列分数类的实现:
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的最大公约数可采用辗转相除法,又称欧几里得算法,其步骤为:
- 交换a, b使a > b;
- 用a除b得到余数r,若r=0,则b为最大公约数,退出.
- 若r不为0,则用b代替a, r代替b,此时a,b都比上一次的小,问题规模缩小了;
- 继续第2步。
输入
测试数据的组数 t
第一组第一个分数
第一组第二个分数
第二组第一个分数
第二组第二个分数
…
输出
第一组两个分数的和
第一组两个分数的差
第一组两个分数的积
第一组两个分数的商
第二组两个分数的和
第二组两个分数的差
第二组两个分数的积
第二组两个分数的商
…
输入样例1
3
1/2
2/3
3/4
5/8
21/23
8/13
输出样例1
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代码
#include<bits/stdc++.h>
using namespace std;
class CFraction
{
private:
int fz, fm;
bool sign;
int gcd(int a, int b) {
if (a < b) swap(a, b);
return b == 0 ? a : gcd(b, a % b);
}
public:
CFraction() {
}
CFraction(int fz_val, int fm_val) :fz(fz_val), fm(fm_val) {
sign = 0;
if (fz_val < 0)
sign = !sign;
if (fm_val < 0)
sign = !sign;
fz = abs(fz);
fm = abs(fm);
int n = gcd(fz, fm);
if (n) {
fz /= n;
fm /= n;
}
}
CFraction add(const CFraction& r) {
CFraction r1 = *this;
CFraction r2 = r;
if (r1.sign)
r1.fz = -r1.fz;
if (r2.sign)
r2.fz = -r2.fz;
return CFraction(r1.fz * r2.fm + r1.fm * r2.fz, r1.fm * r2.fm);
}
CFraction sub(const CFraction& r) {
CFraction r1 = *this;
CFraction r2 = r;
if (r1.sign)
r1.fz = -r1.fz;
if (r2.sign)
r2.fz = -r2.fz;
r2.fz = -r2.fz;
return r1.add(r2);
}
CFraction mul(const CFraction& r) {
return CFraction(fz * r.fz, fm * r.fm);
}
CFraction div(const CFraction& r) {
return CFraction(fz * r.fm, fm * r.fz);
}
int getGCD() {
return gcd(fz, fm);
}
void print() {
if (sign)
cout << "-";
cout << fz << "/" << fm << endl;
}
};
int main() {
int n;
cin >> n;
while (n--) {
int fz1, fm1, fz2, fm2;
scanf("%d/%d", &fz1, &fm1);
scanf("%d/%d", &fz2, &fm2);
CFraction c1(fz1, fm1);
CFraction c2(fz2, fm2);
c1.add(c2).print();
c1.sub(c2).print();
c1.mul(c2).print();
c1.div(c2).print();
cout << endl;
}
return 0;
}
F. 找出某个范围内的所有素数(构造与析构)
题目描述
埃拉托斯特尼筛法简称埃氏筛或爱氏筛,是一种由希腊数学家埃拉托斯特尼所提出的一种简单检定素数的算法。要得到自然数n以内的全部素数,必须把不大于根号n的所有素数的倍数剔除,剩下的就是素数。
给出要筛数值的范围n,找出以内的素数。先用2去筛,即把2留下,把2的倍数剔除掉;再用下一个质数,也就是3筛,把3留下,把3的倍数剔除掉;接下去用下一个质数5筛,把5留下,把5的倍数剔除掉;不断重复下去…。
采用埃拉托斯特尼筛法求素数的算法可用以下CSieve类来实现:
class CSieve
{
private:
char *p_sieve;
unsigned long num; //num是最大范围
public:
CSieve(unsigned long n);
void printPrime();
~CSieve();
};
其中p_sieve为数组指针, p_sieve[i]=1表示i是素数, p_sieve[i]=0表示i不是素数。编写程序采用上述类来打印某个范围内的所有素数。
输入
测试数据的组数
n1
n2
…
输出
2到n1的所有素数
2到n2的所有素数
…
输入样例1
2
10
20
输出样例1
2 3 5 7
2 3 5 7 11 13 17 19
AC代码
#include<bits/stdc++.h>
using namespace std;
class CSieve {
private:
bool* p_sieve;
unsigned long num; //num是最大范围
public:
CSieve(unsigned long n) :num(n) {
p_sieve = new bool[n + 1];
//bool* visited = new bool[n + 1]{ 0 };
for (int i = 0; i < n; i++)
p_sieve[i] = 1;
p_sieve[0] = p_sieve[1] = 0;
for (int i = 2; i <= n; i++) {
if (!p_sieve[i])
continue;
for (int j = 2; i * j <= n; j++)
p_sieve[i * j] = 0;
}
}
void printPrime() {
if (num < 2)
return;
cout << 2;
for (int i = 3; i <= num; i++) {
if (p_sieve[i])
cout << " " << i;
}
cout << endl;
}
~CSieve() {
delete[]p_sieve;
}
};
int main() {
int n;
cin >> n;
while (n--) {
int t;
cin >> t;
CSieve c(t);
c.printPrime();
}
return 0;
}