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!