Fonction qui insert un mot dans un autre

Résolu
Joujou98 -  
mamiemando Messages postés 33228 Date d'inscription   Statut Modérateur Dernière intervention   -
Bonjour,

On nous demande d'écrire une fonction
strinsert(char * M, char * T, int i)
qui insert un mot
T
dans
M
à la position
i
en utilisant un tableau dynamique et les fonctions de
<string.h>
.

J'arrive pas à le faire mais voilà mon code :

void strinsert(char *M, char *T, int i) {
    if (strlen(M) <= strlen(T)) {
        ModifierCapacite(M,T);
    }

    for (int j = strlen(M) - 1; j>0; j--) {
        M[j + 2] = M[j] ;
    }
    for (int j = i - 1 ; j <= strlen(T) ; j++) {
        strcpy(M[j], T[j - 1]);
    }
    printf("final copied string %s", M);
}

void ModifierCapacite(char * M, char * T)
{
    char * tmp;
    if (!tmp) {
        exit(EXIT_FAILLURE);
    }
    tmp = (char *) malloc(strlen(M) * sizeof(char));
    strcpy(tmp, M);
    free(M);
    M = (char *) malloc((strlen(M) + strlen(T)) * sizeof(char));
    strcpy(M, tmp);
}


EDIT: coloration syntaxique + indentation
Configuration: Android / Chrome 70.0.3538.80

1 réponse

  1. mamiemando Messages postés 33228 Date d'inscription   Statut Modérateur Dernière intervention   7 944
     
    Bonjour,

    Conseils préliminaires

    - indente ton code (cf message corrigé) ça t'aidera à ne pas oublier d'accolade (j'en ai rajouté)
    - utilise les balises de code
    - fournit un code compilable et exécutable (avec une fonction main, les #include qui vont bien, etc)
    - n'écrit pas ton programme en un coup : rajoute progressivement des instructions, compile, teste, et si c'est bon, continue à le faire grossir. Ici par exemple ton strinsert appelle la fonction
    ModifierCapacite
    ... qui n'est pas encore déclarée (et qui était mal orthographié en plus dans ton message initial !)
    - le C suit des conventions de notations. Par exemple le nom d'une fonction s'écrit généralement tout en minuscule avec des _ (par exemple
    ma_fonction
    ) et parfois
    maFonction
    . Je préconise la première.
    - toujours dans les notations, un nom de variable en capitale désigne normalement une constante (ce qui n'est pas le cas de ton
    M
    ou de ton
    T
    ).
    - choisis des noms de variables parlants (M et T, bof bof). Une chaine par exemple s'appelle plutôt
    s
    .
    - les pointeurs reçus en paramètre de fonctions et non modifiés par la fonction devraient être
    const
    .

    Retour à ton problème

    Dans ce qui suit je renomme
    M
    en
    s_input
    et
    T
    en
    s_insert
    . J'appelle
    s_output
    la chaîne que tu veux construire.

    Première question : puis je réutiliser
    s_input
    ? Non, car
    s_output
    est plus grande, donc on ne peut pas ajouter ce qui manque et décaler le suffixe. Il va donc falloir recontruire
    s_output
    à partir de
    s_input
    et
    s_insert
    .

    Deuxième question : est-ce que je connais la taille de
    s_output
    ? est-ce que je la connais à la compilation (de manière absolue, car c'est une constante), auquel cas une allocation statique est envisageable ; où à l'exécution (donc de manière dynamique, car ça dépend de ce qui se passe à l'exécution du programme) ? Ici la taille de
    s_ouput
    égale la taille de
    s_input
    + la taille de
    s_insert
    . Ça dépend de deux variables donc on doit faire une allocation dynamique (cf
    malloc
    ). Et qui dit
    malloc
    dit
    free
    si le pointeur a été créé avec succès, comme ça on évite une fuite mémoire.

    Maintenant comment procéder :
    - il faut recopier les
    i
    premiers caractères de
    s_input
    dans s_output ; pour ça on va utiliser
    strncpy
    ,
    - à la suite de quoi il faut écrire
    s_insert
    ; comme ici je vais tout écrire tout jusqu'à la fin de la chaîne je peux utiliser
    strcpy
    ,
    - à la suite de quoi il faut écrire la fin du mot
    s_input
    .

    Pour appeler correctement ces fonctions, toute la difficulté réside dans :
    - à partir de quel index je lis dans
    s_input

    - à quel endroit j'écris dans
    s_output


    Et une fois qu'on a réfléchi à tout ça on arrive à ce programme :

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    char * insert_str(const char * s_input, const char * s_insert, size_t i) {
        size_t len_input = strlen(s_input),
               len_insert = strlen(s_insert);
        char * s_output = malloc(len_input + len_insert + 1);
        if (s_output) {
          strncpy(s_output, s_input, i);
          strcpy (s_output + i, s_insert);
          strcpy (s_output + i + len_insert, s_input + i);
        }
        return s_output;    
    }                         
                              
    int main() {              
        char * s_input = "Bonjour, ça va ?";
        char * s_insert = " Joujou";
        char * s_output = insert_str(s_input, s_insert, 7);
    
        if (s_output) {
            printf("s_output = [%s]\n", s_output);
            free(s_output);
        } else {
            fprintf(stderr, "erreur mémoire\n");
            return 1;
        }
        return 0;
    }


    ... qui donne :

    s_output = [Bonjour Joujou, ça va ?]


    Remarque :

    Pour faire les choses bien, on devrait contrôler au début de
    insert_str
    que :
    -
    i
    est plus petit que
    len_input
    . Pour cela tu peux utiliser la fonction
    assert
    , fournie par
    <assert.h>
    .
    -
    s_input
    et
    s_insert
    sont non
    NULL
    .

    char * insert_str(const char * s_input, const char * s_insert, size_t i) {
        assert(i < len_input);
        assert(s_input);
        assert(s_insert);
        //...
    }


    Remarque :

    Pour plus de détails sur les fonctions utilisées, mettons
    strncpy
    , tape dans un terminal linux ou dans google
    man strncpy
    .

    Une autre manière de faire

    On aurait pu imaginer de :
    -
    realloc
    la chaîne
    s_input 
    pour augmenter la capacité du bloc mémoire associé,
    - décaler le suffixe de
    len_insert
    octets vers la droite à l'aide de
    memmove
    ou
    strcpy
    ,
    - et enfin recopier
    s_insert
    à l'endroit approprié (avec
    strcpy
    ou
    memcpy
    ).

    Ainsi la chaîne
    s_input
    devient
    s_output
    (et doit du coup être passé en tant que
    char *
    , puisqu'elle est modifiée).

    Tout dépend de ce qu'on veut faire. Dans le code que j'ai proposé,
    s_input
    reste dans son état originel.

    Bonne chance
    0
    1. [Dal] Messages postés 6122 Date d'inscription   Statut Contributeur Dernière intervention   1 108
       
      Salut mamiemando :-)

      A cette ligne,
      char * s_output = malloc(len_input + len_insert);
      , tu as oublié d'ajouter
      + 1
      à la quantité de mémoire demandée (donc
      char * s_output = malloc(len_input + len_insert + 1);
      ).

      @Joujou98: cet ajout est nécessaire afin que l'espace mémoire soit suffisant pour accueillir la longueur des deux chaînes déterminée par
      strlen()
      et le caractère de fin de chaîne
      '\0'
      , qui n'est pas compté par
      strlen()
      .
      0
    2. mamiemando Messages postés 33228 Date d'inscription   Statut Modérateur Dernière intervention   7 944
       
      Exact [Dal], j'ai corrigé, merci de ta vigilance.
      0
    3. joujou98
       
      merci beaucoup j'ai bien compris !
      0
    4. mamiemando Messages postés 33228 Date d'inscription   Statut Modérateur Dernière intervention   7 944
       
      Parfait, bonne continuation :-)
      0