Вы находитесь на странице: 1из 7

Licence MIAGe

S720006

Universite de Nantes
2005/2006

Examen
Langage C
: 1h30
Duree

Le bar`eme est donne a` titre indicatif uniquement.


Les copies de transparents du cours, le polycopie de L. Granvilliers et les notes manuscrites

personnelles sont les seuls documents autorises.


Exercice 1 (6 pts.)
Le sudoku est un puzzle utilisant une grille carree composee de 9 regions ; chaque region est elle-meme composee
de 9 cases. On part dune grille partiellement remplie et on doit la completer en respectant les trois r`egles suivantes :
Chaque colonne doit contenir les 9 chiffres de 1 a` 9
Chaque ligne doit contenir les 9 chiffres de 1 a` 9
Chaque region doit contenir les 9 chiffres de 1 a` 9
Rgion

1
4 5 8
7
5
6 3
2
4
4 9
2 1 6
5
3
1
9
5
4 5
3 8
6
2
4 7
1
5
1
8 2 5
3
8 3
5
7

1
5
4
3
9
6
2
7

3
6
7
8
4
2
5
1
8 3 9

0 1 2
3 4 5
6 7 8

2
8
9
7
1
5
4
6

4
3
2
1
5
9
7
8
6

5
9
1
6
7
8
3
2
4

8
7
6
2
3
4
9
5
1

6
2
3
9
8
7
1
4

7
1
5
4
6
3
8
9
5 2

9
4
8
5
2
1
6
3
7

1. Definir un type structure digits t pour representer un tableau de 9 entiers susceptible de contenir une
ligne, une colonne, ou une region ;

2. Ecrire
la fonction contient les 9 chiffres() prenant en entree un digits t et retournant 1 si le
tableau correspondant contient tous les chiffres de 1 a` 9 une seule fois ;

3. Ecrire
les fonctions extraire ligne(), extraire colonne() et extraire region() prenant
en entree une grille de sudoku sous la forme dun tableau dentiers a` 2 dimensions et un entier n compris
entre 0 et 8, et retournant la n-i`eme ligne, la n-i`eme colonne, ou la n-i`eme region ;

4. Ecrire
la fonction sudoku fini() prenant en entree une grille de sudoku et retournant 1 si elle est correctement completee.
Exercice 2 (5 pts.)
1. Indiquez les erreurs se trouvant dans le programme ci-dessous et corrigez-les :
1. #include "stdlib.h"
2.
3. typedef struct {
4.
cellule suiv;
5.
int val;
6. } cellule;
7.

S720006 Universite de Nantes

8.
9.
10.
11.
12.
13.
14.
15.
16.

Examen Langage C

Duree : 1h30

void creer_cellule(cellule *c, int v) {


c=(cellule*)malloc(sizeof(cellule*));
}
int main(void) {
cellule *c;
creer_cellule(c,45);
return 1;
}

1/2

2. Une chane correctement parenthesee contient le meme nombre de parenth`eses ouvrantes et fermantes. De
plus, en tout point de la chane, on ne doit jamais avoir vu plus de parenth`eses fermantes que de parenth`eses
ouvrantes.

Ecrire
la fonction incorrectement parenthesee() prenant une chane de caract`eres en entree et
retournant suivant les cas :
loppose de la position (`a partir de 1) de la premi`ere parenth`ese fermante en trop, sil y a lieu ;
le nombre de parenth`eses ouvrantes en trop (ou 0 si la chane est correctement parenthesee).
Exemples :
Appel
incorrectement
incorrectement
incorrectement
incorrectement

parenthesee("(sdf(gfdgj)dslfkj)")
parenthesee("(sdf(gfdgjdslfkj)")
parenthesee("(sdf(gfdgjdslfkj()")
parenthesee("(sdf(gfd)))gjdslfkj()")

Resultat
0
1
2
-11

Exercice 3 (9 pts.)
On souhaite developper une librairie de manipulation de nombres entiers positifs de grande taille. Pour cela, on
representera un nombre entier par un tableau dentiers dont chaque case correspondra a` un chiffre. Par commodite,
les chiffres dun nombre seront stockes de la droite vers la gauche dans le tableau :

234596578

875695432
0 1 2 3 4 5 6 7 8

1. Definir le type entier representant un entier dont le nombre de chiffres nest connu qu`a lexecution du
programme ;

2. Ecrire
la fonction creer entier() qui prend en entree un pointeur sur un tableau de chiffres tab et une
taille sz, et qui retourne un entier representant lentier contenu dans tab. La fonction devra retourner
lentier codant 0 si tab pointe sur NULL ;

3. Ecrire
la fonction detruire entier() liberant la memoire occupee par un entier ;

4. Ecrire
la fonction chaine en entier() prenant en entree une chane de caract`eres representant un grand
entier positif et retournant lentier correspondant. On ne g`erera pas le cas o`u la chane ne represente pas
un entier positif ;

5. Ecrire
la fonction entier en chaine() prenant en entree un entier et retournant la chane de caract`eres allouee dynamiquement qui lui correspond ;

6. Ecrire
la fonction ajouter entiers() prenant en entree deux entiers e1 et e2 et retournant lentier
correspondant a` leur somme. Les entiers e1 et e2 peuvent e tre de tailles differentes :
428563497 + 356 = 428563853

7. Ecrire
la fonction main() pour un programme prenant en param`etres sur la ligne de commande deux entiers
positifs de taille arbitraire et affichant leur somme a` lecran. Le programme devra sarreter en affichant un
message sur le canal derreur standard si le nombre de param`etres est mauvais.

S720006 Universite de Nantes

Examen Langage C

Duree : 1h30

2/2

Licence MIAGe
S720006

Universite de Nantes
2005/2006

Examen
Langage C
: 1h30
Duree

CORRECTION

Corrige exercice 1 (6 pts.)


#include <stdio.h>
typedef int sudoku_t[9][9];
// On d
eclare une structure pour pouvoir la rendre en r
esultat dune fonction
typedef struct {
int T[9];
} digits_t;
int contient_les_9_chiffres(digits_t l)
{
int occurrences[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
for (int i = 0; i < 9; ++i) {
if (occurrences[l.T[i]-1]++ != 0) { // Chiffre l[i] d
ej`
a vu ?
return 0;
}
}
return 1;
}
digits_t extraire_ligne(sudoku_t sdk, int i)
{
digits_t l;
for (int j = 0; j < 9; ++j) {
l.T[j] = sdk[i][j];
}
return l;
}
digits_t extraire_colonne(sudoku_t sdk, int j)
{
digits_t c;
for (int i = 0; i < 9; ++i) {
c.T[i] = sdk[i][j];
}
return c;
}
digits_t extraire_region(sudoku_t sdk, int n)
{
digits_t r;
int idx = 0;
for (int i = 3*(n/3); i < 3*(n/3) + 3; ++i) {
for (int j = 3*(n%3); j < 3*(n%3)+3; ++j) {
r.T[idx++] = sdk[i][j];
}
}
return r;

S720006 Universite de Nantes

Examen Langage C

Duree : 1h30

1/5

}
int sudoku_fini(sudoku_t sdk)
{
// V
erification sur les lignes
for (int i = 0; i < 9; ++i) {
if (!contient_les_9_chiffres(extraire_ligne(sdk,i))) {
return 0;
}
}
// V
erification sur les colonnes
for (int j = 0; j < 9; ++j) {
if (!contient_les_9_chiffres(extraire_colonne(sdk,j))) {
return 0;
}
}
// V
erification sur les r
egions
for (int n = 0; n < 9; ++n) {
if (!contient_les_9_chiffres(extraire_region(sdk,n))) {
return 0;
}
}
return 1;
}

int main(void)
{
int sdk[9][9] = {
{1, 2, 3, 4, 5,
{5, 8, 6, 3, 9,
{4, 9, 7, 2, 1,
{3, 7, 8, 1, 6,
{9, 1, 4, 5, 7,
{6, 5, 2, 9, 8,
{2, 4, 5, 7, 3,
{7, 6, 1, 8, 2,
{8, 3, 9, 6, 4,
};

8,
7,
6,
2,
3,
4,
9,
5,
1,

6,
2,
3,
9,
8,
7,
1,
4,
5,

7,
1,
5,
4,
6,
3,
8,
9,
2,

9},
4},
8},
5},
2},
1},
6},
3},
7}

printf("=> %d\n", sudoku_fini(sdk));


return 0;
}

Corrige exercice 2 (5 pts.)


1. Erreurs :
Ligne 1. Remplacer les guillemets par des chevrons autour de stdlib.h
Ligne 4. Le type cellule nexiste pas encore. Utiliser un pointeur
Lignes 8 et 1314. Il faut passer un pointeur sur un pointeur de cellule pour changer la valeur
de c avec malloc()
Ligne 9. Il faut utiliser sizeof(cellule)
Ligne 15. Retourner 0
2. Solution :
#include <stdio.h>
int incorrectement_parenthesee(char str[])
{
int openpar = 0;
int idx = 0;
while (str[idx] != \0 && openpar >= 0) {
switch (str[idx]) {
case (:
++openpar;

S720006 Universite de Nantes

Examen Langage C

Duree : 1h30

2/5

break;
case ):
--openpar;
break;
}
++idx;
}
if (openpar < 0) { // Trop de parenth`
eses fermantes
return -idx;
// => on retourne loppos
e de la position entre 1 et n de la
//
1`
ere parenth`
ese en trop
}
// On retourne le nombre de parenth`
eses ouvrantes en trop
return openpar;
}
int main(void)
{
char *str;
str = "(sdf(gfdgj)dslfkj)";
printf("\\code{incorrectement\\_parenthesee(\"%s\")}
str,incorrectement_parenthesee(str));
str = "(sdf(gfdgjdslfkj)";
printf("\\code{incorrectement\\_parenthesee(\"%s\")}
str,incorrectement_parenthesee(str));
str = "(sdf(gfdgjdslfkj()";
printf("\\code{incorrectement\\_parenthesee(\"%s\")}
str,incorrectement_parenthesee(str));
str = "(sdf(gfd)))gjdslfkj()";
printf("\\code{incorrectement\\_parenthesee(\"%s\")}
str,incorrectement_parenthesee(str));
return 0;

& %d\\\\\n",

& %d\\\\\n",

& %d\\\\\n",

& %d\\\\\n",

Corrige exercice 3 (9 pts.)


// Repr
esentation dentiers de taille arbitraire
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char charlookup[] = {0, 1,2,3,4,5,6,7,8,9};
typedef struct {
unsigned int *nb; // Repr
esentation de lentier par un tableau
// Lentier est cod
e avec le chiffre de poids faible
// en premier
unsigned int sz; // Nombre de chiffres de lentier
} entier;

unsigned int min(unsigned int x, unsigned int y)


{
return (x <= y) ? x : y;
}
unsigned int max(unsigned int x, unsigned int y)
{
return (x >= y) ? x : y;
}
entier chaine_en_entier(char ec[])
{
unsigned int sz = strlen(ec);
entier e;
e.nb = (unsigned int*)malloc(sizeof(unsigned int)*sz);
e.sz = sz;
for (unsigned int i = 0; i < sz; ++i) {
e.nb[i] = ec[sz-i-1]-0;

S720006 Universite de Nantes

Examen Langage C

Duree : 1h30

3/5

}
return e;
}
entier creer_entier(unsigned int sz, unsigned int* tab)
{
entier e;
e.nb = (unsigned int*)malloc(sizeof(unsigned int)*sz);
e.sz = sz;
if (tab != (unsigned int*)NULL) {
for (unsigned int i = 0; i < sz; ++i) {
e.nb[i] = tab[i];
}
} else {
for (unsigned int i = 0; i < sz; ++i) {
e.nb[i] = 0;
}
}
return e;
}
void detruire_entier(entier e)
{
free(e.nb);
}
char *entier_en_chaine(entier e)
{
char *ch = (char*)malloc(sizeof(char)*e.sz + 1);
for (unsigned int i = 0; i < e.sz; ++i) {
ch[i] = charlookup[e.nb[e.sz-i-1]];
}
ch[e.sz] = \0;
return ch;
}
void additionneur(unsigned int a, unsigned int b, unsigned int carryin,
unsigned int *c, unsigned int *carryout)
{
unsigned int s = a+b+carryin;
if (s > 9) {
*carryout = 1;
*c = s - 10;
} else {
*carryout = 0;
*c = s;
}
}
entier ajouter_entiers(entier a, entier b)
{
entier c= creer_entier(max(a.sz,b.sz)+1,(unsigned int*)NULL);
unsigned int minsz = min(a.sz,b.sz);
// Sommation des chiffres de la droite vers la gauche
// pour tous les chiffres non nuls
additionneur(a.nb[0],b.nb[0],0,&c.nb[0],&c.nb[1]);
for (unsigned int i = 1; i < minsz; ++i) {
additionneur(a.nb[i],b.nb[i],c.nb[i],&c.nb[i],&c.nb[i+1]);
}
if (a.sz != b.sz) {
// Ajout des chiffres surnum
eraires du nombre le plus grand
if (a.sz == minsz) { // Ajout des chiffres de b
c.nb[minsz] += b.nb[minsz];
for (unsigned int i = minsz+1; i < b.sz; ++i) {
c.nb[i] = b.nb[i];
}
} else { // Ajout des chiffres de a

S720006 Universite de Nantes

Examen Langage C

Duree : 1h30

4/5

c.nb[minsz] += a.nb[minsz];
for (unsigned int i = minsz+1; i < a.sz; ++i) {
c.nb[i] = a.nb[i];
}
}
}
// On regarde si le chiffre suppl
ementaire a
et
e utilis
e
if (c.nb[c.sz-1] == 0) {
--c.sz;
// On ne cherche pas `
a r
eallouer la m
emoire suppl
ementaire
}
return c;
}
int main(int argc, char *argv[])
{
if (argc != 3) {
fprintf(stderr,"Erreur: addition <nb1> <nb2>\n");
return 1;
}
entier e1 = chaine_en_entier(argv[1]);
entier e2 = chaine_en_entier(argv[2]);
char *ch = entier_en_chaine(ajouter_entiers(e1,e2));
printf("%s\n",ch);
free(ch);
detruire_entier(e1);
detruire_entier(e2);
return 0;
}

S720006 Universite de Nantes

Examen Langage C

Duree : 1h30

5/5

Вам также может понравиться