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. ";
    }

这是我在 Stack 上的第一篇文章,如果出现在错误的地方或需要家庭作业,我很抱歉,我不只是在寻找一个简单的答案。我是一名新开发人员,渴望学习。这个话题只是我在处理时遇到了很多麻烦。

4

2 回答 2

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 回答
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循环删除吗?

是的,或者至少您需要以某种方式安排删除每个学生的测试数组。

于 2013-08-27T15:57:16.820 回答