TP2 corrigé

Transcription

TP2 corrigé
ESIEE 2011–2012
IN3T01 Programmation C
TP 2 corrigé Jean-Claude Georges - Michel Landschoot
PARTIE 1: LES FONCTIONS ET LES POINTEURS
fichier fonctions.h
#ifndef _FONCTION_H_
#define _FONCTION_H_
#include <stdio.h>
#include <math.h>
/* inutile sous UNIX */
#define M_PI
3.14159265358979323846
/* les déclarations prototypes des fonctions et les macro-définitions */
# define DUREE_LEGALE 35
# define TAUX_MAJ_HEUR_SUP 150 /* 150 % */
/* Conversion kilomètres-miles */
void km_vers_mile(double km, double * pmile);
/* Conversion Fahrenheit – C */
void F_vers_C(double F, double * pC);
/* Volume d’une sphère */
void volume_sphere(double rayon, double * pvolume);
/* Notes */
void note (int bonnes_reponses, char * pc);
/* Salaire */
void salaire_hebdo(int nb_heures, double salaire_horaire, double * pSalaireHebdo);
#endif
fichier fonctions.c
#include "fonctions.h"
/* les définitions des fonctions */
/* Conversion kilomètres-miles */
void km_vers_mile(double km, double * pmile)
{
*pmile = km /1.609;
}
/* Conversion Fahrenheit – C */
void F_vers_C(double f, double * pc)
{
*pc = 5.0/9.0*(f -32.0);
}
/* Volume d’une sphère */
void volume_sphere(double rayon, double * pvolume)
{
*pvolume = 4.0/3.0 * M_PI * rayon * rayon * rayon;
}
/* Notes */
void note (int bonnes_reponses, char * pc)
{
if ( bonnes_reponses <0 || bonnes_reponses >50) *pc = '#';
else if ( bonnes_reponses <=10) *pc = 'E';
else if ( bonnes_reponses <=20) *pc = 'D';
else if ( bonnes_reponses <=30) *pc = 'C';
else if ( bonnes_reponses <=40) *pc = 'B';
else if ( bonnes_reponses <=50) *pc = 'A';
}
/* Salaire */
void salaire_hebdo(int nb_heures, double salaire_horaire, double * pSalaireHebdo)
{
if ( nb_heures < DUREE_LEGALE )
{
*pSalaireHebdo = nb_heures * salaire_horaire ;
}
else
{
*pSalaireHebdo = ( DUREE_LEGALE
+
( nb_heures - DUREE_LEGALE )
* TAUX_MAJ_HEUR_SUP / 100.0
) * salaire_horaire ;
}
}
fichier testFonctions.c
#include <stdio.h>
#include "fonctions.h"
/* pour afficher le menu */
/* LE MOT CLE static rend la fonction locale
au fichier .c dans lequel elle est définie.
Elle ne peut être appelée dans un fichier .c */
static void afficheMenu(void);
int mainFonctions(void)
{
int choix;
do
{
afficheMenu();
choix = getchar();
switch( choix)
{
case '1':
{
double miles;
km_vers_mile(1609, &miles);
printf("1609 kms valent %.2f miles \n\n", miles);
break;
}
case '2':
{
double celsius;
F_vers_C(457, &celsius);
printf("457 degrés Fahrenheit valent %.2f degrés celsius \n\n", celsius );
break;
}
case '3':
{
double volume;
volume_sphere(60, &volume);
printf("une sphère de rayon 60 m a un volume de %.2f m \n\n", volume);
break;
}
case '4':
{
char c;
note(45, &c);
printf("45 bonnes réponses valent %c \n\n", c);
break;
}
case '5':
{
double salaire;
salaire_hebdo(35, 15, &salaire);
printf("35 heures à 15 euros/h donne un salaire hebdomadaire de %.2f euros \n\n",salaire);
break;
}
default :
printf("choix impossible \n");
break;
}
}
while ((choix = getchar()) != EOF);
return 0;
}
static void afficheMenu(void)
{
printf(" 1 Conversion kilomètres-miles \n");
printf(" 2 Conversion Fahrenheit – C \n");
printf(" 3 Volume d’une sphère \n");
printf(" 4 Notes \n");
printf(" 5 Salaire\n");
printf("taper le numero choisi: ");
}
PARTIE 2: LES TABLEAUX ET LES POINTEURS
Exercice 1: (c'est le passage machine de l'exercice 3 du TD2 avec des double au lieu de int)
Initialiser à 0 un tableau de 20 double avec une boucle for.
Afficher le tableau.
Saisir les valeurs du tableau
Afficher le tableau
1)
version avec la notation des tableaux
2)
version avec la notation des pointeurs
3)
version avec une fonction prenant en paramètre un pointeur
________________________________________________________________________________
fichier testTableaux.c
#include <stdio.h>
void notationTableaux(void);
void notation1Pointeurs(void);
void notation2Pointeurs(void);
void initialiser(float * p, int longueur);
void saisir(float * p, int longueur);
void afficher(float * p, int longueur);
int main(void)
{
printf("\n NOTATION TABLEAU \n");
notationTableaux();
printf("\n NOTATION POINTEUR version simpliste\n");
notation1Pointeurs();
printf("\n NOTATION POINTEUR version élaborée\n");
notation2Pointeurs();
printf("\n AVEC DES FONCTIONS PRENANT EN PARAMETRES DES POINTEURS \n");
/* rappel en C un tableau est passé en paramètre d'une fonction
via l'adresse de son premier élément: &tab[0] noté aussi tab
tab est un pointeur constant valant &tab[0]
il faut aussi passer la longueur du tableau en paramètre */
float tab[5];
initialiser(&tab[0], sizeof(tab)/sizeof(tab[0]));
printf("\n\n Affichage des valeurs initialisées: ");
afficher(tab, sizeof(tab)/sizeof(tab[0]));
printf("\n Saisie des valeurs: ");
saisir(tab, sizeof(tab)/sizeof(tab[0]));
printf("\n\n Affichage des valeurs saisies: ");
afficher(tab, sizeof(tab)/sizeof(tab[0]));
printf("\n");
}
void notationTableaux(void)
{
float tab[5];
int i;
/* initialiser le tableau à 0*/
for ( i = 0; i < sizeof(tab)/sizeof(tab[0]); i++)
{
tab[i] = 0;
}
printf("\n");
/* afficher le tableau */
printf("\n Affichage des valeurs initialisées: ");
for (i = 0; i < sizeof(tab)/sizeof(tab[0]); i++)
{
printf("%.2f ", tab[i]);
}
printf("\n");
/* saisir le tableau */
printf("\n Saisie des valeurs: ");
for (i = 0; i < sizeof(tab)/sizeof(tab[0]); i++)
{
scanf("%f", &tab[i]);
}
printf("\n");
/* afficher le tableau */
printf("\n Affichage des valeurs saisies: ");
for (i = 0; i < sizeof(tab)/sizeof(tab[0]); i++)
{
printf("%.2f ", tab[i]);
}
printf("\n");
}
void notation1Pointeurs(void)
{
float tab[5];
int i;
/* initialiser le tableau à 0*/
for ( i = 0; i < sizeof(tab)/sizeof(tab[0]); i++)
{
*(tab + i) = 0;
}
printf("\n");
/* afficher le tableau */
printf("\n Affichage des valeurs initialisées: ");
for (i = 0; i < sizeof(tab)/sizeof(tab[0]); i++)
{
printf("%.2f ", *(tab + i));
}
printf("\n");
/* saisir le tableau */
printf("\n Saisie des valeurs: ");
for (i = 0; i < sizeof(tab)/sizeof(tab[0]); i++)
{
scanf("%f", tab + i);
}
printf("\n");
/* afficher le tableau */
printf("\n Affichage des valeurs saisies: ");
for (i = 0; i < sizeof(tab)/sizeof(tab[0]); i++)
{
printf("%.2f ", *(tab + i));
}
printf("\n");
}
/* ON UTILISE L'ARITHMETIQUE DES POINTEURS dans les boucles for */
void notation2Pointeurs(void)
{
float tab[5];
float * p;
/* initialiser le tableau à 0*/
for ( p = tab; p < tab + sizeof(tab)/sizeof(tab[0]); p++)
{
*p = 0;
}
printf("\n");
/* afficher le tableau */
printf("\n Affichage des valeurs initialisées: ");
for ( p = tab; p < tab + sizeof(tab)/sizeof(tab[0]); p++)
{
printf("%.2f ", *p);
}
printf("\n");
/* saisir le tableau */
printf("\n Saisie des valeurs: ");
for ( p = tab; p < tab + sizeof(tab)/sizeof(tab[0]); p++)
{
scanf("%f", p);
}
printf("\n");
/* afficher le tableau */
printf("\n Affichage des valeurs saisies: ");
for ( p = tab; p < tab + sizeof(tab)/sizeof(tab[0]); p++)
{
printf("%.2f ", *p);
}
printf("\n");
}
/* ON UTILISE L'ARITHMETIQUE DES POINTEURS dans les boucles for */
void initialiser(float * p, int longueur)
{
float * pcourant;
for ( pcourant = p; pcourant < p + longueur; pcourant++)
{
*pcourant = 0;
}
}
void saisir(float * p, int longueur)
{
float * pcourant;
for ( pcourant = p; pcourant < p + longueur; pcourant++)
{
scanf("%f", pcourant);
}
}
void afficher(float * p, int longueur)
{
float * pcourant;
for ( pcourant = p; pcourant < p + longueur; pcourant++)
{
printf("%.2f ", *pcourant);
}
}
Pour les exercices suivants les tableaux seront initialisés en dur dans la fonction main:
exemple:
double tab[4] = { 2.1, 4.8, 16.32, 5.0 };
tab tableau de 4 double
ou
double tab[] = { 2.1, 4.8, 16.32, 5.0 };
tab tableau de 4 double (le compilateur calcule tout seul le nombre
d'éléments du tableau).
Toutes les déclarations prototypes des fonctions sont dans un fichier fonctions_tableaux.h
Toutes les définitions des fonctions sont dans un fichier fonctions_tableaux.c
La fonction main contient les appels aux fonctions demandées et les affichages des résultats dans
un fichier main.c
Exercice 2: Moyenne
Écrivez la fonction qui calcule la moyenne des n premiers éléments stockés dans un
tableau de double.
Prototype :
double moyenne (double t[], int n); ou
double moyenne (double * t, int n);
Exercice 3: Les carrés
Écrivez la fonction qui remplit un tableau de n int par les carrés des n premiers nombres
entiers et ne retourne aucune valeur.
Prototype :
void remplit_carres (doublet[], int n); ou
void remplit_carres (double * t, int n);
Afficher le tableau remplit en utilisant une fonction d'affichage.
Exercice 4: Recherche d’éléments sur critère
Écrivez la fonction qui retourne l’indice du premier élément strictement négatif parmi les n
premiers éléments d’un tableau de double (-1 si aucun élément n’est négatif).
Prototype :
ou
int indice_premier_negatif (double t[], int n);
int indice_premier_negatif (double * t, int n);
Exercice 5:Maximum
Écrivez la fonction qui retourne la valeur du plus grand des n premiers éléments d’un
tableau de double.
Prototype :
ou
double valeur_plus_grand (double t[], int n);
double valeur_plus_grand (double * t, int n);
Exercice 6: Position du maximum
Écrivez la fonction qui retourne l’indice du plus grand des n premiers éléments d’un
tableau de double (en cas d’ex-æquo, l’indice du premier d’entre eux).
Prototype :
ou
int indice_plus_grand (double t[], int n);
int indice_plus_grand (double * , int n);
Exercice 7: Copie
Écrivez la fonction qui copie les n premiers éléments d’un tableau source de double dans
le tableau destination de double et retourne l’adresse du tableau destination. On prendra
en compte le fait que les deux tableaux ne peuvent pas se recouvrir partiellement (2 tableaux
différents).
Prototype : double * copie (double * destination, double * source, int n);
fichier fonctions_tableaux.h
#ifndef _FONCTION_TABLEAUX_H_
#define _FONCTION_TABLEAUX_H_
double moyenne (double * t, int n);
void remplit_carres (int * t, int n);
int indice_premier_negatif (double * t, int n);
double valeur_plus_grand (double * t, int n);
int indice_plus_grand (double * t, int n);
double * copie (double * destination, double * source, int n);
#endif
LES FONCTIONS SONT ECRITES EN UTILISANT LES NOTATIONS TABLEAU
fichier fonctions_tableaux.c
#include "fonctions_tableaux.h"
double moyenne (double * t, int n)
{
int i;
double total =0.0;
for (i = 0 ; i < n ; ++ i )
{
total += t[i];
}
return total /n;
}
void remplit_carres (int * t, int n)
{
int i;
for (i=0; i<n ; ++i )
{
t[i]=i*i;
}
}
indice_premier_negatif
L'analyse du problème nous conduit à la solution suivante :
on parcourt le tableau
si l'on rencontre un élément négatif, on termine la fonction en retournant l'indice courant
si l'on a parcouru l'intégralité du tableau sans avoir rencontré d'élément négatif, on retourne
−1 comme indiqué dans la spécification.
Attention : c'est après la boucle que l'on peut constater l'absence d'élément négatif.
Une erreur courante de programmation consiste à retourner −1 trop tôt, avec un test du style
if (t[i]<0) return i; else return -1;
ce qui conduit à retourner -1 si le premier un élément n'est pas négatif.
int indice_premier_negatif (double * t, int n)
{
int i;
for (i =0; i<n ; ++ i)
{
if (t[i] <0)
return i;
}
return -1;
}
valeur_plus_grand
L'analyse du problème nous conduit à la solution suivante :
Un parcours du tableau s'impose, avec une mémorisation du plus grand élément rencontré.
En effet, le plus grand élément du tableau peut se situer n'importe où (en début, en cours ou en fin de
tableau) et donc on ne peut le connaître qu'après avoir examiné tous les éléments du tableau, et le
mémoriser permettra de le retourner en fin de parcours.
L'initialisation de ce maximum pourra se faire par le premier élément du tableau ( t[0] ), et la
boucle peut commencer par l'indice 1. Le corps de la boucle consistera à comparer l'élément courant
au maximum, et, s'il lui est supérieur, à le mémoriser dans le maximum.
Ce qui conduit à la solution suivante :
double valeur_plus_grand (double * t, int n)
{
int i;
double maxi =t [0];
for (i=1; i<n ; ++i )
{
if (t[i]> maxi )
maxi =t[i];
}
return maxi ;
}
indice_plus_grand
L'analyse du problème nous conduit à la solution suivante :
Le programme est semblable au précédent. Un parcours du tableau s'impose, avec une mémorisation
de l'indice du plus grand élément rencontré. En effet, le plus grand élément du tableau peut se
situer n'importe où (en début, en cours ou en n de tableau) et donc on ne peut le connaître qu'après
avoir examiné tous les éléments du tableau ; mémoriser sa position permettra de la retourner en fin
de parcours.
L'initialisation de cet indice maximum pourra se faire par l'indice du premier élément du tableau
( 0 ), et la boucle peut commencer par l'indice 1.
Ce qui conduit à la solution suivante :
int indice_plus_grand (double * t, int n)
{
int i;
int imax =0;
for (i=1; i<n ; ++i )
{
if (t[i]>t[ imax ])
imax =i;
}
return imax ;
}
copie
L'analyse du problème nous conduit à la solution suivante :
La solution naturelle est basée sur le principe : on parcourt parallèlement les deux tableaux et on
copie élément par élément le contenu du tableau source dans le tableau destination, ce qui donne :
/* Attention : ne fonctionne que si
* les tableaux ne se recouvrent pas
*/
double * copie (double * destination, double * source, int n)
{
int i;
for (i =0 ; i<n ; ++ i)
{
destination [i ] = source [i];
}
return destination ;
}

Documents pareils

Examen - Master 1 - UPMC

Examen - Master 1 - UPMC avec tout autre pointeur et dont la valeur à cette adresse ne peut être modifiée. L’argument compar est un pointeur sur une fonction prenant deux arguments (duex pointeurs génériques sur valeur con...

Plus en détail

Petite initiation au langage C et au graphisme SDL

Petite initiation au langage C et au graphisme SDL 2.1018. C’est le moment de voir la limite du bon usage des entiers. Pour cela reprendre le programme de la factorielle, en faisant à la fois un calcul en entiers et un calcul en flottants pour des ...

Plus en détail