Aller au menu - Aller au contenu

[Plan du site] Vous êtes ici --- > Le Site du Zéro > Les forums > Programmation > Langage C > la bilbiothèque des zeros en C! > Lecture du sujet

la bilbiothèque des zeros en C!

zeros.h et zeros.c

Vous devez être inscrit pour pouvoir poster des messages

Page : 1  2  3  4  5  6  7  8  Suivante
Auteur Message
1 visiteur sur ce sujet (1 anonyme)
Page : 1  2  3  4  5  6  7  8  Suivante
Hors ligne Jaloyan1 # Posté le 21/04/2008 19:45:28
Choisir = se priver du reste.
Avatar
Groupe : Membres
Bonjour, c'est en lisant un livre enfin une partition intéressante je dois dire(symphonie n°9 de Dvorak 4eme mouvement)
qu'il m'est venu cette idée.

Peut être que ce topic est mal placé, et qu'il serait mieux en tutoriel, si c'est le cas, merci de me le signaler.

Eh oui!
Un bibliothèque en C pour les nouveaux et les anciens.
Ca vous évitera de coder vous même 50 fois la même fonction qui peut être très utile.

-Cette bibliothèque sera faite obligatoirement en C89 ou C90 car tout le monde n'a pas la norme C99
-Un manuel sera fourni avec chaque fonction pour expliquer comment cela fonctionne.



Tout le monde peut participer pour créer la bibliothèque des zeros.Il suffit juste que ca serve a quelque chose et que l'idée soit bonne.
Si vous prenez une fonction sur le net et vous voudriez nous la présenter, merci de citer la source.


J'actualiserai assez souvent cette bibliothèque.

Je construit la première brique de cet édifice avec ces 4 fonctions + une en prime.
Elles permettent de convertir une chaine en majuscules/minuscules et 2 autres pour faire la même chose en calculant le nombre de caractères convertis.
La dernière initialise une chaine de caractère a 0.


Code : C - zstring.h
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
int stolowercalc(char s[]);
int stolower(char *s);
int stoupper(char *s);
int stouppercalc(char s[]);
int sinitatzero(char *Str);
typedef enum
{
    Z_STR_OK = 0,
    Z_STR_ERR_INVALID_ARG = -1,
    Z_STR_NB = -2
}
Z_StrError;



Code : C - zstring.c
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
/********* CHAINE DE CARACTERES *******/
    /******** TRANSFORMATION DE CHAINES DE CARACTERES *****/

int stoupper(char *s)
{
    int err = 0;

    /* -tc- On teste la vilidité de l'argument */
    if (s != NULL)
    {
        while(*s != '\0')
        {
            *s = toupper((unsigned char) *s);
            s++;
        }
    }
    else
    {
        /* -tc- Erreur: argument invalide */
        err = Z_STR_ERR_INVALID_ARG;
    }
    return err;
}


int stolower(char *s)
{
    int err = 0;

    /* -tc- On teste la vilidité de l'argument */
    if (s != NULL)
    {
        while(*s != '\0')
        {
            *s = tolower((unsigned char) *s);
            s++;
        }
    }
    else
    {
        /* -tc- Erreur: argument invalide */
        err = Z_STR_ERR_INVALID_ARG;
    }
    return err;
}



int stolowercalc(char s[]){//stolower + calacul du nombre de caracteres transformes
    char copie[50000] = "";
    int i = 0,j = 0,carac = 0;
    strcpy(copie, s);
    j = stolower(s);
    if(j != 0){
        while(copie[i] != '\0'){
            if(copie[i] != s[i]){carac++;}
            i++;
        }
    }
    else carac = Z_STR_ERR_INVALID_ARG;
    return carac;
}

int stouppercalc(char s[]){//stolower + calacul du nombre de caracteres transformes
    char copie[50000] = "";
    int i = 0,j = 0,carac = 0;
    strcpy(copie, s);
    j = stoupper(s);
    if(j != 0){
        while(copie[i] != '\0'){
            if(copie[i] != s[i]){carac++;}
            i++;
        }
    }
    else carac = Z_STR_ERR_INVALID_ARG;
    return carac;
}
    /********* INITIALISATION DE CHAINES *******/
int sinitatzero(char *Str){
    if(*Str != NULL){
        while(*Str != '\0')
        {
            *Str = 0;
            Str++;
        }
    }
    else return Z_STR_ERR_INVALID_ARG;
}







Image utilisateur
Gestion de chaines de caracteres


transformations de chaines



stoupper


Code : C - prototype
1
int stoupper(char *Str);

Elle s'utilise assez facilement, son nom venant de toupper qui est une fonction qui permet de transformer un seul caractère en majuscule,s voulant dire string(chaine).
stoupper, prend en paramètre un pointeur qui peut être comme dit dans le tutoriel de mateo21, le nom de la chaine sans ses crochets. Elle revoit une 0 si tout s'est bien passé, et 0 si il y a un problème. On peut directement utiliser la chaine sans la stocker.Ce petit programme vous permettra surement de comprendre.

Code : C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
int stoupper(char *s);

int stoupper(char *s)
{
    int err = 0;

    /* -tc- On teste la vilidité de l'argument */
    if (s != NULL)
    {
        while(*s != '\0')
        {
            *s = toupper((unsigned char) *s);
            s++;
        }
    }
    else
    {
        /* -tc- Erreur: argument invalide */
        err = Z_STR_ERR_INVALID_ARG;
    }
    return err;
}


int main(){
    char chaine[500] = "abcdefghijklmnopqrstuvwxyz";
    int err = stoupper(chaine);
    if(err == 0){
        printf("%s",chaine);}
    else printf("La chaine est invalide");
    return 0;
}


resultat : Code : Console
ABCDEFGHIJKLMNOPQRSTUVWXYZ




stolower


Code : C - prototype
1
int stolower(char *s);


C'est la même fonction que stoupper a la seule différence que au lieu de convertir en majuscules, elle convertit tout en minuscules.




stouppercalc


Code : C - prototype
1
int stouppercalc(char s[]);


Cette fonction, nécessite absolument la fonction stoupper.
Elle renvoie un int, qui est le nombre de caractères convertis,si la chaine est invalide, elle renvoie une valeur négative. La chaine ne doit pas dépasser 50000 caractères de long.
la,c'est pareil, vous envoyez un tableau de char, vous faites comme si c'était un pointeur.
Je ne vous mettrai pas le tout, mais juste le main.
Code : C
1
2
3
4
5
6
int main(void){
    char chaine[50] = "ALsdfkL";
    int carac = stouppercalc(chaine);
    printf("%s,%ld",chaine,carac);
    Sleep(50000);
}


Code : Console - résultat
ALSDFKL,4




stolowercalc


Code : C - prototype
1
int stolowercalc(char s[]);


Cette fonction est pareille, sauf qu'elle nécessite stolower cette fois ci.
Elle transforme une chaine en minuscules et elle calcule le nombre de caractères transformés.
Je ne vais pas refaire l'exemple cette fois ci. De même que pour son inverse, la chaine ne doit pas faire plus de 50000 caractères de long.



Initialisation de chaines


sinitatzero


Code : C - prototype
1
void sinitatzero(char *Str);


Cette fonction, initialise une chaine de caractères a 0.
Elle se manie comme stoupper ou stolower.
Elle renvoi une valeur négative en cas d'erreur. Elle manie directement la chaine.
Il n'y a aucune limite de longueur de votre chaine.









Voila pour l'instant ce que contient cette bibliothèque.
A vous de la remplir.De temps en temps, je mettrais une ou deux fonction.
Bonne chance tout le monde et bonne lecture!


N'oubliez pas de me donner vos avis sur cette idée qui est euh... Je sais pas a vous de le dire.
Comme ca, on évitera de coder 100 fois la même fonction.
Édité le 22/04/2008 09:50:26 par Jaloyan1

Si quelqu'un vous dit : "Je me tue à vous le répéter", laissez-le mourir.
Image utilisateur
Image utilisateur
Image utilisateur

Chef du fan club de jaloyan1
 
Hors ligne -ed- # Posté le 21/04/2008 19:58:51
C is a sharp tool
Avatar
Groupe : Membres
Citation : Jaloyan1
Code : C
1
2
3
4
5
6
7
void stoupper(char *Str){//toupper pour string
   while(*Str != '\0')
   {
      *Str = toupper(*Str);
      Str++;
   }
}

Attention. Les fonctions de <ctype.h> attendent une valeur non signée. Il faut donc un cast explicite, car un char peut être signé ou non :
Code : C
1
*Str = toupper((unsigned char) *Str);


Citation : Pas de titre
Code : C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
int stolowercalc(char s[]){//stolower + calacul du nombre de caracteres transformes
    char copie[50000] = "";
    int i = 0,j = 0,carac = 0;
    strcpy(copie, s);
    stolower(s);
    while(copie[i] != '\0'){
        if(copie[i] != s[j]){carac++;}
        i++;
        j++;
    }
    return carac;
}


Ca c'est horrible. Pourquoi 5000 ? Pourquoi parcourir la chaine 2 fois ? Il suffit de modifier intelligemment stoupper() pour faire le boulot :

Code : C
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#include <ctype.h>
#include <stddef.h>

char *stoupper (char *s, size_t * p_changes)
{
   size_t changes = 0;
   if (s != NULL)
   {
      if (*s != 0)
      {
         char *p = s;
         while (*p != 0)
         {
            unsigned c = (unsigned char) *p;
            if (islower (c))
            {
               *p = toupper (*p);
               changes++;
            }
            p++;
         }
      }
   }

   /* return the changes count when able */
   if (p_changes != NULL)
   {
      *p_changes = changes;
   }
   return s;
}

#ifdef TEST

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

#define N(a) (sizeof(a)/sizeof *(a))

int main (void)
{
   int ret = EXIT_SUCCESS;
   struct test
   {
      /* test number */
      int n;

      /* in */
      struct
      {
         char const *s;
      }
      in;
      /* out */
      struct
      {
         char const *s;
         size_t n;
      }
      out;
   };

   static const struct test a[] =
/* *INDENT-OFF* */
   {
      {10, {NULL}, {NULL, 0}},
      {11, {""  }, {""  , 0}},

      {20, {"A" }, {"A" , 0}},
      {21, {"A "}, {"A ", 0}},

      {30, {"a" }, {"A" , 1}},
      {31, {"ab"}, {"AB", 2}},
      {32, {"Ab"}, {"AB", 1}},
      {33, {"aB"}, {"AB", 1}},
   };
/* *INDENT-ON* */

   size_t i;
   for (i = 0; i < N (a); i++)
   {
      struct test const *p = a + i;
      char *s_in = NULL;
      if (p->in.s != NULL)
      {
         /* must be modifiable */
         s_in = strdup (p->in.s);
         if (s_in == NULL)
         {
            printf ("ERR memory\n");
            ret = EXIT_FAILURE;
         }
      }

      {
         size_t n_out = -1;

         /* D.U.T. */
         char *s_out = stoupper (s_in, &n_out);

         if (p->in.s == NULL)
         {
            if (s_out != p->in.s)
            {
               printf ("ERR at test #%lu (s_out)\n", (unsigned long) p->n);
               ret = EXIT_FAILURE;
            }
         }
         else
         {
            if (strcmp (s_out, p->out.s) != 0)
            {
               printf ("ERR at test #%lu (s_out='%s' p->out.s='%s')\n"
               , (unsigned long) p->n
               ,s_out
               ,p->out.s
               );
               ret = EXIT_FAILURE;
            }
         }

         if (n_out != p->out.n)
         {
            printf ("ERR at test #%lu (n_out)\n", (unsigned long) p->n);
            ret = EXIT_FAILURE;
         }
         free (s_in), s_in = NULL;
      }
   }

   if (ret == EXIT_SUCCESS)
   {
      puts ("P A S S E D");
   }
   return ret;
}
#endif

Ne pas oublier de faire un test unitaire sérieux qui passe les cas tordus en revue...

Je te laisse faire la doc de la fonction (ce qui aurait du être fait avant de la coder ...)
Édité le 21/04/2008 21:40:34 par -ed-

Emmanuel Delahaye. Image utilisateur
Des infos sur la programmation et le langage C:
http://bien-programmer.blogspot.com/
http://mapage.noos.fr/emdel/

 
Hors ligne Jaloyan1 # Posté le 21/04/2008 20:19:05
Choisir = se priver du reste.
Avatar
Groupe : Membres
oups petite erreur de ma part, c'est la meme chose. je voulais dire C99 je sais pas pourquoi j'ai dit ca.
Pardon ,toutes mes excuses.
Édité le 21/04/2008 20:19:52 par Jaloyan1

Si quelqu'un vous dit : "Je me tue à vous le répéter", laissez-le mourir.
Image utilisateur
Image utilisateur
Image utilisateur

Chef du fan club de jaloyan1
 
Hors ligne The Whiplash # Posté le 21/04/2008 20:27:02
Avatar
Groupe : Membres
Je trouve que c'est une bonne initiative même si les fonctions que tu as codé sont pas très belles... (indentations etc...) et pas très utiles (mais bon ca peut toujours servir hein !).
Il faudrait également que les codes soient contrôlés quand même, un buffer overflow est si vite arrivé.
J'essayerai d'envoyer quelque truc des que j'ai le temps (vivement le week end de 5jours...)

The Whiplash

"Savoir par coeur n'est pas savoir".
Montaigne.

Image utilisateur
 
Hors ligne Jaloyan1 # Posté le 21/04/2008 20:45:47
Choisir = se priver du reste.
Avatar
Groupe : Membres
oui ,je sais que c'est pas très joli, mais je trouve que ce genre de fonction peut souvent venir, tout convertir en majuscules etc etc...
Je vais essayer de corriger mais je ne comprends pas en quoi il y a buffer overflow.
Pour les améliorations a faire, vous pouvez aussi me contacter par mp.

Perso, je sais j'explique mal, mais bon, je fais comme je peux, je suis ouvert a toute critique et suggestions.

Si quelqu'un vous dit : "Je me tue à vous le répéter", laissez-le mourir.
Image utilisateur
Image utilisateur
Image utilisateur

Chef du fan club de jaloyan1
 
Hors ligne tc # Posté le 21/04/2008 20:58:50
Make it pythonic!
Avatar
Groupe : Membres
Cette réponse a aidé l'auteur du sujet Cette réponse a aidé l'auteur du sujet
Si tu codes en C90, n'utilise pas les commentaires de fin de ligne à la C++. L'usage de // pour les commentaires n'est en effet défini qu'en C99. Remplace par /*...*/.

Pour l'organisation de ta bibliothèque, je pense qu'il serait préférable de regrouper les fonctions ayant un lien dans des unités de compilations séparées. Utiliser zeros.h et zeros.c comme fichiers "fourre-tout" nuit à la clareté du code et pourrait, à long terme, rendre la maintenance du code difficile.

Si je devais me servir des fonctions de ta bibliothèques, je m'attendrais à trouver un peu de programmation defensive (on teste les codes d'erreurs renvoyés par les fonctions standards utilisées et on teste la validité des argument (implantation sommaire de la notion de contrat)):

Code : C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
typedef enum 
{
    Z_STR_OK,
    Z_STR_ERR_INVALID_ARG,
    Z_STR_NB
}
Z_StrError;

int stoupper(char *s)
{
    int err = 0;

    /* -tc- On teste la vilidité de l'argument */
    if (s != NULL)
    {
        while(*s != '\0')
        {
            *s = toupper((unsigned char) c);
            s++;
        }
    }
    else
    {
        /* -tc- Erreur: argument invalide */
        err = Z_STR_ERR_INVALID_ARG;
    }
    return err;
}


Pour les fonctions liées au travail sur les chaines, j'utiliserais les fichiers zstring.h et zstring.c. Pour les fonctions d'entree/sortie, zio.h et zio.c. Etc.

Thierry
Édité le 21/04/2008 21:08:23 par tc

"Now is better than never. Although never is often better than right now." - The Zen of Python
| FAQ-Python | FAQ-C - FAQ-c.l.c | FAQ-C++ - FAQ-Lite |
 
Hors ligne aiii # Posté le 21/04/2008 21:43:16
Je pars du 18 juillet au 31
Avatar
Groupe : Membres
Je trouve que c'est une idée très intéressante ;)
Pourquoi ne pas commencer par les fonctions permettant la saisie sécurisée de chaînes ?

Je pars du 18 juillet au 31.

 
Hors ligne noob4ever # Posté le 21/04/2008 21:55:52
.NETeu boutoneu :)
Avatar
Groupe : Membres
Citation : aiii
Je trouve que c'est une idée très intéressante ;)
Pourquoi ne pas commencer par les fonctions permettant la saisie sécurisée de chaînes ?


Le but c'est pas de re-écrire la lib standard hein ?
 
Hors ligne corentin1234 # Posté le 21/04/2008 22:00:34
Avatar
Groupe : Membres
Code : C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

#define TAILLE_BLOC 8

char *
chaine_lire_ligne_de_fichier (FILE *f){
  int c = getc (f);
  if (c == EOF)
    return NULL;

  int taille = TAILLE_BLOC;
  char *tampon = malloc(taille);
  assert(tampon != NULL);
  int i;

  for (i = 0; c != EOF; c = getc (f)){
    if (c == '\n')
      break;

    tampon[i++] = c;
    if (i == taille){
      /* Agrandissement du tampon de lecture */
      tampon = realloc(tampon, 2 * taille);
      taille *= 2;
    }
  }
  tampon[i] = '\0';
  return realloc(tampon, i + 1);
}

Ce code n'est pas de moi, mais il est très facile à comprendre.
Pour lire les entrées utilisateurs, il suffit de lui passer stdin comme paramètre.
Édité le 21/04/2008 22:03:37 par corentin1234
Hors ligne aiii # Posté le 21/04/2008 22:01:15
Je pars du 18 juillet au 31
Avatar
Groupe : Membres
Je me suis mal exprimé. Je voulais parler de fonctions permettant de "nettoyer" la saisie de texte grâce à fgets.
ex: vider stdin

Je pars du 18 juillet au 31.

 
Hors ligne sharky.fr # Posté le 21/04/2008 22:11:48
DIY
Avatar
Groupe : Membres
Cette réponse a aidé l'auteur du sujet Cette réponse a aidé l'auteur du sujet
Citation : aiii
Je trouve que c'est une idée très intéressante ;)
Pourquoi ne pas commencer par les fonctions permettant la saisie sécurisée de chaînes ?


Voir ici module IO.


---


Voici une fonction permettant de lire une ligne.

NOTE :
s_malloc s_realloc sont simplement des wrappers de malloc et realloc. Ils peuvent aisément être remplacer par une vérification du retour de ces fonctions.

ES.h

Code : C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#ifndef SLIB_ES_INCLUDED
#define SLIB_ES_INCLUDED



/* enumeration ============================================================= */
enum EsErr
{
  ES_SUCCES,            /* Tout s'est bien passe                          */
  ES_ERR_LECT,          /* La fct a rencontrer EOF                        */
  ES_ERR_TAILLE,        /* La taille passee est <= 0                      */
  ES_ERR_BUFF,          /* Le buffer passe est NULL                       */
  ES_ERR_FLUX,          /* Le pointeur sur FILE passe est NULL            */
  ES_ERR_PERTE,         /* Il restait des caracteres dans le flux         */
  ES_ERR_POINTEUR_NULL, /* La fct devait ecrire dans un pointeur NULL     */
  ES_ERR_CHAINE_NULL,   /* La saisie a echouee, rien a convertir          */
  ES_ERR_CONVERSION     /* La fct de conversion utilisee (std) a echouee  */
};
typedef enum EsErr EsErr_e;



/* macro-constante ========================================================= */
#define SZ_MAX 1000000  /* valeur arbitraire */



/* prototypes ============================================================== */
char *fobt_ln (FILE *f, int *err);
char *obt_ln  (int *err);



#endif





ES.c

Code : C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
/* en-tetes ================================================================ */
#include <stdlib.h>
#include <stdio.h>
#include "ES.h"



/* Fonction : char *fobt_ln(FILE *f, int *err);
 * -------------------------------------------------------------------------
 * Permet la lecture d'une ligne dans un flux `f`. La taille maximale de la
 * chaine renvoyee est definie par la macro SZ_MAX.
 * La fonction renvoie un pointeur sur le premier element d'un tableau
 * contenant la chaine lue, ou un pointeur sur NULL en cas d'echec.
 * Si `err` est un pointeur valide, la fonction y place un code d'erreur :
 * ES_SUCCES si tout s'est bien deroule
 * ES_ERR_LECT si EOF est rencontre en cours de lecture
 * ES_ERR_PERTE si apres avoir lue SZ_MAX caracteres, il en reste dans le 
 * flux
 * ES_ERR_FLUX si `f` est invalide
 * -------------------------------------------------------------------------
 */
char *fobt_ln(FILE *f, int *err)
{
  char *s = NULL;

  if (f)
  {
    int c;
    size_t sz = 0;

    s = s_malloc(1 * sizeof *s);

    while ( (c = fgetc(f)) != '\n' && c != EOF && sz < SZ_MAX )
    {
      s       = s_realloc(s, (sz + 2) * sizeof *s);
      s[sz++] = (char) c;
    }

    s[sz] = '\0';

    if (err)
    {
      if (c == '\n')
      {
        *err = ES_SUCCES;
      }
      else if (c == EOF)
      {
        *err = ES_ERR_LECT;
      }
      else if (sz == SZ_MAX - 1)
      {
        *err = ES_ERR_PERTE;
      }
    }
  }
  else
  {
    if (err)
    {
      *err = ES_ERR_FLUX;
    }
  }

  return s;
}



/* Fonction : char *obt_ln(int *err);
 * -------------------------------------------------------------------------
 * Equivalent a fobt_ln(err, stdin).
 * -------------------------------------------------------------------------
 */
char *obt_ln(int *err)
{
  return fobt_ln(stdin, err);
}


EDIT: orthographe :$
EDIT2: modification du code. `c` devient un `int` car `fgetc` renvoie un `int`... rajout d'un cast.
Édité le 23/04/2008 17:17:38 par sharky.fr

  • Être conscient de son ignorance, c'est tendre vers la connaissance. Benjamin Disraeli
  • Il semble que la perfection soit atteinte non quand il n’y a plus rien à ajouter, mais quand il n’y a plus rien à retrancher. Antoine de Saint-Exupéry
Image utilisateur

 
Connecté SirJulio # Posté le 22/04/2008 04:18:05
Groupe : Membres
@Sharky.fr

Tu ne devrais pas realloc à chaque tour de boucle, double plutot la taille quand il le faut et teste la capacité restante à chaque tour, ca serait bien plus efficace sur de grosses chaines. =)
Hors ligne Jaloyan1 # Posté le 22/04/2008 08:15:36
Choisir = se priver du reste.
Avatar
Groupe : Membres
Citation : tc
Si tu codes en C90, n'utilise pas les commentaires de fin de ligne à la C++. L'usage de // pour les commentaires n'est en effet défini qu'en C99. Remplace par /*...*/.

Pour l'organisation de ta bibliothèque, je pense qu'il serait préférable de regrouper les fonctions ayant un lien dans des unités de compilations séparées. Utiliser zeros.h et zeros.c comme fichiers "fourre-tout" nuit à la clareté du code et pourrait, à long terme, rendre la maintenance du code difficile.

Si je devais me servir des fonctions de ta bibliothèques, je m'attendrais à trouver un peu de programmation defensive (on teste les codes d'erreurs renvoyés par les fonctions standards utilisées et on teste la validité des argument (implantation sommaire de la notion de contrat)):

Code : C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
typedef enum 
{
    Z_STR_OK,
    Z_STR_ERR_INVALID_ARG,
    Z_STR_NB
}
Z_StrError;

int stoupper(char *s)
{
    int err = 0;

    /* -tc- On teste la vilidité de l'argument */
    if (s != NULL)
    {
        while(*s != '\0')
        {
            *s = toupper((unsigned char) c);
            s++;
        }
    }
    else
    {
        /* -tc- Erreur: argument invalide */
        err = Z_STR_ERR_INVALID_ARG;
    }
    return err;
}


Pour les fonctions liées au travail sur les chaines, j'utiliserais les fichiers zstring.h et zstring.c. Pour les fonctions d'entree/sortie, zio.h et zio.c. Etc.

Thierry


Les commentaires fonctionnent sur code blocks qui est en C90.


Bon update acceptée.

Je reformule mes deux chaines.

Je vais essayer de créer une doc en ligne sur un tuto peut etre ou quelque chose d'autre.
Je vais formuler le début ici, pendant que je formulerai sur un big tuto.



EDIT : j'ai modifié le début avec succès, j'ai même modifié un peu l'enum.
Car si c'était des valeurs positives, on pouvait les confondre avec le nombre de caractères retournés.

J'ai pas encore lu les autres posts, je m'y mets dès maintenant.


ed : ta methode me semble beaucoup trop compliquée.
Édité le 22/04/2008 08:34:54 par Jaloyan1

Si quelqu'un vous dit : "Je me tue à vous le répéter", laissez-le mourir.
Image utilisateur
Image utilisateur
Image utilisateur

Chef du fan club de jaloyan1
 
Connecté rz0 # Posté le 22/04/2008 08:30:20
meuh
Avatar
Groupe : Membres
Hors ligne Jaloyan1 # Posté le 22/04/2008 08:46:27
Choisir = se priver du reste.
Avatar
Groupe : Membres
Citation : sharky.fr
Citation : aiii
Je trouve que c'est une idée très intéressante ;)
Pourquoi ne pas commencer par les fonctions permettant la saisie sécurisée de chaînes ?


Voir ici module IO.


---


Voici une fonction permettant de lire une ligne.

NOTE :
s_malloc s_realloc sont simplement des wrappers de malloc et realloc. Ils peuvent aisément être remplacer par une vérification du retour de ces fonctions.

ES.h

Code : C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#ifndef SLIB_ES_INCLUDED
#define SLIB_ES_INCLUDED



/* enumeration ============================================================= */
enum EsErr
{
  ES_SUCCES,            /* Tout s'est bien passe                          */
  ES_ERR_LECT,          /* La fct a rencontrer EOF                        */
  ES_ERR_TAILLE,        /* La taille passee est <= 0                      */
  ES_ERR_BUFF,          /* Le buffer passe est NULL                       */
  ES_ERR_FLUX,          /* Le pointeur sur FILE passe est NULL            */
  ES_ERR_PERTE,         /* Il restait des caracteres dans le flux         */
  ES_ERR_POINTEUR_NULL, /* La fct devait ecrire dans un pointeur NULL     */
  ES_ERR_CHAINE_NULL,   /* La saisie a echouee, rien a convertir          */
  ES_ERR_CONVERSION     /* La fct de conversion utilisee (std) a echouee  */
};
typedef enum EsErr EsErr_e;



/* macro-constante ========================================================= */
#define SZ_MAX 1000000  /* valeur arbitraire */



/* prototypes ============================================================== */
char *fobt_ln (FILE *f, int *err);
char *obt_ln  (int *err);



#endif





ES.c

Code : C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
/* en-tetes ================================================================ */
#include <stdlib.h>
#include <stdio.h>
#include "ES.h"



/* Fonction : char *fobt_ln(FILE *f, int *err);
 * -------------------------------------------------------------------------
 * Permet la lecture d'une ligne dans un flux `f`. La taille maximale de la
 * chaine renvoie est definie par la macro SZ_MAX.
 * La fonction renvoie un pointeur sur le premier element d'un tableau
 * contenant la chaine lue, ou un pointeur sur NULL en cas d'echec.
 * Si `err` est un pointeur valide, la fonction y place un code d'erreur :
 * ES_SUCCES si tout s'est bien deroule
 * ES_ERR_LECT si EOF est rencontre en cours de lecture
 * ES_ERR_PERTE si apres avoir lue SZ_MAX caracteres, il en reste dans le 
 * flux
 * ES_ERR_FLUX si `f` est invalide
 * -------------------------------------------------------------------------
 */
char *fobt_ln(FILE *f, int *err)
{
  char *s = NULL;

  if (f)
  {
    char c;
    size_t sz = 0;

    s = s_malloc(1 * sizeof *s);

    while ( (c = fgetc(f)) != '\n' && c != EOF && sz < SZ_MAX )
    {
      s       = s_realloc(s, (sz + 2) * sizeof *s);
      s[sz++] = c;
    }

    s[sz] = '\0';

    if (err)
    {
      if (c == '\n')
      {
        *err = ES_SUCCES;
      }
      else if (c == EOF)
      {
        *err = ES_ERR_LECT;
      }
      else if (sz == SZ_MAX - 1)
      {
        *err = ES_ERR_PERTE;
      }
    }
  }
  else
  {
    if (err)
    {
      *err = ES_ERR_FLUX;
    }
  }

  return s;
}



/* Fonction : char *obt_ln(int *err);
 * -------------------------------------------------------------------------
 * Equivalent a fobt_ln(err, stdin).
 * -------------------------------------------------------------------------
 */
char *obt_ln(int *err)
{
  return fobt_ln(stdin, err);
}





je n'ai pas très bien compris ton code, on peut très bien le faire avec fgets.

Peut tu apporter plus de précisions pour que je puisse faire la doc, je n'ai pas compris a quoi elle sert cette fonction. Comment elle fonctionne?

Si quelqu'un vous dit : "Je me tue à vous le répéter", laissez-le mourir.
Image utilisateur
Image utilisateur
Image utilisateur

Chef du fan club de jaloyan1
 
Hors ligne 1337833K # Posté le 22/04/2008 08:51:27
fgsfds
Groupe : Membres
Citation : Jaloyan1
Peut tu apporter plus de précisions pour que je puisse faire la doc, je n'ai pas compris a quoi elle sert cette fonction. Comment elle fonctionne?

Elle alloue un buffer, puis lit une ligne entière et agrandit le buffer si besoin, et renvoie un pointeur sur le buffer.

En (très) très gros, c'est une lecture d'une chaine (théoriquement seulement) infinie.

Image utilisateur
Big Brother is watching you.
Libérez quelqu'un et quelqu'un-d'autre !
 
Hors ligne Jaloyan1 # Posté le 22/04/2008 09:05:56
Choisir = se priver du reste.
Avatar
Groupe : Membres
et l'interet par rapport aux autres fonctions?
Je n'ai toujours pas compris quel est l'interet de cette fonction, elle permet de faire a peu la meme chose que fgets sauf que c'est infini sa taille ou alors c'est autre chose? Pour eviter d'inonder le sujet, vous pouvez si vous le voulez me contacter par mp.

Si quelqu'un vous dit : "Je me tue à vous le répéter", laissez-le mourir.
Image utilisateur
Image utilisateur
Image utilisateur

Chef du fan club de jaloyan1
 
Hors ligne -ed- # Posté le 22/04/2008 09:11:04
C is a sharp tool
Avatar
Groupe : Membres
Citation : Jaloyan1
Citation : tc
Si tu codes en C90, n'utilise pas les commentaires de fin de ligne à la C++. L'usage de // pour les commentaires n'est en effet défini qu'en C99. Remplace par /*...*/.

Les commentaires fonctionnent sur code blocks qui est en C90.

Euh, tu contestes la norme ?

Si MinGW (peu importe l'IDE qui est au-dessus) accepte les commentaires //, c'est parce que par défaut, il fonctionne dans un mode étendu qui ajoute des fonctionnalités au C90 de base.

Pour se limiter au C90 strict, il faut activer les flags -ansi et -pedantic

Là, tu verras que ce style de commentaire ne passe plus.

Citation : Pas de titre
ed : ta methode me semble beaucoup trop compliquée.


Tu parles de quoi ? Du codage de stoupper() ?

En quoi est-ce compliqué ? De toutes façons, tes 'impressions' importent peu. Ce qui compte, pour une bibliothèque de fonctions, c'est que le code soit correctement codé et testé. On doit pouvoir utiliser les fonctions dans toutes les conditions sans que ça casse.

Si tu as une méthode plus simple à proposer, on t'écoute. Au fait, on attend toujours la spécification précise des fonctions...

Citation : Pas de titre
et l'interet par rapport aux autres fonctions?

C'est qu'on a plus à gérer la taille, c'est automatique. Il faut juste penser à libérer le bloc après usage (free()).

COmme beaucoup qui on traité ce problème, j'ai aussi fait une fonction de ce style dans ma bibliothèque CLIB/ED, module IO, fonction get_line().
Code : C
1
2
3
4
/* Dynamic. To be freed */
   char *fget_line (FILE * fp, int *p_end);

   char *get_line (void);
Édité le 22/04/2008 09:24:01 par -ed-

Emmanuel Delahaye. Image utilisateur
Des infos sur la programmation et le langage C:
http://bien-programmer.blogspot.com/
http://mapage.noos.fr/emdel/

 
Hors ligne Jaloyan1 # Posté le 22/04/2008 09:22:52
Choisir = se priver du reste.
Avatar
Groupe : Membres
ok mais il faut que vous m'expliquiez un peu a quoi ca sert ces fonctions, comment elles fonctionnent.

J'avais constaté un gros bug dans les fonctions, j'ai corrigé immédiatement.



ed tu peux m'expliquer comment ca fonctionne ton code?


De toutes manières, j'avais pensé a une idée mais bon je ne sais pas si elle peut marcher.


EDIT : je suis en train de commencer a rédiger les tutos et les fichiers pour les stockers dans des dossiers de la zerolib.

Une fois la zerolib terminée, il va falloir une personne qui puisse heberger tout cela sur le site du zero ou autre part.
Voila.
Je vais updater plus rarement ici.
Car 3 trucs en meme temps, ca va etre dur mais ne vous en faites pas, je vous lacherais pas.



j'ai une question, quelle est le 2eme paramètre de la fonction?

Aussi, je vais la renommer car le nom a l'air un peu bizarre.
Édité le 22/04/2008 13:09:04 par Jaloyan1

Si quelqu'un vous dit : "Je me tue à vous le répéter", laissez-le mourir.
Image utilisateur
Image utilisateur
Image utilisateur

Chef du fan club de jaloyan1
 
Hors ligne sharky.fr # Posté le 22/04/2008 15:15:33
DIY
Avatar
Groupe : Membres
Citation : SirJulio
@Sharky.fr

Tu ne devrais pas realloc à chaque tour de boucle, double plutot la taille quand il le faut et teste la capacité restante à chaque tour, ca serait bien plus efficace sur de grosses chaines. =)


Oui j'y ai pensé de nombreuses fois mais après avoir testé le code je me demande si c'est bien nécessaire :

longueur chainetemps d'exécution (s)taille chaine (byte)
100 0.000000 101
90000 0.015000 90001
500000 0.093000 500001
900000 0.218000 900001


Après.. j'avoue ne pas avoir la moindre idée de comment effectuer des tests unitaires et/ou de performance.

EDIT: coquille
Édité le 22/04/2008 15:23:39 par sharky.fr

  • Être conscient de son ignorance, c'est tendre vers la connaissance. Benjamin Disraeli
  • Il semble que la perfection soit atteinte non quand il n’y a plus rien à ajouter, mais quand il n’y a plus rien à retrancher. Antoine de Saint-Exupéry
Image utilisateur

 
Hors ligne -ed- # Posté le 22/04/2008 15:23:13
C is a sharp tool
Avatar
Groupe : Membres
Citation : Jaloyan1
ed tu peux m'expliquer comment ca fonctionne ton code?

Je ne sais pas de quoi tu parles... Il faut citer sinon, on y comprend rien.

Citation : sharky.fr
j'avoue ne pas avoir la moindre idée de comment effectuer des tests unitaires

J'ai pourtant donné un exemple avec stoupper()...

Édité le 22/04/2008 15:25:55 par -ed-

Emmanuel Delahaye. Image utilisateur
Des infos sur la programmation et le langage C:
http://bien-programmer.blogspot.com/
http://mapage.noos.fr/emdel/

 
Hors ligne Gambit2099 # Posté le 22/04/2008 15:28:21
Crow never dies...
Avatar
Groupe : Membres
A quoi bon réinventer la roue si ça n'apporte rien de nouveau ?

Mon Blog-Art (dessins, recherches, croquis)
Mon compte Dailymotion (animations)
Image utilisateur
Voyons la vérité en face !!
 
Hors ligne Jaloyan1 # Posté le 22/04/2008 15:52:57
Choisir = se priver du reste.
Avatar
Groupe : Membres
Citation : sharky.fr
Citation : aiii
Je trouve que c'est une idée très intéressante ;)
Pourquoi ne pas commencer par les fonctions permettant la saisie sécurisée de chaînes ?


Voir ici module IO.


---


Voici une fonction permettant de lire une ligne.

NOTE :
s_malloc s_realloc sont simplement des wrappers de malloc et realloc. Ils peuvent aisément être remplacer par une vérification du retour de ces fonctions.

ES.h

Code : C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#ifndef SLIB_ES_INCLUDED
#define SLIB_ES_INCLUDED



/* enumeration ============================================================= */
enum EsErr
{
  ES_SUCCES,            /* Tout s'est bien passe                          */
  ES_ERR_LECT,          /* La fct a rencontrer EOF                        */
  ES_ERR_TAILLE,        /* La taille passee est <= 0