Search code examples
c++linked-listnodes

How do I read multiple variables into a node?


So my project is to get a file called "contacts.txt", read in the data and put the data into a node. Then, I put that node into a list. I purge duplicates and print out the resulting list. I'm trying to get the reading in the data and the printing part down first but I'm having problem printing out my list.

A line of contact looks like: Angelina M. Pierre 306 420 1235

And each part of the line (first name, middle initial, last name, phone number) is supposed to have their own variable. I'm not really sure what I'm doing wrong and I would appreciate the help. My code is:

#include <iostream>
#include <bits/stdc++.h>
#include <stdlib.h>
#include <fstream>
using namespace std;


class Node
{
public:
  string firstName;
  string middleI;
  string lastName;
  string phoneNum;
    Node *next;
};


// This function prints contents of linked list
// starting from the given node
void printList(Node* n)
{
    while (n != NULL) {
        cout << n->firstName->middleI->lastName->phoneNum << endl;
        n = n->next;
    }
}

//This function reads the data from a file called "contacts"
//And streams each line into a new node.
void readData(Node* &p)
{
  Node *newNode = new Node; /* Initializing the node*/

  ifstream fin("C:\\Users\\owner\\Documents\\contacts.txt");


  p = newNode;
  while(!EOF){
//fin >> firstName >> middleI >> lastName >> phoneNum; 
  //while(getline(fin,newNode->contacts)){
newNode->firstName;
newNode->middleI;
newNode->lastName;
newNode->phoneNum;
     newNode->next = new Node;
     newNode = newNode->next;
  }
}

// Driver code
int main()
{
    Node *head;
    readData(head);
    printList(head);
    return 0;
}


Solution

  • There are a couple things that I think are majorly detracting from your program's performance. In your printList function, you have the line cout << n->firstName->middleI->lastName->phoneNum << endl;, and I assume here you intend to print all of the information for a user. What is happening here, however, is that the program takes the pointer n, attempts to find the firstName property of the object being pointed to, then takes this property and attempts to find the middleI property of that property, then the lastName property of that property, etc. These fields of course do not exist, so your program will likely crash. Rather, I think using something like cout << n->firstName << " " << n->middleI << " " << n->lastName << " " << n->phoneNum << endl; would work better.

    Also, in your readData function, your while loop will continue to update the singular node p instead of creating new nodes, so (assuming that your input file is properly formatted and all that jazz) your head node, which is what is passed into this function when it is called by main(), will only be equal to the last contact in your file and your list will have a length of 1.


    Incidentally, I see that you only have a Node class. If you are wanting to work with lists, you probably should create a second class (i.e. LinkedList) that takes one more level of abstraction. Your Node class, then, will handle setting/reporting its data and answering which node follows it, and your LinkedList class will handle keeping track of the list (by remembering where the head is), adding to/deleting from the list, and finding specific nodes in the list.


    Some other considerations:

    1. Variables held by a class should almost always be private instead of public. The reason for encapsulating the information in the first place, aside from organizing it, is to make sure that other parts of the program that have no business altering this portion of your code cannot touch it, and you lose this safeguard when you make everything public.
    2. The functions that you are using to create/add nodes, print lists, etc., should all be methods (i.e. functions of a particular class). Say I have some class, Foo, which has a function that acts upon it named bar. To implement it, I could write something like:
    class Foo {
        private:
            //Foo's variables
        public:
            void bar() {
                //bar's implementation
            }
        }
    

    You will be able to use the method bar() elsewhere because it is labeled public, and bar() will be responsible for handling any necessary manipulation of Foo's information.

    1. It is considered bad practice to use using namespace std; because it can sometimes lead to ambiguous function calls and adding std:: is more explicit. See here for more information.
    2. Using the keyword NULL is very C-style, whereas nullptr is considered more proper (and even safer) in C++. If you are curious, this seems to give a pretty in-depth explanation of this change.
    3. Using while(!fin.eof()) is also considered wrong because !fin.eof() will only return true after you have finished reading the input file. Thus, you will attempt to read past the end of the file and this is plain dangerous. See here for more information.

    A little lengthy, but I hope this clarifies things for you a bit! Feel free to comment if you have any questions.