Université des Antilles et de la Guyane
Contrôle terminal Informatique (session 2) UEO12
Durée 1 heure 30 Mai 2010
(polycopié, cours en ligne, notes de cours/TD et TP autorisés)
Proposition de correction – PEROUMALNAÏK M. <mperouma@univ-ag.fr>
Question 1 (6 pts)
Ecrire une fonction nommée «modif» qui prend un entier en paramètre. La fonction ne renvoie rien. Si cet entier est strictement inférieur à 0, alors cet entier est modifié: sa valeur est mise à 0. Si cet entier est positif ou nul, alors il reste inchangé.
Proposition de correction (commentée)
Les questions sur l'écriture de fonctions sont des questions usuelles à cet examen. Dans tous les cas, pour parvenir à coup sûr à la solution de l'exercice, la procédure à adopter pour les résoudre est la même :
1) Identifier les Entrées / Sorties et les actions à réaliser par la fonction 2) Ecrire l'entête de la fonction
3) Préciser le traitement à effectuer (variables/types, étapes) 4) Ecrire le corps de la fonction.
5) (Si c'est demandé) Ecrire le main() permettant d'appeler la fonction Je vous propose donc de corriger cet exercice en suivant ces étapes.
1) Identification des E/S
D'après l'énoncé, cette fonction « prend un entier en paramètre et ne renvoie rien ». De plus, l'énoncé nous précise que la valeur passée en paramètre est modifiée par la fonction.
Cette opération n'est possible qu'en utilisant les pointeurs. En effet, l'ensemble des variables déclarées au sein d'une fonction (variables locales) n'existent que dans le cadre de l'exécution de cette fonction. Pour modifier des variables externes à la fonction, il faut utiliser leur adresse mémoire.
2) Ecriture du prototype de la fonction
Le paramètre de la fonction sera donc un pointeur sur une valeur entière donc de type « int * ». La fonction ne renvoyant rien, son type de retour sera « void ». Le nom de la fonction est donné par l'énoncé (« modif »).
Prototype de fonction :
type_de_retour nom (type1 arg1, type2 arg2, ....) {
//Déclarations //Traitement
//Si type_de_retour n'est pas « void »
return var //var étant de type type_de_retour }
type_de_retour : type de la donnée renvoyée à la procédure appelante par la fonction
nom : nom de la fonction
typen argn : type et nom des paramètres de la fonction
Nous pouvons ainsi écrire le prototype de notre fonction : void modif (int* nb_ent)
{ }
3) Traitement à effectuer
D'après l'énoncé, nous allons réaliser un test sur le contenu de la variable entière dont l'adresse mémoire est passée en paramètre de la fonction. Si sa valeur est strictement inférieure à 0, en utilisant l'adresse mémoire de cette variable, nous allons remplacer son contenu par 0. C'est tout.
if(*nb_ent <0) {
*nb_ent=0 ; }
Il ne reste plus qu'à placer ce traitement dans la fonction 4) Ecriture de la fonction
L'énoncé étant explicite et ne demandant pas de justifier votre réponse, après avoir recopié ce dernier, votre réponse à cette question peut-être la suivante :
void modif (int* nb_ent) {
if(*nb_ent <0) {
*nb_ent=0 ; }
}
Question 2 ( 7 pts)
Ecrire un programme qui demande à l'utilisateur de créer un tableau de réel. Le programme demande à l'utilisateur de donner une valeur pour la taille du tableau, puis lui demande de rentrer les valeurs. Enfin le programme donne la moyenne des valeurs positives du tableau
Proposition de correction (commentée)
Au cours du programme, nous aurons à la fois à réserver dynamiquement de l'espace mémoire, mais aussi à effectuer un traitement sur les données saisies par l'utilisateur au sein de cet espace.
La réservation dynamique d'espace mémoire peut-être réalisée en C par la fonction « malloc »
Rappel cours
Malloc permet d'allouer dynamiquement un espace mémoire dont la taille est précisée en paramètre de la fonction1. Si l'appel à la fonction se réalise correctement, cette fonction renvoie un pointeur (de type void*
donc il faut réaliser un cast) sur la plage mémoire réservée. Dans le cas contraire, la fonction renvoie NULL
Une fois que l'espace mémoire n'est plus utilisé, il faut le libérer en utilisant la fonction free
void* malloc(int size)
Dans ce programme, nous devrons :
1) Récupérer la taille du tableau en interrogeant l'utilisateur 2) Allouer le tableau
3) Faire l'utilisateur saisir chacune des cases du tableau 4) Réaliser la moyenne des valeurs positives du tableau Il nous faut donc les variables suivantes :
int taille_tab => pour récupérer la taille du tableau int* tab => pointeur destiné à recevoir le tableau
int i => compteur pour la boucle de parcours du tableau (saisie et calcul moyenne val positives)
float moy => variable pour recevoir la somme puis la moyenne des cases positives du tableau.
int nb_pos => variable permettant de compter le nombre de valeurs positives trouvées dans le tableau.
#include<stdlib.h>
int main() {
int taille_tab, i, nb_pos=0, *tab=NULL ; float moy=0.0;
//Saisie de la taille du tableau tant qu'incorrecte do
{
printf(« Saisir la taille du tableau : ») ; scanf(« %d », &taille_tab) ;
}while(taille_tab <1);
//Allocation du tableau
tab = (int*)malloc(sizeof(int)*taille_tab) ; if(tab == NULL)
{
//Si pb d'allocation mémoire, quitter programme printf(« Erreur allocation tableau\n ») ;
return 0 ; }
//Saisie des éléments du tableau et calcul de la somme for(i=0 ; i<taille_tab ; i++)
{
printf(« Saisir case %d : »,i) ; scanf(« %d », &tab[i]) ;
if(tab[i] >0) {
nb_pos=nb_pos+1 ; moy=moy+tab[i] ; }
}
if(nb_pos>0) {
moy=moy/nb_pos ;
printf(« La moyenne des nbres positifs ») ; printf(« est : %0.2f\n », moy) ;
} else {
printf(« Pas de nombres positifs saisis\n ») ; }
//Libérer le tableau free(tab) ;
return 0 ; }
Question 3 ( 7 pts) Soit la structure suivante:
struct Segment {
float Xa;
float Xb;
};
qui représente les deux extrémités d'un segment.
Ecrire une fonction nommée « Milieu » qui prend en paramètre une variable de type Segment et qui renvoie la valeur du milieu du segment.
Ecrire une autre fonction nommé « ModifSeg » qui prend en paramètre une variable de type Segment et modifie ce paramètre: le point Xb du segment est remplacer par la valeur de (-Xa).
Ecrire un programme qui demande à l'utilisateur de rentrer les valeurs Xa et Xb d'un segment puis:
• qui appelle la fonction Milieu sur ce segment et affiche le milieu
• qui appelle la fonction ModifSeg sur ce segment et affiche les nouvelles de Xa et Xb de ce segment.
Rappel:
Le milieu d'un segment est égal à (Xa+Xb)/2
Proposition de correction
La fonction Milieu ne réalise pas de modification sur la variable passée en paramètre. Elle utilise la valeur des champs Xa et Xb de cette variable (Xa et Xb sont des réels) et renvoie un réel égal au milieu du segment.
Nous pouvons donc en déduire l'écriture suivante : float Milieu(struc Segment seg)
{
return ((seg.Xa + seg.Xb)/2.0 ; }
La fonction ModifSeg, elle, effectue une modification sur le paramètre. Il faut donc utiliser un pointeur sur une structure Segment. Le remplacement préconisé n'est soumis à aucune condition :
void ModifSeg(struct Segment *seg) {
seg>Xb = 1 * seg>Xa ;
code suivant :
#include<stdio.h>
//Définition de la structure struct Segment{
float Xa ; float Xb ; } ;
//Fonction Milieu
float Milieu(struc Segment seg) {
return ((seg.Xa + seg.Xb)/2.0 ; }
//Fonction ModifSeg
void ModifSeg(struct Segment *seg) {
seg>Xb = 1 * seg>Xa ; }
main() {
struct Segment seg1 ; //Saisie du segment
printf(« Saisir l'extremité A du segment : ») ; scanf(« %f », &(seg1.Xa));
printf(« Saisir l'extremité B du segment : ») ; scanf(« %f », &(seg1.Xb)) ;
//Affichage segment
printf(« Segment saisi [%0.2f, %0.2f]\n »,seg1.Xa, seg1.Xb);
//Appel à Milieu
printf(« Le milieu du segment %0.2f\n », Milieu(seg1)) ; //Modification segment
ModifSeg(&seg1) ; //Affichage segment
printf(« Nouveau segment [%0.2f, %0.2f]\n »,seg1.Xa, seg1.Xb) ;
}