Académique Documents
Professionnel Documents
Culture Documents
— En cas de manque de place, des cadres supplémentaires sont disponibles en page 7 pour la partie 1, et en
page 14 pour la partie 2.
— Le memento FORTRAN figure en fin de premier et deuxième livret pages 8, 15 et 16.
1. Parmi les instructions suivantes, cocher celles qui permettent de générer aléatoirement un entier compris entre 1 et 6
au sens large, avec la même probabilité. La variable r est déclarée réelle, la variable e entière.
2016-2017(by
c UPMC/Licence Mécanique/2A005) 9 mai 2017
UE 2A005 Version enseignant Examen 2016-2017 – page 2/9
Solution :
Les réponses 1 et 5 sont valides.
2. Le code suivant doit créer un tableau dynamique de n réels, n étant saisi par l’utilisateur, puis demander d’en saisir
le contenu et l’afficher. Trouver 5 erreurs ou oublis (penser aux bonnes pratiques liées à l’allocation dynamique).
Corriger les lignes correspondantes dans le cadre de droite, sans récrire la totalité du code.
PROGRAM cinq_erreurs
IMPLICIT NONE
PROGRAM cinq_erreurs
INTEGER :: n, ok
IMPLICIT NONE
! Erreur 1 : ALLOCATABLE
INTEGER :: n, ok
REAL, DIMENSION(:), ALLOCATABLE :: tab
REAL, DIMENSION(:) :: tab
! Erreur 2 : saisie d’abord
PRINT *, "Saisir la taille n"
ALLOCATE(tab(n), IOSTAT=ok)
READ *, n
! Erreur 3 : STAT et pas IOSTAT
PRINT *, "Saisir la taille n"
ALLOCATE(tab(n), STAT=ok)
READ *, n
! Oubli 4 : Test allocation
IF (ok /= 0) STOP "probleme allocation"
PRINT *, "Saisir le tableau"
PRINT *, "Saisir le tableau"
READ *, tab
READ *, tab
PRINT *, "Le tableau est :"
PRINT *, "Le tableau est :"
PRINT *, tab
PRINT *, tab
! Oubli 5 : Desallocation
END PROGRAM cinq_erreurs
DEALLOCATE(tab)
END PROGRAM cinq_erreurs
2016-2017(by
c UPMC/Licence Mécanique/2A005) 9 mai 2017
UE 2A005 Version enseignant Examen 2016-2017 – page 3/9
11
ARTHAUD Nathalie 232428
ASSELINEAU Francois 332588
CHEMINADE Jacques 65598
DUPONT-AIGNAN Nicolas 1695186
...
On écrit un programme permettant d’afficher le classement des candidats et le pourcentage des voix exprimées qui se
sont portées sur eux.
1. Le programme a été commencé et le listing disponible est affiché ci-dessous. Le compléter aux endroits indiqués par
des lignes horizontales : _________.
Solution :
MODULE mod_election
IMPLICIT NONE
CONTAINS
SUBROUTINE lecture_fichier(nom_fichier, nom_cand, nb_voix)
CHARACTER(LEN=*), INTENT(IN) :: nom_fichier
CHARACTER(LEN=22), DIMENSION(:), ALLOCATABLE, INTENT(OUT) :: nom_cand
INTEGER, DIMENSION(:), ALLOCATABLE, INTENT(OUT) :: nb_voix
DO i=1, nb_cand
READ (UNIT=10, FMT=’(A22,I10)’) nom_cand(i), nb_voix(i)
END DO
CLOSE(UNIT=10) ! Fermeture fichier
END SUBROUTINE lecture_fichier
END MODULE mod_election
PROGRAM election
USE mod_election
IMPLICIT NONE
CHARACTER(LEN=22), DIMENSION(:), ALLOCATABLE :: nom_cand
INTEGER, DIMENSION(:), ALLOCATABLE :: nb_voix
2016-2017(by
c UPMC/Licence Mécanique/2A005) 9 mai 2017
UE 2A005 Version enseignant Examen 2016-2017 – page 4/9
Solution :
Le sous-programme lecture_fichier prend en entrée l’argument nom_fichier, qui contient le nom
d’un fichier qu’il ouvre. En cas d’échec, le programme s’arrête avec un message d’erreur. Le sous-programme
lit ensuite nb_cand le nombre de candidats placé dans le premier enregistrement. Ceci lui permet de faire l’al-
location des tableaux dynamiques nom_cand et nb_voix, avec arrêt et message d’erreur éventuels. Ensuite,
à l’aide d’une boucle, le nom et le nombre de voix de chaque candidat sont lus et placés dans les tableaux, puis
le fichier est fermé.
2. On rappelle l’algorithme du tri à bulles, qui trie les n éléments d’un tableau tab de la plus petite valeur à la plus
grande.
Algorithme 1 Tri à bulles du tableau tab. Les variables i et j sont entières, fini est booléenne.
1: Pour j de 1 à n
2: fini ←− vrai
3: Pour i de n − 1 à j par pas de −1
4: Si tab(i + 1) < tab(i) alors
5: Échanger tab(i + 1) et tab(i)
6: fini ←− faux
7: Fin si
8: Fin pour
9: Si fini alors exit
10: Fin pour
Écrire la subroutine de tri, appelée par le programme principal (voir listing plus haut), qui trie le tableau nb_voix
du plus grand nombre de voix au plus petit. Bien entendu, les opérations faites sur le tableau nb_voix devront
également être effectuées sur le tableau nom_cand afin de pas perdre la correspondance entre nombre de voix et
nom des candidats !
La subroutine aura l’interface suivante :
SUBROUTINE tri_candidats(nom_cand, nb_voix)
CHARACTER(LEN=*), DIMENSION(:), INTENT( ??? ) :: nom_cand
INTEGER, DIMENSION(:), INTENT( ??? ) :: nb_voix
END SUBROUTINE tri_candidats
Solution :
SUBROUTINE tri_candidats(nom_cand, nb_voix)
CHARACTER(LEN=*), DIMENSION(:), INTENT(INOUT) :: nom_cand
INTEGER, DIMENSION(:), INTENT(INOUT) :: nb_voix
INTEGER :: i, j, tmp
CHARACTER(LEN=22) :: ctmp
LOGICAL :: fini
DO j = 1, SIZE(nb_voix, 1)
fini = .TRUE.
DO i = SIZE(nb_voix, 1) - 1, j, -1
IF (nb_voix(i+1) > nb_voix(i)) THEN
tmp = nb_voix(i) ; nb_voix(i) = nb_voix(i+1) ; nb_voix(i+1) = tmp
ctmp = nom_cand(i) ; nom_cand(i) = nom_cand(i+1) ; nom_cand(i+1) = ctmp
fini = .FALSE.
END IF
END DO
2016-2017(by
c UPMC/Licence Mécanique/2A005) 9 mai 2017
UE 2A005 Version enseignant Examen 2016-2017 – page 5/9
IF (fini) EXIT
END DO
END SUBROUTINE tri_candidats
3. Écrire la subroutine d’affichage appelée par le programme principal (voir listing plus haut). Cette procédure affichera,
en colonnes parfaitement alignées, le classement, le nom du candidat, et le pourcentage de voix obtenues avec deux
chiffres après le séparateur décimal. On donne ici un extrait de l’affichage attendu à l’écran :
01 - MACRON Emmanuel 24.01 %
...
09 - ASSELINEAU Francois 0.92 %
10 - ARTHAUD Nathalie 0.64 %
11 - CHEMINADE Jacques 0.18 %
Solution :
SUBROUTINE affichage_resultats(nom_cand, nb_voix)
CHARACTER(LEN=*), DIMENSION(:), INTENT(IN) :: nom_cand
INTEGER, DIMENSION(:), INTENT(IN) :: nb_voix
REAL :: pourcentage
INTEGER :: i
DO i = 1, SIZE(nb_voix, 1)
pourcentage = 100.*nb_voix(i)/SUM(nb_voix)
WRITE(*,FMT=’(I2.2,A3,A22,F6.2,A)’) i, ’ - ’, nom_cand(i), pourcentage, " %"
END DO
END SUBROUTINE affichage_resultats
4. Pensez-vous que ce stockage des données sous la forme de deux tableaux soit bien adapté ? Justifier.
Solution :
Non, il aurait été préférable de créer un type dérivé candidat avec des champs nom_cand, nb_voix, etc.
Cela aurait évité de manipuler indépendamment les différents tableaux lors du tri.
2016-2017(by
c UPMC/Licence Mécanique/2A005) 9 mai 2017
UE 2A005 Version enseignant Examen 2016-2017 – page 6/9
Afin de représenter le boulier, nous définissons le type dérivé boulier qui comprend :
— un champ entier valeur, destiné à prendre la valeur totale représentée par le boulier
— deux champs boul_sup, et boul_inf, qui sont des tableaux entiers dont l’indice est le numéro de fil (de 0
à nf-1). Le tableau boul_sup contiendra, pour chaque fil du boulier pris de droite à gauche, le nombre de
boules activées dans la partie haute (0 ou 1). Le tableau boul_inf contiendra, pour chaque fil du boulier, le
nombre de boules activées dans la partie basse (0, 1, 2, 3 ou 4).
Solution :
MODULE mod_boulier
IMPLICIT NONE
INTEGER, PARAMETER :: nf = 4
TYPE boulier
INTEGER, DIMENSION(0:nf-1) :: boul_sup
INTEGER, DIMENSION(0:nf-1) :: boul_inf
INTEGER :: valeur
END TYPE boulier
END MODULE mod_boulier
Pour les questions 2 à 7, les différentes procédures sont supposées placées dans le module précédent.
2. Écrire une fonction nbmax(n_fils) qui calcule et retourne la plus grande valeur qu’il est possible d’inscrire sur
un boulier à n_fils fils. On notera qu’un entier e inscrit sur le fil i donne une contribution e × 10i à la valeur
représentée par le boulier.
Solution :
2016-2017(by
c UPMC/Licence Mécanique/2A005) 9 mai 2017
UE 2A005 Version enseignant Examen 2016-2017 – page 7/9
nbmax = 0
DO i = 0, n_fils-1
nbmax = nbmax + 9*10**i
ENDDO
! ou bien tout simplement
! nbmax = 10**n_fils - 1
END FUNCTION nbmax
3. Écrire la procédure afficherBoulier(b) qui affiche sur deux lignes le nombre de boules activées dans la partie
haute, et le nombre de boules activées dans la partie basse de la variable b de type dérivé boulier (attention à
l’ordre : les unités doivent être à droite). On suppose ici que les champs de la variable b ont déjà été initialisés, de
sorte qu’il suffit de les afficher.
On utilisera un format. Pour l’exemple donné plus haut, l’affichage devra donner :
haut : 1 1 0 0
bas : 0 1 0 3
Solution :
SUBROUTINE afficherBoulier(b)
TYPE(boulier), INTENT(IN) :: b
4. Pour initialiser un boulier b, il faut activer des boules sur chaque fil. Écrire le sous-programme activerBoules
(b, ifil, e) qui permet l’activation des boules sur le fil ifil du boulier b, de manière à représenter l’entier
e sur ce fil. L’entier e est connu lors de l’appel au sous-programme. Il est compris au sens large entre 0 et 9 (il n’est
pas nécessaire de contrôler la valeur de e).
Solution :
SUBROUTINE activerBoules(b, ifil, e)
TYPE(boulier), INTENT(INOUT) :: b
INTEGER, INTENT(IN) :: ifil, e
IF (e < 5) THEN
b%boul_sup(ifil) = 0
b%boul_inf(ifil) = e
ELSE
b%boul_sup(ifil) = 1
b%boul_inf(ifil) = e - 5
ENDIF
END SUBROUTINE activerBoules
5. Expliquer ce que fait la procédure X suivante. Illustrer avec nf = 4 et n = 183, et indiquer le contenu de T qui
serait affiché à la fin de la procédure.
2016-2017(by
c UPMC/Licence Mécanique/2A005) 9 mai 2017
UE 2A005 Version enseignant Examen 2016-2017 – page 8/9
SUBROUTINE X(n, T)
INTEGER, INTENT(IN) :: n
INTEGER, DIMENSION(0:nf-1), INTENT(OUT) :: T
INTEGER :: i, nb
nb = n
DO i = 0, nf-1
T(i) = MOD(nb,10)
nb = nb/10
ENDDO
PRINT *, "T = ", T
END SUBROUTINE X
Solution :
La procédure prend en entrée un entier n et le décompose en unités, dizaines, etc... dans le tableau de sortie T .
Par exemple, si n = 183, alors initialement nb = 183, et MOD(183, 10) vaut 3 qui est affecté dans T (0). Puis
nb = 183/10 prend la valeur 18, et MOD(18, 10) vaut 8, affecté dans T (1). Puis nb = 18/10 prend la valeur 1,
et MOD(1, 10) vaut 1, affecté dans T (2). Puis nb = 1/10 prend la valeur 0, et MOD(0, 10) vaut 0, affecté dans
T (3). L’affichage de T donne donc T = 3 8 1 0.
6. A l’aide des procédures nbmax, X et activerBoules, écrire le sous-programme initBoulier(b) qui effec-
tue les tâches suivantes :
— demande à l’utilisateur de saisir un nombre n, la saisie de n étant recommencée tant que ce nombre est négatif
ou nul, ou est trop grand pour le boulier,
— appelle le sous-programme X et active correctement les boules sur chaque fil du boulier b.
On pourra avoir besoin d’un tableau dynamique T(0:nf-1), à allouer et initialiser à 0 en début de sous-programme.
Solution :
SUBROUTINE initBoulier(b)
TYPE(boulier), INTENT(INOUT) :: b
INTEGER n, i, ok
INTEGER, DIMENSION(:), ALLOCATABLE :: T
ALLOCATE(T(0:nf-1),stat=ok)
IF (ok /= 0) STOP "erreur allocation T"
T(:) = 0
! decomposition de n en puissances de 10
CALL X(n,T)
DO i = 0, nf-1
CALL activerBoules(b, i, T(i))
ENDDO
2016-2017(by
c UPMC/Licence Mécanique/2A005) 9 mai 2017
UE 2A005 Version enseignant Examen 2016-2017 – page 9/9
7. Écrire le sous-programme valeurBoulier(b) qui, à l’aide des champs boul_sup et boul_inf du boulier b
donné en entrée, calcule la valeur représentée et l’affecte au champ valeur du boulier b.
Solution :
SUBROUTINE valeurBoulier(b)
TYPE(boulier), INTENT(INOUT) :: b
INTEGER :: i, n
b%valeur = 0
DO i = 0, nf-1
b%valeur = b%valeur + (5*b%boul_sup(i) + b%boul_inf(i)) * 10**i
ENDDO
END SUBROUTINE valeurBoulier
8. Écrire un programme principal boulier_japonais qui utilise le module mod_boulier contenant toutes les
déclarations et procédures. Le programme déclare une variable BJ de type dérivé boulier, initialise ce boulier,
l’affiche, calcule ensuite la valeur représentée par le boulier et l’affiche (ce qui permet de vérifier que l’initialisation
s’est bien passée).
Solution :
PROGRAM boulier_japonais
USE mod_boulier
IMPLICIT NONE
TYPE(boulier) :: BJ
CALL initBoulier(BJ)
CALL afficherBoulier(BJ)
CALL valeurBoulier(BJ)
PRINT *, "valeur boulier = ", BJ%valeur
END PROGRAM boulier_japonais
2016-2017(by
c UPMC/Licence Mécanique/2A005) 9 mai 2017