« INFO517-cours6 » : différence entre les versions
(Création de la page) |
mAucun résumé des modifications |
||
Ligne 1 : | Ligne 1 : | ||
Séance 6 du Cours-TD de [[INFO517|Programmation C]]. |
|||
== Structures == |
== Structures == |
||
Dernière version du 18 novembre 2008 à 22:56
Séance 6 du Cours-TD de Programmation C.
Structures
Une petite bibliothèque de vecteurs en deux dimensions:
Les en-têtes vect.h: <source lang="C">
- ifndef VECT_H
- define VECT_H
/* On a besoin de la fonction `double sqrt(double d)' qui
* est déclarée dans `math.h' : * penser à compiler avec l'option `-lm' de gcc. */
- include <math.h>
/************************/ /* Définitions de types */ /************************/
/* type des scalaires (fixe la précision des calculs) */ typedef double scal_t ;
/* type des vecteurs */ typedef struct { scal_t x ; scal_t y ; } vect_t ;
/*******************************/ /* Opérations sur les vecteurs */ /*******************************/
/* création */
vect_t vect_nouv (scal_t x, scal_t y) ;
/* addition */ vect_t vect_add (vect_t u, vect_t v) ;
/* différence */ vect_t vect_diff (vect_t u, vect_t v) ;
/* produit scalaire */ scal_t vect_scal (vect_t u, vect_t v) ;
/* déterminant */ scal_t vect_det (vect_t u, vect_t v) ;
/* norme */ scal_t vect_norm (vect_t u) ;
/* distance */ scal_t vect_dist (vect_t u, vect_t v) ;
- endif /* #ifndef VECT_H */
</source> Le code vect.c: <source lang="C">
- include "vect.h"
/*******************************/ /* Opérations sur les vecteurs */ /*******************************/
/* création */ vect_t vect_nouv (scal_t x, scal_t y) { vect_t u ; u.x=x ; u.y=y ; return u ; }
/* addition */ vect_t vect_add (vect_t u, vect_t v) { vect_t w ; w.x = u.x + v.x ; w.y = u.y + v.y ; return w ; }
/* différence */ vect_t vect_diff (vect_t u, vect_t v) { vect_t w ; w.x = u.x - v.x ; w.y = u.y - v.y ; return w ; }
/* produit scalaire */ scal_t vect_scal (vect_t u, vect_t v) { return u.x * v.x + u.y * v.y ; }
/* déterminant */ scal_t vect_det (vect_t u, vect_t v) { return u.x * v.y - u.y * v.x ; }
/* norme */ scal_t vect_norm (vect_t u) { return sqrt(vect_scal(u,u)) ; }
/* distance */ scal_t vect_dist (vect_t u, vect_t v) { return vect_norm(vect_diff(u,v)) ; }
/* ... on pourrait continuer ... */ </source> Et un programme benêt qui l'utilise test_vect.c: <source lang="C">
- include <stdio.h>
- include "vect.h"
/***********************/ /* Programme principal */ /***********************/
void aff_calcul (const char calcul[], scal_t valeur) { printf("%20s = %5.2f\n",calcul, valeur) ; }
int main () {
vect_t u = vect_nouv(1,1) ; vect_t v = vect_nouv(-1,2) ;
/* Affichage des vecteurs choisis */
printf("Avec u=(%5.2f,%5.2f) et v=(%5.2f,%5.2f), on a :\n\n",u.x,u.y,v.x,v.y) ;
/* Calculs */ aff_calcul("|u|",vect_norm(u)) ; aff_calcul("|v|",vect_norm(v)) ; aff_calcul("u.v",vect_scal(u,v)) ; aff_calcul("det(u,v)",vect_det(u,v)) ; aff_calcul("dist(u,v)",vect_dist(u,v)) ;
printf("\n") ;
return 0 ;
} </source>
Pointeurs dans les structures
Une bibliothèque de buffers.
En-têtes char_buf.h: <source lang="C">
- ifndef CHAR_BUF_H
- define CHAR_BUF_H
- include <stdio.h>
typedef char elem_t ;
typedef struct { size_t nb ; /* Nombre d'éléments du buffer */ elem_t *buf ; /* Pointeur vers le premier élément */ } buf_t ;
buf_t buff_new (size_t nb) ;
void buff_free (buf_t b) ;
size_t buff_size (buf_t b) ;
buf_t buff_resize (buf_t b, size_t nb) ;
- endif /* #ifndef CHAR_BUF_H */
</source>
Code char_buf.c: <source lang="C">
- include <stdlib.h>
- include "char_buf.h"
buf_t buff_new (size_t nb) { buf_t b ; elem_t *buf = (elem_t *) malloc(sizeof(elem_t) * nb) ; if (buf != NULL) { b.nb = nb ; b.buf = buf ; } else { b.nb = 0 ; } return b ; }
void buff_free (buf_t b) { if (b.buf != NULL) free(b.buf) ; }
size_t buff_size (buf_t b) { return b.nb ; }
buf_t buff_resize (buf_t b, size_t nb) { char *buf = realloc(b.buf,nb) ; if (buf != NULL) { b.nb = nb ; b.buf = buf ; } else { b.nb = 0 ; } return b ; } </source>
Un exemple complet avec: struct, union, enum
Un exemple un peu arbitraire pour fabriquer un type composé. On abstrait au maximum.
D'abord les valeurs (données dans une union): En-têtes val.h: <source lang="C">
- ifndef VAL_H
- define VAL_H
typedef union { char c ; unsigned long int u ; long int i ; long double f ; const char *s ; } val_t ;
/* Constructeurs pour le type val_t */
val_t val_char (char c) ; val_t val_uint (unsigned long int u) ; val_t val_int (long int i) ; val_t val_float (long double f) ; val_t val_chaine (const char s[]) ;
- endif /* #ifndef VAL_H */
</source>
Code val.c: <source lang="C">
- include "val.h"
/* Constructeurs pour le type val_t */
val_t val_char (char c) { val_t v ; v.c = c ; return v ; }
val_t val_uint (unsigned long int u) { val_t v ; v.u = u ; return v ; }
val_t val_int (long int i) { val_t v ; v.i = i ; return v ; }
val_t val_float (long double f) { val_t v ; v.f = f ; return v ; }
val_t val_chaine (const char s[]) { val_t v ; v.s = s ; return v ; } </source>
Ensuite le type comp_t construit comme une somme disjointe.
En-têtes comp.h: <source lang="C">
- ifndef COMP_H
- define COMP_H
- include <stdio.h>
- include "val.h"
/* On définit un type composé comp_t, qui peut contenir des données de types
* divers : * - le type union val_t défini dans val.h est assez grand pour contenir une donnée ; * - le champ de type cas_t est une clé qui renseigne sur le type de la donnée. **/
typedef enum { CHAR, UINT, INT, FLOAT, CHAINE, FIN } cas_t ;
typedef struct { cas_t cas ; val_t val ; } comp_t ;
/* Constructeurs pour le type comp_t */
comp_t comp_char (char c) ; comp_t comp_uint (unsigned long int u) ; comp_t comp_int (long int i) ; comp_t comp_float (long double f) ; comp_t comp_chaine (const char s[]) ; comp_t comp_fin () ;
/* Affiche un comp_t */ int comp_aff (comp_t x) ;
/* Formate une chaîne de comp_t :
* les éléments sont affichés entre crochets et on s'arrête sur FIN * */
int comp_aff_s (comp_t t[]) ;
- endif /* #ifndef COMP_H */
</source>
Code comp.c: <source lang="C">
- include "val.h"
- include "comp.h"
/* Constructeurs pour le type comp_t */
comp_t compose (cas_t cas, val_t val) { comp_t x ; x.cas = cas ; x.val = val ; return x ; }
comp_t comp_char (char c) { return compose(CHAR,val_char(c)) ; }
comp_t comp_uint (unsigned long int u) { return compose(UINT,val_uint(u)) ; }
comp_t comp_int (long int i) { return compose(INT,val_int(i)) ; }
comp_t comp_float (long double f) { return compose(FLOAT,val_float(f)) ; }
comp_t comp_chaine (const char s[]) { return compose(CHAINE,val_chaine(s)) ; }
comp_t comp_fin () { comp_t x ; x.cas = FIN ; return x ; }
/* Affiche un comp_t */ int comp_aff (comp_t x) { cas_t cas = x.cas ; if (cas == CHAR) printf("%c",x.val.c) ; else if (cas == UINT) printf("%lx",x.val.u) ; else if (cas == INT) printf("%ld",x.val.i) ; else if (cas == FLOAT) printf("%Lf",x.val.f) ; else if (cas == CHAINE) printf("%s",x.val.s) ; else return 1 ; return 0 ; }
/* Formate une chaîne de comp_t :
* les éléments sont affichés entre crochets et on s'arrête sur FIN * */
int comp_aff_s (comp_t t[]) { comp_t x ; cas_t cas ; int i ; /* nombre de comp_t lus sauf FIN */ x = t[0] ; i = 0 ; cas = x.cas ; while (cas != FIN) { putchar('[') ; comp_aff(x) ; putchar(']') ; ++i ; x = t[i] ; cas = x.cas ; } putchar('\n') ; return i ; }
</source>
En un programme d'exemple test_comp.c: <source lang="C">
- include <stdio.h>
- include "val.h"
- include "comp.h"
int main () { comp_t t[6] ; t[0]=comp_int(127) ; t[1]=comp_uint(127) ; t[2]=comp_char('a') ; t[3]=comp_chaine("un test") ; t[4]=comp_float(3.14159) ; t[5]=comp_fin() ; comp_aff_s(t) ; return 0 ; } </source>
Premier partiel
Le sujet de l'épreuve de 30 minutes: INFO517-Partiel1.pdf.