C ++ - 读取输入文件并存储和计算统计信息

时间:2015-04-25 20:53:07

标签: c++ arrays struct

当我开始问题时,我早些时候就此主题发布了一个问题。从那以后,我一直致力于源代码并填补了很多空白。我现在遇到了一些麻烦,因为我的源代码存在很多差异和问题。

请忽略评论。我把它们包括在内是为了我个人的利益,因为它们有助于提醒我正在做什么或正在发生什么,特别是当我检查自己的工作时。

首先,它有9个函数原型,分为3组,每组3个方法,但是对于不同的变量,它们做同样的事情。例如,int getFirstLowest(StudentData[]) int getFirstHighest(StudentData[])double getAverage1(StudentData[], int)。我想要一种不同的方法来查找每个考试的最低,最高和最低,以及每个考试的最低,最高和平均值。我的想法是为我需要计算的每个统计数据创建一个大小为3的数组(最低,最高,平均和标准偏差),但我不知道该怎么做。

接下来,我很好奇我是否应该将我的getTotal函数和getGrades函数结合起来以提高效率。 getTotal方法只是将所有考试成绩相加,而getGrades只填充if else语句来对分数进行分类并确定其成绩。

此外,我还需要print函数的一些帮助。我的输出需要看起来与我下面附带的图像类似,但它不是。每个学生的计数结果都是错误的,从0开始,弄乱了我的对齐,这就是我没有包含它的原因。

以下是我的输出应如何显示的图像: enter image description here

这是我当前输出的图像: enter image description here

我在顶部打印了最低,最高和最低的数据,以检查我的计算是否对每个方面都正确,因为我仍然不确定如何将数据放入数组以更顺利地打印出来。另外,请注意两个图像中的一些数据是相同的并且是不同的,因为第一个图像是前一个学期的样本。我的数字在考试专栏中是正确的。

    #include "stdafx.h"
    #include <iostream> 
    #include <string> 
    #include <fstream>
    #include <iomanip> 

    using namespace std; 

    struct StudentData
    {
        int studentID; 
        string first_name; 
        string last_name; 
        int exam1; 
        int exam2; 
        int exam3; 
        int total; 
        char ch; 
    }; 

    istream& operator >> (istream& in, StudentData& st)
    {
        return (in >> st.studentID
                   >> st.first_name
                   >> st.last_name
                   >> st.exam1
                   >> st.exam2
                   >> st.exam3);
    }

    const int SIZE = 9; 

    // Function prototypes
    void openInputFile(ifstream &, string); 
    int getFirstLowest(StudentData[]); 
    int getSecondLowest(StudentData[]); 
    int getThirdLowest(StudentData[]); 
    int getFirstHighest(StudentData[]); 
    int getSecondHighest(StudentData[]); 
    int getThirdHighest(StudentData[]); 
    double getAverage1(StudentData[], int); 
    double getAverage2(StudentData[], int); 
    double getAverage3(StudentData[], int); 
    void getTotal(StudentData arr[]); 
    void getGrade(StudentData arr[]); 
    void print(StudentData[]); 

    int main()
    {
        // Variables
        //standardDeviation;  
        StudentData arr[SIZE]; 
        int x, y, z, w; // Stores lowest exam scores
        int i, j, k, l; // Holds highest exam scores
        double average1, average2, average3, average4; // Represents average of each exam 

    int lowest[3]; 
    int highest[3]; 
    double average[3]; 

    ifstream inFile; 
    string inFileName = "C:\\Users\\Lisa\\Desktop\\scores.txt"; 

    // Call function to read data in file
    openInputFile(inFile, inFileName);

    // Read data into an array of structs 
    size_t numItems = 0;
    while (inFile >> arr[numItems])
    {
        ++numItems;
    }

    // Close input file
    inFile.close();  

    // Get lowest exam scores from each exam
    x = getFirstLowest(arr); 
    y = getSecondLowest(arr); 
    z = getThirdLowest(arr); 

    // Get highest exam scores from each exam 
    i = getFirstHighest(arr); 
    j = getSecondHighest(arr); 
    k = getThirdHighest(arr); 

    cout << "\nLowest exam scores (in order): " << x << " " << y << " " << z << endl; 
    cout << "\nHighest exam scores (in order): " << i << " " << j << " " << k << endl; 

    cout << "\n"; 

    // Get average score of each exam 
    average1 = getAverage1(arr, SIZE); 
    average2 = getAverage2(arr, SIZE); 
    average3 = getAverage3(arr, SIZE); 

    cout << "Exam 1 Average: " << setprecision(2) << fixed << average1 << endl; 
    cout << "Exam 2 Average: " << setprecision(2) << fixed << average2 << endl; 
    cout << "Exam 3 Average: " << setprecision(2) << fixed << average3 << endl; 

    cout << "\n"; 

    getTotal(arr); 

    getGrade(arr); 

    print(arr); 

    system("PAUSE"); 

    return 0; 
}

/**
* Pre-condition: 
* Post-condition: 
*/
void openInputFile(ifstream &inFile, string inFileName)
{
    //Open the file
    inFile.open(inFileName);

    //Input validation
    if (!inFile)
    {
        cout << "Error to open file." << endl;
        cout << endl;
        return;
    }
}

/**
* Pre-condition: 
* Post-condition: 
*/
int getFirstLowest(StudentData arr[])
{
    int lowest = 0; 
    int num = arr[0].exam1; 

    for (int i = 0; i<SIZE; i++)
    {
        if (num > arr[i].exam1)
        {
            num = arr[i].exam1; 
            lowest = i; 
        }
    }
    return num;
}

/**
* Pre-condition: 
* Post-condition: 
*/
int getSecondLowest(StudentData arr[])
{
    int lowest = 0; 
    int num = arr[0].exam2; 

    for (int i = 0; i<SIZE; i++)
    {
        if (num > arr[i].exam2)
        {
            num = arr[i].exam2; 
            lowest = i; 
        }
    }
    return num;
}

/**
* Pre-condition: 
* Post-condition: 
*/
int getThirdLowest(StudentData arr[])
{
    int lowest = 0; 
    int num = arr[0].exam3; 

    for (int i = 0; i<SIZE; i++)
    {
        if (num > arr[i].exam3)
        {
            num = arr[i].exam3; 
            lowest = i; 
        }
    }
    return num;
}

/**
* Pre-condition: 
* Post-condition: 
*/
int getFirstHighest(StudentData arr[])
{
    int highest = 0; 
    int num = arr[0].exam1; 

    for (int i = 0; i<SIZE; i++)
    {
        if (num < arr[i].exam1)
        {
            num = arr[i].exam1; 
            highest = i; 
        }
    }
    return num;
}

/**
* Pre-condition: 
* Post-condition: 
*/
int getSecondHighest(StudentData arr[])
{
    int highest = 0; 
    int num = arr[0].exam2; 

    for (int i = 0; i<SIZE; i++)
    {
        if (num < arr[i].exam2)
        {
            num = arr[i].exam2; 
            highest = i; 
        }
    }
    return num;
}

/**
* Pre-condition: 
* Post-condition: 
*/
int getThirdHighest(StudentData arr[])
{
    int highest = 0; 
    int num = arr[0].exam3; 

    for (int i = 0; i<SIZE; i++)
    {
        if (num < arr[i].exam3)
        {
            num = arr[i].exam3; 
            highest = i; 
        }
    }
    return num;
}

/**
* Pre-condition: 
* Post-condition: 
*/
double getAverage1(StudentData arr[], int size)
{
    int sum = 0; 
    double average = 0; 

    for(int i = 0; i < SIZE; i++)
    {
        sum += arr[i].exam1; 
    }

    average += static_cast<double>(sum)/size; 

    return average; 
}

/**
* Pre-condition: 
* Post-condition: 
*/
double getAverage2(StudentData arr[], int size)
{
    int sum = 0; 
    double average = 0; 

    for(int i = 0; i < SIZE; i++)
    {
        sum += arr[i].exam2; 
    }

    average += static_cast<double>(sum)/size; 

    return average; 
}

/**
* Pre-condition: 
* Post-condition: 
*/
double getAverage3(StudentData arr[], int size)
{
    int sum = 0; 
    double average = 0; 

    for(int i = 0; i < SIZE; i++)
    {
        sum += arr[i].exam3; 
    }

    average += static_cast<double>(sum)/size; 

    return average; 
}

/**
* Pre-condition: 
* Post-condition: 
*/
void getTotal(StudentData arr[])
{
    for(int i = 0; i < SIZE; i++)
    {
        arr[i].total = arr[i].exam1 + arr[i].exam2 + arr[i].exam3; 
    }
}

/**
* Pre-condition: 
* Post-condition: 
*/
void getGrade(StudentData arr[])
{
    for(int i = 0; i < SIZE; i++)
    {
        if(arr[i].total >= 270)
            arr[i].ch = 'A'; 
        else if(arr[i].total >= 240)
            arr[i].ch = 'B'; 
        else if(arr[i].total >= 210)
            arr[i].ch = 'C'; 
        else if(arr[i].total >= 180)
            arr[i].ch = 'D'; 
        else 
            arr[i].ch = 'F'; 
    }
}

/**
* Pre-condition: 
* Post-condition: 
*/
void print(StudentData arr[])
{
    cout << "ID First Name  Last Name   Exam1   Exam2   Exam3   Total   Grade" << endl; 
    for(int i = 0; i < SIZE; i++)
    {
        cout << left << arr[i].studentID << "\t" << setw(10) <<  arr[i].first_name << "\t" << setw(5) << arr[i].last_name << "\t\t" 
             << arr[i].exam1 << "\t" << arr[i].exam2 << "\t" << arr[i].exam3 << "\t" << arr[i].total << "\t" << arr[i].ch << endl; 
    }
}

1 个答案:

答案 0 :(得分:1)

  

首先,它有9个函数原型,分为3组,每组有3个方法,每个方法对不同的变量做同样的事情。

这不是非常可扩展的(即,因为所涉及的所有工作,意味着代码改变,当新的考试分数和/或学生被添加时)。也许你已经知道了这一点,因为你做了以下陈述。

  

我想要一种不同的方法来查找每项考试的最低,最高和最低,以及每项考试的最低,最高和平均值。

由于这是一项学习任务,我可以向您展示我的输出,主要和我的骨架实现。如果它看起来像你想要做的那样,那么你可以完成骨架代码的实现。 注意,我没有尝试确保格式化,因为它应该足够容易。

我的输出

1234            David           Dalton          82              86              80              248
9138            Shirley         Gross           90              98              94              282
3124            Cynthia         Morley          87              84              82              253
4532            Albert          Roberts         56              89              78              223
5678            Amelia          Pauls           90              87              65              242
6134            Samson          Smith           29              65              33              127
7874            Michael         Garett          91              92              92              275
8026            Melissa         Downey          74              75              89              238
9893            Gabe            Yu              69              66              68              203

                                Lowest:         29              65              33              127
                                Higest:         91              98              94              283
                                Avg:            74.2222         82.4444         75.6667         232.333

我的主要

实施非常直接/简单。

int main()
{
    Students students;
    Exams exams;

    // Read data from file and populate all student and exam data structures
    if (!initialize(students, exams))
    {
        return -1;
    }

    // Compute all the exam statistics
    exams.computeStatistics();

    // Print all the student information
    for (const auto& student : students)
    {
        std::cout << student << "\n";
    }

    // Print the exam information
    std::cout << "\n";
    std::cout << exams << "\n";

    return 0;
}

骨架代码

以下是我使用的代码的框架,可能对您有所帮助。

// A class to represent a single exam
class Exam
{
public:
    // Computes min, max, and avg (later can be extended to compute
    // additional statistics)
    void computeStatistics()
    {
        // TODO
    }

    int min() const { return mMin; }
    int max() const { return mMax; }
    double avg() const { return mAvg; }

    // Adds a score earned by a student (i.e., keeps track of all scores
    // which are used by the 'computeStatistics' function)
    void addScore(int score)
    {
        // TODO
    }

private:
    std::vector<int> mScores; // All scores for this exam

    // Values computed for all available scores
    int mMin;
    int mMax;
    double mAvg;
};

// A class to represent all exams (this is helpful since there are some
// statistics that need to be computed for all exams)
class Exams
{
public:
    // Get the exam associated with the specified exam numer
    Exam& operator[](std::size_t examNumber)
    {
        return mExams[examNumber];
    }

    // Compute min total, max total, average average, store all exam min
    // scores, store all exam max scores, store all exam avg scores
    void computeStatistics()
    {
        // TODO
    }

    // Prints the exam information (e.g., Lowest, Highest, Average)
    friend std::ostream& operator<<(std::ostream& stream, const Exams& exams)
    {
        // TODO
    }

private:
    // Mapping from 'exam number' to the exam data type
    std::map<int, Exam> mExams;

    // Stores all min, max, and avg exam scores (for printing later)
    std::vector<int> mMinScores;
    std::vector<int> mMaxScores;
    std::vector<double> mAvgScores;

    // Values computed for all available exams
    int mMinTotal;
    int mMaxTotal;
    double mAvgAvg;
};

// Class to represent a student
class Student
{
public:
    Student() :
        mTotalScore(0)
    {
        // Do nothing
    }

    // Records a student's score on a particular exam (this is also used
    // to keep a running total of all exam scores for this student, which
    // can be printed later)
    void addScore(int examNumber, int score)
    {
        // TODO
    }

    // Each exam score for this student is added to 'exams'
    void updateExams(Exams& exams) const
    {
        // TODO
    }

    int mId;
    std::string mFirstName;
    std::string mLastName;

    // Mapping from 'exam number' to exam score
    std::map<int, int> mExams;
    int mTotalScore; // Total of all exam scores for this student
};

// Reads a student from a stream (hint: uses the 'addScore' function)
std::istream& operator>>(std::istream& stream, Student& student)
{
    // TODO
}

// Prints out a student (i.e., id, fist, last, exam1, exam2, exam3, examTotal)
std::ostream& operator<<(std::ostream& stream, const Student& student)
{
    // TODO
}

// Just an alias so that you don't have to type 'std::vector<Student>' all over
using Students = std::vector<Student>;

// Reads all the data from the text file and adds each student to 'students'
// and each exam to 'exams' (hint: after each student is read it can be
// used to update all the exams)
bool initialize(Students& students, Exams& exams)
{
    // TODO
}