As you managed to fix my code last time, i wanted to ask for your help again.
As i already have a predefined list of five elements, this code seems rather nonsens, as there is no purpose of checking if the list is empty. I can't seem to figure out who to bypass the if-else, and just keep the "insert" function instead of also checking if the list is empty...
#include <iostream>
#include <cmath>
using namespace std;
struct node
{
string nameOfFood;
int eatCalories;
int number;
node *next;
};
bool isEmpty(node *head);
char menu();
void insertAsFirstElement(node *&head, node *&last, string name, int eatCalories);
void insert(node *&head, node *&last, string name, int eatCalories);
void showList(node *current);
bool isEmpty(node *head)
{
if(head == NULL)
return true;
else
return false;
}
char menu()
{
char choice;
cout << "Menu\n";
cout << "1. Add food, beverage etc.\n";
cout << "2. Show the list of food(s), beverage(s) etc.\n";
cout << "3. Update your current weight\n";
cout << "4. What have you been eaten?\n";
cout << "5. What exercise have you done?\n";
cout << "6. Exit program \n";
cin >> choice;
return choice;
}
void insertAsFirstElement(node *&head, node *&last, string nameOfFood, int eatCalories)
{
node *temp = new node;
temp->nameOfFood = nameOfFood;
temp->eatCalories = eatCalories;
temp->next = NULL;
head = temp;
last = temp;
}
void insert(node *&head, node *&last, string nameOfFood, int eatCalories)
{
if(isEmpty(head))
insertAsFirstElement(head, last, nameOfFood, eatCalories);
else
{
node *temp = new node;
temp->nameOfFood = nameOfFood;
temp->eatCalories = eatCalories;
temp->next = NULL;
last->next = temp;
last = temp;
}
}
Let me know if you need more of the code?
Hoping for your help!
That check is necessary, because if your list is empty then you have to perform a certain number of operations that are only performed in that case.
There's really no purpose in implementing your own linked list. Classes that are way more flexible than yours have already been defined by the standard, see std::forward_list (singly linked list) and std::list (doubly linked list).
It is recommended that you default to std::vector or std::array when choosing a container. In this case, if you simply have a list of 5 elements, just use std::array and a custom type:
struct food
{
string nameOfFood;
int eatCalories;
int number;
};
and then:
std::array<food, 5> food_list { ... };
But my list will never be empty, as i have five predefined elements. I will post the rest of the code, and maybe you will understand what i mean? Or else, it's me who got it wrong.
#include <iostream>
#include <cmath>
using namespace std;
struct node
{
string nameOfFood;
int eatCalories;
int number;
node *next;
};
bool isEmpty(node *head);
char menu();
void insertAsFirstElement(node *&head, node *&last, string name, int eatCalories);
void insert(node *&head, node *&last, string name, int eatCalories);
void showList(node *current);
bool isEmpty(node *head)
{
if(head == NULL)
return true;
else
return false;
}
char menu()
{
char choice;
cout << "Menu\n";
cout << "1. Add food, beverage etc.\n";
cout << "2. Show the list of food(s), beverage(s) etc.\n";
cout << "3. Update your current weight\n";
cout << "4. What have you been eaten?\n";
cout << "5. What exercise have you done?\n";
cout << "6. Exit program \n";
cin >> choice;
return choice;
}
void insertAsFirstElement(node *&head, node *&last, string nameOfFood, int eatCalories)
{
node *temp = new node;
temp->nameOfFood = nameOfFood;
temp->eatCalories = eatCalories;
temp->next = NULL;
head = temp;
last = temp;
}
void insert(node *&head, node *&last, string nameOfFood, int eatCalories)
{
if(isEmpty(head))
insertAsFirstElement(head, last, nameOfFood, eatCalories);
else
{
node *temp = new node;
temp->nameOfFood = nameOfFood;
temp->eatCalories = eatCalories;
temp->next = NULL;
last->next = temp;
last = temp;
}
}
void showList(node *current)
{
if(isEmpty(current))
cout << "The list of foods is empty\n";
else
{
cout << "The list of foods contain: \n";
int number = 0;
while(current != NULL)
{
++number;
cout << number << " " << current->nameOfFood << " " << current->eatCalories << " calories" << endl;
current = current->next;
}
}
}
node* subtractCalories(node *head)
{
int choice;
showList(head);
cout << "Pick the food, beverage etc. from the list by number\n";
cin >> choice;
int number = 1;
node *current = head;
while (current != NULL && choice != number)
{
++number;
current = current->next;
}
cout << "You have choosen: " << current->nameOfFood << endl;
return current;
}
int main(int argc, const char * argv[]) {
double caloriesToBurn;
double weight;
double height;
double BMI;
int answerWhile = 1;
int answerToExercise = 0;
float minutesExerciseInHour;
float caloriesBurned;
node *head = NULL;
node *last = NULL;
node *current;
char choice;
int eatCalories;
string nameOfFood;
insert(head, last, "Tuna (in oil)", 190);
insert(head, last, "Milkchocolate (Marabou)", 540);
insert(head, last, "Milk (skimmed)", 33 );
insert(head, last, "Ice Tea (white peach)", 1);
insert(head, last, "Peanuts (roasted and salted)", 624);
cout << "*** Welcome to the calorie calculator! ***\n";
cout << "To get started, i need some numbers from you\n";
cout << "Please enter the number of calories you need to burn today:\n";
cin >> caloriesToBurn;
cout << "What are your current weight? (please enter in kilograms)\n";
cin >> weight;
cout << "And lastly i need to know your height (please enter in centimeters)\n";
cin >> height;
BMI = (weight / pow(height/100,2));
cout << "Your BMI is: " << BMI << endl;
if (BMI <= 18.5)
cout << "You are in the range: under weight" << endl;
else if ((BMI > 18.5) && (BMI < 25))
cout << "You are in the range: normal weight" << endl;
else
cout << "You are in the range: over weight" << endl;
do{
choice = menu();
switch(choice)
{
case '1':
cout << "Enter the name of the food, beverage etc.:";
cin >> nameOfFood;
cout << "How many calories did it contain? (measured per 100 grams):";
cin >> eatCalories;
insert(head, last, nameOfFood, eatCalories);
break;
case '2': showList(head);
break;
case '3': cout << "What you wanna update your weight to?\n";
cin >> weight;
cout << "Your weight have been update to: \n";
cout << weight << endl;
if (BMI <= 18.5)
cout << "You are in the range: under weight" << endl;
else if ((BMI > 18.5) && (BMI < 25))
cout << "You are in the range: normal weight" << endl;
else
cout << "You are in the range: over weight" << endl;
break;
case '4':
cout << endl << "You need to consume " << caloriesToBurn << " calories today!" << endl << endl;
current = subtractCalories(head);
caloriesToBurn = caloriesToBurn-current->eatCalories;
cout << endl << "You need to eat " << caloriesToBurn << " calories more today!" << endl;
break;
case '5':
do
{
cout << "How many minuttes have you ben exercising (please enter in hours)\n";
cin >> minutesExerciseInHour;
cout << "What type of exercise have you been doing?" <<endl;
cout << "1. Running" <<endl;
cout << "2. Swimming" <<endl;
cout << "3. Cycling" <<endl;
cin >> answerToExercise;
switch(answerToExercise)
{
case 1:
caloriesBurned = weight*7.5*minutesExerciseInHour;
cout << "You have burned: " << caloriesBurned << "calories\n";
caloriesToBurn = caloriesToBurn + caloriesBurned;
cout << "You have: " << caloriesToBurn << " left today\n";
break;
case 2:
caloriesBurned = weight*7*minutesExerciseInHour;
cout << "You have burned: " << caloriesBurned << "calories\n";
caloriesToBurn = caloriesToBurn + caloriesBurned;
cout << "You have: " << caloriesToBurn << " left today\n";
break;
case 3:
caloriesBurned = weight*6*minutesExerciseInHour;
cout << "You have burned: " << caloriesBurned << "calories\n";
caloriesToBurn = caloriesToBurn + caloriesBurned;
cout << "You have: " << caloriesToBurn << " left today\n";
break;
default: cout << "I think something went wrong? Try again..";
}
}
while (answerWhile != 1);
default: cout << "System exit\n";
}
}while(choice != '6');
return 0;
}
I think i understand with the check for empty list - therefore i will take my code to another question.
I got the InsertAsFirstElement function, but at the moment, i think i forgot what the function does, because nowhere in the code, there will be "insert by first element", so can someone tell what that function does?
Sorry for the inconvenience!
Related
So in my current program I am tasked to store a vector of branches. These branches contain a string name, and a pointer to a node.
These nodes store a book, which has an author name, a title, and the number of copies.
Overall, this should create the data structure of a linked list.
Currently I am attempting to write a program to print all the books within a branch.
After adding these books to the branch Alex.
Stan Moon
Bill Sun
Chris Ground
I attempt to print them all out using the printall() function. However, I simply get blank output. Is there something I am missing?
Thanks in advance!
#include "Library.h"
#include <vector>
#include <string>
#include <iostream>
using namespace std;
int total;
int index;
Library::Library()
{
}
struct Node //Has everything in it
{
string author;
string title;
int copies;
Node* next;
};
struct Branch // Stores just the branch, and a point to the node with information in it.
{
string b_name;
Node* next;
};
vector<Branch> lib;
void Library::start()
{
int choice;
cout << "Please select a choice." << endl;
cout << " " << endl;
cout << "1. Create a branch and insert its books" << endl;
cout << "2. Given an author name, a title and a branch name, CHECKOUT that book from the branch." << endl;
cout << "3. Given an author name, title and a branch name, RETURN that book to the branch." << endl;
cout << "4. Given an author name, title and branch name, FIND the number of copies of that book are available in that branch." << endl;
cout << "5. PRINT all books contained in a branch." << endl;
cout << "6. Exit the program." << endl;
cin >> choice;
if (choice == 1)
{
insert();
}
if (choice == 5)
{
printAll();
}
}
void Library::insert()
{
string br;
string auth;
string titl;
cout << "What is the name of the branch?" << endl;
cin >> br;
Branch *branch = new Branch();
branch->b_name = br;
lib.push_back(*branch);
if (total == 0)
{
cout << "What is the author and title of the book?" << endl;
cin >> auth >> titl;
Node *book = new Node();
book->author = auth;
book->title = titl;
book->copies++;
book->next = NULL;
branch->next = book;
total++;
}
do
{
cout << "What is the author and title of the book?" << endl;
cin >> auth >> titl;
Node *book = new Node();
book->author = auth;
book->title = titl;
book->copies++;
book->next = branch->next;
branch->next = book;
total++;
} while (auth != "NONE" && titl != "NONE");
start();
}
void Library::checkout()
{
string auth;
string titl;
string bran;
}
void Library::Return()
{
//TODO
}
void Library::find()
{
//TODO
}
void Library::printAll()
{
for (unsigned int i = 0; i < lib.size(); i++)
{
while (lib.at(i).next != NULL)
{
cout << "There are " << lib.at(i).next->copies << "of " << lib.at(i).next->title << "by " << lib.at(i).next->author << "in branch " << lib.at(i).b_name << endl;
lib.at(i).next = lib.at(i).next->next;
}
}
start();
}
I found some problems of your source code:
You should hold pointer in the lib vector, or it will be cloned when push_back
The insert function was wrongly implemented
You should use loop instead of recusive call, it maybe cause stack overflow
Check the modified version:
#include "Library.h"
#include <vector>
#include <string>
#include <iostream>
using namespace std;
int total;
int index;
Library::Library()
{
}
struct Node //Has everything in it
{
string author;
string title;
int copies;
Node* next;
};
struct Branch // Stores just the branch, and a point to the node with information in it.
{
string b_name;
Node* next;
};
vector<Branch*> lib;
void Library::start()
{
int choice = 0;
do
{
cout << "Please select a choice." << endl;
cout << " " << endl;
cout << "1. Create a branch and insert its books" << endl;
cout << "2. Given an author name, a title and a branch name, CHECKOUT that book from the branch." << endl;
cout << "3. Given an author name, title and a branch name, RETURN that book to the branch." << endl;
cout << "4. Given an author name, title and branch name, FIND the number of copies of that book are available in that branch." << endl;
cout << "5. PRINT all books contained in a branch." << endl;
cout << "6. Exit the program." << endl;
cin >> choice;
switch (choice)
{
case 1:
insert();
break;
case 5:
printAll();
break;
// TODO: other choises
}
} while (choice != 6);
}
void Library::insert()
{
string br;
string auth;
string titl;
cout << "What is the name of the branch?" << endl;
cin >> br;
Branch *branch = new Branch();
branch->b_name = br;
lib.push_back(branch);
Node* lastNode = nullptr;
do
{
cout << "What is the author and title of the book?" << endl;
cin >> auth >> titl;
Node *book = new Node();
book->author = auth;
book->title = titl;
book->copies++;
if (lastNode == nullptr) {
branch->next = book;
}
else {
lastNode->next = book;
}
lastNode = book;
} while (auth != "NONE" && titl != "NONE");
}
void Library::checkout()
{
string auth;
string titl;
string bran;
}
void Library::Return()
{
//TODO
}
void Library::find()
{
//TODO
}
void Library::printAll()
{
for (unsigned int i = 0; i < lib.size(); i++)
{
auto* branch = lib[i];
auto* node = branch->next;
while (node)
{
cout << "There are " <<
node->copies << " of " <<
node->title << " by " <<
node->author << " in branch " <<
branch->b_name << endl;
node = node->next;
}
}
}
I'm having some difficulties with writing adding and removing function.
Here's some code for displaying the list, searching and removing the list.
I know how to implement it iteratively, but with recursion, I have some problems.
#include <iostream>
#include <string>
using namespace std;
struct AddressBook
{
string name;
string surname;
long long phone;
AddressBook* next;
};
void delPerson(AddressBook*& head)
{
if (head == NULL)
{
cout << "There are no persons in my book\n";
}
else
{
string pName;
cout << "Enter name of person: ";
getline(cin, pName);
AddressBook* temp = head;
AddressBook* curr = NULL;
while (temp != NULL)
{
if (temp->name == pName)
{
break;
}
else
{
curr = temp;
temp = temp->next;
}
}
if (temp == NULL)
{
cout << "There are no person with this name\n";
}
else
{
if (temp == head)
{
head = head->next;
delete temp;
}
else
{
curr->next = temp->next;
delete temp;
}
cout << pName << " was deleted from the book\n";
}
}
}
void display(AddressBook* head)
{
if (head == NULL)
{
cout << "My book is empty\n";
}
else
{
AddressBook* temp = head;
while (temp != NULL)
{
cout << endl;
cout << "Name: " << temp->name << endl;
cout << "Surname: " << temp->surname << endl;
cout << "Phone: " << temp->phone << endl;
temp = temp->next;
}
}
}
void search(AddressBook* head)
{
if (head == NULL)
{
cout << "My book is empty\n";
}
else
{
cin.get();
string pName;
cout << "Enter name of person: ";
getline(cin, pName);
AddressBook* temp = head;
while (temp != NULL)
{
if (temp->name == pName)
{
cout << temp->name << " is found\n\n";
cout << "Name: " << temp->name << endl;
cout << "Surname: " << temp->surname << endl;
cout << "Phone: " << temp->phone << endl;
break;
}
else
{
temp = temp->next;
}
}
if (temp == NULL)
{
cout << pName << " isn't found in my book\n";
}
}
}
void delMemory(AddressBook* head)
{
while (head != NULL)
{
AddressBook* temp = head;
head = head->next;
delete temp;
}
}
void addPerson(AddressBook*& head)
{
string pName;
string sName;
long long pPhone = 0;
while (true)
{
cin.ignore();
cout << endl;
cout << "Enter the name(press '0' to end): ";
getline(cin, pName);
if (pName == "0")break;
cout << "Enter surname: ";
getline(cin, sName);
cout << "Enter phone: ";
cin >> pPhone;
AddressBook* bleah = new AddressBook;
bleah->name = pName;
bleah->surname = sName;
bleah->phone = pPhone;
bleah->next = NULL;
if (head == NULL)
{
head = bleah;
}
else
{
AddressBook* temp = head;
while (temp->next != NULL)
{
temp = temp->next;
}
temp->next = bleah;
}
}
}
int main()
{
cout << "=============== My Address Book ===============\n\n";
cout << "1. To add person\n";
cout << "2. To display all\n";
cout << "3. To delete person\n";
cout << "4. To search person\n";
cout << "5. Exit\n";
AddressBook* head = NULL;
int choice = 0;
while (true)
{
cin >> choice;
switch (choice)
{
case 1: addPerson(head);
break;
case 2: display(head);
break;
case 3: cin.get();
delPerson(head);
break;
case 4: search(head);
break;
case 5: return 0;
default: return 0;
}
cout << "=============== My Address Book ===============\n\n";
cout << "1. To add person\n";
cout << "2. To display all\n";
cout << "3. To delete person\n";
cout << "4. To search person\n";
cout << "5. Exit\n";
cout << endl;
}
delMemory(head);
return 0;
}
And this is recursive solution, but I have troubles implementing add and removing functions
#include <iostream>
#include <string>
using namespace std;
struct AddressBook
{
string name;
string surname;
long long phone;
AddressBook* next;
};
AddressBook* delPerson(AddressBook*& head)
{
}
AddressBook* display(AddressBook* head)
{
if (head!= NULL)
{
cout << endl;
cout << "Name: " << head->name << endl;
cout << "Surname: " << head->surname << endl;
cout << "Phone: " << head->phone << endl;
return display(head->next);
}
return head;
}
AddressBook* search(AddressBook* head, string pName)
{
if (head == NULL)
{
cout << pName << " isn't found in my book\n";
return head;
}
if (head->name == pName)
{
cout << head->name << " is found\n\n";
cout << "Name: " << head->name << endl;
cout << "Surname: " << head->surname << endl;
cout << "Phone: " << head->phone << endl;
return head;
}
else
{
return search(head->next, pName);
}
}
void delMemory(AddressBook* head)
{
if (head != NULL)
{
delMemory(head->next);
}
delete head;
}
AddressBook* allMem(AddressBook*& head)
{
}
int main()
{
cout << "=============== My Address Book ===============\n\n";
cout << "1. To add person\n";
cout << "2. To display all\n";
cout << "3. To delete person\n";
cout << "4. To search person\n";
cout << "5. Exit\n";
AddressBook* head = NULL;
string pName;
int choice = 0;
while (true)
{
cin >> choice;
switch (choice)
{
case 1: allMem(head);
break;
case 2: display(head);
break;
case 3: cin.get();
delPerson(head);
break;
case 4: cin.get();
cout << "Enter name of person: ";
getline(cin, pName);
search(head, pName);
break;
case 5: return 0;
default: return 0;
}
cout << "=============== My Address Book ===============\n\n";
cout << "1. To add person\n";
cout << "2. To display all\n";
cout << "3. To delete person\n";
cout << "4. To search person\n";
cout << "5. Exit\n";
cout << endl;
}
delMemory(head);
return 0;
}
What's already posted misses a huge portion of the problem: Asking for user input in a recursive function just leads to pain. Either the user input is asked for in every iteration or additional control information needs to be passed to to tell the function to NOT ask for user input. Either is bad planning.
Instead insert another function or two. This is beneficial from a software engineering standpoint: A function should do the absolute minimum to do one job. Functions that do only one thing are very easy to comprehend, very easy to debug, and tend to be very short.
So we need a function to get an AddressBook from the user:
AddressBook*createAddressBook()
{
AddressBook* bleah = new AddressBook; // terrible name, by the way
// since we got the bleah first, we can directly assign to it. No need for
// extra temporary variables.
cout << "Enter the name: ";
getline(cin, bleah->name);
cout << "Enter surname: ";
getline(cin, bleah->surname);
cout << "Enter phone: ";
cin >> bleah->phone; // bad idea to store phone number as a number.
// For example a number can't record preceding zeros
bleah->next = NULL;
return bleah;
}
This is a simple stupid function that does nothing but make an AddressBook. To be honest, this should be an AddressBook constructor, but we can save that for a future question. Note also that there is none of the exit on 0 nonsense. This function makes an AddressBook. Period. If you don't want an AddressBook, you don't call this function. Let the menu handle exiting.
Next we need a function to find where the AddressBoook will be added. It looks like this is always the end of the list, so
AddressBook*& findEnd(AddressBook *& head)
{
if (head != NULL)
{
return findend(head->next); // keep looking for the end
}
return head; // return the end.
}
Again, a simple, stupid function that does nothing but find the last next in the list. Note you get a reference to a pointer to an AddressBook. This allows you to happily return a next that points to NULL and replace the NULL with the new AddressBook
Which brings us back to addPerson
AddressBook* addPerson(AddressBook*& head)
{
findEnd(head) = createAddressBook();
return head;
}
Simple, stupid function that calls two other simple, stupid functions and adds a person to the list.
Apply a similar process to delPerson.
Note: I haven't run any of this. Could be a typo or two in there.
Here's a really simple example of how you can use a add to a linked list using recursion. You can apply this technique to your example above.
struct node{
int i;
node* next;
};
void add(node* cur, int i){
if(cur->next == nullptr){
node* n = new node;
n->i = i;
cur->next = n;
}
else
add(cur->next, i);
}
You simply check to see if the next node is null. If it is, you've reached the end of your list and you can add your new node there. If not, call the function recursively, providing the current next node.
Try this:
typedef struct Nodetype {
int key;
struct Node * next;
} Node;
Node * newNode(int data){
Node *temp = (Node*)malloc(sizeof(Node));
temp->key = data;
temp->next = NULL;
return temp;
}
Node* add(Node * head, int val){
if(!head)
return newNode(val);
head->next = add(head->next, val);
return head;
}
Node * delete(Node *head, int val){
if(!head)
return NULL;
Node * temp;
if(head->key == val){
temp = head;
head = head->next;
free(temp);
}
else{
head->next = delete(head->next, val);
}
return head;
}
You can change your code as per your need. I have assumed everything as integer.
I've written my own implementation of linked list which stores numbers. It was quite simple. Now I have to change it to store information about students. Every student that is added to the list must contain:
index
name,
surname,
university,
field of study,
year of study,
age
The index is sth like key, if we want to find the student in the list, we type index to find it and display full info about student. The same thing with deleting specified student - we type index to delete it.
Can anyone give me an advice or an example how to change it to store informations about students? I thought about asking about every info in constructor - when the object is created, it would display a query about the item and the object would be added to the list. :
linkedList::linkedList(){
head = NULL;
cout << "Type index: ";
cin >> index;
cout << "Type name: ";
cin >> name;
.
.
.
}
But I don't know if it would work properly and if it is generally good idea. Any advice would be helpful. Thank you in advance!
Here is the code that stores numbers in list:
class node{
public:
node();
int data;
node *next;
};
node::node(){
}
class linkedList{
node * head;
public:
linkedList();
node * createNode(int);
void insertBegin();
void insertPos();
void insertLast();
void deletePos();
void display();
void deleteList();
~linkedList();
};
linkedList::linkedList(){
head = NULL;
}
node *linkedList::createNode(int value){
node *temp;
temp = new(node);
temp->data = value;
temp->next = NULL;
return temp;
}
void linkedList::insertBegin(){
int value;
cout << "------------------------" << endl;
cout << "Type value: ";
cin >> value;
node *temp, *p;
temp = createNode(value);
if (head == NULL){
head = temp;
head->next = NULL;
}
else{
p = head;
head = temp;
head->next = p;
}
cout << "Element added." << endl;
cout << "------------------------" << endl;
}
void linkedList::insertLast(){
int value;
cout << "------------------------" << endl;
cout << "Type a value:: ";
cin >> value;
node *temp, *s;
temp = createNode(value);
if (head == NULL){
head = temp;
head->next = NULL;
} else{
s = head;
while (s->next != NULL){
s = s->next;
}
temp->next = NULL;
s->next = temp;
}
cout << "Element added." << endl;
cout << "------------------------" << endl;
}
void linkedList::insertPos(){
int value, pos, counter = 0;
cout << "------------------------" << endl;
cout << "Type value: ";
cin >> value;
node *temp, *s, *ptr;
temp = createNode(value);
cout << "Type position: ";
cin >> pos;
cout << "------------------------" << endl;
int i;
s = head;
while (s != NULL){
s = s->next;
counter++;
}
if (pos == 1){
if (head == NULL){
head = temp;
head->next = NULL;
}
else{
ptr = head;
head = temp;
head->next = ptr;
}
}
else if (pos > 1 && pos <= counter){
s = head;
for (i = 1; i < pos; i++){
ptr = s;
s = s->next;
}
ptr->next = temp;
temp->next = s;
}
else{
cout << "------------------------" << endl;
cout << "There is no such position. Type a value from 1 to " << counter <<
endl;
cout << "------------------------" << endl;
}
cout << "Element added." << endl;
cout << "------------------------" << endl;
}
void linkedList::deletePos(){
int pos, i, counter = 0;
if (head == NULL){
cout << "------------------------" << endl;
cout << "List is empty" << endl;
cout << "------------------------" << endl;
return;
}
cout << "------------------------" << endl;
cout << "Type position: ";
cin >> pos;
cout << "------------------------" << endl;
node *s, *ptr;
s = head;
if (pos == 1){
head = s->next;
}
else{
while (s != NULL)
{
s = s->next;
counter++;
}
if (pos > 0 && pos <= counter){
s = head;
for (i = 1;i < pos;i++){
ptr = s;
s = s->next;
}
ptr->next = s->next;
}
else{
cout << "There is no such position. Type a value from 1 to " << counter <<
endl;
cout << "------------------------" << endl;
}
delete s;
cout << "Element added." << endl;
cout << "------------------------" << endl;
}
}
void linkedList::display(){
node *temp;
if (head == NULL){
cout << "------------------------" << endl;
cout << "List is empty" << endl;
cout << "------------------------" << endl;
return;
}
temp = head;
cout << "------------------------" << endl;
cout << "List elements:: " << endl;
while (temp != NULL){
cout << temp->data << "->";
temp = temp->next;
}
cout << "NULL" << endl;
cout << "------------------------" << endl;
}
void linkedList::deleteList (){
node *temp;
while (head != NULL){
temp = head;
head = head -> next;
delete temp;
}
cout << "------------------------" << endl;
cout << "List deleted." << endl;
cout << "------------------------" << endl;
}
linkedList::~linkedList(){
deleteList();
}
class menu{
public:
void displayMenu();
};
void menu::displayMenu(){
linkedList link;
int option;
do
{
cout << "1.Add element at the first pos" << endl;
cout << "2.Add element at the last pos" << endl;
cout << "3.Add element at the pos" << endl;
cout << "4.Delete specific pos" << endl;
cout << "5.Delete whole list" << endl;
cout << "6.Print list" << endl;
cout << "0.End " << endl;
cout << "Choose an option: ";
cin >> option;
switch(option){
case 1:
link.insertBegin();
break;
case 2:
link.insertLast();
break;
case 3:
link.insertPos();
break;
case 4:
link.deletePos();
break;
case 5:
link.deleteList();
break;
case 6:
link.display();
break;
}
} while (option != 0);
}
int main(){
menu k;
k.displayMenu();
return 0;
}
Use templates. C++ version of generic programming.
Define your linked list node with a template:
template<class T>
class node<T>{
public:
node<T>();
T data;
node<T> *next;
};
This means that you can now have a node of any kind of data type, just by accessing node's data attribute member.
Then define a new container class/struct to hold that other relevant information you were mentioning to include:
class data {
public:
/* ctor, dtor, accesor and modifier operations */
private:
unsigned int index, age;
std:string name, surname, university, fieldOfStudy, yearOfStudy;
};
You would need to redefine your linkedList class to also use templates:
template<class T>
class linkedList<T> {
/* ...declaration and implementation taking in to account <T> data type.
};
Then outside your scope, in main() for example, you can do the following:
int main() {
linkedList<data> list;
list.insertBegin();
list.insertLast();
// ... etc.
return 0;
}
You could also NOT use generic programming/templates and make your node have specific data you want
This will also impact your code less, because when adding templates you would probably have to add and change more lines of code.
What you can do is to simply change your node class adding all the attributes that we had added to the data class, like so:
class node {
public:
/* ctor, dtor, accesor and modifier operations */
private:
node();
node *next;
unsigned int index, age;
std:string name, surname, university, fieldOfStudy, yearOfStudy; // Now we have all the attributesyou needed and we omit the data attribute member.
};
You will need to make simple modifications to your linkedList methods, mainly only when you're instantiating node objects.
The problem with this solution is that it binds you to those attributes you chose above. The previous generic solution does not bind you to any data type and still all the linkedList functionality will work for any data type you decide to use (C++ int, double, float, std::string, custom classes).
For some odd reason when I attempt to display the range of my list it is giving extra output. The program asks for the user to enter the start and end node integers to display and then for some reason it will display a blank node and then the first node. After about 10 seconds it will then display the correct range of nodes.
for instance, i would input
ball, 4, 9.99
doll, 2, 10.00
lava lamp, 5, 24.99
but when putting say a range of 2 to 3 it would output
2. (blank), (blank), (blank)
3. ball, 4, 9.99
(pause for 10 seconds that is not called for)
2. doll, 2, 10.00
3. lava lamp, 5, 24.99
Does anyone know why this may be? (The function in question is void displayRange)
#include <iostream>
#define nullptr 0
#include <cstdlib>
#include <algorithm>
#include <string>
#include <conio.h>
using namespace std;
int menu();
class ItemList {
private:
struct ListNode{
string IName;
string QQuantity;
string PPrice;
double value;
struct ListNode * next;
};
ListNode *head;
public:
ItemList()
{
head = new ListNode;
head->next=nullptr;
}
~ItemList();
void insertNode(string Item, string Quantity, string Price)
{
ListNode *newNode;
ListNode *nodePtr;
ListNode *previousNode=nullptr;
newNode=new ListNode;
newNode->IName=Item;
newNode->QQuantity=Quantity;
newNode->PPrice=Price;
if(!head)
{
head=newNode;
newNode->next=nullptr;
}
else
{
nodePtr=head;
previousNode=nullptr;
while(nodePtr != nullptr && nodePtr->IName < Item)
{
previousNode=nodePtr;
nodePtr=nodePtr->next;
}
if(previousNode==nullptr)
{
head=newNode;
newNode->next=nodePtr;
}
else
{
previousNode->next=newNode;
newNode->next=nodePtr;
}
}
}
void displayNode()
{
ListNode *nodePtr;
nodePtr=head->next;
int i=0;
while(nodePtr)
{
i++;
cout << i << ". " << nodePtr->IName << ", ";
cout << nodePtr->QQuantity << " ";
cout << "$" << nodePtr->PPrice << "\n" << endl;
nodePtr=nodePtr->next;
}
if(!head)
{
cout << "The store is empty." << endl;
}
}
void modifyNode(string Item)
{
ListNode *nodePtr;
ListNode *nodePrev;
string newName, newQuantity, newPrice;
int modify;
if (!head)
{
return;
cout << "Store is empty." << endl;
}
else
{
nodePtr = head;
if (head->IName==Item)
nodePtr = head->next;
else
{
while (nodePtr != nullptr && nodePtr->IName != Item)
{
nodePrev = nodePtr;
nodePtr = nodePtr->next;
}
}
if (nodePtr)
{
cout << nodePtr->IName << "\t" << nodePtr->QQuantity << "\t" << nodePtr->PPrice << endl;
cout << "What would you like to change?\n";
cout << "1. Item" << endl;
cout << "2. Quantity" << endl;
cout << "3. Price" << endl;
cout << "4. Whole Entry" << endl;
cin >> modify;
switch (modify)
{
case 1:
cout << "Change to what?\n";
cin.sync();
getline(cin,newName);
transform(newName.begin(), newName.end(), newName.begin(), ::toupper);
nodePtr->IName = newName;
break;
case 2:
cout << "Change to what?\n";
cin >> newQuantity;
transform(newQuantity.begin(), newQuantity.end(), newQuantity.begin(), ::toupper);
nodePtr->QQuantity = newQuantity;
break;
case 3:
cout << "Change to what?\n";
cin >> newPrice;
transform(newPrice.begin(), newPrice.end(), newPrice.begin(), ::toupper);
nodePtr->PPrice = newPrice;
break;
case 4:
cout << "What is the product called?\n";
cin.sync();
getline(cin,newName);
transform(newName.begin(), newName.end(), newName.begin(), ::toupper);
nodePtr->IName = newName;
cout << "How many are there really?\n";
cin >> newQuantity;
transform(newQuantity.begin(), newQuantity.end(), newQuantity.begin(), ::toupper);
nodePtr->QQuantity = newQuantity;
cout << "What is the actual price?\n";
cin >> newPrice;
transform(newPrice.begin(), newPrice.end(), newPrice.begin(), ::toupper);
nodePtr->PPrice = newPrice;
}
}
else
cout << "Product not found\n";
}
}
void deleteNode(string Item)
{
ListNode *nodePtr;
ListNode *previousNode;
if(!head)
return;
if(head->IName==Item)
{
nodePtr=head->next;
delete head;
head=nodePtr;
}
else
{
nodePtr=head;
while(nodePtr!=nullptr && nodePtr->IName!=Item)
{
previousNode=nodePtr;
nodePtr=nodePtr->next;
}
if(nodePtr)
{
previousNode->next=nodePtr->next;
delete nodePtr;
}
else
{
cout << "Nothing to delete." << endl;
}
}
}
void deleteRangeNode(int start, int stop)
{
ListNode *nodePtr;
ListNode *newNode;
nodePtr = head;
int i=-1;
cin.sync();
while(nodePtr!=nullptr)
{
i++;
if((i>=start)&&(i<=stop))
{
newNode->next = nodePtr -> next;
cout << "Deleted Product: " << nodePtr->IName << endl;
delete nodePtr;
nodePtr=newNode;
}
newNode=nodePtr;
nodePtr=nodePtr->next;
}
}
void displayRange(int start, int stop)
{
ListNode * nodePtr;
nodePtr=head;
int i=-1;
bool found=false;
cin.sync();
while(nodePtr!=nullptr)
{
i++;
if((i>=start && i<=stop))
{
cout << i << ". " << nodePtr->IName << ", ";
cout << nodePtr->QQuantity << " ";
cout << "$" << nodePtr->PPrice << "\n" << endl;
nodePtr=nodePtr->next;
}
}
}
};
ItemList::~ItemList()
{
ListNode *nodePtr;
ListNode *nextNode;
nodePtr=head;
while(nodePtr!=nullptr)
{
nextNode=nodePtr->next;
delete nodePtr;
nodePtr=nextNode;
}
}
int main()
{
ItemList pro;
int method;
while(method!=0)
{
int method=menu();
system("cls");
string It, Q, P;
int begin, end;
switch(method)
{
case 1:
int count;
cout << "How many products would you like to put in?" << endl;
cin >> count;
system("cls");
for(int i=0; i<count; i++)
{
cout << "Product #" << i + 1 << endl;
cout << "Enter the item name: ";
cin.sync();
getline(cin,It);
transform(It.begin(), It.end(), It.begin(), ::toupper);
cout << "Enter the Quantity: ";
cin >> Q;
transform(Q.begin(), Q.end(), Q.begin(), ::toupper);
cout << "Enter the Price: ";
cin >> P;
pro.insertNode(It, Q, P);
cout << "\n";
}
break;
case 2:
int dis;
cout << "How many products would you like to display?" << endl;
cout << "1. Entire Store" << endl;
cout << "2. Range of Products" << endl;
cin >> dis;
system("cls");
switch(dis)
{
case 1:
pro.displayNode();
break;
case 2:
cout << "The display should START at: ";
cin >> begin;
cout << "The display should END at: ";
cin >> end;
pro.displayRange(begin,end);
system("pause");
break;
}
break;
case 3:
pro.displayNode();
cout << "What product do you wish to modify? (by item name)" << endl;
cin.sync();
getline(cin, It);
transform(It.begin(), It.end(), It.begin(), ::toupper);
system("cls");
pro.modifyNode(It);
break;
case 4:
int del;
cout << "Do you wish to delete one product or more?" << endl;
cout << "1. One" << endl;
cout << "2. Range of Products" << endl;
cout << "3. Entire Store" << endl;
cin >> del;
system("cls");
switch(del)
{
case 1:
cout << "What product do you wish to delete? (by item name)" << endl;
pro.displayNode();
cout << "\n";
cin.sync();
getline(cin,It);
transform(It.begin(), It.end(), It.begin(), ::toupper);
pro.deleteNode(It);
cout << "\n";
break;
case 2:
pro.displayNode();
cout << "What range of items do you wish to delete?" << endl;
cout << "START: ";
cin >> begin;
cout << "STOP: ";
cin >> end;
pro.deleteRangeNode(begin, end);
break;
case 3:
pro.~ItemList();
cout << "All items deleted." << endl;
break;
}
break;
case 0:
cout << "Exiting the program." << endl;
return 0;
}
system("pause");
system("cls");
}
return 0;
}
int menu()
{
string space1= " ";
string space2= " ";
int method;
cout << space1 << "What would you like to do to the store?" << endl;
cout << space2 << "1. Add Product" << endl;
cout << space2 << "2. Display" << endl;
cout << space2 << "3. Modify Product" << endl;
cout << space2 << "4. Delete Product" << endl;
cout << space2 << "0. Exit\n" << endl;
cout << space2;
cin >> method;
return(method);
}
The root of your problem is that you are creating a sentinel node in the list, but then not ignoring it in displayRange. You are ignoring it when you call displayNode. The reason you are seeing the delay is because the loop in displayNode relies on signed integer overflow (which is undefined behavior) to terminate. Moving the increment of nodePtr outside of the range check will fix this.
There are several problems with this code. There are many reasons not to implement your own list container, but the most important one is because it's hard to get exactly correct the first time unless you are experienced with the language. I strongly encourage you to look into std::vector. Here is a list of items I found.
#define nullptr 0 DO NOT DO THIS. The standard does not guarantee that this is well defined behavior, and the two do not have the same type.
Calling cin.sync() isn't guaranteed to do anything (it's implementation defined).
You need to clear the whitespace from the input stream before you try to call std::getline on it. This is covered in the reference page under "Notes."
When inserting a new node, you need to set newNode->next to null.
Turn on your compiler's warnings. You have a several usages of uninitialized variables which can lead to undefined behavior.
Cause of blank node Problem: insertion started at next-node of head in insertNode method. But, display started from head in displayRange method.
Solution: Resolve this mismatch !!! You can resolve this problem by changing ItemList as followings:
ItemList()
{
head = nullptr; //changed here
}
Cause of wrong range and late display Problems: display pointer (nodePtr) is not updated accordingly.
Solution: Resolve this mismatch !!! You can resolve this problem by changing displayRange as followings:
void displayRange(int start, int stop)
{
ListNode * nodePtr;
nodePtr = head;
int i = 0; //changed here
bool found = false;
cin.sync();
while (nodePtr != nullptr)
{
i++;
if ((i >= start && i <= stop))
{
cout << i << ". " << nodePtr->IName << ", ";
cout << nodePtr->QQuantity << " ";
cout << "$" << nodePtr->PPrice << "\n" << endl;
//nodePtr = nodePtr->next; //changed here
}
nodePtr = nodePtr->next; //changed here
}
}
I just pointed out the mention problems area, though it has some other bugs.
Thanks !!!
I'm not getting any errors, but I am not able to append songs to the doubly linked list.`I do not currently have any delete operators because I plan on adding them near the end of creating the program.
#include <iostream>
#include <string>
#include <cstdlib>
#include <cstring>
using namespace std;
struct Song
{
int id;
string name;
string singerName;
};
struct Node
{
Song sg;
Node* next;
Node* prev;
};
struct FirstSong
{
Node* first;
};
Node *getLastSong(FirstSong *head);
void addSong(FirstSong *head, Node *tail);
Node *removeSong(FirstSong *head, int index);
void displayListElements(FirstSong *head);
void clearList(FirstSong *head);
int main()
{
Node* tail;
FirstSong* head;
int choice;
int ID;
string name;
string singer;
//Creating the first node
head = new FirstSong;
head->first = new Node;
cout << "What is your song's number" << endl;
cin >> ID;
head->first->sg.id = ID;
cout << "What is the name of your song?" << endl;
cin.ignore();
getline(cin, name);
head->first->sg.name = name.c_str();
cout << "What is the name of your singer?" << endl;
getline(cin, singer);
head->first->sg.singerName = singer.c_str();
head->first->prev = NULL;
tail = head->first;
//Prompting user for what they want to do
cout << "What would you like to do now?" << endl;
labelA:
cout << "1 - add song" << endl;
cout << "2 - remove song" << endl;
cout << "3 - show last song" << endl;
cout << "4 - display all songs" << endl;
cout << "5 - clear songs" << endl;
cout << "6 - quit" << endl;
cin >> choice;
//Switch statement will be right here
return 0;
}
Node *getLastSong(FirstSong *head)
{
}
void addSong(FirstSong *head, Node *tail)
{
Node* n;
char choice;
int ID;
string name;
string singer;
myLabelB:
if(tail->next == NULL){
cout << "NULL" << endl;
}
else{
cout << "Not NULL" << endl;
}
n = new Node;
cout << "What is your song's number" << endl;
cin >> ID;
n->sg.id = ID;
cout << "What is the name of your song?" << endl;
cin.ignore();
getline(cin, name);
n->sg.name = name.c_str();
cout << endl;
cout << "What is the name of your singer?" << endl;
getline(cin, singer);
n->sg.singerName = singer.c_str();
n->prev = tail;
tail->next = n;
tail = n;
cout << "Add another song?" << endl;
cin >> choice;
if(choice == 'Y' || choice == 'y')
{
goto myLabelB;
}
else
{
tail->next = NULL;
}
}
Node *removeSong(FirstSong *head, int index)
{
}
void displayListElements(FirstSong *head)
{
Node* temp = head->first;
while(temp != NULL){
cout << temp->sg.id << " ";
cout << temp->sg.name << " ";
cout << temp->sg.singerName << " " << endl;
temp = temp->next;
cout << endl;
}
}
What can I do to append the new songs without deleting the old ones? My guess is that I am somehow setting the newest Node = NULL, but I can't find where.