一、目的要求
1.理解面向对象的程序设计的特点;
2.学会构造函数的使用和函数重载;
3.学会对象指针的使用、对象的动态建立和释放;
4.理解类的封装性和信息隐藏、析构函数的作用。
二、实验内容:
1.定义学生类,包括学号、姓名、性别、成绩,学生分为两类,课程门数不同,并将课程成绩全部初始化为0;假设有n个学生,由键盘输入学生信息;
2.定义类成员函数,完成修改学生的信息,统计所有学生课程的平均成绩、最高分和最低分;
3.同时输出所有学生信息;
4.通过输入学生学号或姓名查询某学生的信息。
三、实验要求:
1.利用头文件和多个源文件分别实现类的声明、类成员函数的定义和主函数;
2.从键盘输入学生数,为对象动态分配内存空间,并保证对象使用完毕时释放内存空间;
3.定义构造函数完成类成员变量的初始化;
4.利用静态成员变量与静态成员函数统计所有学生课程的平均成绩、最高分和最低分;
5.利用函数的重载实现通过输入学生学号或姓名查询某学生的信息。
兼顾程序的逻辑性、人性化设计,并减少冗余代码,(比如输入时提示输入内容、输出格式一目了然等。
附代码
!!!编译环境 DevC++ 5.11 TDM-GCC 4.9.2 64-Bit Release
头文件 iquery.h
#ifndef _IQUERY_H
#define _IQUERY_H 1
using namespace std;
#define MAXN 100
#define MAXY 5
class student{
private:
int old;
string sex;
string name;
int number;
double chinese;
double math;
double english;
double science;
double art;
double ave_grade; //个人主科综合成绩
static double sum_1[MAXY];
static int count_1;
static double max_allgrade_1[MAXY];
static double min_allgrade_1[MAXY];
static double sum_2[MAXY];
static int count_2;
//第一类 存储平均值和最大最小值的数组
static double ave_allgrade_1[MAXY];
static double max_1[MAXY];
static double min_1[MAXY];
//第二类
static double ave_allgrade_2[MAXY];
static double max_2[MAXY];
static double min_2[MAXY];
public:
void data_input(int idx);
bool data_grade_judge(); //judge 每个学生成绩是否及格
void data_output(int idx);
//查找函数
bool data_search(string pname)const;//重载实现姓名或学号查找 int data_search(int *pnumber);
bool data_search(int pnumber)const;
//析构
~student();
//计算平均数
static double data_ave_allgrade(int idx);
//输出静态变量,实现静态成员封装
static double output_ave_allgrade(int idx);
static double output_max_allgrade(int idx);
static double output_min_allgrade(int idx);
//total函数
void total(int idx);
//找最大最小
void judge_max(int idx);
void judge_min(int idx);
void init_judge_min(int idx); //min数组第一次调用时初始化
//修改
void data_change();
};
#endif
// 类成员函数中const的使用
// 一般放在函数体后,形如:void fun() const;
// 任何不会修改数据成员的函数都因该声明为const类型。
头文件实现文件 iquery,cpp
#include <iostream>
#include "string"
#include "iquery.h"
#include "iomanip"
using namespace std;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
void student :: data_input(int idx){
if(idx==1){
cout<<" 姓名:" ;cin>>name;
cout<<" 年龄:" ;cin>>old;
cout<<" 性别:" ;cin>>sex;
cout<<" 学号:" ;cin>>number;
cout<<"接下来依次输入语文,数学,英语,科学成绩"<<endl;
cin>>chinese>>math>>english>>science;
ave_grade=(math+chinese+english)/3;
}
else if(idx==2){
cout<<" 姓名:" ;cin>>name;
cout<<" 年龄:" ;cin>>old;
cout<<" 性别:" ;cin>>sex;
cout<<" 学号:" ;cin>>number;
cout<<"接下来依次输入语文,数学,英语,科学,艺术成绩"<<endl;
cin>>chinese>>math>>english>>science>>art;
ave_grade=(math+chinese+english)/3;
}else{
cout<<"error in student choice, only 1 or 2"<<endl;
}
}
bool student :: data_grade_judge(){
while(chinese<90||math<90||english<90){
return 1;
}
return 0;
}
void student :: data_output(int idx){
if(idx==1){
cout<<setiosflags(ios::left);
cout<<" 姓名:" <<name<<endl;
cout<<" 年龄:" <<old<<endl;
cout<<" 性别:" <<sex<<endl;
cout<<" 学号:" <<number<<endl;
cout<<setw(10)<<" 语文:" <<setw(6)<<chinese<<setw(6)<<"数学:"<<setw(6)<<math<<setw(6)<<"英语:"<<setw(6)<<english<<endl;
cout<<setw(10)<<" 科学:"<<setw(6)<<science <<endl;
cout<<" 主科平均成绩:"<<ave_grade<<endl;
}
else if(idx==2){
cout<<setiosflags(ios::left);
cout<<" 姓名:" <<name<<endl;
cout<<" 年龄:" <<old<<endl;
cout<<" 性别:" <<sex<<endl;
cout<<" 学号:" <<number<<endl;
cout<<setw(10)<<" 语文:" <<setw(6)<<chinese<<setw(6)<<"数学:"<<setw(6)<<math<<setw(6)<<"英语:"<<setw(6)<<english<<endl;
cout<<setw(10)<<" 科学:"<<setw(6)<<science <<setw(6)<<"艺术:"<<setw(6)<<art<<endl;
cout<<" 主科平均成绩:"<<ave_grade<<endl;
}else{
cout<<"error in student choice, only 1 or 2"<<endl;
}
}
bool student :: data_search(string pname) const {
if(this->name.compare(pname)==0)
return 1;
else return 0;
}
bool student :: data_search(int pumber) const {
if(pumber==this->number)
return 1;
else return 0;
}
//静态成员变量初始化 类一
int student::count_1=0;
double student::sum_1[MAXY]={0,0,0,0,0};
double student::max_1[MAXY]={0,0,0,0,0};
double student::min_1[MAXY]={0,0,0,0,0};
double student::ave_allgrade_1[MAXY]={0,0,0,0,0};
//类二
int student::count_2=0;
double student::sum_2[MAXY]={0,0,0,0,0};
double student::max_2[MAXY]={0,0,0,0,0};
double student::min_2[MAXY]={0,0,0,0,0};
double student::ave_allgrade_2[MAXY]={0,0,0,0,0};
double student :: output_ave_allgrade(int idx){
switch(idx){
case 10:
return ave_allgrade_1[0];
case 11:
return ave_allgrade_1[1];
case 12:
return ave_allgrade_1[2];
case 13:
return ave_allgrade_1[3];
//类2
case 20:
return ave_allgrade_2[0];
case 21:
return ave_allgrade_2[1];
case 22:
return ave_allgrade_2[2];
case 23:
return ave_allgrade_2[3];
case 24:
return ave_allgrade_2[4];
default:
cout<<"error in ave_allgrade choice, only 10 11 12 13 or 20 21 22 23 24"<<endl;
}
}
double student :: output_max_allgrade(int idx){
switch(idx){
case 10:
return max_1[0];
case 11:
return max_1[1];
case 12:
return max_1[2];
case 13:
return max_1[3];
//类2
case 20:
return max_2[0];
case 21:
return max_2[1];
case 22:
return max_2[2];
case 23:
return max_2[3];
case 24:
return max_2[4];
default:
cout<<"error in ave_allgrade choice, only 10 11 12 13 or 20 21 22 23 24"<<endl;
}
}
double student :: output_min_allgrade(int idx){
switch(idx){
case 10:
return min_1[0];
case 11:
return min_1[1];
case 12:
return min_1[2];
case 13:
return min_1[3];
//类2
case 20:
return min_2[0];
case 21:
return min_2[1];
case 22:
return min_2[2];
case 23:
return min_2[3];
case 24:
return min_2[4];
default:
cout<<"error in ave_allgrade choice, only 10 11 12 13 or 20 21 22 23 24"<<endl;
}
}
void student :: total(int idx){
if(idx==1){
sum_1[0]+=chinese;
sum_1[1]+=math;
sum_1[2]+=english;
sum_1[3]+=science;
count_1++;
}
else if(idx==2){
sum_2[0]+=chinese;
sum_2[1]+=math;
sum_2[2]+=english;
sum_2[3]+=science;
sum_2[4]+=art;
count_2++;
}else{
cout<<"error in student choice, only 1 or 2"<<endl;
}
}
double student :: data_ave_allgrade(int idx){
if(idx==1){
ave_allgrade_1[0]=sum_1[0]/(count_1);
ave_allgrade_1[1]=sum_1[1]/(count_1);
ave_allgrade_1[2]=sum_1[2]/(count_1);
ave_allgrade_1[3]=sum_1[3]/(count_1);
}
else if(idx==2){
ave_allgrade_2[0]=sum_2[0]/(count_2);
ave_allgrade_2[1]=sum_2[1]/(count_2);
ave_allgrade_2[2]=sum_2[2]/(count_2);
ave_allgrade_2[3]=sum_2[3]/(count_2);
ave_allgrade_2[4]=sum_2[4]/(count_2);
}else{
cout<<"error in student choice, only 1 or 2"<<endl;
}
}
void student :: judge_max(int idx){
if(idx==1){
if(max_1[0]<this->chinese)
max_1[0]=this->chinese;
if(max_1[1]<this->math)
max_1[1]=this->math;
if(max_1[2]<this->english)
max_1[2]=this->english;
if(max_1[3]<this->science)
max_1[3]=this->science;
}
else if(idx==2){
if(max_2[0]<this->chinese)
max_2[0]=this->chinese;
if(max_2[1]<this->math)
max_2[1]=this->math;
if(max_2[2]<this->english)
max_2[2]=this->english;
if(max_2[3]<this->science)
max_2[3]=this->science;
if(max_2[4]<this->art)
max_2[4]=this->art;
}else{
cout<<"error in student choice, only 1 or 2"<<endl;
}
}
void student :: judge_min(int idx){
if(idx==1){
if(min_1[0]>this->chinese)
min_1[0]=this->chinese;
if(min_1[1]>this->math)
min_1[1]=this->math;
if(min_1[2]>this->english)
min_1[2]=this->english;
if(min_1[3]>this->science)
min_1[3]=this->science;
}
else if(idx==2){
if(min_2[0]>this->chinese)
min_2[0]=this->chinese;
if(min_2[1]>this->math)
min_2[1]=this->math;
if(min_2[2]>this->english)
min_2[2]=this->english;
if(min_2[3]>this->science)
min_2[3]=this->science;
if(min_2[4]>this->art)
min_2[4]=this->art;
}else{
cout<<"error in student choice, only 1 or 2"<<endl;
}
}
void student :: init_judge_min(int idx){
if(idx==1){
min_1[0]=this->chinese;
min_1[1]=this->math;
min_1[2]=this->english;
min_1[3]=this->science;
}
else if(idx==2){
min_2[0]=this->chinese;
min_2[1]=this->math;
min_2[2]=this->english;
min_2[3]=this->science;
min_2[4]=this->art;
}else{
cout<<"error in student choice, only 1 or 2"<<endl;
}
}
void student :: data_change(){
int cnt;
int grade_change;
cout<<"修改成绩,请输入对应位置"<<endl;
cin>>cnt;
switch(cnt){
case 1:
cout<<"请输入修改后的chinese成绩"<<endl;
cin>>grade_change;this->chinese =grade_change;
break;
case 2:
cout<<"请输入修改后的math成绩"<<endl;
cin>>grade_change;this->math =grade_change;
break;
case 3:
cout<<"请输入修改后的english成绩"<<endl;
cin>>grade_change;this->english =grade_change;
break;
default :
cout <<"error in fun_data_change" ;
}
}
//析构函数
student::~student()
{
cout<<endl<<"thank you for use,written by chenfeng."<<endl<<"all right reserved";
}
源码 main.cpp
#include <iostream>
#include "iquery.h"
#include "string"
#include "iomanip"
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
using namespace std;
int main(int argc, char** argv) {
int num1,num2;
int cnt=0;
string search;
int psearch;
cout<<"请注意学生共有两类,请分别输入两类学生的信息。"<<endl;
cout<<"请输入第一类学生人数:"<<endl;
cin>>num1;
cout<<"请输入第二类学生人数:"<<endl;
cin>>num2;
student *stu1=new student[num1];
student *stu2=new student[num2];
system("cls");
cout<<"--------------------输入第一类学生信息--------------------"<<endl;
for (int i=0;i<num1;i++)
{
stu1[i].data_input(1);
}
cout<<"--------------------输入第二类学生信息--------------------"<<endl;
for (int i=0;i<num2;i++)
{
stu2[i].data_input(2);
}
cout<<"信息输入结束"<<endl;
getchar();
system("cls");
cout<<setiosflags(ios::left);
//对数据进行处理
//计算平均值
for(int i=0;i<num1;i++){
stu1[i].total(1);
}
student :: data_ave_allgrade(1);
for(int i=0;i<num2;i++){
stu2[i].total(2);
}
student :: data_ave_allgrade(2);
//计算最大最小值
stu1[0].init_judge_min(1);
for(int i=0;i<num1;i++){
stu1[i].judge_max(1);
stu1[i].judge_min(1);
}
stu2[0].init_judge_min(2);
for(int i=0;i<num2;i++){
stu2[i].judge_max(2);
stu2[i].judge_min(2);
}
//输出成绩数据
cout<<"------------------所有课程成绩统计------------------------"<<endl;
cout<<"第一类"<<endl;
cout<<"课程 平均分 最高分 最低分" <<endl;
cout<<"语文 "<<setw(12)<<student::output_ave_allgrade(10)<<setw(12)<<student::output_max_allgrade(10)<<setw(12)<<student::output_min_allgrade(10)<<endl;
cout<<"数学 "<<setw(12)<<student::output_ave_allgrade(11)<<setw(12)<<student::output_max_allgrade(11)<<setw(12)<<student::output_min_allgrade(11)<<endl;
cout<<"英语 "<<setw(12)<<student::output_ave_allgrade(12)<<setw(12)<<student::output_max_allgrade(12)<<setw(12)<<student::output_min_allgrade(12)<<endl;
cout<<"科学 "<<setw(12)<<student::output_ave_allgrade(13)<<setw(12)<<student::output_max_allgrade(13)<<setw(12)<<student::output_min_allgrade(13)<<endl;
// cout<<"艺术 "<<setw(12)<<student::output_ave_allgrade(14)<<setw(12)<<student::output_max_allgrade(14)<<setw(12)<<student::output_min_allgrade(14)<<endl<<endl;
cout<<"第二类"<<endl;
cout<<"课程 平均分 最高分 最低分" <<endl;
cout<<"语文 "<<setw(12)<<student::output_ave_allgrade(20)<<setw(12)<<student::output_max_allgrade(20)<<setw(12)<<student::output_min_allgrade(20)<<endl;
cout<<"数学 "<<setw(12)<<student::output_ave_allgrade(21)<<setw(12)<<student::output_max_allgrade(21)<<setw(12)<<student::output_min_allgrade(21)<<endl;
cout<<"英语 "<<setw(12)<<student::output_ave_allgrade(22)<<setw(12)<<student::output_max_allgrade(23)<<setw(12)<<student::output_min_allgrade(22)<<endl;
cout<<"科学 "<<setw(12)<<student::output_ave_allgrade(23)<<setw(12)<<student::output_max_allgrade(23)<<setw(12)<<student::output_min_allgrade(23)<<endl;
cout<<"艺术 "<<setw(12)<<student::output_ave_allgrade(24)<<setw(12)<<student::output_max_allgrade(24)<<setw(12)<<student::output_min_allgrade(24)<<endl;
cout<<"----------------------所有学生信息------------------------"<<endl;
cout<<"第一类学生"<<endl;
for(int i=0;i<num1;i++){
stu1[i].data_output(1);
cout<<endl;
}
cout<<"第二类学生"<<endl;
for(int j=0;j<num2;j++){
stu2[j].data_output(2);
cout<<endl;
}
cout<<"-------------------------信息查询------------------------"<<endl;
cout<<"请注意:查询既可以使用姓名也可以使用学号,但使用姓名可能出现重名情况。" <<endl;
do{
cout<<"请输入查询姓名或学号:"<<endl;
cout<<" 查询姓名,输入1"<<endl;
cout<<" 查询学号,输入2"<<endl;
cin>>psearch;
if(psearch==1){
cout<<"请输入要查询的学生姓名:"<<endl;
cin>>search;
for(int i=0;i<num1;i++){
if(stu1[i].data_search(search)){
stu1[i].data_output(1);
}
}
for(int j=0;j<num2;j++){
if(stu2[j].data_search(search)){
stu2[j].data_output(2);
}
}
fflush(stdin);
cout<<"你想修改该成员信息么?"<<"输入1,需要"<<"输入2,不需要"<<endl<<"没有输出结果请忽略该提示"<<endl;
cin>>psearch;
if(psearch==1) {
for(int i=0;i<num1;i++){
if(stu1[i].data_search(search)){
stu1[i].data_change();
}
}
for(int j=0;j<num2;j++){
if(stu2[j].data_search(search)){
stu2[j].data_change();
}
}
}
}
if(psearch==2){
cout<<"请输入要查询的学生学号:"<<endl;
cin>>psearch;
for(int i=0;i<num1;i++){
if(stu1[i].data_search(psearch)){
stu1[i].data_output(1);
}
}
for(int j=0;j<num2;j++){
if(stu2[j].data_search(psearch)){
stu2[j].data_output(2);
}
}
fflush(stdin);
cout<<"你想修改该成员信息么?"<<"输入1,需要"<<endl<<"输入2,不需要";
cin>>psearch;
if(psearch==1) {
for(int i=0;i<num1;i++){
if(stu1[i].data_search(search)){
stu1[i].data_change();
}
}
for(int j=0;j<num2;j++){
if(stu2[j].data_search(search)){
stu2[j].data_change();
}
}
}
}
fflush(stdin);
if(psearch==0){
break;
}
cout<<endl<<"如果没有输出结果,则无此学生信息"<<endl<<"你可重新输入1 or 2 进行查找"<<endl<<"输入0结束查询,程序退出"<<endl<<endl;
}while(psearch);
cout<<"-------------------------使用结束------------------------"<<endl;
delete [] stu1;
delete [] stu2;
return 0;
}
注:
已经出现过的error:
- 静态成员变量在DevC++ 5.11 TDM-GCC 4.9.2 64-Bit Release 下需要手动初始化,并注意不要在头文件里进行初始化
- 静态成员函数只能操作或访问静态成员,不能访问非静态成员;非静态成员函数则两者都可以
存在的问题:
- 析构函数调用次数的问题:有时候调用一次,有时候是两次
- 输出时逻辑存在一定问题。
可行性优化:
- 功能通过菜单进行选择
- 调用构造函数进行对象的初始化
- 使用继承完成student类
- 使用linkedList优化数据结构
- 减少冗余代码
- student类数据的封装带来的接口的冗余怎么处理?