C++期末综合练习

id:159 A. 音像制品(类与对象)

题目描述

某商店出租音像制品,制品信息包括:类型、名称、租金单价、状态。

其中类型用单个数字表示,对应关系为:1-黑胶片,2-CD,3-VCD,4-DVD

名称是字符串,存储制品的名称信息

租金单价表示每天租金价格

状态用单个数字表示,0是未出租,1是已出租

商店提供业务操作包括

  1. 初始化(使用构造方法),从键盘输入音像制品的信息,并设置到对象中
  2. 查询print,输出音像制品的信息
  3. 计算租金fee,参数是租借的天数,输出租金总价,如果未出租则提示,具体输出信息看示范

请定义音像制品类,并创建相应的对象来完成操作

题目涉及的数值均用整数处理

输入

第一行输入n表示有n个音像制品

每个音像制品对应两行输入

一行输入一个音像制品的多个参数,具体为:类型、名称、租金单价(正整数)、状态

一行输入操作命令,如果输入为0表示查询操作,非0则表示查询并且计算租金费用,租用天数就是这个非0值

依次输入2n行

输出

根据每个音像制品的操作命令,调用相应的操作,然后输出相关结果

输出样式看示范。

输入样例

4

1 AAA 43 1

0

2 BBB 19 0

3

3 CCC 27 1

5

4 DDD 32 1

7

输出样例

黑胶片[AAA]已出租

CD[BBB]未出租

未产生租金

VCD[CCC]已出租

当前租金为135

DVD[DDD]已出租

当前租金为224

题解

  • 使用到的知识点是类,较简单

代码实现

cpp 复制代码
#include <iostream>
using namespace std;

class CVideo
{
private:
    int price, state, type;
    string name;
public:
    CVideo(int p, int s, int t, string n);
    void print();
    void count(int d); // 计算租金fee
};

CVideo::CVideo(int p, int s, int t, string n)
    : price(p), state(s), type(t), name(n)
{
}

void CVideo::print()
{
    if (type == 1)
    {
        cout << "黑胶片";
    }
    else if (type == 2)
    {
        cout << "CD";
    }
    else if (type == 3)
    {
        cout << "VCD";
    }
    else
    {
        cout << "DVD";
    }
    cout << "[" << name << "]";
    if (state == 0)
    {
        cout << "未出租" << endl;
    }
    else
    {
        cout << "已出租" << endl;
    }
}

void CVideo::count(int d)
{
    if (state == 0) // 未出租
    {
        cout << "未产生租金" << endl;
    }
    else
    {
        cout << "当前租金为" << price * d << endl;
    }
}

int main()
{
    int n, i, type, price, state, order;
    string name;
    cin >> n;

    for (i = 0; i < n; i++)
    {
        cin >> type >> name >> price >> state >> order;
        CVideo v1(price, state, type, name);

        if (order == 0) // 查询
        {
            v1.print();
        }
        else
        {
            v1.print();
            v1.count(order);
        }
    }

    return 0;
}

id:300 B. OOP双人决斗(多重继承)

题目描述

写一个Node2D基类,属性有位置location(String)

一个Body子类继承自Node2D,属性初始生命值maxHealth,当前生命值health,防御力defense

一个Weapon子类也继承自Node2D,属性有武器名w_name,武器伤害damage

一个Player多继承自Body和Weapon,属性有名字name,方法有attack,对目标造成伤害

在主函数创建两个Player,p1、p2,判断在p1首先开始攻击的情况下谁会获胜

我们规定,每次造成的伤害等于damage减去defense

输入

输入:地点location,玩家1的名字、生命值、防御力、武器名、武器伤害,玩家2的名字、生命值、防御力、武器名、武器伤害

输出

输出:获胜信息

输入样例

palace

p1 30 5 bow 30

p2 50 10 sword 20

输出样例

p1 deal 20 damage to p2

p2 still have 30 health

p2 deal 15 damage to p1

p1 still have 15 health

p1 deal 20 damage to p2

p2 still have 10 health

p2 deal 15 damage to p1

p2 defeated p1 by sword in palace

题解

  • 本题使用到的知识点是菱形继承,虚继承
  • 首先看父类Node2D,属性是地点,实现的方法是构造
  • Body类虚继承父类,属性有最大生命值,当前生命值与防御力,实现的方法有构造,获取当前生命值与计算被攻击后的生命值
  • Weapon类虚继承父类,属性有武器伤害值和武器名字,实现的方法有构造
  • Player类继承上面两个子类,属性有人的名字,实现的方法有构造,对目标进行伤害,能造成的伤害是武器的攻击值减去另一个人的防御值得到的值,如果得到的值小于零,则不造成伤害,则将得到的伤害作为参数传进计算另一个人剩余的生命值的函数中计算剩余的生命值,然后输出
  • 在主函数,如果被攻击的人的生命值大于零就一直进行相互攻击的循环

代码实现

cpp 复制代码
#include <iostream>
using namespace std;

class Node2D
{
protected:
    string location;
public:
    Node2D(string l);
};

Node2D::Node2D(string l)
{
    location = l;
}

class Body : virtual public Node2D
{
protected:
    int maxHealth, health, defense;
public:
    Body(string l, int mh, int h, int d);
    int getH();
    void cntH(int x);
};

Body::Body(string l, int mh, int h, int d)
    : Node2D(l), maxHealth(mh), health(h), defense(d)
{
}

int Body::getH()
{
    return health;
}

void Body::cntH(int x)
{
    health = health - x;
    if (health < 0)
    {
        health = 0;
    }
}

class Weapon : virtual public Node2D
{
protected:
    int damage;
    string w_name;
public:
    Weapon(string l, int d, string w);
};

Weapon::Weapon(string l, int d, string w)
    : Node2D(l), damage(d), w_name(w)
{
}

class Player : public Body, public Weapon
{
private:
    string name;
public:
    Player(string l, string n, int h, int de, string w, int da);
    void attack(Player& pp); // 对目标造成伤害
};

Player::Player(string l, string n, int h, int de, string w, int da)
    : Node2D(l), Body(l, h, h, de), Weapon(l, da, w)
{
    name = n;
}

void Player::attack(Player& pp)
{
    int da = damage - pp.defense;
    if (da < 0)
    {
        da = 0;
    }
    cout << name << " deal " << da << " damage to " << pp.name << endl;
    pp.cntH(da);

    if (pp.health > 0)
    {
        cout << pp.name << " still have " << pp.health << " health" << endl << endl;
    }
    else
    {
        cout << name << " defeated " << pp.name << " by sword in " << location << endl;
    }
}

int main()
{
    int h1, h2, defense1, defense2, damage1, damage2;
    string l, n1, n2, w_n1, w_n2;
    cin >> l >> n1 >> h1 >> defense1 >> w_n1 >> damage1;
    cin >> n2 >> h2 >> defense2 >> w_n2 >> damage2;
    Player p1(l, n1, h1, defense1, w_n1, damage1);
    Player p2(l, n2, h2, defense2, w_n2, damage2);

    while (p1.getH() > 0 && p2.getH() > 0)
    {
        p1.attack(p2);
        if (p2.getH() == 0)
        {
            break;
        }
        p2.attack(p1);
    }

    return 0;
}

id:181 C. 宠物的生长(虚函数和多态)

题目描述

需要开发一个系统,对宠物的生长状态进行管理。给出下面的基类框架:

cpp 复制代码
class Pet

{ protected:

  string name;//姓名

float length;//身长

float weight;//体重

CDate current;//开始记录时间

(日期类CDate包含年、月、日三个私有数据,其他方法根据需要自拟。)

public:

virtual void display(CDate day)=0;//输出目标日期时宠物的身长和体重

}

以Pet为基类,构建出Cat和Dog两个类:

Cat一天身长加0.1,体重加0.2。

Dog一天身长加0.2,体重加0.1。

生成上述类并编写主函数,要求主函数中有一个基类指针Pet *pt,用于测试子类数据。

主函数根据输入的信息,相应建立Cat类对象或Dog类对象,并给出测量日期时宠物的身长和体重。

输入

第一行为测试次数

第二行是开始记录日期

从第三行起,每个测试用例占一行,每行给出宠物的基本信息:宠物的类型(1为Cat,2为Dog)、名字、身长、体重、最后测量的日期。

输出

要求输出目标日期宠物姓名、身长和体重(结果要求保留小数点后2位)。若测量日期小于开始日期,输出"error"。

输入样例

3

2019 5 5

1 tony 10 10 2018 12 30

2 jerry 5 6 2019 5 10

1 tom 3 4 2019 6 1

输出样例

error

jerry after 5 day: length=6.00,weight=6.50

tom after 27 day: length=5.70,weight=9.40

题解

  • 用到的知识点是虚函数与多态,计算日期也是一个点

代码实现

cpp 复制代码
#include <iostream>
#include <iomanip>
using namespace std;

class CDate
{
private:
    int year, month, day;
public:
    CDate(int y, int m, int d);
    bool isLeapYear();
    int getY();
    int getM();
    int getD();
    int getDayofYear();
};

CDate::CDate(int y, int m, int d)
{
    year = y, month = m, day = d;
}

bool CDate::isLeapYear()
{
    return (year % 4 == 0 && year % 100 != 0) || year % 400 == 0;
}

int CDate::getY()
{
    return year;
}

int CDate::getM()
{
    return month;
}

int CDate::getD()
{
    return day;
}

int CDate::getDayofYear()
{
    int i, sum = day;
    int a[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
    if (isLeapYear())
    {
        a[2]++;
    }
    // 求日期的天数
    for (i = 0; i < month; i++)
    {
        sum += a[i];
    }
    return sum;
}

class Pet
{
protected:
    string name;//姓名
    float length, weight;
    CDate current; // 开始记录时间
public:
    Pet(string n1, float l, float w, int y, int m, int d);
    virtual void display(CDate day) = 0; // 输出目标日期时宠物的身长和体重
    ~Pet() {} // 虚析构函数
};

Pet::Pet(string n1, float l, float w, int y, int m, int d)
    : current(y, m, d)
{
    name = n1;
    length = l;
    weight = w;
}

class Cat : public Pet
{
public:
    Cat(string n1, float l, float w, int y, int m, int d);
    void display(CDate day);
};

Cat::Cat(string n1, float l, float w, int y, int m, int d)
    : Pet(n1, l, w, y, m, d)
{
}

void Cat::display(CDate day)
{
    int date = day.getDayofYear() - current.getDayofYear();
    length += date * 0.1;
    weight += date * 0.2;
    cout << name << " after " << date << " day: length=" << fixed << setprecision(2) << length << ",weight=" << fixed << setprecision(2) << weight << endl;
}

class Dog : public Pet
{
public:
    Dog(string n1, float l, float w, int y, int m, int d);
    void display(CDate day);
};

Dog::Dog(string n1, float l, float w, int y, int m, int d)
    : Pet(n1, l, w, y, m, d)
{
}

void Dog::display(CDate day)
{
    int date = day.getDayofYear() - current.getDayofYear();
    length += date * 0.2;
    weight += date * 0.1;
    cout << name << " after " << date << " day: length=" << fixed << setprecision(2) << length << ",weight=" << fixed << setprecision(2) << weight << endl;
}

int main()
{
    int t, i, y1, m1, d1, type, y2, m2, d2, cnt1, cnt2;
    float l, w;
    string name;
    Pet* pt;
    cin >> t >> y1 >> m1 >> d1;
    CDate dd1(y1, m1, d1);
    cnt1 = y1 * 10000 + m1 * 100 + d1;

    for (i = 0; i < t; i++)
    {
        cin >> type >> name >> l >> w >> y2 >> m2 >> d2;
        CDate dd2(y2, m2, d2);
        cnt2 = y2 * 10000 + m2 * 100 + d2;
        if (cnt2 < cnt1)
        {
            cout << "error" << endl;
            continue;
        }
        if (type == 1) // Cat
        {
            pt = new Cat(name, l, w, y1, m1, d1);
        }
        else
        {
            pt = new Dog(name, l, w, y1, m1, d1);
        }
        pt->display(dd2);
    }

    return 0;
}

id:187 D. 集合(运算符重载)

题目描述

集合是由一个或多个确定的元素所构成的整体。集合的运算有并、交、相对补等。

集合A和集合B的交集:由属于A且属于B的相同元素组成的集合。

集合A和集合B的并集:由所有属于集合A或属于集合B的元素所组成的集合。

集合B关于集合A的相对补集,记做A-B:由属于A而不属于B的元素组成的集合。

假设集合A={10,20,30},集合B={1,10,50,8}。则A与B的并是{10,20,30,1,50,8},A与B的交是{10},B关于A的相对补集是{20,30}。

定义整数集合类CSet,属性包括:集合中的元素个数n,整型指针data存储集合中的元素。

方法有:重载输出,按样例格式输出集合中的元素。

重载+运算符,求集合A和集合B的并集,并返回结果集合。

重载-运算符,求集合B关于集合A的相对补集,并返回结果集合。

重载*运算符,求集合A和集合B的交集,并返回结果集合。

主函数输入集合A、B的数据,计算集合的并、交、相对补。

可根据题目,为CSet类添加需要的成员函数。

输入

测试次数

每组测试数据两行,格式如下:

第一行:集合A的元素个数和元素

第二行:集合B的元素个数和元素

输出

每组测试数据输出如下:

第一行:集合A

第二行:集合B

第三行:A和B的并

第四行:A和B的交

第五行:B关于A的相对补集 与 A关于B的相对补集的并,即(A-B)+(B-A)

每组测试数据间以空行分隔。

输入样例

2

3 10 20 30

4 10 1 2 3

5 100 2 3 4 -10

6 -34 12 2 4 90 100

输出样例

A:10 20 30

B:10 1 2 3

A+B:10 20 30 1 2 3

A*B:10

(A-B)+(B-A):20 30 1 2 3

A:100 2 3 4 -10

B:-34 12 2 4 90 100

A+B:100 2 3 4 -10 -34 12 90

A*B:100 2 4

(A-B)+(B-A):3 -10 -34 12 90

题解

  • 运用到的知识点是运算符重载和输出重载
  • 求并集方法,首先定义一个类的数组让他等于第一个数组,然后遍历另一个数组,如果这个数组中的某个元素与新定义的数组中都找不到相同的元素,则赋值,要注意的是,要记录新定义的数组中放进去了多少个元素,然后重新作为这个数组的大小
  • 求相对补集的方法,在运算符重载函数中我只求了一个数组对另一个数组的相对补集,并没有将两个数组的相互补集都求出来,而是分别求出来后在主函数进行输出拼接,在重载函数中,用冒泡方法遍历其中一个数组,如果在另一个数组中都找不到跟这个元素相同的元素则赋值,也要记录新定义的数组存储了多少个元素,更新这个新定义的数组的大小
  • 求交集就是找两个数组都存在的元素
  • 还需要一个赋值号运算符重载
  • 记得析构和主函数删除地址

代码实现

cpp 复制代码
#include <iostream>
#include <algorithm>
using namespace std;

class CSet
{
private:
    int n, * data;
public:
    CSet(int n1);
    CSet(int n1, int a[]);
    CSet(const CSet& s1);
    ~CSet();
    friend ostream& operator<<(ostream&, const CSet&); // 重载输出
    CSet operator+(const CSet& s1); // 并集
    CSet operator-(const CSet& s1); // 相对补集
    CSet operator*(const CSet& s1); // 交集
    CSet& operator=(const CSet& s1);
};

CSet::CSet(int n1)
    : n(n1)
{
    int i;
    data = new int[n];
    for (i = 0; i < n; i++)
    {
        data[i] = 0;
    }
}

CSet::CSet(int n1, int a[])
    : n(n1)
{
    int i;
    data = new int[n];
    for (i = 0; i < n; i++)
    {
        *(data + i) = *(a + i);
    }
}

CSet::CSet(const CSet& s1)
    : n(s1.n), data(s1.data)
{
}

CSet::~CSet()
{
    delete[] data;
}

ostream& operator<<(ostream& o, const CSet& s1)
{
    int i;
    for (i = 0; i < s1.n; i++)
    {
        if (i == 0)
        {
            o << s1.data[i];
        }
        else
        {
            o << " " << s1.data[i];
        }
    }
    return o;
}

CSet CSet::operator+(const CSet& s1)
{
    int i, k, j, f;
    CSet s2(n + s1.n);

    for (i = 0; i < n; i++)
    {
        s2.data[i] = data[i];
    }
    j = n;
    for (i = 0; i < s1.n; i++)
    {
        f = 0; // 无相同
        for (k = 0; k < j; k++)
        {
            if (data[k] == s1.data[i])
            {
                f = 1;
                break;
            }
        }
        if (f == 0)
        {
            s2.data[j] = s1.data[i];
            j++;
        }
    }
    s2.n = j;
    return s2;
}

CSet CSet::operator-(const CSet& s1)
{
    int i, j, f, k;
    CSet s2(n);
    k = 0;

    for (i = 0; i < n; i++)
    {
        f = 0;
        for (j = 0; j < s1.n; j++)
        {
            if (data[i] == s1.data[j])
            {
                f = 1;
                break;
            }
        }
        if (f == 0)
        {
            s2.data[k] = data[i];
            k++;
        }
    }
    s2.n = k;
    return s2;
}

CSet CSet::operator*(const CSet& s1)
{
    int i, j, k;
    CSet s2(n);
    k = 0;

    for (i = 0; i < n; i++)
    {
        for (j = 0; j < s1.n; j++)
        {
            if (data[i] == s1.data[j])
            {
                s2.data[k] = data[i];
                k++;
                break;
            }
        }
    }
    s2.n = k;
    return s2;
}

CSet& CSet::operator=(const CSet& s1)
{
    int i;
    n = s1.n;
    for (i = 0; i < s1.n; i++)
    {
        data[i] = s1.data[i];
    }
    return *this;
}

int main()
{
    int t, i, n1, n2, * a, * b, j;
    cin >> t;

    for (i = 0; i < t; i++)
    {
        cin >> n1;
        a = new int[n1];
        for (j = 0; j < n1; j++)
        {
            cin >> *(a + j);
        }
        cin >> n2;
        b = new int[n2];
        for (j = 0; j < n2; j++)
        {
            cin >> *(b + j);
        }
        CSet s1(n1, a);
        CSet s2(n2, b);

        cout << "A:" << s1 << endl;
        cout << "B:" << s2 << endl;
        CSet s3(n1 + n2);
        s3 = (n1 + n2);
        s3 = s1 + s2; // 并
        cout << "A+B:" << s3 << endl;
        s3 = s1 * s2; // 交
        cout << "A*B:" << s3 << endl;
        s3 = s1 - s2; // 相对补集
        cout << "(A-B)+(B-A):" << s3 << " ";
        s3 = s2 - s1;
        cout << s3 << endl;

        delete[] a;
        delete[] b;
        cout << endl;
    }

    return 0;
}

id:192 E. 最贵的书(重载+友元+引用)

题目描述

定义CBook,属性包含书名(string),编者(string)、售价(double),出版社(string)。方法有:重载输入、输出。

定义友元函数find(CBook *book, int n, int &max1index,int &max2index)查找n本书中售价最高、次高的两本书,并通过引用返回其下标。若有相同售价最高、次高的两本书,按输入顺序输出第一本、第二本。

输入n,输入n本书的信息,调用上述友元函数,求价格最高的两本书下标,并按样例格式输出书信息。

输入

测试次数

每组测试数据格式如下:

n

n行书信息(书名,编者,售价,出版社)

输出

每组测试数据输出两行:

第一行:售价最高的书信息。

第二行:售价次高的书信息。

具体输出格式见样例,售价保留两位小数。书中间以空格分隔。

输入样例

1

5

python从入门到精通,艾里克.马瑟斯,62.00,人民邮电出版社

Java并发编程实战,盖茨,54.5,机械工业出版社

Effective Java中文版,约书亚.布洛克,94,机械工业出版社

重构 改善既有代码的设计,马丁.福勒,122.6,人民邮电出版社

活用数据:驱动业务的数据分析实战,陈哲,61.4,电子工业出版社

输出样例

重构 改善既有代码的设计

马丁.福勒

122.60

人民邮电出版社

Effective Java中文版

约书亚.布洛克

94.00

机械工业出版社

提示

读取','前的字符用 getline进行输入,如下所示

cpp 复制代码
#include <string>

string  name;

getline(cin, name, ',');

题解

  • 运用到的知识点是重载有元和引用
  • 查找最大最小值的方法我是使用了冒泡排序的方法,但是实际上最好不好改变题目给出的数组顺序

代码实现

cpp 复制代码
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;

class CBook
{
private:
    double price;
    string name, person, press;
public:
    friend istream& operator>>(istream& i, CBook& c);
    friend ostream& operator<<(ostream& o, const CBook& c);
    friend void find(CBook* book, int n, int& max1index, int& max2index);
    CBook& operator=(const CBook& b1);
};

istream& operator>>(istream& i, CBook& c)
{
    char ch;
    getline(i, c.name, ','); // 书名
    getline(i, c.person, ','); // 编者
    i >> c.price >> ch;
    getline(i, c.press, '\n');
    return i;
}

ostream& operator<<(ostream& o, const CBook& c)
{
    o << c.name << endl;
    o << c.person << endl;
    o << fixed << setprecision(2) << c.price << endl;
    o << c.press << endl << endl;
    return o;
}

void find(CBook* book, int n, int& max1index, int& max2index)
{
    int i, j;
    CBook c;

    for (i = 0; i < n; i++)
    {
        for (j = i + 1; j < n; j++)
        {
            if (book[i].price < book[j].price)
            {
                c = book[i];
                book[i] = book[j];
                book[j] = c;
            }
        }
    }
    max1index = 0;
    max2index = 1;
}

CBook& CBook::operator=(const CBook& b1)
{
    name = b1.name;
    person = b1.person;
    press = b1.press;
    price = b1.price;
    return *this;
}

int main()
{
    int t, n, i, j, ans1, ans2;
    char ch;
    CBook* cc;
    cin >> t;
    ans1 = 0;
    ans2 = 0;

    for (i = 0; i < t; i++)
    {
        cin >> n;
        cc = new CBook[n];
        ch = getchar();
        for (j = 0; j < n; j++)
        {
            cin >> cc[j];
        }
        find(cc, n, ans1, ans2);
        cout << cc[ans1];
        cout << cc[ans2];
        delete[] cc;
    }

    return 0;
}
相关推荐
td爆米花几秒前
C#冒泡排序
数据结构·算法·排序算法
我曾经是个程序员3 分钟前
C#File文件基础操作大全
开发语言·c#
捕鲸叉6 分钟前
C++软件设计模式之代理(Proxy)模式
c++·设计模式
林浔09068 分钟前
QT信号槽
开发语言·qt
重生之绝世牛码12 分钟前
Java设计模式 —— 【结构型模式】享元模式(Flyweight Pattern) 详解
java·大数据·开发语言·设计模式·享元模式·设计原则
chenziang120 分钟前
leetcode hot100
算法·leetcode·职场和发展
Allen Bright26 分钟前
【Java基础-26.1】Java中的方法重载与方法重写:区别与使用场景
java·开发语言
执着的小火车28 分钟前
02-18.python入门基础一基础算法
数据结构·python·算法·排序算法
梦茹^_^29 分钟前
排序算法(系列)
数据结构·python·算法·排序算法·希尔排序·基数排序·计数排序和桶排序
秀儿y31 分钟前
单机服务和微服务
java·开发语言·微服务·云原生·架构