Salve a tutti, seguo questo forum da molto tempo e mi è sempre stato molto ultile, questa è la prima volta che scrivo un messaggio! così colgo l'occasione per ringraziare gli utenti 
Ora vengo al dunque:
Mi è stato posto il problema di creare un programma che funzioni da catalogatore per una biblioteca.
E' richiesto far uso delle liste concatenate per contenere i dati di ogni singolo libro e di dare la possiblità all'utente di inserire, eliminare, e ricercare certi libri in base a parole chiave. Penso di essere a buon punto, però si verifica un'errore che non riesco proprio a capire. Vi posto la parte essenziale del codice e poi torno a commentare in basso:
(Ho eliminato le funzioni di ricerca perchè non possono influire sul problema, si verifica anche non utilizzandole affatto)
codice:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 10
typedef struct Libro *lista;
typedef struct Libro{
int ID;
char Autore[255];
char Titolo[255];
char Parole[255];
lista next;
} Libro;
Libro * newLibro(void); // Restituisce un puntatore ad un nuovo libro allocato.
void makeMenu(int *select); // Stampa il menu e acquisice la scelta.
void destLibri(Libro *p); // Dealloca tutta la lista.
void stampLibri(Libro *p); // Stampa la lista completa.
void remLibri(Libro *p, int nLibri); // Rimuove il libro selezionato dall'elenco.
void add2tail(Libro *p, Libro *new); // Aggiunge un elemento in coda.
int countlibri(Libro *p); // Conta gli elementi della lista.
int main(int argc, char *argv)
{
int select, nLibri, mod;
Libro *inizio = (Libro *) malloc(sizeof(Libro));
Libro *p;
do{ //cicla fino a quando l'utente decide di terminare.
makeMenu(&select);
while (getchar() != '\n');
switch(select){
case 0: //exit
break;
case 1: //alloca libro, lo accoda e aggiorna nLibri
if(nLibri<SIZE){
p = newLibro();
add2tail(inizio, p);
nLibri = countlibri(inizio);
printf("Libro inserito correttamente(%d/%d).\n", nLibri, SIZE);
}else
printf("Lo spazio sugli scaffali della biblioteca è esaurito.\n");
break;
case 2: //stampa lista
if(nLibri!=0)
stampLibri(inizio->next);
else
printf("Non ci sono libri.\n");
break;
case 5: //rimuove un libro dalla lista, aggiorna nLibri
if(nLibri!=0){
remLibri(inizio, nLibri);
nLibri = countlibri(inizio);
printf("Libro rimosso con successo(%d/%d).\n", nLibri, SIZE);
}else
printf("Non ci sono libri.\n");
break;
}
}while(select != 0);
destLibri(inizio);
return 0;
}
void makeMenu(int *select)
{
printf("\t\t==M E N U==\n"
"0- Esci.\n1- Inserisci Libro.\n2- Visualizza Libri.\n3- Ricerca libri(1+ matching).\n4- Ricerca libri(full matching).\n5- Rimuovi libro.\n>");
scanf("%d", select);
}
Libro * newLibro(void)
{
Libro *p;
p= (Libro *) malloc(sizeof(Libro));
printf("Inserire l'ID del libro: ");
scanf("%d", &p->ID);
while (getchar() != '\n'); //per pulire il buffer dopo scanf
printf("Inserire l'Autore: ");
fgets(p->Autore, 255, stdin);
printf("Inserire il Titolo: ");
fgets(p->Titolo, 255, stdin);
printf("Inserire le 5 parole chiavi, separate da spazi: ");
fgets(p->Parole, 255, stdin);
return p;
}
int countlibri(Libro *p)
{
int i = 0;
while(p->next != NULL ){ //<<SI BLOCCA QUI
i++;
p = p->next;
}
return i;
}
void add2tail(Libro *p, Libro *new)
{
while(p->next) p = p->next;
p->next = new;
}
void destLibri(Libro *p)
{
if(p == NULL)
return;
Libro *temp;
temp = p->next;
free(p);
destLibri(temp);
}
void stampLibri(Libro *p)
{
int i = 1;
while(p){
printf("========\nLibro (%d/%d):\nID: %d\nAutore: %sTitolo: %s========\n", i, SIZE, p->ID, p->Autore, p->Titolo);
p = p->next;
i++;
}
}
void remLibri(Libro *p, int nLibri)
{
Libro *temp;
int i, n;
stampLibri(p->next);
do{
printf("Inserisci il numero in elenco del libro da rimuovere(1/%d): ", nLibri);
scanf("%d", &n);
}while(n<1 || n>nLibri);
for(i=0; i < n-1; i++) p = p->next; //scorre fino al libro prima di quello da eliminare
temp = p->next;
p->next = temp->next;
free(temp);
}
Vi spiego brevemente quello che accade:
Dopo aver elminato un'elemento dalla lista (che non sia l'ultimo), quando vado a creare un nuovo elemento. la funzione countlibri entra in un loop infinito, e pur sapendo dov'è il problema non capisco proprio cosa lo causi!
Ho analizzato attentamente la funzione remLibri, ma "su carta" il problema non dovrebbe esserci.(almeno credo)
Questa è la prova su carta che ho fatto:
Ipotizziamo una lista composta da:
inizio->libro1->libro2->NULL
così concatenata:
Inizio->next = libro1
libro1->next = libro2
libro2->next = NULL
Il for all'interno della funzione non esegue nulla (i=0 ; n-1=0), quindi siamo fermi ad "Inizio". proseguento passo a passo:
- temp punta a libro1 (quello da eliminare)
- inizio punta al next di libro1 (libro2)
- libero lo spazio a cui punta libro1
Dopo tutto questo però, quando provo ad inserire un nuovo libro countlibri si blocca nel ciclo anche se in teoria il next di libro2 non è stato toccato e punta ancora a NULL. Spero di essermi spiegato in modo comprensibile
A presto!