linked list not printing output - c++

I have to dynamically allocate a list of robots for a school project. In an actual program, there will be other member functions that will require the list of names in order to perform certain functions.
As of right now, I just learned about this concept, and have tried really hard to put together some things I have seen online. The issue at the moment is that I can not tell if my list is properly being stored -- I am also getting wonky output when I try to call my display of list function.
Please help if you can. Also, I am happy to hear any tips for literally anything, as I am fairly new to programming.
class Node{
public:
std::string name_;
Node* next;
};
class linkedBotList{
public:
linkedBotList() {head = nullptr;} //constructor
~linkedBotList(){}; // destructure
void addNode();
void display();
private:
Node* head;
};
int main(int argc, const char * argv[]) {
linkedBotList* list = new linkedBotList();
int siz;
std::cout << "How many Robots?" << std::endl;
std::cout << "What are the names?" << std::endl;
std::cin >> siz;
for(int i = 0; i < siz; i++){
list->addNode();
}
delete list;
return 0;
}
void linkedBotList::addNode(){
std::string botName;
Node* newNode = new Node();
newNode->name_ = botName;
newNode->next = nullptr;
std::cin >> botName;
if(head == nullptr){
head = newNode;
}
else {
Node* temp = head; // head is not null
while(temp->next != nullptr){ // go until at the end of the list
temp = temp->next;
}
temp->next = new Node; // linking to new node
}
}
void linkedBotList::display() {
if (head == NULL) {
std::cout << "List is empty!" << std::endl;
}
else {
Node* temp = head;
while (temp != NULL) {
std::cout << "Made it to display funct.\n";
std::cout << temp->name_ << " ";
temp = temp->next;
}
std::cout << std::endl;
}
}
I did try a few things, like switching around my temp variable, and a few other re-assignments. Maybe someone can quickly spot the issue and help?

Your display function is fine.
The problem is that you have 2 logic flaws in addNode():
you are not storing strings in your list correctly. You are assigning botName to newNode->name_ before botName has been assigned a value. So all of your nodes have empty strings. Assigning botName afterwards will not update newNode->name_. 1
if the list is not empty, you iterate to the end of the list correctly 2, but then you assign a new blank node to temp->next instead of assigning your newNode that you already populated. And your Node constructor is not initializing the next member to nullptr, so you are creating a corrupted list, which will cause subsequent loops through the list to invoke undefined behavior.
Try this instead:
void linkedBotList::addNode(){
std::string botName;
std::cin >> botName; // <-- move up here
Node* newNode = new Node{botName, nullptr};
if (!head){
head = newNode;
}
else {
Node* temp = head;
while (temp->next){
temp = temp->next;
}
temp->next = newNode; // <-- linking to new node
}
}
Alternatively, you can eliminate the if like this:
void linkedBotList::addNode(){
std::string botName;
std::cin >> botName;
Node** temp = &head;
while (*temp){
temp = &((*temp)->next);
}
*temp = new Node{botName, nullptr};
}
1: A better design would be to have addNode() take in a string as an input parameter, and then move the cin call into your loop in main().
2: consider adding a tail member to your list to avoid having to loop on each addition.
Try this alternate design:
class Node{
public:
std::string name;
Node* next = nullptr;
};
class linkedBotList{
public:
linkedBotList() = default;
~linkedBotList();
void addNode(std::string name);
void display() const;
private:
Node* head = nullptr;
Node* tail = nullptr;
};
int main() {
linkedBotList list;
int siz;
std::string botName;
std::cout << "How many Robots?" << std::endl;
std::cin >> siz;
std::cout << "What are the names?" << std::endl;
for(int i = 0; i < siz; i++){
std::cin >> botName;
list.addNode(botName);
}
list.display();
return 0;
}
linkedBotList::~linkedBotList(){
Node *temp = head, *next;
while (temp) {
next = temp->next;
delete temp;
temp = next;
}
}
void linkedBotList::addNode(std::string name){
Node* newNode = new Node{name};
if (tail)
tail->next = newNode;
else
head = newNode;
tail = newNode;
}
void linkedBotList::display() const {
if (!head) {
std::cout << "List is empty!" << std::endl;
}
else {
Node* temp = head;
do {
std::cout << temp->name << " ";
temp = temp->next;
}
while (temp);
std::cout << std::endl;
}
}

Related

I read the input number with getchar(), why is the number reversed in the linked list?

I typed 1234, but the list has 4,3,2,1 in it. I suspect the problem is getchar() itself, or a function in the class, but I have no way to find out.
The link class is responsible for some linked list operations, such as deletion, insertion, etc., while the node class is responsible for creating and assigning nodes.
The createlist class is responsible for the creation of the linked list, which is the main source of the problem. I wrote the debug statement in it, so you can run it and see the results for yourself
using namespace std;
class Node
{
public:
int data;
Node *next;
Node()
{
next = nullptr;
}
Node(int data)
{
this->data = data;
}
Node(const Node &temp)
{
this->data = temp.data;
}
};
class Link
{
public:
Node *head;
int length = 0;
Link()
{
head = new Node();
}
~Link()
{
while (head != nullptr)
{
Node *p = head->next;
free(head);
head = p;
}
}
void insert(const Node &cache)
{
Node *temp = new Node(cache);
temp->next = head->next;
head->next = temp;
length++;
}
};
void Creatlist(Link &link)
{
char cache;
while (1)
{
cache = getchar();
if (cache == '\n')
break;
link.insert(Node(cache - '0'));
cout << cache << " ";
}
cout<<endl;
Node *p = link.head->next;
cout << "in the linklist:";
while (p != nullptr)
{
cout << p->data << " ";
p = p->next;
}
}
int main()
{
Link link;
cout<<"inut numbers:"<<endl;
Creatlist(link);
}```
With the insert you inserted to the FRONT of the list. So you had "1", then "2->1" ... If you want to insert to the end, don't insert at the head, but hake a Node* tail in the class Link and an insert_end function as
//...
Node* temp;
void insert_end(const Node &cache){
Node *temp = new Node(cache);
tail->next=temp;
tail=tail->next;
length++;
}
Alsoin the constructor set tail=head

How to remove a certain node from a linked list by the data its holding?

We are suppose to enter a string, and then find where the string is in the linked list and remove that node
when i insert to the front of the list, so i enter data values a, b, c , d, when i print it it comes up as d,c,b,a. Now i insert to the rear of it, entering f and g, and the list now looks, d,c,b,a,f,g. I want to remove f but it just use the remove function it does not and still output the same list
using namespace std;
struct node {
string data;
node* next;
};
node* addFront(node* s);
node* addRear(node* s);
void remove(node* head, string abc);
void print(node* head);
int main() {
node* head = NULL;
cout << "Enter 5 data strings\n";
cout << "This will be inserted from the back\n";
for (int i = 0; i < 5; i++) {
head = addFront(head);
}
print(head);
cout << "Enter 3 strings and this will be inserted from the back of the orignal string\n";
for (int i = 0; i < 3; i++) {
head = addRear(head);
}
print(head);
cout << "Removing the head node\n";
string n;
cout << "Enter a string to remove\n";
cin >> n;
remove(head, n);
print(head);
}
node* addFront(node* s)
{
node* person = new node;
cin >> person->data;
person->next = s;
s = person;
return s;
}
node *addRear(node*s ) {
node* person = new node;
cin >> person->data;
person->next = NULL;
if (s == NULL) {
return person;
}
else {
node* last = s;
while (last->next != NULL) {
last = last->next;
}
last->next = person;
}
return s;
}
void remove(node* head, string a) {
node* previous = NULL;
node* current = head;
if (current == NULL) {
cout << "Value cannot be found\n";
return;
}
else {
while (previous != NULL) {
if (current->data == a) {
previous->next = current->next;
delete current;
break;
}
current = current->next;
}
}
}
void print(node * head)
{
node* temp = head;
while (temp != NULL) // don't access ->next
{
cout << temp->data << " ";
temp = temp->next;
}
cout << endl;
}
In remove function, previous is most certainly NULL when you hit that while loop.
Perhaps consider a do-while loop instead (with better handling of previous).
You may be better off handling the first node in a different manner since the holder of its previous is essentially the root pointer.

C++ Linked List Not Preserving New Nodes

I'm trying to transition from an almost entirely Java background to getting comfortable with C++. I'm practicing by trying to build a basic Linked List.
#include <iostream>
#include <string>
using namespace std;
struct node
{
string data;
node *next = NULL;
};
class linkedlist
{
public:
node *head;
public:
linkedlist()
{
head = NULL;
}
void addNode(string s)
{
node *newNode = new node;
newNode->data = s;
if(head == NULL)
head = newNode;
else
{
node *temp = head->next;
while(temp != NULL)
temp = temp->next;
temp = newNode;
}
}
void printList()
{
node *temp = head;
while(temp != NULL)
{
cout << temp->data << '\n';
temp = temp->next;
}
}
};
The issue at hand is that once I add a new node using void addNode(string s), it does not appear when I attempt to print the list (starting from the head) with void printList().
For example:
int main(int argc, const char * argv[])
{
int n;
string str;
linkedlist list;
cout << "Please enter the number of strings you'd like to enter:\n";
cin >> n;
for(int i = 0;i < n;i++)
{
string temp;
cout << "Enter string #" << i + 1 << '\n';
cin >> temp;
list.addNode(temp);
}
cout << "This is your linked list: ";
list.printList();
return 0;
}
Using main() above, my results become:
This is your linked list:
(string 1)
I'm pretty certain I'm using pointers improperly here but I don't see why. I've done as much digging as I can on my own for some clarification on how I could be doing this wrong but I'm coming up blank.
Thanks for any clarification you folks can provide.
The problem is here:
node *temp = head->next;
while(temp != NULL)
temp = temp->next;
temp = newNode;
You're traversing the list, then setting temp to the value of the newNode. When temp goes out of scope, the value for newNode isn't stored anyplace.
What you want to do is set the next pointer of the last node to the value of newNode, i.e.
node *temp = head;
while(temp->next != NULL)
temp = temp->next;
temp->next = newNode;
The code above traverses the list until it finds a node that doesn't have a next node, and sets its next node to the newNode, thus adding it to the list.

Linked list class

The purpose of my program is to read in data from a file and build a linked list with this data and then deallocate all the nodes used.
the program also needs to print out the address of nodes after they are created and then after that they are deleted
#include <iostream>
#include <string>
#include <fstream>
#include "BigHero.h"
using namespace std;
// Linked List Struct
struct Node{
BigHero data;
Node* Next;
};
// Funtion Prototypes
int countHeros(string,int&);
void createList(BigHero,int,Node*&,Node*&,Node*&);
void printList(Node*,Node*,Node*);
void deallocateList(Node*&,Node*&,Node*&);
int main()
{
// Program Variables
Node* head;
Node* currentPtr;
Node* newNodePtr;
string Filename = "ola5party.dat"; // File string varible
int charNumber = 0; // variable to hold number of Heroes
int i = 0; // Loop control varible
countHeros(Filename,charNumber); // Function call used to count number of Heros
ifstream inFile;
inFile.open(Filename.c_str());
if(!inFile){
cout << "Error in opening file" << endl;
return 0;
}
BigHero Hero;
while(inFile)
{
inFile >> Hero;
createList(Hero,charNumber,head,currentPtr,newNodePtr);
}
printList(head,currentPtr,newNodePtr);
deallocateList(head,currentPtr,newNodePtr);
inFile.close();
return 0;
}
int countHeros(string Filename,int& charNumber)
{
ifstream inFile;
inFile.open(Filename.c_str());
string aLineStr;
while (getline(inFile, aLineStr))
{
if (!aLineStr.empty())
charNumber++;
}
inFile.close();
return charNumber;
}
void createList(BigHero Hero, int charNumber,Node*& head, Node*& currentPtr, Node*& newNodePtr)
{
head = new Node;
head->data =Hero;
currentPtr = head;
newNodePtr = new Node;
cout << "Allocated # " << newNodePtr << endl;
newNodePtr->data = Hero;
currentPtr->Next = newNodePtr;
currentPtr = newNodePtr;
}
void printList(Node* head, Node* currentPtr, Node* newNodePtr)
{
if(head != NULL)
{
currentPtr = head;
while(currentPtr->Next != NULL)
{
cout << currentPtr->data << endl;
currentPtr = currentPtr->Next;
}
}
}
void deallocateList(Node*& head ,Node*& currentPtr,Node*& newNodePtr)
{
if( head != NULL)
{
currentPtr = head;
while( head -> Next != NULL)
{
head = head->Next;
cout << "Deleting # " << head << endl;
delete currentPtr;
currentPtr = head;
}
delete head;
head = NULL;
currentPtr = NULL;
}
}
the program like this runs without errors, but here is the problem it will input all the information required but since i only have one variable hero class it is constantly replacing the information.
i tried to make a class array (example hero[i]) but cant seem to get it right and am not even sure if that is the solution. Everything is fine but i cant get the desired number of class object and i always end up with one class
this is my desired output but i only get one class object
Allocated#0x8722178
Allocated#0x87221d0
Allocated#0x8722210
Allocated#0x8722230
Allocated#0x8722288
Allocated#0x87222c8
Hero:MacWarrior­Level134,(34,16,48)­Exp:13425
Hero:LinuxMage­Level149,(24,54,21)­Exp:14926
Hero:PCBard­Level122,(18,32,17)­Exp:12221
Hero:PythonThief­Level90,(24,18,61)­Exp:9001
Hero:CplusPaladin­Level159,(31,38,29)­Exp:15925
Deleting#0x8722178
Deleting#0x87221d0
Deleting#0x8722210
Deleting#0x8722230
Deleting#0x8722288
Deleting#0x87222c8
It seems you have misunderstood the basic idea behind a link listed. You are not supposed to overwrite head again and again when adding element. head shall only be changed when the list is empty.
Try something like this:
struct Node
{
BigHero data;
Node* next;
};
void addNewNode(Node*& head, ....)
{
if (head == nullptr)
{
// List empty so add new node as head
head = new Node;
head->next = nullptr;
return;
}
// Find last element in list (performance can be improved with a tail*)
Node* temp = head;
while (temp->next != nullptr) temp = temp->next;
// Add new element to end of list
temp->next = new Node;
temp->next->next = nullptr
return;
}
int main()
{
Node* head = nullptr;
addNewNode(head, ....);
return 0;
}
For performance it is often good to have a tail-pointer also.
Further you should not define head in main() but make a class/struct for it and put the relevant functions in the class. Like:
struct Node
{
BigHero data;
Node* next;
};
class ListOfNode
{
public:
ListOfNode() : head(nullptr), size(0) {}
~ListOfNode()
{
// Delete all nodes
}
void addNewNode(....)
{
// ....
++size;
}
size_t size() { return size; }
private:
Node* head; // Optional: Add a tail* for better performance
size_t size;
};
int main()
{
ListOfNode list;
list.addNewNode(....);
cout << list.size() << endl;
return 0;
}

C++ doubly linked list

I got a problem with my doubly linked list. How can i make the input unique ( i don`t want it to be repeated )
for example i can input 1 and then again 1 i will have a list of 1 and 1. I need to forbid this somehow :) so the list can contain only not repeating numbers.
#include <cstdlib>
#include <iostream>
using namespace std;
struct node
{
int data;
node* next;
node* prev;
};
class Node
{
public:
Node();
~Node();
void setKopa();
void printForward();
private:
node* head;
node* tail;
node* n;
};
Node::Node()
{
setKopa();
}
Node::~Node()
{
delete n;
}
void Node::setKopa()
{
int lenght;
do
{
cout << "Input list lenght (how many elements): ";
cin >> lenght;
if(lenght<2)
cout << "Error list has to have atleast 2 elements!" <<endl;
}
while(lenght<2);
int fill;
cout << "Input "<< lenght <<" elements: "<<endl;
for (int i=0; i<lenght; i++)
{
cin>>fill;
n = new node;
n->data = fill;
if (i==0)
{
n->prev = NULL;
head = n;
tail = n;
}
else if (i+1==lenght)
{
n->prev = tail;
tail->next = n;
tail = n;
tail->next = NULL;
}
else
{
n->prev = tail;
tail->next = n;
tail = n;
}
}
}
void Node::printForward()
{
node* temp = head;
while(temp != NULL)
{
cout << temp->data << " ";
temp = temp-> next;
}
cout << endl;
}
int main()
{
Node a;
a.printForward();
system("pause");
return 0;
}
When you read input, go through the list to see if the input is already there.
With that (simple) answer out of the way, I would like to address some other things regarding your code. The first is that you have a memory leak in that you never delete the list. The second is that you don't need the class member variable n, it might as well be a local variable inside the setKopa loop.
Your way of adding new nodes is also, well, weird. It should, in my opinion, be more general instead of using the loop counter to check what to do. What I suggest is that you make a member function to add new nodes, taking the integer data as argument. This way you can call this function to add nodes anywhere, and not just in the setKopa function. In fact, I think the list should not handle that input at all, instead it should be a free-standing function called from main and which calls the addNode function.
Also the node structure doesn't need to be in the global namespace, it could be a private structure in the Node class. And speaking of the Node class, shouldn't it really be called List instead?
So if I may suggest, you might want to do something like this:
#include <iostream>
class List
{
public:
List()
: head(nullptr), tail(nullptr)
{}
~List();
void addNode(const int data);
void printAll() const;
private:
struct node
{
node()
: next(nullptr), prev(nullptr)
{}
node* next;
node* prev;
int data;
};
node* head;
node* tail;
};
List::~List()
{
for (node* next, *cur = head; cur; cur = next)
{
next = cur->next;
delete cur;
}
}
void List::addNode(const int data)
{
node* n = new node;
n->data = data;
if (tail == nullptr)
{
// First node in list
head = tail = n;
}
else
{
n->prev = tail;
tail->next = n;
tail = n;
}
}
void List::printAll() const
{
std::cout << "{ ";
for (node* cur = head; cur != nullptr; cur = cur->next)
std::cout << cur->data << ' ';
std::cout << "}\n";
}
int main()
{
List list;
for (int i = 0; i < 10; ++i)
list.addNode(i);
list.printAll();
}
The above code should print
{ 0 1 2 3 4 5 6 7 8 9 }
Replace the node-adding loop with your own.