Le niveau des copies est assez faible : la syntaxe s'est nettement amelioree avec le second semestre, mais les reponses proposees restent souvent tres incorrectes, confuses et/ou tres inefficaces. Une ou deux copies s'en tirent un peu mieux que les autres, malgre beaucoup de maladresses. La partie II du sujet, un peu longue a rediger mais conceptuellement assez facile, a globalement ete traitee de maniere tres insuffisante, faute apparemment d'une analyse reelle des conditions posees - peut-etre aurais-je du insister encore plus lourdement sur celles-ci, ou peut-etre aurais-je du interdire les documents pour vous inciter a reflechir d'avantage par vous-memes. VP -------- PARTIE I -------- Il faut au moins un tableau auxiliaire, par exemple un tableau dans lequel on stocke le nombre de valeurs successives non nulles deja lues dans chaque colonne (dh[0]...dh[L-1]), plus une variable indiquant le nombre de valeurs non nulles successives deja lues sur la ligne courante (dh). A chaque fois que l'on rencontre une valeur non nulle, dh et dv[j] sont incrementes, et la densite courante (d) est mise a jour (via les deux if). dh et dv[j] reviennent a 0 dans le cas d'une valeur nulle. int densite(int m[H][L]) { int dv[L] = {}, i, j, d = 0, dh = 0; for (i = 0; i < H; i++) { for (j = 0; j < L; j++) { if (!m[i][j]) { dh = 0; dv[j] = 0; } else { dh++; dv[j]++; if (dh > d) d = dh; if (dv[j] > d) d = dv[j]; } } } return d; } --------- PARTIE II --------- Des exercices elementaires, ne mettant en jeu que les elements de base du langage, et assez similaires. A une ou deux exceptions pres (mais pas meme pour tous les exercices poses), aucune copie ne gere la forme generale de texte mentionnee en debut d'enonce - meme lorsqu'elles fonctionnent plus ou moins, les reponses proposees supposent implicitement que le texte ne commence pas par des separateurs, et que chaque mot est suivi d'un unique separateur - soit le principe du decoupage d'un texte en lignes et non en mots Aucune copie ne mentionne cette restriction - en fait, je ne suis pas sur que beaucoup d'entre vous aient eu conscience de cette difference. Meme sans tenir compte de cette erreur d'analyse, peu de solutions sont convaincantes. On y trouve beaucoup d'erreurs de base : relectures multiples, boucles en strlen(s), tableaux auxiliaires inutiles et transferts laborieux de mots dans ce ou ces tableaux pour un examen local, demultiplication des boucles inutiles, flags inutiles, variables non declarees et/ou confondues, etc. ------------ Exercice 2.1 ------------ Il faut d'une maniere ou d'une autre mesurer la longueur de chaque mot. (1) on avance jusqu'au debut du mot suivant (2) on memorise la position du debut de ce mot (3) on avance jusqu'a la fin du mot (4) on compare la longueur du mot lu avec la longueur courante. (5) on incremente la longueur courante, on revient a (1). int boule_de_neige(char *s) { int lg = 1, i = 0, j; while(1) { while (!lettre(s[i]) && s[i] != '\0') //(1) i++; if (s[i] == '\0') return 1; j = i; //(2) while (lettre(s[i])) //(3) i++; if ((i - j) != lg) //(4) return 0; lg++; //(5) } } ------------ Exercice 2.2 ------------ Il faut d'une maniere ou d'une autre verifier que chaque mot forme un palindrome local. (1) on avance jusqu'au debut du mot suivant (2) on memorise la position du debut de ce mot (3) on avance jusqu'a la fin du mot (4) on verifie que le mot est un palindrome local, on revient a (1). int loc_pal(char *s) { int i = 0, j, k; while(1) { while (!lettre(s[i]) && s[i] != '\0') //(1) i++; if (s[i] == '\0') return 1; j = i; //(2) while (lettre(s[i])) //(3) i++; k = 0; //(4) while (j + k < i - 1 - k) { if (s[j + k] != s[i - 1 - k]) return 0; k++; } } } ------------ Exercice 2.3 ------------ Il faut determiner la taille d'allocation, allouer, reprendre le meme code et effectuer le transfert. (1) on avance jusqu'au debut du mot suivant (2) on memorise la position du debut de ce mot (3) on avance jusqu'a la fin du mot (4) on verifie que le mot est de longueur au moins n, et si oui, on incremente le compteur du nombre de mots (nbm), et le compteur de lettres (lgl). La taille d'allocation totale est le nombre de lettres lues, en comptant en plus un espace apres chaque mot sauf le dernier (nbm - 1), plus 1 pour le marqueur de fin dans la chaine resultat (lgm + nbm - 1 + 1 == lgl + nbm). (5) on se replace en debut de chaine, on reprend la structure du code precedent. (6) on avance jusqu'au debut du mot suivant (7) on memorise la position du debut de ce mot (8) on avance jusqu'a la fin du mot (9) on verifie que le mot est de longueur au moins n, et si oui, - (10) si le mot lu n'est pas le premier, on ecrit d'abord un unique espace, - (11) on recopie le mot, on revient a (6) (12) on place le marqueur de fin, on renvoie le resultat. char *mots_longs(char *s, int n) { int lgl = 0, nbm = 0, i = 0, j, iw = 0; char *res; while(1) { while (!lettre(s[i]) && s[i] != '\0') //(1) i++; if (s[i] == '\0') break; j = i; //(2) while (lettre(s[i])) //(3) i++; if ((i - j) >= n) { //(4) lgl += i - j; nbm ++; } } res = malloc((nbm + lgm) * sizeof(char)); i = 0; //(5) while(1) { while (!lettre(s[i]) && s[i] != '\0') //(6) i++; if (s[i] == '\0') break; j = i; //(7) while (lettre(s[i])) //(8) i++; if ((i - j) >= n) { //(9) if (iw) { //(10) res[iw] = ' '; iw++; } while (lettre(s[j])) { //(11) res[iw] = s[j]; j++; iw++; } } } res[iw] = '\0'; //(12) return res; } ------------ Exercice 2.4 ------------ Il faut examiner en parallele les mots de s et t, et n'avancer d'un mot dans t que lorsque les mots courants de s et t coincident. (1) on avance jusqu'au mot suivant dans s (2) on avance jusqu'au mot suivant dans t (3) on compare les mots courants dans s et t (4) s'ils sont egaux, on se deplace apres ces deux mots dans s et dans t, sinon, (5) on se deplace apres le mot courant dans s. int sous_texte(char *s, char *t) { int is = 0, it = 0, k; while(1) { while (!lettre(t[it]) && t[it] != '\0') //(1) it++; if (t[it] == '\0') return 1; while (!lettre(s[is]) && s[is] != '\0') //(2) is++; if (s[is] == '\0') return 0; k = 0; while (lettre(s[is + k]) && // (3) lettre(t[it + k]) && s[is + k] == t[it + k]) k++; if (!lettre(s[is + k]) && !lettre(t[it + k])){//(4) is = is + k; it = it + k; } else { //(5) while(lettre(s[is])) is++; } } } ---------- PARTIE III ---------- Deux exercices tres elementaires - et peu reussis. struct cell *filtrer(struct cell *pc, int n) { struct cell *pcs; if (pc == NULL) return NULL; if (pc -> clef < n) { pcs = pcs -> suiv; free(pc); return filtrer(pcs, n); } pc -> suiv = filtrer(pc -> suiv, n); return pc; } struct cell *echanger_paires(struct cell *pc) { struct cell *pcs; if (pc == NULL) return NULL; if (pc -> suiv == NULL) return pc; pcs = pc -> suiv; pc -> suiv = echanger_paires(pc -> suiv -> suiv); pcs -> suiv = pc; return tmp; }