C++_第八周做题总结

news/2025/3/26 4:04: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: backupmedia: 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.ppmy.cn/news/1435335.html

相关文章

rysnc 通过文件输入密码的设置方法

在使用 rsync 进行文件同步时&#xff0c;你可以通过一个文件输入密码来避免在命令行中显示或手动输入密码。这在自动化脚本中特别有用。下面是详细的步骤和方法&#xff1a; 创建密码文件 创建一个包含密码的文件&#xff1a; 打开一个文本编辑器&#xff0c;输入远程服务器的…

排列对称串

Description:很多字串&#xff0c;有些是对称的&#xff0c;有些是不对称的&#xff0c;请将那些对称的字事按从小到大的顺序输出&#xff0c;字事先以长度论大小&#xff0c;如果长度相同&#xff0c;再以ASCI码值为大小标准 Input.输入数据中含有一些字串(1≤串长≤256)。 #…

Android Binder——数据传输限制(二十三)

在前面的学习中,我们了解到在创建用户和内核的虚拟空间的时候,会开辟 1M-8K 的内存空间,用于当前进程与 Binder 驱动进行传递数据,但是在实际传输过程中,其实并不能达到1M-8k的数据。这里我们就来分析一下 Binder 通信数据传输的限制。 一、Linux系统启动 Linux 系统在启…

数据结构系列-堆排序

&#x1f308;个人主页&#xff1a;羽晨同学 &#x1f4ab;个人格言:“成为自己未来的主人~” 今天我们开始讲解一下堆排序和T-TOK问题&#xff0c;这个也是堆排序相对于qsort排序和冒泡排序来说最大的竞争力&#xff0c;首先我们回顾一下之前我们学过的qsort排序和冒泡排序…

Windows系统中下Oracle 19C数据库超级详细安装、设置教程(自己电脑上安装Oracle学习,保姆级教学,亲测有效)

Oracle 官方提供了一个基于 Java 技术的图形界面安装工具&#xff1a;Oracle Universal Installer&#xff08;Oracle 通用安装器&#xff09;简称 OUI&#xff0c;利用它可以完成在不同操作系统平台上&#xff08;Windows、Linux、UNIX&#xff09;的、不同类型的、不同版本的…

Xilinx 7系列MMCM/PLL的使用模型

本文展示了MMCM的一些使用模型&#xff08;同样适用于PLL&#xff09;&#xff0c;如时钟网络去偏斜、具有内部反馈的MMCM和零延迟缓冲区等。 1、时钟网络去偏斜&#xff08;Clock Network Deskew&#xff09; MMCM的主要用途之一是用于时钟网络去偏斜。图3-11和图3-12展示了…

【Linux 开发第一篇】如何在安装中完成自定义配置分区

安装配置自定义配置分区 在安装Centos的过程中&#xff0c;我们可以在安装位置部分手动配置分区 选择我要配置分区&#xff0c;点击完成&#xff1a; 我们自动分区分为三个分区&#xff1a;boot分区&#xff08;引导分区&#xff09;&#xff0c;swap&#xff08;交换分区&…

在ubuntu上搭建nexus私有仓库(指定版本以及jdk!)

前言 本来以为搭建一个nexus随随便便就好了&#xff0c;但是遇到了最新版本根本没办法在jdk17下面正常运行—起码我调了一下不知道怎么运行&#xff0c;我才知道。。。不升级版本其实是很有道理的。 这一篇是最新版本的尝试&#xff1a; 在ubuntu上搭建nexus私有仓库[失败草稿…