Here are some of the problems in your code:
Data type of different variables: Your data (say Wesley s012980520 30 3.5
) is of the format string string int float
, which clearly does not match with the types in your struct Students
.
To fix this, simply change your struct to:
struct Student {
string name;
string studentID;
int credits;
float gpa;
} students[SIZE];
Also, high
should be float
(as it stores gpa
).
high
and j
become 0
on each iteration. Move high
above the loop and j
to init-list of the loop, like this:
float high = 0;
for (int i = 0, j = 0; i < count; i++)
index[j] = i;
(first-occurrence) assigns index of student with highest gpa
to index[j]
but prior to this, j = 0
(although the index
array is reset).
The second if
condition (if (students[i].gpa == high)
) inside the loop assigns the index of student with highest gpa
to index[1]
, if the conditional block above it has executed. Make it else if
to prevent redundancy.
Suggestions:
There is a setprecision(2)
, if you have put it display 3.6
as 3.60
then you need to add fixed
before that.
There is no need to traverse whole index
array, you simply need to do that from 0
to count
.
Remove magic number 150
from your code, use the constant you have declared instead.
Put an endline ('\n'
) after printing each Student
object.
Don't use std::endl
to put simple newline characters. Use it only if you also need to flush the stream.
Avoid putting using namespace std;
at top of your code.
Why put "
when '
can do the job ;).
ifstream inputFile
and inputFile.open
can be written in a single line like : ifstream inputFile("...")
.
Corrected Code (doesn't work if name
has spaces in it):
#include <fstream>
#include <iomanip>
#include <iostream>
using namespace std; // <-- (10), remove this yourself
int main() {
ifstream inputFile("lab9input.dat"); // <-- (12)
const int SIZE = 150;
int count = 0;
int index[SIZE] = {}; // <-- (7)
struct Student {
string name;
string studentID; // <-- (1)
int credits;
float gpa; // <-- (1)
} students[SIZE];
while (count < SIZE && inputFile >> students[count].name >>
students[count].studentID >>
students[count].credits >> students[count].gpa)
count++;
cout << "The highest GPA student(s) is(are): \n"; // <-- (9)
float high; // <-- (1), (2)
for (int i = 0, j = 0; i < count; i++) { //<-- (2)
if (students[i].gpa > high) {
high = students[i].gpa;
for (int k = 0; k < 150; k++) index[k] = 0;
j = 0; // <-- (3)
index[j] = i;
} else if (students[i].gpa == high) // <-- (4)
index[++j] = i;
}
for (int i = 0; i < count; i++) // <--(6)
if (index[i] != 0)
cout << students[index[i]].name << ' ' << students[index[i]].studentID
<< ' ' << students[index[i]].credits << ' ' << fixed // <-- (5)
<< setprecision(2) << students[index[i]].gpa << '\n'; // <--(8)
}
Better code to do the same thing:
#include <algorithm>
#include <cctype>
#include <fstream>
#include <iostream>
#include <iterator>
#include <string>
#include <vector>
struct Student {
std::string name, studentID;
int credits;
float gpa;
friend std::ostream &operator<<(std::ostream &, const Student &);
friend std::istream &operator>>(std::istream &, Student &);
};
std::ostream &operator<<(std::ostream &out, const Student &s) {
out << s.name << ' ' << s.studentID << ' ' << s.credits << ' ' << s.gpa
<< '\n';
return out;
}
std::istream &operator>>(std::istream &in, Student &s) {
s.name.clear();
std::string str;
while (in >> str && std::none_of(str.begin(), str.end(), ::isdigit))
s.name += str + ' ';
s.name.pop_back();
s.studentID = str;
in >> s.credits >> s.gpa;
return in;
}
int main() {
std::ifstream is("lab9input.dat");
std::vector<Student> v(std::istream_iterator<Student>(is), {});
auto max_gpa = std::max_element(v.begin(), v.end(), [](auto &a, auto &b) {
return b.gpa > a.gpa;
})->gpa;
std::cout << "The highest GPA student(s) is(are): \n";
for (auto &i : v) if (i.gpa == max_gpa) std::cout << i;
}