Langage C : concaténation de chaines de caractères

Langage C : concaténation de chaines de caractères - C - Programmation

Marsh Posté le 08-04-2010 à 12:17:15    

Bonjour,  
 
j'essaie d'écrire une méthode qui prend en argument une chaine de caractères correspondant au nom d'un fichier : par exemple "mon_fichier" et qui par la suite lui associe le dossier dans lequel il se situe ainsi que son extension.  
 
Voici mon tout petit bout de code :  
 
 

Code :
  1. void ma_fonction(char *mon_fichier )
  2. {
  3. // chaines à concatener avec mon_fichier
  4. char *chemin = "files\\";
  5. char *extension = ".jpg";
  6. //j'affiche chacune de ces chaines pour vérifier
  7. printf("%s\n",chemin);
  8. printf("%s\n",nom_fichier);
  9. printf("%s\n",extension);
  10.        
  11. //je concatene le chemin avec mon_fichier
  12. strcat(chemin,nom_fichier);
  13. //j'affiche pour vérifier la concatenation
  14. printf("%s\n",chemin);
  15. //je reconcatene ensuite avec l'extension
  16. strcat(chemin,extension);
  17. printf("%s\n",chemin);
  18. }
  19. int main(void){
  20.         enregistrer_image("mon_fichier" );
  21.         return 0;
  22. }


 
 
A la fin de la méthode, chemin devrait correspondre à la chaine "files\mon_fichier.jpg", mais cela ne marche pas lorsque je concatène chemin avec la chaine passée en paramètres (ligne 12)... cela marche seulement avec les chaines que j'ai créées à l'intérieur de ma fonction. Voilà si quelqu'un pouvait m'expliquer... je ne vois pas pourquoi cela ne fonctionne pas...
Merci pour votre aide,
 
bonne journée.

Reply

Marsh Posté le 08-04-2010 à 12:17:15   

Reply

Marsh Posté le 08-04-2010 à 12:25:22    

rahela a écrit :

je ne vois pas pourquoi cela ne fonctionne pas...


Peut-être parce que "nom_fichier" != "mon_fichier" ?
 
De rien :D


Message édité par Turkleton le 08-04-2010 à 12:25:42

---------------
If you think it could look good, then I guess it should
Reply

Marsh Posté le 08-04-2010 à 12:35:32    

ahah non c'est une erreur , j'ai voulu bidouiller dans mon message...
Dans mon code les noms correspondent bien, et j'ai bien une erreur (du type segmentation fault (core dumped))
Je remets le VRAI code   :ange:  
 

Code :
  1. void ma_fonction(char *nom_fichier )
  2. {
  3. char *chemin = "files\\";
  4. char *extension = ".jpg";
  5. printf("%s\n",chemin);
  6. printf("%s\n",nom_fichier);
  7. printf("%s\n",extension);
  8. strcat(chemin,nom_fichier);
  9. printf("%s\n",chemin);
  10. strcat(chemin,extension);
  11. printf("%s\n",chemin);
  12. }
  13. int main(void){
  14. ma_fonction("nom_fichier" );
  15. return 0;
  16. }


 
mercii

Reply

Marsh Posté le 08-04-2010 à 12:57:55    

Tu as bien inclus "#include <string.h>" hein ?
 
Et tu fais bien de préciser que ça plante à l'exécution, et pas à la compilation.
Du coup, je pense à un débordement en mémoire où il ne doit pas y avoir assez de place de réservée pour agrandir ta variable "chemin".
 
Essaie de la déclarer avec  

Code :
  1. char[100] chemin;



---------------
If you think it could look good, then I guess it should
Reply

Marsh Posté le 08-04-2010 à 14:50:34    

Ouais, aucune chance que ton code fonctionne.
 
Tu déclares un pointeur sur une chaine de caractère (char * chemin) et tu lui assignes une chaine statique: non seulement il n'y a pas la place à la fin de la chaine pour rajouter quoi ce soit, mais en plus ces chaines sont en lectures seules, toute tentative d'écriture = plantage direct.
 
Pour contourner le problème tu peux faire comme Turkleton t'as dit : déclarer une tableau et l'initialiser dans la foulée :
 
char chemin[100] = "files\\";
 

Reply

Marsh Posté le 08-04-2010 à 14:54:45    

En effet

char *chemin = "files\\";

ne réserve de la place que pour f-i-l-e-s-\-0, soit sept caractères.
Mais

strcat(chemin,nom_fichier);

metstous les caractères de nom_fichier dérrière, et cela déborde donc.
La solution est de réserver plus d'espace, par exemple :

Code :
  1. char *chemin = "files\\";
  2. char *extension = ".jpg";
  3. char full_name[250];
  4. strcpy(full_name, chemin);
  5. strcat(full_name, nom_fichier);
  6. strcat(full_name, extension);
  7. // ou sprintf(full_name, "%s%s%s", chemin, nom_fichier, extension);


Message édité par olivthill le 08-04-2010 à 14:55:54
Reply

Marsh Posté le 08-04-2010 à 15:02:43    

strncpy/strncat éviteront même de dépasser les 250 caractères et d'avoir un comportement indéfini ;-)


---------------
deluser --remove-home ptitchep
Reply

Marsh Posté le 08-04-2010 à 19:12:48    

ptitchep a écrit :

strncpy/strncat éviteront même de dépasser les 250 caractères et d'avoir un comportement indéfini ;-)


 
A part que strncpy d'une part écrit toujours n caractères et d'autre part ne garanti pas que le résultat soit une chaîne terminée par \0.
strncat est un peu moins piégeux.  La taille disponible à la destination doit être strlen(dst)+n+1.


---------------
The truth is rarely pure and never simple (Oscar Wilde)
Reply

Marsh Posté le 08-04-2010 à 19:13:15    

ptitchep a écrit :

strncpy/strncat éviteront même de dépasser les 250 caractères et d'avoir un comportement indéfini ;-)


 
Jamais vu ça [:lectrodz]

Reply

Marsh Posté le 08-04-2010 à 20:36:46    

Effectivement ça fonctionne!! j'ai tout le chemin affiché ! :D merci à vous !

Reply

Marsh Posté le 08-04-2010 à 20:36:46   

Reply

Marsh Posté le 08-04-2010 à 21:38:51    

404 Not Found a écrit :


 
Jamais vu ça [:lectrodz]


Si l'utilisateur rentre une chaîne de 5000 caractère et que toi tu la strcpy comme un boeuf dans ton buffer de 250 octets ton programme risque de pas aimer. Bon c'est sûr sur une utilisation normale y'aura jamais de problèmes cependant je tends à penser qu'il faut toujours utiliser strncpy en copiant n - 1 caractère (pour laisser de la place au \0) par sécurité :jap:
 
L'autre solution étant de faire un strlen de l'argument passé puis de vérifier si la taille de la chaîne est bien inférieure à la taille du buffer. Ca a l'avantage de pouvoir faire une gestion d'erreur correcte, alors qu'avec un strncpy tu vas juste copier les x premiers caractères et donc peut être tronquer ce que l'utilisateur a rentré :D


---------------
"I can cry like Roger. It's just a shame I can't play like him" - Andy Murray, 2010
Reply

Marsh Posté le 08-04-2010 à 22:08:08    

Un Programmeur a écrit :


 
A part que strncpy d'une part écrit toujours n caractères et d'autre part ne garanti pas que le résultat soit une chaîne terminée par \0.
strncat est un peu moins piégeux.  La taille disponible à la destination doit être strlen(dst)+n+1.


Je n'ai pas dit qu'il fallait les utiliser sans se soucier de rien non plus.


---------------
deluser --remove-home ptitchep
Reply

Marsh Posté le 08-04-2010 à 22:31:08    

Sinon y a snprintf() qui est très bien aussi (mais C99, ce qui ne devrait quand même plus trop poser de problème aujourd'hui) : pas besoin de se soucier de la taille du buffer vs. la taille de la chaîne initiale (strncpy), et pas besoin d'initialiser le buffer avant recopie (strncat). Bon, je parle là des tâches communes hein.

 

Mais sinon, je plussoie "Un Programmeur" : strncat est bien moins casse-gueule. À préférer à strncpy, qui est une fonction si fourbe que je me demande qui a bien pu spécifier ce... cette... chose.

Message cité 1 fois
Message édité par Elmoricq le 08-04-2010 à 22:32:26
Reply

Marsh Posté le 09-04-2010 à 09:57:40    

Elmoricq a écrit :

Mais sinon, je plussoie "Un Programmeur" : strncat est bien moins casse-gueule. À préférer à strncpy, qui est une fonction si fourbe que je me demande qui a bien pu spécifier ce... cette... chose.


 
L'histoire que j'ai lue est qu'elle était conçue pour remplir le champs nom dans la structure décrivant les répertoires des premières versions de Unix, quand les noms étaient limités à 14 caractères (elle n'est pas dans l'index de mon exemplaire du Lions' Commentary on UNIX 6th Edition et j'ai pas cherché dans le code lui-même mais la structure décrivant les répertoires serait bien remplie correctement avec un strncpy).


---------------
The truth is rarely pure and never simple (Oscar Wilde)
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed