C++_第八周做题总结

news2024/11/18 11:50:51

id:45 A.Equation(类与对象+构造)

题目描述

建立一个类Equation,表达方程ax2+bx+c=0。类中至少包含以下方法:

  1. 无参构造(abc默认值为1.0、1.0、0)与有参构造函数,用于初始化a、b、c的值;

  2. set方法,用于修改a、b、c的值

  3. getRoot方法,求出方程的根。

一元二次方程的求根公式如下:
在这里插入图片描述
一元二次方程的求解分三种情况,如下:
在这里插入图片描述

输入

输入测试数据的组数t

第一组a、b、c

第二组a、b、c

输出

输出方程的根,结果到小数点后2位

在C++中,输出指定精度的参考代码如下:

#include <iostream>
#include <iomanip> //必须包含这个头文件
using namespace std;

void main( )
{
	double a =3.14;
	cout<<fixed<<setprecision(3)<<a<<endl;  //输出小数点后3位

输入样例

3
2 4 2
2 2 2
2 8 2

输出样例

x1=x2=-1.00
x1=-0.50+0.87i x2=-0.50-0.87i
x1=-0.27 x2=-3.73

题解

  • 首先分析类,Equation();,无参构造,用于初始化abc的值;void set(double m, double n, double p);,用于将abc的值修改为参数的值;void getRoot();求根的函数,在函数中,我们首先定义一个变量来记录b * b - 4 * a * c的值,然后通过这个值的判断,分为三种情况进行讨论,注意,当这个变量小于零时,我们开平方时需要开这个变量的相反数,最后做一些细节处理输入输出即可
  • 在主函数中,我们输入abc的值后,调用设置值的函数,将输入的值传递到类的变量中,然后进行x值的输出

代码实现

#include <iostream>
#include <iomanip>
#include <cmath>
using namespace std;

class Equation
{
private:
    double a, b, c;
public:
    Equation(); // 无参构造,初始化
    void set(double m, double n, double p); // 修改a, b, c的值
    void getRoot(); // 求根
};

Equation::Equation()
{
    a = 1.0;
    b = 1.0;
    c = 0;
}

void Equation::set(double m, double n, double p)
{
    a = m;
    b = n;
    c = p;
}

void Equation::getRoot()
{
    double x1, x2, t, j1, k1, k2;
    t = b * b - 4 * a * c;

    if (t == 0)
    {
        x1 = (-b + sqrt(t)) / (2 * a);
        cout << "x1=x2=" << fixed << setprecision(2) << x1 << endl;
    }
    else if (t > 0)
    {
        x1 = (-b + sqrt(t)) / (2 * a);
        x2 = (-b - sqrt(t)) / (2 * a);
        cout << "x1=" << fixed << setprecision(2) << x1 << " x2=" << fixed << setprecision(2) << x2 << endl;
    }
    else // 共轭复数
    {
        j1 = -b / (2 * a);
        k1 = (sqrt(-t)) / (2 * a);
        k2 = (sqrt(-t)) / (2 * a);
        cout << "x1=" << fixed << setprecision(2) << j1 << "+" << fixed << setprecision(2) << k1;
        cout << "i x2=" << fixed << setprecision(2) << j1 << "-" << fixed << setprecision(2) << k2 << "i" << endl;
    }
}

int main()
{
    int t, i;
    double aa, bb, cc;
    Equation y;
    cin >> t;

    for (i = 0; i < t; i++)
    {
        cin >> aa >> bb >> cc;
        y.set(aa, bb, cc);
        y.getRoot();
    }

    return 0;
}

id:50 B.对象是怎样构造的(拷贝构造函数)

题目描述

某个类包含一个整型数据成员.程序运行时若输入0表示用缺省方式定义一个类对象;输入1及一个整数表示用带一个参数的构造函数构造一个类对象;输入2及一个整数表示构造2个类对象,一个用输入的参数构造,另一个用前一个对象构造。试完成该类的定义和实现。

输入

测试数据的组数 t

第一组数

第二组数

输出

第一个对象构造输出

第二个对象构造输出

输入样例

3
0
1 10
2 20

输出样例

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

题解

  • 首先来分析类,Member(); // 缺省定义,用于初始化val的值;Member(int a);用于将参数的值赋值到valMember(const Member&ans1); // 拷贝构造函数,我们也是将参数的val值赋值到val中;void set(int b); // 设置值,用于将参数的值赋值到val中;int get(); // 获得值,返回val的值
  • 在主函数中,输入组数后,在for循环中在输入一个整数表示用什么方法来构造,然后通过这个整数的判断,用不同的方法,然后不同的输出

代码实现

#include <iostream>
using namespace std;

class Member
{
private:
    int val;
public:
    Member(); // 缺省定义
    Member(int a);
    Member(const Member&ans1); // 拷贝构造函数
    void set(int b); // 设置值
    int get(); // 获得值
};

Member::Member()
{
    val = 0;
}

Member::Member(int a)
{
    val = a;
}

Member::Member(const Member&ans1)
{
    val = ans1.val;
}

void Member::set(int b)
{
    val = b;
}

int Member::get()
{
    return val;
}

int main()
{
    int t, i, n, x;
    cin >> t;

    for (i = 0; i < t; i++)
    {
        cin >> n;

        if (n == 0)
        {
            Member ans;
            cout << "Constructed by default, value = " << ans.get() << endl;
        }
        else if (n == 1)
        {
            cin >> x;
            Member ans(x);
            cout << "Constructed using one argument constructor, value = " << ans.get() << endl;
        }
        else if (n == 2)
        {
            cin >> x;
            Member ans1(x); // 输入的参数构造
            cout << "Constructed using one argument constructor, value = " << ans1.get() << endl;
            Member ans2(ans1); // 调用拷贝构造函数
            cout << "Constructed using copy constructor, value = " << ans2.get() << endl;
        }
    }

    return 0;
}

id:51 C.电话号码升位(拷贝构造函数)

题目描述

定义一个电话号码类CTelNumber,包含1个字符指针数据成员,以及构造、析构、打印及拷贝构造函数。

字符指针是用于动态创建一个字符数组,然后保存外来输入的电话号码

构造函数的功能是为对象设置键盘输入的7位电话号码,

拷贝构造函数的功能是用原来7位号码的对象升位为8位号码对象,也就是说拷贝构造的对象是源对象的升级.电话升位的规则是原2、3、4开头的电话号码前面加8,原5、6、7、8开头的前面加2。

注意:电话号码只能全部是数字字符,且与上述情况不符的输入均为非法

输入

测试数据的组数 t

第一个7位号码

第二个7位号码

输出

第一个号码升位后的号码

第二个号码升位后的号码

如果号码升级不成功,则输出报错信息,具体看示例

输入样例1

3
6545889
3335656
565655

输出样例1

26545889
83335656
Illegal phone number

输入样例2

2
1234567
22a2567

输出样例2

Illegal phone number
Illegal phone number

题解

  • CTelNumber类:先定义一个私有的字符型指针,用于存储号码;四个公有的函数,CTelNumber(char *p1); // 构造,构造函数,用于设置七位电话号码;~CTelNumber(); // 析构,析构函数,用于释放动态创建的用于存储电话号码的字符指针所指向的空间;void print(); // 打印,打印函数,用于打印电话号码;CTelNumber(const CTelNumber& p1); // 拷贝构造,是拷贝构造函数,用于处理在电话号码前添加数字
  • CTelNumber(char *p1);,构造函数,我们先用srelen函数计算得到传入的电话号码的字节数,然后为phone申请的内存空间比得到的字节数多2,一个用来存储后面添加进来的数字,一个用来放字符串结束符\0,然后使用strncpy函数将值进行赋值,最后在末尾放结束标志符
  • CTelNumber(const CTelNumber& p1);拷贝构造函数,首先为phone申请一段新的内存空间,然后赋值,判断号码的第一位的数字是几,则实行不同的相应操作,操作结束后在字符数组的末尾添加字符串结束符
  • 首先读入组数,然后我们是用字符数组存储电话号码,所以我们要去掉输入组数后的那个换行符,然后动态创建一个字符指针,输入号码,获取长度,判断其长度是否为7,若不是,则视为非法输入,否则,挨个判断每个元素是否是数字,若不是,记为非法输入,所以我们需要有一个变量判断输入进来的电话号码是否为非法输入,还要判断电话号码的第一位数字不能是019,若输入的号码是正确的,则进行构造初始化,和拷贝构造在开头新添数字,然后输出,最后记得要释放动态创建的内存

犯的错误

修改前的代码中

  1. CTelNumber 构造函数中,我首先为 phone 分配了新的内存,然后立即将 phone 指向 p1。这样会导致内存泄漏,因为我无法再访问和删除之前分配的内存。所以应该使用 strncpy 函数来复制 p1phone

  2. 在拷贝构造函数中,我没有为 phone 分配新的内存,但是试图将数据复制到 phone。这将导致未定义的行为,因为我正在写入未分配的内存。所以需要首先为 phone 分配新的内存。

  3. 我之前的的程序没有处理电话号码的长度。如果电话号码的长度不是7,程序可能会出现问题。所以需要添加一些检查来确保电话号码的长度是正确的。

  4. 且我在判断输入的电话号码是否合法时,及判断输入的第一位数字,没有用到ACSLL的值

代码实现

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

class CTelNumber
{
private:
    char* phone;
public:
    CTelNumber(char *p1); // 构造
    ~CTelNumber(); // 析构
    void print(); // 打印
    CTelNumber(const CTelNumber& p1); // 拷贝构造
};

CTelNumber::CTelNumber(char *p1) // 设置7位电话号码
{
    size_t len = strlen(p1);
    phone = new char[len + 2]; // 存储'\0'
    strncpy(phone, p1, len);
    phone[len] = '\0';
}

CTelNumber::~CTelNumber()
{
    delete[] phone;
}

void CTelNumber::print()
{
    cout << phone << endl;
}

CTelNumber::CTelNumber(const CTelNumber& p1)
{
    int i, len;
    len = strlen(p1.phone);
    phone = new char[len + 2]; // 重新分配内存,存储'\0'
    strncpy(phone, p1.phone, len);

    if (*phone == '2' || *phone == '3' || *phone == '4') // 234开头
    {
        *phone = '8';
        for (i = 0; i < 7; i++)
        {
            *(phone + 1 + i) = *(p1.phone + i);
        }
    }
    else
    {
        *phone = '2';
        for (i = 0; i < 7; i++)
        {
            *(phone + 1 + i) = *(p1.phone + i);
        }
    }
    *(phone + len + 1) = '\0'; // 添加结束字符
}

int main()
{
    int t, i, f, j;
    char ch;
    cin >> t; // 组数
    ch = getchar(); // 舍弃换行符

    for (i = 0; i < t; i++)
    {
        f = 0; // 正确
        char* p = new char[9];
        cin >> p; // 读取一行输入,最多8个字符和一个结束字符
        int len = strlen(p); // 获取输入的长度

        if (len != 7) // 如果输入的长度不是7,标记为非法输入
        {
            f = 1;
        }
        else
        {
            for (j = 0; j < len; j++)
            {
                if ((*(p + j) - '0') < 0 || (*(p + j) - '9') > 9)
                {
                    f = 1; // 输入不为数字
                    break;
                }
            }
        }
        if (*p == '0' || *p == '1' || *p == '9') // 如果第一位的数字是019
        {
            f = 1; // 错误
        }
        if (f == 1) // 非法输入
        {
            cout << "Illegal phone number" << endl;
        }
        else
        {
            CTelNumber pp(p); // 设置7位电话号码
            CTelNumber p2(pp); // 调用拷贝构造函数
            p2.print();
        }
        delete[] p;
    }

    return 0;
}

id:52 D.软件备份(拷贝构造函数)

题目描述

软件作为一种对象也可以用类来描述,软件的属性包括软件名称、类型(分别用O、T和B表示原版、试用版还是备份)、有效截止日期(用CDate类子对象表示)和存储介质(分别用D、H和U表示光盘、磁盘和U盘)等。软件拷贝可通过拷贝构造函数来实现,此时在拷贝构造函数中软件类型改成“B”, 存储介质改为"H",其它不变。试完成该类的拷贝构造、构造和打印(包括从2015年4月7日算起有效期还有多少天,是否过期)成员函数的实现。

当输入软件有效截止日期是0年0月0日,表示无日期限制,为unlimited;当输入日期在2015年4月7日之前,则是过期,表示为expired;如果输入日期在2015年4月7日之后,则显示之后的剩余天数。具体输出信息看输出范例。

附CDate类的实现:

class CDate
{
    private:
        int year, month, day;
    public:
        CDate(int y, int m, int d);
        bool isLeapYear();
        int getYear();
        int getMonth();
        int getDay();
        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::getYear()
{ 
    return year;
}
 
int CDate::getMonth() 
{ 
    return month;
}
 
int CDate::getDay() 
{ 
    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;
}

输入

测试数据的组数 t

第一个软件名称

第一个软件类型  第一个软件介质类型  第一个软件有效期年 月 日

第二个软件名称

第二个软件类型 第二个软件介质类型 第二个软件有效期年 月 日

......

注意:软件名称最大长度为30

输入

name: 第一个软件名称

type: 第一个软件类型

media: 第一个软件介质类型

第一个软件2015-4-7后的有效天数

 

name: 第一个软件名称

type: backup

media: hard disk

第一个软件2015-4-7后的有效天数

......

输入样例1

3
Photoshop_CS5
O D 0 0 0
Audition_3.0
B U 2015 2 3
Visual_Studio_2010
T H 2015 5 5

输出样例1

name:Photoshop_CS5
type:original
media:optical disk
this software has unlimited use

name:Photoshop_CS5
type:backup
media:hard disk
this software has unlimited use

name:Audition_3.0
type:backup
media:USB disk
this software has expired

name:Audition_3.0
type:backup
media:hard disk
this software has expired

name:Visual_Studio_2010
type:trial
media:hard disk
this software is going to be expired in 28 days

name:Visual_Studio_2010
type:backup
media:hard disk
this software is going to be expired in 28 days

输入样例2

2
Photoshop_CS5
O D 2015 4 8
Audition_3.0
B U 2023 4 7

输出样例2

name:Photoshop_CS5
type:original
media:optical disk
this software is going to be expired in 1 days

name:Photoshop_CS5
type:backup
media:hard disk
this software is going to be expired in 1 days

name:Audition_3.0
type:backup
media:USB disk
this software is going to be expired in 2922 days

name:Audition_3.0
type:backup
media:hard disk
this software is going to be expired in 2922 days

题解

  • CDate类:定义三个私有变量,年月日,定义六个公有函数,CDate(int y, int m, int d); // 构造函数初始化bool isLeapYear(); // 判断是否是闰年int getYear(); // 返回年份int getMonth();int getDay();int getDayofYear();,返回一个整数,这个整数是这个日期前的天数的总和
  • CDate(int y, int m, int d);,将参数的值传入年月日中
  • bool isLeapYear();,如果是闰年,返回1,否则,返回0
  • int getYear();int getMonth();int getDay();,分别返回调用这个函数的变量的年月日
  • int CDate::getDayofYear();,题目给出的函数,定义一个存放12个月份的天数的数组,然后把这个月份之前的月份的天数累加,再加上这个月份的天数,得到的结果即为这个日期前所有的月份总和,把值返回
  • Soft类:定义四个私有变量,软件名称,软件类型,有效日期和存储介质;和四个公有函数,Soft(const Soft &s1); // 软件拷贝Soft(char *m, char n, char p, CDate d); // 构造初始化void print(); // 打印 ~Soft(); // 析构函数释放内存
  • Soft::Soft(const Soft &s1) // 拷贝构造函数;,首先用: dd(s1.dd) // 初始化来进行对日期的初始化,因为日期不是一个指针,所以可以这样对其赋值,然后计算软件名称的字节数,动态分配这个字节数加1的内存给name,加1是为了在末尾处放上字符串结束符,然后使用strncpy函数对其赋值,由于软件名称和存储介质都是单个字符型,所以可以直接使用赋值号对其进行赋值,软件类型改为‘B‘,存储介质改为’H‘
  • Soft::Soft(char *m, char n, char p, CDate d) // 构造,构造函数和拷贝构造函数大同小异
  • void Soft::print();,输出函数,按照输出样例,分不同的情况进行不同的输出,注意后面有效天数的年份大于2015年时的计算
  • Soft::~Soft();,析构函数,释放软件名称内存
  • 主函数中,进行输入,初始化,拷贝构造,打印,释放内存即可

代码实现

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

class CDate
{
private:
    int year, month, day;

public:
    CDate(int y, int m, int d); // 构造函数初始化
    bool isLeapYear();          // 判断是否是闰年
    int getYear();              // 返回年份
    int getMonth();
    int getDay();
    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::getYear()
{
    return year;
}

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

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

int CDate::getDayofYear()
{
    int i, sum;
    int a[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    sum = day;

    if (isLeapYear()) // 如果是闰年
    {
        a[2]++; // 有29号
    }
    // 求日期的天数
    for (i = 0; i < month; i++)
    {
        sum += a[i];
    }
    return sum;
}

class Soft
{
private:
    char *name; // 软件名称
    char type;  // 软件类型
    CDate dd;
    char media; // 存储介质
public:
    Soft(const Soft &s1);                   // 软件拷贝
    Soft(char *m, char n, char p, CDate d); // 构造初始化
    void print();                           // 打印
    ~Soft();                                // 析构函数释放内存
};

Soft::Soft(const Soft &s1) // 拷贝构造函数
    : dd(s1.dd)            // 初始化
{
    int len = strlen(s1.name);
    name = new char[len + 1];
    strncpy(name, s1.name, len);
    type = 'B';
    media = 'H';
    name[len] = '\0';
}

Soft::Soft(char *m, char n, char p, CDate d) // 构造
    : dd(d)
{
    int len = strlen(m);
    name = new char[len + 1];
    strncpy(name, m, len);
    type = n;
    media = p;
    name[len] = '\0';
}

void Soft::print()
{
    int t, x, i, sum, n;
    t = 0; // 未过期

    cout << "name:" << name << endl;
    if (type == 'O')
    {
        cout << "type:original" << endl;
    }
    else if (type == 'B')
    {
        cout << "type:backup" << endl;
    }
    else if (type == 'T')
    {
        cout << "type:trial" << endl;
    }

    if (media == 'D')
    {
        cout << "media:optical disk" << endl;
    }
    else if (media == 'U')
    {
        cout << "media:USB disk" << endl;
    }
    else if (media == 'H')
    {
        cout << "media:hard disk" << endl;
    }

    if (dd.getYear() == 0 && dd.getMonth() == 0 && dd.getDay() == 0)
    {
        t = 2; // 无日期
    }
    else if (dd.getYear() < 2015 || (dd.getYear() == 2015 && dd.getMonth() < 4) || (dd.getYear() == 2015 && dd.getMonth() == 4 && dd.getDay() < 7))
    {
        t = 1; // 过期
    }
    if (t == 2) // 无日期
    {
        cout << "this software has unlimited use" << endl;
    }
    else if (t == 1) // 过期
    {
        cout << "this software has expired" << endl;
    }
    else
    {
        sum = 0; // 总的天数
        if (dd.getYear() > 2015)
        {
            x = dd.getYear() - 2015; // 和15年的差值
            for (i = 1; i < x; i++)
            {
                n = 2015 + i;
                CDate d1(n, dd.getMonth(), dd.getDay());
                if (d1.isLeapYear()) // 如果是闰年
                {
                    sum += 366;
                }
                else // 平年
                {
                    sum += 365;
                }
            }
            sum += dd.getDayofYear();
            cout << "this software is going to be expired in " << sum + 268 << " days" << endl;
        }
        else
        {
            sum = dd.getDayofYear();
            cout << "this software is going to be expired in " << sum - 97 << " days" << endl;
        }
    }
    cout << endl;
}

Soft::~Soft()
{
    delete[] name;
}

int main()
{
    int t, i, yy, mm, dd;
    char *na, ty, me, ch;
    cin >> t; // 组数
    ch = getchar();
    na = new char[31];

    for (i = 0; i < t; i++)
    {
        cin >> na >> ty >> me >> yy >> mm >> dd;
        CDate d(yy, mm, dd);   // 初始化日期
        Soft s(na, ty, me, d); // 初始化软件的属性
        s.print();
        Soft s1(s); // 拷贝构造
        s1.print();
    }
    delete[] na;

    return 0;
}

id:53 E.手机服务(构造+拷贝构造+堆)

题目描述

设计一个类来实现手机的功能。它包含私有属性:号码类型、号码、号码状态、停机日期;包含方法:构造、拷贝构造、打印、停机。

  1. 号码类型表示用户类别,只用单个字母,A表示机构,B表示企业、C表示个人
  2. 号码是11位整数,用一个字符串表示
  3. 号码状态用一个数字表示,1、2、3分别表示在用、未用、停用
  4. 停机日期是一个日期对象指针,在初始化时该成员指向空,该日期类包含私有属性年月日,以及构造函数和打印函数等

  1. 构造函数的作用就是接受外来参数,并设置各个属性值,并输出提示信息,看示例输出

  2. 拷贝构造的作用是复制已有对象的信息,并输出提示信息,看示例输出。
    想一下停机日期该如何复制,没有停机如何复制??已经停机又如何复制??

  3. 打印功能是把对象的所有属性都输出,输出格式看示例

  4. 停机功能是停用当前号码,参数是停机日期,无返回值,操作是把状态改成停用,并停机日期指针创建为动态对象,并根据参数来设置停机日期,最后输出提示信息,看示例输出


要求:在主函数中实现号码备份的功能,对已有的虚拟手机号的所有信息进行复制,并将号码类型改成D表示备份;将手机号码末尾加字母X

输入

第一行输入t表示有t个号码

第二行输入6个参数,包括号码类型、号码、状态、停机的年、月、日,用空格隔开

依次输入t行

输出

每个示例输出三行,依次输出原号码信息、备份号码信息和原号码停机后的信息

每个示例之间用短划线(四个)分割开,看示例输出

输入样例1

2
A 15712345678 1 2023 1 1
B 13287654321 2 2012 12 12

输出样例1

Construct a new phone 15712345678
类型=机构||号码=15712345678||State=在用
Construct a copy of phone 15712345678
类型=备份||号码=15712345678X||State=在用
Stop the phone 15712345678
类型=机构||号码=15712345678||State=停用||停机日期=2023.1.1
----
Construct a new phone 13287654321
类型=企业||号码=13287654321||State=未用
Construct a copy of phone 13287654321
类型=备份||号码=13287654321X||State=未用
Stop the phone 13287654321
类型=企业||号码=13287654321||State=停用||停机日期=2012.12.12
----

输入样例2

1
C 15674561389 3 2020 1 2

输出样例2

Construct a new phone 15674561389
类型=个人||号码=15674561389||State=停用
Construct a copy of phone 15674561389
类型=备份||号码=15674561389X||State=停用
Stop the phone 15674561389
类型=个人||号码=15674561389||State=停用||停机日期=2020.1.2
----

题解

  • Date类:有三个私有变量,分别是年月日;两个公有函数,一个是构造函数,作用是给变量初始化,赋予参数的值,还有一个是打印函数,作用是打印出停机日期
  • Phone类:定义三个私有变量,一个是char型的号码类型,一个是字符指针号码,一个是整数型的号码状态,还有一个是Date型的指针表示停机日期;五个公有的函数,一个是构造函数,用于初始化四个变量的值,一个是拷贝构造函数,一个是打印函数,一个是析构函数,还有一个是用于处理停机的函数
  • 下面来分别分析各个公有的函数,Phone(char t, char *n, int s, Date *d); // 构造,构造函数,用于将参数的值传入四个私有变量中,参数的类型与四个私有变量的类型应该要一致,在这个函数中,因为号码类型是字符型,所以我们可以直接使用赋值号“=”来对号码类型赋值;由于号码的类型是字符指针型,所以我们不能使用赋值号对其进行赋值,因为在析构函数中可能会重复释放相同的一片内存,造成程序崩溃,所以我们可以使用strncpy函数,其中,为这个变量开辟的空间大小要比需要复制给他的变量的字节数加一,这是因为多出来的一个字节用来存放字符串结束符\0,计算参数的变量我们可以使用strlen函数,使用这两个函数我们需要调用头文件cstring;号码状态是整数型,可以直接使用赋值号来进行复制;因为停机日期是Date类型的指针,如果我们也使用:day(d)来对day进行赋值的话,这个day也会和被赋值的day指向同一片内存空间,在析构函数中也会被重复释放,所以我们使用day = new Date(*d); // 创建新的Date对象这种方法来对day进行赋值,这行代码的含义是创建一个新的 Date 对象,并将指针 d 所指向的 Date 对象的内容(即 *d)作为参数传递给构造函数。在这行代码中,假设 d 是一个指向 Date 对象的指针,*d 则是解引用操作符,表示获取指针 d 所指向的 Date 对象的值。所以,这行代码的作用是利用指针 d 所指向的 Date 对象的值来初始化一个新的 Date 对象,这样就创建了一个新的 Date 对象,其内容与原始对象相同。
  • Phone(const Phone &p1); // 拷贝构造,拷贝构造函数,看输出样例可知,我们需要额外的创建一个变量,将第一次用Phone类型创建的变量赋值到这个新的创建的变量中,然后要改变这个新的创建的变量的号码类型,变为“备份”;然后同样的方法赋值号码,但有所区别的是,这次我们为num开辟的空间要比被拷贝的变量的字节多两个,一个用来存储末尾的X,一个用来存储字符串结束符;同样的方法赋值号码状态和停机日期
  • 在打印函数中,看输出样例,每个不同的类型的处理的第一行输出都不相同,在打印函数中难以做到条件判断,所以每个类型的第一行输出我们把它放在主函数中输出,然后我们可以在打印函数中处理中间的输出;首先判断号码类型,不同的类型输出不同的中文,然后输出号码状态,由于最后一个打印的停机类型的第一行输出又有所特殊,在主函数中不能直接调用停机日期,所以我们考虑在停机函数中输出第一行,然后最后要输出的停机日期中文也在主函数中输出,日期就调用Date类型的输出函数即可
  • 在析构函数中我们需要释放两个变量的内存,一个是num,一个是day
  • 在停机函数中,我们需要将号码状态改为停机,然后输出最后一个停机的第一行输出
  • 在主函数中,我们先输入有多少个号码,然后处理最后一个回车符,因为后一个是一个字符型输入;号码也是定义为字符型指针,动态创建内存,记得最后释放;最后就是输入和一些初始化和输出

遇到的问题

  • 不知道停机函数如何实现,拷贝函数在数组末尾加X
  • 使用:day(d)初始化,导致后面的析构函数重复释放内存
  • 忘记在字符串末尾添加结束符
  • 输出函数过于混乱

代码实现

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

class Date
{
private:
    int year;
    int month;
    int day;

public:
    Date(int y, int m, int d); // 构造函数
    void print();              // 打印函数
};

Date::Date(int y, int m, int d) // 构造初始化
{
    year = y;
    month = m;
    day = d;
}

void Date::print()
{
    cout << year << "." << month << "." << day << endl;;
}

class Phone
{
private:
    char type; // 号码类型
    char *num; // 号码
    int state; // 号码状态
    Date *day; // 停机日期
public:
    Phone(char t, char *n, int s, Date *d); // 构造
    Phone(const Phone &p1);                 // 拷贝构造
    void print();                           // 打印
    ~Phone();                               // 析构释放内存
    void stop(Date* d);                     // 停机
};

Phone::Phone(char t, char *n, int s, Date *d) // 初始化
{
    type = t;
    int len = strlen(n);
    num = new char[len + 1]; // 额外的空间用于添加'X'
    strncpy(num, n, len);
    num[len] = '\0';
    state = s;
    day = new Date(*d); // 创建新的Date对象
}

Phone::Phone(const Phone &p1)
{
    type = 'D'; // 表示备份
    int len = strlen(p1.num);
    num = new char[len + 2];
    strncpy(num, p1.num, len);
    num[len] = 'X';
    num[len + 1] = '\0';
    state = p1.state;
    day = new Date(*(p1.day));
}

void Phone::print()
{
    if (type == 'A') // 输出类型
    {
        cout << "类型=机构||号码";
    }
    else if (type == 'B')
    {
        cout << "类型=企业||号码";
    }
    else if (type == 'C')
    {
        cout << "类型=个人||号码";
    }
    else
    {
        cout << "类型=备份||号码";
    }
    cout << "=" << num << "||State=";

    if (state == 1) // 输出号码状态
    {
        cout << "在用";
    }
    else if (state == 2)
    {
        cout << "未用";
    }
    else
    {
        cout << "停用";
    }
}

Phone::~Phone()
{
    delete[] num; // 释放动态分配的内存
    delete day;
}

void Phone::stop(Date* d)
{
    state = 3; // 号码状态改为停机
    cout << "Stop the phone " << num << endl;
}

int main()
{
    int t, i, st, yy, mm, dd;
    char ty, ch, *num;
    cin >> t; // t个号码
    ch = getchar();
    num = new char[12];

    for (i = 0; i < t; i++)
    {
        cin >> ty >> num >> st >> yy >> mm >> dd;
        Date d1(yy, mm, dd);       // 日期初始化
        Phone p1(ty, num, st, &d1); // 手机初始化

        cout << "Construct a new phone " << num << endl; // 输出号码
        p1.print();                // 打印

        Phone p2(p1);              // 拷贝
        cout << endl << "Construct a copy of phone " << num << endl; // 备份
        p2.print();
        cout << endl;
		
        p1.stop(&d1); // 停机
		p1.print();
        cout << "||停机日期=";
        d1.print();
        cout << "----" << endl;
    }
    delete[] num;

    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1621156.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

视频教程下载:用ChatGPT的 API 开发AI应用指南

通过这门关于 OpenAI API 和 ChatGPT API 的全面课程&#xff0c;在您的应用中释放人工智能的力量。随着人工智能技术的快速发展&#xff0c;比以往任何时候都更重要的是保持领先地位&#xff0c;并为您的项目利用这些尖端工具。在本课程中&#xff0c;您将深入了解人工智能驱动…

汇智知了堂晨会聚焦:NAS应用如何赋能网络安全实战

在近期汇智知了堂网络安全75班的晨会上&#xff0c;一场关于NAS应用的深入分享完美展开。学员们以饱满的热情投入到这场安全讨论中&#xff0c;共同探索网络安全的新天地。 此次分享会聚焦于NAS的应用&#xff0c;旨在帮助学员们更好地了解NAS的定义与功能&#xff0c;掌握其在…

带头双向循环链表的基本操作(c语言实现)

带头双向循环链表 带头双向循环链表是一种结合了双向链表和循环链表特性的数据结构。其主要特点如下&#xff1a; 双向性&#xff1a;链表中的每个节点都有两个指针&#xff0c;一个指向下一个节点&#xff08;next&#xff09;&#xff0c;另一个指向前一个节点&#xff08;p…

idea中打印日志不会乱码,但是部署到外部tomcat中乱码了。

问题&#xff1a;如图Tomcat乱码&#xff0c;而且启动时的系统日志不会乱码&#xff0c;webapp中的打印日志才乱码。 idea中的情况如下&#xff1a;正常中文展示。 问题分析&#xff1a;网上分析的原因是Tomcat配置的字符集和web应用的字符集不匹配&#xff0c;网上集中的解决…

分类预测 | Matlab实现CNN-BiLSTM-SAM-Attention卷积双向长短期记忆神经网络融合空间注意力机制的数据分类预测

分类预测 | Matlab实现CNN-BiLSTM-SAM-Attention卷积双向长短期记忆神经网络融合空间注意力机制的数据分类预测 目录 分类预测 | Matlab实现CNN-BiLSTM-SAM-Attention卷积双向长短期记忆神经网络融合空间注意力机制的数据分类预测分类效果基本描述程序设计参考资料 分类效果 基…

李廉洋:4.24-4.25现货黄金,WTI原油区间震荡,走势分析。

黄金消息面分析&#xff1a;金银近日回调。随着伊朗方面淡化以色列最新反击&#xff0c;中东地区局势没有进一步发酵下&#xff0c;风险溢价下降金银出现较大幅度调整。由于近期高于预期的通胀数据&#xff0c;降息预期持续降温。昨日疲软的美国PMI以及以色列在加沙攻击的加剧支…

数据结构系列-堆排序当中的T-TOK问题

&#x1f308;个人主页&#xff1a;羽晨同学 &#x1f4ab;个人格言:“成为自己未来的主人~” 之前我们讲到了堆排序的实现逻辑&#xff0c;那么接下来我们重点关注的就是其中的T-TOK问题 T-TOK说简单点&#xff0c;就是说&#xff0c;假如有10000个数据&#xff08;随机的…

记录一个hive中跑insert语句说没创建spark客户端的问题

【背景说明】 我目前搭建离线数仓&#xff0c;并将hive的执行引擎改成了Spark&#xff0c;在将ods层的数据装载到dim层&#xff0c;执行insert语句时报如下错误 【报错】 [42000][40000] Error while compiling statement: FAILED: SemanticException Failed to get a spark…

【C++】vector常用函数总结及其模拟实现

目录 一、vector简介 二、vector的构造 三、vector的大小和容量 四、vector的访问 五、vector的插入 六、vector的删除 简单模拟实现 一、vector简介 vector容器&#xff0c;直译为向量&#xff0c;实践中我们可以称呼它为变长数组。 使用时需添加头文件#include<v…

HFSS端口介绍1---集总端口

HFSS中可以设定多种激励端口,但在射频和SI领域使用集总端口(Lumped Port)和波端口(Wave Port)比较多,今天我们主要介绍集总端口。下面是HFSS仿真流程和端口设定说明。 端口定义 端口在电磁仿真中非常重要,它提供3维电磁场求解时的激励,进而求解S参数等信息,这相当于我们平…

网工内推 | 深圳网工专场,上市公司、国企,安全认证优先

01 深圳市同为数码科技股份有限公司武汉分公司 招聘岗位&#xff1a;网络工程师 职责描述&#xff1a; 1、负责网络设备的管理、调试、配置、维护等&#xff1b; 2、负责信息安全网络安全设备、系统的运维&#xff1b; 3、负责整体网络系统技术的相关工作&#xff0c;包括架构…

AI+BI第二弹:QuickBI已支持智能搭建智能问数

缘起&#xff1a;一场主题分享 吴恩达&#xff08;Andrew Ng&#xff09;教授&#xff0c;DeepLearning.AI和AI Fund的创始人&#xff0c;在美国红杉资本于2024年3月26日举办的AI Ascent活动中&#xff0c;谈到了人工智能代理工作流程的未来及其潜力&#xff0c;这些工作流程有…

面向对象三大特征(python)

目录 1. 封装 为什么使用封装&#xff1f; 如何实现封装&#xff1f; 一个简单的封装示例 二.继承 为什么使用继承&#xff1f; 如何实现继承&#xff1f; 一个简单的继承示例 使用继承的好处 三.多态 为什么使用多态&#xff1f; 如何实现多态&#xff1f; 一个简…

【已解决】电脑设置notepad++默认打开txt

1、以管理员的方式打开notepad 步骤&#xff1a;打开设置 -> 首选项 -> 文件关联 2、 设置Notepad默认打开 按照以下步骤将Notepad设置为默认打开.txt文件&#xff1a; 右键单击任何一个.txt文件。选择“属性”。在“常规”选项卡中&#xff0c;找到“打开方式”&#…

Windows SMBGhost CVE-2020-0796 Elevate Privileges

SMBGhost CVE-2020-0796 Microsoft Windows 10 (1903/1909) - ‘SMBGhost’ SMB3.1.1 ‘SMB2_COMPRESSION_CAPABILITIES’ Local Privilege Escalation https://www.exploit-db.com/exploits/48267 Github https://github.com/danigargu/CVE-2020-0796 修改载荷[可选] 生成 c# …

删除链表的倒数第n个节点的最优算法实现

给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点。 提示&#xff1a; 链表中结点的数目为 sz 1 < sz < 300 < Node.val < 1001 < n < sz 你能尝试使用一趟扫描实现吗&#xff1f; 具体实现 要删除链表的倒数第 n 个…

Linux动态追踪——eBPF

目录 摘要 1 什么是 eBPF 2 eBPF 支持的功能 3 BCC 4 编写脚本 5 总结 6 附 摘要 ftrace 和 perf 与 ebpf 同为 linux 内核提供的动态追踪工具&#xff0c;其中 ftrace 侧重于事件跟踪和内核行为的实时分析&#xff0c;perf 更侧重于性能分析和事件统计&#xff0c;与…

Json-server 模拟后端接口

json-server&#xff0c;模拟rest接口&#xff0c;自动生成增删改查接口。(官网地址&#xff1a;json-server - npm) 使用方法&#xff1a; 1. 安装json-server&#xff0c;npm i json-server -g 2. 创建json文件&#xff0c;文件中存储list数据&#xff0c;db.json {"…

路由器本地docker 下载node容器部署 thressjs文档

1. 每次启动本地文档太麻烦 &#xff0c;路由器刚好支持docker&#xff08;tp-link6088&#xff09; &#xff0c;部署上去自启动 2.

简述MASM宏汇编

Hello , 我是小恒不会java。今天写写x86相关底层的东西 寄存器 8086由BIU和EU组成 8088/8086寄存器有14个。8通用&#xff0c;4段&#xff0c;1指针&#xff0c;1标志 8个通用寄存器&#xff1a;这些寄存器可以用来存储任意类型的数据&#xff0c;包括整数、地址等。8086有8个…