#include #include #include #include // Déclaration des structures struct Livre { char titre[50]; char auteur[50]; int annee; }; struct Index { char titre[50]; long position; // Position de l'enregistrement dans le fichier struct Index* gauche; struct Index* droite; }; FILE* fichierDonnees, *FichierIndex = NULL; struct Index* racineArbre = NULL; int nbIndex = 0; // Fonction pour insérer un nouvel index dans l'arbre binaire de recherche void insererDansArbre(struct Index** racine, struct Index* nouvelIndex) { if (*racine == NULL) { *racine = nouvelIndex; (*racine)->gauche = NULL; (*racine)->droite = NULL; } else { if (strcmp(nouvelIndex->titre, (*racine)->titre) < 0) { insererDansArbre(&(*racine)->gauche, nouvelIndex); } else if (strcmp(nouvelIndex->titre, (*racine)->titre) > 0) { insererDansArbre(&(*racine)->droite, nouvelIndex); } } } // Fonction de recherche basée sur le titre du livre dans l'arbre struct Index* rechercherIndexParTitre(struct Index* racine, char* titre) { if (racine == NULL || strcmp(titre, racine->titre) == 0) { return racine; } if (strcmp(titre, racine->titre) < 0) { return rechercherIndexParTitre(racine->gauche, titre); } else { return rechercherIndexParTitre(racine->droite, titre); } } // Fonction pour sauvegarder l'arbre d'index dans un fichier void sauvegarderIndexEnFichier(struct Index* racine, FILE* fichierDonnees) { if (racine != NULL) { sauvegarderIndexEnFichier(racine->gauche, fichierDonnees); fwrite(racine, sizeof(struct Index), 1, fichierDonnees); sauvegarderIndexEnFichier(racine->droite, fichierDonnees); } } // Fonction d'ajout d'un livre void ajouterLivre(struct Livre livre) { // Vérifier si le titre du livre existe déjà struct Index* existant = rechercherIndexParTitre(racineArbre, livre.titre); if (existant != NULL) { printf("Un livre avec ce titre existe déjà. Veuillez choisir un titre unique.\n"); return; } // Déplacer le curseur à la fin du fichier pour ajouter à la fin fseek(fichierDonnees, 0, SEEK_END); // Écrire la structure Livre dans le fichier fwrite(&livre, sizeof(struct Livre), 1, fichierDonnees); // Ajouter une entrée d'index pour le nouveau livre dans le tableau struct Index* index = malloc(sizeof(struct Index)); strcpy(index->titre, livre.titre); index->position = ftell(fichierDonnees) - sizeof(struct Livre); index->gauche = NULL; index->droite = NULL; // Insérer le nouvel index dans l'arbre binaire de recherche insererDansArbre(&racineArbre, index); // Sauvegarder l'arbre d'index dans le fichier sauvegarderIndexEnFichier(racineArbre, FichierIndex); printf("Livre ajouté avec succès.\n"); } // Fonction pour rechercher un livre par titre void rechercherLivreParTitre(char* titre) { struct Index* resultat = rechercherIndexParTitre(racineArbre, titre); if (resultat != NULL) { fseek(fichierDonnees, resultat->position, SEEK_SET); struct Livre livre; fread(&livre, sizeof(struct Livre), 1, fichierDonnees); printf("Livre trouvé :\n"); printf("Titre : %s\n", livre.titre); printf("Auteur : %s\n", livre.auteur); printf("Année : %d\n", livre.annee); } else { printf("Aucun livre trouvé avec le titre \"%s\".\n", titre); } } // Fonction pour afficher le contenu du fichier de données void afficherContenuFichier() { fseek(fichierDonnees, 0, SEEK_SET); struct Livre livre; printf("\nContenu du fichier de données :\n"); while (fread(&livre, sizeof(struct Livre), 1, fichierDonnees) == 1) { printf("Titre : %s\n", livre.titre); printf("Auteur : %s\n", livre.auteur); printf("Année : %d\n", livre.annee); printf("-------------------------\n"); } } // Fonction récursive pour afficher l'arbre d'index avec les nœuds gauche et droite void afficherArbreIndex(struct Index* racine, int niveau, int estDroite) { if (racine != NULL) { // Afficher le nœud actuel avec le niveau approprié et le caractère de branche for (int i = 0; i < niveau - 1; i++) { printf(" "); // Ajouter des espaces pour représenter la profondeur } if (niveau > 0) { if (estDroite) { printf("└── "); } else { printf("├── "); } } printf("%s (Position : %ld)\n", racine->titre, racine->position); // Afficher les nœuds gauche et droite récursivement avec un niveau augmenté afficherArbreIndex(racine->gauche, niveau + 1, 0); afficherArbreIndex(racine->droite, niveau + 1, 1); } } // Fonction pour afficher le contenu de l'arbre d'index void afficherContenuArbreIndex(struct Index* racine) { printf("\nContenu de l'arbre d'index :\n"); afficherArbreIndex(racine, 0, 0); } // Fonction pour libérer la mémoire occupée par l'arbre void libererArbre(struct Index* racine) { if (racine != NULL) { libererArbre(racine->gauche); libererArbre(racine->droite); free(racine); } } int main() { int choix; fichierDonnees = fopen("bibliotheque.dat", "ab+"); if (fichierDonnees == NULL) { perror("Erreur lors de l'ouverture du fichier de données."); return 1; } // Charger l'arbre d'index depuis le fichier FichierIndex = fopen("bibliotheque.idx", "rb+"); if (FichierIndex != NULL) { while (1) { struct Index* index = malloc(sizeof(struct Index)); if (fread(index, sizeof(struct Index), 1, FichierIndex) != 1) { free(index); break; } insererDansArbre(&racineArbre, index); } } else { FichierIndex = fopen("bibliotheque.idx", "wb"); } do { // Menu printf("\nMenu :\n"); printf("1. Ajouter un livre\n"); printf("2. Rechercher un livre\n"); printf("3. Afficher le contenu du fichier de données\n"); printf("4. Afficher le contenu de l'arbre d'index\n"); printf("5. Quitter\n"); printf("Choix : "); scanf("%d", &choix); switch (choix) { case 1: { // Ajouter un livre struct Livre nouveauLivre; 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); break; } case 2: { // Rechercher un livre char titreRecherche[50]; printf("Titre du livre à rechercher : "); scanf("%s", titreRecherche); rechercherLivreParTitre(titreRecherche); break; } case 3: // Afficher le contenu du fichier de données afficherContenuFichier(); break; case 4: // Afficher le contenu de l'arbre d'index //construireTableauIndex(racineArbre); afficherContenuArbreIndex(racineArbre); break; case 5: // Sauvegarder et décharger l'arbre d'index lors de la fermeture du fichier de données sauvegarderIndexEnFichier(racineArbre, FichierIndex); libererArbre(racineArbre); fclose(FichierIndex); fclose(fichierDonnees); printf("Au revoir.\n"); break; default: printf("Choix invalide.\n"); } } while (choix != 5); // Fermer le fichier de données fclose(fichierDonnees); return 0; }