INFO517-cours6

De Wiki du LAMA (UMR 5127)
Aller à la navigation Aller à la recherche

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">

  1. ifndef VECT_H
  2. 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.
*/
  1. 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) ;

  1. endif /* #ifndef VECT_H */

</source> Le code vect.c: <source lang="C">

  1. 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">

  1. include <stdio.h>
  2. 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">

  1. ifndef CHAR_BUF_H
  2. define CHAR_BUF_H
  1. 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) ;

  1. endif /* #ifndef CHAR_BUF_H */

</source>

Code char_buf.c: <source lang="C">

  1. include <stdlib.h>
  2. 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">

  1. ifndef VAL_H
  2. 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[]) ;

  1. endif /* #ifndef VAL_H */

</source>

Code val.c: <source lang="C">

  1. 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">

  1. ifndef COMP_H
  2. define COMP_H
  1. include <stdio.h>
  2. 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[]) ;

  1. endif /* #ifndef COMP_H */

</source>

Code comp.c: <source lang="C">

  1. include "val.h"
  2. 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">

  1. include <stdio.h>
  1. include "val.h"
  2. 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.