Solved

Linked List load from file

Posted on 2003-11-25
30
1,568 Views
Last Modified: 2013-12-14
I am trying to load a linked list from file and it is not working... at all.

For each entry there is a line item in the file:
   The Book Title
   A. Jackson
   etc...

In my Driver, I am calling the function like this:      
    string book1 = "books1.txt";
    test.loadFromFile(book1);            

The function is (that is in a separate .cpp file):

bool llistBooks::loadFromFile(string fileName)
{
ifstream in;
in.open("fileName");
bookNodePtr here = head;
for (here; here != NULL; here = here->next)
      in >> here->title;
      in >> here->author;
      in >> here->publisher;
      in >> here->isbn;
      in >> here->price;
      in >> here->cost;
                delete here;

in.close();
return true;
}
0
Comment
Question by:puckerhoop
  • 16
  • 12
  • 2
30 Comments
 
LVL 4

Expert Comment

by:n_fortynine
ID: 9820900
Seems you forgot a couple things:
for( .. )
{

}

And you do not have to delete here, because it is only an external pointer. Only need to set it to NULL.
here = NULL;

Are you sure the list has enough nodes to contain the records from the file?
0
 
LVL 11

Expert Comment

by:bcladd
ID: 9820907
(1) You pass a string parameter that contains the file name. Don't use quotes around it:

  in.open(fileName); // instead of in.open("fileName");

(2) Put a test to make sure the file opened after you open it:

  in.open(fileName);
  if (!in) { // something when wrong opening the file
    cout << "Something went wrong opening the file " << fileName << endl;
    return false;
  }

Hope this helps, -bcl
0
 
LVL 4

Expert Comment

by:n_fortynine
ID: 9820908
And in >> will stop at the first space it encounters, so it's better to use getline.
0
ScreenConnect 6.0 Free Trial

Explore all the enhancements in one game-changing release, ScreenConnect 6.0, based on partner feedback. New features include a redesigned UI, app configurations and chat acknowledgement to improve customer engagement!

 
LVL 11

Expert Comment

by:bcladd
ID: 9820922
I am getting that n_fortynine is on to something: You want to create the elements that go into your linked list so the loop should probably be an eof-controlled loop with appropriate calls to the insert function (read one record and insert it, read the next record and insert it, etc. until the file is done).

-bcl
0
 

Author Comment

by:puckerhoop
ID: 9821029
yes, i missed the {}.. tx!
and i have added the test... good point!

NO I do not have enough nodes!  i will change that

when i try to use in.open(filename):
     i get the following error:
:\Program Files\MS Visual C\llistbook.cpp(139) : error C2664: 'void __thiscall std::basic_ofstream<char,struct std::char_traits<char> >::open(const char *,int)' : cannot convert parameter 1 from 'class std::basic_string<char,struct std::char_traits
<char>,class std::allocator<char> >' to 'const char *'
        No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called

getline also gets errors:
C:\Program Files\MS Visual C\llistbook.cpp(170) : error C2784: 'class std::basic_istream<_E,_Tr> &__cdecl std::operator >>(class std::basic_istream<_E,_Tr> &,_E *)' : could not deduce template argument for 'class std::basic_istream<_E,_Tr> &' from '
'
C:\Program Files\MS Visual C\llistbook.cpp(170) : error C2677: binary '>>' : no global operator defined which takes type 'class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >' (or there is no acceptable conversion)
Error executing cl.exe.
0
 
LVL 4

Expert Comment

by:n_fortynine
ID: 9821043
that has better be in.open(fileName.c_str());
0
 
LVL 4

Expert Comment

by:n_fortynine
ID: 9821054
What does your line 170 look like?
0
 

Author Comment

by:puckerhoop
ID: 9821112
line 170:

getline >> here->title;

this is not right, is it?
0
 

Author Comment

by:puckerhoop
ID: 9821118
better:
      getline(in, here->title);
0
 
LVL 4

Expert Comment

by:n_fortynine
ID: 9821132
that is not how you use getline. Nice try though :).

if title is of type char*:
in.getline(<char*>, <maximum number of letters>, <delimiter>);

if title is of type string:
getline(in, title, <delimiter>);

So some example calls would be:
//if title is declared to be char[80];
in.getline(title, 79, '\n');

or
//if title is std::string
getline(in, title, '\n');
0
 

Author Comment

by:puckerhoop
ID: 9821138
I always have the toughest time outputting to file!

The above is getting error:
C:\Program Files\MS Visual C\llistbook.cpp(176) : error C2780: 'class std::basic_istream<_E,_Tr> &__cdecl std::getline(class std::basic_istream<_E,_Tr> &,class std::basic_string<_E,_Tr,_A> &,const _E)' : expects 3 arguments - 2 provided
        c:\program files\microsoft visual studio\vc98\include\string(149) : see declaration of 'getline'
0
 
LVL 4

Expert Comment

by:n_fortynine
ID: 9821141
should be here->title instead of just title, I'm sorry.
0
 

Author Comment

by:puckerhoop
ID: 9821175
That is much better... the only problem is, that it does not now recogize the pieces of the struct (title, author, etc...).  Should these be temp?  But then how would I load into node?
0
 
LVL 4

Expert Comment

by:n_fortynine
ID: 9821273
Your question is quite vague. Who does not recognize the title author variables (which I believe is part of your struct bookNode - or something similar to that?)? The compiler? Does it give you any compile errors? Or run-time errors?
0
 

Author Comment

by:puckerhoop
ID: 9821294
I redid the code and the function is clean
BUT it will not load from my driver program.  
The driver just completely bypasses the function!
llistBooks is my class.  Then I try and call the function:

llistBooks test;            //declaration of an empty list of books
test.loadFromFile(book1);            //load data from file
0
 
LVL 4

Expert Comment

by:n_fortynine
ID: 9821318
if you list is empty, how do you suppose it will look like?
A single NULL head pointer.
then how would this code behave: (I assume you haven't changed it have you?)

>>bookNodePtr here = head;
>>for (here; here != NULL; here = here->next)

I'm quote bcladd's advice here (so that I don't have to type it down again)

>>I am getting that n_fortynine is on to something: You want to create the elements that go into your linked list so the >>loop should probably be an eof-controlled loop with appropriate calls to the insert function [b](read one record and >>insert it, read the next record and insert it, etc. until the file is done).[/b]
>>
>>-bcl
0
 

Author Comment

by:puckerhoop
ID: 9821319
This is what I am getting when it tries to compile

Loaded 'ntdll.dll', no matching symbolic information found.
Loaded 'C:\WINDOWS\system32\kernel32.dll', no matching symbolic information found.

etc...
there are a whole lot of errors similar to the last one.
0
 
LVL 4

Expert Comment

by:n_fortynine
ID: 9821348
I'm assuming you're using VC++? I think it's saying you don't have a debugger for your compiler.
0
 
LVL 4

Expert Comment

by:n_fortynine
ID: 9821350
Is this an application dealing with API calls? You might want to check the settings of your project.
0
 

Author Comment

by:puckerhoop
ID: 9821359
The function is not opening at all from the driver.
The function now looks like this:

bool llistBooks::loadFromFile(string fileName)
{ifstream in;
in.open(fileName.c_str());
if(!in)
cout << "There was a problem saving files";
else
{      string Ititle, Iauthor, Ipublisher, Iisbn, Iprice, Icost;
      bookNodePtr here;
      here = head;
      for (here; !EOF; here = here->next)
            { getline(in,Ititle,'\n');
            here->title = Ititle;
            getline(in,Iauthor, '\n');
            here->author = Iauthor;
            getline(in,Ipublisher,'\n');
            here->publisher;
            getline(in,Iisbn, '\n');
            here->isbn;
            getline(in,Iprice, '\n');
            here->price;
            getline(in,Icost, '\n');
            here->cost;            }
0
 
LVL 4

Expert Comment

by:n_fortynine
ID: 9821384
What you should be doing is something like:

bool llistBooks::loadFromFile(string fileName) {
   ifstream in;
   in.open(fileName.c_str());
   if(!in)
      cout << "There was a problem saving files";
   else {
      bookNode  tempNode; /*I assume that's the name of your struct Node.*/
      while(!in.eof()) {
          getline(in, tempNode->title, '\n');
          getline(in, tempNode->author, '\n');
          //Do some more here to get information you want.
          //Now I assume you have a function to insert into the list called insertNode.
          this->insertNode(tempNode);
          //Change the parameter list to match your own function.
      }
   }

We now have the insert function taking care of allocating memory (creating new bookNodes) for you.
Makes any sense to you?
0
 
LVL 4

Expert Comment

by:n_fortynine
ID: 9821385
I'm missing a } at the end. =)
0
 
LVL 4

Expert Comment

by:n_fortynine
ID: 9821389
Let me clean that up then

bool llistBooks::loadFromFile(string fileName) {
   ifstream in;
   in.open(fileName.c_str());
   if(!in) {
      cout << "There was a problem saving files";
      return false;
   }
   else {
      bookNode  tempNode; /*I assume that's the name of your struct Node.*/
      while(!in.eof()) {
          getline(in, tempNode->title, '\n');
          getline(in, tempNode->author, '\n');
          //Do some more here to get information you want.
          //Now I assume you have a function to insert into the list called insertNode.
          this->insertNode(tempNode);
          //Change the parameter list to match your own function.
      }
   }
   in.close();
   return true;
}
0
 

Author Comment

by:puckerhoop
ID: 9821459
I have set the insertion up.  So I think that the function is clean.
The standing issue is that I am unable to access from my driver.
I have not used a BOOL function in this way before... am I calling it wrong (ie. not allowing it to return?)

llistBooks test;            //declaration of an empty list of books
test.loadFromFile(book1);            //load data from file


I get the following error:
First-chance exception in books_test.exe: 0xC0000005: Access Violation.

It locks up in the XSTRING file:
void insert(iterator _P, _It _F, _It _L)
      {replace(_P, _P, _F, _L); }
_Myt& erase(size_type _P0 = 0, size_type _M = npos)
**      {if (_Len < _P0)
0
 
LVL 4

Expert Comment

by:n_fortynine
ID: 9821495
C++ should allow you to call a bool function in C style so it's OK (though not recommended) to do test.loadFromFile(book1);

If possible, would you be willing to post your code here so we could have a better look at what's causing that error? Access violation can be many things, but in this case it sounds like a memory access problem.
0
 

Author Comment

by:puckerhoop
ID: 9821511
If I step in I can get in the function and I get the access violation and  above mentioned errors on this line:
      getline(in,here->title,'\n');
0
 
LVL 4

Expert Comment

by:n_fortynine
ID: 9821520
Could you post the new entire loadFromFile function that you've just fixed?
0
 

Author Comment

by:puckerhoop
ID: 9821573
This is the current code (if you need more background code, ie. the struct or class, etc. let me know):
(normally would include #include "llistBook.cpp" (the function file) and NOT had the ".h" file, but when I do this, i am getting this error:
llistbook.obj : error LNK2005: "public: bool __thiscall llistBooks::deleteB(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (?deleteB@llistBooks@@QAE_NV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@
@std@@@Z) already defined in books_test.obj)


DRIVER:
#include <string>
#include <iostream>
#include <fstream>
using namespace std;
#include "llistBook.h"            //llistBook class definition
void main ()  {
      string book1 = "books1.txt";
      llistBooks test;            
      test.loadFromFile(book1);            
...}


FUNCTION (in separate file):
bool llistBooks::loadFromFile(string fileName)
{ ifstream in;
in.open(fileName.c_str());
if(!in)
      cout << "There was a problem saving files";
else
      { string Iprice, Icost;
                bookNodePtr here;
      here = head;
      do
      {      getline(in,here->title,'\n');
            getline(in,here->author, '\n');
            getline(in,here->publisher,'\n');
            getline(in,here->isbn, '\n');
            getline(in,Iprice, '\n');
            here->price;
            getline(in,Icost, '\n');
            here->cost;
            here->next;
      }while(!EOF);
      delete here;      }
      in.close();
      return true;      }
0
 

Author Comment

by:puckerhoop
ID: 9821579
one code change:
here->next;
is now:
      this->newNode(here);
0
 
LVL 4

Accepted Solution

by:
n_fortynine earned 500 total points
ID: 9821600
Let me explain this. The problem with this code is that it is trying to access memory that has not yet been allocated.
Read the post I posted at 3:10PM. I advised you to call the insert function WITHIN the loadfromFile function.

Why? Because as you could notice you are creating an entirely new list from main.
>>    llistBooks test;
Unless you have created a fully functional list with many many nodes in the constructor of llistBooks, which I don't think anybody would do, and which I don't think you should do either, UNLESS that has happened, your list contains only a head pointer with a value NULL. There is no memory.

When you try to set:
>>here = head;
what do you think here is set to? NULL, of course.
So from now on, all references to here->title, here->author, etc. would make no sense, because they don't actually exist.

That's why if you already have an insert function (please look at my post at 3:10PM again) then use it. It doesn't hurt and would save you from some hard, error-prone labor. :)
0

Featured Post

What is SQL Server and how does it work?

The purpose of this paper is to provide you background on SQL Server. It’s your self-study guide for learning fundamentals. It includes both the history of SQL and its technical basics. Concepts and definitions will form the solid foundation of your future DBA expertise.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

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…
Update (December 2011): Since this article was published, the things have changed for good for Android native developers. The Sequoyah Project (http://www.eclipse.org/sequoyah/) automates most of the tasks discussed in this article. You can even fin…
This tutorial covers a step-by-step guide to install VisualVM launcher in eclipse.
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.

832 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