厦大计算机系C++程序设计实验(二)
1 实验目的
熟悉C++中类与对象的相关关系,掌握如何定义一个类,如何使用构造函数初始化一个类,并了解公有成员、私有成员之间的区别。
2 实验内容
(1)定义一个满足如下要求的Date类和对象。
①其数据成员包括day、month、year;
②可设置日期;
③用下面的格式输出日期:日/月/年;
④可运行在日期上加一天操作;
⑤可判断是否是闰年
⑥定义Date对象,设置时间,输出该对象提供的时间。
(2)定义一个学生类:
①其数据成员为:姓名、学号、总学分、平均成绩;
②其成员函数有:
a. 构造函数:能对学生类的姓名和学号进行初始化,同时应默认将学生类中的学分和平均成绩初始化为0。
b. Show函数: 显示该学生总学分和平均成绩。
定义一个班级类:
①其数据成员为:学生总数,学生信息;
②其成员函数有:
a. 构造函数;
b. 显示所有学生信息;
c. 根据学生查找指定学生信息;
d. 增加学生信息;
e. 为学生添加成绩和学分,并适时修改平均成绩。
定义一个班级类对象和若干个学生类对象,进行初始化操作、把学生对象添加进班级,并尝试为学生添加成绩和学分信息。
3 实验步骤
(1)Date类与对象
将年、月、日作为私有成员予以保护。setDate()用来设置具体日期,缺省值为1970年1月1日。plusOneDay()用来将日期加一,但是特别考虑了需要对月份、年份进位加一的情形。isLeap()则用来判断现在的年份是不是闰年。源代码如下:
#include <iostream>
using namespace std;
int daysOfEachMonth[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
class Date
{
public:
void setDate(int new_date = 1, int new_month = 1, int new_year = 1970);
void showDate();
void plusOneDay();
bool isLeap();
int getYear() { return year; }
private:
int date, month, year;
};
void Date::setDate(int new_date, int new_month, int new_year)
{
date = new_date;
month = new_month;
year = new_year;
if( year < 0 || month < 0 || month > 12 )
{
year = 1970;
month = 1;
date = 1;
}
else if( (year % 4 == 0 && year % 100 != 4) || (year % 400 == 0) )
{
if((month == 2 && date > daysOfEachMonth[month] + 1) || ( month != 2 && date > daysOfEachMonth[month]))
{
year = 1970;
month = 1;
date = 1;
}
}
else if(date > daysOfEachMonth[month])
{
year = 1970;
month = 1;
date = 1;
}
}
inline void Date::showDate()
{
cout << date << "/" << month << "/" << year << endl;
}
void Date::plusOneDay()
{
if(isLeap() == true)
{
if(month == 2)
{
if(date == daysOfEachMonth[month] + 1)
{
month = 3;
date = 1;
}
else
++date;
}
else
{
if(date == daysOfEachMonth[month])
{
if(month == 12)
{
++year;
month = 1;
date = 1;
}
else
{
++month;
date = 1;
}
}
else
++date;
}
}
else
{
if(date == daysOfEachMonth[month])
{
if(month == 12)
{
++year;
month = 1;
date = 1;
}
else
{
++month;
date = 1;
}
}
else
++date;
}
}
bool Date::isLeap()
{
if( (year % 4 == 0 && year % 100 != 0) || year % 400 == 0 )
return true;
else
return false;
}
int main()
{
Date d;
int day, month, year;
cout << "Please input date(day month year):";
cin >> day >> month >> year;
d.setDate(day, month, year);
d.showDate();
d.plusOneDay();
d.showDate();
if(d.isLeap() == true)
cout << d.getYear() << " is leap year" << endl;
else
cout << d.getYear() << " is not leap year" << endl;
return 0;
}
(2)学生类、班级类的实现
首先定义学生类。在学生类中,构造函数Student用来初始化学生类,其中学分、平均分都默认为0。函数show用来显示学分和平均分。之后的公有成员都是用来获取和存储私有成员的函数。
在班级类中,函数showStudentMessage用来显示所有学生的信息;Find用来查找指定学号的学生并予以显示;addStudent用来添加学生信息;fillMessage则用来填充指定学号学生的学分和平均分。
源代码如下:
#include <iostream>
using namespace std;
const int NUM_STU = 5;
class Student
{
public:
Student(string stu_name, long long stu_no, int stu_credits = 0, double stu_average = 0);
void show();
string getName(){ return name; }
void setName(string stu_name){ name = stu_name; }
long long getNo(){ return no; }
void setNo(long long stu_no){ no = stu_no; }
int getCredits(){ return totalCredits; }
void setCredits(int stu_credits){ totalCredits = stu_credits; }
double getAverage(){ return averageScore; }
void setAverage(double stu_average){ averageScore = stu_average; }
private:
string name;
long long no;
int totalCredits;
double averageScore;
};
Student::Student(string stu_name, long long stu_no, int stu_credits, double stu_average)
{
name = stu_name;
no = stu_no;
totalCredits = stu_credits;
averageScore = stu_average;
}
void Student::show()
{
cout << name << ": " << endl;
cout << " Total Credits: " << totalCredits <<endl;
cout << " Average Score: " << averageScore <<endl;
}
class Class
{
public:
Class();
void showStudentMessage();
void Find(long long stu_no);//find student by his NO.
void addStudent(string stu_name, long long stu_no, int stu_credits, double stu_average);
void fillMessage(long long no, int totalCredits, double averageScore);//fill message for the student with No.
private:
int numbers;
Student *stu[NUM_STU];
};
Class::Class()
{
numbers = 0;
for(int i = 0;i < NUM_STU;++i)
{
stu[i] = new Student("", 0);
}
}
void Class::showStudentMessage()
{
cout << "All message in this class: " << endl;
for(int i = 0;i < numbers;++i)
{
stu[i]->show();
}
}
void Class::Find(long long stu_no)
{
bool isFind = false;
for(int i = 0;i < numbers;++i)
{
if(stu[i]->getNo() == stu_no)
{
cout << "Successful to find!" << endl;
stu[i]->show();
isFind = true;
break;
}
}
if(isFind == false)
{
cout << "Fail to find!" << endl;
}
}
void Class::addStudent(string stu_name, long long stu_no, int stu_credits, double stu_average)
{
if(numbers < NUM_STU)
{
bool canInsert = true;
for(int i = 0;i < numbers;++i)
{
if( stu[i]->getNo() == stu_no )
{
canInsert = false;
break;
}
}
if(canInsert == true)
{
stu[numbers]->setName(stu_name);
stu[numbers]->setNo(stu_no);
stu[numbers]->setCredits(stu_credits);
stu[numbers]->setAverage(stu_average);
++numbers;
}
}
}
void Class::fillMessage(long long no, int totalCredits, double averageScore)
{
bool isFind = false;
for(int i = 0;i < numbers;++i)
{
if(stu[i]->getNo() == no)
{
stu[i]->setCredits(totalCredits);
stu[i]->setAverage(averageScore);
isFind = true;
break;
}
}
if(isFind == false)
cout << "Fail to find!" << endl;
}
int main()
{
Class c;
int number;
string name;
long long no;
int credits;
double average;
cout << "input the number of students:";
cin >> number;
cout << "input students' message:" << endl;
for(int i = 1;i <= number;++i)
{
cin >> name >> no >> credits >> average;
c.addStudent(name,no,credits,average);
}
c.showStudentMessage();
cout << "student you want to find, his no:";
cin >> no;
c.Find(no);
cout << "student you want to fill, his message:";
cin >> no >> credits >> average;
c.fillMessage(no,credits,average);
c.showStudentMessage();
return 0;
}
4 实验结果
(1)Date类与对象
将当前日期设置为2016年3月26日,之后予以显示,同时加一,再显示。效果如下:
若设置当前日期为2016年2月29日,则输出:
若设置为2016年12月31日,则输出:
若设置为2016年12月32日,则输出:
(2)学生类、班级类与对象
对于相应的输入,输出如下:
5 心得小结
通过本次实验,我学会了如何定义一个类,如何使用构造函数进行初始化,如何利用公有函数访问私有成员,如何申请并初始化对象数组等等技能。在定义对象数组时,遇到了初始化的难题,通过查阅相关书籍,采用了先定义一个一维对象数组指针,然后逐一分配内存并在申请时进行初始化。同时,在编写时,没有很好的注意不能在外部访问私有成员,导致先前编译时出错,后编写了几个公有的访问函数,解决了问题。