2017-07-06 57 views
-1

我正在寫一個程序,使用結構數組來存儲一定數量的學生的姓名,身份證號碼和一系列測試分數。結構數組和測試成績數組成員都需要動態分配。我已經完成了允許用戶爲每個學生輸入測試分數的功能,但是我在最後一個函數(getScores函數)中遇到了cin問題。當使用Linux時,我得到了一個分段錯誤,所以我假設它與動態分配的測試數組是相關的,我只是看不到它。我想知道如何去調試它,並解釋爲什麼會發生這種情況,所以我可以在將來避免它。動態分配的數組作爲C++中的結構成員的分割錯誤?

//Preprocessor Directives 
#include <iostream> 
#include <iomanip> 
#include <string> 
using namespace std; 

//Structure declaration 
struct Students 
{ 
    string name; //Student name 
    int idNum; //Student ID number 
    double *tests; //Pointer to an array of test scores 
}; 

//Function prototypes 
Students *getStudents(int &); 
double *getTests(int &); 
void getInfo(string &, int &, int); 
void getScores(double &, string, int); 

//Main program section 
int main() 
{ 
    int numStudents = 0; 
    int numTests = 0; 
    Students *studentFiles = NULL; 

    //Call the getStudents function 
    studentFiles = getStudents(numStudents); 

    //Call the getTests function 
    studentFiles->tests = getTests(numTests); 

    for(int i = 0; i < numStudents; i++) 
    { 
     //Call the getInfo function 
     getInfo(studentFiles[i].name, studentFiles[i].idNum, i+1); 
    } 

    for(int i = 0; i < numStudents; i++) 
    { 
     for(int j = 0; j < numTests; j++) 
     { 
      getScores(studentFiles[i].tests[j], studentFiles[i].name, j); 
     } 
    } 
    delete [] studentFiles; 
    delete [] studentFiels->tests; 
    return 0; 
} 

Students *getStudents(int &numStudents) 
{ 
    Students *studentFiles = NULL; 

    //Prompt the user for the number of students 
    cout<<"Enter the number of students: "; 
    cin>>numStudents; 
    //Dynamically allocate an array of structs, one for each student 
    studentFiles = new Students[numStudents]; 

    return studentFiles; 
} 

double *getTests(int &numTests) 
{ 
    double *tests = NULL; 

    //Prompt the user for the number of tests 
    cout<<"Enter the number of tests: "; 
    cin>>numTests; 
    cin.ignore(); 
    //Dynamicall allocate an array of integers, one for each test 
    tests = new double[numTests]; 

    return tests; 
} 

void getInfo(string &name, int &idNum, int index) 
{ 
    //Prompt for each student's name and id number 
    cout<<"Enter the name of student #"<<index<<": "; 
    getline(cin, name); 
    cout<<"Enter the id number of student #"<<index<<": "; 
    cin>>idNum; 
    cin.ignore(); 
} 

void getScores(double &test, string name, int numTest) 
{ 
    cout<<name<<endl; 
    cout<<numTest<<endl; 
    //Prompt for each test score for each student 
    cout<<"Enter "<<name<<"'s score for test #"<<numTest+1<<": "; 
    cin>>test; 
} 
+1

你調試了代碼嗎?你做什麼時看到了什麼?它在哪裏崩潰,內存值是什麼,... – UnholySheep

+0

只要有不止一個學生,就在getScores函數中的最後一個cin後面,它就會崩潰。它似乎沒有讀取最後一個值,因爲可能沒有放置它或什麼的地方,但我不明白爲什麼。如果我輸入2個學生2個測試,它會通過第一個學生的前兩個測試分數。當它輸入第二個學生的考試分數時,您可以輸入分數,按回車,然後崩潰。這就是Linux給我分段錯誤的地方。 – mobandy644

+1

'studentFiles-> tests = getTests(numTests);'''studentFiles'是一個指向你的代碼中的數組的指針,但是在這裏你將它解引用,就像它是一個指向單個元素的指針 - >只有你的第一個'Student'對象有一個有效的'測試'指針,其他人不會(所以你得到*未定義的行爲*) – UnholySheep

回答

3

一個錯誤是您訪問已刪除對象studentFiles的成員。扭轉線來修復:

delete [] studentFiles->tests;  
delete [] studentFiles; 

理想情況下,使用std::vector<>代替動態分配和釋放手動存儲器。

另請注意,代碼只初始化數組第一個成員的Student::tests,其餘的Student對象具有未初始化的此成員。表達式studentFiles[i].tests[j]的結果未定義,並可能導致崩潰。

您需要初始化每個StudentStudent::tests成員。完成後,取消分配每個StudentStudent::tests

+1

對於'std :: vector'建議+1。使用適當的RAII還有助於確保按照聲明的相反順序正確銷燬對象,就像這裏的問題 – KABoissonneault

+0

似乎沒有解決問題,並且我們只是覆蓋了動態內存分配,所以我不知道如何使用您提供的其他解決方案。 – mobandy644

+1

@ mobandy644添加了關於'Student :: tests'的註釋。 –