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

标签 c++ arrays struct

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

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

首先,它有 9 个函数原型(prototype),分为 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; 
    }
}

最佳答案

First, it has 9 function prototypes that are categorized into 3 groups with 3 methods each that do the same thing but for different variables.

这不是很可扩展(即,因为涉及所有工作,意味着代码更改,当添加新的考试成绩和/或学生时)。也许您在发表以下声明后就已经意识到这一点。

I want a different method to find the lowest, highest and average of each exam and the lowest, highest and average value of the totals of each.


由于这是一项学习任务,我可以向您展示我的输出、我的主要实现和我的框架实现。如果它看起来像您正在尝试做的事情,那么您可以完成框架代码的实现。 请注意,我没有尝试获取准确的格式,因为它对您来说应该足够简单。

我的输出

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
}

关于C++ - 读取输入文件并存储和计算统计数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29870594/

相关文章:

c++ - C++ : 中用于 GUI 的 WXwidgets

c++ - 调用从另一个函数 c++ 定义的函数

c++ - 有没有办法在 QScriptEngine#pushContext/popContext 之外维护 Qt 脚本上下文环境?

arrays - 比较matlab中的细胞

c - 尝试使用调用 stat 的 ctime 返回值对 c 中的结构数组进行排序

使用 vector 的 C++ 3D 数组声明

javascript - 在 JavaScript 中交换对象内的键

C - 从数组中删除数字,不会删除相同数字的多个实例,仅删除一个

c - 通过引用传递并将值赋给结构指针的指针

c - 结构内存分配方式