2023级cpp第二学期上机练习题第3次(类的小小综合)

题源地址

1:构造函数-4

描述

构造函数有另一种写法,例如Student类中

class Student
{
private:
 string name;
 double score;
public:
 Student(string n, double s)
 {
  name = n;
  score = s;
  cout << name << "'s constructor" << endl;
 }
 //...
};

构造函数可以改写成

 Student(string n, double s) :name(n), score(s)
 {
  cout << name << "'s constructor" << endl;
 }

甚至还可以写成

 Student(string name, double score) :name(name), score(score)
 {
  cout << name << "'s constructor" << endl;
 }

请用这种写法改写下面的代码中的构造函数

#include
#include
using namespace std;
class Cat
{
private:
 string name;
 int age;
public:
 Cat(string n, int a)
 {
  name = n;
  age = a;
  cout << name << "'s constructor" << endl;
 }
 void display()
 {
  cout << name << " " << age << endl;
 }
};
int main()
{
 Cat c("Tom", 10);
 c.display();
 return 0;
}

输入

输出

Tom's constructor
Tom 10
 

样例输入

样例输出

Tom's constructor
Tom 10

关键点:

        有这玩意?

代码:

#include <iostream>
#include <string>
using namespace std;

class Cat
{
private:
    string name;
    int age;

public:
    Cat(string n, int a) : name(n), age(a)
    {
        cout << name << "'s constructor" << endl;
    }
    void display()
    {
        cout << name << " " << age << endl;
    }
};

int main()
{
    Cat c("Tom", 10);
    c.display();
    return 0;
}

2:拷贝构造函数(copy constructor)

描述

定义一个学生类Student,类的成员包括:

1、name:姓名,string类型,私有

2、score:成绩,double类型,私有

3、构造函数Student(string, double):初始化学生的姓名和成绩,并且输出“[name]'s constructor”,其中[name]要用具体的值。

4、拷贝构造函数Student(Student &):根据参数学生的姓名和成绩,初始化学生的姓名和成绩,其中名字前面多个C,成绩相同。例如参数的姓名叫Tom,成绩是90,则初始化的姓名是CTom,成绩也是90。还要输出“[name]'s copy constructor”,其中[name]要用加C后的具体值。

5、析构函数~Student():输出“[name]'s destructor”,其中[name]要用具体的值。

6、void display()函数:输出学生的姓名和成绩,中间有一个空格,最后要换行。

规定主函数是如下代码(不可以修改),根据输入输出,设计Student类以满足要求。

int main()
{
 string n1, n2;
 double a1, a2;
 cin >> n1 >> a1 >> n2 >> a2;
 Student s[2] = { {n1,a1},{n2,a2} };
 Student t = s[0];
 s[0].display();
 s[1].display();
 t.display();
 return 0;
}

输入

只有一组案例。字符串n1、浮点数a1、字符串n2、浮点数a2,分别表示第一个学生姓名和成绩、第二个学生姓名和成绩。

输出

[第一个学生的姓名]'s constructor

[第二个学生的姓名]'s constructor

[第一个学生的拷贝的姓名]'s copy constructor

[第一个学生的姓名][空格][第一个学生的成绩]

[第二个学生的姓名][空格][第二个学生的成绩]

[第一个学生的拷贝的姓名][空格][第一个学生的拷贝的成绩]

[第一个学生的拷贝的姓名]'s destructor

[第二个学生的姓名]'s destructor

[第一个学生的姓名]'s destructor

每行输出结果后面都有换行。

样例输入

AAA 10

BBB 20

样例输出

AAA's constructor
BBB's constructor
CAAA's copy constructor
AAA 10
BBB 20
CAAA 10
CAAA's destructor
BBB's destructor
AAA's destructor

提示说明

用Student类型的B对象拷贝构造A对象时,以下两种写法都是一样触发拷贝构造

Student A=B;

Student A(B);

但如果定义和构造分开写,只能是

Student A;

A=B;

关键点:

        拷贝构造函数的使用方法。

代码:

/*
定义一个学生类Student,类的成员包括:

1、name:姓名,string类型,私有

2、score:成绩,double类型,私有

3、构造函数Student(string, double):初始化学生的姓名和成绩,并且输出“[name]'s constructor”,其中[name]要用具体的值。

4、拷贝构造函数Student(Student &):根据参数学生的姓名和成绩,初始化学生的姓名和成绩,其中名字前面多个C,成绩相同。例如参数的姓名叫Tom,成绩是90,则初始化的姓名是CTom,成绩也是90。还要输出“[name]'s copy constructor”,其中[name]要用加C后的具体值。

5、析构函数~Student():输出“[name]'s destructor”,其中[name]要用具体的值。

6、void display()函数:输出学生的姓名和成绩,中间有一个空格,最后要换行。

规定主函数是如下代码(不可以修改),根据输入输出,设计Student类以满足要求。

int main()
{
 string n1, n2;
 double a1, a2;
 cin >> n1 >> a1 >> n2 >> a2;
 Student s[2] = { {n1,a1},{n2,a2} };
 Student t = s[0];
 s[0].display();
 s[1].display();
 t.display();
 return 0;
}
*/
#include <iostream>
#include <string>
using namespace std;

class Student
{
private:
    //私有变量
    string name;
    double score;
public:
    //构造函数
    Student(string n, double s)
    {
        name = n;
        score = s;
        cout << name << "'s constructor" << endl;
    }

    //拷贝构造函数
    Student(Student &s)
    {
        name = "C" + s.name;
        score = s.score;
        cout << name << "'s copy constructor" << endl;
    }

    //析构函数
    ~Student()
    {
        cout << name << "'s destructor" << endl;
    }

    //输出函数
    void display()
    {
        cout << name << " " << score << endl;
    }
};

int main()
{
 string n1, n2;
 double a1, a2;
 cin >> n1 >> a1 >> n2 >> a2;
 Student s[2] = { {n1,a1},{n2,a2} };
 Student t = s[0];
 s[0].display();
 s[1].display();
 t.display();
 return 0;
}

3:内联函数和外联函数

描述

把以下代码中类的内联成员函数(包括构造和析构函数)改写成外联的写法。(不要改程序的功能)

#include
#include
using namespace std;
class Student
{
private:
 string name;
 double score;
public:
 Student(string name, double score) :name(name), score(score)
 {
  cout << name << "'s constructor" << endl;
 }
 ~Student()
 {
  cout << name << "'s destructor" << endl;
 }
 void display()
 {
  cout << name << " " << score << endl;
 }
};
int main()
{
 Student s("Tom", 90);
 s.display();
 return 0;
}

输入

输出

Tom's constructor
Tom 90
Tom's destructor

样例输入

样例输出

Tom's constructor
Tom 90
Tom's destructor

关键点:

        我々はペイン、神だ!

代码:

//把以下代码中类的内联成员函数(包括构造和析构函数)改写成外联的写法。(不要改程序的功能)
#include<iostream>
#include<string>
using namespace std;

class Student
{
private:
 string name;
 double score;
public:
 Student(string name, double score);
 ~Student();
 void display();
};

int main()
{
 Student s("Tom", 90);
 s.display();
 return 0;
}

Student::Student(string name, double score)
{
 this->name = name;
 this->score = score;
 cout << name << "'s constructor" << endl;
}

Student::~Student()
{
 cout << name << "'s destructor" << endl;
}

void Student::display()
{
 cout << name << " " << score << endl;
}

4:类的综合题-1

描述

定义一个平面直角坐标系下的坐标点类Point,输入两个点x轴和y轴的坐标,输出两个坐标点到原点的距离,以及两个坐标点之间的距离。与正确答案的误差不大于0.01即算正确。

主函数如下:

int main()
{
 double x1, y1, x2, y2;
 cin >> x1 >> y1 >> x2 >> y2;
 Point p1(x1, y1), p2(x2, y2);
 cout << p1.getDistance() << endl; //输出p1到原点的距离
 cout << p2.getDistance() << endl; //输出p2到原点的距离
 cout << p1.getDistance(p2) << endl; //输出p1到p2的距离
 return 0;
}

输入

只有一组案例。

4个浮点数,分别是第一个点的x轴、y轴坐标,第二个点的x轴、y轴坐标

输出

3个浮点数,分别是第一个点到原点的距离、第二个点到原点的距离、两个点之间的距离。

每个数字输出完都要换行。与正确答案的误差不大于0.01即算正确。

样例输入

1 1 2 2

样例输出

1.41421
2.82843
1.41421

关键点:

        小学数学

代码:

/*
定义一个平面直角坐标系下的坐标点类Point,输入两个点x轴和y轴的坐标,输出两个坐标点到原点的距离,以及两个坐标点之间的距离。与正确答案的误差不大于0.01即算正确。

主函数如下:

int main()
{
 double x1, y1, x2, y2;
 cin >> x1 >> y1 >> x2 >> y2;
 Point p1(x1, y1), p2(x2, y2);
 cout << p1.getDistance() << endl; //输出p1到原点的距离
 cout << p2.getDistance() << endl; //输出p2到原点的距离
 cout << p1.getDistance(p2) << endl; //输出p1到p2的距离
 return 0;
}
*/
#include<iostream>
#include<string>
#include<cmath>
using namespace std;

class Point
{
private:
    //私有成员变量
    double x, y;
public:
    //构造函数
    Point(double x, double y) : x(x), y(y) {}

    //成员函数
    double getDistance()
    {
        return sqrt(x * x + y * y);
    }
    
    double getDistance(Point p)
    {
        return sqrt((x - p.x) * (x - p.x) + (y - p.y) * (y - p.y));
    }
};

int main()
{
 double x1, y1, x2, y2;
 cin >> x1 >> y1 >> x2 >> y2;
 Point p1(x1, y1), p2(x2, y2);
 cout << p1.getDistance() << endl; //输出p1到原点的距离
 cout << p2.getDistance() << endl; //输出p2到原点的距离
 cout << p1.getDistance(p2) << endl; //输出p1到p2的距离
 return 0;
}

5:类的综合题-2

描述

定义一个MyString类,用于提取字符串中的数字字符、大写字母字符和小写字母字符。

主函数如下:

int main()
{
 string s;
 cin >> s;
 MyString ms(s);
 cout << ms.f1() << endl; //输出字符串中所有的数字字符
 cout << ms.f2() << endl; //输出字符串中所有的大写字母字符
 cout << ms.f3() << endl; //输出字符串中所有的小写字母字符
 return 0;
}
 

输入

只有一组案例。

一个字符串s。

输出

3个字符串:字符串中所有的数字字符、字符串中所有的大写字母字符、字符串中所有的小写字母字符

每个字符串输出完都要换行。
 

样例输入

aPd31%E2a

样例输出

312
PE
ada

关键点:

        循环迭代 --> 用ASCII码判断 || 使用函数

代码:

/*
定义一个MyString类,用于提取字符串中的数字字符、大写字母字符和小写字母字符。

主函数如下:

int main()
{
 string s;
 cin >> s;
 MyString ms(s);
 cout << ms.f1() << endl; //输出字符串中所有的数字字符
 cout << ms.f2() << endl; //输出字符串中所有的大写字母字符
 cout << ms.f3() << endl; //输出字符串中所有的小写字母字符
 return 0;
}
*/
#include<iostream>
#include<string>
using namespace std;

class MyString
{
private:
    //成员变量
    string str;
public:
    //构造函数
    MyString(string s) : str(s) {}

    //返回字符串中所有的数字字符
    string f1()
    {
        string s;
        for(char c : str)
        {
            if(isdigit(c))
            {
                s += c;
            }
        }
        return s;
    }

    //返回字符串中所有的大写字母字符
    string f2()
    {
        string s;
        for(char c : str)
        {
            if(isupper(c))
            {
                s += c;
            }
        }
        return s;
    }

    //返回字符串中所有的小写字母字符
    string f3()
    {
        string s;
        for(char c : str)
        {
            if(islower(c))
            {
                s += c;
            }
        }
        return s;
    }
};

int main()
{
 string s;
 cin >> s;
 MyString ms(s);
 cout << ms.f1() << endl; //输出字符串中所有的数字字符
 cout << ms.f2() << endl; //输出字符串中所有的大写字母字符
 cout << ms.f3() << endl; //输出字符串中所有的小写字母字符
 return 0;
}

6:类的综合题-3

描述

根据主函数以及输入输出要求,定义猫类Cat

int main()
{
 Cat c1("Tom"), c2("Kitty"), c3("Garfield");
 c1.playwith(c2);
 c2.playwith(c1);
 c3.playwith();
 return 0;
}

输入

输出

输出的是以下三行文字,最后一行后也有换行。

Tom is playing with Kitty
Kitty is playing with Tom
Garfield is playing alone
 

样例输入

样例输出

Tom is playing with Kitty
Kitty is playing with Tom
Garfield is playing alone

关键点:

        成员函数和成员变量的使用。

代码:

/*
输出的是以下三行文字,最后一行后也有换行。

Tom is playing with Kitty
Kitty is playing with Tom
Garfield is playing alone
*/
#include<iostream>
#include<string>
using namespace std;

class Cat{
private:
    //成员变量
    string name;
public:
    //构造函数
    Cat(string n):name(n){}

    //成员函数
    void playwith(Cat &c){
        cout<<name<<" is playing with "<<c.name<<endl;
    }
    
    void playwith(){
        cout<<name<<" is playing alone"<<endl;
    }
};

int main()
{
 Cat c1("Tom"), c2("Kitty"), c3("Garfield");
 c1.playwith(c2);
 c2.playwith(c1);
 c3.playwith();
 return 0;
}

7:类的综合题-4

描述

定义圆类Circle,有3个版本的构造函数(无参时表示半径为0,有参时参数是半径,还有拷贝构造函数),display成员函数用于输出半径、周长、面积,用空格间隔,要换行。

主函数如下:

int main()
{
 double r;
 cin >> r;
 Circle c1(r), c2(c1), c3;
 c1.display();
 c2.display();
 c3.display();
 return 0;
}

输入

一个浮点数,表示c1对象的半径。

输出

3行,分别是c1、c2、c3三个圆的信息,包括半径、周长、面积,用空格间隔,要换行。

圆周率用3.14计算。

样例输入

1

样例输出

1 6.28 3.14
1 6.28 3.14
0 0 0

关键点:

        无参构造函数,拷贝构造函数

代码:

/*
定义圆类Circle,有3个版本的构造函数(无参时表示半径为0,有参时参数是半径,还有拷贝构造函数),display成员函数用于输出半径、周长、面积,用空格间隔,要换行。

主函数如下:

int main()
{
 double r;
 cin >> r;
 Circle c1(r), c2(c1), c3;
 c1.display();
 c2.display();
 c3.display();
 return 0;
}
*/
#include<iostream>
#include<string>

// 定义圆周率
constexpr auto PI = 3.14;
using namespace std;

class Circle
{
private:
    // 半径
    double r;
public:
    // 默认半径为0
    // 构造函数
    Circle(double r = 0):r(r){}

    // 拷贝构造函数
    Circle(const Circle &c):r(c.r){}

    // 输出半径、周长、面积
    void display()
    {
        cout << r << " " << 2 * PI * r << " " << PI * r * r << endl;
    }
};

int main()
{
 double r;
 cin >> r;
 Circle c1(r), c2(c1), c3;
 c1.display();
 c2.display();
 c3.display();
 return 0;
}

Δ8:类的综合题-5

描述

编写日期类Date,可以保存一个日期的年、月、日信息

成员函数isLeapYear(),用于判断当前年份是否闰年,如果是闰年则返回true,如果不是闰年则返回false。

成员函数void decrease(int a),用于把当前日期往回减a天,例如当前日期是2019.3.4,则调用decrease(3)就变成了2019.3.1。

成员函数void increase(int a),用于把当前日期变后a天,例如当前日期是2019.3.4,则调用increase(3)就变成了2019.3.7。

成员函数void display(),用于显示当前日期,以及当前日期是所在年份的第几天,例如当前日期是2019.3.4,则应该显示2019 3 4 63,最后的63表示2019.3.4是2019年的第63天。

主函数是:

int main()
{
 int n;
 cin >> n;
 while (n--)
 {
  int year, month, day, a;
  cin >> year >> month >> day >> a;
  Date d(year, month, day);
  if (d.isLeapYear())
  {
   d.decrease(a);
  }
  else
  {
   d.increase(a);
  }
  d.display();
 }
 return 0;
}
 

输入

一个正整数n,表示有n组案例。

每组案例先是3个正整数,表示年、月、日,组成的日期保证是合法的;然后是一个正整数a,表示调整的天数。

输出

针对每组案例,如果当前年份是闰年,则调用decrease成员函数把当前日期往回减a天;如果当前年份不是闰年,则调用increase成员函数把当前日期变后a天。然后调用display成员函数输出当前日期,以及当前日期是所在年份的第几天。

样例输入

2

2019 3 4 3

2020 3 4 3

样例输出

2019 3 7 66

2020 3 1 61

关键点:

        *闰年边界条件处理

        *建议自行编写

代码:

/*
编写日期类Date,可以保存一个日期的年、月、日信息

成员函数isLeapYear(),用于判断当前年份是否闰年,如果是闰年则返回true,如果不是闰年则返回false。

成员函数void decrease(int a),用于把当前日期往回减a天,例如当前日期是2019.3.4,则调用decrease(3)就变成了2019.3.1。

成员函数void increase(int a),用于把当前日期变后a天,例如当前日期是2019.3.4,则调用increase(3)就变成了2019.3.7。

成员函数void display(),用于显示当前日期,以及当前日期是所在年份的第几天,例如当前日期是2019.3.4,则应该显示2019 3 4 63,最后的63表示2019.3.4是2019年的第63天。

主函数是:

int main()
{
 int n;
 cin >> n;
 while (n--)
 {
  int year, month, day, a;
  cin >> year >> month >> day >> a;
  Date d(year, month, day);
  if (d.isLeapYear())
  {
   d.decrease(a);
  }
  else
  {
   d.increase(a);
  }
  d.display();
 }
 return 0;
}

*/
#include <iostream>
using namespace std;

class Date
{
private:
    // 年、月、日
    int year, month, day;
    // 每个月的天数
    int days[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

public:
    // 构造函数
    Date(int y, int m, int d) : year(y), month(m), day(d) {}

    // 判断是否是闰年
    bool isLeapYear()
    {
        // 年份能被4整除且不能被100整除,或者能被400整除的是闰年
        if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0)
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    // 往回减a天
    void decrease(int a)
    {
        // 循环减a天
        while (a--)
        {
            day--;
            // 如果日期小于1
            if (day == 0)
            {
                // 月份减1
                month--;

                // 如果月份小于1
                if (month == 0)
                {
                    // 年份减1
                    year--;

                    // 月份变成12
                    month = 12;
                }
                
                //天数变成上个月的天数
                day = days[month];

                // 如果是闰年
                if (month == 2 && isLeapYear())
                {
                    // 2月变成29天
                    day++;
                }
            }
        }
    }

    // 往后加a天
    void increase(int a)
    {
        // 循环加a天
        while (a--)
        {
            // 天数加1
            day++;
            // 如果天数大于当前月份的天数
            if (day > days[month])
            {
                // 如果是闰年
                if (month == 2 && isLeapYear())
                {
                    // 如果日期大于29
                    if (day > 29)
                    {
                        // 月份加1
                        month++;

                        // 天数变成1
                        day = 1;
                    }
                }
                else
                {
                    // 月份加1
                    month++;
                    
                    // 天数变成1
                    day = 1;
                }
                // 如果月份大于12
                if (month == 13)
                {
                    // 年份加1
                    year++;

                    // 月份变成1
                    month = 1;
                }
            }
        }
    }

    // 显示当前日期
    void display()
    {
        // 输出年、月、日
        cout << year << " " << month << " " << day << " ";

        // 计算当前日期是所在年份的第几天
        int sum = 0;

        // 从1月开始累加
        for (int i = 1; i < month; i++)
        {
            // 累加每个月的天数
            sum += days[i];
        }

        // 加上当前日期的天数
        sum += day;

        // 如果是闰年并且月份大于2
        if (month > 2 && isLeapYear())
        {
            // 多加1天
            sum++;
        }

        // 输出当前日期是所在年份的第几天
        cout << sum << endl;
    }
};

int main()
{
    int n;
    cin >> n;
    while (n--)
    {
        int year, month, day, a;
        cin >> year >> month >> day >> a;
        Date d(year, month, day);
        if (d.isLeapYear())
        {
            d.decrease(a);
        }
        else
        {
            d.increase(a);
        }
        d.display();
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值