2013-08-27 79 views
0

我是一名學生,負責涉及數組,指針,結構和解除/引用的問題。我瞭解每種方法的意義和每種方法的一般初始化,但我感覺我仍然沒有在我的程序中正確使用它們。我有什麼運行/工作很好,但我想知道是否有更好的方式來使用這些?C++指針和數組...什麼時候使用[],*和&

一般程序要求如下:(我已經包括了我認爲涵蓋每個問題的行,我想確保我正在使用並將每一行正確地合併到程序中,主要在我使用的地方StudentData[i].testArray

1 - 使用一個結構來存儲以下數據:name,id#,test(指向 數組測試分數),平均值,字母等級。

struct StudentData {...}; 

2 - 向學生的數量和測試次數(同樣爲每個 學生)

3 - 動態分配結構的陣列

StudentData *allStudents; 
allStudents = new StudentData[numStudents]; 

4 - 每個結構的測試成員應該指向動態分配的數組t est分數。

double *testsArray; 
for (int i=0; i < numStudents; i++) 
{ 
    allStudents[i].testsArray = new double[numTests]; 
} 
//does this need to be deleted with a for loop as well?? 

5 - 計算測試平均和字母等級

6 - 顯示信息

全碼:

// Course Grade 
// A program to gather and display a collection of student information. 
// Programmer Name : Chuck 
// C++ II 

#include <iostream> 
#include <string> 
#include <iomanip> 
using namespace std; 

//structure to hold data for each student 
struct StudentData 
{ 
    string studentName; 
    int studentID; 
    double *testsArray;  //pointer to an array of test scores 
    double testAverage;  //calculated average test score 
    char courseGrade;  //calculated course letter grade (A-F) 
}; 


//function prototypes 
string getName(); 
int getID(); 
double getScore(int count); 
char calcGradeLetter(double *testAverage); 
void displayData (StudentData allStudents[], int sCount); 



int main() 
{ cout << " Welcome to the Test Score Storer. This program will gather test\n"; 
    cout << "scores for a given student name/id#. We'll start with some questions.\n\n"; 

    int numTests; 
    cout << "How many test scores per student? : "; 
    cin >> numTests; 

    int numStudents; 
    cout << "How many students?    : "; 
    cin >> numStudents; 

    cout << "Creating Database..."; 
    //create array to hold all studentData structs 
    StudentData *allStudents; 
    allStudents = new StudentData[numStudents]; 
    cout << "..."; 
    //create a tests member array for each student struct 
    double *testsArray; 
    for (int i=0; i < numStudents; i++) 
    { 
     allStudents[i].testsArray = new double[numTests]; 
    } 
    cout <<"...Done!\n"; 
    system ("pause"); 
    system ("CLS"); 


    //TRYING 
    for (int i=0; i < numStudents; i++) 
    { 
     cout << "Student " << i+1 << " of " << numStudents << endl; 
     cout << "=================================\n"; 
     allStudents[i].studentName = getName(); 
     allStudents[i].studentID = getID(); 
     double testTotal = 0.0; 
     for (int j=0; j < numTests; j++) 
     { 
      allStudents[i].testsArray[j] = getScore(j); 
      testTotal += allStudents[i].testsArray[j]; 
      allStudents[i].testAverage = testTotal/numTests; 
     } 
     //calculate letter grade 
     allStudents[i].courseGrade = calcGradeLetter(&allStudents[i].testAverage); 
     cout << "Student, " << allStudents[i].studentName << ", completed.\n"; 
     system ("pause"); 
     system ("CLS"); 
    } 

    //Display all collected student data in chart form 
    displayData(allStudents, numStudents); 


    delete [] allStudents; 
    system ("pause"); 
    return (0); 
} 


//===========FUNCTIONS===========FUNCTIONS===========FUNCTIONS 
string getName() 
{ 
    string name; 
    cout << "Student Name : "; 
    cin >> name; 
    return name; 
} 

int getID() 
{ 
    int IDnum; 
    cout << "Student ID : "; 
    cin >> IDnum; 
    return IDnum; 
} 

double getScore(int count) 
{ 
    double score; 
    score = -500; 
    while (score <0) 
    { cout << "Test Score #" << count+1 <<" : "; 
     cin >> score; 
     if (score < 0) 
     { 
      cout << "Scores cannot be less than 0, try again.\n"; 
     } 
    } 
    return score; 
} 


char calcGradeLetter(double *testAverage) 
{ 
    if (*testAverage >= 90) return 'A'; 
    else if (*testAverage >= 80) return 'B'; 
    else if (*testAverage >= 70) return 'C'; 
    else if (*testAverage < 70) return 'F'; 
    else return ('X'); 
} 

void displayData(StudentData allStudents[], int sCount) 
{ 
    cout << "Student Data Chart:\n"; 
    cout << "=================================================\n"; 
    cout << "NAME    ID#   TEST AVE. GRADE\n"; 
    for (int i = 0; i < sCount; i++) 
    { 
     cout << left << setw(18) << allStudents[i].studentName << " " 
      << left << setw(12) << allStudents[i].studentID << " " 
      << left << setw(11) << setprecision(4) << allStudents[i].testAverage << " " 
      << allStudents[i].courseGrade << endl; 
    } 
    cout << "\nTable complete. "; 
    } 

這是我對堆棧的第一篇文章,對不起,如果這出現在錯誤的地方或作爲功課的需要Ÿ,我不只是尋找一個簡單的答案。我是一位新開發人員,渴望學習。這個話題只是我遇到了很多麻煩。

+4

使用'std :: vector'代替動態數組'la'new []'更容易。 – chris

+3

如果只有你知道在這兩個地方使用'std:; vector <>'消失了多少*。除了虛假地使用'std :: string','operator new()'和控制檯輸出外,這也可能是C代碼。另外,你的'StudentData'是一個構造函數和析構函數。 – WhozCraig

回答

1

你的問題的簡短答案是肯定的,有更好的方法來完成結果。

更長的答案是,由於你的任務的性質和你必須專門處理內存分配和釋放的要求(順便說一句,我沒有看到你在哪裏釋放每個測試內核的位置學生,你需要在刪除它之前遍歷每個學生並刪除測試分數數組),它限制了你使用諸如std::vector之類的東西,它會爲你處理所有的數組問題。

只是爲了幫助內存管理了一下:

struct StudentData 
{ 
    StudnetData() : studentID(0), testsArray(NULL), testAverage(0.0), courseGrade('N') 
    { 

    } 

    ~StudentData() 
    { 
     delete [] testsArray; 
    } 

    string studentName; 
    int studentID; 
    double *testsArray;  //pointer to an array of test scores 
    double testAverage;  //calculated average test score 
    char courseGrade;  //calculated course letter grade (A-F) 
private: 
    StudentData(const StudentData&); // unimplemented intentionally 
    StudentData& operator= (const StudentData&); // unimplemented intentionally 
}; 

然後,當你刪除學生陣列:

delete [] allStudents; 

他們也將被刪除的任何檢測結果。

+0

我們已經瞭解了矢量,並且看到它們在這裏如何非常有用,但不幸的是我們必須使用數組。 Zac,我不確定是否刪除allStudents數組會刪除測試分數數組。我將循環並刪除,如下所示: –

+0

如果向結構添加析構函數,則可以在刪除學生時刪除測試分數數組。 –

+0

對不起...忘了轉移+輸入然後用完了時間。 正確刪除。將這個 對(INT X = 0; X

1

呃,這在很大程度上是很好的,因爲你被要求使用new而不是像std::vector這樣的標準練習。

C++確實有工具可以用來包裝這種使用new,以使其更容易,更安全,更自動化等,同時仍符合要求。你基本上將實施vector的簡化版本。但是,你可能還沒有學習C++的所有必要部分。

structs TestsArray { 
    double *scores; 
    // constructors, destructors, etc. to make this behave properly 
    // ... 
}; 

structs StudentsArray { 
    StudentData *students; 
    // basically the same as for TestArray; templates avoid this duplication 
}; 

還在爲等級可以定義一個枚舉:

enum Grade { A, B, C, D, F}; 

這樣你就不太可能在某處遇到一個無效的等級(例如,「E」)。

struct StudentData 
{ 
    string studentName; 
    int studentID; 
    TestsArray testsArray; 
    double testAverage; 
    Grade courseGrade; 
}; 


cout << "Creating Database..."; 
//create array to hold all studentData structs 
StudentsArray allStudents(numStudents, numTests); 
cout <<"...Done!\n"; 

// allStudents will automatically be cleaned up at the end 

//這是否需要一個被刪除的循環也?

是的,或者至少你需要以某種方式安排每個學生的testsArray被刪除。

+0

不一定是一個for循環,但這是做到這一點的一種方式(向學生結構添加析構函數是另一種方法)。 –

+0

@ZacHowland啊,我只是在改變它。我首選的方法(考慮到'std :: vector'不在表格中)將會實現一個數組類型來處理它自己(所以'Student'可以使用默認的析構函數,而整個'Student'數組可以是類似的類型(或者是同一個數組模板的另一個實例)。)。 – bames53

+0

我同意。我總是討厭這樣的任務,迫使你做一些不好的練習。至少,他們應該允許使用智能指針。 –