#include #include #include #include // Déclaration des structures struct Livre { int id; char titre[50]; char auteur[50]; int annee; }; struct Index { int id; int position; // Position de l'enregistrement dans le fichier }; FILE *fichier, *FichierIndex = NULL; struct Index *TableIndex = NULL; int nbIndex = 0; // Fonction de recherche basée sur l'ID du livre (recherche dichotomique simple) int rechercherIndex(int id) { int debut = 0; int fin = nbIndex - 1; while (debut <= fin) { int milieu = (fin + debut) / 2; if (TableIndex[milieu].id == id) { return milieu; // L'élément a été trouvé, renvoyer l'index } if (TableIndex[milieu].id < id) { debut = milieu + 1; } else { fin = milieu - 1; } } return -1; // L'élément n'a pas été trouvé } // Fonction pour insérer un nouvel index dans le tableau d'index void insererIndex(struct Index index) { int position = nbIndex; // Position par défaut pour la première insertion // Recherche dichotomique pour trouver la position d'insertion int debut = 0; int fin = nbIndex - 1; while (debut <= fin) { int milieu = (debut + fin) / 2; if (TableIndex[milieu].id == index.id) { // Si l'ID existe déjà, ne rien faire (ou mettre à jour si nécessaire) return; } else if (TableIndex[milieu].id < index.id) { debut = milieu + 1; } else { fin = milieu - 1; position = milieu; // Mettre à jour la position pour l'insertion } } // Réallouer la mémoire pour le tableau d'index TableIndex = realloc(TableIndex, (nbIndex + 1) * sizeof(struct Index)); // Décaler les éléments pour faire de la place pour le nouvel index for (int i = nbIndex; i > position; i--) { TableIndex[i] = TableIndex[i - 1]; } // Insérer le nouvel index à la position appropriée TableIndex[position] = index; nbIndex++; } // Fonction d'ajout d'un livre void ajouterLivre(struct Livre livre) { // Vérifier si l'ID du livre existe déjà while (rechercherIndex(livre.id) != -1) { printf("Un livre avec cet ID existe déjà. Veuillez choisir un ID unique.\n"); printf("ID du livre : "); scanf("%d", &livre.id); } // Déplacer le curseur à la fin du fichier pour ajouter à la fin fseek(fichier, 0, SEEK_END); // Écrire la structure Livre dans le fichier fwrite(&livre, sizeof(struct Livre), 1, fichier); // Ajouter une entrée d'index pour le nouveau livre struct Index index = {livre.id, ftell(fichier) - sizeof(struct Livre)}; insererIndex(index); printf("Livre ajouté avec succès.\n"); } // Fonction de suppression basée sur l'ID du livre void supprimerLivre(int id) { int index = rechercherIndex(id); if (index != -1) { // Ouvrir un fichier temporaire pour l'écriture FILE *tempFile = fopen("temp.dat", "wb"); if (tempFile == NULL) { perror("Erreur lors de l'ouverture du fichier temporaire"); fclose(fichier); exit(EXIT_FAILURE); } // Copiez tous les enregistrements sauf celui à supprimer dans le fichier temporaire struct Livre livre; int idx; while (fread(&livre, sizeof(struct Livre), 1, fichier) == 1) { if (livre.id != id) { fwrite(&livre, sizeof(struct Livre), 1, tempFile); idx = rechercherIndex(livre.id); TableIndex[idx].position = ftell(tempFile) - sizeof(struct Livre); } } fclose(fichier); fclose(tempFile); // Supprimer le fichier d'origine if (remove("bibliotheque.dat") != 0) { perror("Erreur lors de la suppression du fichier d'origine"); exit(EXIT_FAILURE); } // Renommer le fichier temporaire if (rename("temp.dat", "bibliotheque.dat") != 0) { perror("Erreur lors du renommage du fichier temporaire"); exit(EXIT_FAILURE); } // Supprimer l'enregistrement de la table d'index nbIndex--; for (int i = index; i < nbIndex; i++) { TableIndex[i] = TableIndex[i + 1]; } TableIndex = realloc(TableIndex, nbIndex * sizeof(struct Index)); printf("Livre supprimé avec succès.\n"); } else { printf("Livre non trouvé.\n"); } } // Fonction pour afficher le contenu du fichier de données void afficherContenuFichier() { bool vide = true; fseek(fichier, 0, SEEK_SET); struct Livre livre; while (fread(&livre, sizeof(struct Livre), 1, fichier) == 1) { if (vide) { printf("Contenu du fichier de données :\n"); vide = false; } printf("ID: %d, Titre: %s, Auteur: %s, Année: %d\n", livre.id, livre.titre, livre.auteur, livre.annee); } if (vide) { printf("Le fichier de données est vide.\n"); } } // Fonction pour afficher le contenu du fichier d'index void afficherContenuIndex() { bool vide = true; for (int i = 0; i < nbIndex; i++) { if (vide) { printf("Contenu du tableau d'index :\n"); vide = false; } printf("ID: %d, Position: %ld\n", TableIndex[i].id, TableIndex[i].position); } if (vide) { printf("Le tableau d'index est vide.\n"); } } // Fonction pour charger le fichier d'index en mémoire sous forme de tableau void chargerIndexEnMemoire() { FichierIndex = fopen("bibliotheque.idx", "rb"); if (FichierIndex != NULL) { fseek(FichierIndex, 0, SEEK_END); long size = ftell(FichierIndex); fseek(FichierIndex, 0, SEEK_SET); TableIndex = malloc(size); fread(TableIndex, size, 1, FichierIndex); nbIndex = size / sizeof(struct Index); fclose(FichierIndex); } } // Fonction pour sauvegarder et décharger le fichier d'index lors de la fermeture du fichier de données void sauvegarderEtDechargerIndex() { // Sauvegarder le tableau d'index dans le fichier FichierIndex = fopen("bibliotheque.idx", "wb"); fwrite(TableIndex, sizeof(struct Index), nbIndex, FichierIndex); fclose(FichierIndex); // Libérer la mémoire allouée pour le tableau d'index free(TableIndex); TableIndex = NULL; nbIndex = 0; } // Fonction de recherche basée sur l'ID du livre void rechercherLivre(int id) { int index = rechercherIndex(id); if (index != -1) { // Trouvé, déplacer le curseur à la position de l'enregistrement dans le fichier fseek(fichier, TableIndex[index].position, SEEK_SET); // Lire et afficher les détails du livre struct Livre livre; fread(&livre, sizeof(struct Livre), 1, fichier); printf("Livre trouvé - Titre: %s, Auteur: %s, Année: %d\n", livre.titre, livre.auteur, livre.annee); } else { printf("Livre non trouvé.\n"); } } int main() { int choix; chargerIndexEnMemoire(); do { // Menu printf("\nMenu :\n"); printf("1. Ajouter un livre\n"); printf("2. Rechercher un livre\n"); printf("3. Supprimer un livre\n"); printf("4. Afficher le contenu du fichier de données\n"); printf("5. Afficher le contenu du fichier d'index\n"); printf("6. Quitter\n"); printf("Choix : "); scanf("%d", &choix); switch (choix) { case 1: { // Ajouter un livre fichier = fopen("bibliotheque.dat", "ab+"); struct Livre nouveauLivre; printf("ID du livre : "); scanf("%d", &nouveauLivre.id); printf("Titre du livre : "); scanf("%s", nouveauLivre.titre); printf("Auteur du livre : "); scanf("%s", nouveauLivre.auteur); printf("Année du livre : "); scanf("%d", &nouveauLivre.annee); ajouterLivre(nouveauLivre); fclose(fichier); break; } case 2: { // Rechercher un livre int id; fichier = fopen("bibliotheque.dat", "rb"); printf("ID du livre à rechercher : "); scanf("%d", &id); rechercherLivre(id); fclose(fichier); break; } case 3: { // Supprimer un livre int id; fichier = fopen("bibliotheque.dat", "ab+"); printf("ID du livre à supprimer : "); scanf("%d", &id); supprimerLivre(id); fclose(fichier); break; } case 4: // Afficher le contenu du fichier de données fichier = fopen("bibliotheque.dat", "rb"); afficherContenuFichier(); fclose(fichier); break; case 5: // Afficher le contenu du fichier d'index afficherContenuIndex(); break; case 6: // Sauvegarder et décharger le fichier d'index lors de la fermeture du fichier de données sauvegarderEtDechargerIndex(); printf("Au revoir.\n"); break; default: printf("Choix invalide.\n"); } } while (choix != 6); // Fermer le fichier de données fclose(fichier); return 0; }