Posez votre question Signaler

Strncpy et strncat [Résolu]

encolie - Dernière réponse le 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);
}
Lire la suite 

Strncpy et strncat »

12 réponses
Réponse
+0
moins plus
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
Ajouter un commentaire
Réponse
+0
moins plus
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
Ajouter un commentaire
Réponse
+0
moins plus
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.
Ajouter un commentaire
Réponse
+0
moins plus
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?
Ajouter un commentaire
Réponse
+0
moins plus
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);

}

Ajouter un commentaire
Réponse
+0
moins plus
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
Ajouter un commentaire
Réponse
+0
moins plus
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.
Ajouter un commentaire
Réponse
+0
moins plus
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
Ajouter un commentaire
Réponse
+0
moins plus
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);
}
Ajouter un commentaire
Réponse
+0
moins plus
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.
}
Ajouter un commentaire
Réponse
+0
moins plus
Un grand merci^^ Merci de m'avoir aider^^
Ajouter un commentaire
Réponse
+0
moins plus
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
Ajouter un commentaire
Ce document intitulé « strncpy et strncat » issu de CommentCaMarche (www.commentcamarche.net) est mis à disposition sous les termes de la licence Creative Commons. Vous pouvez copier, modifier des copies de cette page, dans les conditions fixées par la licence, tant que cette note apparaît clairement.
Dossier à la une
Passage au tout numérique : quel coût pour les particuliers ?