Thread: reading a txt file into a linked list:

  1. #1
    Registered User
    Join Date
    Jul 2013
    Location
    Germany
    Posts
    499

    Question reading a txt file into a linked list:

    Code:
    void loadData(fstream& fin, nodePtr head)
    {
        if (fin.eof()) {
            return ;
        }
        else
        {
            while (!fin.eof())
            {
            if (!head) {
                head= new node;
                getline(cin, head->name, '\n');
                getline(cin, head->last, '\n');
                fin>>head->age;
                head->next=nullptr;
            }
            else
            {
                nodePtr curr =head;
                while (curr->next)
                    curr=curr->next;
                getline(cin, curr->next->name, '\n');
                getline(cin, curr->next->last, '\n');
                fin>>curr->next->age;
                curr->next->next=nullptr;
            }
        }
        }
            
    }
    This is my function and it is not working. Any advice?

  2. #2
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,817
    Why are you reading in from both the file and cin? Should it not be just the file (fin)?

    How does it not work? What is your evidence for this?

    What does nodePtr look like? It does not look like a double pointer which would be needed for line 11 to work correctly once the function ends.

    FAQ > Explanations of... > Why it's bad to use feof() to control a loop (the explanation uses C as an example, but the lesson applies to C++ as well). You're loop will have idiosyncrasies due to your use of the streams eof member function to control the looping.

    Code:
    while (curr->next)
        curr=curr->next;
    getline(cin, curr->next->name, '\n');
    getline(cin, curr->next->last, '\n');
    fin>>curr->next->age;
    curr->next->next=nullptr;
    Your while loop continues until cur->next is null (nullptr). The next several lines attempt to set data at the location where curr->next is pointing to without valid memory having been allocated.
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

  3. #3
    Registered User
    Join Date
    Jul 2013
    Location
    Germany
    Posts
    499
    Do you have a link I can read more on how to do this? I think my problem is truly my lack of understanding how to do this. I didn't learn it in my C++ class. However I would really like to figure this out.

  4. #4
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,817
    Your question is rather broad. Are you saying that you don't understand the file/cin reading? Passing in your "head" pointer as a reference? Not using an end-of-file test to control your loop? Attempting to access memory that you should not? Or all of the above?

    Are you determined to - or required to - implement the list yourself or could you use the already available stl::list container?
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

  5. #5
    Registered User
    Join Date
    Apr 2013
    Posts
    1,658
    Note that void loadData(fstream& fin, nodePtr head) is taking a copy of the pointer value in head, so it doesn't update head. In order to update a head pointer the function should be: loadData(fstream& fin, nodePtr *head), and the function should use *head instead of head.

    The function should always allocate a node unless it's reached the end of file. Use a temp nodePtr for this.

    As already mentioned, the program is using both fin and cin

    I don't know if there is an issue mixing getline() calls with ... >> to a variable. The code could always use getline, and for the numeric fields, use getline() with a temp buffer, then sscanf() to convert the buffer into an integer.

  6. #6
    Registered User
    Join Date
    Jul 2013
    Location
    Germany
    Posts
    499
    Code:
    #include <iostream>
    #include <string>
    #include <fstream>
    #include <sstream>
    #include <cstdlib>
    #include <iomanip>
    #include "contacts.h"
    
    #define MYFILE "/Users/peterjocham/Desktop/textoutput.txt"
    
    using namespace std;
    
    void loadData(ifstream& fin, nodePtr &head)
    {
        if (fin.eof()) {
            return ;
        }
        else
        {
            while (!fin.eof())
            {
                if (!head) {
                    head= new node;
                    getline(fin, head->name, '\n');
                    getline(fin, head->last, '\n');
                    fin>>head->age;
                    head->next=nullptr;
                }
                else
                {
                    nodePtr curr = head;
                    while (curr->next)
                        curr=curr->next;
                    curr->next=new node;
                    fin.ignore();
                    getline(fin, curr->next->name, '\n');
                    getline(fin, curr->next->last, '\n');
                    fin>>curr->next->age;
                    curr->next->next=nullptr;
                }
                
            }
        }
    }
    
    int main()
    {
        
        addressBook MyaddressBook;
        ofstream outfile;
        ifstream infile(MYFILE,ios::in);
    
        int userInput=0;
    	nodePtr temp=new node;
    	string NAME;
        MyaddressBook.userPromptStatement();
        
    	nodePtr head=nullptr;
        loadData(infile, head);
        MyaddressBook.sethead(head);
        outfile.open(MYFILE,ios::app);
        
        if (outfile.fail()) {
            cerr<<"File couldn't be opened";
            exit(EXIT_FAILURE);
        }
        while(1)
    	{
      cin>>userInput;
            if (!cin || (userInput!=1 && userInput!=2 && userInput!=3 && userInput!=4 &&userInput!=5))
            {
                cin.ignore();
                cout<<"Only enter a 1,2,3,4, or 5"<<endl;
                cout<<"You have entered an incorrect value."<<endl;
                cout<<endl<<endl;
                MyaddressBook.userPromptStatement();
                continue;
            }
            switch (userInput) {
                case 1:
                    
                    cout<<"NAME: ";
                    cin.ignore();
                    getline(cin,temp->name,'\n');
                    
                    cout<<"\nLAST NAME: ";
                    getline(cin,temp->last,'\n');
                    
                    cout<<"\nAGE: ";
                    cin>>temp->age;
                    
                    outfile<<
                    setw(2)<<temp->name<<"\n"
                    <<setw(2)<<temp->last<<"\n"
                    <<setw(2)<<temp->age<<"\n\n";
                    
                    MyaddressBook.addContact(temp);
                    MyaddressBook.userPromptStatement();
                    cout<<"\n"<<"\n";
                    break;
                    
                case 2:
                    cout<<"Which contact would you like to delete?\n";
                    cin>>NAME;
                    
                    MyaddressBook.deleteName(NAME);
                    MyaddressBook.userPromptStatement();
                    cout<<"\n"<<"\n";
                    break;
                case 3:
                    MyaddressBook.editName(NAME);
                    break;
                case 4:
                    MyaddressBook.printContactList();
                    MyaddressBook.userPromptStatement();
                    cout<<"\n"<<"\n";
                    break;
                case 5:
                    outfile.close();
                    exit(EXIT_SUCCESS);
                default:
                    break;
            }
        }
        
        return 0;
    }
    I have nodPtr is a point as I will show below:
    Code:
    typedef struct node{
        std::string name;
        std::string last;
        int age;
        node *next;
    }*nodePtr;
    so I am doing *head, however yes I did need to do fin and not cin.

    I tried using
    Code:
    stringstream convert (head->age);
    and I had a few problems. So I decided to use fin>>, was I wrong in doing so?

    I tired not using eof but I don't think I quite got the concept.

    I got the program to work but now I am concern I am using bad programing practice.

  7. #7
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Quote Originally Posted by jocdrew21 View Post
    I have nodPtr is a point as I will show below:
    Code:
    typedef struct node{
        std::string name;
        std::string last;
        int age;
        node *next;
    }*nodePtr;
    so I am doing *head
    This is equivalent to saying "I received a paper today, therefore there are eight days in a week." (1) The two concepts are not related (that is, the type of nodePtr is irrelevant to the problem), and (2) the conclusion is false (as you are not doing *head).
    What you have done to fix it is change your function prototype to accept a reference, instead of a copy of the value, and that is what you needed to do.

    Quote Originally Posted by jocdrew21 View Post

    I tried using
    Code:
    stringstream convert (head->age);
    and I had a few problems.
    What does that even mean? Do you mean you tried to write a convert function?

    Quote Originally Posted by jocdrew21 View Post
    So I decided to use fin>>, was I wrong in doing so?
    If you try to mix >> with getline, you're going to have sprinkle those "ignore" statements very carefully (get one too many, and you'll ignore some input; get one too few, and you'll get a blank read). Easier to just do it correctly, I would think.

    Quote Originally Posted by jocdrew21 View Post
    I tired not using eof but I don't think I quite got the concept.
    Since your loop still says "while (!fin.eof())" I'm skeptical that you tried not using eof. You need something like
    Code:
    while (READ INTO YOUR VARIABLE HERE)
    to check whether your read was successful.

  8. #8
    Registered User
    Join Date
    Jul 2013
    Location
    Germany
    Posts
    499
    Hook, Hook, jape, upper cut....

    I'll work at it more. I just don't want it to work, I want it to be correct.(I am really happy it works though) This is not an assignment, and i have didn't learn this in my pervious C++ class but I know it is very important concept. I am getting the there slowly and I thank you for your advice. I am sure I will be back shortly with new code asking for a critique.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. linked list and file reading.
    By mgracecar in forum C Programming
    Replies: 1
    Last Post: 03-22-2012, 07:11 PM
  2. reading in file to linked list?
    By rickyson49 in forum C Programming
    Replies: 2
    Last Post: 03-31-2011, 09:07 AM
  3. Reading from a file into a linked list.
    By Wiretron in forum C Programming
    Replies: 5
    Last Post: 01-23-2006, 08:24 AM
  4. Reading a file into a Linked List
    By Unregistered in forum C Programming
    Replies: 2
    Last Post: 05-20-2002, 07:08 AM
  5. reading from a file to linked list
    By opacity in forum C++ Programming
    Replies: 3
    Last Post: 04-14-2002, 09:56 AM