Sorry if this seems dumb, I am pretty new to C++ and I'm having trouble displaying information read into an array of structures from an input file.
I have 3 functions. One for reading my file into the array, one for prompting the user to search for a specific struct in the array, and the last one for displaying the contents of the array.
I don't know for certain if my readFile()
or displayAllStudents()
is broken. I am able to output the first line from the file, but the rest is 0. Next my selectStudent()
is probably terrible; I'm having trouble finding a good solution for what I'm trying to accomplish.
I've tried many solutions posted here, but my issue seems unique so I'm hoping I can help pointed in the right direction.
Input file and desired output.
ID CLA OLA Quiz Homework Exam Bonus Total FinalGrade
c088801 10 15 4 15 56 5
c088802 9 12 2 11 46 2
c088803 8 10 3 12 50 1
c088804 5 5 3 10 53 3
c088805 3 11 1 10 45 0
c088806 8 14 2 11 40 -1
c088807 4 12 2 12 48 -2
c088808 10 10 3 11 36 0
c088809 8 8 3 11 39 0
c088810 6 9 4 9 47 3
c088811 8 7 3 13 41 3
c088812 4 11 3 11 37 1
c088813 9 15 2 8 50 2
c088814 8 12 2 10 48 4
c088815 6 8 1 7 45 1
c088816 7 7 2 6 51 2
c088817 8 9 2 12 38 2
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
struct Student {
char ID[7];
int CLA;
int OLA;
int Quiz;
int Homework;
int Exam;
int Bonus;
int Total;
int FinalGrade;
};
const int SIZE = 20;
//Function prototypes
void readFile(Student[]);
int selectStudent(Student[]);
void displayAllStudents(Student[]);
int main() {
Student Roster[SIZE] = {}; //Initalizes array
readFile(Roster);
//selectStudent(Roster);
displayAllStudents(Roster);
system("pause");
return 0;
}
//This function will read the text file into our array of structures.
void readFile(Student Roster[]) {
ifstream inFile("point.dat"); //Reads input file
string line;
getline(inFile, line); //Skips first line of file
for (int i = 0; i < SIZE; i++) {
inFile >> Roster[i].ID >> Roster[i].CLA >> Roster[i].OLA >>
Roster[i].Quiz >> Roster[i].Homework >> Roster[i].Exam >>
Roster[i].Bonus >> Roster[i].Total >> Roster[i].FinalGrade;
}
}
//This function will prompt user to select an individual student ID
//then display that student's information.
int selectStudent(Student Roster[]) {
char* cNumber;
cout << "Please enter the student's c-number:" << endl;
cin >> cNumber;
for(int i; i < SIZE; i++){
if(strcmp(Roster[i].ID, cNumber)==0){
return i;
}
}
return -1;
}
//This function will display all our student information
void displayAllStudents(Student Roster[]) {
cout << " ID CLA OLA Quiz Homework Exam Bonus Total FinalGrade" << endl;
for (int i = 0; i < SIZE; i++) {
cout << Roster[i].ID[0] << Roster[i].ID[1] << Roster[i].ID[2] << Roster[i].ID[3] << Roster[i].ID[4] << Roster[i].ID[5] << Roster[i].ID[6]
<< " " << Roster[i].CLA << " " << Roster[i].OLA << " " << Roster[i].Quiz << " " <<
Roster[i].Homework << " " << Roster[i].Exam << " " << Roster[i].Bonus << " " <<
Roster[i].Total << " " << Roster[i].FinalGrade << endl;
}
}
My output.
ID CLA OLA Quiz Homework Exam Bonus Total FinalGrade
c088801 10 15 4 15 56 5 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
Press any key to continue . . .
In
readFile
, when you're reading the contents of your file here, you've assumed that all fields for every Student struct contain data.Since your input doesn't have content in the
Total
andFinalGrade
columns, when your program hits>> Roster[i].Total
for the first time it's actually trying to read the second student's id, c088802, which isn't the integer value expected byRoster[i].Total
.If you know your input data will never have content in the
Total
andFinalGrade
columns, you can remove>> Roster[i].Total >> Roster[i].FinalGrade
from your file read loop.If you know your input data might not be complete, but don't know how much of the row will be filled, something like this should work, though there's likely a better way.
IMHO, you should change your perspective and have the object read its members from the stream:
You can then read in the data with a simple loop:
I've made two subtle changes here: 1) Use of
std::string
for the ID and 2) Usingstd::vector
instead of an array.The
std::vector
is an excellent data structure to use when reading from files, as it expands as necessary. With an array, you will have to keep checking for overflow and reallocating as necessary to accommodate new items.I believe your issue is using
operator>>
with a character array. There is no method to limit the input to the size of your array. You may want to increase your array by 1 to allow for the terminating nul character (which may be appended byoperator>>
). The C-style strings (arrays of characters) are terminated by a nul character so you will always need that extra array slot.I fully agree with the statements from Thomas Matthews.
Additionally I would like to show a full example.
I packed all the student data and methods in one
struct Student
. All the integer data are stored in onestd::vector
and can be accessed via an index. This makes life easier.Then we overload the extractor operator. With that, we can easily read the complete data for one student. For debug purposes, we overload also the inserter.
Please note: With that, reading of all student data into a vector is an one-liner, by simply using the vectors range constructor.
Also the output of all data is an ultra simple one-liner.
For the fun of it, I added also
the printSelectedStudendData
function.Please see:
I hope this helps . . .