Partage
  • Partager sur Facebook
  • Partager sur Twitter

[C] pointeurs et liste chainée

supprimer les doublons d'un fichier

Sujet résolu
    24 juillet 2006 à 19:03:18

    Bonsoir, :)

    mon problème vient d'une fonction qui est cencée supprimer les lignes en double d'un fichier (supprimée les partie enregistrée en double dans le jeu Puissance 4 ;)

    Pour cela, je me suis dit que si il y avait une ligne a supprimer au début du fichier je devrais sauvegarder presque tout le fichier pour le réécrire. Donc, autant tout sauvegarder en même temp qu'on le lit et réécrire le fichier a la fin.
    Or, comme je ne connais pas le nombre de ligne du fichier ni leur taille, je n'ai pas voulu faire un tableau de char* contenant chacune des ligne pour ne pas avoir a le réalouer a chaque nouvelle ligne.
    J'ai donc fait un système de liste chainée, chaque élépent contient une ligne et un pointeur sur un autre élément. je m'occupe manuellement du premier, et je retouve tout les autres en suivant la liste des éléments suivant jusqu'à trouver un pointeur NULL. :p


    pour chaqe ligne, le programme la lit, vérifie qu'elle n'est pas dans la liste, et si elle n'y est pas on la rajoute a la liste.
    Une fois qu'on a fini, je repasse la liste en réécrivant chaque ligne dans le fichier et libérant la mémoire :-° .

    voici mon code :
    int sortirDoublons(char *nameFile)
    {

        typedef struct Partie
        {
            char *ligne;
            struct Partie *partieSuivante;
        }Partie;

        int nbDeDoublons = 0;
        int nbDeParties = 0;
        int test;
        char ligne[LIGNE*COLONNE + 2];
        FILE* fichier = NULL;
        Partie partie;
        Partie *pPartie = NULL;
        Partie *pPartie2 = NULL;
        char *pChar = NULL;



        fichier = fopen(nameFile, "r");
        if (fichier == NULL)
        {
            fprintf(stderr, "erreur lors de l'ouverture"
                            " du fichier %s pour sortir les doublons l'ia\n", nameFile);
        }
        else
        {
            if (fgets(ligne, LIGNE*COLONNE + 2, fichier) == NULL)
            {
                printf("le fichier de savegarde %s est vide", nameFile);
                return 0;
            }
            partie.ligne = malloc(strlen(ligne)*sizeof(char));
            strcpy(partie.ligne, ligne);
            partie.partieSuivante = NULL;
            pPartie = &partie;
            nbDeParties++;
            printf("Partie : %d | %s\n", nbDeParties, partie.ligne);

            while (fgets(ligne, LIGNE*COLONNE + 2, fichier) != NULL)
            {// on passe toutes les autres lignes (autre que la 1ère) du fichier

                // on regarde que cette ligne n'existe pas déjà (doublon)
                test = 0;
                if (strcmp(partie.ligne, ligne) == 0)
                {
                    pPartie2 = &partie;
                    test = 1;
                    nbDeDoublons++;
                } else
                {
                    pPartie2 = partie.partieSuivante;
                }

                while (pPartie2 != pPartie)
                {
                    if (strcmp(pPartie2->ligne, ligne) == 0)
                    {
                        nbDeDoublons++;
                        test = 1;
                        break;
                    } else
                    {
                        pPartie2 = pPartie2->partieSuivante;
                    }
                }

                // test = 0 c'est qu'on a pas encore cette ligne en mémoire,
                // on la rajoute donc a la liste
                if (test == 0)
                {
                    pPartie->partieSuivante = malloc(sizeof(Partie));
                    pPartie = pPartie->partieSuivante;

                    pPartie->ligne = malloc(strlen(ligne)*sizeof(char));
                    strcpy(pPartie->ligne, ligne);
                    pPartie->partieSuivante = NULL;

                    nbDeParties++;
                    printf("Partie : %d | %s\n", nbDeParties, pPartie->ligne);
                }

            }

            fclose(fichier);
        }
        printf("nbDeParties : %d\n", nbDeParties);



        // on libère la mémoire et réécrit le fichier :
        // provisoirement je l'écrit dans un autre fichier.
        fichier = fopen("test2", "w+");
        if (fichier == NULL)
        {
            fprintf(stderr, "erreur lors de l'ouverture"
                            " du fichier test2 la réécriture\n");
        }

        if (fichier != NULL)
        {
            if ( fputs(partie.ligne, fichier) == EOF )
            {
                fprintf(stderr, "erreur lors de la réécriture"
                " du fichier de sauvegarde ligne : %s\n", partie.ligne);
            }
            fputc('\n', fichier);
        }

        free(partie.ligne);
        partie.ligne = NULL;
        pPartie = partie.partieSuivante;
        partie.partieSuivante = NULL;

        while (pPartie->partieSuivante != NULL)
        {
            pPartie2 = pPartie;

            if (fichier != NULL)
            {
                if ( fputs(pPartie2->ligne, fichier) == EOF )
                {
                    fprintf(stderr, "erreur lors de la réécriture"
                    " du fichier de sauvegarde ligne : %s\n", partie.ligne);
                }
                fputc('\n', fichier);
            }

            free(pPartie2->ligne);
            pPartie2->ligne = NULL;
            pPartie = pPartie2->partieSuivante;
            pPartie2->partieSuivante = NULL;
            free(pPartie2);
            pPartie2 = NULL;
        }
        if (fichier != NULL)
        {
            fclose(fichier);
        }

        return nbDeDoublons;
    }


    j'appelle la fonction tout bètement "sortirDoublons("test.txt");"
    et le fichier test contient ceci :
    bonjour
    123
    456
    123
    au revoir
    bonjour
    salut
    456
    azerty
    salut
    yeeee
    yeeee


    je n'ai pas d'erreurs de compilation, pas de warning, mais ça plante.
    le fichier test2.txt n'est même pas crée et stderr ne contien rien.
    stdout contient
    Partie : 1 | bonjour



    voilà seulement le programme plante sans rien me dire o_O , et je ne trouve pas l'erreur. Je fait donc appel a votre savoir ^^ c'est où que j'ai déconner ?
    • Partager sur Facebook
    • Partager sur Twitter
      25 juillet 2006 à 23:53:32

      bon je vois que mon code n'as pas passioné les foules...

      enfin a force de chercher j'ai trouvé le problème :

      dans le while il me falais tester que pPartie2 ne soit pas null car pour la 1er ligne, il l'est.

      voici le code corrigé pour ceux que ça interresserait un jour... :euh:

      cette fonction supprime les lignes en double du fichier passé en paramètre :

      int sortirDoublons(char *nameFile)
      {

          typedef struct Partie
          {
              char *ligne;
              struct Partie *partieSuivante;
          }Partie;

          int nbDeDoublons = 0;
          int nbDeParties = 0;
          int test;
          char ligne[LIGNE*COLONNE + 2];
          FILE* fichier = NULL;
          Partie partie;
          Partie *pPartie = NULL;
          Partie *pPartie2 = NULL;
          char *pChar = NULL;



          fichier = fopen(nameFile, "r");
          if (fichier == NULL)
          {
              fprintf(stderr, "erreur lors de l'ouverture"
                              " du fichier %s pour sortir les doublons l'ia\n", nameFile);
          }
          else
          {
              if (fgets(ligne, LIGNE*COLONNE + 2, fichier) == NULL)
              {
                  printf("le fichier de savegarde %s est vide", nameFile);
                  return 0;
              }
              partie.ligne = malloc(strlen(ligne)*sizeof(char));
              strcpy(partie.ligne, ligne);
              partie.partieSuivante = NULL;
              pPartie = &partie;
              nbDeParties++;

              while (fgets(ligne, LIGNE*COLONNE + 2, fichier) != NULL)
              {// on passe toutes les autres lignes (autre que la 1ère) du fichier

                  // on regarde que cette ligne n'existe pas déjà (doublon)
                  test = 0;
                  pPartie2 = NULL;
                  if (strcmp(partie.ligne, ligne) == 0)
                  {
                      pPartie2 = &partie;
                      test = 1;
                      nbDeDoublons++;
                  } else
                  {
                      pPartie2 = partie.partieSuivante;
                  }

                  while (pPartie2 != pPartie && pPartie2 != NULL)
                  // tantqu'on est pas a la dernière partie de la liste
                  {
                      if (strcmp(pPartie2->ligne, ligne) == 0)
                      {
                          nbDeDoublons++;
                          test = 1;
                          break;
                      } else
                      {
                          pPartie2 = pPartie2->partieSuivante;
                      }
                  }

                  // test = 0 c'est qu'on a pas encore cette ligne en mémoire,
                  // on la rajoute donc a la liste
                  if (test == 0)
                  {
                      pPartie->partieSuivante = malloc(sizeof(Partie));
                      pPartie = pPartie->partieSuivante;

                      pPartie->ligne = malloc(strlen(ligne)*sizeof(char));
                      strcpy(pPartie->ligne, ligne);
                      pPartie->partieSuivante = NULL;


                  }
                  nbDeParties++;

              }

              fclose(fichier);
          }

          //printf("nbDeParties : %d\n", nbDeParties);


          // on libère la mémoire et réécrit le fichier :
          // provisoirement je l'écrit dans un autre fichier.
          fichier = fopen(nameFile, "w+");
          if (fichier == NULL)
          {
              fprintf(stderr, "erreur lors de l'ouverture"
                              " du fichier test2 la réécriture\n");
          }

          if (fichier != NULL)
          {
              if ( fputs(partie.ligne, fichier) == EOF )
              {
                  fprintf(stderr, "erreur lors de la réécriture"
                  " du fichier de sauvegarde ligne : %s\n", partie.ligne);
              }
          }

          free(partie.ligne);
          partie.ligne = NULL;
          pPartie = partie.partieSuivante;
          partie.partieSuivante = NULL;

          while (pPartie->partieSuivante != NULL)
          {
              pPartie2 = pPartie;

              if (fichier != NULL)
              {
                  if ( fputs(pPartie2->ligne, fichier) == EOF )
                  {
                      fprintf(stderr, "erreur lors de la réécriture"
                      " du fichier de sauvegarde ligne : %s\n", partie.ligne);
                  }
              }

              free(pPartie2->ligne);
              pPartie2->ligne = NULL;
              pPartie = pPartie2->partieSuivante;
              pPartie2->partieSuivante = NULL;
              free(pPartie2);
              pPartie2 = NULL;
          }
          if (fichier != NULL)
          {
              fclose(fichier);
          }

          return nbDeDoublons;
      }
      • Partager sur Facebook
      • Partager sur Twitter

      [C] pointeurs et liste chainée

      × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
      × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
      • Editeur
      • Markdown