Solution du Test1 PROG 2016-17 - Moodle

Transcription

Solution du Test1 PROG 2016-17 - Moodle
TEST1 PROG_I MT & EL 11.11.2016
EPFL / R. Boulic
W=blanc, B=bleu, G=vert, Y=jaune, All = même réponse pour tous
1) (12 pts) Anagrammes
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include
#include
#define
#define
<stdio.h>
<stdlib.h>
MAX 1000
MAX_OCTET 256
int main(void){
char mot1[MAX], mot2[MAX], c;
int code_count[MAX_OCTET], k1 = 0, k2 = 0, i;
for(i=0 ; i< MAX_OCTET ; i++) code_count[i]=0;
while(k1 < MAX
mot1[k1++]
while(k2 < MAX
mot2[k2++]
&& ((c = getchar()) != '\n'))
= c;
&& ((c = getchar()) != '\n'))
= c;
if (k1 != k2) {
printf("The two words are not anagrams\n");
return EXIT_SUCCESS;
}
int num_unique_chars = 0;
int num_completed_t = 0;
for (i = 0; i < k1; i++) {
c = mot1[i];
if (code_count[(int) c] == 0) ++num_unique_chars;
code_count[(int) c]++;
}
for (i = 0; i < k2; i++) {
c = mot2[i];
if (code_count[(int) c] == 0) {
printf("The two words are not anagrams\n");
return EXIT_SUCCESS;
}
code_count[(int) c]--;
if (code_count[(int) c] == 0) {
num_completed_t++;
if (num_completed_t == num_unique_chars) {
printf("The two words are anagrams\n");
return EXIT_SUCCESS;
}
}
}
printf("The two words are anagrams\n");
return EXIT_SUCCESS;
}
Le premier but de ce programme est d’indiquer si un mot est l‘anagramme d’un autre mot
(Un anagramme est un mot qui utilise exactement les mêmes lettres qu’un autre mot mais
dans un ordre différent).
1
TEST1 PROG_I MT & EL 11.11.2016
EPFL / R. Boulic
W=blanc, B=bleu, G=vert, Y=jaune, All = même réponse pour tous
Exemples de mots qui doivent être détectés comme anagramme avec ce programme: le mot
« sujet » est l’anagramme du mot « juste », le mot « aube » est l’anagramme du mot « beau ».
Le second but de ce programme est d’effectuer une vérification très stricte comme suit :
a) il fait la différence entre une lettre majuscule et la même lettre en minuscule
b) il fait la différence entre un caractère du code de base (codes sur 7 bits fourni en cours dont
la valeur décimale est comprise entre 0 et 127) et les caractères accentués supplémentaires
disponibles pour écrire en français ou en allemand (nous supposons que ces caractères sont
codés avec un seul octet dont la valeur de code est comprise entre les valeurs décimales 128 et
255 comme avec le code ISO 8859-1 Latin 1).
Exemples de mots qui ne doivent PAS être détectés comme anagrammes avec ce programme:
« crane » n’est pas l’anagramme de « écran » car le caractère « é » est différent du caractère
« e ». « Marion » n’est pas l’anagramme de « Romain » à cause des lettres « M » et « m », et
des lettres « r » et « R ».
Contexte de l’exercice : cet exercice cherche à établir progressivement si le programme réalise
bien sa tâche pour deux mots isolés (il pourrait être utilisé pour deux « suites de mots » mais
nous n’examinons pas ce cas ici).
Remarque : le symbole EXIT_SUCCESS qui suit l’instruction return n’a pas d’importance pour
cet exercice. Vous devez l’ignorer.
1.1) Choisir une réponse parmi les propositions suivantes :
A) Ce programme ne compile pas
B) Ce programme compile mais l’exécutable peut produire un crash (arrêt prématuré du
programme) quand on fourni un mot contenant un caractère avec un accent (français ou
allemand) dont le code est compris entre 128 et 255 en décimal.
C) Ce programme compile et l’exécutable produit un résultat (= un message est affiché) aussi
quand on fourni un mot contenant un caractère avec un accent (français ou allemand) dont le
code ASCII est compris entre 128 et 255 en décimal. Pour ce choix, on ne fait aucune supposition
sur le fait que le message est correct ou incorrect.
Réponse (justifier en donnant des précisions ici pour le choix A). Pour le choix B) indiquer
pourquoi un caractère accentué peut poser un problème, puis passer à la question 1.2. Pour le
choix ‘C’, indiquer seulement ‘C’ puis passer à la question 1.2): [All]
Nous acceptons les réponses B et C si le cours n’a pas illustré le cas particulier de la conversion
automatique du type char vers le type int dans le cas où le bit de poids fort du char est à 1.
C’est ce qui ce produit pour les codes compris entre 128 et 255 en décimal. Cela en fait un
nombre négatif dans la représentation des entiers. Or, cette valeur négative est utilisée comme
indice du tableau code_count ce qui va modifier la mémoire dans une zone non-réservée pour
ce tableau et va produir eun comportement indéterminé du programme. La suite de l’exercice
n’est pas concernée par ce problème car les caractères ont tous des codes inférieurs à 127.
1
Il est possible que la machine virtuelle utilisée en TP utilise un codage différent de celui indiqué ici
2
TEST1 PROG_I MT & EL 11.11.2016
EPFL / R. Boulic
W=blanc, B=bleu, G=vert, Y=jaune, All = même réponse pour tous
1.2) Nous supposons ici que le programme compile et qu’on peut l’exécuter en obtenant un
résultat affiché (choix C).
1.2.1) Quel message est affiché et à quelle ligne du code source l’exécution atteint-elle
l’instruction « return EXIT SUCCESS » pour ce contenu du buffer d’entrée :
[W]
d u \n d e u x \n
[B]
p i \n p a i x \n
[G]
m i \n m a i s \n
[Y]
s i \n s a i t \n
[All] The two words are not anagrams
Ligne 19
Justifier en précisant le rôle des variables k1 et k2 et leur valeur pour cet exemple
k1 vaut 2 et k2 vaut 4 . le test de la ligne 17 est vrai ; les intructions ainsi exécutée produisent
l’affichage ainsi que la fin de l’exécution.
1.2.2) Quel message est affiché et à quelle ligne du code source l’exécution atteint-elle
l’instruction « return EXIT SUCCESS » pour ce contenu du buffer d’entrée :
[W]
l i s t e n \n s i l e n t \n
[B]
l e m o n \n m e
l o n \n
t r e e s \n r e
s e t \n
p a n e l \n p l
a n e \n
[G]
[Y]
[All] The two words are anagrams
Ligne 39
Pour cet exemple, justifier en précisant a) combien d’éléments du tableau code_count ont été
modifés entre les lignes 12 et 44 du programme, b) combien de fois chaque élément a été
modifié entre les lignes 12 et 44 du programme :
3
TEST1 PROG_I MT & EL 11.11.2016
EPFL / R. Boulic
W=blanc, B=bleu, G=vert, Y=jaune, All = même réponse pour tous
[W] 6 éléments de code_count ont été modifiés car chaque mot contient 6 lettres différentes
Chaque élément a été modifié 2 fois : une incrémentation et une décrémentation
[B]5 éléments de code_count ont été modifiés car chaque mot contient 5 lettres différentes
Chaque élément a été modifié 2 fois : une incrémentation et une décrémentation
[G] 4 éléments de code_count ont été modifiés car chaque mot contient 4 lettres différentes
Chaque élément a été modifié 2 fois (une incrémentation, une décrémentation) sauf l’élément
correspondant à la lettre e qui a été modifié 4 fois car il apparait 2 fois dans chaque mot
[Y] 5 éléments de code_count ont été modifiés car chaque mot contient 5 lettres différentes
Chaque élément a été modifié 2 fois : une incrémentation et une décrémentation
1.2.3) Quel message est affiché et à quelle ligne du code source l’exécution atteint-elle
l’instruction « return EXIT SUCCESS » pour ce contenu du buffer d’entrée :
[W]
A l i n e \n l a i n e \n
[B]
L a y e r \n e a
r l y \n
E a g e r \n a g
r e e \n
I t e m s \n t i
m e s \n
[G]
[Y]
[All] The two words are not anagrams
Ligne 30
Justifier la valeur finale de la variable i (au moment où l’instruction « return EXIT SUCCESS » est
exécutée)
[W] la détection est faite dans la boucle qui parcourt mot2 lorsqu’on traite la lettre ‘a’ d’indice
i=1 car code_count vaut 0 pour cette lettre (contre code_count vaut 1 pour la lettre ‘A’.)
[B] la détection est faite dans la boucle qui parcourt mot2 lorsqu’on traite la lettre ‘l’ d’indice
i=3 car code_count vaut 0 pour cette lettre. ( code_count vaut 1 pour la lettre ‘L’. )
[G] la détection est faite dans la boucle qui parcourt mot2 lorsqu’on traite la seconde lettre ‘e’
d’indice i=4 car code_count vaut 0 pour cette seconde lettre ‘e’ puisqu’il a été décrémenté
d’une unité quand on a traité la première lettre ‘e’ du mot2 (code_count vaut 1 pour la lettre
‘E’).
[Y] la détection est faite dans la boucle qui parcourt mot2 lorsqu’on traite la lettre ‘i’ d’indice
i=1 car code_count vaut 0 pour cette lettre (code_count vaut 1 pour la lettre ‘I’).
4
TEST1 PROG_I MT & EL 11.11.2016
EPFL / R. Boulic
W=blanc, B=bleu, G=vert, Y=jaune, All = même réponse pour tous
2) (6 pts) type float IEEE 754
Donner le motif binaire sur 32 bits de ce nombre octal avec onze chiffres :
[W] 07720000000
0 0 1 1 1 1 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
En déduire la valeur des trois champs de la représentation en virgule flottante avec le type
float IEEE 754 :
Signe
Exposant
Mantisse
: 0 signe positif
: 01111110 c’est-à-dire 126
: 100…00
c’est-à-dire 2-1
Donner ensuite ce nombre sous la forme normalisée et en déduire sa valeur en base dix:
Forme normalisée en binaire = 2(126 – 127) *1,1 = 2– 1 *1,1 = 0,11
Valeur décimale de 0,11 = 0,5 + 0,25 = 0,75
[B]
30020000000
1 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
En déduire la valeur des trois champs de la représentation en virgule flottante avec le type
float IEEE 754 :
Signe
Exposant
Mantisse
: 1 signe négatif
: 10000000 c’est-à-dire 128
: 100….000 c’est-à-dire 2-1
Donner ensuite ce nombre sous la forme normalisée et en déduire sa valeur en base dix:
Forme normalisée en binaire = - 2(128 – 127) *1,1 = - 21 *1,1 = - 11
Valeur décimale de - 11 = -(2 + 1) = -3
[G]
30104000000
1 1 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
En déduire la valeur des trois champs de la représentation en virgule flottante avec le type
float IEEE 754 :
Signe
Exposant
Mantisse
: 1 signe négatif
: 10000010 c’est-à-dire 130
: 00100….0 c’est-à-dire 2-3
Donner ensuite ce nombre sous la forme normalisée et en déduire sa valeur en base dix:
Forme normalisée en binaire = - 2(130 – 127) *1,001 = - 23 *1,001 = - 1001
Valeur décimale de - 1001 = -(8 + 1) = -9
5
TEST1 PROG_I MT & EL 11.11.2016
EPFL / R. Boulic
W=blanc, B=bleu, G=vert, Y=jaune, All = même réponse pour tous
[Y]
07660000000
0 0 1 1 1 1 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
En déduire la valeur des trois champs de la représentation en virgule flottante avec le type
float IEEE 754 :
Signe
Exposant
Mantisse
: 0 signe positif
: 01111101 c’est-à-dire 125
: 100…000 c’est-à-dire 2-1
Donner ensuite ce nombre sous la forme normalisée et en déduire sa valeur en base dix:
Forme normalisée en binaire = 2(125 – 127) *1,1 = 2– 2 *1,1 = 0,011
Valeur décimale de 0,011 = 0,25 + 0,125 = 0,375
3) (6 pts) évaluation d’expression
Donner la valeur et le type de l’expression suivante. Montrer les priorités mises en œuvre par
le langage C en soulignant les sous-expressions et en indiquant leur type et la valeur des
calculs intermédiaires.
[W](char) (
'A' + 1 == 'B' && 'C' / 'D' ? 'X' - 1 : 'T' + 1 )
Type : int
Val : code ascii
de la lettre B
Type : int
Val : 0 (faux)
car le rapport
des deux codes
ASCII est < 1
Pas évalué
Type : int
Val : 1 (vrai) car il y a égalité des codes
B == B DONC on évalue l’opérande droit du &&
Type : int ; Val : 0 (faux) car l’opérande de droite est faux
Type : int ; Val : résultat de l’opérateur ternaire car la condition est VRAIE, on obtient le code ASCII de la lettre U
Type : char; Val : conversion du int obtenu avec l’opérateur ternaire en un char de valeur 'U'
[B]
[G]
[Y]
(char)( 'A' + 1 == 'B' && 'C' / 'D' ? 'X' - 1 : 'P' + 1 )
(char)( 'A' + 1 == 'B' && 'C' / 'D' ? 'X' - 1 : 'R' + 1 )
(char)( 'A' + 1 == 'B' && 'C' / 'D' ? 'X' - 1 : 'S' + 1 )
[All] les priorités sont les mêmes pour les 4 expressions, seule la valeur finale est
différente :
[B] : char de valeur 'Q'
[G] : char de valeur 'S'
[Y] : char de valeur 'T'
6
TEST1 PROG_I MT & EL 11.11.2016
EPFL / R. Boulic
W=blanc, B=bleu, G=vert, Y=jaune, All = même réponse pour tous
4) (6 pts) programme mystère [ All ]
1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int
a = 1;
float x = a << 25 ;
printf("réponse = %d\n", x == x + 2 );
return EXIT_SUCCESS;
}
Justifiez la réponse affichée par ce programme :
Ligne 6 : l’entier 1 possède un seul bit à 1 : celui de poids faible associé à 20.
Ligne 7 : l’expression a << 25 décale le seul bit à 1 de la variable entière sur le poids associé à la
puissance 225. Ensuite cet entier est converti automatiquement en float par l’instruction
d’affectation. La variable x prend donc la valeur 225 qui est exactement représentable en float.
Ligne 9 : la précision du float étant 2-23, la première valeur représentée immédiatement audessus de 225 est : 225 +225-23 = 225 + 22 = 225 + 4
Or la sous-expression x + 2 vaudrait en théorie 225 + 2 et est de type float et cette valeur n’est
pas représentable exactement en float (il n’y a rien entre 225 et 225 + 4). Donc x + 2 est
approchée par troncation à la valeur de x. De ce fait on obtient une expression logique x == x
qui est vraie. C’est pourquoi l’instruction printf affiche 1 (équivalent entier de VRAI).
7