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類數據的封裝帶來的接口的冗餘怎麼處理?

歡迎訪問陳風的個人博客

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章