Linked List : Adding and removing issues - c

First of all, sorry for my english.
For a project, I have to make a garage management program. There's a linked list of mechanics. I made tho function at the moment : one for adding mechanics (addMec) in this list and one for removing mechanics (remMec).
Here is the addMec function :
void addMec(mechanics* first)
{
mechanics *new = malloc(sizeof(mechanic));
int speciality();
if(first==NULL)
{
return(0);
} else
{
printf("Add mechanic : \n");
// Ask for needed informations.
printf("Employee-Number : ");
scanf("%5d",&new->number);
printf("\nName : ");
scanf("%s",&new->name);
printf("\nFirst Name : ");
scanf("%s",&new->first_name);
new->speciality = speciality();
// Add to end -> new->next = NULL
new->next = NULL;
printf("%d %s %s %d\n",new->number,
new->name, new->first_name, new->speciality);
mechanics *current = first;
while(current->next!=NULL)
{
current = current->next;
}
current->next = new;
}
}
This function doesn't add anything in the list. If I try to debug the program, I have a SIGSEGV message.
function remMec
int remMec(mechanics* first)
{
int numrem, ret = 0;
mechanics *current, *intercale;
printf("Supprimer l'employe numero : ");
scanf("%5d",&numrem);
// On parcoure la liste à la recherche du numero d'employe.
current = first;
while(current->next != NULL)
{
// Nécéssaire si l'élément à supprimer est le premier de la liste.
if(current->number == first->number)
{
if(current->number == numrem && current != NULL)
{
intercale = first;
first = first->next;
free(intercale);
ret = 1;
}
}
if(current->number == numrem)
{
intercale = current->next;
current->next = intercale->next;
free(intercale);
ret = 1;
}
current = current->next;
}
if(ret)
{
return 1;
} else
{
return 0;
}
}
The issue with this function is that it removes the next element of the searched element.
example : in the list :
15264 John Chris 1
12569 Chris John 2
If I try to remove John Chris, it'll remove Chris John
Here's the struct :
typedef struct{
char name[31],first_name[31];
int speciality, number;
struct mechanic *next;
}mechanic;
EDIT : It seems that the SIGSEGV happen when i try to display the list. Here is that function :
void displayList(mechanic *first, int n)
{
int i;
mechanic *courant = malloc(sizeof(mechanic));
current = first;
printf("Mechanics :\n");
for(i = 1; i<n; i++)
{
printf("%5d %s %s",current->number,current->name, current->first_name);
switch(current->speciality)
{
case 1: printf(" Wheels\n");break;
case 2: printf(" Motor\n");break;
case 3: printf(" Carrosserie\n");break;
case 4: printf(" Chassis\n");break;
default: printf(" Maintenance\n");break;
}
current = current->next;
}
}
Main :
int main()
{
int nbMec = 1,i,choise;
int menu();
int remMec(mechanics*);
void afficherListe(mechanics*, int);
void addMec(mechanics*);
mechanics *first, *current, *nextM;
first = malloc(sizeof(mechanics));
current = first;
FILE *fdat, *fdat2;
fdat = fopen("clients.dat","r");
fdat2 = fopen("employe.dat","r");
// Lecture du fichier contenant les mécaniciens
fscanf(fdat2,"%5d",&current->number);
while(!feof(fdat2))
{
fscanf(fdat2,"%s%s%1d",&current->name, &current->first_name, &current->speciality);
nextM = malloc(sizeof(mechanics));
current->next = nextM;
nbMec++;
current = nextM;
fscanf(fdat2,"%5d",&currentM->number);
}
//Finir la liste avec NULL
current = first;
for(i = 1; i<nbMec; i++){
current = current->next;
}
current->next = NULL;
free(nextM);
DisplayList(first,nbMec);
// Redirection en fonction du choix dans le menu
choise = menu();
if(choise == 1)
{
// Ajout d'un mécano
addMec(first);
nbMec++;
displayList(first,nbMec);
} else if (choise == 2)
{
if(remMec(first))
{
printf("Mecanicien efface de la liste.\n");
nbMec--;
} else
{
printf("Impossible.\n");
}
afficherListe(first,nbMec);
} else
{
//Ajout d'un rendez-vous
}
return 0;
}
Here is the employe.dat file :
12345 Ric Hochet 1
13456 Jean Valjean 2
14567 Rick Grimes 3
15007 James Bond 4
16789 Rogge Jacquie 5
example of record :
XXXXX CCCCC CCCCC X
number name first_name speciality
Can you help me ?
Thank you !

I found the solution :
Concerning addMec, thanks to CiaPan.
After these issues, I choose to add a new mechanic at the beginning of the list.
I've also created a list struct, containing the first element.
Here is the correct addMec (Please note that for the project, i've added a rep (reparation) array).:
void addMec(list *list, int number, char name[], char first_name[], int speciality)
{
int i;
mechanics *new = malloc(sizeof(mechanics));
if(list == NULL || new == NULL)
{
exit(EXIT_FAILURE);
}
new->number = number;
strcpy(new->name,name);
strcpy(new->first_name,first_name);
new->speciality = speciality;
for(i = 1; i<=50; i++)
{
new->rep->year=0;
new->rep->day = 0;
new->rep->month = 0;
new->rep->price = 0;
new->rep->emergency = 0;
strcpy(new->rep->brkdwn,"");
}
new->next = list->first;
list->first = new;
list->nbElmt++;
}
Concerning remMec, i searched on a other site, and an user, called pagrette explained me.
With these lines,
intercale = current->next;
current->next = intercale->next;
free(intercale);
I just free the next element
Thank you for helping !

Your first function begins like this:
void addMec(mechanics* first)
{
mechanics *new = malloc(sizeof(mechanic));
int speciality();
if(first==NULL)
{
return(0);
} else
{
......
......
THIS WILL NOT COMPILE! First because of return with a value from a void function, second for an undefined type name.
And even if it did, it would not make any sense. First you allocate a block of memory and store the pointer in the new variable. Then you test if first is NULL and you return from the function if so.
Look carefully: you return from the function. So you do not input any data for the new variable and do not append it to the list. That means your program can not build any list from the user's input if it is not filled from the file before.
Additionally, when you return from the function, all the local, automatic variables are lost. With the new among them. That means you no longer have access to the just allocated block—it is lost. You allocated some memory but can not utilize it in any way. That's what we call a memory leak.
To make the function more readable (and easier to further development) I'd split it into two parts: one to create a new object and put it into the list and a subroutine to fill it with the user input:
void inputMec(mechanic *mec)
{
int speciality();
printf("Add mechanic : \n");
// Ask for needed informations.
printf("Employee-Number : ");
scanf("%5d", & mec->number);
printf("\nName : ");
scanf("%s", & mec->name);
printf("\nFirst Name : ");
scanf("%s", & mec->first_name);
mec->speciality = speciality();
}
void addMec(mechanic* first)
{
if(first != NULL) // only if the list's head exists
{
mechanic *new = malloc(sizeof(mechanic));
if(new != NULL) // a new object created sucessfully
{
inputMec(new);
printf("%d %s %s %d\n",new->number,
new->name, new->first_name, new->speciality);
// find the last item in the list
mechanic *last = first;
while(last->next != NULL) // still not the last one?
{
last = last->next; // step forward
}
last->next = new; // append after the last
new->next = NULL; // terminate the list
}
}
}
If the ordering in the list is not important (as it seems from your code), then you can easier add the new item at the beginning of the list:
// insert the item just after the list's head
new->next = first->next; // append the list after the new item
first->next = new; // link the new item to the head
In a real programming task you would have to consider also restricting and validating input, both for internal limitations (are strings non-empty? aren't they too long? is the speciality value in the dictionary range?) and for external consistency (are employees' identifiers distinct? are their name+first_name pairs distinct?).
In case of internal inconsistency you might ask for correct data, and loop reading input until it is correct, or abandon input operation; in the latter case the inputMec routine should return some status. Then the caller routine addMec should test the status to decide whether insert a new item into a list if it is correct, or free() it in case of input failure.
In case of external conflicts you might print appropriate message, retain temporarily the new item and iterate reading input to obtain non-conflicting data or you may abandon the operation, free() the object and return to the main menu, where the user can enter adding mechanics again.

Related

Delete elements from linked list

The function not working properly it's deleating only the id_capt and changing the value of another to zero...
Besides I want to do verification that the sensor does belong to the list but it's not working
void suppression_capt(Liste* liste)//id donner par utilisateur a modifier
{
float new_longitude,new_latitude;//vals a modifier
char id_capt_user[10];
Element *courant = liste->premier;
Element *precedent =courant;
printf("donner id_capt= ");
scanf("%s",id_capt_user);
while(courant != NULL)
{
if(strcmp(courant->capt.id_capt,id_capt_user)==0)
{
precedent=courant->suivant;
free(courant);
}
courant=courant->suivant;
}
printf("\n");
}
Besides I want to do verification that the sensor does belong to the list but it's not working
/*do
{
printf("donner id_capt= ");
scanf("%s",id_capt_user); //verification du capteur
courant=courant->suivant;
}while(strcmp(courant->capt.id_capt,id_capt_user)!=0);*/
and here is the struct that I used
typedef struct//valeur d'une cellule/noeud
{
char id_capt[10];
float longitude;
float latitude;
}capt_hum;
typedef struct//liste chainee
{
capt_hum capt;
struct Element* suivant;
struct Element* precedent;
}Element;
You should note that you are accessing a pointer which you have already freed
if(strcmp(courant->capt.id_capt,id_capt_user)==0)
{
precedent=courant->suivant;
free(courant);
}
courant=courant->suivant;
As for deleting an element from a linked list freeing it is not enough as you need to update the element’s neighbors as well.
Say you have a list as follows:
A <-> B <-> C
And you wish to remove B, you will also need to update A and C to point to each other
A <-> C
if(strcmp(courant->capt.id_capt,id_capt_user)==0)
{
temp = courant->suivant;
precedent=courant->precedent;
free(courant);
precedent->suivant = temp;
temp->precedent = precedent;
courant = precedent; //perhaps replace with break
}
courant=courant->suivant;
With this implementation you will iterate the entire list an remove any node that contains the string you’ve entered.
You could replace the commented line with “break” if you wish to stop seeking once you’ve found the node to delete.
You should add some check for the cases where the node to remove is either the first or the last so you wont accidentally try to assign them when the pointers are NULL or garbage.
after looking and trying because I'm still new to doubly linked list
this program worked
void supprimer_capt(Liste **list) {
Element* tmp = *list;
Element* prev = NULL;
char id_capt_user[10];
printf("donner id_capt= ");
scanf("%s",id_capt_user);
while (tmp != NULL)
{
if (strcmp(tmp->capt.id_capt,id_capt_user)==0)
{
if (prev == NULL)
{
tmp = tmp->suivant;
free(*list);
*list = tmp;
} else {
prev->suivant = tmp->suivant;
free(tmp);
tmp = prev->suivant;
}
} else {
prev = tmp;
tmp = tmp->suivant;
}
}
}
I know I there must be two pointers prev and next and thanx to this function I have a better understanding and the link sent by Mr.Roberet

So im trying to make a c program with a menu that adds/subtracts classes from a linked list... why does this not work

problem is occuring "current = head;", "error: cannot convert 'course*' to 'main()::node*' in assignment"
example run should look like:
What courses would you like to do?
Add Course
Drop Course
Print Schedule
Exit
3
You aren't currently taking any courses.
What courses would you like to do?
Add Course
Drop Course
Print Schedule
Exit
1
What course name would you like to add?
Intro_to_C
What course number would you like to add?
COP3223C
Added!
What courses would you like to do?
Add Course
Drop Course
Print Schedule
Exit
1
What course name would you like to add?
Computer_Science_1
What course number would you like to add?
COP3502C
Added!
What courses would you like to do?
Add Course
Drop Course
Print Schedule
Exit
3
Course Schedule:
COP3223C - Intro_to_C
COP3502C - Computer Science_1
What courses would you like to do?
Add Course
Drop Course
Print Schedule
Exit
1
What course name would you like to add?
Concepts_in_Computer_Science
What course number would you like to add?
COP2500C
Added!
What courses would you like to do?
Add Course
Drop Course
Print Schedule
Exit
3
Course Schedule:
COP2500C - Concepts_in_Computer_Science
COP3223C - Intro_to_C
COP3502C - Computer Science_1
What courses would you like to do?
Add Course
Drop Course
Print Schedule
Exit
2
What course code would you like to drop?
COP2100C
This course is not in your schedule.
What courses would you like to do?
Add Course
Drop Course
Print Schedule
Exit
2
What course code would you like to drop?
COP3223C
Course has been removed.
What courses would you like to do?
Add Course
Drop Course
Print Schedule
Exit
3
Course Schedule:
COP2500C - Concepts_in_Computer_Science
COP3502C - Computer Science_1
What courses would you like to do?
Add Course
Drop Course
Print Schedule
Exit
4
Done!
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
//linked list of structs
struct course {
char name[31], number[11];
struct course *next;
};
//prints the list
void printList(struct course *h) {
struct course *temp = h;
int num = 1;
while (temp != NULL) {
printf("%d. %s - %s\n", num, temp->number, temp->name);
temp = temp->next;
}
}
int contains(struct course *h, char code[11]) {
struct course *temp = h;
while (temp != NULL) {
if (strcmp(temp->number, code)) {
return 1;
}
temp = temp->next;
}
return 0;
}
int Menu() {
printf("What courses would you like to do?\n1. Add Course\n2. Drop Course\n3. Print Schedule\n4. Exit\n");
int value;
scanf("%d", &value);
return value;
}
int main() {
struct course *head = NULL;
struct node *current = NULL;
int option = -1;
while (option != 4) {
option = Menu();
if (option == 1) {
//Add new course
struct course *new_course = (struct course *) malloc(sizeof(struct course));
printf("What course name would you like to add?\n");
scanf("%s", new_course->name);
printf("What course number would ypou like to add?\n");
scanf("%s", new_course->number);
new_course->next = NULL;
if (head == NULL) {
head = new_course;
} else if (contains(head, new_course->number) == 1) {
printf("Course has already been added.\n");
} else {
int flag = 0;
if (strcmp(head->number, new_course->number) > 0) {
new_course->next = head;
head = new_course;
flag = 1;
}
current = head;
while (current->next != NULL && flag == 0) {
if (strcmp(current->next->number, new_course->number) > 0) {
new_course->next = current->next;
current->next = new_course;
flag = 1;
break;
}
current = current->next;
}
// inserts at the end;
if (flag == 0) {
current->next = new_course;
}
}
} else if (option == 2) {
//Remove course
char remove[11];
int flag = 0;
printf("What element would you like to delete?\n");
scanf("%s", remove);
while (head != NULL && strcmp(head->number, remove) == 0) {
head = head->next;
flag = 1;
}
current = head;
while (current != NULL && current->next != NULL) {
if (strcmp(current->next->number, remove) == 0) {
current->next = current->next->next;
flag = 1;
} else {
current = current->next;
}
}
if (flag == 0) {
printf("This course is not on the schedule.\n");
} else {
printf("The course has been deleted.");
}
} else if (option == 3) {
//Print out schedule
printList(head);
}
return 0;
}
The variable head is of type struct course *, whereas the variable current is of type struct node *. Since they are of different type, you cannot assign one to the other.
You probably want to make the pointer current of type struct course * instead. So you should change the line
struct node *current = NULL;
to:
struct course *current = NULL;

Program updates Linked List

I am trying to create a linked list with names, for example:
Tom -> David -> John...
In my main function, I have a switch menu where the program asks if you want to create a new list or exit.
When the user choose 1, the program calls insertIntoLinkedList(name, &head) function where the user can add name(s) or type "end" to exit.
Everything works fine, however if the user enter end and choose option 1 again, the program creates a new linked list whereas I want to add names to an existing list.
Can someone please help me to figure out my problem? Thank you for your time.
EDIT
Here is my source code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define NAME_SIZE 30
#define EXIT "end"
// Node structure
struct node {
char name[NAME_SIZE];
struct node *next;
};
typedef struct node Node;
typedef struct node* NodePointer;
int userChoice(void);
void insertIntoLinkedList(char [], NodePointer *);
void displayNames(NodePointer);
int nodeCounter = 0;
int main(void) {
int choice = 99;
do {
printf("\n--- MENU ---\n\n");
printf("1.\tCreate a new friend list\n");
printf("2.\tExit o_O");
printf("\n\n------------\n");
printf("Go to:\t");
choice = userChoice();
switch (choice) {
case 1: {
char name[NAME_SIZE] = "";
NodePointer head = NULL;
while(0 != strcmp(name, EXIT)){
printf("Enter new friend name or \"%s\" to return back to the main menu: ", EXIT);
scanf("%s", name);
if(0 != strcmp(name, EXIT)){
insertIntoLinkedList(name, &head);
displayNames(head);
}
}
displayNames(head);
break;
}
case 2: {
printf("\n\nYou have %d node(s) in your linked list. Have a great day.\n\n", nodeCounter);
break;
}
default:
printf("There is no such option. Please choose one of the option from 1 to 2.\n");
}
} while(choice != 2);
return 0;
}
int userChoice() {
int num;
scanf("%d", &num);
return num;
}
void insertIntoLinkedList(char word[], NodePointer *head){
NodePointer newNode = NULL;
NodePointer previous = NULL;
NodePointer current = *head;
newNode = malloc(sizeof(Node));
if(NULL != newNode){
strcpy(newNode -> name, word);
while(NULL != current && strcmp(word, current -> name) > 0){
previous = current;
current = current -> next;
}
if(NULL == previous){
newNode -> next = current;
*head = newNode;
} else {
previous -> next = newNode;
newNode -> next = current;
}
}
}
void displayNames(NodePointer current) {
nodeCounter = 0;
if(NULL == current){
printf("Friend list is empty... I am sorry :(\n\n");
return;
} else {
printf("\nCurrent friend list: ");
while(NULL != current){
nodeCounter++;
printf("%s → ", current -> name);
current = current -> next;
}
printf("\nNumber of friends in your current list:\t%d\n\n", nodeCounter);
}
}
Well U Can Just Declare A New Function For That. Because Every Time You Call This Function Head Is Re-declared .
E.g case 3:printf("\nEnter A New Friend Name:\n");
scanf("%s",name);
insertIntoLinkedList(name, &head);
displayNames(head);
break;
Everything works fine, however if the user enter end and choose option 1 again, the program creates a new linked list whereas I want to add names to an existing list.
The issue is that you have to declare the pointer which sores the head of the list outside the while loop.
NodePointer head = NULL;
do {
....
switch (choice) {
case 1: {
char name[NAME_SIZE] = "";
while(0 != strcmp(name, EXIT)){
....
}
....
}
} while(choice != 2);
Note you have declared the variable in the block scope inside the case. See Scope rules in C.
At the end of the scope the variable is not longer accessible and its content is lost. When you "reach" the code the next time, the you get a completely new initialized variable.

Bubble Sort in linked lists C

any idea why does my program crash after showing the right result? (i.e. i insert 6 2 4 3 he returns 2 3 4 6 but the console crashes right after!)
The main idea is to sort a linked list after the user giving the integers. I tried to solve it like if it was a bubble sort but for some reason it's not 100% operational. sorry for the portuguese comments!
#define ITEM_TYPE int
typedef struct lnode* List;
typedef struct lnode{
ITEM_TYPE info;
List next;
}List_node;
void ordenalista(List lista){
int contador = 0, i;
/* lista é uma lista recebida */
List head = lista; /* termos sempre disponível o início da lista*/
List actual = NULL; /*lista vazia, ou nó */
List temp = NULL;
if(head == NULL || head->next == NULL){ /* caso de lista vazia ou so com 1 elemento*/
printf("A lista esta vazia ou tem apenas um elemento");
return 0;
}
while(head != NULL){ /* contar quantos elementos tem a lista*/
contador++;
head = head->next;
printf("%d \n", contador);
}
for(i=0; i<contador; i++){ /* percorrer todos os elementos da lista*/
while(head->next != NULL){ /* enquanto não chegarmos ao final da lista*/
if(head->info > head->next->info){ /* se o valor do atual for maior que o valor do seguinte*/
temp = head->next;
head->next = head->next->next; /* não precisamos de usar actual->data, apenas precisamos de mudar os ponteiros*/
temp->next = head;
}
}
}
}
void ex213(){
int numero;
List lista;
lista = create_list();
while((scanf("%d",&numero)) == 1){ /* lê da esquerda para a direita. SCANF DÁ 1 SE INSERIR INTEIRO, 0 CASO CONTRÁRIO */
insertwithoutorder(lista, numero);
}
ordenalista(lista);
printlist(lista);
}
void insertwithoutorder(List lista, ITEM_TYPE it){
List no;
List ant, inutil;
no = (List)malloc(sizeof(List_node));
if (no != NULL) {
no->info = it;
searchwithoutorder(lista, it, &ant, &inutil);
/*while(ant->next != NULL){
ant = ant->next;
}*/
no->next = NULL;
ant->next = no;
}
}
void searchwithoutorder(List lista, ITEM_TYPE chave, List *ant, List*actual){
*ant = lista; *actual = lista->next;
while ((*actual) != NULL){
*ant = *actual;
*actual = (*actual)->next;
}
if ((*actual) != NULL && (*actual)->info != chave)
*actual = NULL; /* Se elemento não encontrado*/
}
void printlist(List lista){
List l = lista->next; /* Salta o header */
while (l){
printf("%d ", l->info);
l=l->next;
}
}
int main(){
ex213();
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#define ITEM_TYPE int
typedef struct lnode* List;
typedef struct lnode{
ITEM_TYPE info;
List next;
} List_node;
List create_list(void){
//top node unused
return calloc(1, sizeof(List_node));//note : might NULL != 0
}
List lastNode(List lista){
while (lista->next != NULL){
lista = lista->next;
}
return lista;
}
void insertwithoutorder(List lista, ITEM_TYPE it){
List no, ant;
no = create_list();
if (no != NULL) {
no->info = it;
no->next = NULL;
ant = lastNode(lista);
ant->next = no;
} else {
printf("failed to create a new node.\n");
}
}
void ordenalista(List lista){
List head = lista;
List actual, neighbor, sentinel = NULL;
if(head->next == NULL){
printf("A lista esta vazia\n");
return ;
}
while(head->next != sentinel){
actual = head->next;
neighbor= actual->next;
while(neighbor != sentinel){
if(actual->info > neighbor->info){
ITEM_TYPE temp = actual->info;
actual->info = neighbor->info;
neighbor->info = temp;
}
actual = neighbor;
neighbor= neighbor->next;
}
sentinel = actual;
}
}
void printlist(List lista){
List l = lista->next;
while (l){
printf("%d ", l->info);
l=l->next;
}
puts("");
}
void ex213(void){
int numero;
List lista = create_list();
while((scanf("%d", &numero)) == 1){
insertwithoutorder(lista, numero);
}
//printlist(lista);
ordenalista(lista);
printlist(lista);
//deallocate ?
}
int main(void){
ex213();
return 0;
}
The crash must be occurring in the function (now) named printlist(), as your program does nothing else after that function returns.
I don't see anything inherently wrong with printlist(), but it does depend on the list being in a valid state. In particular, my best guess at why the program fails where it does would be that the next pointer of the last list element contains a junk value instead of the expected NULL. You could verify that by running the program in a debugger.
How, then, might the list be corrupted?
Well, your insertion function looks ok. The searchwithoutorder() function on which it relies doesn't actually do what its name says, but it does do what insertwithoutorder() needs it to do.
That leaves the sort function, ordenalista(), and here I'm a bit flumoxed. I don't see how the version you posted could do any sorting at all. You have a while loop like so: while(head != NULL){...}, whithout any break or goto inside, so when control passes beyond this loop it must be that head == NULL. Then, without modifying the value of head, you go into a loop nest like this:
for(i=0; i<contador; i++) { /* percorrer todos os elementos da lista*/
while(head->next != NULL) { /* enquanto não chegarmos ao final da lista*/
...
}
}
But head is NULL at that point, so dereferecing it produces undefined behavior. If that behavior were not itself a crash, then correctly guessing and dereferencing the pointer you meant is an extremely unlikely alternative. Moreover, you do not modify head in the body of the loop, so it remains NULL. There are other problems with this loop, too.
As if all that weren't enough, there is also no good way for your sort function to change which element is at the head of the list -- at least none that would be effective for the caller.
So basically, I don't believe you have accurately described the problem. It must be either that the failure behavior you observed is different from what you described, or that the code you presented does not correspond to the program whose misbehavior you described.
When asking the user for data, it is useful to let the user know what you are asking for and how to handle/terminate any requests for input. A blinking cursor on a blank line tells the user nothing. (even when it is testing for you, it can help prevent an inadvertent keystroke of the wrong type). For example your ex213 function leaves a blinking cursor on a blank line leaving the user wondering "Is the program hung?" "Did it encounter a race condition?" etc.. When asking the user for linked-list data, a simple additional line or two of guidance can really help. Example:
void ex213 (void)
{
int numero;
List lista = create_list ();
printf ("\nEnter a number to add to the list [CTRL+D] when done:\n\n");
while (printf (" data: ") && (scanf ("%d", &numero)) == 1) {
insertwithoutorder (lista, numero);
}
ordenalista (lista);
printf ("\n\nThe ordered linked-list is:\n\n");
printlist (lista);
printf ("\n");
//deallocate ?
}
Output
$ ./bin/ll_single_sort
Enter a number to add to the list [CTRL+D] when done:
data: 2
data: 8
data: 20
data: 6
data: 9
data: 1
data:
The ordered linked-list is:
1 2 6 8 9 20
Adding that to the answer provided by BLUEPIXY provides the results you were looking for.

Issue when comparing a value in a linked list in C

I'm working on a "simple" program in C, where we create a linked list with a structure that acts as a movie which stores, a title, year it was made, rating (1-5), and a pointer to the next node. We are not allowed to add anything to this structure, or define functions.
On top of that, we (for some reason) are required to write the entire linked list in the body of main(), so that adds a certain layer of spaghetti to the problem. Anyways, in this program, we are supposed to have the user enter either 'U' for update or 'S' for search for a movie. The update does what you would expect, you enter a title, year, rating. From this, we are supposed to insert the node at the end of the linked list.
Our search should iterate through this linked list and if it finds a match, should print out the movie, title, and year.
Although the update part of my code works, I can't seem to get search to work. I'm using a movie struct called temp, that starts at head and iterates through the list in an attempt to find the movie. After running some tests through printf, I'm finding that temp is just a null node no matter what, and no matter what movies I enter.
I am assuming this has something to do with the way I'm calling malloc? Or something to do with not assigning nodes correctly? I'm honestly not sure, and unfortunately, the lab's TA had no idea what was wrong either D:
Here is my code:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
struct movie_node {
char title[250];
int year;
unsigned char rating;
struct movie_node *next;
};
typedef struct movie_node movie;
int main() {
// variables
int loop = 1;
movie *head = NULL; // represents first
movie *current; // represents the last node
movie *temp; // used for traversing the linked list
head = malloc(sizeof(movie));
int amountOfMovies = 0; // increment after each addition
char choice; // either 'u' (update) or 's' (search)
// ask user for input
while(loop) {
printf("%d Movie(s) in the database. Update or search (U/S): ", amountOfMovies);
scanf(" %c", &choice);
/* CHOICE 1, UPDATE */
if(choice == 'U') {
// case 1, head is null, we must create a new node
if(head == NULL) {
// get input
printf("Name of the movie: ");
scanf(" %[^\n]%*c", head->title);
printf("Year: ");
scanf("%d", &head->year);
printf("Rating: ");
scanf("%hhu", &head->rating);
head->next = NULL;
head = current; // set head to point to current
} else {
current = head;
// need to find where current is
while(current != NULL) {
current = current->next;
} // end while
// current is now at the null position, indicating empty node
current = malloc(sizeof(movie)); // allocate mem
// get user input
printf("Name of the movie: ");
scanf(" %[^\n]%*c", current->title);
printf("Year: ");
scanf("%d", &current->year);
printf("Rating: ");
scanf("%hhu", &current->rating);
current->next = NULL;
} // end else
// output movie
printf("Movie \"%s\" is added to the database.\n", current->title);
amountOfMovies++; // increment amount of movies in database
} else if(choice == 'S') {
/* CHOICE 2, SEARCH */
// temp string
char tempTitle[250];
// flag to let us know if we found something
bool found = false;
// temp linked list to traverse
temp = head;
temp = malloc(sizeof(movie));
// ask user for input
printf("Name of movie: ");
scanf(" %[^\n]%*c", tempTitle);
printf("NAME OF MOVIE IN HEAD: %s\n", temp->title); // test, take out later
while(temp != NULL) {
printf("NAME OF CURRENT MOVIE TO COMPARE TO: %s\n", temp->title); // test
if(strcmp(temp->title, tempTitle) == 0) {
// match
printf("Year: %d\n", temp->year);
printf("Rating: %hhu\n", temp->rating);
found = true;
break;
} else { // no match so far
temp = temp->next;
printf("HAVEN'T FOUND MATCH, NEXT TITLE TO CHECK IS: %s\n", temp->title); // test print
found = false;
} // end else
} // end while
if(found == false) { // no match confirmed
printf("Movie \"%s\" does not exist in the database.\n", tempTitle);
}
} else { // choice is invalid
loop = 0; // exit
} // end if-else
} // end while
// free all the nodes
return 0;
}
Note: the only thing I haven't implemented yet is freeing the memory.. which I'm not a hundred percent sure how I should accomplish it.
Any help is greatly appreciated..
The problem is with your malloc() calls. First you do:
movie *head = NULL;
// ...
head = malloc(sizeof(movie));
This means that head is no longer null and you won't be able to insert first movie the way you want to - move that malloc() somewhere else.
Secondly, few lines of code below, you do:
current = head; // <- this is OK
// ...
current = malloc(sizeof(movie)); // allocate mem <- this is NOT OK, for the same reason as before
Also, you can read titles of the movies like that: scanf("%249s", head->title).
Let me know if you know how to go from there.
Apart from the problems in your code, there is another problem: the lab's TA had no idea what was wrong either.
sample to fix
movie *new_node(void){//aggregate the creation of a new node
movie *node = malloc(sizeof(*node));//error check omit
printf("Name of the movie: ");
scanf(" %249[^\n]%*c", node->title);
printf("Year: ");
scanf("%d", &node->year);
printf("Rating: ");
scanf("%hhu", &node->rating);
node->next = NULL;
return node;
}
int main() {
int loop = 1;
movie *head = NULL;
movie *current;
movie *temp;
//head = malloc(sizeof(movie));//"if(head == NULL) {" don't work
int amountOfMovies = 0;
char choice;
while(loop) {
printf("%d Movie(s) in the database. Update or search (U/S): ", amountOfMovies);
scanf(" %c", &choice);
if(choice == 'U') {
if(head == NULL) {
current = head = new_node();//need set to current
} else {
current = head;
while(current->next != NULL) {//"current != NULL" can't link
current = current->next;
}
current = current->next = new_node();
}
printf("Movie \"%s\" is added to the database.\n", current->title);
amountOfMovies++;
} else if(choice == 'S') {
char tempTitle[250];
bool found = false;//need <stdbool.h>
temp = head;
//temp = malloc(sizeof(movie));//Unnecessary
printf("Name of movie: ");
scanf(" %249[^\n]%*c", tempTitle);
//printf("NAME OF MOVIE IN HEAD: %s\n", temp->title);
while(temp != NULL) {
//printf("NAME OF CURRENT MOVIE TO COMPARE TO: %s\n", temp->title);
if(strcmp(temp->title, tempTitle) == 0) {
printf("Year: %d\n", temp->year);
printf("Rating: %hhu\n", temp->rating);
found = true;
break;
} else {
temp = temp->next;
printf("HAVEN'T FOUND MATCH, NEXT TITLE TO CHECK IS: %s\n", temp->title);
//found = false;//Unnecessary
}
}
if(found == false) {
printf("Movie \"%s\" does not exist in the database.\n", tempTitle);
}
} else {
loop = 0;
}
}
// free all the nodes
return 0;
}

Resources