I can't figure out why my code breaks. Every thing works, except when I try to reverse the linked list. It "stops working." (This function; void reverseList(struct produceItem** inHead)) Any ideas? I've been stuck on this for some time now. I think the issue might be that it doesn't read a NULL some where, but I cannot figure it out.
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<stdlib.h>
struct produceItem{
char produce[20];
char type[20];
char soldBy[20];
float price;
int quantityInStock;
struct produceItem *next;
};
struct produceItem* append(struct produceItem *inHead, char *nextProduce, char *nextType, char *nextSoldBy, char *nextPrice, char *nextQuantityInStock){
struct produceItem *temp;
temp =(struct produceItem *)malloc(sizeof(struct produceItem));
strcpy(temp->produce, nextProduce);
strcpy(temp->type, nextType);
strcpy(temp->soldBy, nextSoldBy);
temp->price = atof(nextPrice);
temp->quantityInStock = atoi(nextQuantityInStock);
if(inHead == NULL){
inHead = temp;
temp->next = NULL;
}
else{
temp->next = inHead;
inHead = temp;
}
return inHead;
}
struct produceItem* readData(struct produceItem *inHead){
const char comma[2] = ",";
char *produceTemp;
char *typeTemp;
char *soldByTemp;
char *priceTemp;
char *quantityInStockTemp;
char dataLine[100];
char fileName[] = "AssignmentTwoInput.txt";
FILE *inputFile;
printf("\nFile %s has been read.\n\n", fileName);
inputFile = fopen(fileName, "r");
if( inputFile == NULL){
printf("%sList Does not exist\n", fileName);
return;
}
while((fgets(dataLine, 100, inputFile)) != NULL){
produceTemp = strtok(dataLine, comma);
typeTemp = strtok(NULL, comma);
soldByTemp = strtok(NULL, comma);
priceTemp = strtok(NULL, comma);
quantityInStockTemp = strtok(NULL, comma);
inHead = append(inHead, produceTemp,typeTemp,soldByTemp,priceTemp,quantityInStockTemp);
}
fclose(inputFile);
return inHead;
}
void display(struct produceItem *inHead){
int i = 1;
if(inHead == NULL){
printf("List does not exist.\n");
return;
}
printf("=========================================================================\n");
printf("Item # Produce Type Sold By Price In Stock\n");
printf("==========================================================================\n");
for(i=1; i<27; i++){
//while(inHead != NULL){
printf("\n%5d", i);
printf(" %-12s ", inHead->produce);
printf("%-16s ", inHead->type);
printf("%-16s ", inHead->soldBy);
printf("%3.2f ", inHead->price);
printf("%8d", inHead->quantityInStock);
inHead = inHead->next;
//i++;
}
printf("\n\n");
}
exportData(struct produceItem *n){
char fileName[] = "AssignmentTwoOutput.txt";
FILE *exportFile;
int i =1;
if(n == NULL){
printf("List does not exist.\n");
return;
}
exportFile = fopen(fileName, "w");
//printf("hi");
fprintf(exportFile,"================================================================\n");
//printf("hi");
fprintf(exportFile,"Item# Produce Type Sold By Price In Stock\n");
fprintf(exportFile,"================================================================\n");
for(i=1; i<27; i++){
//while(n->next != NULL){
//printf("hi");
fprintf(exportFile,"\n%3d", i);
fprintf(exportFile," %-12s ", n->produce);
fprintf(exportFile,"%-15s ", n->type);
fprintf(exportFile,"%-15s ", n->soldBy);
fprintf(exportFile,"%3.2f ", n->price);
fprintf(exportFile,"%8d", n->quantityInStock);
n = n->next;
}
printf("\nYour data has been written to AssignmentTwoOutput.txt, thank you.\n\n");
fclose(exportFile);
}
//void recursiveReverse(struct node** head_ref)
//{
//struct node* first;
// struct node* rest;
/* empty list */
// if (*head_ref == NULL)
//return;
/* suppose first = {1, 2, 3}, rest = {2, 3} */
//first = *head_ref;
//rest = first->next;
/* List has only one node */
//if (rest == NULL)
//return;
/* reverse the rest list and put the first element at the end */
//recursiveReverse(&rest);
//first->next->next = first;
/* tricky step -- see the diagram */
//first->next = NULL;
/* fix the head pointer */
//*head_ref = rest;
//}
void reverseList(struct produceItem** inHead){
//printf("1");
struct produceItem* first;
struct produceItem* follow;
//printf("2");
if (*inHead==NULL){
// printf("3");
printf("List does not exist.\n");
return;}
first = *inHead;
//printf("4");
follow = first->next;
if(follow==NULL)
//printf("5");
return;
reverseList(&follow);
first->next->next = first;
first->next = NULL;
*inHead = follow;
}
int main (void){
int choice;
struct produceItem *head;
while(1){
printf("List of Operations\n");
printf("===============\n");
printf("1. Stock Produce Department\n");
printf("2. Display Produce Inventory\n");
printf("3. Reverse Order of Produce Inventory\n");
printf("4. Export Produce Inventory\n");
printf("5. Exit\n");
printf("Enter you choice: ");
scanf("%d", &choice);
if(choice <= 0 || choice > 5){
printf("Enter a valid response please: \n");
exit(0);
}
switch(choice){
case 1:
//reading from thefile
head = readData(head);
break;
case 2:
//displays the list
display(head);
break;
case 3:
//reverse the list
reverseList(&head);
break;
case 4:
exportData(head);
break;
case 5:
//Exits the operation
printf("Exiting, Thank you.");
exit(0);
break;
}
}
}
in this recursive function:
void reverseList(struct produceItem** inHead){
//printf("1");
struct produceItem* first;
struct produceItem* follow;
//printf("2");
if (*inHead==NULL){
// printf("3");
printf("List does not exist.\n");
return;}
first = *inHead;
//printf("4");
follow = first->next;
if(follow==NULL)
//printf("5");
return;
reverseList(&follow);
first->next->next = first;
first->next = NULL;
*inHead = follow;
}
This function will run recursively through the list.
Ok lets look at your code:
2 local variables (does nothing really)
code to exit if input is null (mostly for safety)
You set your local variables to the current and next node.
code to exit if this is the last node in the list.
You call your function recursively.
Note that at this stage actually nothing has happened.
This means that your processing (the lines at the end of your function) will happen in reverse order of the list. From back to front.
This seems correct for what you want to do.
Next line:
first->next->next = first;
This seems correct as it would set the next of the "following" node to point to this one. As in change the direction of the next pointer within the list.
Now you have this line:
first->next = NULL;
Remember that we said your "processing" of the nodes will happen in the reverse order. So effectively one by one you will set all your next pointers to NULL. Which I think will completely disconnect your queue completely?
The last line I understand is simply to enable you to find the new head pointer for your queue and that seems fine.
btw doing this kind of algorithm with recursion is a bad idea normally.
As you can easily cause stack overflow problems if your list is getting long.
Also if for some reason your list has a problem and it is circular then it is difficult to detect that and not cause problems.
Also generally in terms of performance this type of recursive algorithm will be slower than just a proper loop implementation.
Pseudo code to "reverse" list:
reverseList(** head)
{
current = head
prev = null
next = null
int i = 0;
while (current)
{
next = current->next;
current->next = prev;
prev = current;
current = next;
i++;
if (i > MAX) reportError();
}
head = prev;
}
Related
I am trying to build a simple linked list.
I have successfully built a linked list only with int variables but when I add *char variables the output is wrong.
The int values seem to be correct but the *char type are wrong.
The *char type seem to always be the last one inserted.
Sample Input
Number: 5
Character: a
Number: 4
Character: b
Sample Output
5
b
**************
4
b
#include <stdio.h>
#include <stdlib.h>
typedef struct BOOKS
{
int value;
char *char_value;
struct BOOKS *next;
} BOOKS;
BOOKS *insert_value(BOOKS *node, int n, char *char_value);
BOOKS *read_list(BOOKS *head);
int main()
{
int aux = 0;
int menu = 0;
int option;
BOOKS *head = NULL;
BOOKS *tail = NULL;
while (menu != -2)
{
int choices;
printf("1. Insert Book\n");
printf("2. Print Books\n");
printf("3. Exit\n");
scanf("%d", &choices);
switch (choices)
{
case 1:
{
int n;
char char_value[2000] = "";
printf("Number:");
scanf("%d", &n);
printf("Character: ");
scanf("%s", &char_value);
if (aux == 0)
{
/*FIRST INTERACTION*/
head = malloc(sizeof(BOOKS));
tail = malloc(sizeof(BOOKS));
head = tail = insert_value(tail, n, char_value);
aux = 1;
}
else
{
tail->next = malloc(sizeof(BOOKS));
/*FORMING TAIL->NEXT*/
tail->next = insert_value(tail->next, n, char_value);
/*ASSIGNING TAIL->NEXT AS THE NEW TAIL */
tail = tail->next;
}
break;
}
case 2:
{ /*READ THE LIST*/
read_list(head);
break;
}
case 3:
{
menu = -2;
break;
}
default:
printf("Invalid choice\n");
break;
}
}
}
BOOKS *insert_value(BOOKS *node, int n, char *char_value)
{
node->value = n;
node->char_value = char_value;
node->next = NULL;
return node;
}
BOOKS *read_list(BOOKS *head)
{
BOOKS *a = head;
while (a != NULL)
{
printf("%d\n", a->value);
printf("%s\n", a->char_value);
printf("\n********************\n");
a = a->next;
}
}
You're passing char_value from main to your insert_books function, and then saving this pointer in your newly created node. The address of char_value from main doesn't change, so you're saving the same address to each node you create. Since all these pointers point to the same place, they will all read back whatever value was written there last. If you want to make a copy of string in each node, you can use (non standard) strdup or malloc more memory and use strcpy. But, it's an odd design choice you're using a character array to accept one character anyway. I recommend changing char_value in both main and struct BOOKS to char char_value;, then you can simply use equals assignment as with value to save copies of the char. Be sure to scanf a char the correct way.
A couple of other things:
As written, you can change scanf("%s", &char_value); to scanf("%s", char_value);. char_value is a character array, which decays to a char* in this context, there's no need to specify the address of char_value.
head = malloc(sizeof(BOOKS));
tail = malloc(sizeof(BOOKS));
head = tail = insert_value(tail, n, char_value);
This is a memory leak. You're allocating separate memory for head and tail, but then setting both pointers equal to the memory allocated for tail (the return value of insert_value). The memory allocated for head is never freed nor used.
This will help with the errors:-
#include <stdio.h>
#include<string.h>
#include <stdlib.h>
typedef struct BOOKS
{
int value;
char char_value[2000];
struct BOOKS *next;
} BOOKS;
BOOKS *insert_value(BOOKS *node, int n, char *char_value);
BOOKS *read_list(BOOKS *head);
int main()
{
int aux = 0;
int menu = 0;
int option;
BOOKS *head = NULL;
BOOKS *tail = NULL;
while (menu != -2)
{
int choices;
printf("1. Insert Book\n");
printf("2. Print Books\n");
printf("3. Exit\n");
scanf("%d", &choices);
switch (choices)
{
case 1:
{
int n;
char char_value[2000];
printf("Number:");
scanf("%d", &n);
printf("Character: ");
scanf("%s", char_value);
if (aux == 0)
{
/*FIRST INTERACTION*/
head = malloc(sizeof(BOOKS));
tail = malloc(sizeof(BOOKS));
head = tail = insert_value(tail, n, char_value);
aux = 1;
}
else
{
tail->next = malloc(sizeof(BOOKS));
/*FORMING TAIL->NEXT*/
tail->next = insert_value(tail->next, n, char_value);
/*ASSIGNING TAIL->NEXT AS THE NEW TAIL */
tail = tail->next;
}
break;
}
case 2:
{ /*READ THE LIST*/
read_list(head);
break;
}
case 3:
{
menu = -2;
break;
}
default:
printf("Invalid choice\n");
break;
}
}
}
BOOKS *insert_value(BOOKS *node, int n, char *char_value)
{
node->value = n;
int size = sizeof(char_value)/sizeof(char);
strncpy(node->char_value, char_value, size);
node->next = NULL;
return node;
}
BOOKS *read_list(BOOKS *head)
{
BOOKS *a = head;
while (a != NULL)
{
printf("%d\n", a->value);
printf("%s\n", a->char_value);
printf("\n********************\n");
a = a->next;
}
}
i guess this is question is as custom as it can get because i haven't found anything like it online.
i am doing a homework for school where i am supposed to create a program that takes as input a file of type csv containing student information(first name, last name , phone number, class, etc ), creates and fills up a chained list from the info in that file, sorts it using a column of the user's choice, then displays the sorted list.
i got the program to work, but the part where the user can choose a sort column i haven't written it yet; right now, the sort parameter is injected inside the sort function.
i need your help to find out how i can take the input of the user and get it inside the sort function..
which data type points to the sort column inside the linked list? i tried pointers but i got nowhere..
here is the code:
// ============================
// BEGINNING OF CODE
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <math.h>
#include <conio.h>
#include <string.h>
// ============================
// DEFINE
#define FILE_TO_READ "TPP_TP_Data_2019_base.csv"
// ============================
// GLOBAL VARIABLES
typedef struct node
{
char Lastname[50];
char Firstname[50];
char Initials[50];
char Mobile[50];
char Class[50];
char InitialSort[50];
char RandomSort[50];
struct node *next;
} node;
node *HEAD=NULL;
// ============================
// FONCTION PROTOTYPE DECLARATIONS
node * Read();
void Display(node *);
void Sort();
void InsertionSort(node **);
void sortedInsert(node** ,node*);
// ============================
// MAIN
int main()
{
HEAD=Read();
Display(HEAD);
printf("\n\n\n");
Sort();
printf("\n\n\n");
InsertionSort(&HEAD);
return 0;
}
// ============================
// FUNCTIONS
node * Read()
{
FILE *fPointer;
fPointer = fopen(FILE_TO_READ,"r");
if (fPointer == NULL)
{
printf("\nCould not open file %s",FILE_TO_READ);
exit(1);
}
//reading the file and creating liked list
char parsedLine[100];
node *head = NULL;
node *p = NULL;
while(fgets(parsedLine, 100, fPointer) != NULL)
{
node * temp=malloc(sizeof(node));
char *getNom = strtok(parsedLine, ";");
strcpy(temp->Lastname, getNom);
char *getPrenom = strtok(NULL, ";");
strcpy(temp->Firstname, getPrenom);
char *getInitials = strtok(NULL, ";");
strcpy(temp->Initials, getInitials);
char *getMobile = strtok(NULL, ";");
strcpy(temp->Mobile, getMobile);
char *getClasse = strtok(NULL, ";");
strcpy(temp->Class, getClasse);
char *getTriInitial = strtok(NULL, ";");
strcpy(temp->InitialSort, getTriInitial);
char *getTriAleatoire = strtok(NULL, ";");
strcpy(temp->RandomSort, getTriAleatoire);
temp->next = NULL;
if(head == NULL) // if first is empty, then make temp the first node
{
head = temp;
}
else
{
p=head;
while(p->next != NULL)
p=p->next;
p->next=temp;
}
}
fclose(fPointer);
return head;
}
void Display(node * head) // prints out the contents of the linked list // done
{
node *temp=head;
while(temp!=NULL)
{
printf("%s %s %s %s %s %s %s \n",temp->Lastname,temp->Firstname,temp->Initials,temp->Mobile,temp->Class,temp->InitialSort,temp->RandomSort);
temp = temp->next;
}
printf("\n");
printf("===========================================");
}
void Sort()
{
char SortParameter;
// declare SortChoice here;
printf("\n Enter sort Parameter : ");
printf("\n P - Firstname");
printf("\n N - Lastname");
printf("\n I - Initials");
printf("\n M - Mobile");
printf("\n C - Class");
printf("\n X - Tri Initial");
printf("\n Z - Tri Aleatoire");
printf("\n Your Choice : ");
fflush(stdin);
SortParameter=getch();
/*
switch(SortParameter)
{
case 'P': SortChoice = ;
case 'N': SortChoice = ;
case 'I': SortChoice = ;
case 'M': SortChoice = ;
case 'C': SortChoice = ;
case 'X': SortChoice = ;
case 'Z': SortChoice = ;
}
*/
putch(SortParameter);
printf("\n\n");
printf("\n Sorting done, Here is the Sorted list : \n");
InsertionSort(&HEAD);
Display(HEAD);
}
void InsertionSort(node **head_ref) // function to sort a singly linked list using insertion sort
{
// Initialize sorted linked list
node *sorted = NULL;
// Traverse the given linked list and insert every node to sorted
node *current = *head_ref;
while (current != NULL)
{
// Store next for next iteration
node *next = current->next;
// insert current in sorted linked list
sortedInsert(&sorted, current);
// Update current
current = next;
}
// Update head_ref to point to sorted linked list
*head_ref = sorted;
}
void sortedInsert(node** head_ref,node* new_node)
{
node* current;
// Special case for the head end
if (*head_ref == NULL || (*head_ref)->Firstname >= new_node->Firstname)
{
new_node->next = *head_ref;
*head_ref = new_node;
}
else
{
// Locate the node before the point of insertion
current = *head_ref;
while (current->next!=NULL && strcmp(current->next->Firstname, new_node->Firstname)<0 )
{
current = current->next;
}
new_node->next = current->next;
current->next = new_node;
}
}
//=========================================================
It seems that my code isn't working because I cannot add any string to the list. It seems like the list remains empty. After every input of a string like "asd" or a single character, the message that appears every time is:
List is empty
Also, I don't know if the 'delete' function could work, because the 'insert' function isn't working.
Here's my code(It is a bit long):
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
struct listnode
{
char data[100];
listnode *nextPtr;
};
Here is my insert function. PS: I want to insert names so they can be alphabetically ordered.
void insert(struct listnode *strPtr, char value[])
{
struct listnode *previousPtr, *currentPtr, *newPtr;
newPtr=(listnode*)malloc(sizeof(listnode));
strcpy(newPtr->data,value);
newPtr->nextPtr=NULL;
previousPtr=NULL;
currentPtr=strPtr;
if(newPtr!=NULL)
{
while(currentPtr!=NULL && strcmp(currentPtr->data,value)>0)
{
previousPtr=currentPtr;
currentPtr=currentPtr->nextPtr;
}
if(previousPtr==NULL)
{
newPtr->nextPtr=strPtr;
strPtr=newPtr;
}
else
{
previousPtr->nextPtr=newPtr;
newPtr->nextPtr=currentPtr;
}
}else printf("%s was not inserted. Insuffiecient memory!",value);
}
Here is my delete function
const char *del(struct listnode* strPtr, char value[])
{
struct listnode *previousPtr, *currentPtr, *tempPtr;
if(strcmp(value, strPtr->data)==0) /*if the first node shall be
deleted*/
{
/*delete node*/
tempPtr=strPtr;
strPtr=strPtr->nextPtr;
free(tempPtr);
return value;
}
else
{
previousPtr=strPtr;
currentPtr=strPtr->nextPtr;
while(currentPtr!=NULL && strcmp(value, currentPtr->data)!=0)
{
previousPtr=currentPtr;
currentPtr=currentPtr->nextPtr;
}
if(currentPtr!=NULL)
{
tempPtr=currentPtr;
previousPtr->nextPtr=currentPtr->nextPtr;
free(tempPtr);
return value;
}
}
return '\0';//daca nu s-a gasit nodul
}
void instructions(void)
{
printf( "Options:\n"
" 1 to insert a name in the list.\n"
" 2 to delete a name from the list.\n"
" 3 to exit.\n" );
}
void printList(struct listnode *currentPtr)
{
if(currentPtr==NULL)
printf("List is empty\n");
else
{
printf("List is:\n");
while(currentPtr!=NULL)
{
printf("%s -->",currentPtr->data);
currentPtr=currentPtr->nextPtr;
}
}
}
int Empty(struct listnode *strPtr)
{
return strPtr == NULL;
}
int main()
{
struct listnode* startPtr;
startPtr=NULL;
int optiune;
char nume[100];
instructions();
printf("->> ");
scanf("%d",&optiune);
Here is the menu
while(optiune!=3)
{
switch(optiune)
{
case 1:
printf("Enter name:");
fflush(stdin);
gets(nume);
insert(startPtr, nume);
printList(startPtr);
break;
case 2:
printf("Search by name to delete from list:");
gets(nume);
if(!Empty(startPtr))
{
if(del(startPtr, nume))
{
printf("%s a fost sters din lista!\n");
printList(startPtr);
}else printf("%s nu a fost gasit!\n",nume);
}else
printf("List is empty!");
break;
case 3:
break;
default:
printf("No such option!\n\n");
instructions();
break;
}
printf("\n->> ");
scanf("%d",&optiune);
}
printf("Execution stopped.\n" );
return EXIT_SUCCESS;
}
I think I got it to work.
First thing I changed in your code was defining your struct as a typdef.
typedef struct{
char data[100];
struct listnode *nextPtr;
}listnode;
This is how I learned and it makes it easier to declare variables of this struct type, since we can just type "listnode" instead of "struct listnode" all the time.
Since you didn't give us the full code, I had to remove some things so I could compile it. As you are just asking why the list remains empty after the "insert" function I think this is fine for you.So here's the "main()" and "printlist()" functions that I used:
void printList(listnode *strPtr){
listnode *currentPtr = malloc(sizeof(listnode));
//Setting the ptr to run the list
currentPtr = strPtr;
if(strPtr == NULL) printf("Fail\n");
//Printing the list,while next is different than NULL keep going
printf("\nListing:\n");
while(currentPtr->data != NULL){
printf("%s\n",currentPtr->data);
currentPtr = currentPtr->nextPtr;
}
}
int main(){
char nume[128];
listnode *startPtr = NULL;//Initializing the fisrt ptr
//Reading the name
printf("Enter name:\n");
scanf("%s",nume);
//Inserting and printing the list
insert(&startPtr,nume);
insert(&startPtr,"Hello");
printList(startPtr);
return 0;
}
Some pretty basic stuff. Now to the main point:
As our friends told us in the comments, in C, the pointer is passed by value. It means that whatever changes you make in the function, it will not modify the startPtr variable in main().
To fix that all he have to do is to add one extra '*' on the function parameters. This means that we are now passing the strPtr argument by reference.
Here's the final function:
void insert(listnode **strPtr,char value[]){
listnode *previousPtr, *currentPtr,*newPtr;
//Allocating the nodes
newPtr = malloc(sizeof(listnode));
currentPtr = malloc(sizeof(listnode));
//Initializing the new node and setting the currentPtr
strcpy(newPtr->data,value);//Copying the name to the new node
newPtr->nextPtr = NULL;
currentPtr = strPtr;
//Previous is NULL
previousPtr = NULL;
if(newPtr != NULL){
//If there's already a node in the list let's find the right location
//For the new one(sorting)
while(currentPtr != NULL && strcmp(currentPtr->data,value) > 0){
previousPtr = currentPtr;
currentPtr = currentPtr->nextPtr;
}
//If previous is NULL than this is the first node,no while iterations
//Note:strPtr is passed by reference,extra '*' needed
if(previousPtr == NULL){
newPtr->nextPtr = *strPtr;
*strPtr = newPtr;
}else{
previousPtr->nextPtr = newPtr;
newPtr->nextPtr = currentPtr;
*strPtr = newPtr;
}
}else{
printf("%s was not inserted. Insuffiecient memory!",value);
}
}
Note that we are also using an extra '*' when setting the newPtr to strPtr.This will modify the actual variable startPtr from main().
From that I hope you can also fix the delete function!
Don't forget to free the memory!
Also, don't forget to comment your code. It's really important to help you and other people to understand it, no matter how easy it might be!
Cheers!
I'm trying to write a program that enqueue, dequeue, delete a chosen number and print the list. I have problems with the dequeue that i think is because of the menu part when you write a number, I've tried to fix it but the it removes the last number and not the first. The print shows the wrong number and when I tried to solve that problem I got the same problem as I had in dequeue. It's sometinhg wrong in delete but i cant figure it out.
I appreciate all the help i can get
edit:
I've changed it a lot and now everything else works except delete. I want delete to find the number i enter and delete it.
queue.c
#include <stdio.h>
#include <stdlib.h>
#include<conio.h>
struct node
{
int info;
struct node *ptr;
int next;
}*first, *last, *temp, *first1;
void enq(int data);
void deq();
void empty();
void display();
void create();
void delete_queue();
int count = 0;
void main()
{
int no, ch;
printf("\n 1 - Enqueue");
printf("\n 2 - Dequeue");
printf("\n 3 - Delete");
printf("\n 4 - Display");
printf("\n 5 - Exit");
create();
while (1)
{
printf("\n Enter choice : ");
scanf_s("%d", &ch);
switch (ch)
{
case 1:
printf("Enter data : ");
scanf_s("%d", &no);
enq(no);
break;
case 2:
deq();
break;
case 3:
printf("Enter data : ");
scanf_s("%d", &no);
delete_queue(no);
case 4:
display();
break;
case 5:
exit(0);
default:
printf("Wrong choice, Please enter correct choice ");
break;
}
}
}
void create()
{
first = last = NULL;
}
void enq(int data)
{
if (last == NULL)
{
last = (struct node *)malloc(1 * sizeof(struct node));
last->ptr = NULL;
last->info = data;
first = last;
}
else
{
temp = (struct node *)malloc(1 * sizeof(struct node));
last->ptr = temp;
temp->info = data;
temp->ptr = NULL;
last = temp;
}
count++;
}
void display()
{
first1 = first;
if ((first1 == NULL) && (last == NULL))
{
printf("Queue is empty");
return;
}
while (first1 != last)
{
printf("%d ", first1->info);
first1 = first1->ptr;
}
if (first1 == last)
printf("%d", first1->info);
}
void deq()
{
first1 = first;
if (first1 == NULL)
{
printf("\n Error: Trying to display elements from empty queue");
return;
}
else
if (first1->ptr != NULL)
{
first1 = first1->ptr;
printf("\n Dequed value : %d", first->info);
free(first);
first = first1;
}
else
{
printf("\n Dequed value : %d", first->info);
free(first);
first = NULL;
last = NULL;
}
count--;
}
void delete_queue()
{
int retval = -1;
if (first)
{
struct node *temp = first;
first = first->next;
if (!first) { last = first; }
retval = temp->next;
free(temp);
}
return retval;
}
void empty()
{
if ((first == NULL) && (last == NULL))
printf("\n Queue empty");
else
printf("Queue not empty");
}
Let me start with a few points of advice about design and style:
I do not recommend this:
typedef struct node {
int data;
struct node *next;
} node;
you are typedefing struct node to node. while it is not illegal, it is confusing. I would recommend
typedef struct _node {
int data;
struct _node *next;
} node;
Additionally, I do not recommend use of global variable with static storage class to keep track of your queue, instead you should create a queue in your main. Use global variables only when you have compelling reasons to do so.
Do remember that when you get rid of your global variable, you will need to rewrite your enqueue dequeue delete etc... functions to take in a queue_c * as parameter (because it wont have access to queueref any more)
Now for the reason that your code is not working properly and #Weather Vane alluded to:
you have a big problem in your delete function.
int delete(int data)
{
int result = 0;
node *curr_ptr; //pointer just created and not initialized
node *prev_ptr; //not initialized
node *temp_ptr; //not initialized
while (curr_ptr != NULL)
//curr_ptr was just created, where is it pointing? fatal error here
{
//inside this block lets imagine curr_ptr is pointing to a valid
//node in the global queue
if (curr_ptr->data == data)
{
result = 1;
if (curr_ptr->next != NULL)
{
temp_ptr = curr_ptr;
//both pointers point to the same thing
destroy_node(temp_ptr);
//now you just destroyed both nodes
prev_ptr->next = curr_ptr->next;
//the first time this block runs prev_ptr is uninitialized
//so prev_ptr->next will most likely seg fault
//this happens for example if you call this function
//for the first time with a long queue
}
else
{
temp_ptr = curr_ptr;
queueref.last = prev_ptr;
prev_ptr->next = NULL;
destroy_node(temp_ptr);
//again you are destroying both curr_ptr and temp_ptr
}
}
curr_ptr = curr_ptr->next;
prev_ptr = prev_ptr->next;
return result;
}
}
Perhaps it would be better if you think edge cases very carefully and rethink some of the logic from scratch. (test edge cases as you go)
When I run these methods My list never grows and I don't know why. The head and tail are always equal. Is there something wrong with my pointers or struct setup? I spent 4 hours on this switching things around and I just can't seem to find why things aren't working unless it's a pointer thing (which I am learning and not good with)..
typedef struct EmployeeStruct
{
char LastName[10];
char FirstName[10];
struct EmployeeStruct *next;
} Employee;
struct EmployeeStruct *head,*tail, *temp;
Employee* hireEmployee(Employee* head, char LastName[10], char FirstName[10])
{
// exit if max number of employees is reached
if(eNum > MAX_EMPLOYEES)
{
printf("Sorry, but you can't hire any more employees right now\n");
return 0;
}
// insert at tail
newHire = head;
while(newHire->next != NULL)
{
newHire = newHire->next;
printf("nope\n");
}
// allocate memory
newHire->next = malloc(sizeof(Employee));
if(newHire == NULL)
{
printf("Memory allocation failed");
return 0;
}
newHire->next = NULL;
// insert values into this node
strcpy(newHire->LastName, LastName );
strcpy(newHire->FirstName, FirstName );
newHire->EmployeeNumber = eNum;
tail = newHire;
//printf("%d\n",newHire->EmployeeNumber);
eNum+=1;
//printf("%d\n",newHire->EmployeeNumber);
return newHire;
}
int main()
{
char choice;
char first[20];
char last[20];
int i = 0;
// allocate memory
head = malloc(sizeof(Employee));
if(head == NULL)
{
printf("Memory allocation failed");
return 0;
}
head->next = tail;
while(TRUE)
{
// prompt user for choice
printf("Please choose from the following options:\n");
printf("a: Hire new employee\nb: Promote employee\nc: Delete employee\nd: Display roster\ne: Exit\n");
scanf("\n%c", &choice);
switch(choice)
{
case 'a':
printf("New employees first name:\n");
scanf("%s", first);
printf("New employees last name:\n");
scanf("%s", last);
tail = hireEmployee(head,last,first);
temp = head;
while(temp->next != NULL)
{
temp = temp->next;
printf("nope\n");
}
temp->next = tail;
tail = temp->next;
printf("A%d: %s %s\n", tail->EmployeeNumber,tail->FirstName,tail->LastName);
tail = tail->next;
printf("A%d: %s %s\n", tail->EmployeeNumber,tail->FirstName,tail->LastName);
tail->next = NULL;
//printEmployees(head);
break;
case 'b':
//TBD
break;
}
}
}
** Works now, it was these four errors:
(newHire == NULL)
(head == NULL)
newHire =newHire->next;
temp->next = tail;
BTW, I always do my homework and attend class, and I was simply stuck on a small piece of a MUCH larger program. So thank you to those who didn't insult me and actually gave useful advice. I truly appreciate it.
Here are your mistakes
newHire->next = malloc(sizeof(Employee));
the return type of malloc is void* so change it to
newHire->next = (EmployeeStruct *)malloc(sizeof(Employee));
if(newHire == NULL)
it will never be NULL change it to
if(newHire->next == NULL)
also change
newHire->next = NULL;
you have to traverse one more time link
newHire=newHire->next;
newHire->next = NULL;
I think the problem is in here
temp->next = tail;
tail = temp->next;
inside your case 'b'
because it making temp->next to its head