Airline Reservation System using linked list - c

Im doing airline reservation system in c programming, using linked list. It reserves a seat, views the reservation, cancels the reservation. The program runs properly for the first time without adding any data.
But when i add data and want to delete it, it gives this error "Exception thrown at 0x0FFAFBB3 (ucrtbased.dll) in ConsoleApplication1.exe: 0xC0000005: Access violation writing location 0x0004B000."
For deleting data, im comparing the phone number data. And when it compares, it deletes the record. But instead it is giving error. Anyone identify the error area and provide suggestion??
Below is the code for making reservation and deleting a reservation.
void new_reservation()
{
curr = start;
if (start == NULL)
{
//Empty list
start = curr = (struct passenger *)malloc(sizeof(struct passenger));
dataentry();
curr->next = NULL;
printf("\n\t Reservation successful");
return;
}
//Reach end of list
while (curr->next)
curr = curr->next;
curr->next = (struct passenger *)malloc(sizeof(struct passenger));
curr = curr->next;
dataentry();
curr->next = NULL;
printf("\n\t Reservation successful");
printf("\n\t Saved to Reservation list");
}
void del()
{
struct passenger *temp; // assigning a temporary pointer to struct airplane
char str[20];
printf("Enter phone number:");
gets(str);
fflush(stdin);
curr = start;
while (curr)
{
if (strcmp(start->Phone, str) == 0)
{
temp = start;
start = start->next;
free(temp);
return;
}
if (strcmp(curr->next->Phone, str) == 0)
{
temp = curr->next;
curr->next = curr->next->next;
free(temp);
break;
}
else if (strcmp(curr->next->Phone, str) != 0)
{
printf("\n\n No reservations found!!");
break;
}
}
printf("\n\n Deletion successful!!");
}

if (strcmp(start->Phone, str) == 0){...}
if (strcmp(curr->next->Phone, str) == 0){...}
else if (strcmp(curr->next->Phone, str) != 0){...}
This method is too complicated, it is bound to run in to errors unless you carefully check the pointers and that pointer's next member. You can simplify this and make only one comparison. Just make sure to keep track of the node's position, if the node being deleted is the start or it is another node. Example:
void del()
{
char str[20];
struct passenger *walk = start;
if (!walk)
return;
printf("Enter phone number:");
scanf("%s", str);
struct passenger *previous = 0;
while (walk)
{
if (strcmp(walk->Phone, str) == 0)
{
struct passenger *next = walk->next;
free(walk);
if (previous == 0)
{
//deleting the first item
start = next;
}
else
{
//deleting an item in middle or end
previous->next = next;
}
return;
}
previous = walk;
walk = walk->next;
}
}
new_reservation is probably not causing any errors, but it too can be simplified. You only need to allocate once, then insert it either at the end, or assign it as start. Also you can use scanf to read a string.
void new_reservation()
{
//create new item
curr = malloc(sizeof(struct passenger));
curr->next = NULL;
//I don't know this part of your code...
dataentry();
if (start == NULL)
{
//Empty list
start = curr;
}
else
{
//find the end of the list
struct passenger *walk = start;
while (walk->next)
walk = walk->next;
walk->next = curr;
}
}

Related

Error Cannot access memory at address in linked list

I'm creating a linked list with some insert functions.
This method work fine :
void insert_before(){
struct node *new_node, *ptr, *preptr;
int pivot;
new_node = (struct node*)malloc(sizeof(struct node));
ptr = link;
preptr = link;
printf("\n Enter the data : ");
scanf("%d", &new_node->data);
printf("\n Enter the value before which the data has to be inserted : ");
scanf("%d", &pivot);
while(ptr->data != pivot){
preptr = ptr;
ptr = ptr->next;
}
preptr->next = new_node;
new_node->next = ptr;
}
However, I got Cannot access memory at address 0x8 in this method :
void insert_after(){
struct node *new_node, *ptr, *preptr;
int pivot;
new_node = (struct node*)malloc(sizeof(struct node));
ptr = link;
preptr = link;
printf("\n Enter the data : ");
scanf("%d", &new_node->data);
printf("\n Enter the value after which the data has to be inserted : ");
scanf("%d", &pivot);
while(preptr->data != pivot){
preptr = ptr;
ptr = ptr->next;
}
preptr->next = new_node;
new_node->next = ptr;
}
Note that both of the method use the same struct* link, and the only difference is on the looping while(preptr->data != pivot).
Why does the first code working fine, but the second one broken?
Thanks for your help
PS : This is my whole project (very short), in case you need it : https://pastebin.com/wsMEicGv
I don't think that even the first method works correctly (simple proof: the code never changes the value of link, hence an insert before the first node cannot work).
Anyway, your code will produce the mentioned error message in both functions when you enter a value for pivot which does not match any data or which matches the last node in the list:
while(preptr->data != pivot){
preptr = ptr;
ptr = ptr->next;
}
The reason is that the loop above will reach the end of the list (having preptr = NULL), when condition preptr->data still accesses this null-pointer. I suppose that member data is the second one in your struct (the first one is next), right? Then you access actually (NULL + sizeof(node*)) which is (NULL + 8) which is 0x08.
You have a lot of bad practice:
You use global without reason!
You use global without reason!!
You use global without reason!!!
You cast malloc() without reason.
You don't check return value of function like scanf() or malloc().
You code several time the same feature.
fflush(stdin); is undefined behavior.
You don't initialize your variable when you could.
You declare all your variable at the beginning of the function.
For example, display() could look like this:
void display(struct node *head) { // no global it's better, isn't it ?
printf("List:");
while (head != NULL) {
printf(" %d", head->data);
head = head->next;
}
printf("\n");
}
More, in your create_ll() function, why don't you use insert beginning and reverse the list after ?
int create_ll(struct node **head) {
*head = NULL;
while (insert_beginning(head) != ERROR) {
}
return reverse_ll(head);
}
Use example:
int main(void) {
struct node *head;
if (create_ll(&head) == ERROR) {
return 1;
}
display(head);
free_ll(head);
}
For the problem of your both function, read the answer of stephan-lechner. But I make you an example:
int insert_after(struct node **head) {
printf("\n Enter the data : ");
int data;
if (scanf("%d", &data) != 1) { // If the input has no been parse.
// data is invalid here
return ERROR;
}
// data is valid here
printf("\n Enter the value after which the data has to be inserted : ");
int pivot;
if (scanf("%d", &pivot) != 1) {
return ERROR;
}
for (struct node *node = *head; node != NULL; node = node->next) {
if (node->data == pivot) {
struct node *new_node = malloc(sizeof *new_node);
if (new_node == NULL) {
return ERROR;
}
new_node->data = data;
new_node->next = node->next;
node->next = new_node;
return OK;
}
}
return ERROR;
}
Be aware that: If you use global your list functions will be:
Not thread safe.
Only usable for one list.
More info here.

How to delete node from doubly linked list in c

I am working on doubly linked list in c, I have a doubly linked tepm2 with 20 nodes and I want to delete the node whose word user insert.
struct node {
struct node *prev;
char word[100];
int repeatTime;
struct node *next;
} *h, *temp, *temp1, *temp2;
Each node has unique word.
printf("\n Enter word to delete : ");
scanf("%s", &word);
Delete(word);
int delete(char data[200]) { //unable to delete
if (h == NULL)
return;
temp2 = next = previous = h;
while (temp2->next != NULL) {
if ((strcmp(temp2->word, data) == 0)) {
if (temp2->prev == NULL) {
h = temp2->next;
free(temp2);
return;
} else if (temp2->prev == NULL) {
previous->next = temp2;
free(temp2);
previous->next = NULL;
return;
} else {
previous->next = temp2->next;
next->prev = temp2->next;
}
}
temp2 = temp->next;
}
}
I am been unable to delete the specific node that word user enter
Try this:
int delete(const char *data)
{
struct node *temp = h;
if (h == NULL) return;
while (temp->next != NULL)
{
if (strcmp(temp->word, data) == 0)
{
if (temp->prev != NULL)
{
temp->prev->next = temp->next;
}
if (temp->next != NULL)
{
temp->next->prev = temp->prev;
}
if (h == temp)
{
h = temp->next;
}
free(temp);
return;
}
temp = temp->next;
}
}
First of all I don't think this is right temp2 = next = previous = h;
Now all you have to do is find the node that you want to delete by traversing and than link it's prev node to it's next node i.e. (temp2->prev)->next = next and (temp2->next)->prev = prev and free it.
Now the real issue lies with
1. The first node that has other nodes after it
2. last node that has other nodes preceding it
3. only node
You can simplify all three by converting them into the former problem i.e. node in the middle problem which we've just solved.
For simplifying you can just make the head and tail both NULL.

Link list program to Display Student marks

#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
void Insert();
void DisplayList();
struct Student
{
char Name[10];
int Marks;
struct Student *Next;
} *Start;
int main()
{
Start = NULL;
int Choise;
while (1)
{
printf("enter number to choose ");
scanf_s("%d", &Choise);
switch (Choise)
{
case 1:
Insert();
break;
case 3:
DisplayList();
break;
default:
printf("Incorrect assignment Press relevant key :");
}
}
}
void Insert()
{
struct Student *Temp, *current=NULL;
Temp = (struct Student *) malloc(sizeof(struct Student));
printf("Enter Name Of Student");
scanf_s("%s",&Temp->Name);
printf("Enter Marks Of Student");
scanf_s("%d", &Temp->Marks);
Temp->Next = NULL;
if (Start == NULL)
{
Start = Temp;
Temp->Next = NULL;
}
else
current = Start;
while (current->Next != NULL)
{
current = current->Next;
current->Next = Temp;
}
}
void DisplayList()
{
struct Student *current, *Temp;
current = Start->Next;
if (Start == NULL)
{
printf("No Element in the list");
}
else
{
for (current = Start; current != NULL; current = current->Next)
{
printf("The List are\n");
printf_s("%d",current->Marks);
}
}
this is a Program written for single linked list.when i display the list it give only one element in the list. Whenever i am trying to print the elements of the linked list, it gives the output only one element
what mistake i do please help?
change
else
current = Start;
while (current->Next != NULL)
{
current = current->Next;
current->Next = Temp;
}
to
else {
current = Start;
while (current->Next != NULL)
{
current = current->Next;
}
current->Next = Temp;
}
and
scanf_s("%s", Temp->Name, sizeof(Temp->Name)); //remove & and add size(see Amnon's answer)
When using scanf_s which is the safe version of scanf, you are expected to pass not only the address of the buffer but also its size as the next parameter, i.e.:
scanf_s("%s", Temp->Name, _countof(Temp->Name));
You can read more about it in http://msdn.microsoft.com/en-us/library/w40768et.aspx
The other issue with the code is that you're initializing current with NULL but then trying to access its Next field.
Change the code here:
else
current = Start;
while (current->Next != NULL)
{
current = current->Next;
current->Next = Temp;
}
to this:
else {
current = Start;
while (current->Next != NULL)
{
current = current->Next;
}
current->Next = Temp;
temp->next=NULL;
}
you forget to add NULL at next pointer and therefore you are getting only single output.

Linked list structures initialized in functions not being assigned properly

I'm sure this has been asked before, but I cannot find anything on this website or any other about it after searching for quite awhile.
I''m having trouble getting the values of structures that I'm creating and modifying in a function. The code looks something like:
struct node {
char name[35];
int employeeID;
struct node *next;
}
typedef struct node employee;
void insertInOrder(employee *head, employee *curr) {
if (head == NULL) {
*curr->next = *head;
*head = *curr;
} else {
if ((head->employeeID<curr->employeeID)&&(curr->employeeID <head->next->employeeID)) {
*curr->next = *head->next;
*head->next = *curr;
} else {
insertInOrder(head->next, curr);
}
}
}
void addEmployee(char name[], employee *head, employee *curr) {
int id;
scanf("%d", &id);
curr = malloc(sizeof(employee));
strcpy(curr->name, name);
curr->employeeID = id;
insertInOrder(head, curr);
}
int main(void) {
char name[35];
int quit = 1;
employee *head, *curr;
head = NULL;
printf("Enter data about the books: \n");
while (quit) {
scanf("%[^\n]%*c", title);
if (title[0] != '#') {
addBook(name, head, curr);
} else {
quit = 0;
}
}
During my debugging, my code iterates into all of my functions, but once I get back to main after adding all of the data I want, all of the variables are empty. I know it has something to do with the way I'm using or passing pointers, but when I look at the code I keep coming to the logical conclusion that what I have should do what I want. Please, someone point out where my algorithm is flawed.
addBook takes pointers of type Book but you are passing pointers of type Employee
Edit:
So, first you don't need to do things like *curr->next = *head. It should be curr->next = head.
Also, head->next can be null which is not being checked. Finally, head needs to always be pointed at the start of the list.
Edit 2:
Following code should work. head always points to the start of the list. In order to do that, we must pass the address of the head pointer. We need to do this because we will be modifying the address of head.
I've also cleaned up a few things.
void insertInOrder(employee **head, employee *curr) {
if (*head == NULL) {
// We are inserting the first element
*head = curr;
}
else if ((*head)->next == NULL) {
// This is the second element. We either insert it in front of head or before head.
if ((*head)->employeeID < curr->employeeID) {
(*head)->next = curr;
}
else {
curr->next = *head;
*head = curr;
(*head)->next = NULL;
}
}
else {
// We iterate through the list trying to find the best spot to insert curr.
employee *temp = *head;
while (temp->next != NULL) {
if ((temp->employeeID < curr->employeeID) && (curr->employeeID < temp->next->employeeID)) {
curr->next = temp->next;
temp->next = curr;
break;
}
temp = temp->next;
}
// curr has the greatest id so it is inserted at the end
if (temp->next == NULL)
temp->next = curr;
}
}
void addEmployee(char name[], employee **head) {
int id;
printf("Enter id\n");
scanf("%d", &id);
employee *curr = malloc(sizeof(employee));
strcpy(curr->name, name);
curr->employeeID = id;
curr->next = NULL;
insertInOrder(head, curr);
}
int main(void) {
int quit = 1;
employee *head = NULL;
char title[100];
printf("Enter data about the employees: \n");
while (quit) {
scanf("%s", title);
if (title[0] != '#')
addEmployee(title, &head);
else break;
}
return 0;
}
inside the function no need to use *head or *curr ..because -> is made up for pointers only instead directly use head->left & curr->next
thanks

Access violation writing data to a doubly linked list

I got the following error:
0xC0000005: Access violation writing location 0x00000040.Which I assume means that the new contact is empty,when adding a new information to a doubly linked list using pointers.Ths is where I finish the function:
curr->next = newContact;
newContact->prev = curr;
newContact->next = NULL;
So I added the following if..else loop to check if curr is equal to the newContact and add it to the list.But that didn't work either..
if(curr-> newContact)
{
curr->next = newContact;
newContact->prev = NULL;
}
else
{
curr->next = newContact;
newContact->prev = curr;
newContact->next = NULL;
}
This is the complete function for reference:
int addContact(struct contact *theList)
{
struct contact *newContact, *curr;
// create the new structure
newContact = (struct contact *)malloc(sizeof(struct contact));
if( newContact == NULL )
{ // if true, then no memory left - oops
return(0);
}
// find the end of the list
curr = theList;
// scroll through the list
if(curr != NULL)
{
while( curr->next != NULL)
{
curr = curr->next;
}
}
// now have the last contact
// add the new one here.
printf("\nEnter a surname: ");
fflush(stdin);
gets(newContact->sname);
printf("\nEnter a first name: ");
gets(newContact->fname);
printf("\nEnter a phone: ");
gets(newContact->phone);
printf("\nEnter a company: ");
gets(newContact->company);
// need to hook the new contact to
// end of list
if(curr-> newContact)
{
curr->next = newContact;
newContact->prev = NULL;
}
else
{
curr->next = newContact;
newContact->prev = curr;
newContact->next = NULL;
}
return(1);
}//add
I cant see where I'm gone wrong in the check.Any ideas?Thanks
The access violation, and the address 0x00000040 in the error message, are telling you that you have not properly initialized curr which is a pointer to a structure of some sort. Odds are you declared it but never allocated memory for it or set it to point to a valid storage space.
I would bet money that curr is NULL and next is 0x40 bytes into the structure.
Expanding on your edited question... look at this block of code... what happens if curr is NULL ?? You're testing for the possibility, but then if it is NULL you don't do anything about it.
// find the end of the list
curr = theList;
// scroll through the list
if(curr != NULL)
{
while( curr->next != NULL)
{
curr = curr->next;
}
}

Resources