PDA

Visualizza la versione completa : [C] Aiuto lista


thefiery77
04-09-2016, 11:50
Traccia esercizio: Simulare in C la gestione delle camere di un albergo mediante liste lineari rappresentate su un array di struct: i principali campi sono le “informazioni” (numero di camera, cliente, etc.) ed i “link” (puntatori ai nodi della lista). [Suggerimento: L’array di struct corrisponde alla memoria in cui allocare la lista delle camere libere (ListaLibera) e la lista delle camere occupate (ListaDati). È necessario creare prima la ListaLibera, inizializzando l’array dei link in modo che ogni componente punti alla componente successiva. Ogni nodo da inserire nella ListaDati, quando una camera viene assegnata ad un cliente, è prelevato dalla testa della ListaLibera ed inserito nella testa della ListaDati; mentre il nodo da eliminare dalla ListaDati, quando una particolare camera viene liberata, è restituito alla ListaLibera (in testa) per poter essere riutilizzato in seguito.]

Il programma funziona bene, l'unico problema sorge quando elimino l'ultimo elemento della lista e successivamente voglio inserirne un altro. Secondo me il problema è nella function libera ma non capisco come posso risolvere.



#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct
{
int n;
char nome[20];
}inf;
struct listalibera
{
inf info;
struct listalibera *next;
};
struct listadati
{
inf info;
struct listadati *next;
};
typedef struct listalibera l_list;
typedef struct listadati d_list;
void ins_testa(d_list **d, l_list **l)
{
d_list *nuovo;
nuovo=calloc(1,sizeof(d_list));
nuovo->info.n=(*l)->info.n;
printf("Stanza numero %d\n",nuovo->info.n);
puts("Inserisci nome cliente: ");
fflush(stdin);
gets(nuovo->info.nome);
nuovo->next=*d;
*d=nuovo;
l_list *l_t;
l_t=(*l)->next;
free(*l);
*l=l_t;
}
void crea_l_t(l_list **testa)
{
l_list *h;
h=calloc(1,sizeof(l_list));
h->info.n=1;
h->next=*testa;
*testa=h;
}
void crea_l(l_list **pnt)
{
l_list *nuovo;
int i;
for(i=2;i<21;i++)
{
nuovo=calloc(1,sizeof(l_list));
nuovo->info.n=i;
nuovo->next=(*pnt)->next;
(*pnt)->next=nuovo;
*pnt=nuovo;
}
nuovo->next=NULL;
}

void ins_mezzo(d_list **pnt, l_list **l_h)
{
d_list *nuovo;
nuovo=calloc(1,sizeof(d_list));
nuovo->info.n=(*l_h)->info.n;
printf("Stanza numero %d\n",nuovo->info.n);
puts("Inserisci nome cliente: ");
fflush(stdin);
gets(nuovo->info.nome);
nuovo->next=(*pnt)->next;
(*pnt)->next=nuovo;
*pnt=nuovo;
l_list *temp;
temp=(*l_h)->next;
free(*l_h);
*l_h=temp;
}
void libera(d_list **d, l_list **l)
{
d_list *temp;
l_list *h;
int n;
temp=*d;
puts("Quale camera devi liberare?");
printf("La numero ");
scanf("%d",&n);
while(temp->info.n!=n)
{
temp=temp->next;
}
h=calloc(1,sizeof(l_list));
h->info.n=temp->info.n;
h->next=*l;
*l=h;
d_list *cur, *prev;
for(cur=*d, prev=NULL; cur!=NULL && cur->info.n!=n; prev=cur, cur=cur->next);
prev->next=cur->next;
free(cur);
}
void libera_t(d_list **d, l_list **l)
{
l_list *h;
d_list *temp;
temp=*d;
h=calloc(1,sizeof(l_list));
h->info.n=temp->info.n;
h->next=*l;
*l=h;
temp=(*d)->next;
free(*d);
*d=temp;
}
void visualizza_d(d_list *d)
{
if(d==NULL)
puts("Non ci sono capere occupate.");
else
{
puts("Camere occupate:");
while(d!=NULL)
{
printf("Numero camera: %d\n",d->info.n);
printf("Nome cliente: %s\n", d->info.nome);
d=d->next;
}
}
}
void visualizza_l(l_list *l)
{
if(l==NULL)
puts("Non ci sono capere libere.");
else
{
puts("Camere occupate:");
while(l!=NULL)
{
printf("Numero camera: %d\n",l->info.n);
l=l->next;
}
}
}

int main()
{
l_list *l_head, *l_punt;
d_list *d_head, *d_punt;
l_head=NULL;
d_head=NULL;
l_punt=calloc(1,sizeof(l_list));
crea_l_t(&l_head);
l_punt=l_head;
crea_l(&l_punt);
int sc;
while(sc!=6)
{
puts("Menu':\n1) Occupa stanza\n2) Libera stanza\n3) Visualizza camere occupate.\n4) Visualizza camere libere.\n5) Termina programma.");
scanf("%d",&sc);
switch(sc)
{
case 1: if(d_head==NULL){
ins_testa(&d_head,&l_head);
d_punt=d_head;
}
else
ins_mezzo(&d_punt,&l_head);
break;
case 2 : if(d_head->next!=NULL)
libera(&d_head, &l_head);
else
libera_t(&d_head, &l_head);
break;
case 3 : visualizza_d(d_head);
break;
case 4: visualizza_l(l_head);
}
}
return 0;
}

filips
04-09-2016, 12:37
Purtroppo sono al cellulare e non posso controllare niente, ma a occhio mi sembra che ci sia un problema logico nel blocco for di libera.

thefiery77
04-09-2016, 17:47
Purtroppo sono al cellulare e non posso controllare niente, ma a occhio mi sembra che ci sia un problema logico nel blocco for di libera.
capito, quando puoi fammi sapere ^^

filips
04-09-2016, 21:49
Sto provando il programma. Intanto ti dico che il menu "Visualizza camere occupate" ha qualche incoerenza, infatti se inserisco 2 nomi e poi visualizzo, ottengo questo:

Camere occupate:
Numero camera: 1
Nome cliente:
Numero camera: 2
Nome cliente: enzo
Numero camera: 3
Nome cliente: pino


Quando le camere occupate sono solo la 1 e la 2.

thefiery77
04-09-2016, 23:02
Sto provando il programma. Intanto ti dico che il menu "Visualizza camere occupate" ha qualche incoerenza, infatti se inserisco 2 nomi e poi visualizzo, ottengo questo:

Camere occupate:
Numero camera: 1
Nome cliente:
Numero camera: 2
Nome cliente: enzo
Numero camera: 3
Nome cliente: pino


Quando le camere occupate sono solo la 1 e la 2.

guarda l'ho provato parecchie volte e non mi è mai successo

filips
05-09-2016, 07:32
Così sembra funzionare.. ti lascio ragionare sulla base del codice per trovare l'errore logico, per vendetta, visto che io mi sono dovuto concentrare abbastanza per ricostruire il meccanismo che hai utilizzato (della serie: qualche commento sarebbe stato ben accetto :-)

[notare che ho dovuto modificare le parti di input/output del tipo puts; fflush(stdin); gets(nuovo->info.nome); perche il compilatore che uso - gcc - le deprecava, e praticamente falliva l'esecuzione (v. output d'esempio che avevo postato)]


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct
{
int n;
char nome[20];
}inf;

struct listalibera
{
inf info;
struct listalibera *next;
};

struct listadati
{
inf info;
struct listadati *next;
};

typedef struct listalibera l_list;
typedef struct listadati d_list;

void ins_testa(d_list **d, l_list **l)
{
d_list *nuovo;
char s[20];
nuovo=calloc(1,sizeof(d_list));
nuovo->info.n=(*l)->info.n;
printf("Stanza numero %d\n",nuovo->info.n);
printf("Inserisci nome cliente: ");
scanf("%s",s);
int u;
for (u=0;u<20;u++) {
nuovo->info.nome[u] = s[u];
}
//fflush(stdin);
//gets(nuovo->info.nome);
nuovo->next=*d;
*d=nuovo;
l_list *l_t;
l_t=(*l)->next;
free(*l);
*l=l_t;
}

void crea_l_t(l_list **testa)
{
l_list *h;
h=calloc(1,sizeof(l_list));
h->info.n=1;
h->next=*testa;
*testa=h;
}

void crea_l(l_list **pnt)
{
l_list *nuovo;
int i;
for(i=2;i<21;i++)
{
nuovo=calloc(1,sizeof(l_list));
nuovo->info.n=i;
nuovo->next=(*pnt)->next;
(*pnt)->next=nuovo;
*pnt=nuovo;
}
nuovo->next=NULL;
}

void ins_mezzo(d_list **pnt, l_list **l_h)
{
d_list *nuovo;
char s[20];
nuovo=calloc(1,sizeof(d_list));
nuovo->info.n=(*l_h)->info.n;
printf("Stanza numero %d\n",nuovo->info.n);
printf("Inserisci nome cliente: ");
scanf("%s",s);
int u;
for (u=0;u<20;u++) {
nuovo->info.nome[u] = s[u];
}
//fflush(stdin);
//gets(nuovo->info.nome);

nuovo->next=(*pnt)->next;
(*pnt)->next=nuovo;
*pnt=nuovo;
l_list *temp;
temp=(*l_h)->next;
free(*l_h);
*l_h=temp;
}

void libera(d_list **d, l_list **l, d_list **dp)
{

d_list *temp;
l_list *h;
int n;
temp=*d;

puts("Quale camera devi liberare?");
printf("La numero ");
scanf("%d",&n);
while(temp->info.n!=n)
{
temp=temp->next;
}

h=calloc(1,sizeof(l_list));
h->info.n=temp->info.n;
h->next=*l;
*l=h;
d_list *cur, *prev;

for (cur=*d, prev=NULL; cur!=NULL && cur->info.n!=n; prev=cur, cur=cur->next);

prev->next=cur->next;

*dp=prev;
free(cur);
}

void libera_t(d_list **d, l_list **l)
{

l_list *h;
d_list *temp;
temp=*d;
h=calloc(1,sizeof(l_list));
h->info.n=temp->info.n;
h->next=*l;
*l=h;

temp=(*d)->next;
free(*d);
*d=temp;
}

void visualizza_d(d_list *d)
{
if(d==NULL)
puts("Non ci sono capere occupate.");
else
{
puts("Camere occupate:");
while(d!=NULL)
{
printf("Numero camera: %d\n",d->info.n);
printf("Nome cliente: %s\n", d->info.nome);
d=d->next;
}
}
}

void visualizza_l(l_list *l)
{
if(l==NULL)
puts("Non ci sono capere libere.");
else
{
puts("Camere occupate:");
while(l!=NULL)
{
printf("Numero camera: %d\n",l->info.n);
l=l->next;
}
}
}

int main()
{
l_list *l_head, *l_punt;
d_list *d_head, *d_punt;
l_head=NULL;
d_head=NULL;
l_punt=calloc(1,sizeof(l_list));
crea_l_t(&l_head);
l_punt=l_head;
crea_l(&l_punt);
int sc;
while(sc!=5)
{
puts("Menu':\n1) Occupa stanza\n2) Libera stanza\n3) Visualizza camere occupate.\n4) Visualizza camere libere.\n5) Termina programma.");
scanf("%d",&sc);
switch(sc)
{
case 1: if(d_head==NULL){
ins_testa(&d_head,&l_head);
d_punt=d_head;
}
else
ins_mezzo(&d_punt,&l_head);
break;
case 2 : if(d_head->next!=NULL)
libera(&d_head, &l_head, &d_punt);
else
libera_t(&d_head, &l_head);
break;
case 3 : visualizza_d(d_head);
break;
case 4: visualizza_l(l_head);
}
}
return 0;
}

thefiery77
05-09-2016, 10:48
Così sembra funzionare.. ti lascio ragionare sulla base del codice per trovare l'errore logico, per vendetta, visto che io mi sono dovuto concentrare abbastanza per ricostruire il meccanismo che hai utilizzato (della serie: qualche commento sarebbe stato ben accetto :-)

[notare che ho dovuto modificare le parti di input/output del tipo puts; fflush(stdin); gets(nuovo->info.nome); perche il compilatore che uso - gcc - le deprecava, e praticamente falliva l'esecuzione (v. output d'esempio che avevo postato)]

Scusami, non ci avevo proprio pensato di inserire le note. Comunque era un errore stupido e più o meno avevo capito che dovevo aggiornare il puntatore. Grazie mille ^^

thefiery77
05-09-2016, 11:02
Comunque ho modificato ancora la funzione libera perché se inserivo più elementi e poi volevo eliminare la testa giustamente crashava. Ho creato una variabile m nel main passata per indirizzo a libera. Nella funzione libera controlla se prev==NULL. Se è vero m diventa uguale ad 1 e la funzione finisce. Ritornati al main vede se m è uguale ad 1, se è uguale si va alla funzione libera_t (per liberare la testa). Quando si ritorna nel main m diventa uguale a 0.

filips
06-09-2016, 14:43
Comunque ho modificato ancora la funzione libera perché se inserivo più elementi e poi volevo eliminare la testa giustamente crashava. Ho creato una variabile m nel main passata per indirizzo a libera. Nella funzione libera controlla se prev==NULL. Se è vero m diventa uguale ad 1 e la funzione finisce. Ritornati al main vede se m è uguale ad 1, se è uguale si va alla funzione libera_t (per liberare la testa). Quando si ritorna nel main m diventa uguale a 0.

Perfetto, ora direi che è a posto. In effetti non avevo testato sulla testa ed è ovvio che col codice dato si abbia il crash. Resterebbe poi la questione minore (che se, come credo, si tratta di programma didattico, allora diventa irrilevante), che dopo diversi ritocchi alla lista, l'ordine numerico (inizialmente crescente) nella disposizione degli elementi si scombina continuamente. A questo si può ovviare senza ricorrere ad algoritmi di ordinamento, ma con un opportuno controllo in libera e ins_mezzo.

thefiery77
06-09-2016, 14:47
Perfetto, ora direi che è a posto. In effetti non avevo testato sulla testa ed è ovvio che col codice dato si abbia il crash. Resterebbe poi la questione minore (che se, come credo, si tratta di programma didattico, allora diventa irrilevante), che dopo diversi ritocchi alla lista, l'ordine numerico (inizialmente crescente) nella disposizione degli elementi si scombina continuamente.

si l'avevo già pensato solo che non è richiesto nell'esercizio.

Loading