Partage
  • Partager sur Facebook
  • Partager sur Twitter

probleme avec realloc()

l allocation ne se fait pas et le programme sort de la boucle infinie

Sujet résolu
    23 mai 2006 à 12:47:22

    je n arrive plus a avancer vous voyez ce qui cloche ?


    #include <stdio.h>
    #include <stdlib.h>

    #define a_EOL_LEN    2

    int     linelen(FILE* stream);
    int     lineget(FILE* stream, char* line, int len);

    int main(int argc, char *argv[])
    {
        FILE*   origin = NULL;

        char*   line;

        int i = 0;

    //opens alias list, report file, and creates inventory table
        origin = fopen("d:\\aida\\aida\\test.txt", "r");

    //on access failed
        if(origin == NULL)
        {
            fprintf(stderr,"erreur dans l' ouverture des fichiers\n");
            exit(1);
        }


        int len;

    while (1)
    {
        len = linelen(origin);

        printf("\nlongueur de la chaine (len) = %ld\n", len);
        system("PAUSE");

        if (len < 0)
        {
            printf("\nlen < 0\n");
            system("PAUSE");
        }

    //Sizes the Character Table
        line = realloc(line, (len + 1) * sizeof(char));

    //Memory allocation failed ?
        if (line == NULL)
        {
            printf("\nmalloc rate\n");
            printf("\nlen = %ld\n",len);
            system("PAUSE");
        }


    //sends the 'line' CharTab to store first line of text file

        lineget(origin, line, len);

        i++;
    }

        system("PAUSE");
        printf("nombre de lignes : %ld", i);

        free(line);

        if (fclose(origin) != 0)
        {
            printf("erreur de fermeture des fichiers");
        }

        return 1;
    }


    int     linelen(FILE* stream)
    {
        int pos = 0, len, i;
        int c = 0;

    //Saves current position in stream
        pos = ftell(stream);

    //Counts number of characters before End Of Line
        for (len = 0; c != '\n'; len++)
            {
                c = fgetc(stream);
                if (c == EOF) return -1;
            }
            len--; //discards '\r' before '\n'

    //Restores original position in stream
            fseek(stream, -(len + a_EOL_LEN), SEEK_CUR);

    //check if position is OK
        if (ftell(stream) != pos) return -2;

        return len;
    }

    int     lineget(FILE* stream, char* line, int len)
    {
        int i;

    //Saves line in Character Table
        for (i = 0; i <= len; i++)
        {
            line[i] = fgetc(stream);
        }

    //Replaces the End Of Line character by the End Of CharTab
        line[i] = '\0';

        return 1;

    }










    Image utilisateur

    :'(

    • Partager sur Facebook
    • Partager sur Twitter
      23 mai 2006 à 14:34:35

      Citation : Mr.BrYcE

      je n arrive plus a avancer vous voyez ce qui cloche ?


      Peux-tu donner un exemple de fichier ?

      Si j'ai bien compris, tu veux faire un mécanisme de lecture de ligne de taille inconnue ?

      Tu t'y prends mal. Il suffit d'utiliser astucieusement fgets() et realloc() .


      #include <stdio.h>
      #include <stdlib.h>
      #include <string.h>

      static char *get_line(FILE *fp)
      {
         size_t size = 4;
         char *s = malloc(size);

         if (s != NULL)
         {
            if (fgets(s , size, fp) != NULL)
            {
               char *p = strchr(s, '\n');
               if (p != NULL)
               {
                  *p = 0;
               }
               else
               {
                  int end = 0;
                  do
                  {
                     void *tmp = realloc (s, size * 2);
                     if (tmp != NULL)
                     {
                        size *= 2;
                        s = tmp;
                        if (fgets(s + (size / 2) - 1, size / 2 + 1, fp) != NULL)
                        {
                           p = strchr(s, '\n');
                           if (p != NULL)
                           {
                              *p = 0;
                              end = 1;
                           }
                        }
                        else
                        {
                           end = 1;
                        }
                     }
                     else
                     {
                        free (s), s = NULL;
                        end = 1;
                     }
                  }
                  while (!end)
                     ;
               }
            }
            else
            {
               free (s), s = NULL;
            }
         }
         return s;
      }

      int main(int argc, char *argv[])
      {
      #define F "test.txt"

         FILE *fp = fopen (F, "r");

         if (fp != NULL)
         {
            char *line;
            while ((line = get_line(fp)) != NULL)
            {
               printf ("'%s'\n", line);
               free (line), line = NULL;
            }
            fclose (fp), fp = NULL;
         }
         else
         {
            perror(F);
         }
         return 0;
      }

      Dois-je commenter ? Honettement, c'est assez crade comme code. Je pense qu'on arrive à faire plus simple et plus efficace avec fgetc().

      Yapafoto !
      Corrigé


      /* 0=normal 1=debug */
      #define DBG 0
      static char *get_line(FILE *fp)
      {
         size_t i = 0;
         size_t size = 1;
         char *s = NULL;

         int c;
         while ((c = fgetc(fp)) != EOF)
         {
            if (i == size - 1)
            {
               void * tmp = realloc (s, size * 2);
               if (tmp != NULL)
               {
                  size *= 2;
                  s = tmp;
               }
               else
               {
                  free (s), s = NULL;
                  break; /* sortie d'urgence */
               }
            }
            if (c != '\n')
            {
               s[i] = c;
               i++;
            }
            else
            {
               s[i] = 0;
               break;
            }
         }

      #if DBG
         if (s != NULL)
         {
            printf ("size=%u len=%u\n", (unsigned) size, (unsigned) strlen(s));
         }
      #endif     
         return s;
      }

      • Partager sur Facebook
      • Partager sur Twitter
      Music only !
        23 mai 2006 à 15:22:47

        tout de suite -ed-,

        Sinon je ne sais toujours pas pourquoi realloc ne fonctionne pas parfois, MAIS

        j' ai reussi a contourner le probleme, par modifications successives :

        d' abord j' ai rajoute une petite boucle

        do
        {
            line = realloc(line, (len + 1) * sizeof(char));

            if (line == NULL)
            {
                printf("\nmalloc rate\n");
                printf("\nlen = %ld\n",len);
            }
        } while (line == NULL);


        je sais c est sale, dsl mais si ca tourne ca me suffit pr l instant
        donc en fait je realloc JUSQUA ce que ca m alloc quelquechose LOL

        puis a la suite de ca mon programme allait un peu plus loin mais plantait encore et toujours.

        alors je me suis dit que finalement, je vais laisser tomber l' optimisation,
        et que je n' ai besoin que d' agrandir mon tableau a certains moments.

        apres declaration de int sav = 0;
        je rajoute dans la boucle plus haut :

        if (len > sav)
            {
               line = realloc(line, (len + 1) * sizeof(char));
               sav = len;
            }


        du coup ca me realloc le tableau seulement quand il n est pas deja assez grand pour la ligne en cours...

        ca a l' air de tourner je n' ai pas encore fini de verifier...

        voici le code source et le fichier d' entree :

        code source complet
        fichier d entree (origin)
        source.c avec commentaires et debug artisanal dans tous les sens

        EDIT: ah! pas mal comme fonction je vais la tester.
        par contre le role et la nature de size sont un peu flous pour moi...

        qu est ce que le type size_t ?
        que represente size et pourquoi la multiplier par 2 a chaque reallocation ? :o
        ah super on dirait ke j ai la reponse sur ton lien...

        Merci !
        • Partager sur Facebook
        • Partager sur Twitter
          23 mai 2006 à 15:56:36

          Citation : Mr.BrYcE

          Sinon je ne sais toujours pas pourquoi realloc ne fonctionne pas parfois, MAIS


          Ca me parait bien compliqué. Etudie le code que j'ai posté au-dessus. Il suit les préceptes énoncés ici :

          http://mapage.noos.fr/emdel/notes.htm#realloc

          Après corrections :-° la solution avec fgetc() est la bonne. Pose des questions si tu ne comprends pas.

          Citation : Mr.BrYcE

          qu est ce que le type size_t ?


          http://mapage.noos.fr/emdel/notes.htm#size_t

          Citation : Mr.BrYcE

          que represente size et pourquoi la multiplier par 2 a chaque reallocation ?


          C'est vu ?

          • Partager sur Facebook
          • Partager sur Twitter
          Music only !
            23 mai 2006 à 16:21:23

            non mais en fait je ne comprends pas...

            ok alors, utiliser size_t c' est declarer un unsigned int OU long,
            et le besoin de l un ou de l autre se calcule tout seul ?

            et le soucis, dans ton premier code, c' est qu' a chaque appel de la fonction, il me recree un tableau ! mais si je veux reutiliser un tableau deja existant ? :o

            sinon il n' ya pas de cas typiques dans lesquels realloc refuse d allouer la memoire ? j' aimerais savoir pourquoi il me fait ca...

            edit: hahaha tu realloc a chaque caractere ajoute lol j y aurais pas pense... :D
            par contre est ce qu il vaut mieux multiplier les acces en memoire,
            ou lire deux fois la meme ligne d' un meme fichier ouvert :S

            ok.. plutot que de re-allouer case par case tu prefere y aller de facon exponentielle c est ca ? ^^
            merci bcp en tout cas ! c en train de rentrer...
            • Partager sur Facebook
            • Partager sur Twitter
              23 mai 2006 à 17:01:24

              Citation : Mr.BrYcE

              non mais en fait je ne comprends pas...
              ok alors, utiliser size_t c' est declarer un unsigned int OU long,
              et le besoin de l un ou de l autre se calcule tout seul ?


              EDIT: Non. size_t est tout simplement le type entier non signé qui va bien pour contenir la taille d'un objet. Enfin c'est ecrit noir sur blanc dans mon article ! Qu'est-ce que tu ne comprends pas ? Le type réel est mis par celui qui réalise l'implémentation du langage C pour telle ou telle plateforme.

              Par exemple, en x86 16-bit (MS-DOS), la taille max est 65535, donc size_t est défini unsigned int (parce que UINT_MAX vaut 65535, voir <limits.h>).

              en x86 32-bit (PC actuel sous Windows/Linux), la taille max d'un objet est 0xFFFFFFFF, ce qui est la valeur de ULONG_MAX. Le type réel est donc probabalement unsigned long (j'ai pas vérifié... <stddef.h>)

              Citation : Mr.BrYcE


              du moment que j' ai un int que j appelle len, ca suffit non ?


              Rien ne dit qu'un int est suffisament grand pour une longueur de chaine. D'ailleurs, le type retourné par strlen() est ... size_t. Tu crois que c'est par hasard ? Non. C'est une façon d'être portable.

              Citation : Mr.BrYcE


              ce qui compte c est de multiplier cette taille par sizeof(*pointeur) ?

              et le soucis, dans ton premier code, c' est qu' a chaque appel de la fonction, il me recree un tableau ! mais si je veux reutiliser un tableau deja existant ? :o


              Euh, l'expérience prouve qu'on est bien content d'avoir une chaine différente par ligne, surtout si on veut les stocker en mémoire (tableau, liste...).

              Mais si tu y tiens, il faut changer de stratégie et utiliser un objet qui stocke adresse et données

              struct chaine
              {
                 char *s;
                 size_t size;
              };

              C'est tout à fait faisable, mais je te laisse faire, parce que je fatigue un peu là... (en plus je l'ai déjà fait en version 'industrielle')

              http://mapage.noos.fr/emdel/clib.htm
              Module FSTR

              Citation : Mr.BrYcE


              sinon il n' ya pas de cas typiques dans lesquels realloc refuse d allouer la memoire ? j' aimerais savoir pourquoi il me fait ca...


              Le cas typique, c'est un débordement de mémoire qui a brisé l'organisation interne de la mémoire allouée. Le cas rare, c'est 'plus de mémoire disponible' (enfin, c'est pas rare si une appli 24/7 ne libère pas ses blocs...)

              Citation : Mr.BrYcE


              edit: hahaha tu realloc a chaque caractere ajoute lol j y aurais pas pense... :D


              Non, pas du tout. Met une trace, tu verras que size fait 1, puis 2, puis 4,8,16,32 etc. On est bien en complexité O log(n)

              Citation : Mr.BrYcE


              ok.. plutot que de re-allouer case par case tu prefere y aller de facon exponentielle c est ca ? ^^
              merci bcp en tout cas ! c en train de rentrer...


              Oui!
              • Partager sur Facebook
              • Partager sur Twitter
              Music only !
                23 mai 2006 à 17:32:24

                Citation : undefined

                C'est un entier non signé. Il est suffisament grand pour contenir la valeur représentant, en nombre de bytes, la taille du plus grand objet possible d'une implémentation donnée.



                ok en fait j' avais un peu de mal avec le vocabulaire. :euh: je suis dsl.

                Citation : undefined

                C'est un entier non signé.


                question du debutant : mais un entier ca peut etre "int" ou "long"! comment on sait?

                Citation : undefined

                Il est suffisament grand pour contenir la valeur représentant, en nombre de bytes, la taille du plus grand objet possible


                la phrase est juste, tres precise, et contient tous les termes adequats, cependant, elle est un peu longue et je pense que c' est le terme "objet" qui me genait, en fait en plus vague mais plus simple ca signifie que

                size_t est le plus grand type d' entier...

                Citation : undefined

                d'une implémentation donnée.


                ...en fonction de la machine sur laquelle il est compile ! :D

                Citation : undefined

                Tu crois que c'est par hasard ? Non. C'est une façon d'être portable.


                Bah voila. j' ai enfin compris.... MERCI :D:D:D !
                • Partager sur Facebook
                • Partager sur Twitter

                probleme avec realloc()

                × 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