IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C Discussion :

Problème avec realloc


Sujet :

C

  1. #1
    Membre éclairé
    Homme Profil pro
    amateur
    Inscrit en
    Octobre 2007
    Messages
    731
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : amateur

    Informations forums :
    Inscription : Octobre 2007
    Messages : 731
    Par défaut Problème avec realloc
    Bonjour,

    J'ai une erreur à cette ligne : error: invalid operands to binary *

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    TestRealloc = (char *)realloc( TestRealloc, (*LongueurNouvelleChaine+1)*sizeof(char) );
    Je ne comprends pas pourquoi il braille ici !

    et aussi à cette ligne : error: array subscript is not an integer

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    (*NouvelleChaine)[*LongueurNouvelleChaine] = Chaine[i];
    Pourtant LongueurNouvelleChaine est bien de type int.

    On dit qu'il faut initialiser les pointeurs à null puis les tester ensuite.
    Il faut tester uniquement si on a fait une allocation mémoire pour vérifier le retour de l'allocation ?


    Voici le code en entier :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    #include <stdio.h>
    #include <stdlib.h>
     
    int LongueurChaine( char *Chaine );
    void SupprimerOccurenceDansChaine( char *Chaine, int LongueurChaine, char **NouvelleChaine, int **LongueurNouvelleChaine, char Occurrence );
     
    int main()
    {
        char *Chaine="bonjour";
        printf("\n\n Longueur de \"%s\" = %d", Chaine, LongueurChaine( Chaine ) );
     
        int  *NouvelleLongueur;
        char *NouvelleChaine  ;
     
        SupprimerOccurenceDansChaine( Chaine, LongueurChaine( Chaine ), &NouvelleChaine, &NouvelleLongueur, 'b' );
     
        int i;
        for ( i=0 ; i<*NouvelleLongueur ; i++ )
            {
                printf("%c", NouvelleChaine[i]);
            }
     
        free(Chaine);
        free(NouvelleLongueur);
        free(NouvelleChaine);
        return 0;
    }
     
    int LongueurChaine( char *Chaine )
    {
        int Longueur = 0;
     
        while ( *Chaine != '\0' )
              {
                  Longueur++;
                  Chaine++;
              }
     
        return Longueur;
    }
     
    void SupprimerOccurenceDansChaine( char *Chaine, int LongueurChaine, char **NouvelleChaine, int **LongueurNouvelleChaine, char Occurrence )
    {
        *NouvelleChaine         = NULL;
        *LongueurNouvelleChaine = NULL;
     
        *LongueurNouvelleChaine = (int *)malloc( sizeof( int ) );
        *LongueurNouvelleChaine = 0;
     
        char *TestRealloc = NULL;
     
        if ( Chaine != NULL && NouvelleChaine != NULL && LongueurNouvelleChaine != NULL )
           {
               int i;
               for ( i=0 ; i<LongueurChaine ; i++ )
                   {
                       if ( Chaine[i] != Occurrence )
                          {
                              TestRealloc = (char *)realloc( TestRealloc, (*LongueurNouvelleChaine+1)*sizeof(char) );
     
                              if ( TestRealloc != NULL )
                                 {
                                      *NouvelleChaine                           = TestRealloc;
                                     (*NouvelleChaine)[*LongueurNouvelleChaine] = Chaine[i];
                                      *LongueurNouvelleChaine                   = *LongueurNouvelleChaine + 1;
                                 }
     
                            else {
                                     *NouvelleChaine         = NULL;
                                     *LongueurNouvelleChaine = 0;
                                 }
                          }
                   }
           }
     
        else printf("ERREUR");
     
        free(TestRealloc);
    }

  2. #2
    Membre émérite
    Avatar de Pouet_forever
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    671
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 671
    Par défaut
    LongueurNouvelleChaine est un pointeur de pointeur mais toi tu l'utilises en tant que pointeur seul, du coup ça ne va pas =)
    Tu voulais peut-être mettre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    char *TestRealloc = (char *)realloc( TestRealloc, (**LongueurNouvelleChaine+1)*sizeof(char) );
    (*NouvelleChaine)[**LongueurNouvelleChaine] = Chaine[i];

  3. #3
    Membre émérite Avatar de SofEvans
    Homme Profil pro
    Développeur C
    Inscrit en
    Mars 2009
    Messages
    1 084
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France

    Informations professionnelles :
    Activité : Développeur C

    Informations forums :
    Inscription : Mars 2009
    Messages : 1 084
    Par défaut
    Euh, juste une question.

    Apparement, comme l'indique son nom, NouvelleLongueurChaine est fait pour stocker la longueur de la nouvelle chaine. Ce sera donc un int. Si tu veux le modifier, il faut, effectivement, le passer en pointeur. Or, dans le main, cette variable est déjà un pointeur !

    Pourquoi passer un pointeur par pointeur ??

  4. #4
    Membre éclairé
    Homme Profil pro
    amateur
    Inscrit en
    Octobre 2007
    Messages
    731
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : amateur

    Informations forums :
    Inscription : Octobre 2007
    Messages : 731
    Par défaut
    Merci, en effet...

    Apparement, le programme ne passe pas le test realloc

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    TestRealloc = (char *)realloc( TestRealloc, (**LongueurNouvelleChaine+1)*sizeof(char) );
    Mais là j'avoue ne pas m'en sortir. Merci d'avance.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    #include <stdio.h>
    #include <stdlib.h>
     
    int LongueurChaine( char *Chaine );
    void SupprimerOccurenceDansChaine( char *Chaine, int LongueurChaine, char **NouvelleChaine, int **LongueurNouvelleChaine, char Occurrence );
     
    int main()
    {
        char *Chaine="bonjour";
        printf("\n\n Longueur de \"%s\" = %d", Chaine, LongueurChaine( Chaine ) );
     
        int  *NouvelleLongueur;
        char *NouvelleChaine  ;
     
        SupprimerOccurenceDansChaine( Chaine, LongueurChaine( Chaine ), &NouvelleChaine, &NouvelleLongueur, 'b' );
     
        int i;
        for ( i=0 ; i<*NouvelleLongueur ; i++ )
            {
                printf("%c", NouvelleChaine[i]);
            }
     
        free(Chaine);
        free(NouvelleLongueur);
        free(NouvelleChaine);
        return 0;
    }
     
    int LongueurChaine( char *Chaine )
    {
        int Longueur = 0;
     
        while ( *Chaine != '\0' )
              {
                  Longueur++;
                  Chaine++;
              }
     
        return Longueur;
    }
     
    void SupprimerOccurenceDansChaine( char *Chaine, int LongueurChaine, char **NouvelleChaine, int **LongueurNouvelleChaine, char Occurrence )
    {
        *NouvelleChaine         = NULL;
        *LongueurNouvelleChaine = NULL;
     
        *LongueurNouvelleChaine = (int *)malloc( sizeof( int ) );
        *LongueurNouvelleChaine = 0;
     
        char *TestRealloc = NULL;
        printf("\n 1");
        if ( Chaine != NULL && NouvelleChaine != NULL && LongueurNouvelleChaine != NULL )
           {
               printf("2");
               int i;
               for ( i=0 ; i<LongueurChaine ; i++ )
                   {
                       if ( Chaine[i] != Occurrence )
                          {
                              printf("3");
                              TestRealloc = (char *)realloc( TestRealloc, (**LongueurNouvelleChaine+1)*sizeof(char) );
                              printf("3 bis");
                              if ( TestRealloc != NULL )
                                 {
                                     printf("4");
                                      *NouvelleChaine                           = TestRealloc;
                                     (*NouvelleChaine)[**LongueurNouvelleChaine] = Chaine[i];
                                      **LongueurNouvelleChaine                   = **LongueurNouvelleChaine + 1;
                                 }
     
                            else {
                                    printf("5");
                                     *NouvelleChaine         = NULL;
                                     *LongueurNouvelleChaine = 0;
                                 }
                          }
                   }
           }
     
        else printf("ERREUR");
     
        free(TestRealloc);
    }

  5. #5
    Membre éclairé
    Homme Profil pro
    amateur
    Inscrit en
    Octobre 2007
    Messages
    731
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : amateur

    Informations forums :
    Inscription : Octobre 2007
    Messages : 731
    Par défaut
    Citation Envoyé par SofEvans Voir le message
    Euh, juste une question.

    Apparement, comme l'indique son nom, NouvelleLongueurChaine est fait pour stocker la longueur de la nouvelle chaine. Ce sera donc un int. Si tu veux le modifier, il faut, effectivement, le passer en pointeur. Or, dans le main, cette variable est déjà un pointeur !

    Pourquoi passer un pointeur par pointeur ??
    Tout comme NouvelleChaine, comme je fais son allocation dans la fonction et que je modifié son contenu, je suis bien obligé de passer par adresse un pointeur d'où la necessité d'un double pointeur ? ou alors je n'ai pas compris. Il y a plus simple je l'accorde mais c'est pour m'entraîner, tester différente situations, apparemment j'en ai besoin.

  6. #6
    Membre éclairé
    Homme Profil pro
    amateur
    Inscrit en
    Octobre 2007
    Messages
    731
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : amateur

    Informations forums :
    Inscription : Octobre 2007
    Messages : 731
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    void SupprimerOccurenceDansChaine( char *Chaine, int LongueurChaine, char **NouvelleChaine, int **LongueurNouvelleChaine, char Occurrence )
    {
        *NouvelleChaine         = NULL;
        *LongueurNouvelleChaine = NULL;
     
        *LongueurNouvelleChaine = (int *)malloc( sizeof( int ) );
        (*LongueurNouvelleChaine)[0] = 0;
     
        char *TestRealloc = NULL;
        printf("\n 1");
        if ( Chaine != NULL && NouvelleChaine != NULL && LongueurNouvelleChaine != NULL )
           {
               printf("2");
               int i;
               for ( i=0 ; i<LongueurChaine ; i++ )
                   {
                       if ( Chaine[i] != Occurrence )
                          {
     
                              printf("\n Lg = %d", (*LongueurNouvelleChaine)[0]);
                              TestRealloc = (char *)realloc( TestRealloc, (**LongueurNouvelleChaine+1)*sizeof(char) );
     
                              if ( TestRealloc != NULL )
                                 {
     
                                      *NouvelleChaine                            = TestRealloc;
                                     (*NouvelleChaine)[**LongueurNouvelleChaine] = Chaine[i];
                                       printf("\%c",(*NouvelleChaine)[**LongueurNouvelleChaine]);
                                     (*LongueurNouvelleChaine)[0]                = (*LongueurNouvelleChaine)[0] + 1;
                                 }
     
                            else {
     
                                     *NouvelleChaine         = NULL;
                                     *LongueurNouvelleChaine = 0;
                                 }
                          }
                   }
           }
     
        else printf("ERREUR");
     
        free(TestRealloc);
    }
    En ecrivant comme ça, cette fois les affectations sont correctes et dans la fonctions se passe ce qu'il doit se passer. Cependant arrivé dans le main badaboum cela m'affiche n'importe quoi ! Auriez vous une idée ? merci.

    Je viens de m'apercevoir que cela vient de

    une fois enlevé, ça affiche dans le main. Du coup je ne comprends pas pourquoi le free sur le TestRealloc libère aussi NouvelleChaine. A ce stade, la boucle est pourtant terminée et NouvelleChaine a bien reçu les valeurs.
    Ca marche sans le free, cependant, j'aimerais comprendre pourquoi il fait foirer l'execution sachant que j'aimerais bien le libérer quand même xD.

    Merci d'avance

  7. #7
    Membre émérite Avatar de SofEvans
    Homme Profil pro
    Développeur C
    Inscrit en
    Mars 2009
    Messages
    1 084
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France

    Informations professionnelles :
    Activité : Développeur C

    Informations forums :
    Inscription : Mars 2009
    Messages : 1 084
    Par défaut
    Je suis en train de regarder ton code :

    int LongueurChaine(char *Chaine) est-il censer renvoyer le nombre de case allouer a la chaine de caractere ? En fait, c'est la fonction strlen, non ?

    Voici ce que je te propose :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    int LongueurChaine(char *Chaine)
    {
        int Longueur;
        for (Longueur=0 ; Chaine[Longueur] != '\0' ; Longueur++); 
     
        return Longueur;
    }
    Je continue a regarder ton code

    EDIT : Autant pour moi, j'avais mal imaginé la chose. Donc c'est bien return Longueur, j'ai editer mon message pour effecer ma betise ...

  8. #8
    Membre éclairé
    Homme Profil pro
    amateur
    Inscrit en
    Octobre 2007
    Messages
    731
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : amateur

    Informations forums :
    Inscription : Octobre 2007
    Messages : 731
    Par défaut
    Merci, oui c'est bien la fonction strlen qui est re-implémentée, j'aurais pas pensé à votre version, ça change des habitudes merci d'avoir réécrit autrement ça fait voir d'autres manières. Le prof le voulais donc bon. Mais pour le free sur le testrealloc, je comprends vraiment pas son problème Et si je ne mets pas le free sur un pointeur qui a été alloué dynamiquement, mon prof va me taper sur les doigts

  9. #9
    Membre éclairé
    Homme Profil pro
    amateur
    Inscrit en
    Octobre 2007
    Messages
    731
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : amateur

    Informations forums :
    Inscription : Octobre 2007
    Messages : 731
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    void SupprimerOccurenceDansChaine( char *Chaine, int LongueurChaine, char **NouvelleChaine, int **LongueurNouvelleChaine, char Occurrence )
    {
        *NouvelleChaine         = NULL;
        *LongueurNouvelleChaine = NULL;
     
        *LongueurNouvelleChaine = (int *)malloc( sizeof( int ) );
        **LongueurNouvelleChaine = 0;
     
        char *TestRealloc = NULL;
        if ( Chaine != NULL && NouvelleChaine != NULL && LongueurNouvelleChaine != NULL )
           {
               int i;
               for ( i=0 ; i<=LongueurChaine ; i++ )
                   {
                       if ( Chaine[i] != Occurrence )
                          {
                              TestRealloc = (char *)realloc( TestRealloc, (**LongueurNouvelleChaine+1)*sizeof(char) );
     
                              if ( TestRealloc != NULL )
                                 {
     
                                      *NouvelleChaine                            = TestRealloc;
                                     (*NouvelleChaine)[**LongueurNouvelleChaine] = Chaine[i];
                                     **LongueurNouvelleChaine                    = **LongueurNouvelleChaine + 1;
                                 }
     
                            else {
     
                                     *NouvelleChaine         = NULL;
                                     **LongueurNouvelleChaine = 0;
                                 }
                          }
                   }
           }
     
        else printf("ERREUR");
     
        //free(TestRealloc);
    }
    J'ai une question qui me turlupine. Si on décidait de faire une implémentation dans les normes, doit-on initialiser un pointeur à NULL avant d'entrer dans une fonction qui va effectuer un traitement dessus ou peut-on se permettre d'écrire :

    dans le main par exemple sachant que la fonction fera l'initialisation du pointeur à NULL ? ou pas ou alors peut-on faire les deux ?


    J'aurais également une autre question sur le test de retour d'une allocation.
    Quand le realloc fait dans son pantalon, on a le else qui met le pointeur sur NouvelleChaine à NULL et la longueur ré-initialisée à 0. Si ça arrive dans le courant de la boucle, à vrai dire je ne comprends pas trop ce qui va se passer. La boucle s'interrompt et le programme plante ou bien il recommence depuis le début la boucle ? Car à ce moment là il faudrait refaire l'allocation puis recommencer la boucle ? Donc en gros est-ce possible si une allocation foire, de dire tu ne plantes pas mais fais en sorte que la boucle reprenne comme la première fois s'il y a problème d'allocation ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
                              TestRealloc = (char *)realloc( TestRealloc, (**LongueurNouvelleChaine+1)*sizeof(char) );
     
                              if ( TestRealloc != NULL )
                                 {
     
                                      *NouvelleChaine                            = TestRealloc;
                                     (*NouvelleChaine)[**LongueurNouvelleChaine] = Chaine[i];
                                     **LongueurNouvelleChaine                    = **LongueurNouvelleChaine + 1;
                                 }
     
                            else {
     
                                     *NouvelleChaine         = NULL;
                                     **LongueurNouvelleChaine = 0;
                                 }
                          }

  10. #10
    Membre émérite Avatar de SofEvans
    Homme Profil pro
    Développeur C
    Inscrit en
    Mars 2009
    Messages
    1 084
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France

    Informations professionnelles :
    Activité : Développeur C

    Informations forums :
    Inscription : Mars 2009
    Messages : 1 084
    Par défaut
    Erf, je me suis fait avoir comme un gros debutant ... vais devoir aller me coucher ...

    Voici le code que je te propose, je pense qu'il est suffisament commenter.
    Sinon, tu sais quoi faire.
    Je me suis permis de tout changer car je trouvait qu'il y avait beaucoup de parametre inutile.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    int LongueurChaine (char *Chaine);
    void SupprimerOccurenceDansChaine(char *Chaine, char Occurrence);
     
    int main()
    {
        char Chaine[] = "bbobbnjourbb";
     
        printf("Longueur de \"%s\" = %d\n\n", Chaine, LongueurChaine(Chaine));
     
        SupprimerOccurenceDansChaine (Chaine, 'b');
     
        int i;
        for (i=0 ; i<LongueurChaine(Chaine) ; i++)
            printf("%c", Chaine[i]);
     
        return 0;
    }
     
    int LongueurChaine (char *Chaine)
    {
        int Longueur;
        for (Longueur=0 ; Chaine[Longueur] != '\0' ; Longueur++);
     
        return Longueur;
    }
     
    void SupprimerOccurenceDansChaine(char *Chaine, char Occurrence)
    {
        char *ChaineSansOccurence = NULL;
        int longueurChaine = 1;
     
        /* On parcours toutes la chaine passer en argument jusqu'a '\0', '\0' compris.
           C'est pourquoi le test est <= et non < tout seul */
        int i;
        for (i=0 ; i<=LongueurChaine(Chaine) ; i++)
            /* Si on trouve un caractere a copier */
            if (Chaine[i] != Occurrence)
            {
                /* On alloue une case de plus */
                char *Temporaire = realloc (ChaineSansOccurence, longueurChaine*sizeof(char));
                if (Temporaire != NULL)
                {
                    /* et on copie le caractere dedans, sans oublier la MAJ */
                    ChaineSansOccurence = Temporaire;
                    ChaineSansOccurence[longueurChaine-1] = Chaine[i];
                    longueurChaine++;
                }
                else
                {
                    /* Erreur, a toi de voir ce que tu va faire */
                }
            }
     
        /* Ici, nous avons parcouru toute la chaine et ChaineSansOccurence = Chaine - toutes les occurence
           ON va donc copier ChaineSansOccurence dans Chaine */
        strcpy(Chaine, ChaineSansOccurence);
        free(ChaineSansOccurence);
    }
    Par contre, chaine est un char[] et non un char*. Mon code ne fonctionnerai plus si c'est un char*.

  11. #11
    Membre éclairé
    Homme Profil pro
    amateur
    Inscrit en
    Octobre 2007
    Messages
    731
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : amateur

    Informations forums :
    Inscription : Octobre 2007
    Messages : 731
    Par défaut
    Ah oui merci, moins de paramètres moins de pointeurs = moins mal au crâne xD.

    Merci pour ton temps.

  12. #12
    Membre émérite
    Avatar de Pouet_forever
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    671
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 671
    Par défaut
    Je pense que plutôt qu'avoir accès à realloc à chaque fois il serait plus judicieux d'allouer un grand tableau dès le départ et ensuite de réallouer si nécessaire. Je pense que le mieux serait carrément d'allouer la taille de la chaîne de départ et ensuite de faire les opérations et ne plus se soucier de la longueur.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    #include <stdio.h>
    #include <stdlib.h>
     
    int LongueurChaine (char *Chaine);
    char *str_cpy (char *dst, char const *src);
    void SupprimerOccurenceDansChaine(char *Chaine, char Occurrence);
     
    int main(void) {
    	char Chaine[] = "bbobbnjourbb";
     
    	printf("Longueur de \"%s\" = %d\n\n", Chaine, LongueurChaine(Chaine));
    	SupprimerOccurenceDansChaine (Chaine, 'b');
    	printf("%s", Chaine);
     
    	return EXIT_SUCCESS;
    }
     
    int LongueurChaine (char *Chaine) {
    	char *tmp = Chaine;
    	for ( ; *tmp ; tmp++);
    	return tmp - Chaine;
    }
     
    char *str_cpy (char *dst, char const *src) {
    	char *tmp = dst;
    	for ( ; (*dst = *src); src++, dst++);
    	return tmp;
    }
     
    void SupprimerOccurenceDansChaine(char *Chaine, char Occurrence) {
    	int i, j = 0;
    	int len = LongueurChaine(Chaine) + 1;
    	char *ChaineSansOccurence = malloc(len * sizeof(char));
     
    	if (ChaineSansOccurence == NULL)
    		exit(EXIT_FAILURE);
     
    	for (i = 0; Chaine[i] != '\0'; i++)
    		if (Chaine[i] != Occurrence)
    			ChaineSansOccurence[j++] = Chaine[i];
     
    	ChaineSansOccurence[j] = '\0';
    	str_cpy(Chaine, ChaineSansOccurence);
    	free(ChaineSansOccurence);
    }

  13. #13
    Membre éclairé
    Homme Profil pro
    amateur
    Inscrit en
    Octobre 2007
    Messages
    731
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : amateur

    Informations forums :
    Inscription : Octobre 2007
    Messages : 731
    Par défaut
    Wahou c'est violent, merci pour vos optimisations !
    Si j'utilise realloc, c'est pour m'entraîner à l'utiliser correctement ce pourquoi avant d'utiliser vos méthodes j'aimerais faire fonctionner les miennes avec le realloc.

    Dans une autre fonction dont le but est de supprimer tous les caractères communs à deux chaines, puis mettre cette nouvelle chaine dans la chaine passé en argument 1 de la fonction, j'ai encore une erreur avec realloc.
    En fait, j'essaye de ré-allouer à s1 la taille de la nouvelle chaîne.

    Le test sur realloc me renvoit "erreur" c'est à dire que le retour est NULL. Je pensais que le problème était du au fait que je passais char *s1 = "chaine"; et donc que je ne faisais pas explicitement un malloc. J'ai donc fait un malloc puis ai entré la chaine mais rien a changé. Auriez vous une petite idée ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    #include <stdio.h>
    #include <stdlib.h>
     
    int  LongueurChaine              ( char *Chaine                             );
    void SupprimerOccurence2Chaine( char *s1, char *s2 );
     
    int main()
    {
     
        char *s1=  "azertyqwerty";  
        char *s3 = "azertyqwerty";
        char *s4 = "keyboard";
        SupprimerOccurence2Chaine( s3, s4 );
        printf("\n\n s1 : \"%s\" \n s2 : \"%s\" \n s  : \"%s\" sans les caracteres communs aux deux chaines s1 et s2\n\n", s1, s4, s3);
     
        free(s1);
        free(s3);
        free(s4);
        return 0;
    }
     
     
    void SupprimerOccurence2Chaine( char *s1, char *s2 )
    {
        char *RetourRealloc = NULL;
        int   Longueur=0;
     
        int i;
        // Pour chaque caractère de s1
        for ( i=0 ; i<LongueurChaine(s1) ; i++ )
            {
                int Trouve=0;
                int j;
                for ( j=0 ; j<LongueurChaine(s2) ; j++ )
                    {
                        // On regarde s'il est compris dans la deuxième chaine
                        if ( s1[i] == s2[j] )
                           {
                               // Si c'est le cas on incrémente Trouve
                               Trouve++;
                           }
                    }
     
                 // Si le caractère n'a pas été trouvé alors on peut le recopier dans la chaine
                 if ( Trouve == 0 )
                    {
                        RetourRealloc = (char *)realloc( RetourRealloc, (Longueur+1)*sizeof(char) );
     
                        // Après avoir réalloué une case mémoire pour chaque caractère recopiable
                        if ( RetourRealloc != NULL )
                           {
                               // Si le retour de l'allocation est non NULL, on recopie le caractère
                               RetourRealloc[Longueur] = s1[i];
                               printf("%c", RetourRealloc[Longueur] );
                               Longueur++;
                           }
     
                      else {
                               // Sinon on recommence à 0
                               free(RetourRealloc);
                               SupprimerOccurence2Chaine( s1, s2 );
                           }
                    }
            }
     
     
            // On détermine la nouvelle taille de s1 ( on rajoute une case pour le \0 )
            int NouvelleTaille_s1=LongueurChaine(s1)-Longueur+1;
     
            char *RetourRealloc2 = (char *)realloc( RetourRealloc2, NouvelleTaille_s1*sizeof(char) );
     
            // Si le retour de l'allocation est non NULL
            if ( RetourRealloc2 != NULL )
               {
                   for ( i=0 ; i<NouvelleTaille_s1-1 ; i++ )
                       {
                           // On recopie la nouvelle chaine dans la chaine s1
                           s1 = RetourRealloc2;
                           s1[i]=RetourRealloc[i];
                           printf("\n%c %c", RetourRealloc[i], s1[i] );
                       }
     
     
                   // On oublie pas \0 pour terminer la chaine
                   s1[NouvelleTaille_s1-1]='\0';
               }
     
          // Sinon on arrête le programme
          else {
     
                   exit(-1);
                   printf("erreur");
               }
     
        // free(TestRealloc);
        // free(TestRealloc2);
    }

  14. #14
    Membre émérite Avatar de SofEvans
    Homme Profil pro
    Développeur C
    Inscrit en
    Mars 2009
    Messages
    1 084
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France

    Informations professionnelles :
    Activité : Développeur C

    Informations forums :
    Inscription : Mars 2009
    Messages : 1 084
    Par défaut
    Bonjour,

    je trouve que permettre un appel recursif est une tres mauvaise idée, surtout que tu ne fais rien pour gerer les erreurs. En gros, tu va obtenir des chose que tu ne voudrais pas si tu as une erreur.

    Pour alleger le code, je te propose de regarder les commentaire du mien :
    j'ai a un moment donné dit que pour copier integralement la chaine sans occurence (donc, chaine avec '\0'), j'avais mis le signe "<=" et pas seulement "<".

    Je te conseille dans un premier temps de ne plus faire d'appel recursif, et d'afficher avec un perror le probleme qu'aura rencontrer realloc.

  15. #15
    Membre émérite
    Avatar de Pouet_forever
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    671
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 671
    Par défaut
    Comme l'a dit SofEvans plus haut, il faut que ta chaîne soit de type [] et non *
    Quand tu déclares tes chaînes, en fait, tu fais pointer ton pointeur sur une chaîne de caractères constante !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    char s1[] =  "azertyqwerty";  
    char s3[] = "azertyqwerty";
    char s4[] = "keyboard";

  16. #16
    Membre éclairé
    Homme Profil pro
    amateur
    Inscrit en
    Octobre 2007
    Messages
    731
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : amateur

    Informations forums :
    Inscription : Octobre 2007
    Messages : 731
    Par défaut
    Citation Envoyé par Pouet_forever Voir le message
    Comme l'a dit SofEvans plus haut, il faut que ta chaîne soit de type [] et non *
    Quand tu déclares tes chaînes, en fait, tu fais pointer ton pointeur sur une chaîne de caractères constante !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    char s1[] =  "azertyqwerty";  
    char s3[] = "azertyqwerty";
    char s4[] = "keyboard";
    Ok, apparement il y a des notions que je n'ai pas encore intégré. Pour la recursivité sur l'erreur oui en effet, je pensais mettre une variables qui compte le nombre d'erreur et si ce quotas est dépassé alors on arrête le programme pour pas boucler indefinement si à la compilation l'erreur est récurrente. Après je ne sais pas si c'est comme ça que la gestion de cette erreur doit se faire, c'est un idée mais comme vous l'avez dit ce n'est pas encore le propos

  17. #17
    Membre émérite Avatar de SofEvans
    Homme Profil pro
    Développeur C
    Inscrit en
    Mars 2009
    Messages
    1 084
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France

    Informations professionnelles :
    Activité : Développeur C

    Informations forums :
    Inscription : Mars 2009
    Messages : 1 084
    Par défaut
    Et surtout, je me permet de re-insister sur ce point : tester s'il y a eu une erreur, c'est bien.

    Gerer algorithmiquement l'erreur, c'est mieux.

    Mais le "must", c'est de tester, gerer et informer.

    Pas forcement l'utilisateur (ca va lui faire une belle manche de savoir qu'il y a eu un SefFault), mais au moins toi, via le fichier stderr.

    En C standart, perror() le fait a merveille.

    Donc, prend l'habitude d'integrer perror a chaque fois que tu teste quelque chose qui est retourné par une fonction standart.

  18. #18
    Membre éclairé
    Homme Profil pro
    amateur
    Inscrit en
    Octobre 2007
    Messages
    731
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : amateur

    Informations forums :
    Inscription : Octobre 2007
    Messages : 731
    Par défaut
    Voilà ceci fonctionne

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    void SupprimerOccurence2Chaine( char *s1, char *s2 )
    {
        char *ChaineTemporaire = NULL;
        int   Longueur=1;
     
        int i;
        // Pour chaque caractère de s1
        for ( i=0 ; i<LongueurChaine(s1) ; i++ )
            {
                int Trouve=0;
                int j;
                for ( j=0 ; j<=LongueurChaine(s2) ; j++ )
                    {
                        // On regarde s'il est compris dans la deuxième chaine
                        if ( s1[i] == s2[j] )
                           {
                               // Si c'est le cas on incrémente Trouve
                               Trouve++;
                           }
                    }
     
                 // Si le caractère n'a pas été trouvé alors on peut le recopier dans la chaine
                 if ( Trouve == 0 )
                    {
                        char *RetourRealloc = (char *)realloc( ChaineTemporaire, Longueur*sizeof(char) );
     
                        // Après avoir réalloué une case mémoire pour chaque caractère recopiable
                        if ( RetourRealloc != NULL )
                           {
                               // Si le retour de l'allocation est non NULL, on recopie le caractère
                               ChaineTemporaire = RetourRealloc;
                               ChaineTemporaire[Longueur-1] = s1[i];
                               Longueur++;
                           }
     
                      else {
                               // Sinon on recommence à 0
                               printf("erreur");
                           }
                    }
            }
     
     
            strcpy( s1, ChaineTemporaire);
            free(ChaineTemporaire);
    }
    Pour que ça marche avec des char * si j'ai bien compris, il faut que j'utilise une fonction autre que strcpy car elle demande un const char ?
    Surtout que je ne dois pas utiliser de fonction présente dans les bibliothèques standards si possible. Je vais voir les ce que je peux faire à ce propos.

    Merci de m'avoir aidé !

    EDIT : je ne connais pas perror, je vais me documenter voir ce que je trouve.

  19. #19
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    'doit y avoir moyen de le faire sans allocation aucune, comme pour supprimer les occurrences d'un caractère, non?
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  20. #20
    Membre éclairé
    Homme Profil pro
    amateur
    Inscrit en
    Octobre 2007
    Messages
    731
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : amateur

    Informations forums :
    Inscription : Octobre 2007
    Messages : 731
    Par défaut
    C'est pour m'entrainer que je veux utiliser les malloc, je dis pas que c'est judicieux.

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Réponses: 4
    Dernier message: 10/03/2008, 03h59
  2. Problème avec realloc et struct
    Par _SamSoft_ dans le forum Bibliothèque standard
    Réponses: 38
    Dernier message: 27/12/2007, 10h13
  3. Re-problème avec realloc() (désolé)
    Par Yabo dans le forum C
    Réponses: 8
    Dernier message: 30/07/2003, 22h07
  4. Problème avec la mémoire virtuelle
    Par Anonymous dans le forum CORBA
    Réponses: 13
    Dernier message: 16/04/2002, 16h10

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo