Bubble Sort in linked lists C - 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.

Related

insert one element among others in a list language C

Hi I'm trying to insert an element inside a list following a certain order(I have to add a equilateral triangle). When I try to use the code I can insert data(triangle measurements) but when I try to print list nothing appear :/.So I think that I wrote bad something in "inserisciPerPerimetro". Some word is written in italian and this is only a part of the code(two functions to add a triangle in my list),if u have to see also other parts let me know.
Thanks all!
This is my code:
typedef struct punto {
int x;
int y;
} PUNTO;
typedef struct triangolo {
PUNTO v;
int lato;
} TRIANGOLO;
typedef struct nodo {
TRIANGOLO t;
struct nodo *next;
} NODO;
int perimetro(TRIANGOLO t) {
return t.lato*3;
}
void stampaTriangolo(TRIANGOLO t) {
printf("Il triangolo ha il lato uguale a: %d con un perimetro pari a %d, il vertice in alto ha coordinate (%d,%d)\n",
t.lato, perimetro(t),t.v.x,t.v.y);
}
void stampaLista(NODO *head) {
if(head->next==NULL) {
printf("Lista vuota!\n");
} else {
while(head->next != NULL) {
head = head->next;
stampaTriangolo(head->t);
}
}
}
TRIANGOLO creaTriangolo() {
TRIANGOLO nuovo;
printf("Inserisci il lato del nuovo triangolo: ");
scanf("%d", &nuovo.lato);
printf("\n");
printf("Inserisci le coordinate del vertice con y maggiore:\n");
printf("x: ");
scanf("%d",&nuovo.v.x);
printf("\n");
printf("y: ");
scanf("%d",&nuovo.v.y);
printf("\n");
return nuovo;
}
void inserisciPerPerimetro(NODO *head) {
NODO* nuovoNodo;
nuovoNodo = malloc(sizeof(NODO));
nuovoNodo->t = creaTriangolo();
nuovoNodo->next = NULL;
if(head==NULL) {
head = nuovoNodo;
} else {
//Ordinamento per perimetro crescente
while(head->next != NULL)
if(perimetro(nuovoNodo->t) < perimetro(head->t)) {
nuovoNodo->next = head->next;
head->next = nuovoNodo;
} else {
head = head->next;
}
printf("Inserimento effettuato!\n");
}
}
int main() {
/* inizializza la lista */
NODO *head = malloc(sizeof(NODO));
head->next = NULL;
int risposta = -1; // per interazione con utente
while(risposta != 0) {
/* richiedi un'operazione all'utente */
printf("Che operazione vuoi svolgere?\n");
printf("1 -> Inserisci un triangolo nella lista ordinata secondo il perimetro crescente\n");
printf("2 -> Cancella il triangolo in testa alla lista\n");
printf("3 -> Visualizza la lista di triangoli\n");
printf("0 -> Termina il programma\n");
scanf("%d", &risposta);
/* gestisci le operazioni dell'utente */
if(risposta==1) {
inserisciPerPerimetro(head);
}
//else if(risposta==2)
//lista = cancellazione(lista);
else if(risposta==3) {
stampaLista(head);
}
else if(risposta==0) {
printf("Finito!\n\n");
}
else {
printf("Selezione non valida!\n\n");
}
}
}
I'm going to assume that you're holding a NODO* in some outer scope, and calling inserisciPerPerimetro on that pointer.
If you consider just the first time you do this (when the list is empty), your code will do head = nuovoNodo; so you will be putting the address of the newly allocated node into the pointer head. But this is a local copy of the parameter that you passed to the function, so the pointer in the outer scope will remain unchanged (and its value will be NULL). The next time you call the function, the list will still be empty.
One possible way to solve this is by passing a pointer to your head pointer to the function, so that the value of the pointer in the outer scope can be modified.
That is, the function should be defined like this:
void inserisciPerPerimetro(NODO **head)
Inside the function, modifications to head should be implemented as:
*head = nuovoNodo;
And in the outer scope you should have something like:
/*...*/
NODO* head = NULL;
inserisciPerPerimetro(&head);
/*...*/
EDIT:
Note that you are somewhat inconsistent with the node allocations: The head node is allocated in the outer scope (does it ever get its own triangle?), and all the others are allocated within the function. On the other hand, you check inside the function whether head is NULL - how can that happen if you allocate the list head in the outer scope?
Secondly, note that in the first call to inserisciPerPerimetro the while loop will be skipped because head->next is always NULL. This is because you don't handle the case where the new node needs to be inserted after the last node in the list.

C list of a list

im having a problem, im trying to make a list of a list where inicioC refers to the first node of clients, and every node of clients will have a list of rentals, referred as inicioA. The thing is, i dont know how to save the first pointer of the rentals, like, the first node of clients will only be saved one time, but wont the first node of every rental be different?
this are the structs:
typedef struct _aluguer
{
int id, estado, diaI, mesI, anoI, diaE, mesE, anoE;
struct _aluguer *prox;
}aluguer, *pAluguer;
typedef struct _registo
{
int nif,nalu;
char nome[100];
struct _registo *prox;
pAluguer *inicioA;
}registo, *pRegisto;
and this is the code I use to extract the info from a file into the list of lists
pRegisto iniC(pRegisto inicioC, pAluguer inicioA)
{
FILE *c;
int j, nif, nalu, l=0;
char nome[100];
c = fopen("clientes.txt", "r"); // abrir ficheiro
if(c == NULL)
{
printf("Erro ao abrir ficheiro %s", "clientes.txt");
exit(0);
}
while(fscanf(c, "%d %d %s", &nif, &nalu, nome) == 3) //format of info
{
pRegisto novoC = malloc(sizeof(registo));
if(novoC == NULL)
{
printf("erro alocacao memoria\n");
return inicioC;
}
novoC -> prox = NULL;
pAluguer inicioA = NULL;
pRegisto aux = inicioC;
pRegisto p = NULL;
novoC->nif=nif;
novoC->nalu=nalu;
strcpy(novoC->nome, nome);
while(aux != NULL)
{
p = aux;
aux = aux->prox;
}
if( aux == inicioC)
{
inicioC=novoC;
}
else
{
p->prox = novoC;
}
for(j=0; j<novoC->nalu; j++) // repeat is equal to the number of rentals
{
l++;
pAluguer novoA = malloc(sizeof(aluguer));
if(novoA == NULL)
{
printf("erro alocacao memoria\n");
return inicioC;
}
novoA -> prox = NULL;
pAluguer aux = inicioA;
pAluguer p = NULL;
fscanf(c, "%d %d", &(novoA->id), &(novoA->estado));
if(novoA->estado == 0)
{
fscanf(c, " %d %d %d", &(novoA->diaI), &(novoA->mesI), &(novoA->anoI));
}
else
{
fscanf(c, " %d %d %d %d %d %d", &(novoA->diaI), &(novoA->mesI), &(novoA->anoI), &(novoA->diaE), &(novoA->mesE), &(novoA->anoE));
}
while(aux != NULL)
{
p = aux;
aux = aux->prox;
}
if( aux == inicioA)
{
inicioA=novoA;
}
else
{
p->prox = novoA;
}
}
}
fclose(c);
return inicioC;
}
Arraylist (Array of pointers in C) is good choice for implementing list of list but as you are forced to do in this way, I am showing a Simple method how you can develop list of list in C.
It is very simple,suppose you have a list of 3 numbers: 1,2,3 i.e list_1,list of 2 numbers: 5,6 i.e list_2.Now these list_1 and list_2 can be linked in a similar way as the numbers in list linked above.Look at this scenario
list_1:1->2->3->Null
list_2:5->6->Null
list_of_list : list_1->list_2->Null i.e. (1->2->3->Null) -> (5->6->Null) -> Null
Here is a Sample program to insert list of ints in Last:
#include <stdio.h>
#include <stdlib.h>
// for list of Intergers
struct node{
int Data;
struct node *next;
};
// this is for list of nodes i.e list of lists
struct list{
struct node *start;
struct list *listnext;
};
// insert integers in list
void insertNode(struct node **head ,int data){
struct node *temp,*current;
temp=malloc(sizeof(struct node));
temp->Data=data;
temp->next=NULL;
if((*head)==NULL){
(*head)=temp;
}
else{
current=(*head);
while(current->next!=NULL){
current=current->next;
}
current->next=temp;
}
}
// insert lists of integers in a list
void insertList(struct list **Listhead,struct node *head){
struct list *temp,*current;
temp=malloc(sizeof(struct list));
temp->start=head;
temp->listnext=NULL;
if((*Listhead)==NULL){
(*Listhead)=temp;
}
else{
current=(*Listhead);
while(current->listnext!=NULL){
current=current->listnext;
}
current->listnext=temp;
}
}
// Show all the list with their data
void show(struct list *Listhead){
int i=1;
struct list *current;
struct node *currentlist;
current=Listhead;
while(current!=NULL){
currentlist=current->start;
printf("List %d: ",i);
while(currentlist!=NULL){
printf("%d ",currentlist->Data);
currentlist=currentlist->next;
}
i++;
printf("\n");
current=current->listnext;
}
}
int main(){
struct node *head1=NULL,*head2=NULL,*head3=NULL; // 3 lists of integers
struct list *Listhead=NULL; // Listhead will be the head of lists of list
insertNode(&head1,20); // inserting in first list
insertNode(&head1,13);
insertNode(&head1,22);
insertNode(&head1,18);
insertNode(&head2,42); // inserting in second list
insertNode(&head2,15);
insertNode(&head3,12); // inserting in third list
insertNode(&head3,14);
insertNode(&head3,28);
insertList(&Listhead,head1); // inserting lists in list
insertList(&Listhead,head2);
insertList(&Listhead,head3);
show(Listhead);
}
Output for this Program:
List 1: 20 13 22 18
List 2: 42 15
List 3: 12 14 28
I hope you got the point.

Linked List : Adding and removing issues

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.

Linked List C with pointers

I'm trying to push an element in a linked list, then print it but the problem received is: segmentation fault.
I've created struct libro, cella and lista. Then in function insHead i've tried to insert an element to the list, taking input from user and then in function printList (and here i've got the segmentation fault) i would print list's elements.
The code is:
typedef struct libro {
char titolo[64];
char autore[32];
short inLibreria;
short fuoriLibreria;
short id;
} Libro;
typedef struct cella {
Libro libro;
struct cella *pNext;
} Cella;
typedef Cella *Pcella;
typedef struct listaLibri{
Cella *pFirst;
Cella *pLast;
} ListaLibri;
void insHead(ListaLibri lista){
Pcella cella;
Libro libro;
printf("Inserisci titolo libro: ");
scanf("%s", libro.titolo);
printf("Inserisci autore libro: ");
scanf("%s", libro.autore);
printf("Inserisci il numero di copie presenti in libreria: ");
scanf("%d",&libro.inLibreria);
if(lista.pFirst == NULL){
cella = NULL;
Pcella temp = cella;
cella = malloc(sizeof(Cella));
(*cella).libro = libro;
(*cella).pNext = temp;
lista.pFirst = cella;
lista.pLast = cella;
}
printList(lista);
}
void printList(ListaLibri *lista){
Pcella cella = lista->pFirst;
Pcella temp = cella;
while (temp != NULL){
printf("%s", temp->libro.autore);
temp = temp->pNext;
}
free(cella);
free(temp);
}
void main(){
ListaLibri lista;
insHead(lista);
}
First of all you have to initialize lista.pFirst and lista.pLast with NULL.
int main()
{
ListaLibri lista;
lista.pFirst = NULL; // <- init NULL
lista.pLast = NULL; // <- init NULL
insHead( &lista ); // <- pass pointer to list to function insHead
insHead( &lista );
.....
deleteList( &lista );
return 0;
}
The input paramter to your function insHead has to be an in and output paramter. Otherwise you would pass an copy of lista to function insHead and never get back its content.
void insHead( ListaLibri *lista )
// ^ input and outout paramter
{
if ( lista == NULL )
return;
Cella *head = lista->pFirst; // remember head of list
lista->pFirst = malloc(sizeof(Cella)); // allocate new node right to target
lista->pFirst->pNext = head; // successor of new node is head of list
if ( lista->pLast == NULL ) // if list was empty new node is tail of list
lista->pLast = lista->pFirst;
Libro libro;
printf("Inserisci titolo libro: ");
scanf("%s", libro.titolo);
printf("Inserisci autore libro: ");
scanf("%s", libro.autore);
printf("Inserisci il numero di copie presenti in libreria: ");
scanf("%d",&libro.inLibreria);
lista->pFirst->libro = libro;
printList( lista );
}
Don't delete nodes infunction print.
void printList(ListaLibri *lista)
{
if ( lista == NULL )
return;
Pcella temp = lista->pFirst;
while (temp != NULL)
{
printf("%s\n", temp->libro.autore);
temp = temp->pNext;
}
}
Write a function which deletes the list.
void deleteList(ListaLibri *lista)
{
if ( lista == NULL )
return;
Pcella temp = lista->pFirst;
while (temp != NULL) // terminate if tail of list is reached
{
Pcella next = temp->pNext; // rmember successor of node
free( temp ); // delete node
temp = next; // go to next node
}
lista->pFirst = NULL;
lista->pLast = NULL;
}
You are not assigning the pFirst value, so it is having garbage data, which is not equal to NULL.
Modify your code like this;
void insHead(ListaLibri lista)
{
// Your code goes here
lista.pFirst = NULL;
if(lista.pFirst == NULL)
{
// Your code goes here
}
printList(&lista); //Pass it as a reference, because printList() input parameter is a pointer type.
}
Hope this helps.
You declare lista in main, but you don't initialize any fields. My guess is that lista.pFirst is non-NULL garbage and you if is then skipped.

Unexpected behaviour of fread() reading from binary file

This program basically creates a list of flights with all their infos (read by the fread() function from a ListaVoli.bin).
The list is made up mainly by nodes and each node contains a flight.
#include <stdio.h>
#include <stdlib.h>
#define FILE_NAME "/Users/Matt/Downloads/ListaVoli.bin"
struct flight {
int flightCode;
char destination[3];
int scheduledDepHour;
int scheduledDepMinute;
int realDepHour;
int realDepMinute;
int passengers;
};
struct node {
struct flight volo;
struct node *next;
};
struct node *addToList(struct node *list, struct flight voloIn) {
struct node *newNode;
newNode = malloc(sizeof(struct node));
if (newNode == NULL) {
printf("Error: malloc failed\n");
exit(EXIT_FAILURE);
}
newNode -> volo = voloIn;
newNode -> next = list;
return newNode;
}
void printList(struct node *list) {
for (; list != NULL; list = list -> next) {
printf("Code:%d\nDestination:%s\nDeparture:%d-%d\nReal:%d-%d\nPassengers:%d\n\n\n",
list -> volo.flightCode,
list -> volo.destination,
list -> volo.scheduledDepHour,
list -> volo.scheduledDepMinute,
list -> volo.realDepHour,
list -> volo.realDepMinute,
list -> volo.passengers
);
}
}
void decolla(struct node *list, int flightCode, int realDepHour, int realDepMinute) {
for (; list != NULL; list = list -> next) {
if (flightCode == (list -> volo.flightCode)) { /*
printf("Inserisci ora di partenza per il volo %d: ", flightCode);
scanf("%d", &(list -> volo.realDepHour));
printf("Inserisci minuto di partenza: ");
scanf("%d", &(list -> volo.realDepMinute)); */
list -> volo.realDepHour = realDepHour;
list -> volo.realDepMinute = realDepMinute;
}
}
}
void delay(struct node *list) {
for (; list != NULL; list = list -> next) {
if ((list -> volo.realDepHour) - (list -> volo.scheduledDepHour) == 0) {
if ((list -> volo.realDepMinute) - (list -> volo.scheduledDepMinute) > 5 && (list -> volo.realDepMinute) - (list -> volo.scheduledDepMinute) < 30) {
printf("Il volo %d ha più di 5 minuti di ritardo\n", list -> volo.flightCode);
continue;
}
if ((list -> volo.realDepMinute) - (list -> volo.scheduledDepMinute) > 30) {
printf("Il volo %d ha più di 30 minuti di ritardo\n", list -> volo.flightCode);
continue;
}
} else
printf("Il volo %d ha più di 30 minuti di ritardo\n", list -> volo.flightCode);
}
}
void passengersCount(struct node *list) {
for (; list != NULL; list = list -> next) {
if (list -> volo.passengers > 200) {
printf("Il volo %d ha più di 200 passeggeri\n", list -> volo.flightCode);
continue;
}
}
}
int main() {
FILE *fp;
struct node *first = NULL;
struct flight volo;
/* Apro il file e controllo che sia stato aperto correttamente */
if ((fp = fopen(FILE_NAME, "rb")) == NULL) {
printf("Can't open %s\n", FILE_NAME);
exit(EXIT_FAILURE);
}
for (int i = 0; i < 4; i++) {
fread(&volo, sizeof(int), 7, fp);
first = addToList(first, volo);
}
decolla(first, 3497, 11, 30);
decolla(first, 2193, 11, 53);
decolla(first, 4284, 11, 07);
decolla(first, 5536, 12, 26);
printList(first);
delay(first);
passengersCount(first);
/* Controllo che il file sia chiuso correttamente */
if (fclose(fp) == EOF) {
printf("File not closed properly!");
exit(EXIT_FAILURE);
}
return 0;
}
The code compiles correctly so don't worry about the entire code, focus on the main() functions and the two structs.
I have two questions regarding the fread() function in the main() function:
Why, if I put sizeof(int) as the second parameter, the flight.destination value is assigned correctly? Shouldn't a char[3] variable be larger than sizeof(int)?
Why, if I put sizeof(struct flight) as second parameter (which would be the best choice), I get segmentation fault:11?
An array of three characters is three bytes. An int is usually (at least on modern 32 and 64 bit platforms) 4 bytes. It works to read sizeof(int) because the compiler adds padding.
But the "correct" (or at least usual) way to read the structure would be to read the whole structure as one single unit, i.e. using sizeof(volo) in your case:
fread(&volo, sizeof(volo), 1, fp);
If you get other errors because of it, you are doing something else wrong.

Resources