Garbage data when running this program (Student record program) - c++

First off this is my own code, not copied.
The program is supposed to read student data from a "grades.txt" file which has marks for quizzes, finals etc and calculate the average, assign grades, and write the names and grades students who have passed and failed to "pass.txt" and "fail.txt".
Now the issue I face is that the total amount of students is 57. The program does stuff correctly for up to 39 students but it's always garbage values after that :(
#include <iostream>
#include <string>
#include <cmath>
#include <fstream>
#include <cstdlib>
using namespace std;
int counter; //counts the number of students
struct STUDENT
{
string firstname;
string lastname;
long idnumber;
int quiz1; //10%
int quiz2; //10%
int mid1; //15%
int mid2; //15%
double homework; //10%
double Final; //40%
double average; //to be calculated
char grade; //to be calculated
};
void Stcounter()
{
ifstream thing ("Grades.txt");
string dummy;
getline(thing,dummy); //for skipping the first line
string line;
int b=0;
while(getline(thing, line))
b++;
counter=b;
cout<<"Total number of students is "<< counter<<endl;
}
void read( STUDENT record[57])
{
float a;
ifstream thing("Grades.txt");
string d;
getline(thing,d);
for(int i=0;i<56;i++)
{
if( thing>> record[i].idnumber>>record[i].firstname>>record[i].lastname>>record[i].quiz1>>record[i].quiz2>>record[i].mid1>>record[i].mid2>>record[i].homework>>record[i].Final)
a=(record[i].quiz1/10)+(record[i].quiz2/10)+((record[i].mid1*15)/100)+((record[i].mid2*15)/100)+(record[i].homework/10)+((record[i].Final*40)/100);
record[i].average=a;
if(a>=85)
{
record[i].grade='A';
}
else if(a>=70)
{
record[i].grade='B';
}
else if(a>=55)
{
record[i].grade='C';
}
else if(a>=40)
{
record[i].grade='D';
}
else
{
record[i].grade='F';
}
}
}
void WriteToFile (STUDENT record[57])
{
ofstream p, f;
p.open("Pass.txt");
f.open("Fail.txt");
for (int i = 0; i <= 56; i++)
{
if (record[i].average >= 40)
{
p << record[i].idnumber << " " << record[i].firstname << " " << record[i].lastname << " passed with grade " << record[i].grade <<endl;
}
else
f << record[i].idnumber << " " << record[i].firstname << " " << record[i].lastname << " has failed"<<endl;
}
p.close();
f.close();
}
//This function counts how many students got a certain grade
void gradecount(STUDENT record[57])
{
int c1=0,c2=0,c3=0,c4=0,c5=0;
for(int i=0;i<57;i++)
{
if (record[i].grade=='A')
c1++;
else if(record[i].grade=='B')
c2++;
else if(record[i].grade=='C')
c3++;
else if(record[i].grade=='D')
c4++;
else
c5++;
}
cout<<c1<<" students got A"<<endl;
cout<<c2<<" students got B"<<endl;
cout<<c3<<" students got C"<<endl;
cout<<c4<<" students got D"<<endl;
cout<<c5<<" students got F"<<endl;
}
int main()
{
STUDENT record[57];
read(record);
WriteToFile (record);
Stcounter();
gradecount(record);
return 0;
}

If you didnt notice in your if statement
float a;
if(beggar>>record[i].idnumber>>record[i].firstname>>record[i].lastname>>record[i].quiz1>>record[i].quiz2>>record[i].mid1>>record[i].mid2>>record[i].homework>>record[i].Final)
a=(record[i].quiz1/10)+(record[i].quiz2/10)+((record[i].mid1*15)/100)+((record[i].mid2*15)/100)+(record[i].homework/10)+((record[i].Final*40)/100);
record[i].average=a;
it is giving you an error that you used the variable 'a' without it being initialized. So just when you declare a as a float assign it to 0 or something else

Related

What problem present in my program? Why the final output cannot be displayed

The final result cannot be displayed.
/*A Teacher has five students who have taken four tests. The teacher uses the following grading scale to assign a letter grade to a student, based on the average of his or her four test scores:
90-100 A
80-89 B
70-79 C
60-69 D
0-59 F
Write a program that uses an array of string objects to hold the five students' names, an array of five characters to hold the five students' letter grades, and five arrays of four doubles each to hold each student's set of test scores. enter code here
The program should allow the user to enter each student's name, and his or her four test scores. It should then calculate and display each student’s average test score, and a letter grade based on the average.
Input Validation: Do not accept test scores less than zero or greater than 100.*/
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
const int SUBJECT=4,STUDENT=5;
string name[5];
char grade[5];
double score[SUBJECT][STUDENT];
double average[5];
int i,j,k,l;
for (k=0;k<STUDENT;k++)
{
cout<<"Enter the name of student "<<k+1<<":"<<endl;
getline(cin,name[k]);
}
for (i=0;i<STUDENT;i++)
{
double sum=0;
for (j=0;j<SUBJECT;j++)
{
cout<<"Enter the test scores of subject "<<j+1<<" for "<<name[i]<<":";
cin >> score[i][j];
while (score[i][j] < 0||score[i][j] > 100)
{
cout<<"Invalid test score! Test scores can't be less than 0 or greater than 100."<<endl;
cout<<"Enter again the test scores of subject "<<j+1<<":";
cin >> score[i][j];
}
sum+=score[i][j];
average[i]=sum / SUBJECT;
}
}
cout<<setw(30)<<"Student's name"<<setw(25)<<"Average test score"<<setw(15)<<"Letter Grade"<<endl;
cout<<"------------------------------------------------------------------------------------------"<<endl;
for (l=0;l<STUDENT;l++)
{
if (average[l]>=90)
{
grade[l]='A';
}
else if (average[l]<90 && average[l]>=80)
{
grade[l]='B';
}
else if (average[l]<80 && average[l]>=70)
{
grade[l]='C';
}
else if (average[l]<70 && average[l]>=60)
{
grade[l]='D';
}
else
{
grade[l]='F';
}
cout<<setw(30)<<name[l]<<setw(25)<<average[l]<<setw(9)<<grade[l];
}
return 0;
}
The final result name,average and grade did not be displayed before the program terminated.
There are several issues in your code :
In this line cin >> score[i][j]; , i is related to a student and j is related to a subject, while the declaration was score[SUBJECT][STUDENT]
the average must be calculated after the subject loop
you should avoid magic constants, like in name[5]
It is better to avoid using namespace std;
It is better to better encapsulate variables such as i, j, and therefore not to declare them as global
This is a working example. Note that the final output still needs to be optimised but I let you do it!
#include <iostream>
#include <iomanip>
#include <string>
//using namespace std;
int main()
{
const int SUBJECT = 4,STUDENT = 5;
std::string name[STUDENT];
char grade[STUDENT];
double score[STUDENT][SUBJECT];
double average[STUDENT];
for (int i = 0; i < STUDENT;i++)
{
std::cout << "Enter the name of student " << i+1 << " : " << std::endl;
getline (std::cin,name[i]);
}
for (int i = 0; i < STUDENT; i++)
{
double sum = 0;
for (int j = 0; j < SUBJECT; j++)
{
std::cout << "Enter the test scores of subject "<<j+1<<" for "<<name[i]<<": ";
std::cin >> score[i][j];
while (score[i][j] < 0||score[i][j] > 100)
{
std::cout<<"Invalid test score! Test scores can't be less than 0 or greater than 100." << "\n";
std::cout<<"Enter again the test scores of subject " << j+1 << ": ";
std::cin >> score[i][j];
}
sum += score[i][j];
}
average[i] = sum / SUBJECT;
}
std::cout << std::setw(30) << "Student's name" << std::setw(25) << "Average test score" << std::setw(18) << "Letter Grade" << "\n";
std::cout<<"------------------------------------------------------------------------------------------" << "\n";
for (int i = 0;i < STUDENT; i++)
{
if (average[i]>=90)
{
grade[i]='A';
}
else if (average[i]<90 && average[i]>=80)
{
grade[i]='B';
}
else if (average[i]<80 && average[i]>=70)
{
grade[i]='C';
}
else if (average[i]<70 && average[i]>=60)
{
grade[i]='D';
}
else
{
grade[i]='F';
}
std::cout<<std::setw(30)<<name[i]<<std::setw(25)<<average[i]<<std::setw(20)<<grade[i]<<"\n";
}
return 0;
}
How about adding a <<endl statement to the last cout expression. This should flush the internal buffer to the output.

Making vector of objects by class

I have recently tried to learn how to create an object of vectors in order to represent objects of students including their names and grades. but when I wrote my program I got some errors regarding using &. I do not know what is the problem with my errors. could you please help me to fix it?
#include <iostream>
#include <vector>
#include <string>
using namespace std;
void printvector(const vector< student>&); // fill vector.fill in student information
void fillvector(vector< student>&); // print the information of all students
class student {
public:
student();
student(string, char);
~student();
string getName() ;
char getGrade() ;
void setName(string);
void setGrade(char);
private:
string newName;
char newGrade;
};
student::student() { newGrade = ' '; }
student::student(string name, char grade) {
newName = name;
newGrade = grade;
}
student::~student(){ }
string student::getName() { return newName; }
char student::getGrade() { return newGrade; }
void student::setName(string name) { newName = name; }
void student::setGrade(char grade) { newGrade = grade; }
int main() {
vector<student> myclass;
printvector(myclass);
fillvector(myclass);
return 0;
}
void fillvector(vector< student>& newmyclass) {
string name;
char grade;
int classsize;
cout << "how many students are in your class?";
cin >> classsize;
for (int i = 0; i < classsize; i++) {
cout << "enter student name";
cin >> name;
cout << "enter student grade";
cin >> grade;
student newstudent(name, grade);
newmyclass.push_back(newstudent);
cout << endl;
}
}
void printvector( vector< student>& newmyclass) {
unsigned int size = newmyclass.size();
for (unsigned int i = 0; i < size; i++) {
cout << "student name:" << newmyclass[i].getName() << endl;
cout << endl;
cout << "student grade" << newmyclass[i].getGrade() << endl;
cout << endl;
}
}
It seems you're printing your vector before filling it.. Is your problem fixed when you swap them around?
int main() {
vector<student> myclass;
printvector(myclass); // <--- These two lines should probably be swapped
fillvector(myclass); // <---
return 0;
}

I keep getting an error from Xcode that says " Apple Mach-O Linker (Id) Error "readIt(std::_1::basic_ifstream<char,std::_1::char_traits<char> >&,"

that says " Apple Mach-O Linker (Id) Error "readIt(std::_1::basic_ifstream >&,"
Does anyone see the error that it keeps getting stuck on? Thanks so much!
#include <fstream>
#include <iostream>
#include <iomanip>
using namespace std;
//PERRYI
// following: student's name, two test grades and final exam grade.
// It then prints this information to the screen.
const int NAMESIZE = 15;
const int MAXRECORDS = 50;
struct Grades // declares a structure
{
char name[NAMESIZE + 1];
int test1;
int test2;
int final;
char letter;
};
typedef Grades gradeType[MAXRECORDS];
void readIt (ifstream&,Grades [], int []);
int main()
{
ifstream indata;
indata.open("graderoll.txt");
int numRecord; // number of records read in
gradeType studentRecord;
if(!indata)
{
cout << "Error opening file. \n";
cout << "It may not exist where indicated" << endl;
return 1;
}
readIt(indata,studentRecord,&numRecord); // FILL IN THE CODE TO CALL THE FUNCTION ReadIt.
// output the information
for (int count = 0; count < numRecord; count++)
{
cout << studentRecord[count].name << setw(10)
<< studentRecord[count].test1
<< setw(10) << studentRecord[count].test2;
cout << setw(10) << studentRecord[count].final << endl;
}
return 0;
}
void readIt( ifstream& inData, Grades gradeRec[], int& total)
{
total = 0;
inData.get(gradeRec[total].name, NAMESIZE);
while (inData)
{
inData >> gradeRec[total].test1;// FILL IN THE CODE TO READ test1
inData >> gradeRec[total].test2;// FILL IN THE CODE TO READ test2
inData >> gradeRec[total].final;// FILL IN THE CODE TO READ final
total++; // add one to total
inData.ignore(81,'\n');// FILL IN THE CODE TO CONSUME THE END OF LINE
inData >> gradeRec[total].name;
total = (gradeRec[total].test1 + gradeRec[total].test2)*(.30) + (gradeRec[total].final * .40);
if (total <= 100 || total >= 90 )
cout << "A";
else if (total <= 89 || total >= 80)
cout << "B";
else if (total <= 79 || total >= 70)
cout << "C";
else if (total <= 69 || total >= 60)
cout << "D";
else
cout << "F";
}
}
Does anyone see the error that it keeps getting stuck on? Thanks so much!
Your prototype void readIt (ifstream&,Grades [], int []); doesn't match your function void readIt( ifstream& inData, Grades gradeRec[], int& total). The parameter types must match exactly.
As rafeek has just pointed out, prototype and function declaration must match.
If your function prototype is like this: void readIt(ifstream& inData, Grades gradeRec[], int& total);
Then you just need to adjust the declaration as well as the function call arguments to make your program compile.

reading data from a file into an array of a class

//Student file
#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
using namespace std;
#include "student.h"
#define cap 100
void main()
{ string s;
class student student[cap],l;
int i;
fstream f;
i=0;
cout << "Enter the file name: "; //Display to enter the file name
cin >>s;
f.open(s.data(),ios::in);
if(!f.is_open())
cout << "could not open file";
while(i<cap && !f.eof())
{ cout << "good";
student[i].get(f);
//Display if okay
if(f.good())
{
i++;
student[i].put(cout);
cout << i;
}
}
f.close();
}
class student
{
public:
student(); //Constructor without parameters
student(int,string,string,int,float); //Constructor with parameters
~student(); //Deconstructors
bool get(istream &); //Input
void put(ostream &); //Output
int read_array(string,int);
private:
int id,age;
float gpa;
string last,first;
};
student::student()
{
id = 0;
first = "null";
last = "null";
age = 0;
gpa = 0.0;
}
bool student::get(istream &in)
{
in >> id >> first >> last >> age >> gpa;
return(in.good());
}
void student::put(ostream &out)
{
out << id << first << last << age << gpa;
}
When i run this It displays the constructor values over, and over and the data from the file that should be going into the array and displaying them. I am not sure if I am doing the right way to put the data into the class array correctly.
Here's one problem:
if (f.good())
{
// student[i] has just been read from the file.
i++; // Increment counter.
student[i].put(cout); // Print whatever was in the next element.
cout << i;
}
The counter is incremented first, so student[i] refers to the element after the one that was just updated.

How do I display a name associated with a certain variable?...Please clarify this part

#include <iostream>
#include <stack>
#include <string>
using namespace std;
int main()
{
string name;
double gpa;
double high = 0;
stack<string>names;
for (int i=0; i<7; i++)
{
cout << " Enter student's name and gpa " << endl;
cin >> gpa ;
cin >> name ;
}
{
if (gpa > high)
{
high = gpa;
names.push(name);
}
else if (gpa=high)
{
high = gpa;
names.push(name);
}
}
cout << "Highest gpa is"<< high << "Names with highest gpa "<< ??? <<< endl;
system("pause");
return 0;
}
There's this list of names and with GPAs to these names, 7 to be exact. I have the algorithm to get the highest GPA and I know there's some sort of while loop condition to use in order to get the names of the persons with the highest GPA.
From the question 2 people have the same highest GPA... How will I display both these names with the highest GPA separately? I cant seem to get that part where I could associate the name with the GPA.
Help would be much appreciated.
Edited: Is there an easier method of using a while loop somewhere within that for loop in my code? Where I use the if (gpa < high) statement, am I missing something to get the names with the highest GPA?
struct Data {
std::string name;
int gpa;
};
then use a std::priority_queue<Data> to store it ( http://www.cplusplus.com/reference/stl/priority_queue/ ) (and make sure to create a comparison operator)
Also use == for equality not = (which is assignment)
Try this:
#include <iostream>
#include <stack>
#include <string>
using namespace std;
int main()
{
string name;
double gpa;
double high = 0;
stack<string>names;
for (int i=0;i<7;i++) {
cout << " Enter student's name and gpa " <<endl;
cin >> gpa;
cin >> name;
if (gpa > high) {
high = gpa;
names.clear();
names.push(name);
}
else if (gpa == high) {
names.push(name);
}
}
cout << "Highest gpa is "<< high << " held by:" << endl;
for (stack<string>::const_iterator it(names.begin()); it != names.end(); ++it) {
cout << *it << endl;
}
system("pause");
return 0;
}