简体   繁体   中英

reading object from file and printing it

I'm writing a project about reading/writing from file and have same problems when i try to read an object from file.I must print all students with grade > 3.00 but it doesn't print anything! Any suggestion ? ps sorry for my bad English ;) Here is my code:

#include<iostream>
#include<fstream>
#include<cstring>
#include<algorithm>
#include<queue>
const int  MAX_SIZE = 35;

using namespace std;

class Student {

char name[MAX_SIZE];
double mark;
int phone_number;
public:

Student(char const* _name = "anonimous", double = 2, int = 0);
char const* getName() const { return name; }
int getMark() const { return mark; }
int getPhone() const { return phone_number;}
void setMark(double newmark) { mark = newmark; }
void setPhone(int newphone) { phone_number = newphone; }


friend istream& operator>>(istream& is, Student& s);
friend ostream& operator<<(ostream& os, Student const& s);
bool operator>(Student const& s) const;
bool operator<(Student const& s) const;

void mycopy(Student const& s){
strcpy(name,s.getName());
mark = s.getMark();
phone_number = s.getPhone();
}
};


Student::Student(char const* _name, double _mark, int _phone_number)
  :mark(_mark), phone_number(_phone_number){
     strncpy(name, _name, MAX_SIZE);
     name[MAX_SIZE] = '\0';
}

istream& operator>>(istream& is, Student& s){
       return (is >> s.phone_number >> s.mark).getline(s.name,MAX_SIZE);
}

ostream& operator<<(ostream& os, Student const& s){
return os << "Name: "<<s.name<<" Grade: "<<s.mark<<" Phone: "<<s.phone_number<<endl;
 }

 bool Student::operator>(Student const& s) const{
 return name > s.getName();
 }
bool Student::operator<(Student const& s) const{
 return name < s.getName();
 }

Student* readStudent(int n){
   Student* s = new Student[n];
   for(int i=0;i<n;i++){
         cin >> s[i];
   }
   return s;
}

void writeStudent(Student* s, int n){
   ofstream fo("my_database.txt");
   for(int i=0;i<n;i++){
         fo << s[i];
   }
}

int main(){
Student* students = new Student[10];
students[0] = Student("Ivan Petrov",4.25,359887954521);
students[1] = Student("Marina Popopva",5.75,359897254521);
students[2] = Student("Petar Ivanov",3.15,359888845723);
students[3] = Student("Stilqn Petrov",2.65,359895745812);
students[4] = Student("Ivelina Veselinova",3.20,359878745861);
students[5] = Student("Margarita Ivanova",4.50,359885421457);
students[6] = Student("Boqn Pavlov",6.00,359898632541);
students[7] = Student("Iliqn Karov",3.00,359878389699);
students[8] = Student("Ivan Dobromirov",4.18,359886574287);
students[9] = Student("Georgi Lubenov",5.61,359885749354);

writeStudent(students,10);

ifstream sf("my_database.txt");
    Student s;
    while( sf >> s){
        if (s.getMark() > 3.00){
            cout << s << endl;
        }
    }

return 0;}

There are several problems:

  • int getMark() const { return mark; } int getMark() const { return mark; } should return double , not int

  • students[0] = Student("Ivan Petrov",4.25,359887954521); Your phone numbers are larger than int , and what if they need to start with 0 ? Should probably be type std::string instead

  • check your ::operator>> and << . They are not consistent:

Your operator<< :

ostream& operator<<(ostream& os, Student const& s){
   return os << "Name: "<<s.name<<" Grade: "<<s.mark<<" Phone: "  <<s.phone_number<<endl;
}

Will result a data line looking like this:

Name: Ivan Petrov Grade: 4.25 Phone: 359887954521

And then your operator>> :

return (is >> s.phone_number >> s.mark).getline(s.name,MAX_SIZE);

Is wrong. You need to read and ignore some strings along the way. I will suggest you use a std::string to store a name. Here's an implementation that assumes such use:

istream& operator>>(istream& is, Student& s){
   std::string firstName;
   std::string lastName;
   std::string tmpStr;
   is >> tmpStr; // "Name: "
   is >> firstName;
   is >> lastName;
   s.name = firstName + " " + last_name; // consider even storing these in separate fields
   is >> tmpStr; // "Grade: "
   is >> s.mark;
   is >> tmpStr; // "Phone: "
   is >> s.phone_number;
   return is;
}

Other things:

  • Student* students = new Student[10]; No need to use new: Student students[10];

  • Try to avoid hardcoding "database.txt" as the in/out file. Take the filename as a parameter to the function.

Problems I see:

  1. The output and input functions are not symmetric. You have:

     istream& operator>>(istream& is, Student& s){ return (is >> s.phone_number >> s.mark).getline(s.name,MAX_SIZE); } ostream& operator<<(ostream& os, Student const& s){ return os << "Name: "<<s.name<<" Grade: "<<s.mark<<" Phone: "<<s.phone_number<<endl; // "Name: " and " Grade: " are extra data. } 
  2. When a variable of type std::string has spaces in it, the operator<<() function will write the spaces to the output stream but the operator>>() will stop at the first whitespace character. Hence, what you save with

     os << s.name 

    will not be the same as what you read with

     is >> s.name 

    You'll need to change your strategy to save the name.

    Save the length of the name first before saving the name. At the time of reading the data, read the length first before reading the name.

  3. You are not saving the mark . You are not reading it back either.

Here's my suggestion for the functions.

istream& operator>>(istream& is, Student& s){

   // Read the size.
   size_t size;
   is >> size;

   // Read the space and discard.
   is.get();

   // Now read the name.
   is.read(s.name, size);

   // Null terminate the string.
   s.name[size] = '\0';

   // Read the phone number
   is >> s.mark;

   // Read the phone number
   is >> s.phone_number;

   return is;
}

ostream& operator<<(ostream& os, Student const& s){

   // Write the size.
   size_t size = strlen(s.name);
   os << size;

   // Write a space as a separator.
   os << " ";
   os.write((char*)s.name, size);

   // Write a space as a separator.
   os << " ";

   // Write the mark.
   os << s.mark;

   // Write a space as a separator.
   os << " ";

   // Write the phone number.
   os << s.phone_number;

   return os;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM