0

I want to read in student names from a file and insert them into my linked-list, but I am having this problem with an error box. The error reads "Expression: Invalid Null Pointer."

I've googled with no such luck. I think I have an idea where I've went wrong, but I don't know how to fix it.

If you could help, that would be great!

Here is my code:

P.S I'm not nearly done so my code might be incomplete, I'm just trying to weed out all my errors now so I don't have triple my errors at the end.

LList.h

#include <iostream>
#include <iomanip>
#include <string>

#ifndef LLIST_H
#define LLIST_H

typedef int ElementType;

class LList
{
public:
    LList();
    ~LList();
    void insert(std::string new_data);
    void display();
    void remove(std::string delete_data);

private:
    class Node
    {
    public:
        std::string data;
        Node *next;

        Node(std::string data_value = NULL);
    };

    Node *head;
    int mySize;
};

#endif LLIST_H

LList.cpp

#include <iomanip>
#include <iostream>
#include <string>
#include "LList.h"

using namespace std;

LList::Node::Node (string data_value)
{
    this -> data = data_value;
    this -> next = NULL;
}

LList::LList()
{
    this -> head = new Node(0);
    mySize = 0;
    string data = "";
}

LList::~LList()
{
    delete this -> head;
}

void LList::insert(string new_data)
{
    Node *tempHolder;
    tempHolder = this->head;

    while (tempHolder->next != NULL)
    tempHolder = tempHolder -> next;

    Node *newNode = new Node(new_data);
    tempHolder ->next = newNode;
    this->mySize++;
}

void LList::display()
{
    Node *temp;
    temp = head->next;

    while(temp -> next != NULL)
    {
        cout << temp -> data << endl;
        temp = temp -> next ;   
    }
}

void LList::remove(string delete_data)
{
    Node *tempHolder;
tempHolder = head;
while (tempHolder->next != NULL ) 
{
    if (tempHolder->next->data == delete_data)
   {
      Node *delete_ptr = tempHolder->next;
      tempHolder->next = tempHolder->next->next;
      delete delete_ptr;
      mySize-- ;
      break;
   } else
     tempHolder = tempHolder->next;
}
}

Main.cpp

#include <iostream>
#include <iomanip>
#include <string>
#include "LList.h"
#include <fstream>

using namespace std;

int main()
{
    LList student;

    ifstream infile;
    char readLine[500];

    infile.open ("names.txt");

    if(infile.is_open())
    {
        while (!infile.eof()) 
         { 
            infile.getline(readLine,sizeof(readLine)); // read a line from file 
            student.insert(readLine); 
         } 
    }
    else
    {
        cout << "Can't open file!" << endl;
    }
}
Midge
  • 59
  • 2
  • 5
  • 13

2 Answers2

1

I found my problem.

In:

LList::LList()
{
    this -> head = new Node(0);
    mySize = 0;
    string data = "";
}

Node(0);

is calling my

LList::Node::Node (string data_value)
{
    this -> data = data_value;
    this -> next = NULL;
}

which is initialized as a string.

I changed

Node(0);

to

Node("");

and it worked flawlessly.

Midge
  • 59
  • 2
  • 5
  • 13
0

I wonder could you give the reference where you read that you may to write?

Node(std::string data_value = NULL);

Class std::string has no constructor that converts NULL to an object of type std::string.

it would be much better to declare the constructor without a default argument

Node( std::string data_value );

There is no any sense to create a node without data.

In fact there is no any need to declare a constructor of Node. It could be used as an aggregate.

Also change the constructor of LList as

LList::LList() : head( 0 ), mySize( 0 ){}

Also the destructor is invalied

LList::~LList()
{
    delete this -> head;
}

You have to delete not only head but all nodes in the LList.

Also nodes in a single linked list are inserted in the beginning of the list that is before the head.

I would write method insert the following way provided that the constructor of Node is removed bacause it is not needed.

void LList::insert( const std::string &new_data )
{
   head = new Node { new_data, head };
}

If your compiler does not support the initializer list then you indeed need to define constructor in class Node.

Node( const std::string &data_value, next_node = NULL );

In this case method insert will look as

void LList::insert( const std::string &new_data )
{
   head = new Node( new_data, head );
}
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • @Austin Allen Julio The question is very simple: where did you read that you may to write NULL as a default argument for a parameter of type std::string? Whatis not clear?! – Vlad from Moscow Mar 23 '14 at 18:26
  • I did try that though and I am still getting the invalid null pointer error. – Midge Mar 23 '14 at 18:26
  • @Austin Allen Julio What did you try? Did not you understant that you MAY NOT USE NULL as an initialization value of class std::string? – Vlad from Moscow Mar 23 '14 at 18:28
  • Yes I understand that. I took your advice and declared my constructor without a default argument and I am still getting my error. – Midge Mar 23 '14 at 18:29
  • Your answer is wrong. `Class std::string has no constructor that converts NULL to an object of type std::string.` Yes, it does: `std::string`'s constructor can take a `char const*`, which may certainly be initialised by the expression `NULL`. However it _is_ undefined to do so. – Lightness Races in Orbit Mar 27 '14 at 20:40
  • It's interesting to note that inserting a NULL `char` pointer to a stream is also UB, but that [libstdc++ handles it gracefully and sets the error bit](http://stackoverflow.com/a/7019483/560648); it may do something similar here. – Lightness Races in Orbit Mar 27 '14 at 20:43