(re)codage de la fonction printf()

codage de la fonction printf() (re) - C - Programmation

Marsh Posté le 23-01-2012 à 14:08:27    

Bonjour à tous !

 

Dans un but didactique, j'essaie de recoder la fonction printf().
Lors de l’exécution de mon programme (cf ci dessous) j'ai l'erreur suivante : "Bad Format".

 

Le programme s'organise comme suit :

 

myprintf.c < myprintf.h
main.c < main.h

 

Ci-dessous les sources :

 

myprintf.h :

 
Code :
  1. #ifndef __MYPRINTF_H__
  2. #define __MYPRINTF_H__
  3. #include <stdio.h>
  4. #include <unistd.h> //pour write()
  5. #include <stdarg.h>
  6. #include <stdlib.h>
  7. int myprintf(const char* format, ...);
  8. int myStrlen(const char* s);
  9. void myWrite(int fildes, const void *buf, size_t nbytes);
  10. #endif


myprintf.c

 
Code :
  1. #include "myprintf.h"
  2. int myprintf(const char* format, ...)
  3. {
  4.     int i=0;
  5.     //char* s=NULL;
  6.     va_list ap;
  7.     va_start(ap, format);
  8.    
  9.     while(format[i] != 0)
  10.     {
  11.         switch(format[i])
  12.         {
  13.             case '%':
  14.                 switch(format[++i])
  15.                 {
  16.                     /*case 's':
  17.                         myWrite(1, s=va_arg(ap, char*), (size_t)myStrlen(s));
  18.                         break;*/
  19.                     case 'd':
  20.                         myWrite(1, va_arg(ap, int), sizeof(int));
  21.                         break;
  22.                     case 'c':
  23.                         myWrite(1, va_arg(ap, char), sizeof(char));
  24.                         break;
  25.                     default:
  26.                         myWrite(1, "%", sizeof(char));
  27.                         myWrite(1, &format[i], sizeof(char));
  28.                 }
  29.                 break;
  30.             default :
  31.                 myWrite(1, &format[i], sizeof(char));
  32.         }
  33.         i++;
  34.     }
  35.    
  36.     va_end(ap);
  37.     return 0;
  38. }
  39. int myStrlen(const char* s)
  40. {
  41.     int i=0;
  42.     while(s[i] != 0)
  43.         i++;
  44.     return i;
  45. }
  46. /* mywrite() :
  47. * Fait exactement comme write, mais en s'assurant
  48. * que l'écriture est réussie.
  49. */
  50. void myWrite(int fildes, const void *buf, size_t nbytes)
  51. {
  52.     if(buf == NULL)
  53.         exit(1);
  54.    
  55.     int k;
  56.     int n = (int)nbytes;
  57.     int i = 0;
  58.    
  59.     while(i < n && (k=write(fildes, buf, nbytes)) != -1)
  60.     {
  61.         i = i+k;
  62.     }
  63.     if(k == -1)
  64.     {
  65.         perror("write";);
  66.         printf("i=%d, k=%d, n=%d, filedes=%dn", i, k, n, fildes);     //Bon là, je sais que je triche :P
  67.         exit(1);
  68.     }   
  69. }


main.h :

 
Code :
  1. #ifndef __MAIN_H__
  2. #define __MAIN_H__
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #endif


main.c :

 
Code :
  1. #include "main.h"
  2. #include "myprintf.h"
  3. int main(int argc, char* argv[])
  4. {
  5.     int a=1;
  6.     myprintf("test %d\n", a);
  7.     return 0;
  8. }


Une exécution donne :

 

--------------------------------------------------
$ ./myprintf
test write: Bad address
i=0, k=-1, n=4, filedes=1
--------------------------------------------------

  

Je ne suis pas du tout familier avec les fonctions va_*() c'est pour ça que je fais des essais avec ce myprintf().

 

Auriez-vous une idée de l'origine de l'erreur ?
En vous remerciant d'avance.


Message édité par cybkiller le 23-01-2012 à 14:12:57
Reply

Marsh Posté le 23-01-2012 à 14:08:27   

Reply

Marsh Posté le 23-01-2012 à 20:15:16    

Les paramètres que tu passes à myWrite ne sont pas bons, ton compilateur aurait du t'afficher un avertissement.
 
va_arg() te renvoie une valeur et non une adresse, du coup tu fais un déréférencement invalide dans myWrite().
 
Qui plus est, va_arg(ap, char) est une erreur à cause de la promotion implicite des entiers de taille inférieur à "int". Pour récupérer un entier de type char, il faut écrire: va_arg(ap, int)
 
Edit: cette ligne, bien que commentée, est aussi foireuse: myWrite(1, s=va_arg(ap, char*), (size_t)myStrlen(s));
L'ordre des arguments passé à une fonction n'est pas normalisé, dont dépend du compilateur. Tu n'as aucune garantie qu'au moment d'appeler "myStrlen(s)", s à été initialisé par l'affectation juste avant.


Message édité par tpierron le 23-01-2012 à 20:17:58
Reply

Sujets relatifs:

Leave a Replay

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