Fonction qui insert un mot dans un autre

Résolu/Fermé
Joujou98 - Modifié le 23 nov. 2018 à 00:50
mamiemando Messages postés 33079 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 23 avril 2024 - 29 nov. 2018 à 13:42
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
A voir également:

1 réponse

mamiemando Messages postés 33079 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 23 avril 2024 7 749
Modifié le 23 nov. 2018 à 10:58
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
[Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024 1 083
Modifié le 23 nov. 2018 à 09:11
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
mamiemando Messages postés 33079 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 23 avril 2024 7 749
Modifié le 23 nov. 2018 à 10:58
Exact [Dal], j'ai corrigé, merci de ta vigilance.
0
merci beaucoup j'ai bien compris !
0
mamiemando Messages postés 33079 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 23 avril 2024 7 749
29 nov. 2018 à 13:42
Parfait, bonne continuation :-)
0