Solved

store data of a linked-list

Posted on 2003-12-10
15
1,204 Views
Last Modified: 2013-12-14
Hi C++ Experts,

    The following is an unfinished program, but I guess it would be enough to demostrate the question that I want to ask :
-----------------------------------------------
#include <cstdio>
#include <list>
#include <iostream>
#include <string>

int main()
{
   list<string> person;
   int flag = 1 ;

 while(flag){
   system("clear") ;
   cout << "-----------------------------------" << endl ;
   cout << " Choose one of the following items : " << endl ;
   cout << " 0. exit and save "<< endl ;
   cout << " 1. add a name " << endl ;
   cout << " 2. delete a name " << endl ;
   cout << " 3. select a name and change " << endl ;
   cout << " 4. display the list " << endl ;
   cout << " Please enter a number : " << endl ;

  char choice ;
   cin >> choice ;

   switch(choice){
     case '0' :
       flag = 0 ; break ;
     case '1' :
     {   cout << "please enter the name : " << endl ;
         string temp ;
         cin.ignore(80,'\n');
         getline(cin, temp) ;
         person.push_back(temp) ;
         break ;
     }
     case '2' :
     {   cout << "please enter the name : " << endl ;
         string temp ;
         cin.ignore(80,'\n');
         getline(cin, temp) ;
         person.remove(temp) ;
         break ;
     }

    case '3' :
     {   cout << "please enter the name : " << endl ;
         string temp ;
         cin.ignore(80,'\n');
         getline(cin, temp) ;
         list<string>::iterator it ;
         for(it=person.begin() ; it!=person.end() ;it++){
           if(temp == *it) person.remove(temp) ;}
         cout << "we will change " << temp << endl ;
         cout << "please enter the new name :" << endl ;
         cin.ignore(80,'\n') ;
         getline(cin,temp) ;
         person.insert(it,temp) ;
         break ;
      }

      case '4' :
      {   list<string>::iterator it ;
         system("clear") ;
         for(it=person.begin() ; it!=person.end() ;it++){
           cout << *it << endl ;}
         cout << endl << endl << endl << endl;
         cout << " Press a key to continue ....... " << endl ;

         getchar() ;
         cin.ignore() ;
         break ;
      }
      default :
      {
        break ;
      }

   }//swithch
 }//flag

  return 0 ;

}
---------------------------------------
  Here is my question. Everytime we exit the program, we will lose all the data we typed in this time. I am wondering how to save them, so that next time when I run the code again, the data I typed today would still be there. I might be able to dump them into a text file for now since it is only a list of strings. However, I understand that it won't be that easy while I have a list of "blah_blah" in the future .... because the "blah_blah" could be a very complicated structure.

  Therefore, I am wondering what's the standard way of dealing with this situation ? Do people link the database ? or what do they do ? Also, if I want to do things like this, which topic should I go ahead and study ? Thanks very much !!!

meow.....
0
Comment
Question by:meow00
  • 7
  • 5
  • 3
15 Comments
 
LVL 86

Expert Comment

by:jkr
Comment Utility
>>  Therefore, I am wondering what's the standard way of dealing with this situation ?

There is no 'standard' way - the most common one would be add 'serialization' support to the classes that you want to store in the STL container, e.g.

class foo {

//...

public:

  void read ( ostream& os) {

      // read contents from file
  }
  void write ( istream& os) {

      // write contents to file
  }

};
0
 
LVL 17

Expert Comment

by:rstaveley
Comment Utility
If this is a study excercise, I'd suggest looking at writing/reading the strings to a text file.

You already have

--------8<--------
         for(it=person.begin() ; it!=person.end() ;it++){
           cout << *it << endl ;}
--------8<--------

That writes the strings to the standard output.

Your next step should be to look at writing the strings in a similar manner to a file instead of cout.

e.g.
--------8<--------
         {
             ofstream fout("strings.txt"); // See http://www.cplusplus.com/ref/iostream/ofstream/
             for(it=person.begin() ; it!=person.end() ;it++){
                 fout << *it << endl ;}
         } // End the scope - this automatically closes fout
--------8<--------

You already have
--------8<--------
         getline(cin, temp) ;
         person.push_back(temp) ;
--------8<--------

Look at loading persons from a file, using ifstream
e.g.
--------8<--------
         {
             ifstream fin("strings.txt"); // See http://www.cplusplus.com/ref/iostream/ifstream/
             string temp;
             while (getline(cin, temp))
                 person.push_back(temp) ;
         } // End the scope - this automatically closes fin
--------8<--------
0
 
LVL 17

Expert Comment

by:rstaveley
Comment Utility
Ooops....

Look at loading persons from a file, using ifstream
e.g.
--------8<--------
         {
             ifstream fin("strings.txt"); // See http://www.cplusplus.com/ref/iostream/ifstream/
             string temp;
             while (getline(fin, temp))  /* I meant fin not cin - you can see that they work similarly */
                 person.push_back(temp) ;
         } // End the scope - this automatically closes fin
--------8<--------
0
 
LVL 1

Author Comment

by:meow00
Comment Utility
Hi jkr ..... thanks a lot ! And I am wondering is there any good text book or website giving tutorial about the "serialization" ? I am new to this and I could not find them in the standard C++ books ..... Thanks very much !

meow...
0
 
LVL 1

Author Comment

by:meow00
Comment Utility
Hello rstavely, Thanks for the answers !
But I guess my biggest problem would be :
If I have a list of person object
------------------------
class person{
   float weight ;
   int age ;
   string name ;
   class car ;
} ;

class car{ blah } ;
------------------------
I couldn't really dump them to a file ....... do you have any better ideas ? thanks !

meow.
0
 
LVL 86

Assisted Solution

by:jkr
jkr earned 80 total points
Comment Utility
>>And I am wondering is there any good text book or website giving tutorial about the "serialization" ?

There are actually a lot - I remember http://www.codeproject.com/cpp/serialization_primer1.asp being pretty informative (even though it deals with MFC), but the site gives an internal server error at the time...
0
 
LVL 1

Author Comment

by:meow00
Comment Utility
>There are actually a lot - I remember >http://www.codeproject.com/cpp/serialization_primer1.asp being pretty informative (even >though it deals with MFC), but the site gives an internal server error at the time...

er.... is the website there ??? or my webbrowser has problems ? thanks

meow.
0
Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

 
LVL 86

Expert Comment

by:jkr
Comment Utility
The site is there, as I wrote: The server seems to have problems at this time...
0
 
LVL 17

Expert Comment

by:rstaveley
Comment Utility
This should give you an idea about reading/writing person from/to file. I've delimited fields with '|' for no very good reason. I've used getline so that strings can contain ' ';

--------8<--------
#include <iostream>
#include <fstream>
#include <string>
#include <list>
#include <limits>

class car {
      std::string name;
      template<class c> friend std::basic_ostream<c>& operator<<(std::basic_ostream<c>&,const car&);
      template<class c> friend std::basic_istream<c>& operator>>(std::basic_istream<c>&,car&);
public:      car() {}
      car(const std::string& name) : name(name) {}
      car(const car& copycar) : name(copycar.name) {}
};

// This allows the car class to be written to an ostream
template<class c> std::basic_ostream<c>& operator<<(std::basic_ostream<c>& os,const car& buggy)
{
      return os << buggy.name;
}

// This allows the car class to be read from an istream, it assumes that the field
// is delimited by '|'
template<class c> std::basic_istream<c>& operator>>(std::basic_istream<c>& is,car& buggy)
{
      if (!getline(is,buggy.name,'|'))
            return is;

      //is.ignore(std::numeric_limits<std::streamsize>::max(),'|');

      return is;
}

class person{
      float weight;
      int age;
      std::string name;
      car buggy;
      template<class c> friend std::basic_ostream<c>& operator<<(std::basic_ostream<c>&,const person&);
      template<class c> friend std::basic_istream<c>& operator>>(std::basic_istream<c>&,person&);
public:      person() {}
      person(const std::string& name,int age,float weight,const car& buggy)
            : weight(weight),age(age),name(name),buggy(buggy) {}
};

// This allows the person class to be written to an ostream
template<class c> std::basic_ostream<c>& operator<<(std::basic_ostream<c>& os,const person& bod)
{
      return os
            << bod.name << '|'      /* Use this delimiter so we can have spaces in the name */
            << bod.age << '|'
            << bod.weight << '|'
            << bod.buggy << '|';
}

// This allows the person class to be read from an istream, where fields are delimited by '|'
template<class c> std::basic_istream<c>& operator>>(std::basic_istream<c>& is,person& bod)
{
      if (!getline(is,bod.name,'|'))
            return is;

      //is.ignore(std::numeric_limits<std::streamsize>::max(),'|');

      if (!(is >> bod.age))
            return is;

      is.ignore(std::numeric_limits<std::streamsize>::max(),'|');

      if (!(is >> bod.weight))
            return is;

      is.ignore(std::numeric_limits<std::streamsize>::max(),'|');

      return is >> bod.buggy;
}

int main()
{
      std::list<person> folk;

// Read the folk.dat file, if it exists and load the folf into our list

      {
            std::ifstream fin("folk.dat");
            if (fin) {
                  std::cout << "\nHere's the folk we read:\n\n";
                  person temp;
                  while (fin >> temp) {
                        folk.push_back(temp);
                        std::cout << '\t' << temp << '\n';
                  }
            }
      }

// Let's add some more folk

      folk.push_back(person("Fred Bassett",46,120,car("Ford Cortina")));
      folk.push_back(person("Krazy Kat",87,97,car("Datsun Sunny")));

// Write the folk back to file

      {
            std::ofstream fout("folk.dat");
            if (fout) {
                  std::cout << "\nHere's the folk we are writing:\n\n";
                  for (std::list<person>::const_iterator citr = folk.begin();citr != folk.end();++citr) {
                        std::cout << '\t' << *citr << '\n';
                        fout << *citr;
                  }
            }
      }

}
--------8<--------

Try it out and do have a look at the contents of the text file "folk.dat", which (be warned) does not separate persons with lineline characters. I'll leave that to you if you want it :-)
0
 
LVL 17

Expert Comment

by:rstaveley
Comment Utility
> lineline

newline
0
 
LVL 1

Author Comment

by:meow00
Comment Utility
Thanks for all the answers ! Just another short question ... so for the above example provided by rstaveley, is that a kind of "serialization" as well ? or it is something else ???
Thanks very much !!!

meow...
0
 
LVL 17

Accepted Solution

by:
rstaveley earned 220 total points
Comment Utility
Reading and writing of objects to file to allow them to persist is known as serialisation - with a 'z' really, but I can't get used to American spellings :-)

The codeproject tutorial at http://www.codeproject.com/cpp/serialization_primer2.asp shows Microsoft's approach for serialisation, but that's by no means the only way of doing it. I like human-readable files where performance isn't an issue and ideally I'd like my objects to persist in XML files, but that adds the complexity of a SAX parser for reading objects so the delimited text file is a happy compromise.

The approach I've outlined is pretty sketchy, because it doesn't address issues like what to do if one of your strings has a '|' character in it (that's where XML looks apealing), but it works nicely enough for most purposes.

The example I showed you makes the ostream operator<< overload always show the object in the manner required for serialisation. You can improve upon the design by using an ios::iword flag for "serialization mode"/"non-serialization mode" to get the ostream operator<< to display the serialization-friendly format when the ostream is in "serialization mode" and something human-friendly, when it is not.

e.g. Here's an example with a simple structure unimaginatively called X - you could easily adopt the same approach for your person and car classes:
--------8<--------

/* Demonstrating use of a iword formatting flag for serialisation in the stream */

#include <iostream>

// Globals for serialization
namespace serializer {

        const int NotSerializing = 0; // Stream is not serializing - default mode is 0
        const int Serializing = 1; // Stream is serializing

        // Allocate out global ios::iword index
        const int index = std::ios_base::xalloc();

        // Returns true if the ostream is in serialisation mode
        template<class C>
        inline bool is_serializing(std::basic_ostream<C>& os)
        {
                return os.iword(index) == Serializing;
        }

        // Set the ostream's serialisation mode
        template<class C>
        inline void serialize(std::basic_ostream<C>& os,bool goforit = true)
        {
                os.iword(index) = goforit ? Serializing : NotSerializing;
        }

} // serializer namespace

struct X {
        int a,b;
        X(int a,int b) : a(a),b(b) {}
};

// Display the X object on an ostream - display depends on serialization mode
template<class C>
std::basic_ostream<C>& operator<<(std::basic_ostream<C>& os,const X& x)
{
        if (serializer::is_serializing(os)) {
                os << x.a << '|' << x.b;
        }
        else {
                os << "A value is " << x.a << ", and B value is " << x.b;
        }
        return os;
}

int main()
{
        X x(1,2);

        // ostreams are by default not in serialization mode
        std::cout << "x without serialization: " << x << '\n';

        serializer::serialize(std::cout); // Put the stream into serialization mode
        std::cout << "x with serialization: " << x << '\n';

        serializer::serialize(std::cout,false); // Put the stream into non-serialization mode
        std::cout << "x without serialization: " << x << '\n';
}
--------8<--------
0
 
LVL 17

Expert Comment

by:rstaveley
Comment Utility
meow00, looking at http:/QH_1517700.html I see that you have questions open dating back to October :-(
0
 
LVL 1

Author Comment

by:meow00
Comment Utility
Thanks very much for all these ..... I need to spend next few days on the serialization now :-)
0
 
LVL 17

Expert Comment

by:rstaveley
Comment Utility
Glad to have been able to help. Best of luck.
0

Featured Post

Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

Join & Write a Comment

Introduction This article is the first in a series of articles about the C/C++ Visual Studio Express debugger.  It provides a quick start guide in using the debugger. Part 2 focuses on additional topics in breakpoints.  Lastly, Part 3 focuses on th…
This article will show you some of the more useful Standard Template Library (STL) algorithms through the use of working examples.  You will learn about how these algorithms fit into the STL architecture, how they work with STL containers, and why t…
This tutorial covers a step-by-step guide to install VisualVM launcher in eclipse.
The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…

743 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

8 Experts available now in Live!

Get 1:1 Help Now