I was doing last exercise from this list (its called graduation): http://www.cplusplus.com/forum/articles/12974/ but had one major problem. The code I wrote runs, but it will crash at so time (after deleting half bunnies), sometimes after program deletes half bunnies first time, sometimes after 10 such cycles, note that i havent implemented alot yet because i want to fix this bug, with your help of course. Also I know this is not code review, but some small tips about style and improving would be good too. So this is code i wrote so far:
Main.cpp:
include bunnyList.h
include windows.h
using namespace std;
int main(){
srand(time(NULL));
bunnyList Colony;
int turns = 0;
Colony.setUp();
while(Colony.getColonySize() > 0){
//New turn
Colony.increaseAgeAndKill();
Colony.breedBunnies();
std::cout << "Turn: "<< turns << ". Colony size: " << Colony.getColonySize() << std::endl;
//Get rid of these food eaters
if(Colony.getColonySize() > 1000){
std::cout << "500 bunnies died!" << std::endl;
Colony.killHalfBunnies();
}
Sleep(100);
turns++;;
}
}
bunnyList.h:
#ifndef BUNNYLIST_H
#define BUNNYLIST_H
#include <stdlib.h>
#include "node.h"
#include <time.h>
#include <iostream>
#include <string>
const int numOfNames = 4;
const int numOfColors = 4;
const int bunniesIni = 5;
const std::string colors[numOfColors] = {"Black", "White", "Brown", "Spotted"};
const std::string maleNames[numOfNames] = {"Joe", "Rafael", "Buby", "Messi"};
const std::string femaleNames[numOfNames] = {"Reichel", "Agnesa", "Mr Flufy", "Flower"};
class bunnyList{
private:
node *head;
int noOfBunnies;
node *current, *prev;
public:
bunnyList();
void newBunny(std::string);
void killHalfBunnies();
void increaseAgeAndKill();
void deleteNode();
void breedBunnies();
void setUp();
int getRandomNumber(int) const;
std::string getRandomColor();
std::string getRandomName(bool);
bool isMaleRandom();
int getColonySize() const;
};
#endif
bunnyList.cpp:
#include "bunnyList.h"
bunnyList::bunnyList(){
noOfBunnies = 0;
}
void bunnyList::setUp(){
std::string temp = "";
head = NULL;
for(int i = 0; i <= bunniesIni; i++){
newBunny(temp);
}
}
void bunnyList::killHalfBunnies(){
prev = head;
current = head;
while(noOfBunnies > 500){
if(getRandomNumber(2) == 1){
deleteNode();
continue;
} else if(current == NULL){
current = head;
prev = head;
} else {
prev = current;
current = current->next;
continue;
}
}
}
void bunnyList::newBunny(std::string color){
node *bunny = new node();
node *temp = head;
if(color == ""){
bunny->color = getRandomColor();
} else {
bunny->color = color;
}
bunny->isMale = isMaleRandom();
bunny->name = getRandomName(bunny->isMale);
bunny->age = 0;
bunny->next = NULL;
bunny->isBreedable = 0;
if(head == NULL){
head = bunny;
return;
}
while(temp->next != NULL){
temp = temp->next;
}
temp->next = bunny;
noOfBunnies++;
}
void bunnyList::increaseAgeAndKill(){
current = head;
prev = head;
while(current != NULL){
current->age++;
//Check if bunny can breed
if(current->age > 2){
current->isBreedable = 1;
}
//Check if its time to die :/
if(current->age > 10){
deleteNode();
}
prev = current;
current = current->next;
}
current = head;
prev = head;
}
void bunnyList::breedBunnies(){
node *temp = head;
bool oneMale = 0;
int femaleCount = 0;
//Check if there is at least one breedable male
while(temp!=NULL){
if(temp->isMale && temp->isBreedable){
oneMale = 1;
break;
}
temp = temp->next;
}
//For every female bunny over 2 years old a new bunny is born
temp = head;
if(oneMale){
while(temp != NULL){
if(temp->isMale == 0 && temp->isBreedable){
newBunny(temp->color);
}
temp = temp->next;
}
}
}
void bunnyList::deleteNode(){
if(current==head){
head = current->next;
prev = head;
delete current;
current = head;
noOfBunnies--;
} else if(current->next==NULL){
delete current;
prev->next = NULL;
prev = head;
current = head;
noOfBunnies--;
} else {
prev->next = current->next;
current->next = NULL;
delete current;
current = prev->next;
noOfBunnies--;
}
}
std::string bunnyList::getRandomName(bool isMale){
int r = getRandomNumber(numOfNames - 1);
if(isMale)
return maleNames[r];
return femaleNames[r];
}
std::string bunnyList::getRandomColor(){
int r = getRandomNumber(numOfColors - 1);
return colors[r];
}
bool bunnyList::isMaleRandom(){
if(getRandomNumber(2) == 1) {return true;}
return false;
}
int bunnyList::getRandomNumber(int limit) const{
return rand() % limit + 1;
}
int bunnyList::getColonySize() const{
return noOfBunnies;
}
node.h:
#ifndef NODE_H_INCLUDED
#define NODE_H_INCLUDED
#include <string>
class node {
friend class bunnyList;
private:
std::string name;
int age;
std::string color;
bool isMale;
node *next;
bool isBreedable;
public:
};
#endif // NODE_H_INCLUDED
Thank you for your help.
Since you asked for the review...
NEVER write using namespace std. Never. Just this morning there was a problem asked on SO where the reason for the issue at hand was that notorious line. I wonder who and why suggested that this is a good approach - there should be a book somewhere with this. If I had my way, it's author would be condemned to eternal manual removal of this line from every file.
Even without reading a line from the code, just by explanations alone, I know that the problem is most likely (100% likely, as in) to be related to memory management. You are freeing the memory which was not allocated properly, you are freeing the same memory twice or you are freeing something which was not allocated at all or you are accessing the memory after it was freed. Look at your deletes and check them.
On the style. Your code basically is an implementation of the business logic-aware list. Generally, this is not a good practice. It is much better to implement a generic list, supporting addition, deletion and other generic list operations, and than implement your business logic on top of this generic list.
Do not use current in your list. Instead, pass a node to be deleted in your delete function.
Lastly, run your program in the debugger and look into the variables you are deleting.
EDIT
Answering questions in commments.
Here is what I meant by business logic separation. There is a generic data structure, called list. It can be a list of anything, bunnies or space rockets, doesn't matter - but it still supports the basic list operations. Obviously, the two most important are insert and delete, but it is not the only operations for generic list. You can read wikipedia on list (data structure) for general ideas and look into std::list as in implementation. Now, you have your specific use case for list, a list of bunnies. For that specific use case you will add functionality on top of generic list. To clarify further, deleting an item from the list is something generic list supports. But 'killing a rabit' when the poor creature ages 10 years is something of the business logic. It contains iterating over list of rabbits (provided by generic list), checking age and making a decision to eliminate the creature (business-logic level) and than deleting the element (generic list). If this code were to be written using std::list, it would like approximately following:
std::list<Bunny> bunnies;
for (auto bunny = bunnies.cbegin(), end = bunnies.cend(); bunny != end; ++bunny) {
if (bunny->age() > 10)
bunny = bunnies.erase(bunny);
}
I got a crash too. It crashed in deleteNode, trying to reference current->next when current was NULL.
This was called from bunnyList::killHalfBunnies, in this code, which is the problem I find:
if (getRandomNumber(2) == 1){
deleteNode();
continue;
}
else if (current == NULL){
current = head;
prev = head;
}
The problem is you call deleteNode, which assumes that current is not NULL, before checking that current is in fact not NULL. I rearranged the if's as shown here, and I'm no longer getting a crash:
if (current == NULL)
{
current = head;
prev = head;
}
else if (getRandomNumber(2) == 1)
{
deleteNode();
continue;
}
It would also be wise to put a check inside deleteNode, so that if it is called when current is NULL, it can handle it. Possibly by throwing an exception or otherwise warning you.
Since you also asked about style: comments in deleteNode (and elsewhere) would make it all clearer!
I assume this is a class assignment, and that's why you're not using std::list.
Related
I'm working on a C++ assignment where I'll create a search engine on a linked list of linked lists. As per the requirements, I can't use other libraries nor STL.
Basically it will be like this (I removed the variables from small list since they are irrelevant):
My structs are these:
struct small
{
int data;
struct small *next;
};
struct big
{
int playerID;
string playerName;
string playerTeam;
struct small *goals;
struct big *next;
};
Here's the relevant code snippet, I think the problem is at addGoals(...) where I'm failing to assign the small element to the temp->goals.
class biglist
{
private:
big *head, *tail;
public:
biglist()
{
head = NULL;
tail = NULL;
}
. . .
void createbig(int ID, string name, string team)
{
big *temp = new big;
temp->playerID = ID;
temp->playerName = name;
temp->playerTeam = team;
temp->goals = NULL;
temp->next = NULL;
if (head == NULL)
{
head = temp;
tail = temp;
temp = NULL;
}
else
{
tail->next = temp;
tail = temp;
}
}
void addGoals(int id, small *s)
{
big *temp = head;
while (temp != NULL)
{
if (temp->playerID == id)
{
temp->goals = s;
break;
}
temp = temp->next;
}
}
void test()
{
big *temp = head;
while (temp != NULL)
{
if (temp->playerID == 1)
{
if (temp->goals !=NULL)
{
cout << temp->goals->data << endl;
}
else
{
cout << "goals null" << endl;
}
}
temp = temp->next;
}
}
}
. . .
class smalllist
{
private:
small *head, *tail;
public:
smalllist()
{
head = NULL;
tail = NULL;
}
void createsmall(int ID, biglist b)
{
small *temp = new small;
temp->data = ID;
temp->next = NULL;
if (head == NULL)
{
head = temp;
tail = temp;
temp = NULL;
}
else
{
tail->next = temp;
tail = temp;
}
b.addGoals(1, temp);
}
};
Finally, my main code:
int main()
{
biglist obj;
obj.createbig(1, "Player1", "Team1");
obj.createbig(2, "Player2", "Team2");
obj.displaybig();
smalllist sml;
sml.createsmall(9, obj);
sml.displaysmall();
obj.displaybig();
obj.test();
}
Debugging throws an exception at:
cout << temp->goals->data << endl;
saying that
Exception thrown: read access violation. temp->goals was nullptr.
I'm 90% sure I messed up something with pointers; but other stuff I've tried gave errors before compiling. I checked out some books / tutorials but couldn't figure it out.
Also if you have a better approach or saw one of the horrible mistakes that I'm making, please don't hold back :)
Thanks.
EDIT I changed my createbig() like this.
Currently it works with following codes:
void createbig(int ID, string name, string team, small *s)
{
big *temp = new big;
temp->playerID = ID;
temp->playerName = name;
temp->playerTeam = team;
temp->goals = s;
temp->next = NULL;
if (head == NULL)
{
head = temp;
tail = temp;
temp = NULL;
}
else
{
tail->next = temp;
tail = temp;
}
}
and added this to small
small getsmall(int i)
{
small *temp = head;
while (temp != NULL)
{
if (temp->data == i)
{
return *temp;
}
}
}
My final main function is
int main()
{
smalllist sml;
sml.createsmall(9);
sml.displaysmall();
biglist obj;
small s = sml.getsmall(9);
obj.createbig(1, "Player1", "Team1", &s);
//obj.createbig(2, "Player2", "Team2");
obj.displaybig();
obj.test();
}
While it ends successfully now, it gives the address of goals and I get this in debug section:
Let's look at what your code does, going through the main function. (Being able to walk through code like this is a useful skill. You can also use a debugger to help out, stepping through your function line-by-line.)
biglist obj;
Default construct a biglist. The head and tail are null. (By the way, nullptr is C++'s replacement for C's NULL.)
obj.createbig(1, "Player1", "Team1");
obj.createbig(2, "Player2", "Team2");
Add entries in obj for players with IDs 1 and 2. Their goals are null.
obj.displaybig();
Presumably an output of obj?
smalllist sml;
sml.createsmall(9);
sml.displaysmall();
These lines do something with a smalllist, but do not reference obj, so they are not relevant to this issue.
obj.displaybig();
Presumably an output of obj? Kind of redundant since nothing affected obj since the last display.
obj.test();
Call the test code, which finds the element for player ID 1 and outputs the data of that player's first goal. However, if you look up where that player was added, the goal is null, so you get a crash.
Separate from the above, there is probably some confusion in createsmall. Inside that function, a new biglist is created (not obj), and that list is told to add a goal to the player with ID 1. However, this has no effect the biglist in the main function.
You don't seem to have added any goals, so I'm assuming the code initializes with null.
and so the nullptr exception.
call addgoals() with the goals to player before test().
the other suggestions would be
to add a null check before printing goals
temp pointers need not be initialized with new big or small just the head of the list would be enough
#include <iostream>
#include <memory>
using namespace std;
struct Node
{
int data;
Node* next;
};
void append(Node*&, int);
void printList(Node*);
void insertNode(Node*&, int, int);
void searchList(Node*, int, int);
int main()
{
Node* head = nullptr;
int initialCount = -1, userInput, newNodeLoc = -1, newNodeVal, searchVal;
/// INITIALIZE LIST
while(initialCount <= 0)
{
cout<<"Enter the number of initial nodes (must be at least 1): ";
cin>>initialCount;
}
cout<<endl;
for(int i = 0;i<initialCount;i++)
{
cout<<"Enter a number: ";
cin>>userInput;
append(head,userInput);
}
cout<<endl;
cout<<"Here are the initial values in the linked list: "<<endl;
printList(head);
cout<<"\nEnter a number for a new node to insert to the linked list: ";
cin>>newNodeVal;
cout<<endl;
cout<<"Enter which position you want to insert it (ex. "<<head->data<<" is at pos 1): ";
cin>>newNodeLoc;
while((newNodeLoc<=0 || newNodeLoc>initialCount))
{
cout<<"New position must be greater than 1 and less than " << initialCount+1 <<": ";
cin>>newNodeLoc;
}
newNodeLoc--;
insertNode(head, newNodeVal, newNodeLoc);
cout<<"\nHere is the updated linked list: "<<endl;
printList(head);
/// SEARCH
cout<<"\nEnter the number that you want to search for in the list: ";
cin>>searchVal;
cout<<endl;
initialCount++;
cout<<initialCount;
searchList(head,searchVal,initialCount);
return 0;
}
void printList(Node* head)
{
Node *n = head;
cout<<n->data<<endl;
while(n->next != nullptr) // print out all nodes values'
{
cout << n->next->data<<endl;
n = n->next;
}
}
void append(Node*& head, int val)
{
Node* temp = new Node;
temp->data = val;
temp->next = nullptr;
Node* ptr = head;
if(head == nullptr) // check if list is empty
{
head = temp;
}
else
{
while(ptr->next != nullptr) // if list isn't empty, get to last element set it equal to temp
{
ptr = ptr->next;
}
if(ptr->next == nullptr)
{
ptr->next = temp;
}
}
delete temp;
temp = nullptr;
}
void insertNode(Node*& head, int val, int loc)
{
Node* temp = new Node;
Node* prevLoc = new Node;
Node* curr = head;
temp->data = val;
int tempPos = 0;
while(curr->next != nullptr && tempPos != loc)
{
prevLoc = curr;
curr = curr->next;
tempPos++;
}
prevLoc->next = temp;
temp->next = curr;
delete temp;
delete prevLoc;
curr = nullptr;
prevLoc = nullptr;
}
void searchList(Node* head, int sVal, int iCount)
{
Node* curr = head;
int index=0;
while(curr->next != nullptr && curr->next->data != sVal)
{
curr = curr->next;
index++;
}
cout<<index;
cout<<iCount;
if(index != iCount)
{
cout<<"Number found at index "<<index<<" in the linked list!";
}
if(index-1 == iCount)
cout<<"Number could not be found in this linked list.";
delete curr;
curr = nullptr;
}
Hi there! I'm trying to implement append/prntlist/insertnode/search functions and I'm getting extremely inconsistent compiling results. Sometimes the code will run fine. Sometimes the code will randomly break. Other times it'll print out numbers on an infinite loop. I'm thinking it's a memory leak somewhere (in append/print functions), but I'm not super confident. It might also be a loop that's breaking the code. Any and all help is appreciated! I understand that the search function doesn't work so you can ignore it. Thank you!
In your append():
delete temp;
temp is your new element, that you've just append()ed to the list. Now that it's a part of the list, it gets immediately deleted. Good-bye!
The next to the last element of your linked list now points to deleted memory. Subsequent attempt to walk the list results in undefined behavior. Subsequent attempts to append more elements to the list will just make things even worse, scribbling over deleteed memory (if it wasn't scribbled over anyway, by the next new) and generally making a major mess of everything.
The memory allocation logic in insert() is similarly flawed. It's even worse. Two news and two deletes. Furthermore, the overall logic is also wrong. Its ostensible purpose is to insert one more element to the list, so it shouldn't be allocating two new nodes, only one will do. Both append() and insert() add one more node to the list; so only one node needs to be newed in both cases.
But the overall problem is erroneous deletions of newed elements, when they should not be newed, and they continue to be used. You cannot use anything after it gets deleted. It's gone. It ceased to exist. It joined the choir-invisible. It's an ex-object. But the shown code erroneously deletes an element after it gets added to the link list and, ostensibly, is still logically a part of the link list.
The following code builds correctly but causes the program to crash when I run it. Can someone please tell me whats wrong with it. I suspect that there is something wrong with the DeleteNode function.
#include <iostream>
#include <cstdlib>
using namespace std;
class list {
private:
typedef struct node {
int data;
node* next;
}* nodePtr; //this means that 'nodePtr' will mean a pointer to the struct node
nodePtr head;
nodePtr current;
nodePtr temp;
public:
list() { //constuctor
head = NULL;
current = NULL;
temp = NULL;
};
void AddNode(int addData) //to add a particular data value
{
nodePtr n= new node;
n->next = NULL;
n->data = addData;
if (head != NULL) { //if a list is already set up
current = head;
while (current->next != NULL) { //to get to the last node in the list
current = current->next;
}
current->next = n;
}
else { // if list is not created
head = n; //new node is front of the list
}
}
void DeleteNode(int delData) //to delete a particular data value
{
nodePtr delPtr = NULL;
temp = head;
current = head;
while (current != NULL && current->data!=delData) { //pass through whole list && find value
temp = current;
current = current->next;
}
if (current = NULL) { //data value not found in list
cout << delData << " was not in the list." << endl;
delete delPtr; //to free up memory space
}
else {
delPtr = current;
current = current->next;
temp->next = current; //to reconnect list
if (delPtr == head) {
head = head->next;
temp = head;
}
delete delPtr;
cout << "The value " << delData << "was deleted." << endl;
}
}
void PrintList() //to print all the data values
{
current = head;
while (current != NULL) { //to go through the data valued of the list
cout << current->data << endl;
current = current->next;
}
}
};
int main()
{
list Shahzad;
Shahzad.AddNode(2);
Shahzad.AddNode(78);
Shahzad.AddNode(28);
Shahzad.AddNode(2398);
Shahzad.DeleteNode(78);
Shahzad.PrintList();
return 0;
}
Your first problem is with the following line:
if (current = NULL)
You're actually assigning null to current at this point.
This should actually be:
if (current == NULL)
Firstly, few code and file management remarks: consider separating your code into .h file where class members are declared and .cpp where class members are implemented, this will make your class easy to comprehend and possible errors will be easier to locate.
Secondly, a general advice when dealing with structures containing pointers is attention to proper resource management, i.e. pointer definitions, initialisations and deletions should be dealt with caution. If you are novice, consider the use of already provided smart pointer facilities like: std::unique_ptr which will "retain sole ownership of an object through a pointer and destroys that object when the unique_ptr goes out of scope"
Thirdly, use debugger to get rid of trivial errors like:
if (current = NULL)
which by the way contains additional inaccuracy expressed in the use of NULL instead of the pointer literal nullptr.
Lastly, check each of the member functions separately after you finish the initial implementation and only then proceed with further class expansion, otherwise you risk the accumulation of errors from multiple sources which will make your job very difficult
In your delete function in the case of which the node isn't found, you are deleting delPtr.
However, delPtr was never instantiated or assigned so you are trying to delete something that doesn't exist.
Always enclose pointer deletions in if statements to avoid this issue. Try this:
if (delPtr) delete delPtr;
Apart from all the suggestions here, you can use some safe programming practices to catch bugs early.
For ex: you wrote
if (current = NULL)
Instead, try writing the value being checked on the LHS and the variable on the RHS like this:
if ( NULL == current)
Here, if you mistyped
if (NULL = current)
the compiler will complain. You have a compile time bug now instead of a run-time one. This is far easier to find and debug.
Exception thrown at 0x00A12849 in DLL.exe: 0xC0000005: Access violation reading ocation 0xDDDDDDDD.
The error occurs at the parse function and I have no clue why. I wrote the exact same code as in the book they only wrote the del function and not the parse function. pls tell why this error is occurring in this code and how to avoid such in future. also help to write a proper parse function.
thanks to everyone in advance
#include<iostream>
using namespace std;
struct list
{
int data;
list *next;
list *prev;
};
list* createNode()
{
list *node = new list;
node->next = NULL;
node->prev = NULL;
return node;
}
void insert(list**head,int data,int position)
{
int k = 1;
list *current, *temp, *node = createNode();
current = NULL;
temp = *head;
node->data = data;
if (position==1)
{
node->next = *head;
*head = node;
if (*head)
{
(*head)->prev = node;
}
}
else
{
while (temp->next!= NULL&&k < (position-1))
{
temp = temp->next;
k++;
}
node->next = temp->next;
node->prev = temp->prev;
if (temp->next)
temp->next->prev = node;
temp->next= node;
}
}
void del(list**head, int position)
{
int k = 1;
list *current, *temp;
current = NULL;
temp = *head;
if (position == 1)
{
*head = (*head)->next;
if (*head != NULL)
(*head)->prev = NULL;
delete temp;
return;
}
while (k < position&&temp->next != NULL)
{
temp = temp->next;
k++;
}
current = temp->prev;
current->next = temp->next;
if (temp->next)
temp->next->prev = current;
delete temp;
return;
}
void parse(list * temp)
{
while (temp != NULL)
{
cout << "->" << temp->data;
temp = temp->next;
}
}
void main()
{
struct list *head = NULL;
start:
int choice;
cin >> choice;
switch (choice)
{
case 1: int data, position;
cout << "\ndata:"; cin >> data; cout << "\nposition:";
cin>>position;
insert(&head, data, position);
goto start;
case 2:parse(head);
goto start;
case 3: cout << "\nposition:"; cin >> position;
del(&head, position);
goto start;
default: break;
}
exit(0);
}
These steps are in the wrong sequence and make the node its own prev:
*head = node;
if (*head)
{
(*head)->prev = node;
}
Then you also set prev incorrectly here:
node->prev = temp->prev;
The following code is not necessarily incorrect on its own, but it is a needlessly dangerous use of prev that fails do to the bugs that make prev wrong, but also fails in some cases of bad input (invalid position).
while (k < position&&temp->next != NULL)
{
temp = temp->next;
k++;
}
current = temp->prev;
You said that del function was in the book. Maybe you don't have a choice, but you apparently are using a pretty bad book. That function (and your insert function) are written in a beginner style that is not a good way to learn to program. Beginner problems are appropriate for learning, but some aspects of typical beginner solutions should be avoided from the beginning. One of the most important skills in programming is finding the similarities that let you combine related operations into more general operations. Breaking out special cases (such as first position in those functions) is a natural beginner mistake that you should be unlearning, not copying from a book.
You are already using the extra level of indirection ** that enables combining the cases, so you should take full advantage of that, rather than drop the advantage at the first opportunity:
void insert(list**head,int data,int position)
{
list *p = NULL;
while ( (position--)>0 && *head )
{
p = *head;
head = &( p->next );
}
list *node = createNode();
node->prev = p;
node->next = *head;
node->data = data;
*head = node;
}
Notice how many cases are mixed in so they all share the same code. That style cuts down on undiscovered bugs. Learning linked lists is a tiny corner of learning to program. Learning to combine and generalize operations is learning to program.
Okay I know this is a ridiculously easy question, but for some reason I cannot get a linked list to work. It may just be because I am really tired, because I've done them a million times before. Boiled my program down to the simplest possible implementation, still not working.
Very basic implementation, just make a LL of integers, something I have done a million times before but for whatever reason it's never progressing past head.
main.cpp
#include <iostream>
#include "ll.h"
using namespace std;
int main()
{
int x;
list ll;
int i =0;
while(i == 0)
{
cout << "Enter a value to add to the LL ";
cin >> x;
ll.add(x);
ll.display();
}
return 0;
}
ll.h
struct node
{
int val;
node * next;
};
class list
{
public:
list();
void add(int);
void display();
node * head;
};
ll.cpp
#include <iostream>
#include "ll.h"
using namespace std;
list::list()
{
head = NULL;
}
void list::add(int x)
{
if(!head)
{
cout << "First " << endl;
head = new node;
head->val = x;
head->next = NULL;
}
else
{
node * current = head;
while (current)
current = current->next;
current = new node;
current->val = x;
current->next = NULL;
}
}
void list::display()
{
node * current = head;
while(current)
{
cout << current->val << endl;
current = current->next;
}
}
It seems you want to append to the list. In this case, you loop condition shouldn't be
while (current)
but
while (current->next)
making sure is initially non-NULL (which you do with your check for the `head).
Actually, the logic for setting up the new node is also not quite right. You probably want to have the second branch of add() look something like this:
while (current->next) {
current = current->next;
}
current->next = new node(x);
... with a suitable constructor of node:
node::node(int x): val(x), next() {}
In addition to Dietmar's answer, you have an improper while loop:
while ( i == 0 ) {
...
}
In the body of the for loop, i is never changed, causing it to loop indefinitely. I'm not entirely sure what you want to use i for though.