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