-2

Assuming the definition and libs are working, ie. <iostream>, <cassert>, #define__NODE_H__, etc

The question is : how do I insert a node at the head (part 1) and insert data at the head (part 2)?

My header file (part 1):

class Node {
     public:
         typedef int nodeDatatype;

         Node(
             const nodeDatatype& initData = nodeDatatype(),
             Node* initLink = NULL)
         {data = initData; link = initLink;}

         void setData(const nodeDatatype& new_data) {data = new_data;}
         void setLink(Node* new_link)               {link = new_link;}

         nodeDatatype getData() const {return data;}

         const Node*  getLink() const {return link;}
               Node*  getLink()       {return link;}

     private:
         nodeDatatype data;
         Node* link;
};
void insertHead(Node*& head, Node*& entry);

My implementation file function (part 1):

Node* insertHead(Node *head, Node *entry){
     Node* newNode = entry;
     newNode->setData = setData;
     newNode -> next = NULL;
     if(head == NULL){
         head = newNode;
     }
     else{
         newNode->next = head;
         head = newNode;
     }
     return head;
     }

Is this correct? Or am I suppose to add a Node::Node* scope?

For part 2, can I just insert data with the same function as I use for inserting a node at the head? Or does it need to be separate?

The error I get:

not being declared in scope

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
72iskcraft
  • 49
  • 1
  • 5
  • The definition, `Node* insertHead(Node *head, Node *entry)`, must match the declaration `void insertHead(Node*& head, Node*& entry);` or they are different functions and the declaration is never implemented. – user4581301 Jun 28 '19 at 20:38
  • thanks i will do that – 72iskcraft Jun 28 '19 at 20:40
  • 3
    Watch out for `#define__NODE_H__` because `__NODE_H__` is an illegal identifier. See [What are the rules about using an underscore in a C++ identifier?](https://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-a-c-identifier). You probably won't run into a problem here, but if you do, the results can be utterly baffling. – user4581301 Jun 28 '19 at 20:40
  • I think the difference is in part 1 you insert a given `Node`. In part 2 you insert data. To insert data, you need to create a `Node` to hold the data. After that, you can call the function from part 1. – user4581301 Jun 28 '19 at 20:45
  • This looks suspicious `Node* newNode = entry;`. That isn't a new node, `newNode` and `entry` are pointing at the same node. – john Jun 28 '19 at 21:25
  • I have fixed it up, i wrote Node* temp = new node; temp-> setData(entry); temp->setLink(head; head = temp; what do you guys think? still shows me an error though – 72iskcraft Jun 28 '19 at 22:21
  • The error you say you get ("not being declared in scope") is missing a subject. What is not being declared in scope? Copying the exact error message is more useful than paraphrasing it. (If you understand the error message well enough to know which details can be left out of a paraphrase, you probably understand it well enough to fix the problem without asking on SO.) – JaMiT Jun 28 '19 at 22:25
  • well i wouldnt be asking if i didnt need to :) – 72iskcraft Jun 28 '19 at 22:54

2 Answers2

1

The requirements seem to me to be in addition to

void insertHead(Node*& head, Node*& entry);

you will need a

void insertHead(Node*& head, const Node::nodeDatatype & data);

the reference to avoid a copy of data (kind of pointless with an int, but the typedef could be changed to something beefier) and const because insertHead has no business modifying the data. The const also allows the function to accept a wider variety of variable types.

This insertHead overload would have to construct a Node to hold the data, and after that the Node accepting insertHead can be called. Eg:

void insertHead(Node*& head, const Node::nodeDatatype & data)
{
    Node * newNode = new Node(data);
    insertHead(head, newNode);
} 

This is all predicated on

void insertHead(Node*& head, Node*& entry);

being implemented correctly and currently it is not. Let's fix that since the fix is really simple.

Node* insertHead(Node *head, Node *entry){

does not match the declaration. Use

void insertHead(Node*& head, Node*& entry){

instead. The rest of the function mostly does what you want, but does it in a very roundabout fashion.

     Node* newNode = entry;

is not required. it doesn't do any harm, but let's gut it anyway and use entry all the way through.

     newNode->setData = setData;

what is setData? What's wrong with the data already in the node?

     newNode-> next = NULL;
     if(head == NULL){
         head = entry;
     }
     else{
         newNode->next = head;
         head = newNode;
     }

No need for most of the above. The new node goes in ahead of head, so there's no need to test whether head's null or not, just point the new node's next at the same thing as head. In other words, always do the else case.

     return head;

This used to make sense, but now after the matching the definition and the declaration. Don't return a value from a void function.

}

We wind up with

void insertHead(Node*& head, Node*& entry){
    entry->next = head; 
    head = entry; 
}

Bundling all this up we get,

class Node {
     public:
         typedef int nodeDatatype;

         Node(
             const nodeDatatype& initData = nodeDatatype(),
             Node* initLink = NULL)
         {data = initData; link = initLink;}

         void setData(const nodeDatatype& new_data) {data = new_data;}
         void setLink(Node* new_link)               {link = new_link;}

         nodeDatatype getData() const {return data;}

         const Node*  getLink() const {return link;}
               Node*  getLink()       {return link;}

     private:
         nodeDatatype data;
         Node* link;
};
void insertHead(Node*& head, Node*& entry);
void insertHead(Node*& head, const Node::nodeDatatype & data);

And then the implementations

void insertHead(Node*& head, Node*& entry){
    entry->link = head; // this line is currently impossible due to link being private
                        // perhaps these functions should be reworked into members
    head = entry; 
}
void insertHead(Node*& head, const Node::nodeDatatype & data)
{
    Node * newNode = new Node(data);
    insertHead(head, newNode);
} 

Sidenote: Instead of typedef int nodeDatatype;, consider making the class a template.

user4581301
  • 33,082
  • 7
  • 33
  • 54
  • hmm the professor made the header file for us to focus us on learning the implementation file. I kind of did a similar way. my final code is `code` Node*temp = new Node; temp->getLink(entry) = entry; temp->getLink(getLink) = head->getLink(); head = temp.`code` my goal was to create another node(to insert at the head) then have the node have the data (entry) then have the node to be the next node after head – 72iskcraft Jun 29 '19 at 21:54
0

What version of c++ are you using? Try setting up in wandbox or something. So you can easily copy the exact messages into your question.

Some comments:

Errors

  • use std::shared_ptr<> not raw pointers. You will get something wrong if you use raw pointers.
  • insertHead() should be either a member function or a friend function, at the moment is is neither. I assume it should be a member function.
  • what is ->setData??
  • what is ->next??
  • write some tests for insertHead() to cover different situations (each half of the if, etc)
  • just using int for your data will cover up some errors when you change to using real data. Use a template to help avoid this.

Style

  • use nullptr not NULL
  • use using nodeDataType = int or template<T=int> not typedef int nodeDataType
KarlM
  • 1,614
  • 18
  • 28
  • Do not use `shared_ptr` for this. There is no need to share the pointer in a singly linked list. `std::unique_ptr` would be sufficient. Also watch out for stack-smashing recursion if the list is long. Good point on `next` I didn't notice the class defines `link` instead. – user4581301 Jun 28 '19 at 23:55