0

私は、配列、ポインター、構造体、逆参照に関する問題に取り組んでいる学生です。それぞれの意味とそれぞれの一般的な初期化については理解していますが、プログラムでまだ適切に使用していないように感じます。私が持っているものは問題なく動作しますが、これらを使用するためのより良い方法があるかどうか知りたいですか??

プログラムの一般的な要件は次のとおりですStudentData[i].testArray

1 - 構造体を使用して、次のデータを格納します: 名前、ID#、テスト (テスト スコアの配列へのポインター)、平均、文字の成績。

struct StudentData {...};

2 - 生徒数とテスト数を尋ねる (各生徒に同じ)

3 - 構造体の配列を動的に割り当てる

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

4 - 各構造体の Tests メンバーは、動的に割り当てられたテスト スコアの配列を指す必要があります。

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

2 に答える 2

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

//これも for ループで削除する必要がありますか??

はい、または少なくとも、すべての Student の testsArray を削除するように何らかの方法で手配する必要があります。

于 2013-08-27T15:57:16.820 に答える
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;

彼らが持っているすべてのテストも削除されます。

于 2013-08-27T15:46:45.930 に答える