Issue with functions in singly linked list - c++

UPDATED....New issue with addstudent function.
I made some changes based on feedback. I also made an update to the addstudent()function based on the assignment requirements and I am running into a strange issue.
The requirements for the addstudent function are that the parameters be a string id, string name, and string major. I added a line that allocates a new student node in this function, but it seems that only the ID is being kept. When I print the student information, the ID shows up, but the name and major are both blank. Where am I going wrong?
#include <iostream>
#include <string.h>
using namespace std;
class Student
{
public:
string ID;
string name;
string major;
public:
Student *next;
Student()
{
ID = "0";
name = "0";
major = "0";
next = NULL;
}
Student(string id, string name, string major)
{
ID = id;
name = name;
major = major;
next = NULL;
}
};
class Classroom
{
public:
Student* head;
Classroom()
{
head = NULL;
}
Classroom(Student* n)
{
head = n;
}
void addStudent(string id, string name, string major)
{
Student *n=new Student(id, name, major);
Student* current;
if (head == NULL)
{
n->next = head;
head = n;
}
else if(head->name > n->name)
{
n->next = head;
head = n;
}
else
{
current = head;
while (current->next!=NULL &&
current->next->name < n->name)
{
current = current->next;
}
n->next = current->next;
current->next = n;
}
}
void removeStudent(string id)
{
if (!head)
{
cout << "No students exist in this list.\n";
return;
}
Student **precurrent = &head,
*current = head;
while (current)
{
if (current->ID == id)
{
*precurrent = current->next;
cout<< "Student removed from list.\n";
return;
}
precurrent = &current->next;
current = current->next;
}
cout << "No student exists with this ID.\n";
}
void print()
{
if (!head) {
cout << "No students in list.\n";
return;
}
for (Student *temp = head; temp; temp = temp->next)
cout <<"\nStudent Information:\n Student ID: " << temp->ID
<< "\n Student Name: " << temp->name
<< "\n Student Major: " << temp->major << '\n';
}
void print(string id)
{
if (!head)
{
cout << "No students in list.\n";
return;
}
for (Student *temp = head; temp; temp = temp->next)
{
if (temp->ID == id)
{
cout <<"Student Information: \n"<< "Student ID: " << temp->ID <<'\n' << "Student Name: " << temp->name <<'\n' << "Student Major: " << temp->major << '\n';
return;
}
if(temp==NULL)
{
cout<<"Student ID does not exist.\n";
return;
}
}
}
bool isEmpty()
{
if (head == NULL)
return true;
else;
return false;
}
int getSize()
{
int count = 0;
if(head==NULL)
{
return count;
}
Student* temp = head;
while (temp != NULL)
{
temp = temp->next;
count++;
}
return count;
}
Student *at(int index)
{
Student *temp = head;
for (int i=1; i < index && temp; i++, temp = temp->next) {}
if (!temp)
cout << "Index not found.\n";
return temp;
}
};
int main()
{
Classroom cs;
int choice;
do
{
cout <<"\nPlease select an option below: (Enter 0 to exit)\n"
<< "1. Add student.\n"
<< "2. Remove student.\n"
<< "3. Print all student.\n"
<< "4. Print specific student.\n"
<< "5. Print student at index.\n"
<< "6. Print number of students.\n"
<< "7. Check if student list is empty.\n\n";
cin >> choice;
Student* s1 = new Student();
switch (choice)
{
case 0:
break;
case 1:
{
string id, name, major;
cout << "Enter Student ID:";
cin.ignore();
getline(cin, id);
cout << "Enter Student Name:";
getline(cin, name);
cout << "Enter Student Major:";
getline(cin, major);
cs.addStudent(id, name, major);
break;
}
case 2:
{
string id;
cout << "Enter Student ID of the Student to be removed: ";
cin >> id;
cs.removeStudent(id);
break;
}
case 3:
cs.print();
break;
case 4:
{
string id;
cout << "Enter ID of student to print: ";
cin >> id;
cs.print(id);
break;
}
case 5:
{
int index;
if(cs.isEmpty())
{
cout<< "No Students Exists.\n";
break;
}
cout << "Enter index to print: ";
cin >> index;
Student *s=cs.at(index);
if(s)
cs.print(s->ID);
break;
}
case 6:
cout << "There are "<< cs.getSize() << " students.\n";
break;
case 7:
if(cs.isEmpty())
cout<< "No Students Exists.\n";
else
cout << "The list is not empty.\n";
break;
default:
cout << "Enter valid option (0-7)\n";
}
} while (choice != 0);
return 0;
}

You have a large number of small errors that result in trouble throughout your code. With at() you are simply making it much harder than it needs to be. When you think about your at() function, there are simply two-conditions which must be true as you iterate over your list:
Your iteration counter must be less than the index, e.g. i < index (in C/C++ indexes are zero based on everything -- keep your code consistent) and
When you advance your list pointer, temp = temp->next, temp must not be NULL (or just temp for short).
You can put those together as:
Student *at(int index)
{
Student *temp = head;
int i = 0; /* C/C++ use zero based indexes */
for (; i < index && temp; i++, temp = temp->next) {}
if (!temp)
std::cerr << "error: index not found.\n";
return temp;
}
(where you have 2 loop-variables, temp and i and you use the comma operator to increment both in the for loop)
Similarly, you make your void removeStudent(std::string id) function much more complicated than it needs to be. When working with a list, you never keep track of a previous pointer, instead you use a pointer-to-pointer to hold the address of the current node (say Student **ppcurrent;) and you use a temporary pointer to point to the current node (say Student *pcurrent;).
When pcurrent->ID == id to remove, you simply set the pointer at the current address (as held by ppcurrent) to the next pointer in the list overwriting the Student to be removed with the ->next in the list. The beauty of this method is there are no special cases for head or any other node in the list, you simply replace the node at the current address with the next, e.g.
void removeStudent(std::string id)
{
if (!head) {
std::cout << "No students exist in this list.\n";
return;
}
Student **ppcurrent = &head,
*pcurrent = head;
while (pcurrent)
{
if (pcurrent->ID == id) {
*ppcurrent = pcurrent->next;
return;
}
ppcurrent = &pcurrent->next;
pcurrent = pcurrent->next;
}
std::cout << "No student exists with this ID.\n";
}
(See Linus on Understanding Pointers and see Why is “using namespace std;” considered bad practice?)
Your handling of std::cin and your use of std::cin.ignore() will miss cases where extraneous characters exist in stdin. You need to VALIDATE every use of std::cin to check for a stream error and then std::cin.clear() any stream error caused by a type mismatch or otherwise before you can use .ignore() and then you must empty all characters from stdin, not just one. Putting that together, you have a few issues to correct in main(), e.g.
do
{
std::cout <<"\nPlease select an option below: (Enter 0 to exit)\n"
" 1. Add student.\n"
" 2. Remove student.\n"
" 3. Print all student.\n"
" 4. Print specific student.\n"
" 5. Print student at index.\n"
" 6. Print number of students.\n"
" 7. Check if student list is empty.\n\n"
"choice: ";
if (!(std::cin >> choice)) {
std::cerr << "\nerror: invalid integer.\n";
std::cin.clear();
std::cin.ignore (std::numeric_limits<std::streamsize>::max(), '\n');
continue;
}
std::cin.ignore (std::numeric_limits<std::streamsize>::max(), '\n');
and then similarly with case: 5 of your switch() statement:
std::cout << "\nEnter index to print (zero based): ";
if (!(std::cin >> index)) {
std::cerr << "\nerror: invalid integer.\n";
std::cin.clear();
std::cin.ignore (std::numeric_limits<std::streamsize>::max(), '\n');
continue;
}
There were probably a lot more than needed correcting, but the bulk of the remaining problems were just awkwardness in the way things were coded (which is to be expected given that you are just learning C++, so nothing against the way to approached it -- that is normal and to be expected). For example, above, you only need one std::cout to output your entire menu, and you don't add a std::endl; after outputting a string-literal, just include the '\n' at the end of the literal, example:
std::cout << "hello world\n";
instead of
std::cout << "hello world" << std::endl;
It's not that the use of std::endl; is wrong, it's simply that it is not needed. The same applies to your nesting of if { } else { } within your various functions where you can simply return if you if condition is met making the else superfluous and leading to unnecessary levels of code indention. For example print() can simply be:
void print()
{
if (!head) {
std::cout << "No students in list.\n";
return;
}
for (Student *temp = head; temp; temp = temp->next)
std::cout <<"\nStudent Information:\n Student ID: " << temp->ID
<< "\n Student Name: " << temp->name
<< "\n Student Major: " << temp->major << '\n';
}
We will leave it to you to make the remaining comparisons of the changes to your code. The only other note is try and limit your variables to the scope they are needed. You only allocate a new Student if the user selects add from the menu. Otherwise you are just needlessly allocating for all other menu choices. While you may have done this to avoid the error if you tried to declare and allocate within your case 1: statement, you simply need to enclose the entire case in a block, e.g. { .... } and you are free to declare anything you need within that code block, e.g.
case 1: {
std::string id {}, name {}, major {};
std::cout << "\nEnter Student ID: ";
getline (std::cin, id);
std::cout << "Enter Student Name: ";
getline (std::cin, name);
std::cout << "Enter Student Major: ";
getline(std::cin, major);
Student *s1 = new Student(id, name, major);
cs.addStudent(s1);
break;
}
or
case 5: {
int index;
if (cs.isEmpty()) {
std::cout << "\nlist is empty.\n";
break;
}
std::cout << "\nEnter index to print (zero based): ";
if (!(std::cin >> index)) {
std::cerr << "\nerror: invalid integer.\n";
std::cin.clear();
std::cin.ignore (std::numeric_limits<std::streamsize>::max(), '\n');
continue;
}
Student *s = cs.at(index);
if (s)
cs.print (s->ID);
break;
}
(note: from my comment below your question, this is where you must validate the return from at() before calling print())
If you put all the pieces together, you would have:
#include <iostream>
#include <string>
#include <limits>
class Student
{
public:
std::string ID {}, name {}, major {};
Student *next;
Student()
{
ID = "0";
name = "0";
major = "0";
next = NULL;
}
Student(std::string ids, std::string names, std::string majors)
{
ID = ids;
name = names;
major = majors;
next = NULL;
}
};
class Classroom
{
public:
Student* head;
Classroom() { head = NULL; }
Classroom(Student* n) { head = n; }
void addStudent(Student *n)
{
Student* current;
if (head == NULL || head->name >= n->name) {
n->next = head;
head = n;
return;
}
current = head;
while (current->next && current->next->name < n->name)
current = current->next;
n->next = current->next;
current->next = n;
}
void removeStudent(std::string id)
{
if (!head) {
std::cout << "No students exist in this list.\n";
return;
}
Student **ppcurrent = &head,
*pcurrent = head;
while (pcurrent)
{
if (pcurrent->ID == id) {
*ppcurrent = pcurrent->next;
return;
}
ppcurrent = &pcurrent->next;
pcurrent = pcurrent->next;
}
std::cout << "No student exists with this ID.\n";
}
void print()
{
if (!head) {
std::cout << "No students in list.\n";
return;
}
for (Student *temp = head; temp; temp = temp->next)
std::cout <<"\nStudent Information:\n Student ID: " << temp->ID
<< "\n Student Name: " << temp->name
<< "\n Student Major: " << temp->major << '\n';
}
void print(std::string id)
{
if (!head) {
std::cout << "No students in list.\n";
return;
}
for (Student *temp = head; temp; temp = temp->next) {
if (temp->ID == id) {
std::cout <<"\nStudent Information:\n Student ID: " << temp->ID
<< "\n Student Name: " << temp->name
<< "\n Student Major: " << temp->major << '\n';
return;
}
}
std::cerr << "error: ID '" << id << "' not found.\n";
}
bool isEmpty()
{
if (head)
return false;
return true;
}
int getSize()
{
int count = 0;
Student* temp = head;
while (temp) {
temp = temp->next;
count++;
}
return count;
}
Student *at(int index)
{
Student *temp = head;
int i = 0; /* C/C++ use zero based indexes */
for (; i < index && temp; i++, temp = temp->next) {}
if (!temp)
std::cerr << "error: index not found.\n";
return temp;
}
};
int main()
{
Classroom cs;
int choice;
do
{
std::cout <<"\nPlease select an option below: (Enter 0 to exit)\n"
" 1. Add student.\n"
" 2. Remove student.\n"
" 3. Print all student.\n"
" 4. Print specific student.\n"
" 5. Print student at index.\n"
" 6. Print number of students.\n"
" 7. Check if student list is empty.\n\n"
"choice: ";
if (!(std::cin >> choice)) {
std::cerr << "\nerror: invalid integer.\n";
std::cin.clear();
std::cin.ignore (std::numeric_limits<std::streamsize>::max(), '\n');
continue;
}
std::cin.ignore (std::numeric_limits<std::streamsize>::max(), '\n');
switch (choice)
{
case 0:
break;
case 1: {
std::string id {}, name {}, major {};
std::cout << "\nEnter Student ID: ";
getline (std::cin, id);
std::cout << "Enter Student Name: ";
getline (std::cin, name);
std::cout << "Enter Student Major: ";
getline(std::cin, major);
Student *s1 = new Student(id, name, major);
cs.addStudent(s1);
break;
}
case 2: {
std::string id {};
std::cout << "\nEnter Student ID of the Student to be removed: ";
getline (std::cin, id);
cs.removeStudent(id);
break;
}
case 3:
cs.print();
break;
case 4: {
std::string id;
std::cout << "\nEnter ID of student to print: ";
getline (std::cin, id);
cs.print(id);
break;
}
case 5: {
int index;
if (cs.isEmpty()) {
std::cout << "\nlist is empty.\n";
break;
}
std::cout << "\nEnter index to print (zero based): ";
if (!(std::cin >> index)) {
std::cerr << "\nerror: invalid integer.\n";
std::cin.clear();
std::cin.ignore (std::numeric_limits<std::streamsize>::max(), '\n');
continue;
}
Student *s = cs.at(index);
if (s)
cs.print (s->ID);
break;
}
case 6:
std::cout << "\nThere are "<< cs.getSize() << " students.\n";
break;
case 7:
if (cs.isEmpty())
std::cout<< "\nNo Students Exists.\n";
else
std::cout << "\nThe list is not empty.\n";
break;
default:
std::cout << "\nEnter valid option (0-7)\n";
}
} while (choice);
return 0;
}
Take time to understand the changes made and if you have further questions, just drop a comment below.

After going through your code, there are some flaws which need to be addressed.
void addStudent(Student *n)
{
Student* current;
if (head == NULL || head->name >= n->name)
{
n->next = head;
head = n;
}
else
{
current = head;
while (current->next!=NULL &&
current->next->name < n->name)
{
current = current->next;
}
n->next = current->next;
current->next = n;
}
In the above code,
Condition of string comparison need to be corrected. Using >= may not yield always the desired result as per alphabetical order is concerned. Reason being that it compares length or first element both. Instead "compare" function of string can be used.
The condition "if(head == NULL || head->name..." will jump into a situation of operating on a null pointer. So, use nested if statement instead of clubbing both condition under single if.
Coming to "at()" function:
Student* at(int index)
{
Student* temp = head;
int count=1;
if(head==NULL)
{
cout << "No students exist." << endl;
}
else
{
while(temp!=NULL)
{
if(count==index)
{
return(temp);
break;
}
else
{
count++;
temp = temp->next;
}
}
while(temp==NULL)
{
cout << "Index not found."<< endl;
break;
}
}
You need to de-reference the pointer in order to get the value (under switch condition, case 5) as you are returning a pointer.
Your function is not returning a value in all condition. You must finally return a pointer under each condition.
Also, instead of "while(temp == NULL)", you need to use "if(temp == NULL)"
Lastly use "nullptr" instead of "NULL" if you are working on C++11 or above version and use inbuilt containers like std::list if possible.

Related

C++ how to list all linked list data while also using loop to increment var which is for output coord position

#include <iostream>
#include <string.h>
#include <string>
#include <iomanip>
#include <cctype>
#include <ctype.h>
#include <fstream>
#include <cstdlib>
#include <windows.h>
using namespace std;
struct student{
string studentid,yearlevel,fullname,birthday,address,gender,course;
student *next;
};
void mainmenu(){
cout << " [I] Student Information System [I]" << endl;
cout << " | What do you want to do? |" << endl;
cout << " | |" << endl;
cout << " | 1. Add New Record |" << endl;
cout << " | 2. Search Record |" << endl;
cout << " | 3. Display All Records |" << endl;
cout << " | 4. Display Specific Record |" << endl;
cout << " | 5. Delete Record |" << endl;
cout << " | 6. Exit |" << endl;
cout << " ********************************" << endl;
cout << "\t\t\t\t\t Please type your selection:";
}
void border(){
cout <<"////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////"<< endl;
}
void gotoxy(short x,short y){
COORD pos={x,y};
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),pos);
}
void printrecords(student *head){
bool x;
cout <<"\n\n";
//cout <<"Student-ID Fullname Gender Yearlevel Course Birthday Address \n";
system("CLS");
gotoxy(0,1);
cout<<"Student ID";
gotoxy(12,1);
cout<<"Full Name";
gotoxy(30,1);
cout<<"Gender";
gotoxy(39,1);
cout<<"Year Level";
gotoxy(51,1);
cout<<"Course";
gotoxy(61,1);
cout<<"Birthday";
gotoxy(71,1);
cout<<"Address\n\n";
while(head!=NULL){
for(int i=2;x != false;){
gotoxy(0,i);
cout<<head->studentid;
gotoxy(12,i);
cout<<head->fullname;
gotoxy(30,i);
cout<<head->gender;
gotoxy(39,i);
cout<<head->yearlevel;
gotoxy(51,i);
cout<<head->course;
gotoxy(61,i);
cout<<head->birthday;
gotoxy(71,i);
cout<<head->address;
head = head->next;
i++;
if (head = NULL){
x=false;
}
}
x = true;
cout <<"\n\n";
}
}
void addrecord(student **head){
//NEW NODE
student *newnode = new student;
cout <<"Enter Student ID: ";
cin >> newnode->studentid;
cout <<"\nEnter Fullname: ";
cin.ignore();
getline(cin,newnode->fullname);
cout <<"\nEnter Gender (M/F): ";
getline(cin,newnode->gender);
cout <<"\nEnter Yearlevel(1/2/3/4/5): ";
cin >> newnode->yearlevel;
cout <<"\nEnter Course (BS______): ";
cin.ignore();
getline(cin,newnode->course);
cout <<"\nEnter Birthday (MM/DD/YYYY): ";
getline(cin,newnode->birthday);
cout <<"\nEnter Address: ";
getline(cin,newnode->address);
newnode->next = NULL;
// CHECK IF LIST IS EMPTY
if(*head==NULL)
{
*head = newnode;
return;
}
//TRANSVERSING LIST
student *temp = *head;
while(temp->next!=NULL)
{
temp = temp->next;
}
//add the newnode at the end of the list
temp->next = newnode;
}
void searchrecord(string searchValue,student *head){
//TEMP NODE POINT TO HEAD
student* temp=head;
//DECLARE 2 VAR to: TRACK | SEARCH
int found = 0;
int i=0;
/*CHECK temp node if NULL else check node DATA with searchValue,
if found update and break;
else continue searching till temp node is not null */
if(temp != NULL) {
while(temp != NULL) {
i++;
if(temp->studentid == searchValue) {
found++;
break;
}
temp = temp->next;
}
if (found == 1) {
cout<<"\n "<<searchValue<<" Details:\n";
cout<<searchValue<<" is numbered "<<i<<"on the database.\n";
cout <<"Student-ID Fullname Gender Yearlevel Course Birthday Address \n";
while(temp!=NULL){
cout<<left<<setw(9)<<temp->studentid;
cout<<left<<setw(10)<<temp->fullname;
cout<<left<<setw(10)<<temp->gender;
cout<<left<<setw(10)<<temp->yearlevel;
cout<<left<<setw(10)<<temp->course;
cout<<left<<setw(10)<<temp->birthday;
cout<<left<<setw(10)<<temp->address<<endl;
temp = NULL;
cout<<"\n\n";
}
}
else {
cout<<searchValue<<" is not in the database.\n";
}
} else {
cout<<"Their is no data in the database yet...\n";
}
}
int main(){
int select;
string u,searchValue;
bool system=false;
student *head=NULL;
do{
border();
mainmenu();
cin >> select;
switch (select){
case 1: { //Add New Record
cout<<"Adding New Record\n\n";
addrecord(&head);
break;
}
case 2: { //Search Record
cout<<"Accessesing Database Records....\n";
cout<<"Input the Student-ID that you would want to search:\n";
cout<<"Student-ID: ";
cin>>searchValue;
searchrecord(searchValue,head);
break;
}
case 3: { //Display All Records
cout<<"Displaying All Records.....\n\n";
cout<<"Database Record(s)\n";
printrecords(head);
break;
}
case 4: { //Display Specific Record
cout<<"Ran case 4\n";
break;
}
case 5: { //Delete Record
cout<<"Ran case 5\n";
break;
}
case 6:{ //EXIT
cout<<"Ran case 6\n";
cout<<"Exiting Program Have a Good Day!";
system = true;
break;
}
default:{
cout <<"\nInvalid Input... \n Try Again...\n";
break;
}
} //end switch
}while(!system);
return 0;
} // end main
In printrecord I use gotoxy for the outputs position in cmd
when i input 1,1,1,1,1,1 and then second input 2,2,2,2,2,2 it only prints 1,1,1,1 and exits.....
I want the program to list all linked list data while also incrementing var i to position the output going down not overlapping eachother
input 1,1,1,1,1,1 input 2,2,2,2,2 input 3,3,3,3,3,3
I want the program to output all data and then exit. go back to main menu.

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;

How to create a doubly linked list of integers in ascending sorted order?

I'm having hard time to finish the code to get the following steps:
how to read in a file of positive integers (>0)?
how to create a doubly linked list of integers in ascending sorted order?
how to write a method to print the entire list in ascending or descending order (input parameter ‘A’ or ‘D’ tells direction to print)?
how notify the user with a message if the number to add is already in the list or if the number is not in the list if they to delete a number not in the list.
There's no error when i run the program, just trying to solve the 4 steps above.
Here's what I have done so far
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
struct node
{
int number;
node *next;
};
bool isEmpty(node *head);
char menu();
void insertAsFirstElement(node *&head, node *&last, int number);
void inser(node*&head, node*&last, int number);
void remove(node *&head, node *&last);
void showlist(node *current);
int numIntElement(ifstream&x);
int main() {
string filename;
cout << " Please enter the name of the file = ";
cin >> filename;
ifstream myfile;
myfile.open(filename);
if (!myfile.is_open()) {
cout << endl << " failed to open file, check that it exists and you have access \n" << "\n" << endl;
}
else if (myfile.is_open())
{
ifstream x;
numIntElement(x);
cout << " File exists \n";
////
node * head = NULL;
node *last = NULL;
char choice;
int number;
do {
choice = menu();
switch (choice)
{
case '1':
cout << " Please enter number : ";
cin >> number;
inser(head, last, number);
break;
case '2':
remove(head, last);
case '3':
showlist(head);
break;
default:
break;
}
} while (choice != '4');
{
}
}
system("pause");
return 0;
}
int numIntElement(ifstream&x) {
int n = 0;
int m;
ifstream myfile("file.txt");
int countsingfie = 0;
while (!myfile.eof())
{
myfile >> n;
countsingfie += n;
if (countsingfie == 0) {
cout << "Error : file exist but no data " << endl;
}
cout << "total number " << countsingfie << "\n" << endl;
return countsingfie;
}
}
bool isEmpty(node *head) {
if (head == NULL) {
return true;
}
else
{
return false;
}
}
char menu() {
char choice;
cout << " Main Menu \n";
cout << " 1 . Add a number \n";
cout << " 2 . Delete a number from the list \n";
cout << " 3 . Show the list \n";
cout << " 4. Exit \n";
cin >> choice;
return choice;
}
void insertAsFirstElement(node *&head, node *&last, int number) {
node *temp = new node;
temp->number = number;
temp->next = NULL;
head = temp;
last = temp;
}
void inser(node*&head, node*&last, int number) {
if (isEmpty(head)>0){
insertAsFirstElement(head, last, number);
}
else if (isEmpty(head) < 0)
{
cout << " Please enter a number above 0 " << endl;
}
else
{
node *temp = new node;
temp->number = number;
temp->next = NULL;
last->next = temp;
last = temp;
}
}
void remove(node *&head, node *&last) {
if (isEmpty(head)) {
cout << " Sorry, The list is already empty \n";
}
else if (head == last)
{
delete head;
head = NULL;
last = NULL;
}
else
{
node *temp = head;
head = head->next;
delete temp;
}
}
void showlist(node *current) {
if (isEmpty(current)) {
cout << " The list is empty \n";
}
else
{
cout << " The list contains: \n ";
while (current != NULL)
{
cout << current->number << endl;
current = current->next;
}
}
}

Error in my c++ code using linkedlist "Stop working" [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
my code stop working in that test case, i think that the error in function Checktables but i'm not sure and i can't fix the error please help me to tun this code correctly.
image of a test case and the error
this is a cpp file with main .cpp
#include"Header.h"
string Name;
string namess;
customer::customer()
{
name = "";
gsize = status = 0;
next = NULL;
}
customer::customer(string name1, int gsize1, int status1)
{
name = name1;
gsize = gsize1;
status = status1;
next = NULL;
}
waitinglist::waitinglist()
{
chairnum =50 ;
totalcustomers = tables = 0;
head = tail = NULL;
}
waitinglist::waitinglist(int val)
{
chairnum = 50;
totalcustomers = 0;
tables = 0;
head = tail = NULL;
}
void waitinglist::change()
{
customer*temp ;
temp = head;
cout << "enter the name: ";
cin >> namess;
while (temp != NULL)
{
if (namess == temp->name)
{
if (temp->status==2)
{
temp->status=1;
cout << "done! " << endl ;
break ;
}
}
else if (namess != temp->name)
{
temp = temp->next;
}
}
if (temp == NULL)
{
cout << "can't found! " << endl;
}
}
void waitinglist::newcustomer()
{
customer*tmp = new customer;
cout << "enter the name: "; cin >> tmp->name;
customer*tmpo=new customer;
tmpo=head ;
while (tmpo != NULL)
{
if (tmp->name != tmpo->name)
{
tmpo = tmpo->next;
}
else if (tmp->name == tmpo->name)
{
cout<<"The Name already exist! " << endl ;
cout << "enter the name: "; cin >> tmp->name;
tmpo=head;
}
}
cout << "enter the group number: "; cin >> tmp->gsize;
cout << "enter the status: "; cin >> tmp->status;
if (head == NULL) // linkedlist is empty
{
head = tail = tmp;
totalcustomers++;
}
else
{
tail->next = tmp;
tail=tail->next;
totalcustomers++;
}
}
void waitinglist::checktables()
{
float c=5.00;
customer*temp=head;
customer*found;
cout<<"enter number of tables: ";
cin >> tables ;
while (tables>=1 && temp!=NULL)
{
int x;
float y;
y=((temp->gsize)/c);
x=(temp->gsize)/c;
if (tables<y)
{
temp=temp->next;
}
else if (tables>=y)
{
if (x==y)
{
tables=tables-x ; // Correct Table!
cout<<temp->name<<endl;
}
else if (x!=y)
{
tables=tables-(x+1);
cout<<temp->name<<endl;
}
found=temp ;
delete found; // Discard
break ;
}
}
}
void waitinglist::displayall()
{
customer *tmp;
tmp = head;
if (tmp == NULL)
{
cout << "Empty!";
}
while (tmp != NULL)
{
cout << "Name: " << tmp->name <<endl;
cout << "group number: " << tmp->gsize << endl;
tmp = tmp->next;
}
cout << endl;
}
void waitinglist::diplaycustomer()
{
customer*tmp;
tmp = head;
cout << "enter the name: ";
cin >> Name;
while (tmp != NULL)
{
if (Name == tmp->name)
{
cout << "the name : " << tmp->name << endl;
cout << "the group size = " << tmp->gsize << endl;
cout << "the status = " << tmp->status << endl;
break;
}
else if (Name != tmp->name)
{
tmp = tmp->next;
}
}
if (tmp == NULL)
{
cout << "can't found!" << endl;
}
}
int main()
{
int choice;
string name1 = "";
int gsize1 = 0;
int status1 = 0;
waitinglist mylist;
cout << "Note: 1 in status means the customer not here and 2 means the customer is here.\n";
cout << "Select your option.\n\n";
cout << "(1) Add a new Customer.\n";
cout << "(2) Display information based on Name.\n";
cout << "(3) List all Names.\n";
cout << "(4) to change the status. \n" ;
cout << "(5) Check tables by name. \n";
cout << "(6) quit. \n";
do
{
cout << "\n";
cout << "Enter your choice: --> ";
cin >> choice;
if (1 <= choice && choice <= 5)
{
switch (choice)
{
case 1:
mylist.newcustomer();
break;
case 2:
mylist.diplaycustomer();
break;
case 3:
mylist.displayall();
break;
case 4:
mylist.change() ;
break;
case 5 :
mylist.checktables();
break;
default:
cout << "Invalid choice. Enter again.\n\n";
break;
}
}
else if (choice>6)
{
cout << "Invalid choice. Enter again.\n\n";
break;
}
} while (choice != 6);
return 0;
}
and this is the header file .h
#include<iostream>
#include<string>
using namespace std;
class customer
{
public:
string name;
int gsize;
int status;
customer* next;
customer();
customer(string,int,int);
};
class waitinglist
{
public:
int tables; //number of occupied tables
int chairnum;
int totalcustomers;
customer*head,*tail;
waitinglist();
waitinglist(int);
void newcustomer();
void diplaycustomer();
void displayall();
void change () ;
void checktables();
};
One error is that your checktables function corrupts your linked list structure by calling delete on one of the nodes:
found = temp;
delete found; // Discard
What you've just done in those lines above is to have a linked list with a broken (invalid) link in it. Any functions that now traverses the list (like displaytables) will now hit the broken link, and things start to go haywire.
To delete a node from a linked list, you have to not just call delete, but adjust the link in waitinglist that used to point to that deleted node and have it point to the next node after the deleted one.
Think of it like a real chain -- if one of the links in the chain needs to be removed, you have to physically remove it, and hook the link before it to the next good link. You didn't do this step.
I won't write the code for that, but this is what you should have seen much earlier in the development of your program. Better yet would have been to write a singly-linked list class that adds and removes nodes correctly first. Test it, and then once it can add and remove nodes successfully without error, then use it in your larger program.

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.