Searching for data in a linked list - c++

The first part of my program is to extract specific data from a file and insert it into a linked list. I successfully created that part of the program but I'm having difficulty searching through my linked list and printing data. This is my code so far:
struct Country
{
string name;
double population;
};
struct Node
{
Country ctry;
Node *next;
};
Node *world;
void makeList(Node *&world);
void printCountry (Node *&world, string name);
int main ()
{
string name;
makeList(world);
printCountry (world, name);
return 0;
}
void makeList(Node *world)
{
ifstream inFile("population.csv");
if (!inFile.fail())
{
cout << "File has opened successfully." << endl;
}
else
{
cout << "File has failed to open." << endl;
exit(1);
}
double temp, temp1, temp2, temp3, population;
string countryName;
Node *top = new Node;
world = top;
while (!inFile.eof())
{
top -> next = NULL;
inFile >> temp >> temp1 >> temp2 >> temp3 >> population;
getline (inFile, countryName);
top -> ctry.population = population;
top -> ctry.name = countryName;
if (!inFile.eof())
{
top -> next = new Node;
top = top -> next;
}
}
// check if list is created successfully
while (world -> next != NULL)
{
cout << world -> ctry.population << " " << world -> ctry.name << endl;
world = world -> next;
}
}
void printCountry (Node *world, string name)
{
string countryToFind;
cout << "What country do you want to find? " << endl;
cin >> countryToFind;
while (world != NULL)
{
if (world -> ctry.name == countryToFind)
{
cout << "Country has been found: " << world -> ctry.name << " has a population of "
<< world -> ctry.population << endl;
break;
}
else
{
if (world -> next == NULL)
{
cout << "End of file" << endl;
break;
}
world = world -> next;
}
}
}
When I run the printCountry, it just searches through the list and prints End of file. What did I do wrong in the printCountry?

you should really separate
1) data structure (linked list)
2) CSV parser
3) loading the parsed data to the linked list.
Here's an example using C#.
public class LinkedList<T> : IEnumerable<T>
{
private class Node<T>
{
public T Value { get; set; }
public Node<T> Next { get; set; }
}
private Node<T> _startingNode;
public void Add(T item)
{
//define the next node
var nextNode = new Node<T>()
{
Value = item
};
//add the node to the end
Node<T> lastNode = this.GetLastNode();
if (lastNode == null)
{
this._startingNode = nextNode;
}
else
{
lastNode.Next = nextNode;
}
}
public IEnumerator<T> GetEnumerator()
{
Node<T> lastNode = this._startingNode;
while (lastNode != null)
{
yield return lastNode.Value;
if (lastNode.Next == null)
{
yield break;
}
lastNode = lastNode.Next;
}
}
IEnumerator IEnumerable.GetEnumerator()
{
throw new NotImplementedException();
}
private Node<T> GetLastNode()
{
var lastNode = this._startingNode;
while (lastNode != null)
{
if (lastNode.Next == null)
{
break;
}
lastNode = lastNode.Next;
}
return lastNode;
}
}
public class Program
{
public static void Main()
{
//load the list
var numberList = new LinkedList<int>();
numberList.Add(100);
numberList.Add(200);
numberList.Add(300);
numberList.Add(400);
//do something with it
foreach (var item in numberList)
{
Console.WriteLine("Item {0}", item);
}
}
}

Related

Program.exe has triggered a breakpoint in destructor of linked list class

When I run my program, everything works as expected until the destructor of the LList class. On the line that says delete current;, I get the following error:
BlankConsoleLab.exe has triggered a breakpoint.
I have been trying to solve this issue for a long time. I would appreciate it if perhaps someone could try to point out what I am doing wrong here.
Below is my code for the program. Thank you
Linked List Class
class LList
{
private:
Node* head;
Node* tail;
int size = 0;
public:
LList()
{
head = nullptr;
tail = nullptr;
size = 0;
}
LList(Node* h, Node* t)
{
this->head = h;
this->tail = t;
}
~LList()
{
Node* current = head;
while (current != nullptr) {
Node* next = current->m_next;
delete current;
current = next;
}
}
void print()
{
//temporary node pointer to traverse through the linked list
Node* temp = head;
cout << endl << "<MY LINKED LIST>\n";
while (temp != nullptr)
{
cout << temp->m_data.firstName << " ";
cout << temp->m_data.lastName << " ";
cout << temp->m_data.hrWage << " ";
cout << temp->m_data.hrWork << " " << endl;
temp = temp->m_next;
}
cout << endl;
}
void removeFirst()
{
//case 1: linked list is empty (never enters loop)
//case 2: linked list is not empty
if (head != nullptr)
{
Node* temp = head;
head = head->m_next;
delete temp;
//decrease size tracker of the linked list
size--;
}
}
void removeLast()
{
//case 1: linked list is empty (never enters loop)
//case 2: linked list has one node
if (head->m_next == nullptr)
{
removeFirst();
}
//case 3: linked list has more than one node
else if (head != nullptr)
{
Node* cur = head;
Node* prev = nullptr;
while (cur->m_next != nullptr)
{
prev = cur;
cur = cur->m_next;
}
tail = prev;
tail->m_next = nullptr;
delete cur;
//decrease size tracker of the linked list
size--;
}
}
//void removeAt(int pos)
//{
// //Case 1: input is invalid (less than 1 or greater than size)
// if (pos < 1 && pos > size)
// {
// return;
// }
// //Case 2: input is position 1
// else if (pos == 1)
// {
// removeFirst();
// }
// //Case 3: input is the last position (input equals size)
// else if (pos == size)
// {
// removeLast();
// }
// //Case 4: input is valid, and not 1 or last position (greater than 1 and less than size)
// else if (head != nullptr)
// {
// Node* cur = head;
// Node* prev = nullptr;
// for (int i = 1; i < pos; i++)
// {
// prev = cur;
// cur = cur->m_next;
// }
// prev->m_next = cur->m_next;
// delete cur;
// size--;
// }
//}
Node* swap(Node* lh, Node* rh)
{
Node* temp = rh->m_next;
rh->m_next = lh;
lh->m_next = temp;
return rh;
}
void readBin()
{
ifstream file;
file.open("C:\\Users\\there\\source\\repos\\cst126-lab9-JEmersonLawrance\\BlankConsoleLab\\Employee Data.bin", ios::binary);
if (file)
{
Node* cur = head;
Node* prev = nullptr;
for (int i = 0; i < 4; i++)
{
file.read((char*)&cur->m_data.firstName, sizeof(cur->m_data.firstName));
file.read((char*)&cur->m_data.lastName, sizeof(cur->m_data.lastName));
file.read((char*)&cur->m_data.hrWage, sizeof(cur->m_data.hrWage));
file.read((char*)&cur->m_data.hrWork, sizeof(cur->m_data.hrWork));
prev = cur;
cur = cur->m_next;
}
return;
}
else
{
cout << "File could not be opened..\n" << endl;
}
file.close();
}
void writeBin()
{
ofstream file;
file.open("Employee Data Output.bin", ios::binary);
if (file)
{
Node* cur = head;
Node* prev = nullptr;
while (cur != nullptr)
{
file.write((char*)&cur->m_data.firstName, sizeof(cur->m_data.firstName));
file.write((char*)&cur->m_data.lastName, sizeof(cur->m_data.lastName));
file.write((char*)&cur->m_data.hrWage, sizeof(cur->m_data.hrWage));
file.write((char*)&cur->m_data.hrWork, sizeof(cur->m_data.hrWork));
prev = cur;
cur = cur->m_next;
}
}
else
{
cout << "File could not be opened..\n" << endl;
}
file.close();
}
};
Node Class
class Node
{
public:
Employee m_data;
Node* m_next;
Node()
{
m_data.firstName = "";
m_data.lastName = "";
m_data.hrWage = 0;
m_data.hrWork = 0;
m_next = nullptr;
}
Node(Node* next)
{
m_data.firstName = "";
m_data.lastName = "";
m_data.hrWage = 0;
m_data.hrWork = 0;
m_next = next;
}
Node(const Node& copy)
{
m_data.firstName = copy.m_data.firstName;
m_data.lastName = copy.m_data.lastName;
m_data.hrWage = copy.m_data.hrWage;
m_data.hrWork = copy.m_data.hrWork;
}
Node operator = (const Node& copy)
{
m_data.firstName = copy.m_data.firstName;
m_data.lastName = copy.m_data.lastName;
m_data.hrWage = copy.m_data.hrWage;
m_data.hrWork = copy.m_data.hrWork;
return *this;
}
~Node()
{
}
};
Employee Class
struct Employee
{
public:
string firstName;
string lastName;
int hrWage;
int hrWork;
Employee()
{
firstName = "";
lastName = "";
hrWage = 0;
hrWork = 0;
}
Employee(string first, string last, int wage, int work)
{
firstName = first;
lastName = last;
hrWage = wage;
hrWork = work;
}
~Employee()
{
}
void getInput()
{
for (int i = 0; i < 4; i++)
{
cout << "EMPLOYEE # " << i+1 << ":\n" << endl;
cout << "First name: ";
cin >> this[i].firstName;
cout << "Last name: ";
cin >> this[i].lastName;
cout << "Hourly Wage: ";
cin >> this[i].hrWage;
cout << "Hours Worked: ";
cin >> this[i].hrWork;
}
}
void writeBin()
{
ofstream file;
file.open("C:\\Users\\there\\source\\repos\\cst126-lab9-JEmersonLawrance\\BlankConsoleLab\\Employee Data.bin", ios::binary);
if (file)
{
for (int i = 0; i < 4; i++)
{
file.write((char*)&this[i].firstName, sizeof(this[i].firstName));
file.write((char*)&this[i].lastName, sizeof(this[i].lastName));
file.write((char*)&this[i].hrWage, sizeof(this[i]).hrWage);
file.write((char*)&this[i].hrWork, sizeof(this[i]).hrWork);
}
}
else
{
cout << "File could not be opened..\n" << endl;
}
file.close();
}
};
Main Function
int main()
{
cout << "In this program, LIST will read the user information"
<< " in from a binary file, and output it into a different binary"
<< " file.\n" << endl;
Employee data[4];
data->getInput();
data->writeBin();
//creating linked list
Node fourth;
Node third(&fourth);
Node second(&third);
Node first(&second);
LList LIST(&first, &fourth);
LIST.readBin();
LIST.writeBin();
LIST.print();
return 0;
}
In main(), you are constructing your LIST object with pointers to local Node objects that are created in automatic memory within main()'s call frame. When main() exits, all of its local variables are destroyed automatically. But, when the LIST object is destroyed, its destructor tries to call delete on those Node objects which were not created in dynamic memory with new. Thus, your code exhibits undefined behavior.

Cannot find source of segmentation fault

I have been working on this assignment for sometime and cannot figure out what is causing the segmentation fault, any help would be appreciated, here is a copy of my two files!
I am also in the process of fixing my inFile setup, but I would rather focus on that after the fact of the segmentation error.
#include <iostream>
#include <fstream>
#include <string>
#include <list>
#include "source.cpp"
using namespace std;
void scanFile(string fileName);
void printActors(string movie);
void printShows(string actor);
const int MAX_LINE = 128;
int movies = 0;
BST tree;
int main(){
// Scan file
scanFile("tvDB.txt");
// Print all the show titles
cout << "All show titles:" << endl;
tree.displayShows();
cout << endl; // Whitespace
// Print actors /w given show
cout << "Actors from 'The Saint'" << endl;
printActors("The Saint");
// Print show /w given actor
printShows("Tim Conway");
// Print from decade
return 0;
}
// Trims the line removing all excess whitespace before and after a sentence
string isolateLine(string line)
{
int index = 0, start = 0, end = 0;
//Get the start of the line
for(int i = 0; i < line.length(); i++)
{
if(line[i] != ' ' && line[i] != '\t')
{
start = i;
break;
}
}
// Get the end of the line
for(int x = line.length(); x >= 0; x--)
{
if(line[x] != ' ' && line[x] != '\t')
{
end = x;
break;
}
}
// Trim line
line = line.substr(start, end);
return line;
}
// A boolean that returns if the tree is blank, useful for skipping a line and continuing to search for a movie
bool blankLine(string line){
for(int i = 0; i < line.length(); i++)
{
if(line[i] != ' ' && line[i] != '\t')
{
return false;
}
}
return true;
}
// Prints all the shows an actor has starred in
void printShows(string actor){
cout << "Shows with [" << actor << "]:" << endl;
tree.displayActorsShows(actor);
cout << endl; // whitespace
}
// Prints all the actors in a particular movie
void printActors(string show)
{
cout << " Actors for [" << show << "]" << endl;
tree.displayActors(show);
cout << endl;
}
// Scans the fild and categorizes every line of data into the proper categories of the show
void scanFile(string fileName)
{
ifstream inFile;
inFile.open("tvDB.txt");
list <string> actors;
string line = "";
string title = "";
string year = "";
while(getline(inFile, line))
{
line = isolateLine(line);
if(!blankLine(line))
{
// Get movie title
if(line.find('(') != std::string::npos)
{
title = line.substr(0, line.find('(')-1);
}
// Get movie year
if (line.find('(') != std::string::npos) {
year = line.substr(line.find('(') + 1, line.find(')'));
year = year.substr(0, year.find(')'));
}
// Add to actors list
actors.push_back(line);
}
else
{
if(!actors.empty()) // pops the title
{
actors.pop_front();
}
}
tree.insert(title, year, actors);
actors.clear();
movies++;
}
}
and
#include <iostream>
#include <list>
using namespace std;
class BST
{
// Defines the main components of the node object, as well as refrences the left and right elements
struct node
{
string show;
string year;
string genre;
string URL;
list <string> actors;
node*left;
node*right;
};
node* root;
// Deletes all the nodes of the tree
node* makeEmpty(node* t)
{
if(t == NULL)
{
return NULL;
}
else
{
makeEmpty(t->left);
makeEmpty(t->right);
delete t;
}
return NULL;
}
// Inserts a node in the tree
node* insert(string x, string year, list<string> actors, node* t)// DO not include Genrem or URL
{
if(t == NULL)
{
t = new node;
t->show = x;
t->year = year;
t->actors = actors;
t->left = t->right = NULL;
}
else if(x < t-> show)
{
t->left = insert(x, year, actors, t->left);
}
else if(x > t-> show)
{
t->right = insert(x, year, actors, t->left);
}
else
{
return t;
}
}
//Finds the minimum most node to the left
node* findMin(node* t)
{
if(t == NULL)
{
return NULL;
}
else if(t->left == NULL)
{
return t;
}
else
{
return findMin(t->left);
}
}
// Finds the maximum most node to the right
node* findMax(node* t)
{
if(t == NULL)
{
return NULL;
}
else if(t->right == NULL)
{
return t;
}
else
{
return findMax(t->right);
}
}
// Finds a node with the given parameters
node* find(node* t, string x )
{
if(t == NULL)
{
return NULL;
}
else if(x.at(0) < t-> show.at(0))
{
return find(t->left, x);
}
else if(x.at(0) > t->show.at(0))
{
return find(t->right, x);
}
else
{
return t;
}
}
// Prints out the shows inorder
void inorder(node* t)
{
if(t == NULL)
{
// Do nothing
}
else
{
inorder(t->left);
cout << "- " << t->show << endl;
inorder(t->right);
}
}
// Prints the shows of a given actor
void findShow(node* t, string person, list<string> &list)
{
if(t == NULL)
{
// Do nothing
}
else
{
while(!t->actors.empty())
{
if(t->actors.front() == person)
{
list.push_front(t->show);
break;
}
t->actors.pop_front();
}
findShow(t->left, person, list);
findShow(t->right, person, list);
}
}
// Prints the shows within a given year
void findYear(node* t, string year, list<string> &list)
{
if(t == NULL)
{
// Do nothing
}
else
{
if(t->year == year)
{
list.push_front(t->show);
}
findYear(t->left, year, list);
findYear(t->right, year, list);
}
}
public:
BST()
{
root = NULL;
}
~BST()
{
root = makeEmpty(root);
}
// Public calls to modify the tree
// Inserts a node with the given parametersremove
void insert(string x, string year, list<string> actors)
{
root = insert(x, year, actors, root);
}
// Removes a node with the given key
// void remove(string x, node* t)
// {
// root = remove(x, root);
// }
// Displays all shows within the tree
void displayShows()
{
inorder(root);
}
// Displays all the actors with a given show
void displayActors(string show)
{
root = find(root, show);
if(root != NULL) // THIS LINE
{
list<string> temp = root-> actors;
while(!temp.empty())
{
cout << "- " << temp.front() << endl;
temp.pop_front();
}
}
else
{
cout << "root is NULL." << endl;
}
}
// Displays the shows of a given actor
void displayActorsShows(string actor)
{
list<string> show;
findShow(root, actor, show);
while(!show.empty())
{
cout << "- " << show.front() << endl;
show.pop_front();
}
}
// Searches the tree with the given node
void search(string x)
{
root = find(root, x);
}
};// end of class
I would suggest using a debugger (like GDB for unix or the VisualStudioBuildIn Debugger). There the SEG Fault is indicated in which variable the seg fault will be.
Also look out for correct initialized pointers (at least with = nullptr)
Btw: try to use nullptr instead of NULL, since it is not typesafe to use NULL.
Here is why: NULL vs nullptr (Why was it replaced?)

Difficulty printing data in my binary tree in print method

I'm trying to add data to a binary tree, however when I run a method that prints the data of the binarytree in order, nothing prints, and the program exits when it should be printing. I've tested it to see if data is actually being added by having the name and weight values of the rootNode print themselves inside the add method everytime its called, but I cannot get the same results inside of the inOrder method. I believe my issue has something to do with the node being passed.
#include <iostream>
using namespace std;
struct node {
int weight;
string name;
node *left, *right;
};
struct node* newNode(int dataw, string datan)
{
struct node* node = (struct node*)malloc(sizeof(struct node));
node->weight = dataw;
node->name = datan;
node->left = NULL;
node->right = NULL;
return (node);
}
void add(node *rootNode, int dataw, string datan)
{
int lowest_weight;
if (rootNode == NULL )
{
rootNode = newNode(dataw,datan);
lowest_weight = dataw;
}
else
{
if (datan < rootNode->name)
{
if (rootNode->left == NULL)
{
rootNode->left = newNode(dataw,datan);
}
else
{
add(rootNode->left,dataw,datan);
}
}
else
{
if (rootNode->right == NULL)
{
rootNode->right = newNode(dataw,datan);
}
else
{
add(rootNode->right, dataw, datan);
}
}
}
}
void inOrder(node *next)
{
if (next!=NULL)
{
inOrder(next->left);
cout << next->name << " " << next->weight << endl;
inOrder(next->right);
}
}
int main()
{
node *rootNode = NULL;
int height {}, leaves {}, weight {};
string name;
do
{
cout << "Enter name: ";
cin >> name;
if (name == "-1")
break;
cout << "Enter weight: ";
cin >> weight;
add(rootNode, weight, name);
} while (name!="-1");
inOrder(rootNode);
return 0;
}
Resolved it, had to assign the rootNode declaration to a new node method call so the data is not always NULL
node *rootNode = newNode(weight,name);

The order of the user input names and weights are all over the place and not ascending. Why is the doubly linked list not linking properly?

The program is supposed to accept user input names and weights on alternating separate lines and while those are being input, it should be building the doubly linked list in order of ascending names for one pointer and ascending weights for the other pointer. If input name already ordered they print fine, but the weights are messed up and if I input out of order its a disaster. I have tried writing it all down on paper to get a visual of what the computer would be doing, but I cant figure out why this not working.
user input:
jim
150
tom
212
micheal
174
output:
jim
212
tom
1
micheal
1
#include <iostream>
#include <string>
using namespace std;
//Node class for the linked list
class Node
{
public:
string name = " ";
int weight = 1;
Node *nextName;
Node *nextWeight;
Node();
};
Node::Node()
{
nextName = NULL;
nextWeight = NULL;
}
void namePrint(Node *nHead, int counter1);
void weightPrint(Node *wHead, int counter2);
void lister(string name, int weight, Node *builder, Node *nHead, Node *wHead);
Node namePlace(string name, Node *builder, Node *next, Node *nHead);
void weightPlace(int weight, Node *builder, Node *next, Node *wHead);
int main()
{
Node *builder;
Node *nHead;
Node *wHead;
string name;
int weight;
int counter = 0;
builder = new Node;
nHead = builder;
wHead = builder;
cout << "Please enter names and weights on alternating seperate lines." <<
"\n When you are ready to show the results please enter: \n 'print by name' or 'print by weight'" <<
"\n enter 'end program' to end the program" << endl;
do
{
if (counter > 0)
{
cin.ignore();
}
getline(cin, name);
if (name == "end program")
{
system("PAUSE");
return 0;
}
else if (name == "print by name")
{
namePrint(nHead, counter);
}
else if (name == "print by weight")
{
weightPrint(wHead, counter);
}
else
{
cin >> weight;
if (counter > 0)
{
lister(name, weight, builder, nHead, wHead);
}
else
{
builder->name = name;
builder->weight = weight;
nHead = builder;
wHead = builder;
}
counter++;
}
} while (name != "end program");
system("PAUSE");
return 0;
}
void lister(string name, int weight, Node *builder, Node *nHead, Node *wHead)
{
Node *next = nHead;
namePlace(name, builder, next, nHead);
next = wHead;
weightPlace(weight, builder, next, wHead);
}
Node namePlace(string name, Node *builder, Node *next, Node *nHead)
{
bool spot = false;
while (spot == false)
{
if (name < nHead->name)
{
builder = new Node;
builder->name = name;
builder->nextName = nHead;
nHead->nextName = builder;
spot = true;
return *builder;
}
else if (name < next->name || next->nextName == NULL)
{
builder = new Node;
builder->name = name;
builder->nextName = next->nextName;
next->nextName = builder;
spot = true;
return *builder;
}
else if (name > next->name)
{
next = next->nextName;
//return namePlace(name, builder, next, nHead);
}
}
}
void weightPlace(int weight, Node *builder, Node *next, Node *wHead)
{
bool spot = false;
while (spot == false)
{
if (weight < wHead->weight)
{
builder->weight = weight;
builder->nextWeight = wHead;
wHead = builder;
spot = true;
}
else if (weight < next->weight || next->nextWeight == NULL)
{
builder->weight = weight;
builder->nextWeight = next->nextWeight;
next->nextWeight = builder;
spot = true;
}
else if (weight > next->weight)
{
next = next->nextWeight;
//weightPlace(weight, builder, next, wHead);
}
}
}
void namePrint(Node *nHead, int counter1)
{
Node *next = nHead;
for (int i = 0; i < counter1; i++)
{
cout << next->name << endl;
cout << next->weight << endl;
next = next->nextName;
}
}
void weightPrint(Node *wHead, int counter2)
{
Node *next = wHead;
for (int i = 0; i < counter2; i++)
{
cout << next->name << endl;
cout << next->weight << endl;
next = next->nextName;
}
}

Remove a data from a node

#include <conio.h>
#include <iostream>
#include <string>
using namespace std;
class MysticalBag
{
private:
int useCount;
int content;
string itemName;
public:
MysticalBag *next_ptr;
void setAttributes()
{
//Called for showing the items without any placement of item
useCount = 1;
content = 5;
itemName = "Healing Potion";
}
int takeUseCount()
{
return useCount;
}
int takeContent()
{
return content;
}
string takeItemName()
{
return itemName;
}
void setAttributes(int userCount, int content, string itemName)
{
this->useCount = useCount;
this->content = content;
this->itemName = itemName;
}
void itemAdder()
{
cout << "Enter use count (1-3) " <<endl;
cin >> useCount;
cout << "Enter content (1.0 - 100.0) " <<endl;
cin >> content;
cout << "Enter item name as text" << endl;
cin >> itemName;
cout<< itemName <<" is added in the bag."<< endl;
}
void showBag()
{
cout << "Showing bag contents" << endl << endl;
cout << itemName << endl;
cout << "U - "<< useCount <<", C - "<< content << endl;
}
};
int main()
{
char choice1,choice2;
choice1 = 0;
MysticalBag *head, *tail, *navigator;
navigator = new MysticalBag();
navigator->setAttributes();
head = navigator;
tail = navigator;
tail->next_ptr = NULL;
while(choice1 !='x')
{
cout << "What do you want to do with the bag?" << endl;
cout << "(a)dd item" << endl;
cout << "(r)emove item" << endl;
cout << "(s)how items" <<endl;
cout << "e(x)it" <<endl;
cin >> choice1;
if(choice1 == 'a')
{
navigator = new MysticalBag();
if(head==NULL)
{
head=navigator;
tail=navigator;
tail->next_ptr=NULL;
}
navigator->itemAdder();
tail->next_ptr = navigator;
tail = navigator;
tail->next_ptr = NULL;
}
else if(choice1 == 'r')
{
navigator = head;
tail = head;
while(navigator->next_ptr != NULL)
{
navigator = navigator->next_ptr;
tail = navigator;
}
cout << "Do you want to remove "<< navigator->takeItemName() <<" from your bag? (y/n)"<< endl;
cin >> choice2;
if(choice2 == 'y')
{
navigator = head;
if(navigator == head)
//I am stuck at this point!
navigator = NULL;
cout << "Item removed." << endl;
tail = head;
while(tail->next_ptr != NULL)
{
tail = tail->next_ptr;
}
}
else
{
cout<< "No item removed" <<endl;
}
navigator = head;
if(navigator == head && navigator == tail)
{
navigator = NULL;
head = NULL;
tail = NULL;
}
else
{
navigator = tail;
navigator = NULL;
tail = NULL;
tail = head;
while(tail->next_ptr != NULL)
{
tail = tail->next_ptr;
}
}
}
else if(choice1 != 'x')
{
navigator = head;
while(navigator != NULL)
{
navigator->showBag();
navigator = navigator->next_ptr;
}
}
}
getch();
}
My objective is removing data from a node.
the user can put in data in the node, which is the Navigator.
What I am thinking of is to point navigator to head and Making head recalling the setAttributes(). Which will show the "Healing potion". But, if the user adds to items. How would I remove just one item at a time?
Can you only remove the last item added to the bag, or can any item be removed? The more general case is asking about deletions from a linked list.
To remove an node (item) from a linked list(bag), you need to know the parent of the item you wish to remove. The parent of a node is the node who's next_ptr is the node. So in the loop, you need to track the parent of navigator:
while(navigator->next_ptr != NULL)
{
/* a sample list */
/* "parent" --> "navigator" --> "navigator->next_ptr" */
parent = navigator; /* now we know who points to navigator */
navigator = navigator->next_ptr;
tail = navigator;
}
Once we know the parent of navigator, all that needs to be done to remove navigator is:
parent->next_ptr = navigator->next_ptr;
/* now the list looks like */
/* "parent" --> "navigator->next_ptr" */
And now navigator is removed from the bag.
I think there are still issues with many of your while loops, but fixing them requires knowing more about your intentions.
Is this a list? Why don't you use std::list from inside your custom class?
Well, in short, what you're asking is 'How do a I access a class function if I have a pointer to a class member?' At least that's how I see it.
#include "Items.h" //let me assume you have some sort of struct or class for items in your bag
class Bag : public player { //player would give access to attributes like HP/MP/Who Owns the bag, etc..
protected:
vector<Item*> Contents;
int MaxItems;
public:
Bag();
Store(Item* It);
Remove(Item* It);
UseItem(Item* It);
};
Bag::Store(Item* It) {
if(Contents.size() >= MaxItems) return;
for( int i = 0; i < Contents.size(); i++ ) {
if(It == Contents[i] ) {
return;
}
}
Contents.push_back(It);
}
Bag::Remove(Item* It) {
for(int i = 0; i < Contents.size(); i++) {
if( It == Contents[i] ) {
Contents.erase(Contents.begin() + i);
break;
}
}
Bag::UseItem(Item* It) {
if(!(It->Usable())) { return };
It->Use();
}
class Item {
protected:
int ItemType; //suggest you use some enum for this
public:
Item();
virtual bool Usable();
virtual void Use();
};
Item::Item() { };
bool Item::Usable() {
//Purely Virtual
}
void Item::Use() {
//Same
}
class Potion : public Item {
protected:
int PotionType; //Again, I'd enum this
public:
Potion();
virtual bool Useable();
virtual void Use();
}
Potion::Potion() { ItemType = POTION; }
bool Potion::Useable() { return true; }
void Potion::Use() { //Purely Virtual }
class HealPotion : public Potion {
protected:
int Strength; //who knows, # of hp to heal
public:
HealPotion();
virtual void Use();
};
HealPotion::HealPotion() { PotionType = Heal; Strength = 45; }
void HealPotion::Use() { Owner->ChangeHits(Strength);
this->RemoveItem(this); } //Now you might also want to destroy the item to free up memory