| | |
Custom Class - File I/O
Please support our C++ advertiser: Intel Parallel Studio Home
![]() |
•
•
Join Date: May 2007
Posts: 15
Reputation:
Solved Threads: 2
I've got a custom class that is as follows:
And I'm trying to do file input and output as follows:
What's interesting is if I write and read pre-made data like below, it works:
.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!
C++ Syntax (Toggle Plain Text)
class course { private: string prefix; int number; string title; int credits; char grade; public: //Constructors course(); course(string, int, string, int, char); //Accessors void set(); void print() const; string get_prefix() const; int get_number() const; string get_title() const; int get_credits() const; char get_grade() const; //Operators bool operator < (course) const; bool operator > (course) const; course operator = (course); bool operator == (course) const; bool operator == (int n) const; bool operator != (course) const; }; //.... then in main vector<course> cache; //holds courses in memory vector<course>::iterator point; //points at the cache course temp; //buffer fstream file;//for file I/O
C++ Syntax (Toggle Plain Text)
cout << "Loading file..." << endl; file.open("Courses.dat", ios::in | ios::binary); file.clear(); file.read(reinterpret_cast<char *>(&temp), sizeof(temp)); while (!file.eof()) { cache.push_back(temp); temp.print(); file.read(reinterpret_cast<char *>(&temp), sizeof(temp)); } file.close();
C++ Syntax (Toggle Plain Text)
cout << "Saving to file..." << endl; file.open("Courses.dat", ios::out | ios::trunc | ios::binary); file.clear(); for(point = cache.begin(); point != cache.end(); point++) { temp = *point; temp.print(); file.write(reinterpret_cast<char *>(&temp), sizeof(temp)); file.clear(); } file.close();
What's interesting is if I write and read pre-made data like below, it works:
C++ Syntax (Toggle Plain Text)
course one("CSCI", 2012, "C++ Programming 2", 3, 'A'); course two("MATH", 2081, "Multiple Varible Calculus", 4, 'C'); course three("ENGL", 1022, "Composition 2", 3, 'B'); file.open("Courses.dat", ios::out | ios::trunc | ios::binary); file.write(reinterpret_cast<char *>(&one), sizeof(one)); file.write(reinterpret_cast<char *>(&two), sizeof(two)); file.write(reinterpret_cast<char *>(&three), sizeof(three)); file.close(); //close program, open it again without writing that data //load data into cache, and it displays correctly
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!
•
•
Join Date: May 2007
Posts: 15
Reputation:
Solved Threads: 2
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:
Do you mean because the strings are of undefined length, the file I/O messed up?
I'm basing my work off my textbook ("Object-Oriented Programming in C++" by Robert Lafore"), who uses the following example:
c++ Syntax (Toggle Plain Text)
// diskfun.cpp // reads and writes several objects to disk #include <fstream> //for file streams #include <iostream> using namespace std; //////////////////////////////////////////////////////////////// class person //class of persons { protected: char name[80]; //person's name int age; //person's age public: void getData() //get person's data { cout << "\n Enter name: "; cin >> name; cout << " Enter age: "; cin >> age; } void showData() //display person's data { cout << "\n Name: " << name; cout << "\n Age: " << age; } }; //////////////////////////////////////////////////////////////// int main() { char ch; person pers; //create person object fstream file; //create input/output file //open for append file.open("GROUP.DAT", ios::app | ios::out | ios::in | ios::binary ); do //data from user to file { cout << "\nEnter person's data:"; pers.getData(); //get one person's data //write to file file.write( reinterpret_cast<char*>(&pers), sizeof(pers) ); cout << "Enter another person (y/n)? "; cin >> ch; } while(ch=='y'); //quit on 'n' file.seekg(0); //reset to start of file //read first person file.read( reinterpret_cast<char*>(&pers), sizeof(pers) ); while( !file.eof() ) //quit on EOF { cout << "\nPerson:"; //display person pers.showData(); //read another person file.read( reinterpret_cast<char*>(&pers), sizeof(pers) ); } cout << endl; return 0; }
Do you mean because the strings are of undefined length, the file I/O messed up?
•
•
Join Date: May 2007
Posts: 15
Reputation:
Solved Threads: 2
NOTE: Interestingly, when I tried again, here is the output:
Notice the last entry: it read the integers and char correctly, just missed the strings. Not crashing anymore...
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...
>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.
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.
•
•
Join Date: May 2007
Posts: 15
Reputation:
Solved Threads: 2
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 ><
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 ><
•
•
Join Date: May 2007
Posts: 15
Reputation:
Solved Threads: 2
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.
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.
But the same exact error happens! I must be missing something different.
C++ Syntax (Toggle Plain Text)
// This uses classes and STL to manage a listing of courses. // Created by: // Created: 5/3/07 // Modified: 5/4/07 #include <iostream> #include <iomanip> #include <fstream> #include <string> #include <vector> #include <algorithm> #include <iterator> #include <functional> // (?) using namespace std; struct cinfo { //holds course info string prefix; int number; string title; int credits; char grade; }; class course { private: string prefix; int number; string title; int credits; char grade; public: //Constructors course(); course(string, int, string, int, char); course(cinfo in); //Accessors void set(); void print() const; string get_prefix() const; int get_number() const; string get_title() const; int get_credits() const; char get_grade() const; cinfo get_info() const; //Operators bool operator < (course) const; bool operator > (course) const; course operator = (course); bool operator == (course) const; bool operator == (int n) const; bool operator != (course) const; }; //class functions... //indenting below is a little screwed up, my bad int main() { vector<course> cache; //holds courses in memory vector<course>::iterator point; //points at the cache cinfo temp //buffer struct course *buffer; //buffer class fstream file;//for file I/O //stuff happens file.open("Courses.dat", ios::out | ios::trunc | ios::binary); temp = one.get_info(); file.write(reinterpret_cast<char *>(&temp), sizeof(temp)); temp = two.get_info(); file.write(reinterpret_cast<char *>(&temp), sizeof(temp)); temp = three.get_info(); file.write(reinterpret_cast<char *>(&temp), sizeof(temp)); file.close(); cout << "Saving to file..." << endl; file.open("Courses.dat", ios::out | ios::trunc | ios::binary); file.clear(); for(point = cache.begin(); point != cache.end(); point++) { temp = point->get_info(); file.write(reinterpret_cast<char *>(&temp), sizeof(temp)); file.clear(); } file.close();//close file cout << "Loading file..." << endl; file.open("Courses.dat", ios::in | ios::binary); file.clear(); file.read(reinterpret_cast<char *>(&temp), sizeof(temp)); while (!file.eof()) { //read in file buffer = new course(temp); cache.push_back(*buffer);//place object in cache delete buffer; file.read(reinterpret_cast<char *>(&temp), sizeof(temp)); } 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.
>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:
Then you can do this:
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:
C++ Syntax (Toggle Plain Text)
// Convert this to a pipe delimited string const string course::serialize() { stringstream out; out<< prefix <<'|'<< number <<'|'<< title <<'|'<< credits <<'|'<< grade; return out.str(); }
C++ Syntax (Toggle Plain Text)
file<< pers.serialize();
I'm here to prove you wrong.
![]() |
Similar Threads
- custom .htaccess file 301 Redirect to non www form (Search Engine Optimization)
- Question about debugging .class file (Java)
- How it is possible tu use a class that is in a new vb file?? (ASP.NET)
- How to load binary content of a .class file? (Java)
Other Threads in the C++ Forum
- Previous Thread: C++ in wxWidgets
- Next Thread: C Software Programming..
| Thread Tools | Search this Thread |
api application array arrays based beginner binary bitmap c++ c/c++ calculator char char* class classes code coding compile compiler console conversion convert count data database delete desktop developer directshow dll dynamiccharacterarray email encryption error file forms fstream function functions game generator getline graph homeworkhelper iamthwee ifstream input int integer java lib linux list loop looping loops map math matrix memory multiple newbie news node number numbertoword output parameter pointer problem program programming project proxy python random read recursion recursive reference return rpg sorting string strings struct template templates text tree url vector video visualstudio win32 windows winsock word wordfrequency wxwidgets






