[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1577
  • Last Modified:

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;
}
0
puckerhoop
Asked:
puckerhoop
  • 16
  • 12
  • 2
1 Solution
 
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
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
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

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 16
  • 12
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now