Linked List load from file

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;
}
puckerhoopAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

n_fortynineCommented:
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
bcladdCommented:
(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
n_fortynineCommented:
And in >> will stop at the first space it encounters, so it's better to use getline.
0
Introduction to Web Design

Develop a strong foundation and understanding of web design by learning HTML, CSS, and additional tools to help you develop your own website.

bcladdCommented:
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
puckerhoopAuthor Commented:
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
n_fortynineCommented:
that has better be in.open(fileName.c_str());
0
n_fortynineCommented:
What does your line 170 look like?
0
puckerhoopAuthor Commented:
line 170:

getline >> here->title;

this is not right, is it?
0
puckerhoopAuthor Commented:
better:
      getline(in, here->title);
0
n_fortynineCommented:
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
puckerhoopAuthor Commented:
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
n_fortynineCommented:
should be here->title instead of just title, I'm sorry.
0
puckerhoopAuthor Commented:
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
n_fortynineCommented:
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
puckerhoopAuthor Commented:
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
n_fortynineCommented:
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
puckerhoopAuthor Commented:
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
n_fortynineCommented:
I'm assuming you're using VC++? I think it's saying you don't have a debugger for your compiler.
0
n_fortynineCommented:
Is this an application dealing with API calls? You might want to check the settings of your project.
0
puckerhoopAuthor Commented:
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
n_fortynineCommented:
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
n_fortynineCommented:
I'm missing a } at the end. =)
0
n_fortynineCommented:
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
puckerhoopAuthor Commented:
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
n_fortynineCommented:
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
puckerhoopAuthor Commented:
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
n_fortynineCommented:
Could you post the new entire loadFromFile function that you've just fixed?
0
puckerhoopAuthor Commented:
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
puckerhoopAuthor Commented:
one code change:
here->next;
is now:
      this->newNode(here);
0
n_fortynineCommented:
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

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Editors IDEs

From novice to tech pro — start learning today.