2013-04-26 63 views
-2

我寫了一個工作正常的代碼。我只想要額外的眼睛來突出每一件應該/可以改進的東西。我必須創建一個student.dat文件,然後寫入由用戶給出的數據(每個學生的姓名,年齡,gpa),然後關閉它,然後重新打開以供閱讀,從而顯示學生的gpa。學生是一個Class對象。我只想檢查OOP的概念(至少在那個問題上)。我正在使用Dev-C++。代碼如下:C++中的類和文件操作

#include <iostream> 
#include <conio.h> 
#include <fstream> 
#include <string> 
#include <iomanip> 

#define W setw 
using namespace std; 

class Student 
{ 
private: 
    char name[40]; 
    int age; 
    double GPA; 

public: 
    Student(){}; 
    void read(); 
    void show(char* ,int ,double); 
    int writefile(ofstream &OS); 
    double getgpa(double*, int); 
    void readfile(); 
}; 



void Student::read(void) 
{ 
int nbrSt=0; 
cout<<"Please enter the information of the student: "<<endl; 
cout<<"'y' to Continue, Ctrl+Z to exit! "<<endl;  
cout<<"Name, Age and GPA:\n"; 


ofstream OS("student.dat", ios::out); 
while (cin>>name>>age>>GPA) 
{  
     //writing in the file 
     writefile(OS); 
     nbrSt++; //increment the number of students 
     cout<<"Name, Age and GPA:\n"; 
} 
OS.close(); 

} 

int Student::writefile(ofstream & OS) 
{ 

OS<<'\n'<<W(10)<<name<<W(6)<<age<<W(10)<<GPA; 

return 0; 
} 

void Student::show(char* Name, int Age, double gpa) 
{ 
cout<<'\n'<<W(10)<<Name<<W(6)<<Age<<W(8)<<gpa<<endl;  

} 

double Student::getgpa(double* allGPA, int nbrgpa) 
{ 
double sum=0; 
int i =0; 

for (i=0;i<nbrgpa; i++) 
    sum+=allGPA[i]; 

if(nbrgpa>0) 
    return sum/nbrgpa; 

} 


void Student::readfile() 
{ 
char Name[30]; 
int Age; 
double aveGPA, gpa; 
    int nbrgpa=0; 
double allGPA[50]; 
int i=0; 


ifstream IS("Student.dat", ios::in); 
cout<<"reading from Binary file"<<endl; 

if (IS.is_open()) 

    while(IS>>Name>>Age>>gpa) 
    { 
     nbrgpa++; 
     show(Name, Age, gpa); 
     allGPA[i]=gpa; 
     i++;  
} 
    IS.close(); 


aveGPA=getgpa(allGPA, nbrgpa); 

cout<<"Average GPA of students: "<<aveGPA<<endl; 

} 

int main(void) 
{ 
Student S; 

S.read(); 
S.readfile(); 

return 0; 
} 
+4

http://codereview.stackexchange.com/ – 2013-04-26 10:53:03

+1

適當縮進它會是一個很大的改進。使用可讀的名稱而不是例如如果你希望其他人(或者幾天後你自己)閱讀它,'W'和'nbrgpa'也可能是一個好主意。 – 2013-04-26 10:56:03

+0

您更多地使用'Student'作爲命名空間而不是對象。所以:你的代碼中只有一點「OOP」的暗示。 – molbdnilo 2013-04-26 11:20:26

回答

2
Student(){}; 

是非法的語法

Student(){} 

是正確的。


void Student::read(void) 

設計很糟糕。學生::閱讀應該是一種讀取一名學生的方法。閱讀多個stduents和寫作的學生應該在其他功能或方法。


int Student::writefile(ofstream & OS) 

應該

int Student::writefile(ostream & OS) 

因此它可以與各種流(不只是文件流)。顯然你應該重命名該方法。舉個例子來說吧。


double Student::getgpa(double* allGPA, int nbrgpa) 

不應該是學生中的一員,它應該是一個全球性的功能。


您的主要問題是面向對象的設計。你不應該把所有的東西都加入到Student這個課程中,而不會考慮你在做什麼。 Student類中的方法應該是關於一個學生,例如讀或寫一個學生的方法。其他一切都應該在全局函數中(或者在其他類中,如果您向程序中添加第二個類)。

+0

寫入文件是分配所需的,所以它可以用於文件流(僅)。 getgpa也需要成爲一個成員函數。我所做的只是找出每個功能的論點,因爲他們沒有提供。 – T4000 2013-04-26 11:01:57

+0

@john爲什麼getgpa()不應該是Student的成員?它接受所有的gpa,然後提取我猜想的特殊學生。你的意思是說學生是一個明確的參數,然後在其上工作? – 2013-04-26 11:04:18

+1

'學生(){};'不是非法的語法。類中的函數定義可以跟一個可選的'''。 (C++ 11已經擴展了這個以允許一個空語句,因此在語句之後或之間有一個額外的';',無處不在)。 – 2013-04-26 11:15:25

1

我只是想要額外的眼睛來突出每一件應該/可以改進的東西。

#define W setw 

不要那樣做。你可能認爲它使得使用setw的代碼看起來更簡單,但其他人在查看你的代碼將不得不搜索W解決的問題。

using namespace std; 

不要聲明全局使用名稱空間標準。在小型項目中這不是一個大問題,但會使代碼更難重用。

你的班級的界面是非標準的。考慮通過創建ostream << student操作符和通過創建'istream >>學生'來閱讀。這尊重最少突然的規則,並使您能夠(例如)使用迭代閱讀一系列學生。

您需要更好的函數名稱:

您的讀取函數寫入文件。對於我來說,在生產代碼中看到這將是一個很大的WTF時刻。請更改名稱或更改功能。

您的閱讀功能在學生實例上調用(Student s; s.read();),但它不適用於實例。它實際上將一組記錄從cin轉移/存儲到一個文件,並將其被調用的實例設置爲最後一條記錄。如果讀數在數據中途失敗(即cin>>name>>age>>GPA獲得正確的名稱,但不是年齡或GPA),它將使其被調用的實例處於無效狀態。

考慮將您的代碼分別從char name[40];double* allGPA, int nbrgpa分別移至std::stringstd::vector<double>。使用原始數據很容易出錯並且不必要的複雜。

還有很多需要說的,但我想我已經給了你足夠的:-)。

+0

謝謝utnapistim,我會處理所有這些言論和建議。 – T4000 2013-04-26 11:27:33