๐ŸŽ“ A1Learner
๐Ÿ”
0 of 34 lessons completed

C++ Project: Gradebook Report

A gradebook report lists each student with the average of two scores. The report also gives the class average and names the top student.

Reading the class into a vector

The loop reads a name and two scores from each line of grades.txt. Each set of values becomes a Student in the vector, and the loop prints each average.

#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
#include <vector>

class Student {
public:
  std::string name;
  int first;
  int second;
  double average() const {
    return (first + second) / 2.0;
  }
};

int main() {
  std::ifstream in("grades.txt");
  std::string name;
  int first;
  int second;
  std::vector<Student> students;
  while (in >> name >> first >> second) {
    Student student;
    student.name = name;
    student.first = first;
    student.second = second;
    students.push_back(student);
  }
  std::cout << std::fixed << std::setprecision(1);
  for (Student student : students) {
    std::cout << student.name << " " << student.average() << "\n";
  }
  return 0;
}

Sorting by average

The sort call takes a lambda that compares two students by average. The table prints the highest average first, with each name padded to the same width.

#include <iostream>
#include <algorithm>
#include <fstream>
#include <iomanip>
#include <string>
#include <vector>

class Student {
public:
  std::string name;
  int first;
  int second;
  double average() const {
    return (first + second) / 2.0;
  }
};

int main() {
  std::ifstream in("grades.txt");
  std::string name;
  int first;
  int second;
  std::vector<Student> students;
  while (in >> name >> first >> second) {
    Student student;
    student.name = name;
    student.first = first;
    student.second = second;
    students.push_back(student);
  }
  std::sort(students.begin(), students.end(), [](const Student& left, const Student& right) {
    return left.average() > right.average();
  });
  std::cout << std::fixed << std::setprecision(1);
  for (Student student : students) {
    std::cout << std::left << std::setw(8) << student.name << student.average() << "\n";
  }
  return 0;
}

Writing the class average to a report

The program adds the averages and divides by the number of students. It writes the class average line to report.txt, reads the line back, and prints it.

#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
#include <vector>

class Student {
public:
  std::string name;
  int first;
  int second;
  double average() const {
    return (first + second) / 2.0;
  }
};

int main() {
  std::ifstream in("grades.txt");
  std::string name;
  int first;
  int second;
  std::vector<Student> students;
  while (in >> name >> first >> second) {
    Student student;
    student.name = name;
    student.first = first;
    student.second = second;
    students.push_back(student);
  }
  double total = 0;
  for (Student student : students) {
    total += student.average();
  }
  double classAverage = total / students.size();
  std::ofstream report("report.txt");
  report << "Class average: " << std::fixed << std::setprecision(1) << classAverage << "\n";
  report.close();
  std::ifstream reportIn("report.txt");
  std::string line;
  std::getline(reportIn, line);
  std::cout << line << "\n";
  return 0;
}

Example

#include <iostream>
#include <algorithm>
#include <fstream>
#include <iomanip>
#include <string>
#include <vector>

class Student {
public:
  std::string name;
  int first;
  int second;
  double average() const {
    return (first + second) / 2.0;
  }
};

int main() {
  std::ifstream in("grades.txt");
  std::string name;
  int first;
  int second;
  std::vector<Student> students;
  while (in >> name >> first >> second) {
    Student student;
    student.name = name;
    student.first = first;
    student.second = second;
    students.push_back(student);
  }
  std::sort(students.begin(), students.end(), [](const Student& left, const Student& right) {
    return left.average() > right.average();
  });
  std::cout << std::fixed << std::setprecision(1);
  for (Student student : students) {
    std::cout << std::left << std::setw(8) << student.name << student.average() << "\n";
  }
  double total = 0;
  for (Student student : students) {
    total += student.average();
  }
  double classAverage = total / students.size();
  std::ofstream report("report.txt");
  report << "Class average: " << std::fixed << std::setprecision(1) << classAverage << "\n";
  report.close();
  std::ifstream reportIn("report.txt");
  std::string line;
  std::getline(reportIn, line);
  std::cout << line << "\n";
  std::cout << "Top student: " << students[0].name << "\n";
  return 0;
}

Key points

  • The Student class holds a name and two scores for one student.
  • The average method of Student returns the mean of its two scores.
  • A std::vector<Student> holds one Student for each line of the file.
  • std::sort with a lambda orders the students by average from high to low.
  • std::setw pads each name so the averages line up in a column.
  • std::fixed with std::setprecision(1) prints each average with one decimal place.
  • The first student after the sort is the top student.

In this example, the program reads grades.txt into a vector of Student values and sorts the vector by average. The table prints each name with its average in the sorted order. The program then writes the class average line to report.txt, reads that line back and prints it, and prints Mina as the top student.

Note

Every tool in this project came from an earlier lesson of this course.

Try it Yourself

Edit the code, then press Run.

Running is simulated

Exercise

After the sort in the gradebook program, where does the top student sit in the vector?