2017-07-06 9 views
-1

私は、名前、ID番号、一定の学生数のテストスコアの配列を格納する構造体の配列を使用してプログラムを作成しています。構造の配列とテストスコアの配列の両方を動的に割り当てる必要があります。私は、ユーザーが各生徒のテスト得点を入力できるようにする関数に落としましたが、最後の関数(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つの試験を入力すると、最初の生徒の最初の2つの試験のスコアを通過します。 2番目の生徒のテストスコアを入力すると、スコアを入力してEnterを押すとクラッシュします。それがLinuxが私にセグメンテーション違反を与えたところです。 – mobandy644

+1

'studentFiles-> tests = getTests(numTests);' - 'studentFiles'はあなたのコード中の配列へのポインタですが、ここではそれは単一の要素へのポインタであるように逆参照します - >最初の' Student'オブジェクトは有効な 'tests'ポインタを持っていますが、他のポインタは一つもありません。(*未定義の動作*を取得します) – UnholySheep

答えて

3

削除されたオブジェクトstudentFilesのメンバーにアクセスすると、1つのエラーが発生します。それを修正する行を逆:

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

理想的には、動的に割り当てて、手動でメモリを解放するのではなく、std::vector<>を使用します。

また、コードではアレイの最初のメンバのStudent::testsのみが初期化され、Studentの残りのオブジェクトはこのメンバが初期化されていません。式studentFiles[i].tests[j]の結果は定義されておらず、クラッシュする可能性があります。

のメンバーをStudent::testsに初期化する必要があります。そして完了したら、それぞれStudentStudent::testsを割り当て解除します。

+1

+1の 'std :: vector'の提案です。適切なRAIIを使用すると、オブジェクトが宣言の逆順で正しく破棄されるようになります。 – KABoissonneault

+0

これは問題を解決したようではなく、動的メモリ割り当てをカバーしているだけなので、あなたがまだ提供している他のソリューションを使用してください。 – mobandy644

+1

@ mobandy644 'Student :: tests'に関する注釈を追加しました。 –

関連する問題