C++ 实验四 类和对象(二)

一、目的要求
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:

  1. 静态成员变量在DevC++ 5.11 TDM-GCC 4.9.2 64-Bit Release 下需要手动初始化,并注意不要在头文件里进行初始化
  2. 静态成员函数只能操作或访问静态成员,不能访问非静态成员;非静态成员函数则两者都可以

存在的问题:

  1. 析构函数调用次数的问题:有时候调用一次,有时候是两次
  2. 输出时逻辑存在一定问题。

可行性优化:

  1. 功能通过菜单进行选择
  2. 调用构造函数进行对象的初始化
  3. 使用继承完成student类
  4. 使用linkedList优化数据结构
  5. 减少冗余代码
  6. student类数据的封装带来的接口的冗余怎么处理?

欢迎访问陈风的个人博客


版权声明:本文为qq_40724028原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。