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