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