I am in process of learning c++. I am working on creating a linkedlist data structure. One of the functions that displays the values of nodes in the structure does not work. For some reason the while loop that traverses through nodes doesn't work in the display function, hence I can't see the values in those nodes. Does anyone see what the problem is? I've been staring at the code for a while and not sure what is wrong here.
Thanks for your help in advance.
Header:
// linklist.h
// class definitions
#ifndef LINKLIST_H
#define LINKLIST_H
class linklist
{
private:
// structure containing a data part and link part
struct node
{
int data;
node *link;
}*p;
public:
linklist();
void append(int num);
void addatbeg(int num);
void addafter(int loc, int num);
void display();
int count();
void del(int num);
~linklist();
};
#endif
.cpp file
// LinkedListLecture.cpp
// Class LinkedList implementation
#include"linklist.h"
#include<iostream>
using namespace std;
// initializes data member
linklist::linklist()
{
p =NULL;
}
// adds a node at the end of a linked list
void linklist::append(int num)
{
node *temp, *r;
// if the list is empty, create first node
if(p==NULL)
{
temp = new node;
temp->data = num;
temp->link = NULL;
}
else
{
// go to last node
temp = p;
while(temp->link!=NULL)
temp = temp->link;
// add node at the end
r = new node;
r->data=num;
r->link=NULL;
temp->link=r;
}
}
// displays the contents of the linked list
void linklist::display()
{
node *temp = p;
cout<< endl;
// traverse the entire linked list
while(temp!=NULL) // DEBUG: the loop doesn't work
{
cout<<temp->data<<" ";
temp = temp->link;
}
void main()
{
linklist l;
l.append(14);
l.append(30);
l.append(25);
l.append(42);
l.append(17);
cout<<"Elements in the linked list:";
l.display(); // this function doesn't work
system("PAUSE");
}
You never set p to a non NULL value.
if(p==NULL)
{
p = new node;
p->data = num;
p->link = NULL;
}
I think GWW has highlighted the issue, but part of learning to program it to learn how to identify the mistakes.
If you do something and don't get the expected result you could:
Use the visual c++ debugger to step through and see the values of your variables.
Put in log lines to report information you think is important
inspect the code - if you think something is right but it doesn't work, then go to an earlier step and check it does the right thing.
Add unit tests, or follow design by contract adding pre/post conditions and class invariants.
Learning to program C++ by writing a linked list is like learning math by adding 1 + 1. It is old fashioned thinking, slow and mostly boring without having any context.
Math isn't calculating, like C++ programming isn't pointer manipulation. At some stage you might need to know about it, but your better off learning other important things like stl and boost.
If it was understood that append() ment create something, find the end of the list, add it. you could then see that in you append function you have create something mixed uyp with move to the end of the list, but you never add it.
Related
I am learning list in C++ independently, and i have searched many websites about it. However, almost every approach to create a list is the same.
They usually create a struct as the node of a class. I want to create a class without using struct. So I created a class name ListNode which contains an int data and a pointer.
The main member functions of my class are AddNode and show.
Although, this program compiles successfully, it still does not work as I wish.
Here is the header file:
#ifndef LISTNODE_H_
#define LISTNODE_H_
#pragma once
class ListNode
{
private:
int data;
ListNode * next;
public:
ListNode();
ListNode(int value);
~ListNode();
void AddNode(ListNode* node,ListNode* headNode);
void show(ListNode* headNode);
};
#endif
Here is the implementation:
#include "ListNode.h"
#include<iostream>
ListNode::ListNode()
{
data = 0;
next = NULL;
}
ListNode::ListNode(int value)
{
data = value;
next = NULL;
}
ListNode::~ListNode()
{
}
void ListNode::AddNode(ListNode* node,ListNode* headNode) {
node->next = headNode;
headNode =node;
}
void ListNode::show(ListNode* headNode) {
ListNode * traversNode;
traversNode = headNode;
while (traversNode != NULL) {
std::cout << traversNode->data << std::endl;
traversNode = traversNode->next;
}
}
Main function:
#include"ListNode.h"
#include<iostream>
int main()
{
using std::cout;
using std::endl;
ListNode* head = new ListNode();
for (int i = 0;i < 3;i++) {
ListNode* Node = new ListNode(i);
head->AddNode(Node, head);
}
head->show(head);
return 0;
}
As far as I am concerned, the output should be
2
1
0
However, the output is a single zero. There must be something wrong in the AddNode and show function.
Could you please tell me what is wrong with these two functions?
When you call head->AddNode(node, head) you´re passing the memory directions which the pointers point, when the function arguments receive those directions, they are now pointing to the same directions, but those are another pointers, no the ones you declared in main. You could see it like this:
void ListNode::AddNode(ListNode* node,ListNode* headNode) {
/*when the arguments get their value it could be seen as something like:
node = Node(the one from main)
headNode = head(the one from main)*/
node->next = headNode;
/*Here you are modifying the new inserted node, no problem*/
headNode = node;
/*The problem is here, you´re modifying the memory direction
headNode points to, but the headNode argument of the function, no the one declared in main*/
}
So the pointer head in main() always points to the same first node you also declared in main().
In order to fix this you should change your code this way:
void ListNode::AddNode(ListNode* node,ListNode** headNode) {
/* second paramater now receives a pointer to apointer to a node */
node->next = *headNode;//the same as before but due to pointer syntaxis changes a bit
*headNode = node;//now you change the real head
}
And when you call it:
head->AddNode(Node, &head);//you use '&' before head
Now the real head, no the one in the function, will point to the last node you inserted.
I am trying to create a maze that consists of Nodes objects. Each Node object has a member variable Node *attachedNodes[4] that essentially contains all of the attached Nodes that will later tell the program the options it has when it is doing a breadth first search. Every time I think that I understand pointers, another issue like this comes up, and I feel lost all over again. Especially since it was working fine (as far as I knew) until I changed something that I thought was unrelated. Anyways, here is where the issues are:
My Node object looks like this
class Node {
public:
...
void attachNewNode(Node *newNode, int index);
...
private:
...
Node *attachedNodes[4];
...
};
My function to attach the Nodes looks like this:
void Node::attachNewNode(Node *newNode, int index) {
*attachedNodes[index] = *newNode;
}
And then lastly, the part of the other function that is calling the attachNewNode function looks like this:
int mazeIndex = 0;
while (inStream.peek() != EOF) {
int count = 0;
Node n;
Node m;
...
if (System::isNode(name2)) {
m = System::findNode(name2);
}
else {
m = Node(name2);
maze[mazeIndex] = m;
mazeIndex++;
}
Node *temp;
*temp = m;
n.attachNewNode(temp, count); //The error usually happens here, but I added the rest of the code because through debugging it is only consistently in this whole area.
count++;
}
n.setNumberUsed(count);
}
Sorry that this got a little lengthy, but I've been searching all over this portion that I have provided trying to figure out what is wrong, but it would be nice to have someone that knows a little more about pointers give their input on the matter. The Node class was given to me, but everything else I made, so basically any of that could be changed. Thanks in advance for the help.
Your class contains a property:
Node *attachedNodes[4];
The above says that attachedNodes is an array that contains 4 pointers to Nodes. In your attachNewNode function, you do:
*attachedNodes[index] = *newNode;
This means that you are trying to assign value of newNode (as * dereferences the pointer) to the value of the element under attachedNodes[index]. What you probably want is:
attachedNodes[index] = newNode;
This means that you just want to store the address (as pointer is just an address to some place in memory) in the array of addresses.
There is also another error here:
Node *temp;
*temp = m;
n.attachNewNode(temp, count);
Again, you are interested in storing the address of node m. In order to do that, you need to get the said address:
Node *temp;
temp = &m;
n.attachNewNode(temp, count);
These are the most obvious problems with the above code, but there might be more.
I've just started learning C and am fairly a beginner.
Today in school we learned linked list and I was able to put up a code...which thankfully is running without errors.
#include<stdio.h>
#include<stdlib.h>
struct node
{
int data;
struct node *next;
}*head;//*temp;
void create(struct node **h,int num)
{
int i;
struct node *temp=*h;
for(i=0;;i++)
{
if(i>=num)
break;
temp->data=i;
temp->next=malloc(sizeof(struct node));
temp=temp->next;
}
temp->next=NULL;
}
void display(struct node **h)
{
struct node *temp=*h;
while(temp->next!=NULL)
{
printf("%d->",temp->data);
temp=temp->next;
}
printf("\b\b \b\b");
}
void append_end(struct node **h,int val)
{
struct node *temp=*h,*temp1;
//printf("'%d'",val);
while(temp->next!=NULL)
temp=temp->next;
temp1=malloc(sizeof(struct node));
temp1->data=val;
temp1->next=NULL;
temp->next=temp1;
}
void free_list(struct node **h)
{
struct node *temp=*h,*tail;
while(temp->next!=NULL)
{
tail=temp;
temp=temp->next;
free(tail);
}
h=NULL;
}
int main()
{
head=malloc(sizeof(struct node));
int i,num;
scanf("%d",&num);
create(&head,num);
//display(&head);
append_end(&head,5);
append_end(&head,6);
display(&head);
/*temp=head;
while(temp->next!=NULL)
temp=temp->next;
printf("%d",temp->data);*/
free_list(&head);
return 0;
}
The expected output should be
0->1->2->3->5->6
for input of 4
But instead I'm getting
0->1->2->3->(some garbage value)->5
I'll be glad if someone could point out my error(s), and/or link to any article that might help me in understanding the topic clearly.
Thanks in advance.
I've refactored your code. You can see it here: http://ideone.com/nZ55i
Your code was ugly, so I tweaked it into my own style. I suggest you find a style you like, that's easy for you to read.
Moved declaration of head into main method (used to be a global variable)
Functions that took pointer-to-pointer types for no reason have been modified to take pointers.
You used malloc(sizeof(struct node)) in at least 3 places, so I just up and made a function that does it for you.
Added a typedef to the declaration of the node struct, you can declare instances of it now with just node derp;
create function uses a for loop with an empty condition and a break, refactored to use a proper for loop with no break
The garbage value was caused by a bug in your create function that prevented it from writing the value to the last node it created. To fix it, I moved stuff around so it always assigns the data field but doesn't allocate a new node if it's at the end
Failure to write the last item in the list was caused by a bug in the display function that caused it to terminate before displaying the last node.
If this is a homework question and you turn in my code, I will find you, drive to your house, and shoot a rotten potato through your bedroom window with a cannon.
Okay, I started to put this in the comments, but putting code in comments will get brickbats :). This is not tested, and there are myriad ways to approach it (given I've diagnosed the problem correctly :) ), but one way that might work to fix your create method is offered as follows: (Note that I've simplified your loop, just using the normal termination condition for the 'for' loop construct, and eliminated the 'if..break' within the loop as its no longer needed. The "->next" member will always be initialized to a new member if there's one left to create, otherwise its NULL, so we don't need the ending assignment:
void create(struct node **h,int num)
{
int i;
struct node *temp=*h;
for(i=0;i<num;i++)
{
temp->data=i;
if (i==(num-1))
temp->next=NULL;
else
temp->next=malloc(sizeof(struct node));
temp=temp->next;
}
}
I have a problem either adding to or traversing a linked list. The main item class is used by another class but I can add the correct number of these but it looks like when I add more data to the list the app no longer works.
I am not sure exactly where the error is. I know that when I try to traverse the list the application crashes. Any ideas or any improvements would be appreciated.
I can make the crash not happen by changing the AddOccurence method to not do the while loop.
Do
void Item::AddOccurence(int Item,int placeInLine){
ItemOccurence* ocr=myHead;
if(ocr)
{
}
instead of
void Item::AddOccurence(int Item,int placeInLine){
ItemOccurence* ocr=myHead;
while(ocr)
{
}
Basically hitting the first node but no more.
I have an object that contains a list.
Here is the .h file
#include
using namespace std;
class ItemOccurence{
public:
ItemOccurence(int line,int placeInLine,ItemOccurence* link=NULL) :myLine(line),myPlaceInLine(placeInLine),myLink(link){}
int myLine;
int myPlaceInLine;
ItemOccurence* myLink;
};
class Item {
public:
Item();
Item(string Item,int line,int placeInLine);
virtual ~Item();
void deallocate(ItemOccurence* p);
void AddOccurence(int Item,int placeInLine);
string myItem;
ItemOccurence* myHead;
private:
bool isEmpty();
};
And the .cpp file
#include "Item.h"
#include <string>
#include<iostream>
using namespace std;
Item::Item(string Item,int line,int placeInLine):myHead(NULL){
myItem=Item;
myHead= new ItemOccurence(line,placeInLine,NULL);
}
Item::Item():myHead(NULL){
myHead=0;
}
Item::~Item() {
deallocate(myHead);
myHead=0;
}
void Item::deallocate(ItemOccurence* p){
ItemOccurence* tmp;
while(p){
tmp=p;
p=p->myLink;
delete tmp;
}
}
void Item::AddOccurence(int Item,int placeInLine){
ItemOccurence* ocr=myHead;
while(ocr)
{
cout<<"orrucence head while adding " << myHead->myLine << " " << myHead->myPlaceInLine <<"\n";
ocr=ocr->myLink;
}
myHead = new ItemOccurence(Item,placeInLine,myHead);
return;
}
bool Item::isEmpty(){
if(myHead)
return false;
else
return true;
}
EDIT:
I updated AddOccurence to be.
void Item::AddOccurence(int line,int placeInLine){
ItemOccurence* prev = myHead;
ItemOccurence* curr = myHead->myLink;
while(curr){
prev=curr;
curr=curr->myLink;
}
// insert new ItemOccurence
cout<<"adding " <<line<< " and " << placeInLine <<"\n";
prev->myLink = new ItemOccurence(line,placeInLine);
return;
}
But I am still crashing. I am trying to debug but not sure what to look for.
It's very hard to tell what your code is trying to do. Unfortunately, the hard truth is, it's pretty far away from "working".
Here's a few hints:
Reconsider your classes. What is Item and ItemOccurrence? A linked list is a list. It has items. You should probably name it List and Item. If you want, you can do this in a single class representing Item (the List is only a special case of the front Item).
Each Item needs a string (the node data) and a next (the pointer to the next node).
If you use List, it will need to have a pointer to head (the first Item).
You don't need to store placeInLine. placeInLine should only be used when searching for the place to insert a new Item.
It's unclear what ItemOccurrence::myLine is supposed to represent.
When you initialize myHead(NULL), you don't need to set it to 0.
isEmpty() is not usually a private method.
The algorithm for adding a node is:
Loop until you find the place before it needs to be inserted.
It looks like you need to check for two things: "end of list" and "placeInLine"
Set new_node->next = current->next->next node.
Set current->next = new_node node.
Be aware of the special case where current->next is NULL.
Instead of if (x) return true; else return false;, it's common to return x;
There are several issues with the code, but most notably your addOccurrence method does not set the myLink pointer for myHead after it creates it. I think that's what you are trying to do in the loop above it, but in actuality that code only seems to loop through the existing list and print it out. You probably intend to loop through that placeInLine times and then update your myLink pointers at that level. It's not clear what the difference is between item and placeInLine or why you would need both. You definitely don't want to use class names (like Item) as integer variables. That adds to the confusion.
DEAR All;
Hi, I'm just beginner to C++;
Please help me to understand:
What functions should be in the Linked list class ?
I think there should be overloaded operators << and >>;
Please help me to improve the code (style, errors, etc,)
Thanks for advance. Igal.
Edit:
This is only first stage, the next one will be (hopefully) with templates.
Please review the small code for the integer List (enclosed MyNODE.h and ListDriver1.cpp);
MyNODE.h
// This is my first attempt to write linked list. Igal Spector, June 2010.
#include <iostream.h>
#include <assert.h>
//Forward Declaration of the classes:
class ListNode;
class TheLinkedlist;
// Definition of the node (WITH IMPLEMENTATION !!!, without test drive):
class ListNode{
friend class TheLinkedlist;
public:
// constructor:
ListNode(const int& value, ListNode *next= 0);
// note: no destructor, as this handled by TheLinkedList class.
// accessor: return data in the node.
// int Show() const {return theData;}
private:
int theData; //the Data
ListNode* theNext; //points to the next node in the list.
};
//Implementations:
//constructor:
inline ListNode::ListNode(const int &value,ListNode *next)
:theData(value),theNext(next){}
//end of ListNode class, now for the LL class:
class TheLinkedlist
{
public:
//constructors:
TheLinkedlist();
virtual ~TheLinkedlist();
// Accessors:
void InsertAtFront(const &);
void AppendAtBack(const &);
// void InOrderInsert(const &);
bool IsEmpty()const;//predicate function
void Print() const;
private:
ListNode * Head; //pointer to first node
ListNode * Tail; //pointer to last node.
};
//Implementation:
//Default constructor
inline TheLinkedlist::TheLinkedlist():Head(0),Tail(0) {}
//Destructor
inline TheLinkedlist::~TheLinkedlist(){
if(!IsEmpty()){ //list is not empty
cout<<"\n\tDestroying Nodes"<<endl;
ListNode *currentPointer=Head, *tempPtr;
while(currentPointer != 0){ //Delete remaining Nodes.
tempPtr=currentPointer;
cout<<"The node: "<<tempPtr->theData <<" is Destroyed."<<endl<<endl;
currentPointer=currentPointer->theNext;
delete tempPtr;
}
Head=Tail = 0; //don't forget this, as it may be checked one day.
}
}
//Insert the Node to the beginning of the list:
void TheLinkedlist::InsertAtFront(const int& value){
ListNode *newPtr = new ListNode(value,Head);
assert(newPtr!=0);
if(IsEmpty()) //list is empty
Head = Tail = newPtr;
else { //list is NOT empty
newPtr->theNext = Head;
Head = newPtr;
}
}
//Insert the Node to the beginning of the list:
void TheLinkedlist::AppendAtBack(const int& value){
ListNode *newPtr = new ListNode(value, NULL);
assert(newPtr!=0);
if(IsEmpty()) //list is empty
Head = Tail = newPtr;
else { //list is NOT empty
Tail->theNext = newPtr;
Tail = newPtr;
}
}
//is the list empty?
inline bool TheLinkedlist::IsEmpty() const
{ return (Head == 0); }
// Display the contents of the list
void TheLinkedlist::Print()const{
if ( IsEmpty() ){
cout << "\n\t The list is empty!!"<<endl;
return;
}
ListNode *tempPTR = Head;
cout<<"\n\t The List is: ";
while ( tempPTR != 0 ){
cout<< tempPTR->theData <<" ";
tempPTR = tempPTR->theNext;
}
cout<<endl<<endl;
}
//////////////////////////////////////
The test Driver:
//Driver test for integer Linked List.
#include <iostream.h>
#include "MyNODE.h"
// main Driver
int main(){
cout<< "\n\t This is the test for integer LinkedList."<<endl;
const int arraySize=11,
ARRAY[arraySize]={44,77,88,99,11,2,22,204,50,58,12};
cout << "\n\tThe array is: "; //print the numbers.
for (int i=0;i<arraySize; i++)
cout<<ARRAY[i]<<", ";
TheLinkedlist list; //declare the list
for(int index=0;index<arraySize;index++)
list.AppendAtBack( ARRAY[index] );//create the list
cout<<endl<<endl;
list.Print(); //print the list
return 0; //end of the program.
}
What functions should be in the Linked list class ?
That depends on what you need to do with it. At the very least, one should probably be able to add elements to it, and to look at the elements in the list.
(This is common sense. Because if you can't modify or read your list in any way, what could it ever be used for?)
I think there should be overloaded operators << and >>;
Why? What would they do? I suppose you mean operator << to do insertion, similar to how objects are inserted into C++ IO streams; but what exactly should operator >> do? Extraction/removal of elements of some sort? If you implement insertion and extraction (?) in this manner, probably noone will be able to understand your linked list class. A linked list is not an IO stream. (Those operators with IO streams were chosen for brevity.)
I would advise you against operator overloading if the meaning of the operation is not clear. I would suggest you name your operations more explicitly, e.g. by providing methods add and remove (I'm still guessing at the meaning of the latter operation >> btw.).
Please help me to improve the code (style, errors, etc,)
I don't want to make this the main point on my answer, so just very briefly off the top of my head, some issues:
You should #include <iostream> instead of #include <iostream.h>, and then either add a using namespace std; or write (e.g.) std::cout instead of cout.
Try to get rid of the friend. You should be able to design your classes in a way that doesn't require this. friend is easily misused to get around proper encapsulation. But encapsulation is something you should definitely think about in OOP.
Though that's not an advice to give to a C++ beginner, if you made your linked list class into a template class, it could store different values than just ints. Just take this as a hint for future improvements.
And finally:
Just use the STL ("Standard Template Library") containers which are included in the C++ standard library. I know that "rolling your own" helps understanding how these data structures work, but be aware that the C++ standard library already includes a solid and efficient set of data containers.
0 should be NULL
inline only in the case that you don't care that your code will be public, usually implementation puts in separate file Mylist.cpp file.
Why your destructor virtual, do you have inheritance ?
You can just define struct node instead separate class its better define your list for practice like in stl. http://www.sgi.com/tech/stl/List.html http://www.cplusplus.com/reference/stl/list/
In C++ common to use vector vs linked list in Java
http://www.yolinux.com/TUTORIALS/LinuxTutorialC++STL.html