Vous êtes sur la page 1sur 7

UE Complément de Langage C pour l’Electronique (LE315)

Contrôle Continu
Date : 27 novembre 2006
Documents et supports de cours autorisés.

Remarques :
* Vous ferez attention à la gestion des erreurs.
* Toutes les questions peuvent être traitées indépendamment, en supposant connues les
fonctions et procédures définies dans les questions précédentes. Vous veillerez d’ailleurs pour
répondre aux questions à utiliser les fonctions ou procédures des questions précédentes, si possible.
* Vous pouvez définir des procédures ou des fonctions qui ne sont pas demandées, mais dont
vous sentez qu’elles sont nécessaires pour répondre proprement à une question.

EXERCICE I : le triangle de Pascal1 est un arrangement géométrique des coefficients


binomiaux dans un triangle. En voici un exemple :

1 u1(1) =1
1 1
1 2 1 un(i)=un-1(i)+un-1(i-1)=10+10=20
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1
1 7 21 35 35 21 7 1
1 8 28 56 70 56 28 8 1
1 9 36 84 126 126 84 36 9 1
1 10 45 120 210 252 210 120 45 10 1

Remarquez que si on nomme un la ligne n de ce triangle et un(i) l’élément à la ième colonne de


la ligne n, alors on peut écrire : un(i)= un-1(i-1)+ un-1(i), pour tout i∉{1,n} et
un(i)=1 si i∈{1,n}.

1) Ecrire une fonction int**alloue_triangle(int n) qui alloue un double


pointeur d’entier de sorte qu’il corresponde aux n premières lignes du triangle, n étant
fourni en argument d’entrée de cette fonction.

int **alloue_triangle(int n)
{
int **triangle=NULL ;
int i ;
triangle=(int**)malloc(n*sizeof(int*)) ;
if(triangle==NULL){
fprintf(stderr, "Erreur d allocation\n") ;
exit(1) ;}
for(i=0 ;i<n ;i++)

1
NB : L’exercice I a été demandé à un étudiant postulant à un stage à la SNCF lors de son entretien d’embauche en 2004
sous la forme « écrire un programme en langage C qui calcule et affiche un triangle de Pascal », sans aucune autre indication.
{
triangle[i]=(int*)malloc((i+1)*sizeof(int)) ;
if(triangle[i]==NULL) ){
fprintf(stderr, "Erreur d allocation\n") ;
exit(1) ;}

}
return triangle ;

2) Ecrire une procédure void remplit_triangle(int**triangle,int n)


qui remplit correctement le triangle de pascal.

void remplit_triangle(int**triangle,int n)
{
int i,k ;
for(i=0 ;i<n ;i++)
{
for(k=0 ;k<i+1 ;k++)
{
if(k==0||k==i) triangle[i][k]=1;
else triangle[i][k]= triangle[i-1][k-1]+
triangle[i-1][k];
}
}
}

3) Ecrire une procédure void affiche_triangle(int**triangle,int n)


qui affiche à l’écran le triangle comme ci-dessus (chaque nombre d’une même ligne
sera séparé par un espace).

void affiche_triangle(int**triangle,int n)
{
int i,k ;
for(i=0 ;i<n ;i++)
{
for(k=0 ;k<i+1 ;k++)
{
printf("%d ",triangle[i][k]);
}
printf("\n");
}
}

4) Ecrire une procédure void desalloue_triangle(int**triangle,int


n)qui libère la mémoire alloué pour le triangle.

void libere_triangle(int**triangle,int n)
{
int i,k ;
for(i=0 ;i<n ;i++) free(triangle[i]) ;
free(triangle) ;
}

5) Ecrire une fonction principale qui demande à l’utilisateur le nombre de lignes qu’il
veut calculer puis qui utilise les fonctions précédentes pour allouer, remplir et afficher
le triangle, et enfin le désallouer.

int main()
{
int n=0 ;
int **triangle==NULL ;
printf("Nb lignes ? ") ;
scanf("%d",&n) ;
triangle=alloue_triangle(n) ;
remplit_triangle(triangle,n) ;
affiche_triangle(triangle,n) ;
libere_triangle(triangle,n) ;
return 0 ;
}

EXERCICE II : Des wagons dans des trains ; Dans cet exercice, nous allons considérer
deux structures imbriquées.

Soit une structure nommée « wagon », contenant deux entiers positifs, « sieges » et
« passagers » qui indiquent respectivement le nombre de sièges et le nombre de passagers
dans le wagon.

1) Ecrire la déclaration de la structure « wagon », qui aura comme type synonyme


« WAGON ».

typedef struct wagon


{
unsigned int sieges, passagers ;
} WAGON ;

2) Ecrire une fonction WAGON *wagon_init(int n) qui permet d’allouer un


tableau de « n » wagons et d’initialiser les deux champs de chaque wagon : le nombre
de sièges par défaut sera de 90 places et le nombre de passagers, 0.

WAGON *wagon_init(int n)
{
int i ;
WAGON *wag=(WAGON*)malloc(n*sizeof(WAGON));
if(wag==NULL){
fprintf(stderr, "Erreur d allocation\n");
exit(1);}
for(i=0 ;i<n ;i++)
{
wag[i].sieges=90;
wag[i].passagers=0;
}
return wag ;
}
3) Ecrire une fonction unsigned int wagon_places_dispo(WAGON*) qui
calcule le nombre de places disponibles dans un wagon dont on fait passer l’adresse en
argument d’entrée.

unsigned int wagon_places_dispo(WAGON *wag)


{
if(wag !=NULL)
{
return(wag->sieges-wag->passagers) ;
}
else return 0;
}

4) Ecrire une fonction unsigned int wagon_ajouter_passagers(WAGON*,


unsigned int) qui permet d’ajouter des passagers (dont le nombre correspond à
l’entier positif fourni en second argument d’entrée) dans un wagon (dont on connaît
l’adresse, fournie en premier argument) et qui renvoie :
a. 0 si tous les passagers ont trouvé une place,
b. le nombre de passagers qui n’ont pas trouvé de places.

unsigned int wagon_ajouter_passagers(WAGON *wag, unsigned int


ajout)
{
unsigned int places_dispo=_places_dispo(wag) ;
if(places_dispo>=ajout)
{
wag->passagers+=ajout ;
return 0 ;
}
else
{
wag->passagers=wag->sieges ;
return(wag->passagers-places_dispo) ;
}
}

Soit la structure nommée « train » composée de deux champs : le premier sera un entier
positif indiquant le nombre de wagons, et le second, un pointeur sur une structure de type
WAGON.

5) Ecrire la déclaration de la structure « train » de type synonyme « TRAIN ».

typedef struct train{


unsigned int nb ;
WAGON *tab ;
}TRAIN ;
6) Ecrire une fonction TRAIN *train_init(int n) qui permet d’allouer un
pointeur sur un train contenant « n » wagons (on remplira les champs du train en
conséquence).

TRAIN *train_init(int n)
{
TRAIN *tchoutchou=(TRAIN*)malloc(sizeof(TRAIN)) ;
if(tchoutchou==NULL) ){
fprintf(stderr, "Erreur d allocation\n");
exit(1);}
tchoutchou->tab=wagon_init(n) ;
tchoutchou->nb=n ;
return n ;
}

7) Ecrire une fonction TRAIN *train_ajouter_train(TRAIN*, TRAIN*) qui


permet de fusionner ensemble deux trains. Le résultat de cette somme est un nouveau
train contenant tous les wagons des 2 autres.

TRAIN *train_ajouter_train(TRAIN *A, TRAIN *B)


{
int nb_a, nb_b, nb, i, j ;
TRAIN *nouveau =NULL;
if (A==NULL) nb_a=0 ; else nb_a=A->a ;
if (B==NULL) nb_b=0 ; else nb_b=B->b ;
nb=nb_a+nb_b ;
nouveau=(TRAIN*)malloc(sizeof(TRAIN)) ;
if(nouveau ==NULL){
fprintf(stderr, "Erreur d allocation\n");
exit(1);}
nouveau->nb=nb ;
nouveau->tab=wagon_init(nb) ;
for(i=0 ;i<nb_a ;i++)
nouveau->tab[i]=A->tab[i] ;
for(j=0 ;j<nb_b ;j++)
nouveau->tab[i+j]=B->tab[i] ;
return nouveau ;
}

8) Ecrire une procédure void train_ajouter_wagon(TRAIN*, WAGON*) qui


permet d’ajouter un wagon à un train. Le train résultant sera égal au train précédent
avec un wagon supplémentaire (correspondant au wagon dont l’adresse est fournie en
argument d’entrée).

void train_ajouter_wagon(TRAIN *tchoutchou, WAGON *wag)


{
WAGON *nouveau_tab=NULL ;
int i ;
if (tchoutchou==NULL) ){
fprintf(stderr, "Le train n existe pas\n");
exit(1);}
if (wag !=NULL)
{
nouveau_tab=wagon_init(tchoutchou->nb+1) ;
for (i=0 ; i<tchoutchou->nb ;i++)
nouveau_tab[i]= tchoutchou->tab[i] ;
nouveau_tab[i]=*wag ;
if(tchoutchou->tab !=NULL) free(tchoutchou->tab) ;
tchoutchou->tab=nouveau_tab ;
}
}

9) Ecrire une procédure void train_ajouter_passagers(TRAIN*,


unsigned int) qui permet d’ajouter des passagers (dont le nombre correspond à
l’entier positif fourni en second argument d’entrée) au train (dont on connaît l’adresse
via le premier argument) en commençant par remplir le premier wagon, puis le second
et ainsi de suite tant qu’il reste des passagers à placer ; s’il n’y a plus de places
disponibles dans le train, on ajoute un nouveau wagon contenant le nombre de
passagers restant à placer.

void train_ajouter_passagers(TRAIN *tchoutchou, unsigned int


ajout)
{
WAGON *nouveau=NULL ;
int i=0 ;

while(ajout !=0 && i<tchoutchou->nb)


{
ajout=wagon_ajouter_passagers(tchoutchou->tab[i],ajout);
i++ ;
}
while(ajout !=0)
{
nouveau=wagon_init(1) ;
ajout=wagon_ajouter_passagers(nouveau,ajout);
train_ajouter_wagon(tchoutchou,nouveau) ;
if(nouveau !=NULL){free(nouveau) ;nouveau=NULL ;}
}
}

10) Ecrire une procédure void train_tri_wagon(TRAIN*) qui trie les wagons du
train selon l’ordre croissant du nombre de passagers avec la méthode de votre choix.

void wagon_permute(WAGON *A, WAGON *B)


{
WAGON C=*A ;*A=*B ;*B=C ;
}

/* tri à bulle */
void train_tri_wagon(TRAIN *tchoutchou)
{
int permut=1 ;
int i=0, k=tchoutchou->nb-1 ;

while(permut !=0 && k>0)


{
permut=0 ;
for(i=0 ;i<k ;i++)
if(tchoutchou->tab[i]>tchoutchou->tab[i+1])
{
wagon_permute(tchoutchou->tab[i],tchoutchou->tab[i+1]);
permut=1 ;
} /* fin du if */
k-- ;
} /* fin du while */
}

11) Ecrire une procédure void train_libere(TRAIN*) qui libère la mémoire


allouée à un train.

void train_libere(TRAIN *tchoutchou)


{
if(tchoutchou !=NULL)
{
if(tchoutchou->tab !=NULL) free(tchoutchou->tab) ;
free(tchoutchou) ;
}
}