问题一:电话号码升位
题目描述:
定义一个电话号码类CTelNumber,包含1个字符指针数据成员,以及构造、析构、打印及拷贝构造函数。
字符指针是用于动态创建一个字符数组,然后保存外来输入的电话号码
构造函数的功能是为对象设置键盘输入的7位电话号码,
拷贝构造函数的功能是用原来7位号码的对象升位为8位号码对象,也就是说拷贝构造的对象是源对象的升级.电话升位的规则是原2、3、4开头的电话号码前面加8,原5、6、7、8开头的前面加2。
注意:合法的电话号码:1、长度为7位;2、电话号码的字符全部是数字字符;3、第一个字符只能是以下字符:2、3、4、5、6、7、8。与上述情况不符的输入均为非法
输入要求:
测试数据的组数 t
第一个7位号码
第二个7位号码
......
输出要求:
第一个号码升位后的号码
第二个号码升位后的号码
......
如果号码升级不成功,则输出报错信息,具体看示例
输入样例:
3
6545889
3335656
565655
输出样例:
26545889
83335656
Illegal phone number
问题思路:
先把原号码存到CTelNumber中,利用拷贝构造函数,在新的CTelNumber中进行升位。
#include
#include
#include
#include
#include
#include
using namespace std;
class CTelNumber
{
public:
CTelNumber(char num[]);
CTelNumber(const CTelNumber& rhs);
~CTelNumber();
void Print();
private:
char* Tel;
};
CTelNumber::CTelNumber(char num[])
{
Tel = new char[8];//建立动态堆内存
for (int i = 0; i < 8; i++)
{
Tel[i] = num[i];
}
}
CTelNumber::CTelNumber(const CTelNumber& rhs)
{
Tel = new char[9];
if (rhs.Tel[0] == '2' || rhs.Tel[0] == '3' || rhs.Tel[0] == '4')//按照对应的规则对号码进行升位
{
Tel[0] = '8';
for (int i = 0; i < 8; i++)
{
Tel[i + 1] = rhs.Tel[i];
}
}
else if (rhs.Tel[0] == '5' || rhs.Tel[0] == '6' || rhs.Tel[0] == '7' || rhs.Tel[0] == '8')
{
Tel[0] = '2';
for (int i = 0; i < 8; i++)
{
Tel[i + 1] = rhs.Tel[i];
}
}
}
void CTelNumber::Print()
{
cout << Tel << endl;
}
CTelNumber::~CTelNumber()
{
}
bool isright(char telnum[])
{
if (strlen(telnum) != 7)//号码是7位
{
return false;
}
else if (telnum[0] != '2' && telnum[0] != '3' && telnum[0] != '4' && telnum[0] != '5' && telnum[0] != '6' && telnum[0] != '7' && telnum[0] != '8')//第一位不能为1或9
{
return false;
}
else//不能有非法符号
{
for (int i = 0; i < 7; i++)
{
if (telnum[i] > '9' || telnum[i] < '0')
{
return false;
}
}
return true;
}
}
int main() {
int t;
cin >> t;
while (t--)
{
char num[8];
cin >> num;
if (isright(num))//isright判断是否是正确的电话号码
{
CTelNumber tl(num);//基本带参构造
CTelNumber tl2(tl);//拷贝构造传引用对电话号码进行升位
tl2.Print();//打印升位后的号码
}
else
{
cout << "Illegal phone number" << endl;
}
}
return 0;
}
问题二:身份证号码升位
题目描述:
class CDate
{
private:
int year, month, day;
public:
CDate(int,int,int);
bool check(); //检验日期是否合法
bool isLeap();
void print();
};
class CStudentID
{
private:
char *p_id, *p_name; //身份证号码,姓名
CDate birthday; //出生日期
int registered; //登记否
public:
CStudentID(char *p_idval, char *p_nameval, CDate &day); //构造函数,若:日期非法;日期与id日期不符;id有非法字符;id不是15位或18位;id是18位但检验码不对,则输出"illegal id"并置registered=0。否则输出对象的属性并置registered=1.
CStudentID(const CId &r); //拷贝构造函数,若r.p_id为15位则升到18位(加年份的19和校验位)
bool checked() { return registered; }
~CStudentId();
};
按上述方式定义一个日期类CDate和学生ID类CStudentID。
身份证第18位校验码的生成方法:
1、将身份证号码前17位数分别乘以7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2。然后将其相加
2、将17位数字和系数乘加的和除以11,得到余数。
3、余数与校验码的对应关系为1,0,X,9,8,7,6,5,4,3,2。也即:如果余数是3,身份证第18位就是9。如果余数是2,身份证的最后一位号码就是X。
主函数:
//输入测试次数t
//循环t次
//每次循环中首先输入年月日,并定义日期对象
//然后输入姓名和身份证号码,并先用构造函数定义一个CStudentID对象s,若s.checked()为true,则再用s拷贝构造s_copy对象
输入要求:
测试数据的组数 t
第一个出生日期年月日
第一个姓名,身份证号码
第二个出生日期年月日
第二个姓名,身份证号码
......
输出要求:
第一个CStudent对象s的信息
第一个拷贝构造CStudent对象s_copy输出的信息或者无输出
第二个CStudent对象s的信息
第二个拷贝构造CStudent对象s_copy输出的信息或者无输出
......
输入样例:
6
2018 2 29
张三 440301180229113
1997 4 30
李四 440301980808554
1920 5 8
王五 530102200508011
1980 1 1
赵六 340524198001010012
1988 11 12
钱七 1102038811120A4
1964 11 15
孙八 432831641115081
输出样例:
张三 illegal id
李四 illegal id
王五 1920年5月8日 530102200508011
王五 1920年5月8日 53010219200508011X
赵六 illegal id
钱七 illegal id
孙八 1964年11月15日 432831641115081
孙八 1964年11月15日 432831196411150810
问题思路:
首先建立一个CStudentID类判断id是否满足全部条件,若满足则进行拷贝构造函数,从而对身份证号进行升位。
#include
#include
#include
#include
#include
#include
using namespace std;
bool isright(char arr[])//判断18位身份证号是否正确
{
int brr[17], sum;
for (int j = 0; j < 17; j++)
{
brr[j] = arr[j] - '0';
}
sum = 7 * brr[0] + 9 * brr[1] + 10 * brr[2] + 5 * brr[3] + 8 * brr[4] + 4 * brr[5] + 2 * brr[6] + 1 * brr[7] + 6 * brr[8] + 3 * brr[9] + 7 * brr[10] + 9 * brr[11] + 10 * brr[12] + 5 * brr[13] + 8 * brr[14] + 4 * brr[15] + 2 * brr[16];
int r = sum % 11;
char ch;
switch (r)
{
case 0: ch = '1'; break;
case 1: ch = '0'; break;
case 2: ch = 'X'; break;
case 3: ch = '9'; break;
case 4: ch = '8'; break;
case 5: ch = '7'; break;
case 6: ch = '6'; break;
case 7: ch = '5'; break;
case 8: ch = '4'; break;
case 9: ch = '3'; break;
case 10: ch = '2'; break;
}
if (ch == arr[17])
{
return true;
}
else
{
return false;
}
}
bool ismatch(char a[], int yy, int mm, int dd)//检查身份证号码和日期是否相符
{
yy = yy % 100;
int b[15];
for (int i = 0; i < 15; i++)
{
b[i] = a[i] - '0';
}
int idy, idm, idd;
idy = b[6] * 10 + b[7];
idm = b[8] * 10 + b[9];
idd = b[10] * 10 + b[11];
//cout << idy << " " << idm << " " << idd << endl;
//cout << yy << " " << mm << " " << dd << endl;
if (idy == yy && idm == mm && idd == dd)
{
return true;
}
else
{
return false;
}
}
bool islegal(char array[])//判断是否有非法字符
{
for (int i = 0; i < 15; i++)
{
if (array[i] > '9' || array[i] < '0')
{
return false;
}
}
return true;
}
class CDate//定义CDate类来存放生日日期
{
public:
CDate(int ye, int mo, int da);
bool check();
bool isLeap();
void print();
private:
int year, month, day;
};
class CStudentID
{
public:
CStudentID(char* p_idval, char* p_nameval, int ye0, int mo0, int da0);//带参构造
CStudentID(const CStudentID& r);
bool checked() { return registered; }
CDate getBirthday() { return birthday; }
~CStudentID();
private:
char* p_id, * p_name;
CDate birthday;
bool registered;//记已经完成正确修改的id为true
};
CDate::CDate(int ye, int mo, int da)
{
year = ye;
month = mo;
day = da;
}
bool CDate::check()//判断生日是否合法
{
int arr[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 }, brr[13] = { 0,31,29,31,30,31,30,31,31,30,31,30,31 };
if (month < 1 || month > 12)
{
return false;
}
if (isLeap())
{
if (day > brr[month] || day <= 0)
{
return false;
}
}
else
{
if (day > arr[month] || day <= 0)
{
return false;
}
}
return true;
}
bool CDate::isLeap()//判断是否为闰年
{
return (year % 4 == 0 && year % 100) || (year % 400 == 0);
}
void CDate::print()//打印生日
{
cout << year << "年" << month << "月" << day << "日 ";
}
CStudentID::CStudentID(char* p_idval, char* p_nameval, int ye0, int mo0, int da0) :birthday(ye0, mo0, da0)//带参构造
{
p_name = new char[strlen(p_nameval) + 1];
strcpy(p_name, p_nameval);
p_id = new char[strlen(p_idval) + 1];
strcpy(p_id, p_idval);
if (!birthday.check())//判断生日是否正确
{
registered = false;
}
else if (strlen(p_id) != 15 && strlen(p_id) != 18)//判断是否是15位或者18位
{
registered = false;
}
else if (strlen(p_id) == 18)
{
if (isright(p_id))///如果是18位,判断升位是否正确
{
registered = true;
}
else
{
registered = false;
}
}
else if (strlen(p_id) == 15)//如果是15位,判断是否合法,身份证生日是否与生日相符
{
if (islegal(p_id) && ismatch(p_id, ye0, mo0, da0))
{
registered = true;
}
else
{
registered = false;
}
}
}
CStudentID::CStudentID(const CStudentID& r) :birthday(r.birthday)//拷贝构造函数
{
p_name = new char[strlen(r.p_name) + 1];
strcpy(p_name, r.p_name);
p_id = new char[20];
int brr[18];
for (int j = 0; j < 6; j++)
{
brr[j] = r.p_id[j] - '0';
p_id[j] = r.p_id[j];
}
brr[6] = 1;
brr[7] = 9;
p_id[6] = '1';
p_id[7] = '9';
for (int j = 8; j < 17; j++)
{
brr[j] = r.p_id[j - 2] - '0';
p_id[j] = r.p_id[j - 2];
}
int sum = 7 * brr[0] + 9 * brr[1] + 10 * brr[2] + 5 * brr[3] + 8 * brr[4] + 4 * brr[5] + 2 * brr[6] + 1 * brr[7] + 6 * brr[8] + 3 * brr[9] + 7 * brr[10] + 9 * brr[11] + 10 * brr[12] + 5 * brr[13] + 8 * brr[14] + 4 * brr[15] + 2 * brr[16];
int re = sum % 11;
switch (re)//选择循环
{
case 0: p_id[17] = '1'; break;
case 1: p_id[17] = '0'; break;
case 2: p_id[17] = 'X'; break;
case 3: p_id[17] = '9'; break;
case 4: p_id[17] = '8'; break;
case 5: p_id[17] = '7'; break;
case 6: p_id[17] = '6'; break;
case 7: p_id[17] = '5'; break;
case 8: p_id[17] = '4'; break;
case 9: p_id[17] = '3'; break;
case 10: p_id[17] = '2'; break;
}
for (int i = 0; i < 6; i++) p_id[i] = r.p_id[i];
for (int i = 8; i < 17; i++) p_id[i] = r.p_id[i - 2];
p_id[18] = '\0';
cout << p_id << endl;
}
CStudentID::~CStudentID() //析构函数
{
delete[]p_name;
delete[]p_id;
}
int main()
{
int t;
cin >> t;
while (t--)
{
int y0, m0, d0;
cin >> y0 >> m0 >> d0;//输入生日
char name0[10], id0[20];
cin >> name0 >> id0;//输入姓名和原身份证
CStudentID student(id0, name0, y0, m0, d0);//建立ID类
if (student.checked())//check身份证号是否正确
{
cout << name0 << " ";
student.getBirthday().print();//输出生日
cout << id0 << endl;//输出原身份证号
cout << name0 << " ";
student.getBirthday().print();//输出生日
CStudentID student1(student);//拷贝构造
}
else
{
cout << name0 << " illegal id" << endl;//不正确则输出“illegal id”
}
}
return 0;
}
问题三:彩票复制
题目描述:
假设每组彩票包含6个号码,设计一个彩票类lottery,数据成员包括第一组号码、其他组数、其他组号码,描述如下
1、第一组号码group1,整数数组,长度为6
2、其他组数num,表示以第一组号码为样本,创建num组其他号码
3、其他组号码groupn,整数指针(int **),,该数据将动态创建二维整数数组,共9行,每行包含6个号码。
彩票类的成员函数包括:构造函数、拷贝构造函数、打印,描述如下:
1、打印函数,输出彩票的所有组的号码
2、构造函数,两个参数,第一个参数为整数数组,对应第一组号码,第二个参数为整数,表示其他组数(不超过9)。注意在构造函数中,其他组号码groupn不动态分配空间,仍然为指针
3、拷贝构造函数,其他组号码groupn动态创建二维数组,根据其他组数创建其他组的号码,创建规则为:
a)第i组的第j个号码等于上一组第j-1个号码加1,首个号码等于上一组最后一个号码加1
例如第一组号码group1的号码是1、3、5、7、9、11,且其他组数为2
则groupn的第0组号码是12、2、4、6、8、10,第1组号码是11、13、3、5、7、9,以此类推
输入要求:
第一行输入t表示有t个样例,每个样例对应一行数据
接着一行输入7个参数,前6个参数表示首张彩票的第一组6个号码,第7个参数表示其他组数,这时使用使用构造函数
然后采用拷贝构造方法生成第二张彩票,其中复制了首张彩票的第一组号码和其他组数,并且生成其他组号码
依此类推
输出要求:
调用Print方法,输出每个样例中第二张彩票的所有组的号码
输入样例:
2
1 3 5 7 9 11 2
22 44 66 88 100 122 3
输出样例:
1 3 5 7 9 11
12 2 4 6 8 10
11 13 3 5 7 9
22 44 66 88 100 122
123 23 45 67 89 101
102 124 24 46 68 90
91 103 125 25 47 69
#include
#include
#include
#include
#include
#include
using namespace std;
class Lottery
{
public:
Lottery(int arr[], int n0);
Lottery(const Lottery& rhs);
void printGroup1();
void printGroupn();
~Lottery();
private:
int group1[6], num;
int** groupn;
bool iscopy;//标记是否已经被copy,已经被copy的可以析构
};
Lottery::Lottery(int arr[], int n0)//带参构造初始化
{
for (int i = 0; i < 6; i++)
{
group1[i] = arr[i];
}
num = n0;
}
Lottery::Lottery(const Lottery& rhs)//拷贝构造
{
for (int i = 0; i < 6; i++)
{
group1[i] = rhs.group1[i];
}
num = rhs.num;
groupn = new int* [num];
for (int i = 0; i < num; i++)
{
groupn[i] = new int[6];
}
for (int i = 0; i < num; i++)//根据规则进行赋值
{
for (int j = 0; j < 6; j++)
{
if (i == 0)
{
if (j == 0)
{
groupn[i][j] = group1[5] + 1;
}
else
{
groupn[i][j] = group1[j - 1] + 1;
}
}
else
{
if (j == 0)
{
groupn[i][j] = groupn[i - 1][5] + 1;
}
else
{
groupn[i][j] = groupn[i - 1][j - 1] + 1;
}
}
}
}
iscopy = true;
}
void Lottery::printGroup1()//打印原彩票
{
for (int i = 0; i < 6; i++)
{
cout << group1[i];
if (i == 5)
{
cout << endl;
}
else
{
cout << " ";
}
}
}
void Lottery::printGroupn()//打印复制后的彩票
{
for (int i = 0; i < num; i++)
{
for (int j = 0; j < 6; j++)
{
cout << groupn[i][j];
if (j == 5)
{
cout << endl;
}
else
{
cout << " ";
}
}
}
}
Lottery::~Lottery()//析构函数
{
if (iscopy)
{
for (int i = 0; i < num; i++)
{
delete[]groupn[i];
}
delete[]groupn;
}
};
int main()
{
int t;
cin >> t;
while (t--)
{
int number[6], n;
for (int i = 0; i < 6; i++)
{
cin >> number[i];
}
cin >> n;
Lottery l(number, n);//构造彩票类
l.printGroup1();
Lottery lo(l);
lo.printGroupn();
}
return 0;
}
问题四:软件备份
问题描述:
软件作为一种对象也可以用类来描述,软件的属性包括软件名称、类型(分别用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) { year = y; month = m; day = d; }
bool isLeapYear() { return (year%4 == 0 && year%100 != 0) || year%400 == 0; }
int getYear() { return year; }
int getMonth() { return month; }
int getDay() { return day; }
int getDayofYear() //计算日期从当年1月1日算起的天数
{
int i, sum=day;
int a[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
int b[13]={0,31,29,31,30,31,30,31,31,30,31,30,31};
if (isLeapYear()) return sum; 输入要求: 测试数据的组数 t 第一个软件名称 第一个软件类型 第一个软件介质类型 第一个软件有效期年 月 日 第二个软件名称 第二个软件类型 第二个软件介质类型 第二个软件有效期年 月 日 ...... 输出要求: name: 第一个软件名称 type: 第一个软件类型 media: 第一个软件介质类型 第一个软件2015-4-7后的有效天数 name: 第一个软件名称 type: backup media: hard disk 第一个软件2015-4-7后的有效天数 ...... 输入样例: 输出样例: 问题五:手机服务 问题描述: 设计一个类来实现手机的功能。它包含私有属性:号码类型、号码、号码状态、停机日期;包含方法:构造、拷贝构造、打印、停机。 1、号码类型表示用户类别,只用单个字母,A表示机构,B表示企业、C表示个人 2、号码是11位整数,用一个字符串表示 3、号码状态用一个数字表示,1、2、3分别表示在用、未用、停用 4、停机日期是一个日期对象指针,在初始化时该成员指向空,该日期类包含私有属性年月日,以及构造函数和打印函数等 ---------------------------------------- 5、构造函数的作用就是接受外来参数,并设置各个属性值,并输出提示信息,看示例输出 6、拷贝构造的作用是复制已有对象的信息,并输出提示信息,看示例输出。 想一下停机日期该如何复制,没有停机如何复制??已经停机又如何复制?? 7、打印功能是把对象的所有属性都输出,输出格式看示例 8、停机功能是停用当前号码,参数是停机日期,无返回值,操作是把状态改成停用,并停机日期指针创建为动态对象,并根据参数来设置停机日期,最后输出提示信息,看示例输出 ------------------------------------------- 要求:在主函数中实现号码备份的功能,对已有的虚拟手机号的所有信息进行复制,并将号码类型改成D表示备份;将手机号码末尾加字母X 输入要求: 第一行输入t表示有t个号码 第二行输入6个参数,包括号码类型、号码、状态、停机的年、月、日,用空格隔开 依次输入t行 输出要求: 每个示例输出三行,依次输出原号码信息、备份号码信息和原号码停机后的信息 每个示例之间用短划线(四个)分割开,看示例输出 输入样例: 输出样例:
for(i=0;i
for(i=0;i
}
};3
Photoshop_CS5
O D 0 0 0
Audition_3.0
B U 2015 2 3
Visual_Studio_2010
T H 2015 5 5
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
#include
2
A 15712345678 1 2015 1 1
B 13287654321 2 2012 12 12
Construct a new phone 15712345678
类型=机构||号码=15712345678||State=在用
Construct a copy of phone 15712345678
类型=备份||号码=15712345678X||State=在用
Stop the phone 15712345678
类型=机构||号码=15712345678||State=停用 ||停机日期=2015.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
----
#include