Custom Class - File I/O

Please support our C++ advertiser: Intel Parallel Studio Home
Reply

Join Date: May 2007
Posts: 15
Reputation: yesm is an unknown quantity at this point 
Solved Threads: 2
yesm yesm is offline Offline
Newbie Poster

Custom Class - File I/O

 
0
  #1
May 4th, 2007
I've got a custom class that is as follows:
  1. class course {
  2. private:
  3. string prefix;
  4. int number;
  5. string title;
  6. int credits;
  7. char grade;
  8. public:
  9. //Constructors
  10. course();
  11. course(string, int, string, int, char);
  12. //Accessors
  13. void set();
  14. void print() const;
  15. string get_prefix() const;
  16. int get_number() const;
  17. string get_title() const;
  18. int get_credits() const;
  19. char get_grade() const;
  20. //Operators
  21. bool operator < (course) const;
  22. bool operator > (course) const;
  23. course operator = (course);
  24. bool operator == (course) const;
  25. bool operator == (int n) const;
  26. bool operator != (course) const;
  27. };
  28.  
  29. //.... then in main
  30.  
  31. vector<course> cache; //holds courses in memory
  32. vector<course>::iterator point; //points at the cache
  33. course temp; //buffer
  34. fstream file;//for file I/O
And I'm trying to do file input and output as follows:
  1. cout << "Loading file..." << endl;
  2. file.open("Courses.dat", ios::in | ios::binary);
  3. file.clear();
  4. file.read(reinterpret_cast<char *>(&temp), sizeof(temp));
  5. while (!file.eof()) {
  6. cache.push_back(temp);
  7. temp.print();
  8. file.read(reinterpret_cast<char *>(&temp), sizeof(temp));
  9. }
  10. file.close();
  1. cout << "Saving to file..." << endl;
  2. file.open("Courses.dat", ios::out | ios::trunc | ios::binary);
  3. file.clear();
  4. for(point = cache.begin(); point != cache.end(); point++) {
  5. temp = *point;
  6. temp.print();
  7. file.write(reinterpret_cast<char *>(&temp), sizeof(temp));
  8. file.clear();
  9. }
  10. file.close();

What's interesting is if I write and read pre-made data like below, it works:
  1. course one("CSCI", 2012, "C++ Programming 2", 3, 'A');
  2. course two("MATH", 2081, "Multiple Varible Calculus", 4, 'C');
  3. course three("ENGL", 1022, "Composition 2", 3, 'B');
  4. file.open("Courses.dat", ios::out | ios::trunc | ios::binary);
  5. file.write(reinterpret_cast<char *>(&one), sizeof(one));
  6. file.write(reinterpret_cast<char *>(&two), sizeof(two));
  7. file.write(reinterpret_cast<char *>(&three), sizeof(three));
  8. file.close();
  9.  
  10. //close program, open it again without writing that data
  11. //load data into cache, and it displays correctly
.But if I use any custom data (AKA user-input) it saves correctly as far as I can tell, but if I try to load the data it crashes when it tries to display it - printing out random gibberish.


Can anyone spot any errors I missed in the file I/O routines? If need be I can post the entire source code.
Thanks in advance for wading through this post!
Reply With Quote Quick reply to this message  
Join Date: Sep 2004
Posts: 7,771
Reputation: Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute 
Solved Threads: 743
Team Colleague
Narue's Avatar
Narue Narue is offline Offline
Code Goddess

Re: Custom Class - File I/O

 
0
  #2
May 4th, 2007
Your class doesn't meet the requirements for a POD type, so using read and write is undefined. Add a couple of member functions that serialize your class to and from a string, then use that string for file I/O.
I'm here to prove you wrong.
Reply With Quote Quick reply to this message  
Join Date: May 2007
Posts: 15
Reputation: yesm is an unknown quantity at this point 
Solved Threads: 2
yesm yesm is offline Offline
Newbie Poster

Re: Custom Class - File I/O

 
0
  #3
May 4th, 2007
Um... by that do you mean overload the << and >> operators?

I'm basing my work off my textbook ("Object-Oriented Programming in C++" by Robert Lafore"), who uses the following example:
  1. // diskfun.cpp
  2. // reads and writes several objects to disk
  3. #include <fstream> //for file streams
  4. #include <iostream>
  5. using namespace std;
  6. ////////////////////////////////////////////////////////////////
  7. class person //class of persons
  8. {
  9. protected:
  10. char name[80]; //person's name
  11. int age; //person's age
  12. public:
  13. void getData() //get person's data
  14. {
  15. cout << "\n Enter name: "; cin >> name;
  16. cout << " Enter age: "; cin >> age;
  17. }
  18. void showData() //display person's data
  19. {
  20. cout << "\n Name: " << name;
  21. cout << "\n Age: " << age;
  22. }
  23. };
  24. ////////////////////////////////////////////////////////////////
  25. int main()
  26. {
  27. char ch;
  28. person pers; //create person object
  29. fstream file; //create input/output file
  30. //open for append
  31. file.open("GROUP.DAT", ios::app | ios::out |
  32. ios::in | ios::binary );
  33. do //data from user to file
  34. {
  35. cout << "\nEnter person's data:";
  36. pers.getData(); //get one person's data
  37. //write to file
  38. file.write( reinterpret_cast<char*>(&pers), sizeof(pers) );
  39. cout << "Enter another person (y/n)? ";
  40. cin >> ch;
  41. }
  42. while(ch=='y'); //quit on 'n'
  43. file.seekg(0); //reset to start of file
  44. //read first person
  45. file.read( reinterpret_cast<char*>(&pers), sizeof(pers) );
  46. while( !file.eof() ) //quit on EOF
  47. {
  48. cout << "\nPerson:"; //display person
  49. pers.showData(); //read another person
  50. file.read( reinterpret_cast<char*>(&pers), sizeof(pers) );
  51. }
  52. cout << endl;
  53. return 0;
  54. }

Do you mean because the strings are of undefined length, the file I/O messed up?
Reply With Quote Quick reply to this message  
Join Date: May 2007
Posts: 15
Reputation: yesm is an unknown quantity at this point 
Solved Threads: 2
yesm yesm is offline Offline
Newbie Poster

Re: Custom Class - File I/O

 
0
  #4
May 4th, 2007
NOTE: Interestingly, when I tried again, here is the output:
CSCI 2012: C++ Programming 2
Worth 3 credits. Grade: A
MATH 2081: Multiple Varible Calculus
Worth 4 credits. Grade: C
ENGL 1022: Composition 2
Worth 3 credits. Grade: B
2022:
Worth 4 credits. Grade: C


Notice the last entry: it read the integers and char correctly, just missed the strings. Not crashing anymore...
Reply With Quote Quick reply to this message  
Join Date: Sep 2004
Posts: 7,771
Reputation: Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute 
Solved Threads: 743
Team Colleague
Narue's Avatar
Narue Narue is offline Offline
Code Goddess

Re: Custom Class - File I/O

 
0
  #5
May 4th, 2007
>Um... by that do you mean overload the << and >> operators?
If you want. I think explicit serialize and deserialize member functions are more flexible though.

>I'm basing my work off my textbook ("Object-Oriented Programming in C++" by Robert Lafore")
You have my sympathy then. Lafore doesn't come to mind when I think of good writers, and he's on the list when I think of bad writers.

>Do you mean because the strings are of undefined length, the file I/O messed up?
I mean that your objects aren't guaranteed to be convertable to an array of unsigned char due to padding and other internal data structure. That's an absolute requirement when using read or write because you're casting your object to an array of char (roughly the same thing). Do a google search for "plain old data". Those are the rules you have to abide by if you want to be able to cast your objects to an unsigned char* (and you should be using unsigned char* rather than char*).

>Not crashing anymore...
Undefined behavior means anything could happen. It could work for a year and then crash every day for a month straight or vice versa.
Last edited by Narue; May 4th, 2007 at 12:47 pm.
I'm here to prove you wrong.
Reply With Quote Quick reply to this message  
Join Date: May 2007
Posts: 15
Reputation: yesm is an unknown quantity at this point 
Solved Threads: 2
yesm yesm is offline Offline
Newbie Poster

Re: Custom Class - File I/O

 
0
  #6
May 4th, 2007
Gaaaah, okay, now its crashing again...

Yea, I'm also using a textbook by Tony Gaddis, it's just not with me.

Hmm... so if I created a struct to hold my data, built a class around that struct, then wrote only the STRUCT to disk it would work better? I'll start on that, yell at me if I missed the boat again.


Sorry for the confuzzlement, I've never heard of any of this POD stuff, our professor just throws up powerpoints and hopes we get it ><
Reply With Quote Quick reply to this message  
Join Date: May 2007
Posts: 15
Reputation: yesm is an unknown quantity at this point 
Solved Threads: 2
yesm yesm is offline Offline
Newbie Poster

Re: Custom Class - File I/O

 
0
  #7
May 4th, 2007
Wow. I have to re-write everything to deal with structs?
This sucks.
Reply With Quote Quick reply to this message  
Join Date: May 2007
Posts: 15
Reputation: yesm is an unknown quantity at this point 
Solved Threads: 2
yesm yesm is offline Offline
Newbie Poster

Re: Custom Class - File I/O

 
0
  #8
May 4th, 2007
Ooooookay. So I re-wrote everything to write a struct to file, instead of a class. I made a struct called cinfo that I create from a class to write a file, and made a constructor to create a class from one of those structs (for reading data back in).

But the same exact error happens! I must be missing something different.

  1. // This uses classes and STL to manage a listing of courses.
  2. // Created by:
  3. // Created: 5/3/07
  4. // Modified: 5/4/07
  5. #include <iostream>
  6. #include <iomanip>
  7. #include <fstream>
  8. #include <string>
  9. #include <vector>
  10. #include <algorithm>
  11. #include <iterator>
  12. #include <functional> // (?)
  13. using namespace std;
  14.  
  15. struct cinfo { //holds course info
  16. string prefix;
  17. int number;
  18. string title;
  19. int credits;
  20. char grade;
  21. };
  22.  
  23. class course {
  24. private:
  25. string prefix;
  26. int number;
  27. string title;
  28. int credits;
  29. char grade;
  30. public:
  31. //Constructors
  32. course();
  33. course(string, int, string, int, char);
  34. course(cinfo in);
  35. //Accessors
  36. void set();
  37. void print() const;
  38. string get_prefix() const;
  39. int get_number() const;
  40. string get_title() const;
  41. int get_credits() const;
  42. char get_grade() const;
  43. cinfo get_info() const;
  44. //Operators
  45. bool operator < (course) const;
  46. bool operator > (course) const;
  47. course operator = (course);
  48. bool operator == (course) const;
  49. bool operator == (int n) const;
  50. bool operator != (course) const;
  51. };
  52.  
  53. //class functions...
  54. //indenting below is a little screwed up, my bad
  55.  
  56. int main()
  57. {
  58. vector<course> cache; //holds courses in memory
  59. vector<course>::iterator point; //points at the cache
  60. cinfo temp //buffer struct
  61. course *buffer; //buffer class
  62. fstream file;//for file I/O
  63.  
  64. //stuff happens
  65.  
  66. file.open("Courses.dat", ios::out | ios::trunc | ios::binary);
  67. temp = one.get_info();
  68. file.write(reinterpret_cast<char *>(&temp), sizeof(temp));
  69. temp = two.get_info();
  70. file.write(reinterpret_cast<char *>(&temp), sizeof(temp));
  71. temp = three.get_info();
  72. file.write(reinterpret_cast<char *>(&temp), sizeof(temp));
  73. file.close();
  74.  
  75.  
  76.  
  77. cout << "Saving to file..." << endl;
  78. file.open("Courses.dat", ios::out | ios::trunc | ios::binary);
  79. file.clear();
  80. for(point = cache.begin(); point != cache.end(); point++) {
  81. temp = point->get_info();
  82. file.write(reinterpret_cast<char *>(&temp), sizeof(temp));
  83. file.clear();
  84. }
  85. file.close();//close file
  86.  
  87.  
  88.  
  89. cout << "Loading file..." << endl;
  90. file.open("Courses.dat", ios::in | ios::binary);
  91. file.clear();
  92. file.read(reinterpret_cast<char *>(&temp), sizeof(temp));
  93. while (!file.eof()) { //read in file
  94. buffer = new course(temp);
  95. cache.push_back(*buffer);//place object in cache
  96. delete buffer;
  97. file.read(reinterpret_cast<char *>(&temp), sizeof(temp));
  98. }
  99. file.close();

Attached is the entire source code. I cannot upload the blank "Courses.dat" file, so create a new ".txt" file in the same folder and rename it "Courses.dat" for it to work. The prompt at the beginning allows you to add three structs to file, so you don't have to type data every time you blank the .dat file.
Attached Files
File Type: cpp Program.cpp (10.8 KB, 3 views)
Reply With Quote Quick reply to this message  
Join Date: Sep 2004
Posts: 7,771
Reputation: Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute 
Solved Threads: 743
Team Colleague
Narue's Avatar
Narue Narue is offline Offline
Code Goddess

Re: Custom Class - File I/O

 
0
  #9
May 4th, 2007
>Wow. I have to re-write everything to deal with structs?
No. You're so focused on trying to write an object to file, you're completely missing the point. All you need to do is turn the object into something that can be written to file. For example:
  1. // Convert this to a pipe delimited string
  2. const string course::serialize()
  3. {
  4. stringstream out;
  5.  
  6. out<< prefix <<'|'<< number <<'|'<< title <<'|'<< credits <<'|'<< grade;
  7.  
  8. return out.str();
  9. }
Then you can do this:
  1. file<< pers.serialize();
I'm here to prove you wrong.
Reply With Quote Quick reply to this message  
Join Date: May 2007
Posts: 15
Reputation: yesm is an unknown quantity at this point 
Solved Threads: 2
yesm yesm is offline Offline
Newbie Poster

Re: Custom Class - File I/O

 
0
  #10
May 4th, 2007
Oh, God.... we even did something like this a long time ago, I just didn't think we still wanted to use that method...

I'll whip up an in/out and let you know how it goes
Reply With Quote Quick reply to this message  
Reply

This thread is more than three months old.
Perhaps start a new thread instead?
Message:


Thread Tools Search this Thread



About Us | Contact Us | Advertise | DaniWeb | Acceptable Use Policy | RSS Feed

©2003 - 2009 DaniWeb® LLC