These are the specifications for the assignment:
Write the following members functions:
(a) Constructor that creates objects of the student class.
(b) read that prompts the user to enter from the keyboard student name, age and gpa.
To terminate reading the user should enter the EOF (ctrl-D in Unix and Ctrl-Z in
DOS).
(c) show that displays on the screen student name, age and gpa.
(d) writefile that writes a record (name, age, gpa) into the file student.dat.
(e) getgpa that returns gpa of the student.
(f) readfile that reads the student record from the file student.dat .
Here is ONE version, the latest , of what I was trying.

#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#define W setw
using namespace std;

class student{
  private:
    string name; 
    int age ;
    float gpa;

  public:
    student(){};
    student(string n,int a,float g){
    name = n;age = a;gpa = g;
    }
    int read();
    void show();
    void writefile();
    void readfile();
};
  int student::read(){
     
}
  void student::show(){
  cout << W(10) << name << W(4) << age << W(4) << gpa << endl;
}
  void student::writefile(){
    ofstream OF ( "student.dat",fstream::app);
    OF << W(10) <<name <<W(6)<<age<<W(4)<<gpa<<endl;
    OF.close();

}

  void student::readfile(){
  
}

}
int main(){


return 0;
}

Question: An earlier version I got the "read" function to work properly, but it would only get 1 student record, which I ASSUMED was NOT the point of using an EOF character to cease input.
These streams are confusing me and the instructor's specifications are even confusing me!

WHY oh WHY would "readfile" be a member function here?

Any input greatly appreciated!

Recommended Answers

All 13 Replies

member function readfile() only reads one record into the stucent structure. There should be a loop somewhere else in your program that puts that in a loop to read the entire file into an array of student records.

as for part b) -- You could have read() function return TRUE (or 1) if EOF (^Z) is not pressed, or 0 if it is pressed. Then call that function in a loop until it returns TRUE.

#include <iostream>
#include <string>

using namespace std;

int read(string& name)
{
    cin >> name;
    if( cin.fail() )
         return 0;
    return 1;

}

int main()
{
    string name;
    while( read(name) )
        cout << name << "\n";
}

If I ever wrote methods like writefile(...) and readfile(...) for a class that was to be streamed to/from files, I would pass the file handle (or stream) as an argument to the method so that it didn't have to worry about opening the file or closing the file. It would also allow me to call it multiple times for the same file which could write (or read) multiple records from the same file.

The only other logical implementation for a readfile member would be for a 'class owned' rather than 'instance owned' method. The method would read and instantiate multiple student records from the file. It should however either return the list of student records or be updating a global list. (The return of the list tends to be more flexible in the future.)

Is there more that you were given? (function prototypes for example) or is the first paragraph (before your code) all that you were given for the assignement?

Is there more that you were given? (function prototypes for example) or is the first paragraph (before your code) all that you were given for the assignement?

This is the entire specification:

Create the class student that includes the following information about student: name,
age and gpa.

Write the following members functions: [FROM 1st POST]

Write a main program that demonstrates the work with this class. Declare all
necessary objects and variables. Using read and writefile create the student.dat.
After closing the file student.dat reopen it for reading. Read and display all students
from the file and compute and display the average gpa for all of them.

I'm losing it. I got the read function to perform as specified, but I still feel I am misinterpreting the real objective, maybe not.
But still the readfile eludes me.

when a student object has its "readfile" method called i am thinking it looks in the student.dat file for itself? then prints its info? I am so confused now. What's the difference between that and it's "show" method!? :'(

#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#define W setw
using namespace std;

class student{
  private:
    string name; 
    int age ;
    float gpa;

  public:
    student(){};
    student(string n,int a,float g){
    name = n;
    age = a;
    gpa = g;
    }
  
    int read();
    void show();
    void writefile();
    void readfile(ifstream & infile);
};
  int student::read(){
     cout << "Enter student info. EOF character to end\n";
     while(!cin.eof()){
     cin >> name >> age >> gpa;
     }

}
  void student::show(){
  cout << W(10) << name << W(4) << age << W(4) << gpa << endl;
}
  void student::writefile(){
    ofstream OF ( "student.dat",fstream::app);
    OF << W(10) <<name <<W(6)<<age<<W(4)<<gpa<<endl;
    OF.close();

}
  void student::readfile(ifstream & infile){

}

int main(){
  ifstream IF("student.dat");


return 0;
}

So your main shoud do something like the following:

Open the student.dat file (for output)
Read in a student from the keyboard
Write the student data to the file
(until you see the EOF at the keyboard)
Close the file

Open the file
Read in a student from the file
Show the student
get the gpa to use in calculating the average
(until you run out of data in the file)
close the file

print the average gpa

The above is an outline for your main. Start there, attempt to write your main using the above description, modifying it if you find the need. The above code will be implemented by calling the methods that you have been asked to write.

Once you have the main implemented you can flesh-out the methods if they're not doing what you need them to. It should also help you to better understand how the methods are intended to 'fit' into the program you need to write.

OK!

Now I got something to work with here.!!!!

But my feeble brain is fried and the last entry gets written to the file twice?!? I can't see why at this moment!

I just noticed I still have to wrangle my last few statements of the main into the readfile function, but since the behavior is ok, i guess it shouldn't present any major problems *fingers crossed*

ALSO I feel like i redeclared variables in the main that i didn't need to , or declared them in functions unneccessarily. But as I said, my brain is fried now!

#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#define W setw
using namespace std;

class student{
  private:
    string name; 
    int age ;
    float gpa;

  public:
    student(){};
    student(string n,int a,float g){
    name = n;
    age = a;
    gpa = g;
    }
  
    int read();
    void show();
    void writefile();
    void readfile(ifstream & infile);
};
  int student::read(){
     
     cout << "Enter student info. EOF character to end\n";
     
     do{
     cin >> name >> age >> gpa;
     student temp(name,age,gpa);
      temp.writefile();
     }while(!cin.eof());

}
  void student::show(){
  cout << name << " " << age <<" " << gpa << endl;
}
  void student::writefile(){
    ofstream OF ( "student.dat",fstream::app);
    OF << W(10) <<name <<W(6)<<age<<W(4)<<gpa<<endl;
    OF.close();

}

  void student::readfile(ifstream & infile){

}


int main(){
  string name;int age; float gpa;
  ofstream ofile("student.dat");
  ifstream infile;
  student x;
  float sum=0;int i=0;  
 
  x.read();

  ofile.close();

  infile.open("student.dat");

  while(infile >> name >> age >>gpa){
    cout <<W(10)<< name<<W(5) <<age<<W(5) <<gpa<<endl;
   sum += gpa;i++;
  }

  cout << "Avg. GPA=" << sum/i <<endl;
return 0;
}

The read method should not call writefile() You should call it from your main. Where you have

x.read();

You should have

x.read();
x.writefile(ofile);

Note that I passed the file to write to, so stop opening and closing the file in writefile That may be the cause of your double recording, you had the file open twice.

Your main is not supposed to read the file data itself, it is supposed to use the readfile method and then call the show method to display the record. Then it should call getgpa to get the gpa for the average calculation.

(What you have probably works, but does not meet the requirements.)

Still stuck.

Last student gets written to file twice.

Can't figure how to iterate through the gpas to find avg.

#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#define W setw
using namespace std;

class student{
  private:
    string name; int age; float gpa;

  public:
    //Constructors
    student(){};
    student(string n,int a,float g){
    name = n; age = a; gpa = g;
    }
    //Function prototypes
    int read();
    void show();
    void writefile(ofstream &ofile);
    void readfile(ifstream &infile);
    double getgpa();
}; // end class
  
  /****Function Definitions*****/
  int student::read(){
     cout << "Enter student info. EOF character to end\n";
     cin >> name >> age >> gpa;
    
}
  void student::show(){
    cout << name << " " << age <<" " << gpa << endl;
}
  void student::writefile(ofstream &ofile){
    ofile << W(10) <<name <<W(6)<<age<<W(5)<<gpa<<endl;
}

  void student::readfile(ifstream &infile){
  
    while(infile >> name >> age >> gpa)
      cout << name << " " << age << " " << gpa << endl;

}
  double student::getgpa(){
    return gpa;
}

int main(){
  string name;int age; float gpa;
  ofstream ofile("student.dat",fstream::app);
  ifstream infile;
  student x;
  float sum=0;int i=0;  
 
  while(!cin.eof()){
  x.read();
  x.writefile(ofile);
  }

  ofile.close();

  infile.open("student.dat");
  
  infile.close();

return 0;
}

For the double posting of the last student, add a if (!cin.eof()) in front of the x.writefile(ofile)

Ok, so you're opening and closing the infile. Nice start, why don't you read from it until it runs out of data. (Hint it should look a lot like the read from the console until it ran out of data, but use different methods.)

I'll only include my main now, as that is where the changes were made.

This checking if the file or cin is EOF works but it doesn't seem like a sexy solution here. What can I do to make that better?

int main(){
  string name;int age; float gpa;
  ofstream ofile("student.dat",fstream::app);
  ifstream infile;
  student x;
  float sum=0;int i=0;  
 
  while(!cin.eof()){
  x.read();
  if(!cin.eof())
  x.writefile(ofile);
  }

  ofile.close();

  infile.open("student.dat");

  while(!infile.eof()){   
  infile >> name >> age >> gpa ; 
   if(!infile.eof()){
     sum += gpa; i++;
     cout << gpa << " read. " << i << " is the #of students" << endl;
   }  
  }
  infile.close();
  cout << "The avg. GPA is:" << sum/i << endl << "there are " << i << " students in the file." <<endl;
  
return 0;
}

I'm not sure what you mean by a 'sexy' solution. I think any solution that works is sexy! (grin)

I would have indented the x.writefile call to show that it is under the if and I would probably have used braces too.

// If we haven't reached the end of the input, write the latest record
if (!cin.eof())
{
    x.writefile(ofile);
}

You're still refusing to use the members of the student class to do the work!

Why should main read the data when student defines readfile?

Weren't you supposed to display the data you read? maybe you could call something....oh, what about show?

I think there may have been another method defined to help with the gpa calculation...hmm...

Note for future homework: if the teacher assigns you to write a method, you probably need to call it for the assignment. If not, re-evaluate how you're doing the work, maybe you're missing something. (In any case, I would call all of my methods at least once or twice for testing, I hate it when the teacher finds a bug because I didn't bother to test.)

Note for future homework: if the teacher assigns you to write a method, you probably need to call it for the assignment. If not, re-evaluate how you're doing the work, maybe you're missing something. (In any case, I would call all of my methods at least once or twice for testing, I hate it when the teacher finds a bug because I didn't bother to test.)

You are absolutely correct about that! Its important not only in school to test everything you write, but also every programming job you will get after graduation. Learn to do this in school and it will help you immensely after graduation.

My readfile function is screwed.
It doesn't do anything. That's what you mean by my main method doing the work. I guess i fixed that ... but..
I have decided I have no idea HOW to use these streams and insertion operators and what exactly is going on.

If I call x.readfile() in the main
i am thinking readfile says: infile is where i get a thing called 'name' then 'age' then 'gpa'.
This readfile function returns NO value, but puts the first 3 things it finds into those member variables (and remembers its place in the file)?
So i call x.show() immediately after readfile, and it seemingly shows the correct data, but i use gpa soon after and nothing happens!

OK, replaced "gpa" with call to x.getgpa(). Is that the "encapsulation" at work? i hope. :(

Still confused but here is my code again!
What a MESS!
Thanks for all the help just humor me this one last time and respond!

#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#define W setw
using namespace std;

class student{
  private:
    string name; int age; float gpa;

  public:
    //Constructors
    student(){};
    student(string n,int a,float g){
    name = n; age = a; gpa = g;
    }
    //Function prototypes
    int read();
    void show();
    void writefile(ofstream &ofile);
    void readfile(ifstream &infile);
    double getgpa();
}; // end class
  
  /****Function Definitions*****/
  int student::read(){
     cout << "Enter student info. EOF character to end\n";
     cin >> name >> age >> gpa;
    
}
  void student::show(){
    cout << name << " " << age <<" " << gpa << endl;
}
  void student::writefile(ofstream &ofile){
    ofile << W(10) <<name <<W(6)<<age<<W(5)<<gpa<<endl;
}

  void student::readfile(ifstream &infile){
  
   infile >> name >> age >> gpa;
   //cout << name << " " << age << " " << gpa << endl;
   //this is NOT supposed to show the data, just get it into member var?
}
  double student::getgpa(){
    return gpa;
}

int main(){
  string name;int age; float gpa;
  ofstream ofile("student.dat",fstream::app);
  ifstream infile;
  student x;
  float sum=0;int i=0;  
 
  //Fill the file with student records
  while(!cin.eof()){
    x.read();
    if(!cin.eof()){
      x.writefile(ofile);
    }
  }

  ofile.close();

  infile.open("student.dat");
cout<<"______List of Students in student.dat_____"<<endl;
  while(!infile.eof()){   
    x.readfile(infile);
    //infile >> name >> age >> gpa ; 
    if(!infile.eof()){
      x.show();
      sum += x.getgpa(); i++;
   // cout << x.getgpa() << " read. " << i << " is the #of students" << endl;
   }  
  }
  infile.close();
  
 cout << "\nThe avg. GPA is:" << sum/i << endl;// << "there are " << i << " students in the file." <<endl;
  
return 0;
}

That looks pretty close to what I expected.

You can get rid of the variables in main for name, age, gpa.

I tend to declare only one thing per line, but its a coding convention / personal preference issue. I also tend (in c++) to declare most variables close to the point of use:

int main(){
  student x;
  ofstream ofile("student.dat",fstream::app);
 
  //Fill the file with student records
  while(!cin.eof()){
    x.read();
    if(!cin.eof()){
      x.writefile(ofile);
    }
  }
  ofile.close();

  float sum=0;
  int i=0;  
  ifstream infile("student.dat");
  cout<<"______List of Students in student.dat_____"<<endl;
  while(!infile.eof()){   
    x.readfile(infile);
    if(!infile.eof()){
      x.show();
      sum += x.getgpa(); 
      i++;
   }  
  }
  infile.close();
  
 cout << "\nThe avg. GPA is:" << sum/i << endl;
  
return 0;
}

Does it run? Is the output acceptable?

Review the assignment requirements, did your application do everything on the list?

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.