Print Function Linked Lists C++ - c++

I'm currently learning Linked Lists in C++, and I can't write a print function which prints out the elements of the list; I mean I wrote the function but it doesn't work properly.
#include <iostream>
using namespace std;
struct node
{
char name[20];
node* next;
};
node* addNewPerson(node* head)
{
node* person = new node;
cout << "Name: ";
cin >> person->name;
person->next = NULL;
if (head == NULL) //is empty
{
head = person;
}
else
{
person = person->next;
}
return head;
}
void printList(node* head)
{
node* temp = head;
cout << temp->name << endl;
}
int main()
{
node* head = NULL;
node* temp = head;
unsigned short people = 0;
cout << "How many people do you want to invite to the party?" << endl;
cout << "Answer: ";
cin >> people;
cout << endl;
for (unsigned short i = 1; i <= people; i++)
{
addNewPerson(head);
cout << endl;
}
cout << "LIST: " << endl;
cout << endl;
while (temp != NULL)
{
printList(temp);
temp = temp->next;
}
cin.get();
}
I am wondering what I'm doing wrong, please help me!

It is obvious that function addNewPerson is wrong.
node* addNewPerson(node* head)
{
node* person = new node;
cout << "Name: ";
cin >> person->name;
person->next = NULL;
if (head == NULL) //is empty
{
head = person;
}
else
{
person = person->next;
}
return head;
}
You allocated new node person.
node* person = new node;
Set its field next to NULL
person->next = NULL;
Then if head is not equal to NULL you set person to person->next
person = person->next;
As person->next was set to NULL it means that now also person will be equal to NULL.
Moreover the function returns head that can be changed in the function. However you ignore returned value in main
addNewPerson(head);
At least there should be
head = addNewPerson(head);
The valid function addNewPerson could look the following way
node* addNewPerson(node* head)
{
node* person = new node;
cout << "Name: ";
cin >> person->name;
person->next = head;
head = person;
return head;
}
And in main you have to write
for (unsigned short i = 1; i <= people; i++)
{
head = addNewPerson(head);
cout << endl;
}
Function printList does not output the whole list. It outputs only data member name of the first node that is of head.
void printList(node* head)
{
node* temp = head;
cout << temp->name << endl;
}
It should look the following way
void printList(node* head)
{
for ( ; head; head = head->next )
{
cout << head->name << endl;
}
}
And at last main should look as
int main()
{
node* head = NULL;
unsigned short people = 0;
cout << "How many people do you want to invite to the party?" << endl;
cout << "Answer: ";
cin >> people;
cout << endl;
for ( unsigned short i = 0; i < people; i++ )
{
head = addNewPerson(head);
cout << endl;
}
cout << "LIST: " << endl;
cout << endl;
printList( head );
cin.get();
}

In your addNewPerson function person->next never gets set, because head is always NULL.

addNewPerson method
Your addNewPerson method never added a new person to the list it just set the head to the new person.
node* addNewPerson(node* head)
{
node* person = new node;
cout << "Name: ";
cin >> person->name;
person->next = NULL;
if (head->next == NULL) //is empty
{
head->next = person;
}
else
{
person->next = head->next;
head->next = person;
}
return head;
}
printList method
Your method printList should do what it says and print the list, instead of just printing one person at a time.
void printList(node* head)
{
node* tmp = head;
while(tmp->next != NULL) {
tmp = tmp->next;
cout >> tmp->name >> endl;
}
}
main method
Upadted your main method with the new printList method.
int main()
{
node* head = new node;
unsigned short people = 0;
cout << "How many people do you want to invite to the party?" << endl;
cout << "Answer: ";
cin >> people;
cout << endl;
for (unsigned short i = 1; i <= people; i++)
{
addNewPerson(head);
cout << endl;
}
cout << "LIST: " << endl;
cout << endl;
cout << printList(head);
cin.get();
}
Also why are you using unsigned short and char arrays? Do you have a limited amount of memory? Why not just use int and string?

When you are adding a new person, it is not actually put into the linked list, since you have never invoked something like head -> next = person.
The section in your addNewPerson routine should be something like
if (head == NULL) {
head = person;
} else {
node * end = head;
while (end -> next != NULL) // find the end of the list to insert new person
end = end -> next;
end -> next = person;
}
And in the beginning you can't just pass head into addNewPerson, since it is a pointer with null value, the addNewPerson method accepts a pointer by value (value of the memory address it is pointing at) rather than a reference to head. So you need to use
node* addNewPerson(node* &head) { ... }
instead. Finally, when you declare temp, it first receives the value of head as well, so later access to temp would only give you NULL again. You need to change it to
node* &temp = head;

I think the problem is in how the link list is being added to in addNewPerson.
The input to addNewPerson is 'head' so each time, before adding a new node to the linked list, we need to traverse all the way down the linked list till the last node before appending 'person' to the linked list.

struct node
{
char name[20];
node* next;
};
node* addNewPerson(node* head)
{
node* person = new node;
//cout << "Name: ";
cin >> person->name;
person->next = head;
head = person;
return head;
}
void PrintLL(node *head)
{
while (head!=NULL){
cout<< head->name <<endl;
head=head->next;
}
}
int main() {
node* head = NULL;
node* temp = head;
int num_ppl;
cout << "How many people do you want to invite to the party?" << endl;
cout << "Answer: ";
cin >> num_ppl;
for(int arr_i = 0; arr_i < num_ppl; arr_i++){
head = addNewPerson(head);
}
PrintLL(head);
return 0;
}

Related

LinkedList Remove function fails when deleting from the end of the list C++

I have a LinkedList class and everything works except for my remove function. It works except for when it is removing from the end. If I remove from the end and then try to display the new list the program crashes and doesnt give me an error. I was wondering if someone could help me pinpoint what I did wrong in the remove function where I am removing the tail.
Main method
#include "LinkedList.h"
#include <cstdlib>
#include <iomanip>
using namespace std;
void MainMenu(int& menu);
int main(int argc, char** argv) {
int menu = 0;
string name;
LinkedList list;
while (true)
{
MainMenu(menu);
if (menu == 1)
{
cout << "Please enter the name you want to add to the front: " << endl;
cin >> name;
list.addFront(name);
}
else if (menu == 2)
{
cout << "Please enter the name you want to add to the back: " << endl;
cin >> name;
list.addBack(name);
}
else if (menu == 3)
{
cout << "Please enter the name you want to remove: " << endl;
cin >> name;
list.remove(name);
}
else if (menu == 4)
{
list.display();
}
else if (menu == 5)
{
cout << "\nThank you for using my program!" << endl;
exit(0);
}
}
return 0;
}
void MainMenu(int& menu)
{
cout << '\n' << endl;
cout << left << setw(30) << right << setw(20) << "Main Menu" << endl;
cout << setw(36) << setfill('*') << "\n" << endl;
cout << "1. Add node to front." << endl;
cout << "2. Add node to back." << endl;
cout << "3. Remove node." << endl;
cout << "4. Display list." << endl;
cout << "5. Exit" << endl;
cout << setw(36) << "\n" << endl;
cout << "Please enter a menu number to proceed: " << endl;
cin >> menu;
while (menu != 1 && menu != 2 && menu != 3 && menu != 4 && menu != 5)
{
cout << "Menu options are 1 - 5" << endl;
cout << "Please enter a menu number to proceed: " << endl;
cin.clear();
cin.ignore(100, '\n');
cin >> menu;
}
cout << setfill(' ') << "\n" << endl;
}
Header file
#include <iostream>
using namespace std;
#ifndef LINKEDLIST_H
#define LINKEDLIST_H
struct Node
{
string name;
Node * next;
};
class LinkedList {
public:
Node * head = nullptr;
Node * tail = nullptr;
Node * current = nullptr;
void addFront(string name);
void addBack(string name);
void remove(string name);
void display();
LinkedList();
LinkedList(const LinkedList& orig);
virtual ~LinkedList();
private:
};
#endif /* LINKEDLIST_H */
Source File
#include "LinkedList.h"
void LinkedList::addFront(string name)
{
Node * node = new Node();
node->name = name;
if (head != nullptr)
{
node->next = head;
head = node;
}
else
{
head = node;
tail = node;
}
}
void LinkedList::addBack(string name)
{
Node * node = new Node();
node->name = name;
node->next = nullptr;
if (head == nullptr)
{
head = node;
tail = node;
}
else
{
node->next = nullptr;
tail->next = node;
tail = node;
}
}
void LinkedList::remove(string name)
{
Node * temp = head;
while (temp != nullptr)
{
if (temp->name == name)
{
cout << "Name found! Being removed." << endl;
break;
}
temp = temp->next;
if (temp == nullptr)
{
cout << "Name not found!" << endl;
return;
}
}
temp = head;
if(head == nullptr)
{
cout << "The list is empty." << endl;
return;
}
while(!(temp->name == name))
{
temp = temp->next;
}
if (temp == tail && temp == head)
{
head = nullptr;
tail = nullptr;
delete temp;
}
else if (temp == tail)
{
temp->next = tail;
delete temp->next;
temp->next = nullptr;
tail = temp;
}
else if(temp == head)
{
temp = head;
head = temp->next;
delete temp;
}
else
{
temp = head;
while(!(temp->next->name == name))
{
temp = temp->next;
}
Node * next = temp->next->next;
delete temp->next;
temp->next = next;
}
}
void LinkedList::display()
{
current = head;
if (current == nullptr)
{
cout << "The list is empty!" << endl;
}
while (current != nullptr)
{
cout << current->name << endl;
current = current->next;
}
}
LinkedList::LinkedList() {
}
LinkedList::LinkedList(const LinkedList& orig) {
}
LinkedList::~LinkedList() {
}
Your main problem is this section here
else if (temp == tail)
{
temp->next = tail;
delete temp->next;
temp->next = nullptr;
tail = temp;
}
That is what executes if the match is the last item. But if it is the last item then temp->next will be tail because you just set it to tail, and since temp == tail that also invalidates temp. Setting temp->next will be using a deleted pointer. There's no fixing this at this point because you need the previous node to set tail to, and you didn't save it, so you'd have to loop through again to get it.
Now, for the solution, you should do a single loop. No need to loop multiple times (3 in most cases)
void LinkedList::remove(string name)
{
Node * temp = head;
Node * prev = nullptr;
while (temp != nullptr)
{
if (temp->name == name)
{
cout << "Name found! Being removed." << endl;
if (prev != nullptr) {
prev->next = temp->next
}
else {
head = temp->next;
}
if (tail == temp) {
tail = prev;
}
delete temp;
return;
}
prev = temp;
temp = temp->next;
}
cout << "Name not found!" << endl;
}
For starters everywhere in member function declarations where a parameter is declared like
string name
you should change it to
const string &name
Secondly the member function remove shall not issue any message. It is the caller of the function that decides whether to output a message.
Your function is inefficient because it traverses the list two or even three times in loops and has too many conditions that makes the function too complicated. As a result the function has bugs.
For example in this if statement
else if (temp == tail)
{
temp->next = tail;
delete temp->next;
temp->next = nullptr;
tail = temp;
}
there is used deleted pointer temp to access memory because temp is equal to tail (according to the condition of the if statement)
temp->next = nullptr;
and tail again is set to the deleted pointer
tail = temp;
The function can be declared and defined the following way
class LinkedList {
public:
//...
bool remove( const std::string &name );
};
bool LinkedList::remove( const std::string &name )
{
Node *prev = nullptr;
Node *current = head;
while ( current && current->name != name )
{
prev = current;
current = current->next;
}
bool success = current != nullptr;
if ( success )
{
if ( prev )
{
prev->next = current->next;
if ( prev->next == nullptr ) tail = prev;
}
else
{
head = head->next;
if ( head == nullptr ) tail = nullptr;
}
delete current;
}
return success;
}

Having trouble converting a string to a linked character list in C++

I have been working on this for a while and am currently stumped. The starting requirement for the program is to accept a string, create an object for the class, and convert it to a linked list of characters. I'm having trouble with the whole class since when I try to predefine a new object in the Main function before the while loop I get the error charchain.cpp:(.text+0x20): undefined reference to linkedChar::linkedChar() I have tested the class and have had success with converting to a linked list of characters.
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;
struct node {
char data;
node* next;
};
class linkedChar
{
private:
node* head;
public:
string str;
linkedChar();
linkedChar(const std::string s){
head = NULL;
strToLinkedChar(s);
}
node* add(char data)
{
node* newnode = new node;
newnode->data = data;
newnode->next = NULL;
return newnode;
}
node* strToLinkedChar(string str){
head = add(str[0]);
node* curr = head;
for (int i = 1; i < str.size(); i++) {
curr->next = add(str[i]);
curr = curr->next;
}
}
void print()
{
node* curr = head;
while (curr != NULL) {
cout << curr->data << " ";
curr = curr->next;
}
}
void listLen(){
int counter = 0;
node* curr = head;
while (curr != NULL) {
curr = curr->next;
counter++;
}
std::cout << "There are " << counter << " characters in the current linked list of characters." << std::endl;
}
};
int main()
{
int userInput;
linkedChar linkedObject;
while (userInput != 6){
userInput = -1;
std::cout << "Option Menu: \n1. Enter new string and store as linked list of characters in an ADT LinkedChar class\n2. Get current length (number of characters stored) from the LinkedChar \n3. Find index of character in this LinkedChar \n4. Append another LinkedChar to this LinkedChar (no shallow copy)\n5. Test if another LinkedChar is submatch of this LinkedChar\n6. Quit\n" << std::endl << "Input:";
std::cin >> userInput;
std::cout << std::endl;
if(userInput == 1){
string str;
std::cout << "Enter the string you want to turn into a linked list of characters: ";
std::cin >> str;
std::cout << std::endl;
linkedObject = linkedChar(str);
} else if(userInput == 2){
linkedObject.listLen();
}
}
}
I appreciate any input!
You're missing linkedChar no arguments ctor (it's declared but not defined) and you're missing return statement in strToLinkedChar.

Can you check why removing an Item from a linked list is not working in this code? [duplicate]

This question already has an answer here:
How do I properly delete nodes of linked list in C++
(1 answer)
Closed 2 years ago.
I've been asked by a friend to help him with an exercise, basically the idea is like below.
Car number = fr50000 Car owner = AlexNelson Parking time = 3.5 hours.
He was told not to use stuff like string or getline, so it's simple app just to learn the idea of working with linked lists.
So I made this program. When I'm calling the remove() function the first time, it says the list is empty at the beginning (as it should do). But the second and third time, it's saying that the car is removed, but when I call the display() function, the car is still there (it didn't remove from the list)
Can you tell me what's wrong with my code?
#include <iostream>
using namespace std;
int length = 0;//variable of how many items in the list
struct node
{
char carNumber[15];
char carOwner[20];
float parkingTime;
node *link;
};
typedef struct node node;
node *head;//the begining of a list;
bool isempty()
{
if (length == 0)
return true;
else
return false;
}
void insert()
{
if (isempty())
{
head = new node;
cout << "Enter car number: ";
cin >> head->carNumber;
cout << "Enter Car owner: ";
cin >> head->carOwner;
cout << "Enter parking time: ";
cin >> head->parkingTime;
head->link = NULL;
length++;
}
else
{
node *p = head;
node *pnext = new node;
while (true)
{
if (p->link == NULL)
{
p->link = pnext;
break;
}
p = p->link;
}
cout << "Enter car number: ";
cin >> pnext->carNumber;
cout << "Enter Car owner: ";
cin >> pnext->carOwner;
cout << "Enter parking time: ";
cin >> pnext->parkingTime;
pnext->link = NULL;
length++;
}
}
void remove()
{
if (isempty())
{
cout << "List is empty\n";
return;
}
char carnumber[15];
cout << "Enter car number to remove: ";
cin >> carnumber;
node *p;
p = head;
while (p != NULL)
{
if (strcmp(p->carNumber, carnumber) == 0)
{
p = p->link;
cout << "Car removed\n";
return;
}
p = p->link;
}
cout << "Car was not found, check the number\n";
}
void display()
{
if (isempty())
{
cout << "List is empty\n";
return;
}
cout << "Car Number\t\tCar Owner\t\tParking Time\n";
node *p = head;
while (p != NULL)
{
cout << p->carNumber << "\t\t" << p->carOwner << "\t\t" << p->parkingTime << " Hours\n";
p = p->link;
}
}
int main()
{
string number;
display();
insert();
insert();
insert();
display();
remove();
display();
insert();
remove();
display();
}
Your remove() function is not actually removing (or destroying) a node from the list. You need to update the link of the previous node in the list to point to the next node in the list. And you need to update the head too, if removing the 1st node in the list.
Try this instead:
void remove()
{
if (isempty())
{
cout << "List is empty\n";
return;
}
char carnumber[15];
cout << "Enter car number to remove: ";
cin >> carnumber;
node *p = head;
node *prev = NULL;
while (p != NULL)
{
if (strcmp(p->carNumber, carnumber) == 0)
{
if (p == head)
head = p->link;
if (prev)
prev->link = p->link;
delete p;
cout << "Car removed\n";
return;
}
prev = p;
p = p->link;
}
cout << "Car was not found, check the number\n";
}
Alternatively:
void remove()
{
if (isempty())
{
cout << "List is empty\n";
return;
}
char carnumber[15];
cout << "Enter car number to remove: ";
cin >> carnumber;
node **p = &head;
while (*p != NULL)
{
if (strcmp((*p)->carNumber, carnumber) == 0)
{
node *n = *p;
*p = (*p)->link;
delete n;
cout << "Car removed\n";
return;
}
p = &(p->link);
}
cout << "Car was not found, check the number\n";
}
p = p->link; You're modifying the value of the local variable p, not the list. You need to modify the previous node's link field.
In the loop in remove, you are doing p = p->link, when p points to the node you want to remove. But you actually need to update the link field of the node that is pointing to p.
Here's a simple way of doing that:
node **p = &head;
while(*p)
if (strcmp((*p)->carNumber, carnumber) == 0)
break;
else p = &(*p)->link;
if (*p)
{
cout<<"Car removed\n";
delete std::exchange(*p, (*p)->link);
}
else cout << "Car was not found, check the number\n";
If you can't use std::exchange, then you can replace that with:
auto h = *p;
*p = (*p)->link);
delete h;

Creating Linked list insertion function but the code is not running

Unable to recognize the error in creating a linked list insertion function in linked list class the compiler giving this " error: qualified-id in declaration before '(' token But it seems like all the parenthesis are placed correctly.
#include <iostream>
using namespace std;
void additem();
void deleteitem();
void searchitem(int x);
struct student{
int data;
int * next;
};
student * head;
student * curr;
int main()
{
int x;
cout << "To add item type 1" << endl;
cin >> x;
switch(x)
{
case 1:
additem();
}
return 0;
}
void additem()
{
student * temp;
if(head == NULL)
{
temp = new student;
head = temp;
curr = temp;
temp->next = NULL;
cout << "Enter data" << endl;
cin >> temp->data << endl;
}
else if(head != NULL)
{
temp = new student;
curr->next = temp;
curr = temp;
temp->next = NULL;
cout << "Enter data" << endl;
cin >> temp->data ;
}
else{
break;
}
}
You're declaring a class and methods within main. This is not allowed (nested functions). linkedlist::additem needs to be defined before main.

Why is this function causing a crash? (Multilist)

I'm working on my first multilist and it has been nothing but a nightmare so far. Right now, I am allowing the user to place the x,y spots (class_number,student_number) in on their own. My node looks like this:
typedef struct node {
int student_number;
int class_number;
struct node* classpointer;
struct node* studentpointer;
}* nodePtr;
Initialized with
List::List() {
head = nullptr;
currClass = nullptr;
currStudent = nullptr;
}
To add in the data values and set up pointers I have two functions.
void List::addNodeToClass() {
nodePtr n = new node;
n->classpointer = NULL;
cout << "What class number would you like to add?" << endl;
int x;
cin >> x;
n->class_number = x;
if(head != NULL) {
currClass = head;
while (currClass->classpointer != NULL) {
currClass = currClass->classpointer;
}
currClass->classpointer = n;
}
else {
head = n;
}
}
And
void List::addNodeToStudent() {
nodePtr n = new node;
n->studentpointer = NULL;
cout << "What student number would you like to add?" << endl;
int x;
cin >> x;
n->student_number = x;
if(head != NULL) {
currStudent = head;
while (currStudent->studentpointer != NULL) {
currStudent = currStudent->studentpointer;
}
currStudent->studentpointer = n;
}
else {
head = n;
}
}
I make function calls to both of these functions in my menu() function, and in main() I only call for menu()
int menu() {
int input;
List List;
while (input != 3) {
cout << " " << endl;
cout << "Press '1' to input a node" << endl;
cout << "Press '2' to view the list of nodes" << endl;
cout << "Press '3' to exit" << endl;
cout << " " << endl;
cin >> input;
if (input == 1) {
List.addNodeToClass();
List.addNodeToStudent();
}
else if (input == 2) {
List.PrintList();
}
else if (input == 3) {
return 0;
}
else {
cout <<"That is an invalid key" << endl;
}
}
}
When I run the program I am able to input the class node, then when I go to enter the student node, after hitting enter the program crashes. I know that there is a lot to look through, but I can't understand why it is. If someone would be able to tell me what I am doing wrong here I would greatly appreciate it. Thank you.
The addNodeToClass function never sets node->studentpointer. So when you follow that pointer in addNodeToStudent, you are dereferencing garbage.
Your code would be safer with a default node constructor:
typedef struct node {
node()
{
student_number = 0;
class_number = 0;
classpointer = nullptr;
studentpointer = nullptr;
}
int student_number;
int class_number;
struct node* classpointer;
struct node* studentpointer;
}* nodePtr;
And this would fix your issue because those attributes are not always initialized in your code (new node does not initialize the node attributes if there is no such constructor).