Linked List Not Working Properly - c++

Here is my code
struct Node{
char* isbn;
char* author;
char* title;
char* copyright;
char* genre;
bool status;
Node* next;
};
struct LinkedList {
Node* head; // This is the starting pointer of Linked List
LinkedList(){
head = NULL;
}
void insertAtHead(char* a, char* b, char* c, char* d, char* e, bool f){
Node* temp = new Node;
temp->isbn = a;
// etc. assigning information
temp->next = head;
head = temp;
}
void display(){
int i = 1;
Node* it = head;
while (it != NULL){
// display book info
it = it->next;
i++;
}
cout << "\n";
}
};
int main(){
LinkedList LL;
int x;
char a1[10] = "";
char a2[25] = "";
char a3[25] = "";
char a4[15] = "";
char a5[15] = "";
bool a6 = 0;
do{
cout << "\n======================================\n";
cout << "1) Insert Book At Head.\n";
cout << "2) Display All Books.\n";
cout << "3) Exit.\n";
cout << "======================================\n";
cin >> x;
switch(x){
case 1:{
cout << "Enter ISBN: "; cin >> a1;
cout << "Enter The Author's Name: "; cin >> a2;
cout << "Enter The Book Title: "; cin >> a3;
cout << "Enter The CopyRights: "; cin >> a4;
cout << "Enter The Book Genre: "; cin >> a5;
cout << "Enter The Status Of Book: "; cin >> a6;
LL.insertAtHead(a1,a2,a3,a4,a5,a6);
break;
}
case 2:
LL.display();
break;
case 3:
break;
}
}while(x!=3);
return 0;
}
The Problem is That When i insert a book using case 1 of switch it inserts a book in
the linked list with the given data but when i enter a new book the previously saved book
is overwritten by new book

It's not the linked list which is not working. It's the way you assign the values. You givie it adress of your input buffers (which are overwritten at each reading) and you store this adress in your node.
You have to make a copy of your buffers (using the old C-way strdup()).
I'd suggest a better approach: consider the use of C++ strings.
It's suffichent to #include <string> and update your struct into:
struct Node{
string isbn;
string author;
string title;
string copyright;
string genre;
bool status;
Node* next;
};
As strings understand correctly the assignment from char*, it wll generate its own copy, not realying anymore on your buffers. It'll be better though to consider replacing char* with strings in all your code.

Related

I'm stuck on how to make a sorting algorithm in a doubly linked list using a person's first name and last name in C++

So I made a doubly linked list which stores a person's first name, last name, address and age and I am currently stuck on making a sorting algorithm for the list. So far I've managed to create 3 functions, one that adds a node to the list, one that deletes a node from the list and one which prints the list.
Here's what I have so far, the struct:
struct Node {
string First_Name;
string Last_Name;
string Address;
int age;
Node* next;
Node* prev;
} *first = 0, * last = 0;
The addToList function:
void addToList()
{
string temp = "Yes";
string First_Name;
string Last_Name;
string Address;
int age;
Node* current = first;
while (temp == "Yes") {
cout << "Enter the persons first name: ";
cin >> First_Name;
cout << "Enter the persons last name: ";
cin >> Last_Name;
cout << "Enter the persons age: ";
cin >> age;
cout << "Enter the persons address: ";
cin >> Address;
cout << "Would you like to add another person? Yes or No";
cin >> temp;
current = new Node;
current->First_Name = First_Name;
current->Last_Name = Last_Name;
current->age = age;
current->Address = Address;
if (last) last->next = current;
else first = current;
current->prev = last;
current->next = 0;
last = current;
}
return;
}
And the print list:
void printList()
{
if (!first)
{
cout << "Nothing is present in the list." << endl;
return;
}
Node* current = first;
while (current)
{
cout << current->First_Name << " " << current->Last_Name << " " << current->age << " " << current->Address << endl;
current = current->next;
}
}
My question is, how would I be able to sort the list alphabetically, I've never done sorting before...
Thank you!!
To use custom sorting for a doubly-linked list, overload operator<:
struct Person
{
std::string first;
std::string last;
std::string address;
unsigned int age;
bool operator<(const Person& p) const
{
bool is_less_than = false;
if (last == p.last)
{
is_less_than = first < p.first;
}
else
{
is_less_than = last < p.last;
}
return is_less_than;
}
};
Now you can use std::list and it will automatically sort by last name, then first. And std::list is a doubly-linked list.
To compare Persons:
Person a;
Person b;
//...
if (a < b)
{
std::cout << "Person A < Person B\n";
}

Not too sure how to move on from here. Using linked list to search?

Question: Create a Linked list of nodes. Each node should have student names, age, course num, grades and pointer that is used to link the next node in the list. Use append node member function to generate a linked list of 5 students. Create a search member function to display the name of the student who has got 'A' grade. Assume that only one student got "A" grade.
Not too sure how to move on from here. I am new to linked list/nodes and not too sure what I am doing wrong. Any help would be greatly appreciated.
#include <iostream>
#include <cstring>
using namespace std;
struct node
{
string name;
int age;
int coursenum;
char grade;
node *next;
};
node *search (node * head)
{
node *temp = head;
char grade;
while (temp != NULL)
{
//if (temp->grade == 'A')
//if((temp->grade, grade)=='A')
if(strcmp(temp->grade, grade)=='A')
{
cout << temp->name;
return temp;
}
temp = temp->next;
}
}
int main ()
{
node *head = NULL;
string name;
int age;
int coursenum;
char grade;
int i = 0;
while (i < 2)
{
cout << "Enter the students name: ";
cin >> name;
cout << "Enter the studens age: ";
cin >> age;
cout << "Enter the students course number: ";
cin >> coursenum;
cout << "Enter the students grade: ";
cin >> grade;
node *temp = new node;
temp->grade = grade;
temp->next = head;
head = temp;
i++;
}
search (head);
}
strcmp(string1,string2) // returns 0 if strings are equal.
String str1 = 'apple';
String str2 = 'apple';
if(strcmp(str1,str2))
{
cout<<"inside if";
}
else{
cout<<"inside else"
}
// output will be "inside else"
because if condition will evaluate to '0'
Your if statement in search function must be;
if (temp->grade == 'A')
However, your problem is not in your understanding of linked list. You cannot write values to name, age, and coursenum correctly. You need to assign all your read values to struct's variables.
temp->name = name;
temp->age = age;
temp->coursenum = coursenum;
temp->grade = grade;

Doubly linked list c++ crashing after 3rd node

So this is a doubly linked list that is supposed to hold names, address, and phone numbe and print them out. It works for the first 3 nodes then suddenly crashes after the the phone number entry on the third node. something is wrong with the pointers I believe but I have tried everything I can think of.
#include <iostream>
using namespace std;
class node
{
private:
string elem;
node* next;
node* prev;
string firstName;
string lastName;
string address;
string phoneNumber;
friend class linkedList;
};
//Linked list
class linkedList
{
public:
linkedList();
void addFrontNode(const string& e);
void addNode(const string& e);
void addNode2(node* nextloc, const string& e);
void addNode3(node* nextloc, const string& e);
void addNode4(node* nextloc, const string& e);
void print();
void search();
node* nextloc;
private:
node* head;
node* tail;
};
void linkedList::addFrontNode(const string &e)
{
node* v = new node;
string firstNameEntry;
string lastNameEntry;
string addressEntry;
string phoneNumberEntry;
cout << "Enter first name: ";
cin >> firstNameEntry;
cout << "Enter last name: ";
cin >> lastNameEntry;
cout << "Enter the address ";
cin.ignore();
getline(cin, addressEntry);
cout << "Enter a phone number ";
cin >> phoneNumberEntry;
v->elem = firstNameEntry;
v->lastName = lastNameEntry;
v->address = addressEntry;
v->phoneNumber = phoneNumberEntry;
v->next = head;
head = v;
}
void linkedList::addNode(const string &e)
{
node* v = new node;
string firstNameEntry;
string lastNameEntry;
string addressEntry;
string phoneNumberEntry;
cout << "Enter first name: ";
cin >> firstNameEntry;
cout << "Enter last name: ";
cin >> lastNameEntry;
cout << "Enter the address ";
cin.ignore();
getline(cin, addressEntry);
cout << "Enter a phone number ";
cin >> phoneNumberEntry;
v->elem = firstNameEntry;
v->lastName = lastNameEntry;
v->address = addressEntry;
v->phoneNumber = phoneNumberEntry;
v->next = tail;
tail = v;
tail->next = NULL;
}
void linkedList::addNode2(node* nextloc, const string &e)
{
node* v = new node;
string firstNameEntry;
string lastNameEntry;
string addressEntry;
string phoneNumberEntry;
cout << "Enter first name: ";
cin >> firstNameEntry;
cout << "Enter last name: ";
cin >> lastNameEntry;
cout << "Enter the address ";
cin.ignore();
getline(cin, addressEntry);
cout << "Enter a phone number ";
cin >> phoneNumberEntry;
v->elem = firstNameEntry;
v->lastName = lastNameEntry;
v->address = addressEntry;
v->phoneNumber = phoneNumberEntry;
nextloc = head -> next;
v->next = nextloc;
v->next = nextloc;
v->prev = nextloc->prev;
nextloc->prev = v;
}
void linkedList::addNode3(node* nextloc, const string &e)
{
node* v = new node;
string firstNameEntry;
string lastNameEntry;
string addressEntry;
string phoneNumberEntry;
cout << "Enter first name: ";
cin >> firstNameEntry;
cout << " Enter last name: ";
cin >> lastNameEntry;
cout << " Enter the address ";
cin.ignore();
getline(cin, addressEntry);
cout << " Enter a phone number ";
cin >> phoneNumberEntry;
v->elem = firstNameEntry;
v->lastName = lastNameEntry;
v->address = addressEntry;
v->phoneNumber = phoneNumberEntry;
v->next = nextloc;
v->prev = nextloc->prev;
nextloc->prev = v;
}
void linkedList::addNode4(node* nextloc, const string &e)
{
node* v = new node;
string firstNameEntry;
string lastNameEntry;
string addressEntry;
string phoneNumberEntry;
cout << "Enter first name: ";
cin >> firstNameEntry;
cout << " Enter last name: ";
cin >> lastNameEntry;
cout << " Enter the address ";
cin.ignore();
getline(cin, addressEntry);
cout << " Enter a phone number ";
cin >> phoneNumberEntry;
v->elem = firstNameEntry;
v->lastName = lastNameEntry;
v->address = addressEntry;
v->phoneNumber = phoneNumberEntry;
v->next = nextloc;
v->prev = nextloc->prev;
nextloc->prev->next = v;
nextloc->prev = v;
}
linkedList::linkedList() :head(NULL) {}
void linkedList::print()
{
node* v = new node;
v = head;
while (v != NULL)
{
cout << v->elem << " ";
cout << v->lastName << " ";
cout << v->address << " ";
cout << v->phoneNumber;
v = v->next;
}
}
void linkedList::search()
{
node* v = new node;
v = tail;
string lastNameSearch;
cout << "Enter a last name to search ";
cin >> lastNameSearch;
while (v != NULL)
{
if (v->lastName == lastNameSearch)
{
cout << v->elem;
cout << v->address;
cout << v->phoneNumber;
}
v = v->prev;
}
}
int main()
{
string node1;
string node2;
string node3;
string node31;
string node4;
string node5;
linkedList list;
list.addFrontNode(node1);
list.addNode(node2);
list.addNode2(list.nextloc, node3);
list.addNode3(list.nextloc, node4);
list.addNode4(list.nextloc, node5);
list.print();
return 0;
}
There are several issues.
If you use addFrontNode() to add first node, you must set your tail.
Change this:
v->next = head;
head = v;
To this:
v->next = NULL;
head = v;
tail = v;
Your function addNode() doesn't add to list correctly, try calling print and you will see, no node is added by this function.
Change this:
v->next = tail;
tail = v;
tail->next = NULL;
To this:
tail->next = v;
v->next = NULL;
tail = v;
In main() just use addFrontNode() to add first and then use addNode() to add all others. After this your code worked as expected.
Didn't understand meaning of variable nextloc, might be the source of problems.
Overall recommendation: create one function to add node
The code is indeed in need of re-write, but I don't want to repeat recommendations from the first answer. I however, believe that the question was about the reasons of the crash. It's because while copy-pasting the code, you added 2 extra lines to your addNode2:
void linkedList::addNode2(node* nextloc, const string &e)
{
...
nextloc = head -> next;
v->next = nextloc;
...
}
Comment out at least first of them and it won't crash any more (but this wouldn't make it better, really).

Inserting structs in sorted linked list and writing it to binary file

I have one serious problem. I need to write a program in which I input person details like first name, last name and age to a struct, which also contains pointer to the next person and than I need to write that to binary file. It must be ascending sorted by last name and than by first name, like linked list, using pointers, but only one pointer pointing to next struct. After entering all data it needs to go through file and find the struct with the lowest value and than using pointers print all data in ascending order.
This is the code I wrote but it's not working. I need help.
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <cstring>
using namespace std;
struct person{
char firstName[20], lastName[20];
int age;
person *next;
};
void insert(char filename[], int n){
person *head = NULL;
ofstream people(filename, ios::binary | ios::trunc);
for(int i=0; i<n; i++){
system("cls");
person *per = new person;
cout << "firstName: ";
cin >> (*per).firstName;
cout << "lastName: ";
cin >> (*per).lastName;
cout << "age: ";
cin >> (*per).age;
if(head == NULL) {
(*per).next = head;
head = per;
}
else{
person *curr = head;
person *prev = NULL;
bool end = false ;
while(!end){
if(strcmp((*curr).lastName, (*per).lastName) ||
(!strcmp((*curr).lastName, (*per).lastName) &&
strcmp((*curr).firstName, (*per).firstName))){
end = true;
}
else {
prev = curr;
curr = (*curr).next;
}
}
if(curr==head){
(*per).next= head;
head = per;
}
else{
(*per).next = curr;
(*prev).next = per;
}
}
people.write((char *)&(*per), sizeof(*per));
}
people.close();
}
void print(char filename[]) {
person *head = NULL;
person *el;
person c,min;
ifstream people(filename, ios::binary);
people.read((char *)&c, sizeof(c));
min = c;
while(!people.eof()){
people.read((char *)&c, sizeof(c));
if(strcmp(c.lastName,min.lastName)== -1 ||
(!strcmp(c.lastName,min.lastName) &&
strcmp(c.firstName,min.firstName)==-1)){
min = c;
}
}
head = &min;
while (head != NULL) {
cout << (*head).firstName << " " <<(*head).lastName <<" "<<
(*head).age << endl;
el = head;
head = (*head).next;
delete el;
}people.close();
}
int main() {
int n, a;
char filename[40];
cout << "filename: " << endl;
cin.getline(filename, 40);
do{
do{ system("cls");
cout << "Choose one of the options: "<<endl;
cout << "1. insert "<<endl;
cout << "2. print "<<endl;
cout << "0. exit "<<endl;
cin >> a;
} while(a<1||a>2);
switch(a){
case 1: cout << "How many people would you like to enter? ";
cin >> n;
insert(filename, n);
break;
case 2:print(filename);
}
} while(a!=0);
return 0;
}
Looks like you are trying to create a sorted list but your condition for place to insert new node is wrong
strcmp((*curr).lastName, (*per).lastName) ||
(!strcmp((*curr).lastName, (*per).lastName) &&
strcmp((*curr).firstName, (*per).firstName)
It essentially tells - insert new person before curr as soon as it is different from curr.
You have to change it to be - insert new person as soon as it is bigger than (less than) curr - depending on the order of sorting.
So instead of checking strcmp != 0 check strcmp >0 or <0
Of course replacing c-strings with std::string will make it a lot easier and safer

cin a pointer reference to a struct

I am using cin and cout in my program. I starts off fine because it is not executing any of the functions, but after you type your name, it throws an exception in the iostream library. wondering if it is a problem with using cin through refrence.`
// linkedlists.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
struct person {
string name;
int age;
struct person* next;
};
person *head = NULL;
int length() {
int count = 0;
person *current = head;
while (current->next != NULL) {
current = current->next;
count++;
}
return count;
}
void printlist() {
person *current = head;
while (current->next != NULL){
cout << "Name: " << current->name << " Age: " << current->age << "\n";
current = current->next;
}
}
void insert() {
// int choice;
person *newNode = (struct person*)malloc(sizeof(person));
//cout << "Press 1 to insert at beginning of list.\n";
//cin >> choice;
// switch (choice) {
//case 1:
newNode->next = head;
head = newNode;
cout << "What is this person's name?\n";
cin >> newNode->name;
cout << "\nWhat is the age of " << newNode->name << "?";
cin >> newNode->age;
cout << "The current list of people is " << length() << " long.\n";
printlist();
}
void menu() {
int choice;
cout << "Welcome to the person recorder! ";
bool inloop = true;
while (inloop) {
cout << "Press 1 to add more entries. Press 2 to print the entire list. Press 3 to exit the program.\n";
cin >> choice;
switch (choice) {
case 1:
insert();
case 2:
printlist();
case 3:
inloop = false;
}
}
}
/*void change(person* human) {
string temp_name;
int temp_age;
cout << "What is this person's name?\n";
cin >> temp_name;
cout << "\nWhat is this person's age?\n";
cin >> temp_age;
human->name = temp_name;
human->age = temp_age;
}
*/
int main()
{
menu();
}
using visual studio 2015, am a noob to c/c++ and trying to make a linked list.
The problem is caused by your allocation of person:
person *newNode = (struct person*)malloc(sizeof(person));
This will allocate memory on the heap for an instance of person, but it will not call the constructor of person and any of it's members. This does not matter for age and next since they are primitive types, but name is an std::string, which has a constructor that needs to be called for it to function properly.
In C++ you create instances of objects using the keyword new.
person *newNode = new person;
This will create a new instance of person, and also call its constructor, which will initialize name properly.
Once you are done with the instance of person, you will have use the keyword delete to clean it up.
delete newNode;
Similar to the difference between malloc and new, delete will free the memory, but also call the destructor, which is used by name to clean up any resources it may have allocated to store the string.