Solved

Linked List load from file

Posted on 2003-11-25
30
1,562 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
Comment Utility
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
Comment Utility
(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
Comment Utility
And in >> will stop at the first space it encounters, so it's better to use getline.
0
 
LVL 11

Expert Comment

by:bcladd
Comment Utility
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
Comment Utility
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
Comment Utility
that has better be in.open(fileName.c_str());
0
 
LVL 4

Expert Comment

by:n_fortynine
Comment Utility
What does your line 170 look like?
0
 

Author Comment

by:puckerhoop
Comment Utility
line 170:

getline >> here->title;

this is not right, is it?
0
 

Author Comment

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

Expert Comment

by:n_fortynine
Comment Utility
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
Comment Utility
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
Comment Utility
should be here->title instead of just title, I'm sorry.
0
 

Author Comment

by:puckerhoop
Comment Utility
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
Comment Utility
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
Comment Utility
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
Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

 
LVL 4

Expert Comment

by:n_fortynine
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
Is this an application dealing with API calls? You might want to check the settings of your project.
0
 

Author Comment

by:puckerhoop
Comment Utility
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
Comment Utility
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
Comment Utility
I'm missing a } at the end. =)
0
 
LVL 4

Expert Comment

by:n_fortynine
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
Could you post the new entire loadFromFile function that you've just fixed?
0
 

Author Comment

by:puckerhoop
Comment Utility
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
Comment Utility
one code change:
here->next;
is now:
      this->newNode(here);
0
 
LVL 4

Accepted Solution

by:
n_fortynine earned 500 total points
Comment Utility
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

Top 6 Sources for Identifying Threat Actor TTPs

Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

Join & Write a Comment

Article by: SunnyDark
This article's goal is to present you with an easy to use XML wrapper for C++ and also present some interesting techniques that you might use with MS C++. The reason I built this class is to ease the pain of using XML files with C++, since there is…
Jaspersoft Studio is a plugin for Eclipse that lets you create reports from a datasource.  In this article, we'll go over creating a report from a default template and setting up a datasource that connects to your database.
The viewer will learn how to synchronize PHP projects with a remote server in NetBeans IDE 8.0 for Windows.
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.

772 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

10 Experts available now in Live!

Get 1:1 Help Now