C++: Storing data from text file in a STL Vector of pointers

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • davidleeis14
    New Member
    • Aug 2008
    • 8

    C++: Storing data from text file in a STL Vector of pointers

    I have been given and assignment to complete which is about a savings club. The club has two member types (Full and Young). I have written a abstact (Member) class with virtual functions and two classes (Full and Young) for each member type. I think I have managed to write all of my functions but there is one part of the program that I cannot seem to understand. My assignment asks for me to use a C++ STL Vector of pointers. This is what I don't understand. I have set up my program so that my program writes the members data to a text file. What I would like to know is how do I go about getting this data of the text file and stored into a vector of pointers for use in my programs functions. I can upload my code so far if you want. Text in my file is stored as (name, account number, balance, age, date)

    One other thing when I compile my code it does not seem to be to happy about the date declaration.
  • arnaudk
    Contributor
    • Sep 2007
    • 425

    #2
    Originally posted by davidleeis14
    My assignment asks for me to use a C++ STL Vector of pointers.
    Create a vector of base pointers std::vector<Mem ber*>, in that vector you can store the pointers of derived classes Young* and Full*.
    Originally posted by davidleeis14
    What I would like to know is how do I go about getting this data of the text file and stored into a vector of pointers for use in my programs functions.
    Are you able to read the data from the text file, parse the entries and use them to create Member-derived objects? If so then you're nearly there.
    Originally posted by davidleeis14
    One other thing when I compile my code it does not seem to be to happy about the date declaration.
    What date declaration?

    Comment

    • davidleeis14
      New Member
      • Aug 2008
      • 8

      #3
      Thanks for the reply, so in my main function I would want to:

      Read in data from file

      Create a vector like this vector<Member*>//i am using namespace std so no need for std::???

      How do I go about getting the data from the file into the vector and how do I go about storing the vectors of the derived classes from that vector (how do I let the vector know which derived class I am using)

      Pass the data to functions

      Clear and delete vectors.

      I have written a menu which points to the functions, how would I use this with my vector.

      BTW where you meant to say pass the entries?

      Comment

      • arnaudk
        Contributor
        • Sep 2007
        • 425

        #4
        Originally posted by davidleeis14
        Create a vector like this vector<Member*>//i am using namespace std so no need for std::???
        That's true but it's generally regarded as good practice to not to 'using namespace std' but to use std:: instead on anything but the smallest projects. The std namespace is here for a reason, you'll get pretty quick at typing it soon.
        Originally posted by davidleeis14
        How do I go about getting the data from the file into the vector and how do I go about storing the vectors of the derived classes from that vector (how do I let the vector know which derived class I am using)
        That's the point of using a vector of base pointers. A Full is a Member, so it can go in a vector of Member*s, the vector doesn't know that you're storing Full* or Young*, only that you're storing Member*s. If you call a virtual Member* method on an element of your vector that happens to be a Full*, then the appropriate method of the derived class Full* will be called. You only need one vector to do the job and no vector of vectors, etc.
        Originally posted by davidleeis14
        I have written a menu which points to the functions, how would I use this with my vector.
        If the functions are virtual base class methods, you call them on your vector of members like this: members[i]->thefunction( )
        Originally posted by davidleeis14
        BTW where you meant to say pass the entries?
        I didn't say pass, I said parse. When you read your text file you'll have to turn the resulting strings into integers and other data which you use to construct Member-derived objects. This is called "parsing the string".

        Comment

        • davidleeis14
          New Member
          • Aug 2008
          • 8

          #5
          Thanks for that but I still do not understand how I each element of data from my text file in the format (name, accountNumber, balance, age, date) into a vector when you can only store data of the same type.

          So I read in the file like below

          //file open, call it members
          members >> name >> accountNumber >> balance >> age >> date

          How do I store all this in a vector of pointers and pass the above data to my programs other functions? Sorry if I sound dumb, but I am getting worried about not getting this done.

          Comment

          • arnaudk
            Contributor
            • Sep 2007
            • 425

            #6
            Originally posted by davidleeis14
            Thanks for that but I still do not understand how I each element of data from my text file in the format (name, accountNumber, balance, age, date) into a vector when you can only store data of the same type.
            Your vector doesn't store the age, date, etc. It does store data of the same type: pointers to Member objects. It is the Member (derived) objects which store the age, date, etc.

            I presume you have already written the Full and Young classes and that you're able to create Full and Young objects with a given name, balance, age, etc.

            Now, if you can do that, then you're almost there. If each line in the file represents a member, then read the file one line at a time. For each line, you create one object on the heap using new, a Full or a Young. Then you push_back the address of that object into your vector of members. At the end of the file, you will have read all the members into a vector of pointers.

            You can then pass that vector by reference to another function that calculates the total balance of all members, for example. That function will iterate through the elements of the vector, calling balance() on each entry.

            You'll shouldn't forget to iterate through your vector and delete each entry in order not to leak memory at the end of the program.

            PS: If you were doing a proper job of this, you would be using auto_ptr or smart pointers to own the memory resources. I don't suppose you'll need to do this in your assignment but it's a good thing to keep in mind.

            Comment

            • davidleeis14
              New Member
              • Aug 2008
              • 8

              #7
              Thanks for the help and sticking with us on this.

              Would something like below load the elements into the vector

              Code:
              int main()
              {
              vector <Member*> members;
              Member* def_member;
              
              
              ifstream memberdata;
              memberdata.open("members.txt");
              if ( memberdata.fail ())
              
              {
              cout << "There is an error in opening the file." << endl;
              cout << "The program will now close!" <<endl;
              exit(1);
              }
              
              while ( ! memberdata.eof())
              
              {
              memberdate >> name >> accNum >> balance >> age >> day >> month >> year;
              member m1(name, accNum, balance, age, day, month, year);
              
              m1 = new Member
              members.pushback( def_member )
              }

              Comment

              • arnaudk
                Contributor
                • Sep 2007
                • 425

                #8
                No, that won't compile. You shouldn't create Member objects, least of all on the stack. You should create Full or Young objects on the heap only: Member* m1 = new Full(name, ...)

                Comment

                • davidleeis14
                  New Member
                  • Aug 2008
                  • 8

                  #9
                  Originally posted by arnaudk
                  No, that won't compile. You shouldn't create Member objects, least of all on the stack. You should create Full or Young objects on the heap only: Member* m1 = new Full(name, ...)
                  So when I create members can I output each member type to their own file and the have two text extraction loops and after each loop put the data to file so
                  Code:
                  m1 = new Member
                  members.pushback( def_member )
                  would become
                  Code:
                  Member* m1 = new Full(name, and so on)
                  members.pushback( def_member )
                  and for the loop concering the younger members
                  Code:
                  Member* m1 = new Young(name,and so on)
                  members.pushback( def_member)

                  Comment

                  • arnaudk
                    Contributor
                    • Sep 2007
                    • 425

                    #10
                    • Why complicate your code by having a file for each member type when you can simply write the member type in the file?
                    • Why create m1 only to add something else to the vector?
                    • Have you tried to compile your code? This forum is not a compiler; you should try to compile and fix any code you have first and then post specific questions here.

                    Comment

                    • davidleeis14
                      New Member
                      • Aug 2008
                      • 8

                      #11
                      Originally posted by arnaudk
                      • Why complicate your code by having a file for each member type when you can simply write the member type in the file?
                      • Why create m1 only to add something else to the vector?
                      • Have you tried to compile your code? This forum is not a compiler; you should try to compile and fix any code you have first and then post specific questions here.
                      I have now changed my code so that when a member is written to file the member type is written at the start of the line on the text file so only one file is used. Sorry to sound dumb, but how do I go about creating a pointer and storing in the vector and how can I get the program tell which member type is which?

                      Comment

                      • arnaudk
                        Contributor
                        • Sep 2007
                        • 425

                        #12
                        You do not sound dumb to me at all, but you should read the posts above more carefully as these quesions have already been answered :-).

                        You have already correctly created the pointer m1 in post #9, now just push_back that pointer into your vector. You don't need to tell the program the type of the member when you call its methods, this will determined behind the scenes through vtable lookups. Read up a bit on polymorphism.

                        Comment

                        • davidleeis14
                          New Member
                          • Aug 2008
                          • 8

                          #13
                          Originally posted by arnaudk
                          You have already correctly created the pointer m1 in post #9, now just push_back that pointer into your vector.
                          So I need to write
                          Code:
                          m1 = new Member;
                          m1.pushback( def_member )
                          Would that do the job?

                          Comment

                          • boxfish
                            Recognized Expert Contributor
                            • Mar 2008
                            • 469

                            #14
                            I don't think so. You can't create a member object and then say it's a "new Member" afterwards. It has to be dynamically allocated from the very start. How about
                            Code:
                            Member *m1 = new Full; // or new Young.
                            // Modify m1 here.
                            members.push_back(m1);
                            Don't forget to deallocate memory after you are finished with your vector.
                            Last edited by boxfish; Aug 15 '08, 04:10 PM. Reason: Added stuff about "you can't have it be dynamically allocated afterwards".

                            Comment

                            • davidleeis14
                              New Member
                              • Aug 2008
                              • 8

                              #15
                              Code:
                              int main()
                              {
                              vector <Member*> members;
                              Member *m1 = new Full;//may be new young depending on object
                              
                              
                              ifstream memberdata;
                              memberdata.open("members.txt");
                              if ( memberdata.fail ())
                              
                              {
                              cout << "There is an error in opening the file." << endl;
                              cout << "The program will now close!" <<endl;
                              exit(1);
                              }
                              
                              while ( ! memberdata.eof())
                              
                              {
                              memberdate >> name >> accNum >> balance >> age >> Date;
                              member m1(name, accNum, balance, age, Date);
                              
                              members.pushback(m1);
                              }
                              
                              {          
                                          cout<<"Savings Scheme tracking V1.0 by David Lee"<<endl;
                                          cout << endl << "There are currently " << members.size() << " members." endl;
                                          cout<<"Welcome to the Happy Holidays savings club!"<<endl;
                                          cout<<""<<endl;
                                          cout<<""<<endl;
                                          cout<<""<<endl;
                                          cout<<"Select an option please..."<<endl;
                                          cout<<"A->Add new member 		        :"<<endl;
                                      	cout<<"B->Display all members 		    :"<<endl;
                                      	cout<<"C->Allow a member to deposit     :"<<endl;
                                      	cout<<"D->Allow a member to leave       :"<<endl;
                                      	cout<<"E->Display members who can leave :"<<endl;
                                      	cout<<"Q->Quit program                  :"<<endl;
                                      	cout<<"Select your option with the corrosponding letter	:"<<endl;
                              }       
                                      
                                      {
                                          switch(ch)
                                          
                              
                                              {
                                              case 'A':
                                              	createMemberMenu();
                                              	break;
                                              case 'B':
                                              	m1->printDetails();
                                              	break;
                                              case 'C':
                                              	m1->makeDeposit();
                                              	break;
                                              case 'D':
                                              	get_balance();
                                              	break;
                                             	case 'E':
                                              	get_balance();
                                              	break;
                                             	default:
                                                  
                                                  exit(1)
                              
                              
                              
                              //this will be run when the program closes to prevent memory leaks
                              delete m1
                              if( !members.empty() )
                               {
                                    members.clear();
                               }
                               
                               if( members.empty() )
                               {
                                    cout << "Program state saved, now closing..." << endl;
                               }
                               cout << endl;
                               exit(1)
                              
                              }
                              The above is what I have got so far. You may have noticed that I am calling functions using the -> in my menu. How does this know which member that I am talking about?

                              Comment

                              Working...