Strncpy et strncat

Résolu/Fermé
encolie - 15 mars 2009 à 15:37
encolie Messages postés 8 Date d'inscription dimanche 15 mars 2009 Statut Membre Dernière intervention 16 mars 2009 - 16 mars 2009 à 15:12
Bonjour,
j'ai une erreur de segmentation fault du à ma concaténation. Alors la copie avec strncpy ne marche plus. Mon but est de faire une copie d'une adresse envoyé en argument et avec cette copie d'adresse,j'aimerai rajouter un slash d'où l'utilisation d'une concaténation. Je ne vois pas mon erreur et comment le résoudre. Un grand merci d'avance de votre aide.

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

void testcopystring(char* name);

int main(int argc, char *argv[])

{

testcopystring(argv[1]);
/*reçoit en argument une adresse d'un dossier*/
return 0;

}

void testcopystring(char* name)
{
char* copieName;
char *directionAvecSlash;
strncpy(copieName, name, sizeof(name)+1); /*copie l'adresse d'un dossier */
directionAvecSlash =strncat(copieName,"/" , sizeof(directionAvecSlash));
printf(" \n copie name vaut:%s \n",copieName);/*rajoute un slash à l'adresse du dossier*/
printf(" \n directionAvecSlash vaut:%s \n",directionAvecSlash);

}

12 réponses

encolie Messages postés 8 Date d'inscription dimanche 15 mars 2009 Statut Membre Dernière intervention 16 mars 2009
15 mars 2009 à 15:44
directionAvecSlash =strncat(copieName,"/" , sizeof(directionAvecSlash));

ici je me rends compte que si je change sizeof(directionAvecSlash) avec sizeof(directionAvecSlash) +sizeof(copieName) cela ne marche pas non plus
0
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 835
15 mars 2009 à 15:45
Salut,
Il y a plein de petites erreurs.
char* copieName;
char *directionAvecSlash;
strncpy(copieName, name, sizeof(name)+1); /*copie l'adresse d'un dossier */ 

copieName n'est pas allouée. De plus sizeof(name) renvoie 4 (sur une machine 32 bits) car c'est l'adresse du tableau qu'on envoie en arguments. Pour récupérer la taille du tableau, il faut également l'envoyer en paramètre.
Attention à ton utilisation de strncpy, tu n'es pas assuré que copieName contiendra un \0 en fin de caractères. Ce qui est très gênant pour strncat.

Cdlt
0
encolie Messages postés 8 Date d'inscription dimanche 15 mars 2009 Statut Membre Dernière intervention 16 mars 2009
15 mars 2009 à 16:23
merci pour ta réponse. Je débute en c donc j'apprends encore beaucoup sur le tas. Quand tu dis allouer, tu penses à un buffer?pour récupérer la taille du tableau, je démande la taille de l'argument dans la main? en sachant que l'exercice est que l'utilisateur ne tape que l'adresse d'un dossier donc je ne peux pas lui demander la taille.
dsl si les questions sont bêtes mais j'apprends vraiment sur le tas vu le délai de l'exercice.
merci encore de tes réponses.
0
encolie Messages postés 8 Date d'inscription dimanche 15 mars 2009 Statut Membre Dernière intervention 16 mars 2009
15 mars 2009 à 16:35
En fait pour récuperer la taille de l'adresse en argument, je peux faire un size_t strlen(const char* chaine)? Si j'ai bien compri, je dois remplacer: sizeof(name)+1 par la taille du tableau de name renvoyé en argument?
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
encolie Messages postés 8 Date d'inscription dimanche 15 mars 2009 Statut Membre Dernière intervention 16 mars 2009
15 mars 2009 à 16:46
J'ai remodifié et je vois que maintenant on me renvoie que les quatres premières lettres de l'adresse. :(

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

void testcopystring(char* name, long tailleName);

int main(int argc, char *argv[])

{ long taille;
taille=strlen(argv[1]);
testcopystring(argv[1],taille);

return 0;

}

void testcopystring(char* name,long tailleName)
{
char copieName[tailleName];
char *directionAvecSlash;
strncpy(copieName, name, sizeof(tailleName));
directionAvecSlash =strncat(copieName,"/",sizeof(copieName)+1);

printf(" \n directionAvecSlash vaut:%s \n",directionAvecSlash);

}

0
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 835
15 mars 2009 à 16:50
Quand tu dis allouer, tu penses à un buffer?
Soit allouer sur le tas avec un malloc. Soit utiliser un tableau de char.

je peux faire un size_t strlen(const char* chaine)?
Oui, tu peux. Tu ne peux pas faire autrement.

je dois remplacer: sizeof(name)+1 par la taille du tableau de name renvoyé en argument?
Oui, sauf si strlen est supérieure à la taille du tableau ou de la zone allouée.

Cdlt
0
encolie Messages postés 8 Date d'inscription dimanche 15 mars 2009 Statut Membre Dernière intervention 16 mars 2009
15 mars 2009 à 17:05
strncpy(copieName, name, sizeof(tailleName)); (en référent au deuxième code noté au dessus)
En vérifiant ce que vaut strncpy, il ne me renvoie qu'une partie de l'adresse alors que tailleName renvoie bien la taille de l'adresse. Je pense que je ne comprends pas bien à quoi sert le troisième argument de strncpy. Cela concerne aussi le sizeof de strncat.
0
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 835
15 mars 2009 à 18:01
Je t'ai vu utilisé : char copieName[tailleName];, attention ceci n'est valable qu'avec la norme C99. Sinon il faut utiliser malloc ou utiliser une taille maximale arbitraire pour le tableau.

Voici un exemple :
#include <stdio.h>
#include <string.h>

void testcopystring(const char*, const size_t);

int main(int argc, char *argv[]) { 
    if(argc>1)
        testcopystring( argv[1], strlen(argv[1])+1 );

    return 0;
}

void testcopystring(const char* name,const size_t sz) {
    const char ch[]="/";
    char directionAvecSlash[sz+strlen(ch)]; //valable qu'avec un compilateur C99
    strncpy(directionAvecSlash, name, sizeof directionAvecSlash - strlen(ch)); //-strlen pour laisser la place pour ch
    directionAvecSlash[sizeof directionAvecSlash - strlen(ch) - 1]='\0'; //on copie le \0 à l'avant-dernière position

    strncat(directionAvecSlash,ch,strlen(ch));
    printf(" \n directionAvecSlash vaut:%s \n",directionAvecSlash);
} 


Les tailles qu'on met dans strncat, ou strncpy, sont la taille maximum à copier dans directionAvecSlash. Donc c'est utile pour éviter d'écrire trop de caractères par rapport à la taille de directionAvecSlash
Je t'ai mis une chaîne ch contenant le slash pour te montrer une utilisation correcte de strncat. Ici, tu n'avais même pas besoin de strncat, puisque le '/' est un unique caractère. J'ai mis aussi if(argc)... au cas où l'utilisateur ne donne pas de paramètres.

Cdlt
0
encolie Messages postés 8 Date d'inscription dimanche 15 mars 2009 Statut Membre Dernière intervention 16 mars 2009
16 mars 2009 à 13:44
un grand merci je comprends mieux^^ Juste une question: tu fais strlen(argv[1])+1 dans la main, pourquoi tu mets +1? A cause de '\0' qu'il faut compter?

Mais je dois faire en sorte que ce soit compatible avec le compilateur C90. Donc il faut que je tente d'utiliser un malloc. J'ai repris ce que tu as fait en appliquant un malloc dessus, malheureusement cela me rend qu'une partie de l'adresse. L'allocation n'est pas bonne pourtant il me semble que c'est bon.

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

void testcopystring(const char*);

int main(int argc, char *argv[]) {
if(argc>1)
testcopystring( argv[1]);

return 0;
}

void testcopystring(const char* name) {
const char ch[]="/";
char* directionAvecSlash;
directionAvecSlash=malloc(sizeof name+2);
if (directionAvecSlash == NULL) // On vérifie si l'allocation a marché ou pas
{
exit(0); // On arrête tout
}


strncpy(directionAvecSlash, name, sizeof (directionAvecSlash - strlen(ch))); /*-strlen pour laisser la place pour ch*/
directionAvecSlash[sizeof directionAvecSlash - strlen(ch) - 1]='\0'; /*on copie le \0 à l'avant-dernière position*/

strncat(directionAvecSlash,ch,strlen(ch));
printf(" \n directionAvecSlash vaut:%s \n",directionAvecSlash);
free(directionAvecSlash);
}
0
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 835
16 mars 2009 à 14:11
Oui, le +1 c'était pour le '\0'. Tu n'es pas obligé de le mettre si dans ta fonction, tu rajoutes des +1 partout.

directionAvecSlash=malloc(sizeof name+2);
Tu refais la même erreur qu'à ton premier post. le sizeof de name ne va pas te renvoyer la taille du tableau mais va te renvoyer la taille du pointeur.
Il faut donc passer par le strlen().
char* directionAvecSlash=malloc(strlen(name)+2);  //+1 pour le slash, +1 pour le \0
if(directionAvecSlash==NULL) { //toujours tester si l'allocation a échoué
   fputs("erreur allocation\n",stderr);
   exit(1);
}
else {
   ...
  
   free(directionAvecSlash),directionAvecSlash=NULL; //bonne habitude de le remettre à NULL.
}
0
encolie Messages postés 8 Date d'inscription dimanche 15 mars 2009 Statut Membre Dernière intervention 16 mars 2009
16 mars 2009 à 14:26
Un grand merci^^ Merci de m'avoir aider^^
0
encolie Messages postés 8 Date d'inscription dimanche 15 mars 2009 Statut Membre Dernière intervention 16 mars 2009
16 mars 2009 à 15:12
En fait, je vais recommencer tout car je dois intégrer un nom de fichier et je penser rajouter une variable or je peux en faire en une seule
0