Thread: Using string type in class for file storage

  1. #1
    Registered User johnnyd's Avatar
    Join Date
    Mar 2002
    Posts
    70

    Question Using string type in class for file storage

    Hey fellas, question:

    Is is legal to store a class to file when one or more of it's members are of the string type?

    I tried doing this and I get a fatal runtime error, in which the string.cc file is brought up and one of the lines highlighted:

    Code:
     string::traits_type::char_out(os, s[x]);
    The full code for the block (with the problem line highlighted) is as follows:

    Code:
    ostream& RWSTDExport operator<< (ostream & os, const string& s)
    {
        typename string::size_type x;
        if ((os.flags() & ios::adjustfield) == ios::right)
           for (x = 0; x < os.width() - s.length(); x++)
              string::traits_type::char_out(os, os.fill());
        for (x = 0; x < s.length() ; x++)
            string::traits_type::char_out(os, s[x]);
        if ((os.flags() & ios::adjustfield) == ios::left)
           for (x = s.length(); x < os.width(); x++)
              string::traits_type::char_out(os, os.fill());
        return os;
    }
    Remember, all the code I have shown you above is from the string.cc header file. (#include <string>).

    If anyone has even the foggiest idea of what this means, I'd appreciate your help.
    Excuse me, while I water my money tree.

  2. #2
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    It would be alot easier to determine the root cause if you post your code - I doubt there is something wrong with the string implementation you are using (although possible).

    gg

  3. #3
    Registered User johnnyd's Avatar
    Join Date
    Mar 2002
    Posts
    70

    Question Ok, this is a sample:

    Ok, I didn't include all of my code, just the portion that is giving issues.

    Code:
    class book{
       private:
          int isbn;
          string name, author;
       public:
          //usual constructors, accessors, mutators, destructors etc. etc.
    };
    
    void main (void)
    {
       int ISBN;
       string Name, Author;
       book bk;
       
       cin<<ISBN;
       //these getlines don't work for me, but it works for  you guys so I'm putting it here anyway
       getline(cin, name);    
       getline(cin, author);
    
       bk = book(ISBN, Name, Author); //initialise variable
    
       ofstream outbook("books.dat", ios::binary); //open file
    
       //createBook returns a bool if it can create the file.
       //createBook is a separate function not shown here.
       if (!outbook)
          if (!createBook){
             cout<<"System error: Unable to create file on disk.";
             getch();
             exit(1);
             }
    
       //write the data to the file - this works fine.
       outbook.seekp((newBook.getISBN() - 1) * sizeof(Book));
       outbook.write(reinterpret_cast< const char * >(&newBook), sizeof(Book)); 
    
       cout<<"\n\nBook data written successfully.";
    
       outbook.close();
    
       //open the file for data retrieval
       ifstream inbook("books.dat", ios::in);
    
       //if the file was not already created
       if (!inbook){
          cout<<"No customer database exists.";
          getch();
          exit(1);
          }
       
       //this is the line that is giving issues. The line is syntax error free.
       inbook.read(reinterpret_cast< char * >(&bk), sizeof(book));
    
       while (inbook && !inbook.eof()){
          if (bk.getId() != 0){
    
             bk.list(); //'list()' is a member function of the book class, 
    			}
           inbook.read(reinterpret_cast< char * >(&bk), sizeof(book));
          }
          
    }
    It is at the highlighted lines that the error occurs.
    My take on it is that strings can't be written and read via files.

    Could someone kindly confirm or deny my claims please? I'd greatly appreciate it. Thanks.
    Excuse me, while I water my money tree.

  4. #4
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    Ok, this is easier to debug...
    - If createBook is a function, shouldn't it be:
    Code:
    if (!createBook()){
    - Both these lines need a talking to:
    Code:
    (a) outbook.seekp((newBook.getISBN() - 1) * sizeof(Book));
    (b) outbook.write(reinterpret_cast< const char * >(&newBook), sizeof(Book));
    (a) I'll assume this is part of your requirements. If they enter real ISBN's you're gonna have a HUGE file. Also, ISBN of 0 and 1 will be the same. sizeof(Book) isn't right, but we'll move on to that next.
    (b) You can't do this, (have you heard of the term shallow copy?) Consider this code:
    Code:
    typedef struct _Rec_t
       char *first_name;
       char *last_name;
    } Rec_t;
    ...
    Rec_t rec;
    ...
    outf.write(reinterpret_cast<const char*>(&rec),sizeof(Rec_t));
    First, lets consider sizeof(Rec_t) - assuming 32bit architecture, a pointer will be 4bytes. So sizeof(Rec_t) will most likely be 8bytes. When you write() a Rec_t, you are basically saving the address's where string data is located in memory - not the string data itself. In order to use write() is this way, you have to have all storage in the struct/class that you are writting. Also, if you want to use fixed-size records that contain strings, the strings must be a fixed size as well:
    Code:
    typedef struct _Rec_t
       char first_name[MAX_FIRST_NAME_LEN];
       char last_name[MAX_LAST_NAME_LEN];
    } Rec_t;
    Reading and writting this struct will write data instead of pointers. Keep in mind that writting structs in this way isn't portable due to byte ordering (not in strings but ints, longs, etc)

    I'll go ahead and save Prelude a post:
    Code:
    int main() {
    gg

  5. #5
    Registered User johnnyd's Avatar
    Join Date
    Mar 2002
    Posts
    70

    Unhappy Sorry about that...

    I'm profoundly sorry... I forgot to mention a few things...

    createBook really is createBook() - my bad.

    (Dude, you're so good, you could pass as a compiler!! )

    I just rewrote little segments of the code here so it wasn't long winded and easier to understand.

    So what you're basically saying then is that I cannot write a class to file with any of the member variables defined as the string type?

    Does the string type only define them as pointers? Is that what you're saying?
    Excuse me, while I water my money tree.

  6. #6
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    They are definately implemented as pointers. I suggest that you write your own method for serializing the class to a file:
    Code:
    void book::write(ofstream &outf)
    {
       //wite each member individually
    }
    ...
    void book::read(ifstream &inf)
    {
       //read each member individually
    }
    Or you coud overload the << and >> operator for streams.
    You will still have to ensure that your strings are a fixed length to support fixed-length records. Plus, sizeof(book) will not work if you want to be able to seek[g,p]() to a particular record based on ISBN. You'll need to make a constant for the record size (which is not the same as sizeof(book):
    Code:
    #define RECORD_SIZE (MAX_NAME_LEN + MAX_AUTHOR_LEN + 4)
    gg
    Last edited by Codeplug; 03-11-2003 at 10:37 AM.

  7. #7
    Registered User johnnyd's Avatar
    Join Date
    Mar 2002
    Posts
    70

    Thumbs down Just when I thought I found something great

    Drat, double drat, it never ends.

    This is just great.

    I'm becoming more and more disappointed with C++.

    Here I was hoping, just HOPING that this string datatype would save me some code. It's so easy to use.

    But it seems that its not radically different than char*. In fact, it seems like nothing more than char* with the strcmp, strcpy etc. etc. all overloaded into the +,-,=,* etc operators and made a little more like Visual Basic.

    I'm steadily loosing respect for C++. Aside from its extensions of C, I can't swear to it's uniqueness as a language unto itself. I guess C++ is like the Broodwar addon to StarCraft.

    Anyways, thanks for clearing things up for me man. I really appreciate it.

    I have since changed out all of my string variables to char*. There's no point to me using string anywhere in my program. It works just fine now.
    Excuse me, while I water my money tree.

  8. #8
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    Well, realize that string is not a built in datatype - it's just a class (like book).

    C++ as a language isn't going to do anything for you like some other languages. It has the same built in datatypes as C: char, int, long, float, double, etc. Nothing new was added (except maybe bool, but that was added to C as well). You can think of string as a C++ class that does all the char* stuff under the hood for you (gross simplification).

    Yes, you can think of C++ as a <very powerful> addon to C. And just like in C, you can't expect any kind of magic to occur when you cast the address of a class or struct to char* and dump its memory to a file. Remember, the only difference between a struct and a class in C++ is that, by default, all members of a struct are public. C++ is still just as "low-level" as C.

    gg

  9. #9
    Registered User johnnyd's Avatar
    Join Date
    Mar 2002
    Posts
    70

    Smile Cool

    Thanks for that clarification. Now I know my buddies are chatting a lot of horse @#*$ when they say "I know C and C++".

    That's like saying "I'm familiar with Windows 95 and 98". Big deal. I prefer hard cold facts like this. Thanks again Codeplug.
    Excuse me, while I water my money tree.

  10. #10
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    Well, there are more facts than what I've given

    There is alot to learn about the C++ language semantics, even if you already know C (like classes, templates, namespaces, exceptions, etc). And on top of that are the standard library. When someone says "I know C", that usually means they know the language semantics AND the C standard libraries (the stuff inside stdio.h, stdlib.h, etc). There is alot more to learn in the C++ standard libraries. STL is now part of the standard C++ library and there are entire books on STL alone. There is also the concepts of object oriented programming and how to apply these concepts using C++.

    gg

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. String issues
    By The_professor in forum C++ Programming
    Replies: 7
    Last Post: 06-12-2007, 09:11 AM
  2. Question on l-values.
    By Hulag in forum C++ Programming
    Replies: 6
    Last Post: 10-13-2005, 04:33 PM
  3. ras.h errors
    By Trent_Easton in forum Windows Programming
    Replies: 8
    Last Post: 07-15-2005, 10:52 PM
  4. Classes inheretance problem...
    By NANO in forum C++ Programming
    Replies: 12
    Last Post: 12-09-2002, 03:23 PM
  5. creating class, and linking files
    By JCK in forum C++ Programming
    Replies: 12
    Last Post: 12-08-2002, 02:45 PM