How do I read one column from a text file

My professor wants us to make a program that averages and sorts grades from students. But the way he wants it organized is very confusing to me. He requires the .txt file to read

410012 092 063 066 095 078 100 073 067 100 100 070.12
299500 059 048 054 080 073 039 010 042 100 087 093.14
147710 100 018 100 100 065 085 098 071 059 078 075.23
285300 068 063 069 081 081 010 100 087 097 068 070.87
288004 075 090 089 096 056 068 059 079 067 060 076.38
196290 063 060 100 093 059 049 073 069 065 084 081.29
161180 020 100 082 048 100 046 074 056 100 069 023.50
262400 095 062 058 066 100 050 082 059 066 091 093.02
403100 060 068 011 084 054 069 034 100 075 090 056.55
149458 089 080 097 060 092 100 062 068 065 082 072.93
141000 063 069 051 053 100 068 040 036 060 051 100.90
273480 100 098 100 082 047 000 019 066 069 069 037.82
241008 056 089 024 071 066 100 095 071 076 094 087.63
227987 075 062 055 058 081 074 081 031 051 030 071.95
744800 063 067 066 051 098 073 076 097 051 070 067.49
603800 060 090 074 079 100 100 100 095 100 081 026.28
236200 048 094 071 074 070 059 014 054 079 051 093.33
278920 060 050 053 026 025 052 067 089 073 067 097.83
241820 051 067 078 071 059 098 100 041 021 100 085.58
214500 052 034 082 074 095 075 090 054 037 080 062.92
254900 087 100 100 081 100 032 051 070 080 100 081.55
313160 051 100 100 043 060 100 100 090 054 018 100.00
231006 069 074 041 100 050 071 021 055 051 055 052.97
172535 100 065 073 047 051 065 083 044 070 021 100.04
102023 036 066 044 093 100 073 100 060 100 059 070.32
177738 080 017 026 085 069 031 084 073 076 048 040.44
110232 074 065 070 100 068 087 068 056 065 084 081.51
191877 083 056 100 071 072 092 100 098 100 094 046.09
269500 054 070 021 066 054 056 065 086 056 046 056.00

The columns correspond with the test/lab/exam
column 1 is the student ID, column 2 is Exam01, column 3 is Exam02, column 4 is Exam03, column 5 is Exam04, column 6 is Final, column 7 is Lab01, column 8 is Lab02, column 9 is Lab03, column 10 is Lab04, column 11 is Lab05, column 12 is Average grade of quizzes

the problem is that each column means something different and I cant figure out how to group every column to average and sort them.

Any help would be appreciated
Last edited on
So are there any "weights" for any of the fields. For example do "regular" exams affect the grade the same as the Final exam? Do the labs affect the grade the same as exams, etc?

Perhaps you should consider posting the actual assignment so we can offer more relevant advice.

But the first thing I would do is create a structure/class to hold the information for each student. Something like:

1
2
3
4
5
6
7
8
9
struct Student
{
   std::string id;
   std::vector<int> exams;
   int final;
   std::vector<int> labs;
   double average_quiz;
};


You need to be careful when reading your file, numbers like 056 denote Octal base, not Decimal. If you have control of the file I would remove all of those leading zeros to make things simpler.

Also I wouldn't be surprised that you are being asked to sort the Students based on their grade.

Here is the assignment
Design and develop a C++program for reporting grades for a class. Your program should read in an input file of student grades records,and it should produce an output file of student grades records plus a report (output to monitor) of grade distributions. Your program would read in the records from the file one record at a time (sequentially) and output one record at a time to the output file, it update an array of grades. After building the array of grades, then it processes the array to print the grade distributions histogram. The program will also build array each student score in the class and then sort it (use bubble sort) then out put the LOWEST SCORE IN CLASS, HIGHEST SCORE IN CLASS, and NUMBER OF STUDENTS.

There are no weights, he only wants us to put the lowest score in the class for each Exam/Final/Lab/Average quiz grade. He wants the output to look like this, the 999's are just placeholders

OUTPUT DESIGN:______________________________________
A ( 90 –100)*************
B( 80 –89)********************
C( 70 –79) ************************
D( 60–69) **************
F( 00 –59)********

LOWEST SCORE IN CLASS : 99
HIGHEST SCORE IN CLASS: 999
NUMBER OF STUDENTS:999

EXAM01 AVERAGE: 999.99
EXAM02 AVERAGE: 999.99
EXAM03 AVERAGE: 999.99
EXAM04 AVERAGE: 999.99

FINAL AVERAGE: 999.99

LABS AVERAGE: 999.99

QUIZZES AVERAGE: 999.99
Here is a start to manipulating the data you are given in the text file.
Put the various numbers into an array or better still <vector> and work on that.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <iostream>
#include <fstream>
#include <string>

int main ()
{
    std::string line;
    std::ifstream myfile ("test_scores.txt");
    
    const int NO_STUDENTS = 100;
    int ID[NO_STUDENTS]{0};
    int score[NO_STUDENTS][10]{0};
    double average[NO_STUDENTS]{0};
    
    int class_size = 0;
    
    if (myfile.is_open())
    {
        while ( myfile >> ID[class_size] )
        {
            std::cout << class_size << '\t' << ID[class_size] << ' ';
            
            for(int count = 0; count < 10; ++count)
            {
                myfile >> score[class_size][count];
                std::cout << score[class_size][count] << ' ';
            }
            
            myfile >> average[class_size];
            std::cout << average[class_size] << '\n';
            
            class_size++;
        }
        std::cout << "Actual number of students: " << class_size << '\n';
        
        myfile.close();
    }
    
    else std::cout << "Unable to open file";
    
    return 0;
}
text mode, you have to read and discard unwanted data.
binary mode lets you jump around, if you know where to go. if your file will always be in the format given, everything is fixed positions, you could do this, but it is more complicated than read/discard.
it looks like (pseudo code)
while(position in range) //you probably need to fetch the size of the file in bytes up front
seek(position)
position += some_constant;
read

and if the file format changes at all, it will not work, and if the file has stray endings, like extra spaces or extra end of lines at the end, it will not work.

I don't actually recommend doing this today, but keep in the back of your head that it is possible. It is also not useful here: you are not really reading just 1 column, you want them all. If you really just wanted to average the third column, though, it would be a reasonable approach.
Last edited on
out put the LOWEST SCORE IN CLASS, HIGHEST SCORE IN CLASS, and NUMBER OF STUDENTS.
What is a student's score? Is that the final (column 6)? Or is "final" the score for the final exam and the class score is some combination of all the other values?

To solve this, I created a class that represents a student. I stored each student's info in one of these and I also used a separate instance, called "total" to store the accumulated total of all the students. After reading all the data, I divided the values in "total" by the number of students to convert it to the averages. Here is the code. I've removed much of the code. My hope is that you can use this to help structure your solution:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>

using std::istream;
using std::ostream;
using std::string;
using std::cin;
using std::cout;
using std::vector;
using std::sort;

class Student {
public:
    int id = {};
    static constexpr int NumExams=4;
    int exams[NumExams] = {};
    int final{};
    static constexpr int NumLabs=5;
    int labs[NumLabs] = {};
    double quizAvg{};

    void read(istream &is);
    bool operator < (const Student &rhs) const {
	return final < rhs.final;
    }
    void write(ostream &os);
};

void Student::read(istream &is)
{
    // YOU MUST WRITE THIS
}

void Student::write(ostream &os)
{
    // YOU MUST WRITE THIS
    
}

// Add the data in "from" into "to"
void accumulate(Student &from, Student &to)
{
    // YOU MUST WRITE THIS
}


// Given a student record and the number of students it represents,
// divide all grades by the number of students to convert them to an
// average
void averages(Student &st, int n)
{
    // YOU MUST WRITE THIS
}

// Print one line of the histogram for grades between
// low and high (inclusive)
void printHistogram(const vector<Student> &students,
		    char grade, int low, int high)
{
    // YOU MUST WRITE THIS
}


// Calculate and return the average of "arr" which has
// "size" elements
int calcAvg(int arr[], int size)
{
    // YOU MUST WRITE THIS

int main()
{
    vector<Student> students;
    Student st;
    Student total;		// a dummy record to accumulate the totals
    while (st.read(cin), cin) {
	students.push_back(st);
	accumulate(st, total);
	st.write(cout);
    }
    averages(total, students.size());
    sort(students.begin(), students.end());
    printHistogram(students, 'A', 90, 100);
    printHistogram(students, 'B', 80, 89);
    printHistogram(students, 'C', 70, 79);
    printHistogram(students, 'D', 60, 69);
    printHistogram(students, 'F',  0, 59);

    cout << "LOWEST SCORE IN CLASS: " << students[0].final << '\n';
    cout << "HIGHEST SCORE IN CLASS: " << students.back().final << '\n';
    cout << "NUMBER OF STUDENTS: " << students.size() << '\n';
    cout << '\n';
    for (int i=0; i<Student::NumExams; ++i) {
	cout << "EXAM0" << i << " AVERAGE: " << total.exams[i] << '\n';
    }
    cout << '\n';
    cout << "FINAL AVERAGE: " << total.final << '\n';
    cout << '\n';
    cout << "LABS AVERAGE: " << calcAvg(total.labs, total.NumLabs) << '\n';
    cout << '\n';
    cout << "QUIZZES AVERAGE: " << total.quizAvg << '\n';
}


Here is the output I get (assuming that the "final" column represents the final class grade.
A ( 90 - 100)*********
B ( 80 - 89)**
C ( 70 - 79)****
D ( 60 - 69)*****
F ( 0 - 59)*********
LOWEST SCORE IN CLASS: 25
HIGHEST SCORE IN CLASS: 100
NUMBER OF STUDENTS: 29

EXAM00 AVERAGE: 68
EXAM01 AVERAGE: 68
EXAM02 AVERAGE: 67
EXAM03 AVERAGE: 73

FINAL AVERAGE: 73

LABS AVERAGE: 68

QUIZZES AVERAGE: 71.5062


Important hint:
Once you have code, run it with just one line of the input file. This will let you check the output. Then try it with two lines and double check.
Topic archived. No new replies allowed.