Vous êtes sur la page 1sur 344

Algorithmique et Programmation C

Cours et exercices corrigés

Dr Maher HENI
Mme Sonia GUERBOUJ

• Formation d'ingénieur
• Licence
• Formation continue
• BTS
Mheni & SGarbouje

Liste des ouvrages:

Dr: Maher HENI:

Routage orienté optimisation énergétique dans les réseaux sans


fil: Routage et efficacité énergétique dans les MANETs et les
WSN, Editions universitaires europeennes (Aôut -2013)
Mheni & SGarbouje

Algorithmique et
Programmation C
Cours et exercices corrigés

Dr Maher HENI
Mme Sonia GUERBOUJ

© Tous droits de reproduction, de traduction et d'adaptation


réservés pour tous pays
©Centre de Publication Universitaire, Manouba, 2015
B.P:223 La Manouba 2010-Tunisie
Tél:(+216)71600025 Fax:(+216)71601266
Mheni & SGarbouje

« Dans la vie rien à craindre, tout est à comprendre » Marie Curie

*******

« L'imagination, c'est l'art de donner vie à ce qui n'existe pas,


de persuader les autres d'accepter un monde qui n'est pas vraiment là » Paul
Auster

*******

« I arise in the morning torn between a desire to improve the world and a desire to
enjoy the world.
This makes it hard to plan the day » Elwyn Brooks White

*******

«The world can develop only with the human imagination,


so you must try to imagine an idea that can change the world
or we'll just live and die and will be forgotten » Maher HENI
Mheni & SGarbouje

Avant propos
Cet ouvrage présente les algorithmes et structures de
données de base qu'on rencontre souvant en programmation.
Ces algorithmes sont implémentés par la suite en langage C.
En effet, de ce langage, nombreux langages en dérivant et
aussi il est à la base de tous les systèmes d'exploitation
populaires. L'algorithmique et la programmation C est très
enseigné dans les écoles et institutions d'eseignement
superieure. Ce livre s'adresse aux étudiants en licence
fondamentale et appliquée en informatique, aux élèves
ingénieurs, et à tous ceux qui souhaitent acquérir des bases
solides en algorithmique et programmation C.
L'ouvrage est structuré en douze chapitres, chaque
chapitre est structuré en trois parties :
• Syntaxe algorithmique: Il s'agit de fournir une
solution à un problème, la première étape consiste à analyser
ce problème, c'est-à-dire en cerner les limites puis le mettre
en forme dans un langage descriptif.
• Le langage de programmation C
Un langage de programmation est l'intermédiaire entre
l'utilisateur humain et l'ordinateur. Il permet d'écrire dans un
langage proche de la machine mais intelligible par l'humain
les opérations que l'ordinateur doit effectuer. Ainsi, étant
donné qu'il est destiné à l'ordinateur, le langage de
programmation doit respecter une syntaxe stricte. Un
algorithme peut toutefois aboutir à plusieurs programmes.
Dans notre ouvrage nous présentons la traduction des
algorithmes en langage C.
• Exercices corrigés:
Nous avons choisit des exercices et problèmes contigus
aux notions de cours présentés, formalisés comme
complément à la compréhension des notions.
Nous avons aussi présenté quelques problèmes de
concours nationaux et des examens semestriels avec des
corrigés détaillés.
Mheni & SGarbouje
Mheni & SGarbouje

Introduction à l’algorithmique
I. Notion de programmation
Programmation
Un programme est une liste d’instructions bien
structurées qu’on exécute afin de répondre à un problème.
L’exécution de ces instructions peut être faite par l’homme
ou par l’ordinateur. Dans ce dernier cas, on parle de
programmation informatique.
Algorithme :
Dérivé du nom du mathématicien arabe « Al-
Khawarizmi », il s’agit d’une séquence d’opérations pour
résoudre un type de problème spécifique. Selon la définition
précédente de programmation, on remarque qu’il existe une
grande similitude entre les termes « programme » et «
algorithme ». Les deux désignent une méthode pour résoudre
un problème donné. On emploie le terme « algorithme »
lorsque la séquence d’instructions est écrite en langage
algorithmique et fait abstraction d’un ensemble de détails. On
emploie le terme « programme » lorsque la séquence
d’instructions est écrite dans un langage compréhensible par
la machine (tel que le langage C).

II. Démarche de programmation


Pour élaborer un programme, il faut suivre les 5 étapes
suivantes:
Étape-1: SPECIFICATIONS DU PROBLEME

p. 7
Mheni & SGarbouje

Dans cette étape, on doit spécifier les objectifs attendus


du programme. On doit par la suite dissocier le problème en
deux parties, données du problème et résultat attendu.
Etape-2: ANALYSE et CONCEPTION
Lors de cette étape, on analyse le problème et on
élabore la méthode de sa résolution. Cette méthode est
exprimée en un langage humain simple appelée algorithme.
Etape-3: CODAGE
L’algorithme obtenu à l’issu de l’étape précédente est
traduit en un langage de programmation bien spécifique.
Etape-4: TEST et CORRECTION (Debugging)
Tout programme doit passer par cette étape qui consiste
à tester le code et chercher les erreurs afin de les corriger.
Cette étape peut être l’étape la plus longue.
Etape-5: EXPLOITATION et MAINTENANCE
Le programme est maintenant prêt à être utilisé. Et au
fur et à mesure de son exploitation, on continue à le maintenir
c'est-à-dire à corriger les erreurs qui n’ont pas été détectées
auparavant et l’améliorer.

i.e: Le mot compilation se traduit en algorithmique et en


programmation par la traduction d'un programme en langage
compréhensible par la machine dans un premier temps, puis
l'éxécuter dans un deuxième temps. L'entité responsable de
cette fonction s'appelle compilateur.

p. 8
Mheni & SGarbouje

III. Les variables :


Définition
Tous les langages de programmation sont basés sur la
manipulation de variables. En programmation, une variable
sert à stocker une valeur qui correspond à une donnée ou un
résultat. Elle est identifiée par un nom et une adresse, c'est-à-
dire une zone mémoire dans laquelle on enregistre sa valeur.
Le nom de la variable peut être formé d’un ou de
plusieurs caractères (lettres et chiffres), à condition de ne pas
commencer par un chiffre pour éviter toute confusion entre la
nomination et l’opération de multiplication. En plus, les
caractères spéciaux ne sont pas pris en compte sauf le tirait
bas "_".

Déclaration

Syntaxe Exemple
En nom_variable : x, age_etudiant :
algorithmique type_variable entier

type_variable int x,
En langage C
nom_variable ; age_etudiant ;

p. 9
Mheni & SGarbouje

Les constantes

Les constantes sont des valeurs de certaines grandeurs


qui ne changent jamais durant l’exécution du programme.
Elles doivent être déclarées au début du programme avant les
variables. Par convention, les noms des constantes sont écrits
en majuscule pour les différencier des variables dans le code.

Syntaxe Exemple

En nom_const = valeur_const PI = 3.14


algorithmique G = 10

const type_const const float PI


nom_const = = 3.14 ;
En langage C
valeur_const ; const int G =
10 ;

IV. Les types simples


Un type spécifie la liste des valeurs que peut prendre
une variable. Il spécifie aussi les opérations qu’on peut
effectuer sur cette valeur. En algorithmique,
algorithmique on définit 5
types de données simples :
- Type entier : les valeurs de l’ensemble « »

- Type réel : les valeurs de l’ensemble ℝ (l’ensemble


(l’ensemble des entiers relatifs) en mathématique

des réels) en mathématique

p. 10
Mheni & SGarbouje

- Type caractère : cet ensemble est formé par les


chiffres de 0 à 9, les lettres alphabétiques et les caractères
spéciaux (£, $, +, &, @...)
- Les chaines de caractères : les séquences de
caractères
- Le type logique ou booléen : les valeurs vrai et faux.
Nous verrons dans un autre chapitre comment créer un type
personnalisé.
1. Le type entier
L’ensemble des valeurs que peut prendre un entier varie
selon le langage de programmation utilisé.
Les opérations qu’on peut effectuer sur un entier sont :
+ : Addition
- : Soustraction
* : Multiplication
div : Division entière
mod : Modulo, le reste de la division
Et aussi les opérations de comparaison:
≠ : Différence
= : Egalité
< : Inférieur
≤ : Inférieur ou égal
> : Supérieur
≥ : Supérieur ou égal

2. Le type réel
Pour représenter des nombres flottants, on utilise le
type réel. En plus des opérations de comparaison, les
opérations qu’on peut effectuer sur un réel sont :

p. 11
Mheni & SGarbouje

+ : Addition
- : Soustraction
* : Multiplication
/ : Division
^:Puissance
3. Le type caractère
Un caractère peut être un chiffre ou une lettre
aphabétique ou un caractère spécial. Le caractère espace est
aussi pris en considération. Les opérations qu’on peut
effectuer sur les caractères sont principalement des opérations
de comparaison utilisant le code ASCII (American Standard
Code for Information Interchange) de chaque caractère. Ce
codage permet d’affecter un code entier à chaque caractère.
Les principales opérations qu’on peut effectuer sur les
caractères sont :
≠ : Différence
= : Egalité
< : Inférieur
≤ : Inférieur ou égal
> : Supérieur
≥ : Supérieur ou égal
Le résultat de comparaison entre deux caractères est de
type booléen.
4. Le type booléen
Une variable de type booléen peut prendre la valeur
« vrai » ou « faux ». Ce type peut être utilisé dans
l’évaluation d’une condition. Les opérations qu’on peut
effectuer sur les booléen sont :

p. 12
Mheni & SGarbouje

NON : Négation
OU : Ou logique
ET : Et logique
5. Les types en langage C
La notion de type sert à déterminer le nombre d'octets
nécessaire en mémoire pour stocker une variable.
Les types de base du langage C se répartissent en trois
grandes catégories : les nombres entiers (int), les nombres
flottants (float ou double), et les caractères (char). Ce tableau
résume l’ensemble des types qui existent en langage C.

Taille
Type Signification (en Plage de valeurs
octets)
char Caractère 1 -128 à 127
unsigned Caractère non
1 0 à 255
char signé
short int Entier court 2 -32 768 à 32 767
unsigned Entier court non
2 0 à 65 535
short int signé
-32 768 à 32 767
2
int Entier -2 147 483 648 à 2
4
147 483 647
unsigned Entier non 2 0 à 65 535
int signé 4 0 à 4 294 967 295
long int Entier long 4 -2 147 483 648 à 2

p. 13
Mheni & SGarbouje

147 483 647


unsigned Entier long non
4 0 à 4 294 967 295
long int signé
3.4*10-38 à
float Flottant (réel) 4
3.4*1038
1.7*10-308 à
double Flottant double 8
1.7*10308
long Flottant double 3.4*10-4932 à
10
double long 3.4*104932

V. Les expressions :
Les expressions sont des opérations entre les variables
et les constantes qui permettent de manipuler leurs valeurs.
Elles expriment des calculs arithmétiques ou des relations
logiques.
1. Expression arithmétiques :

Priorité Opérateurs
1 Parenthèses : ( )
2 Puissance : ^
3 Multiplication et division : *, /, Div, Mod
4 Addition et soustraction : + et -
Les opérateurs de calculs sont organisés selon un ordre
de priorité afin d’éviter toute ambiguïté lors de l’évaluation
de toute expression. En plus de respecter l’ordre de priorité,
on doit aussi commencer de gauche à droite.

p. 14
Mheni & SGarbouje

2. Expressions logiques :

Ce sont les expressions de comparaison (=, ≠, <, ≤, >,


≥,) pour les types réels, entiers et caractères mais aussi les
opérations logiques (ET, OU, NON) pour les booléens.
Priorité Opérateur
1 Supérieur : >
2 Supérieur ou égale : ≥
3 Inférieur : <
4 Inférieur ou égale : ≤
5 Egale : =
6 Différent : ≠
7 Négation : NON
8 Et logique: ET
9 Ou logique: OU
3. Expressions en langage C :

Les expressions en langage C diffèrent de


l’algorithmique uniquement dans la représentation
symbolique des opérateurs qui les composent. Voici un
tableau récapitulatif des opérateurs les plus utilisés en
langage C.
Priorité Classe Sens de
Opérateur
d’opérateur priorité
De gauche à
1 Parenthésage ()
droite
De gauche à
2 Multiplicatifs *, / ,%
droite

p. 15
Mheni & SGarbouje

De droite à
3 Additifs +, -
gauche
De gauche à
4 Comparaison < , <= , >, >=
droite
Egalité et De gauche à
5 ==, !=
différence droite
De gauche à
6 Négation !
droite
De gauche à
7 ET logique &&
droite
De gauche à
8 OU logique ||
droite
De gauche à
9 Condition ?:
droite
=, += , -=, *= , /=
, %=, De droite à
10 Affectation
&=, |=, ^= gauche
(^ : ou-exclusif)

VI. Les Instructions Simples


1. Instruction d’affectation

Cette instruction permet d’affecter à une variable une


valeur, une expression, un résultat d'une fonction ou aussi
une autre variable ayant une valeur dans la mémoire, elle
s'écrit de cette manière :

p. 16
Mheni & SGarbouje

En algorithmique : En langage C :
Variable ← Valeur Variable = Valeur ;
Exemple : Exemple :
a ←3 a=3;
b ←6+a => b contiendra 9 b=a+6;

La variable à droite doit avoir une valeur et doit être de


même type que la variable à gauche. Si on affecte une valeur
à une variable dans le programme, l’ancienne sera écrasée
(perdue) et on enregistre en mémoire cette nouvelle valeur.
Remarque
Le langage C, étant très riche, introduit des opérateurs
d’affectation qui ne sont pas utilisés en algorithmique. Ces
opérateurs permettent à la fois de faire une opération
arithmétique suivie d’une affectation ce qui a pour but de
minimiser l’écriture.
Opérateur Signification Exemple
int i=1 ;
++ Incrémentation i++ ; i = i+1 ;
=> i vaut 2
int j=5 ;
-- Décrémentation
j-- ; j = j-1 ;

p. 17
Mheni & SGarbouje

=> j vaut 4
float x=7, PI=3.14 ;
Addition et initialisation
+=
affectation x+=PI ; x = x+PI ;
=> x vaut 10.14

Soustraction et x -= PI ;
-=
affectation => x vaut 4.14

Multiplication et x *= PI ;
*=
affectation => x vaut 21.98

Division et x /= PI ;
/=
affectation => x vaut 2.229…

int j=5, i=2;


Modulo et initialisation
%=
affectation j %= i ;
=> j vaut 1
2. Instruction d’écriture

L’écriture en programmation correspond à l’affichage


d’un message sur l’écran. Ce message peut être un texte à
l’utilisateur ou un résultat. Une seule instruction d'écriture
peut rassembler plusieurs messages séparés par des virgules
en utilisant la syntaxe :
Ecrire (exp1, exp2, exp3…)

p. 18
Mheni & SGarbouje

Pour afficher un message de type chaine de caractère


tel qu’il est sans modification, il doit être placé entre deux
guillemets, sans guillemets, la chaine sera interprétée comme
un nom de variable dont on affiche la valeur.
Exemple

Instruction Résultat
x ←4 Affecter 4 à la variable x
chaine← "Bonjour" Affecter bonjour à la variable
chaine
Ecrire ("bonjour tout le Afficher : bonjour tout le
monde") monde
Ecrire (chaine, "tout le Afficher : Bonjourtout le
monde") monde
Ecrire ("chaine ", chaine) Afficher : chaine Bonjour
Ecrire(x) Afficher : 4
Ecrire (chaine, " x=", x) Afficher : bonjour x =4
Ecrire("le résultat =",x+5) Afficher: le résultat=9
En langage C

L’affichage, en langage C, se fait généralement avec la


fonction « printf » définie dans la bibliothèque d'E/S
"stdio.h".
Exemple :
printf ("Entrez un réel positif") ;

p. 19
Mheni & SGarbouje

Cependant, pour afficher une variable, c’est un peu plus


complexe qu’en algorithmique, car la machine a besoin de
connaître le format d'affichage pour cette variable. Par
exemple, on a la possibilité d’afficher un caractère sous le
format caractère ou entier (c'est-à-dire son code ASCII), et on
peut afficher un entier sous format décimal, hexadécimal, ou
octal.
Pour cela, le langage C possède des indicateurs de
format prédéfinis qui doivent être spécifiés entre guillemets
dans la fonction printf selon la syntaxe suivante :
printf ("format_variable", nom_variable) ;
Exemple :
printf ("Résultat= %f", moyenne);
printf ("Vous avez %i ans", age) ;
L’ensemble des indicateurs de format pour la fonction
prinft sont résumés dans ce tableau.

Formatage Description
%i ou %d Entier (ou décimal)
%u Cardinal
%f Réel
%e Réel avec exposant
%c Caractère
%s Chaîne de caractères
%o Octal

p. 20
Mheni & SGarbouje

%x Hexadécimal
%ld Long décimal, l'indication "l" est
aussi valable pour les autres
types
%5.2f 5 chiffres, 2 chiffres après la
virgule

Il faut néanmoins savoir qu’il existe d’autres fonctions


moins élaborées pour l’affichage en langage C telles que:
putc et putchar pour afficher un caractère et puts pour
afficher une chaine de caractères. Toutes ces fonctions ne
nécessitent aucun indicateur de format.
Exemples : puts(nom_etudiant) ; putc(sexe) ;
3. Instruction de lecture

L'instruction de lecture (Lire) permet de lire une valeur


donnée par l'utilisateur. On peut lire une ou plusieurs valeurs
et les mettre dans des variables à la fois:
Lire (Var) ou Lire (Var1, Var2, Var3…)
Généralement l'instruction de lecture est précédée par
un message exprimant la nature des données demandées (une
ou plusieurs valeurs et leurs types).
Exemple :
Ecrire ("Donner la valeur de x et y :")
Lire (x,y)

p. 21
Mheni & SGarbouje

En langage C
La lecture, en langage C, se fait généralement avec la
fonction « scanf ». Cette fonction nécessite, comme la
fonction printf, qu’on lui spécifie entre guillemets le format
de la variable à lire, d’où la syntaxe suivante :
scanf ("format_variable", &nom_variable") ;

Exemple :
printf("Donner la valeur de x et y :") ;
scanf ("%i",&x) ;
scanf ("%f",&y) ;

Remarques

- L'ordre d'exécution en algorithmique est


séquentiel instruction par instruction, ce-ci sera traduit en
langage "C" par un "point-vérgule ;"
- Il est possible de faire la lecture de plusieurs
variables dans la même ligne, mais cela peut engendrer
des erreurs lors de l’exécution, surtout si l’utilisateur se
trompe. Une bonne habitude de programmation est de
s’habituer à lire chaque variable à part.
- Les indicateurs de format pour scanf sont les
mêmes que pour la fonction printf et indiqués dans le
tableau précédent.
- Il existe une différence entre les deux
fonctions : printf pour l’affichage et scanf. La lecture d'une
valeur permet de la stocker mémoire, d’où le symbole

p. 22
Mheni & SGarbouje

« & » qui précède le nom de la variable dans la syntaxe de


scanf qui signifie l'adresse mémoire réservée pour la
variable désignée. Si l’on oublie de mettre le symbole &,
la variable à lire ne sera pas modifiée par la valeur entrée,
et donc cette valeur sera perdue.
- Attention ! Le symbole « & » se met devant
tous les types de variables (entier, caractère, réel) sauf les
chaînes de caractères.
- Tout au long de ce livre, nous allons mettre le
point sur d'autres fonctions standards en algorithmique et
en langage C. Pour ce dernier, afin d'utiliser une fonction
prédifinie il faut appeler la bibliothèque contenant cette
fonction.

VII. Structure générale d'un algorithme /


programme
1. Structure d’un algorithme

La structure générale d'un algorithme est comme suit :


on commence par donner un nom à l'algorithme (bien sûr il
doit être significatif) suivi par l’ensemble des déclarations :
les constantes, les types puis les variables. Les nouveaux
types de données autre que les types de bases (entier, réel,
caractère, etc..), doivent être définis avant la déclaration des
variables (pour être utilisés). Après les déclarations, on
trouve l’ensemble des instructions placé entrée les mots clés
Début et Fin comme présenté dans la figure suivante. Nous

p. 23
Mheni & SGarbouje

verrons plus tard la déclaration des fonctions et procédures et


comment les placer dans un algorithme.

Algorithme nom_algorithme
Constantes

Types

Variables
….
Début
Instr 1
Instr 2

Fin

Exemple :
Algorithme PremierAlgo
Variables
ch : chaine de caractère

p. 24
Mheni & SGarbouje

Début
ch = "intéressant"
Ecrire ("Bonjour tout le monde, ce cours est ", ch)
Fin

2. Structure d’un programme

Tout programme en langage C commence par


l’inclusion des bibliothèques standards. Ces bibliothèques
contiennent les fonctions prédéfinies dans le langage et qui
seront utilisées dans le programme, telles que printf, scanf,
etc. On doit donc spécifier le fichier d’entête appelé header
où elles sont définies. Ensuite, le reste du programme est une
séquence de déclarations (types, constantes, variables) puis
d’instructions délimitées entre deux accolades et précédées
par le mot clé main qui signifie qu’il s’agit du programme
principal. Ainsi, en langage C un programme possède la
structure suivante :

p. 25
Mheni & SGarbouje

/* inclusion des bibliothèques */

main ( )
{

/* déclarations */

/* instructions */

On remarque donc que le nom du programme n’est pas


mis à l’intérieur du code comme en algorithmique. En fait,
tout le code est enregistré dans un fichier appelé
nom_programme.c. Ce fichier sera compilé pour générer un
fichier objet nom_programme.o. Enfin, à partir de ce dernier
fichier et des bibliothèques référencées, l’étape d’édition des
liens aboutit à la génération du fichier exécutable.
Exemple :
#include <stdio.h> /* bibliothèque pour les
fonctions standards d'entré/sortie contenant
printf */
main()
{
printf("\n Bonjour tout le monde !");

p. 26
Mheni & SGarbouje

/* le caractère \n n’apparaît pas à l’écran il permet


de faire un saut de ligne */
}
Remarque :
Tout texte écrit entre /* et */ est un commentaire, il
n’est pas pris en compte lors de l’exécution. On peut écrire
un commentaire sur une ligne seulement lorsqu'on le précède
par "//". Exemple : //un commentaire

VIII. Exercices d'application:


Exercice 1:
Ecrire un algorithme qui permet de lire les valeurs de
deux variables entiers puis affiche leur somme et leur produit.
Traduire cet algorithme en programme C.
Exercice 2:
Ecrire un algorithme qui lit le rayon d'un cercle puis
affiche son périmètre et sa surface.
Traduire cet algorithme en programme C.
Exercice 3:
Ecrire un algorithme qui lit la longueur et la largeur
d'un rectangle puis affiche le périmètre et la surface.
Traduire cet algorithme en programme C.

p. 27
Mheni & SGarbouje

Exercice 4:
Ecrire un algorithme qui lit les valeurs de a et b puis
affiche a à puissance b (ab).
Traduire cet algorithme en programme C.
N.B: vous pouvez utiliser la fonction standard pow de la
bibliothèque <math.h>

IX. Correction des exercices


Exercice 1:

Algorithme somme_produit
Variables
a, b: entier
Début
Ecrire ("donner un entier a:")
lire(a)
Ecrire ("donner un entier b:")
lire(b)
Ecrire ("la somme =",a+b, "et le produit =",a*b)
Fin

Programme somme_produit.c

#include <stdio.h>
main(){
int a, b;
printf ("donner un entier a:");
scanf("%d",&a);
printf ("donner un entier b:");
scanf("%d",&b);
printf ("la somme =%d et le produit =%d", a+b, a*b);}

p. 28
Mheni & SGarbouje

Exercice 2:

Algorithme cercle
Constantes
PI=3,14
Variables
p, s, r : réel
Début
Ecrire ("donner le rayon du cercle: ")
Lire(r)
p ← 2*PI*r
s← PI*r*r
Ecrire ("le périmètre est =", p , " et la surface =",s)
Fin

Programme cercle.c
#include <stdio.h>
main(){
float p, s, r;
const float PI=3.14;
printf ("donner le rayon du cercle :");
scanf("%f",&r);
p = 2*PI*r ;
s = PI*r*r ;
printf ("le périmètre est =%f et la surface =%f \n", p , s);
}

Exercice 3:

Algorithme rectangle
Variables
lo, la: entier
Début

p. 29
Mheni & SGarbouje

Ecrire ("donner la longueur du rectangle:") lire(lo)


Ecrire ("donner la largeur du rectangle") lire(la)
Ecrire ("le périmètre =",2*(lo+la), "et la surface =",lo*la)
Fin
Programme rectangle.c
#include <stdio.h>
main(){
int lo, la;

printf ("donner la longueur du rectangle:");


scanf("%d",&lo);
printf ("donner la largeur du rectangle:");
scanf("%d",&la);
printf ("le périmètre = %d et la surface =%d",2*(lo+la),
lo*la);
}
Exercice 4:

Algorithme Puissance
Variables
a, b: entier
Début
Ecrire ("donner un entier a:")
lire(a)
Ecrire ("donner un entier b:")
lire(b)
Ecrire ("a puissance b =", a^b)
Fin
Programme puissance.c
#include <stdio.h>
#include <math.h>
main(){
int a, b;

p. 30
Mheni & SGarbouje

printf ("donner un entier a:");


scanf("%d",&a);
printf ("donner un entier b:");
scanf("%d",&b);
printf ("%d puissance %d = %f \n", a, b, pow (a, b));
}

p. 31
Mheni & SGarbouje

Les structures conditionnelles


I. Introduction
En programmation, on est souvent amené à exécuter
des instructions selon un choix précis d’où le besoin d’utiliser
des blocs conditionnels. Par exemple, lorsque le nombre saisi
est positif on effectue un traitement, dans le cas contraire, on
doit faire un traitement différent. Ceci est la notion de
traitement conditionnel. On peut distinguer deux formes
générales :

• Structure conditionnelle simple : Si une condition est


valide, le programme exécute un bloc d’instructions.
Exemple : Si l'utilisateur clique sur un bouton fermer,
la fenêtre se ferme et l'exécution s'arrête. On n'a pas
d'autre condition.
• Structure conditionnelle multiple : avec laquelle on
peut choisir entre deux ou plusieurs traitements.

II. Structure conditionnelle simple


En algorithmique En langage C
Si < Condition> Alors if ( Condition )
<Liste d'instructions> {
Syntaxe <Liste d'instructions>
FinSi }

p. 32
Mheni & SGarbouje

Si (x>0) alors if (age>=20)


Ecrire (x, "est positif") printf ("Vous avez
Exemple le droit
FinSi de
voter") ;
Remarque :

- Dans la partie <Liste d'instructions, si on a une


seule instruction on peut ne pas mettre les accolades
{} et ce pour les différentes structures en C.

- En langage C, les parenthèses sont obligatoires


pour délimiter la condition et les accolades peuvent
être omises quand on a une seule instruction.

Exercice :

Ecrire l'algorithme et le programme en C qui permet


de résoudre dans R l'équation ax+b=0, tels que a et b sont
deux réels saisis au clavier.

Solution:
/** En algorithmique*/
Algorithme Equation
Variables
a, b : réel
Début
Ecrire ("donner la valeur de a:")
Lire (a)
Ecrire ("donner la valeur de b:")

p. 33
Mheni & SGarbouje

Lire (b)
Si (a≠0) alors
Ecrire (" la solution est ", (-b/a))
FinSi
Fin
/** En langage C*/

Programme equation.c
#include <stdio.h>
void main(){
float a, b ;
printf ("Donner la valeur de a :") ;
scanf ("%f", &a) ;
printf ("Donner la valeur de b :") ;
scanf ("%f", &b) ;
if (a !=0)
printf ("La solution est : %f", (-b/a)) ;}

III. Structure conditionnelle multiple


1. Forme alternative
Avec la forme alternative, la première liste
d'instructions est exécutée dans le cas où la condition est
vraie, dans le cas contraire, on passe à la deuxième liste
d'instructions.

En algorithmique En langage C
Si < Condition> Alors if (Condition)
Syntaxe <Liste 1 d'instructions> {
<Liste 1 d'instructions>
Sinon }

p. 34
Mheni & SGarbouje

<Liste 2 d'instructions> else


{
FinSi <Liste 2 d'instructions>
}

Si (année mod 4=0) alors if (annee%4==0)


Ecrire ("Année printf ("Année
bissextile") bissextile ") ;
Exemple Sinon else
Ecrire ("Année à 365 jours printf ("Année à 365
") jours ") ;
FinSi
Exercice:

Ecrire un programme qui lit un entier puis affiche sa


valeur absolue.

Solution :

/**En algorithmique */
Algorithme ValeurAbsolue
Variables
x : entier
Début
Ecrire ("Entrer un entier:")
Lire (x)
Si (x>0) alors
Ecrire (" la valeur absolue = ", x)
SiNon
Ecrire ("la valeur absolue = ", -x ")

p. 35
Mheni & SGarbouje

FinSi
Fin

/**En langage c */
Programme Val_Absolue.c
#include <stdio.h>
void main(){
int x ;
printf ("Entrer un entier :") ;
scanf ("%i", &x) ;
if (x>=0)
printf ("La valeur absolue = %i", x) ;
else
printf ("La valeur absolue = %i", -x) ;
}

2. Forme imbriquée :
Cette forme est utilisée lorsqu’on a plus qu’une
condition (deux ou plusieurs). Dans ce cas, on a recourt à des
blocs de si… sinon imbriqués l’un à l’intérieur de l’autre
comme les poupées russes.

En algorithmique En langage C
Si <Condition1> Alors if (Condition1)
<Liste 1 {
d'instructions> <Liste 1 d'instructions>
Sinon Si <Condition2> }
Syntaxe else if (Condition2)
Alors
<Liste 2 {
d'instructions> <Liste 2 d'instructions> }
else if (Condition3)
Sinon Si <

p. 36
Mheni & SGarbouje

Condition3> Alors {
<Liste 3 <Liste 3 d'instructions> }
d'instructions>
…….
….
else
Sinon { <Liste N
<Liste N d'instructions> }
d'instructions>
FinSi
Si (salaire ≤ 5000) alors if (salaire <= 5000)
impot 0.01 impot = 0.01;
Sinon else if (salaire >5000 &&
Si (salaire >5000) ET salaire<=15000)
Exemple (salaire≤15000) alors impot = 0.03;
impot 0.03 else
Sinon impot = 0.05;
impot 0.05
FinSi
Exercice :
Ecrire un algorithme (et un programme C), qui affiche
l’état de l’eau selon sa température. L’algorithme doit
indiquer l'une des 3 réponses possibles (glace, liquide ou
gaz).
Solution :
/**En algorithmique */

Algorithme EtatEau
Variables
T : entier
Début
Ecrire ("Entrez la température de l’eau :")
Lire (T)

p. 37
Mheni & SGarbouje

Si (T ≤ 0) Alors
Ecrire ("C’est de la glace")
Sinon
Si (T < 100) Alors
Ecrire ("C’est du liquide")
Sinon
Ecrire ("C’est de la vapeur")
FinSi
Fin

/**En langage C */
Programme EtatEau.c

#include <stdio.h>
void main ()
{
int t ;
printf ("Entrer la température") ;
scanf ("%d", &t) ;
if (t<=0)
printf ("C’est de la glace") ;
else if (t<100)
printf ("C’est du liquide") ;
else
printf ("C’est de la vapeur") ;
}
3. Structure de choix :
Cette forme est utilisée lorsque l’on a plusieurs
conditions qui expriment une égalité stricte (pas de notion
d’intervalles). Dans ce cas, on a recourts à une structure qui
traite les conditions une par une. Selon la valeur ou la liste

p. 38
Mheni & SGarbouje

des valeurs pouvant prendre le selecteur (variable), on traite


la liste des instructions correspandante:

En algorithmique En langage C
Selon <sélecteur> faire switch (sélecteur)
<val1>: liste 1 {
d'instructions case <val1>:
<val2>: liste 2 <instructions1> ; break ;
d'instructions case <val2>:
<val3>: liste 3 <instructions2> ; break ;
Syntaxe d'instructions case <val3>:
…. <instructions3> ; break ;
Sinon ….
Autre liste default :
d'instructions <autres
FinSelon instructions> ;
}

Selon (mois) Faire switch (mois) {


1 : Ecrire (”Janvier”) case 1 :
2 : Ecrire (”Février”) printf("Janvier"); break ;
… case 2 :
12 : Ecrire printf("Février"); break ;
(”Décembre”) ….
Exemple Sinon case 12 :
Ecrire (”numéro de mois printf("Décembre");
erroné... ”) break ;
FinSelon default :
printf ("le numéro
du mois est erroné") ;
}

p. 39
Mheni & SGarbouje

Remarques :
- On aurait pu faire cet exemple avec la forme
imbriquée mais le code aurait été plus long et surtout
plus compliqué, on se serait perdu dans les
imbrications. Pour un code plus compréhensible on
utilise la structure de choix. Néanmoins, dans certains
cas, cela n’est pas possible, comme lorsqu’on a un
sélecteur de type réel qui peut prendre plusieurs
valeurs dans un intervalle. D’où, généralement cette
forme de choix est utilisée avec les sélecteurs de type
entier ou caractère.
- En langage C, le mot clé break est très important
après chaque cas. Si on l’oublie, après l’exécution des
instructions du cas sélectionné, les instructions de
tous les cas suivants sont aussi exécutées ! ceci
semble être une défaillance mais au contraire, elle
peut être utilisée à profit (voir l'exemple suivant).

Exemple :
On est demandé d'ecrire l'algorithme et le programme
C permettant de saisir le numéro de mois et d’afficher le
nombre de jours correspondant.
/**En Algorithmique */

Algorithme NombreJours
Variables
mois : entier
Début
Ecrire (”Entrer le numéro du mois : ”)

p. 40
Mheni & SGarbouje

Lire (mois)
Selon (mois) Faire
1, 3, 5, 7, 8, 10, 12 : Ecrire(”31 jours”)
2 : Ecrire (”28 ou 29 jours”)
4, 6, 9, 11 : Ecrire (”30 jours”)
Sinon
Ecrire (”numéro de mois erroné”)
FinSelon
Fin

/**En langage C */
#include <stdio.h>
void main()
{
int mois ;
printf ("Entrer le mois en chiffre :") ;
scanf ("%i", &mois) ;
switch (mois) {
case 1, case 3, case 5, case 7, case 8, case 10, case 12 :
printf("31 jours") ; break ;
case 2 : printf ("28 ou 29 jours") ; break ;
case 4, case 6, case 9, case 11 : printf("30 jours") ; break ;
default : printf ("le numéro du mois est erroné") ;
}
}

IV. Exercices d'application


Exercice 1:
Ecrire l'algorithme (et le programme c) qui lit la moyenne
d'un étudiant puis affiche sa mention, telle que :

Moyenne < 10 redoublant

p. 41
Mheni & SGarbouje

10 <=Moyenne < 12 passable


12<=Moyenne < 14 Assez Bien
14<=Moyenne < 16 Bien
16<=Moyenne < 18 Très Bien
18<=Moyenne <= 20 Excellent

Exercice 2:
Ecrire l'algorithme (et le programme c) en langage C qui
affiche la résistance équivalente à trois résistances R1, R2,
R3 (de type double) sachant que :
– si les résistances sont branchées en série : Rsérie =
R1+R2+R3
– si les résistances sont branchées en parallèle : Rparal =
R1× R2 × R3
R1× R2 + R1× R3 + R2× R3
Exercice 3:
Ecrire l'algorithme (et le programme c) qui permet de
résoudre dans R l'équation : ax²+bx+c=0. Utiliser la fontion
sqrt qui exprime la racine carré de la bibliothèque math.h.

V. Correction
Exercice 1

/**En algorithmique */

Algorithme Mention
Variables
Moy : réel
Début

p. 42
Mheni & SGarbouje

Ecrire ("Entrez la moyenne :")


Lire (Moy)
Si (Moy <10) Alors
Ecrire ("Redoublant")
Sinon
Si ((10 ≤ Moy) ET (Moy < 12)) Alors
Ecrire ("Passable")
Sinon
Si ((12 ≤ Moy) ET (Moy < 14)) Alors
Ecrire ("Assez bien")
Sinon
Si ((14 ≤ Moy) ET (Moy < 16)) Alors
Ecrire ("Bien")
Sinon
Si ((16 ≤ Moy) ET (Moy < 18)) Alors
Ecrire ("Très bien")
Sinon
Si ((18 ≤ Moy) ET (Moy ≤ 20)) Alors
Ecrire ("Excellent")
Sinon
Ecrire ("La valeur de la moyenne n'est pas valide")
FinSi
Fin

/**En langage C */
Programme Mention.c

#include <stdio.h>
main()
{ float Moy;
printf ("Entrez la moyenne :");
scanf ("%f",&Moy);
if (Moy <10)

p. 43
Mheni & SGarbouje

printf ("Redoublant");
else if ((10 <= Moy) && (Moy < 12))
printf ("Passable");
else
if ((12 <= Moy) && (Moy < 14))
printf ("Assez bien");
else
if ((14 <= Moy) && (Moy < 16))
printf ("Bien");
else
if ((16 <= Moy) && (Moy < 18))
printf ("Très bien");
else
if ((18 <= Moy) && (Moy <= 20))
printf ("Excellent");
else
printf ("La valeur de la moyenne n'est pas valide"); }
Exercice 2
/**En algorithmique */

Algorithme Résistance
Variables
R1,R2,R3 : réel
Montage : caractère
Début
Ecrire ("donner R1") lire (R1)
Ecrire ("donner R2") lire (R2)
Ecrire("donner R3") lire(R3)
Ecrire("quel est le type de montage? S
si série et P si parallèle:") lire(Montage)
Si (Montage ='P') Alors
Ecrire ("Résistance parallèle="

p. 44
Mheni & SGarbouje

,(R1*R2*R3)/((R1*R2)+(R2*R3)+(R1*R3)))
Sinon
Si (Montage ='S') Alors
Ecrire ("Résistance série = ",(R1+R2+R3) )
Sinon
Ecrire ("entrée incorrecte")
FinSi
FinSi
Fin

/**En langage C */

Programme resistance.c
#include <stdio.h>
main()
{ float R1,R2,R3;
char montage;
printf ("donner R1:");
scanf ("%f",&R1);
printf ("donner R2:");
scanf ("%f",&R2);
printf ("donner R3:");
scanf ("%f",&R3);
printf ("quel est le type de montage? S si série et P si parallèle :");
scanf ("%c",&montage);
if(montage =='P')
printf ("Résistance parallèle =
%f",(R1*R2*R3)/((R1*R2)+(R2*R3)+(R1*R3)));
else
if (montage =='S')
printf ("Résistance série = %f ",(R1+R2+R3) );
else
printf ("entrée incorrecte");}

p. 45
Mheni & SGarbouje

Exercice 3
/**En Algorithmique */

Algorithme Equation

Variables
a,b,c, delta:réel
Début
Ecrire ("donner a:") lire (a)
Ecrire ("donner b:") lire (b)
Ecrire("donner c:") lire(c)
delta←(b*b-4*a*c)
Si (delta =0) Alors
Ecrire (" une seule solution x1=x2=", -b/2*a)
Sinon
Si (delta>0) Alors
Ecrire ("deux solution x1 = ",
-b-sqrt(delta)/2*a,"et x2 = ",-b+sqrt(delta)/2*a)
Sinon
Ecrire ("pas de solution")
FinSi
Fin
/**En langage C */

Programme equation.c
#include <math.h>
#include <stdio.h>
main()
{ float a,b,c,delta;
printf ("donner a:");
scanf ("%f",&a);
printf ("donner b:");

p. 46
Mheni & SGarbouje

scanf ("%f",&b);
printf ("donner c:");
scanf ("%f",&c);
delta = b*b - 4*a*c;
if (delta ==0)
printf (" une seule solution x1=x2=%f ", -b/2*a);
else
if (delta>0)
printf ("deux solutions x1 =%f et x2=%f ", -b-sqrt(delta)/2*a, -
b+sqrt(delta)/2*a);
else
printf ("pas de solution dans R");
}

p. 47
Mheni & SGarbouje

Les boucles itératives


I. Introduction
Prenons un exemple de programme dans lequel on
voudrait lire et traiter les notes de 20 étudiants. Si on utilise
uniquement les notions de programmation vu jusqu'à
maintenant, l’algorithme contiendrait au moins 50 lignes de
code ce qui est inacceptable. Ainsi, pour répondre à des
situations où un programmeur veut répéter plusieurs fois la
même liste d'instructions, il existe la notion de boucles
itératives. Ces boucles peuvent être de trois types :

• Boucle pour … faire


• Boucle répéter… jusqu'à
• Boucle tant que… faire

II. Boucle « pour...faire »


Cette boucle est généralement utilisée lorsqu’on connaît
à l’avance le nombre de répétitions. Le contrôle des itérations
est assuré par un compteur.

En algorithmique :

- On doit préciser la valeur initiale que doit prendre le


compteur, la valeur finale et le pas d'incrémentation.

p. 48
Mheni & SGarbouje

- Dans le cas ou le pas=1, on supprime cette partie


[pas = 1]. En langage C, ce n'est pas le cas, on doit
toujours préciser le pas d'incrémentation.

- si le pas est négatif (décrementation) la valeur finale


doit être inférieur à la valeur initiale.

Syntaxe :

Pour < compteur> de <Valeur_Init> à


<Valeur_Fin> [pas = p] Faire
En
algorithmique Liste d'instructions

FinPour

for (compteur=Valeur_Init ;
compteur<=Valeur_Fin;compteur++)
En langage C
{
Liste d'instructions}
Principe de fonctionnement :

Le compteur prend au début la valeur initiale. Si cette


valeur est inférieure ou égale à la valeur finale, on traite la
liste des instructions puis le compteur est incrémenté de la
valeur p (pas) et on vérifie si la nouvelle valeur est encore
inférieure à la valeur finale pour effectuer la liste des
instructions. On répète ce traitement jusqu'à ce que le

p. 49
Mheni & SGarbouje

compteur dépasse la valeur finale. Dans ce cas, on sort de la


boucle sans exécuter les instructions.

Exemple :

En algorithmique En langage C
Pour i de 1 à 5 faire for (i=1 ; i<=5 ; i++)
Ecrire (i*10) printf (" %d ", i*10) ;
FinPour

Cette boucle affiche respectivement les nombres 10, 20, 30,


40 et 50.

Exemple:

Ecrire un programme qui lit un entier n puis affiche sa


factorielle: n!=1×2×3×4….×(n-1) × n

Solution:

/**En algorithmique*/

Algorithme Factoriel
Variables
n, f, i : Entier
Début
Ecrire (”Entrer un entier positif : ”)
Lire(n)
f←1
Pour i de 2 à n Faire

p. 50
Mheni & SGarbouje

f ←f * i
FinPour
Ecrire (n,”! = ”,f)
Fin.

/**En langage C */
Programme Facto.c :
#include <stdio.h>
void main ()
{
int n,i,f ;
printf ("Entrer un entier positif: ") ;
scanf ("%d", &n) ;
f=1;
for (i=2 ; i<=n ; i++)
f *= i ;
printf ("%d ! = %d", n, f) ;
}

III. Boucle « Répéter...jusqu'à»

Cette boucle est utilisée lorsqu’on ignore d'avance le


nombre de répétitions. Sa particularité est que la liste
d’instructions à l’intérieur de la boucle est exécutée au moins
une fois. En effet, le test pour s’arrêter de boucler n’est
effectué qu’à la fin de chaque itération. D’où, ce genre de
boucle est souvent utilisé pour les saisies conditionnées au
clavier. La différence entre l'algorithmique et le langage C
pour cette boucle, c'est qu'en algorithmique en doit préciser la
condition d'arrêt, et en C on doit préciser la condition
d'itération.

p. 51
Mheni & SGarbouje

Syntaxe :

Syntaxe Exemple
Répéter Répéter
Liste Ecrire ("Entrer un
En
d'instructions entier positif")
algorithmique jusqu'à (condition Lire (n)
d’arrêt) Jusqu’à (n>0)
do { do {
printf ("Entrer un
Liste entier positif") ;
En langage C d'instructions scanf ("%i", &n) ;
} while (condition } while (n<0);
d’itération);

Principe de fonctionnement :

En Algorithmique : La liste d’instructions est exécutée


une fois, ensuite, on vérifie si la condition d’arrêt est valide
dans ce cas on sort de la boucle, sinon, on répète la liste des
instructions et le test de la condition encore de la même
manière.

En langage C: c’est assez déroutant mais la condition


est inversée. Cela vient du fait que do…while en anglais
signifie en fait répéter… tant que. Le fonctionnement est le
même, on exécute la liste d’instruction puis on teste.
Néanmoins, quand la condition est valide, on itère la liste
d’instruction et le test, sinon on sort de la boucle.

p. 52
Mheni & SGarbouje

Cette structure peut être utilisée avec un compteur


comme dans la boucle pour. Dans ce cas, il faut faire
attention au nombre d'itérations et faire les bons choix
concernant la valeur d’initialisation, la condition d'arrêt
(choisir entre supérieur, supérieur ou égale, ou égale) et la
position de l’incrémentation du compteur (avant ou après le
traitement à répéter). En outre, il faut se méfier des boucles
infinies, dues souvent au fait d’oublier l'incrémentation du
compteur à l’intérieur de la boucle.

Exemple : On reprend l’exemple précédent

En algorithmique En langage C
i←1 i=1;
Répéter do
Ecrire (i*10) {
i←i+1 printf (" %d ", i*10) ;
Jusqu'à (i >5) i++ ;
} while (i <= 5) ;

Remarque :
Si l’on met " Jusqu'à (i=5)", on aura 4 itérations car
le cas où i =5 n'est pas inclus, et l’affichage s’arrêtera à 40.
En langage C, on remarque qu’il faut mettre l’inverse de la
condition en algorithmique. Si on se trompe en mettant i<5,
lorsque i=5 on sort de la boucle et l’affichage s’arrêtera à 40.
Par ailleurs, si l’on ne met pas i←i+1, l'exécution affichera
infiniment la valeur 10.

p. 53
Mheni & SGarbouje

Exercice:

Ecrire un algorithme (et le programme C) qui lit un


entier n puis calcule et affiche sa factorielle en utilisant une
boucle répéter…jusqu’à sachant que n!=1×2×3×4...×(n-1) × n

Solution:

/**En algorithmique */
Algorithme Factoriel2
Variables
n, f, i : Entier
Début
Répéter
Ecrire (”Entrer un entier positif : ”)
Lire(n)
Jusqu’à (n>=0)
f← 1
i← 1
Répéter
f← f * i
i← i + 1
Jusqu'à (i > n)
Ecrire (n,”! = ”, f)
Fin.

/**En langage C */
Programme Facto.c :
#include <stdio.h>
void main (){
int n,i,f ;
do {

p. 54
Mheni & SGarbouje

printf ("Entrer un entier positif: ") ;


scanf ("%d", &n) ;
}while ( n<0 ) ;
i=1 ;f=1;
do{
f *= i ;
i++ ;
}while ( i<=n ) ;
printf ("%d ! = %d \n", n, f) ;
}

p. 55
Mheni & SGarbouje

IV. Boucle «Tant que…faire »


Cette boucle s’utilise aussi dans les cas où le nombre
d’itérations est inconnu mais elle se différencie de la boucle
"répéter jusqu'à" par le fait qu’aucun traitement ne doit être
effectué si la condition au début est fausse.

Syntaxe :

Syntaxe Exemple
Tant que (condition somme ←0
d’itération) faire Tant que
(somme<100) faire
<Liste
En d'instructions> Ecrire ("Entrer un
algorithmique entier positif")
FinTQ Lire (n)
somme ←somme + n
Fin Tant que
while (condition somme=0 ;
d’itération) while (somme<100){
{ printf ("Entrer un
<Liste entier positif") ;
En langage C d'instructions>
} scanf ("%i", &n) ;
somme += n ;
}

p. 56
Mheni & SGarbouje

Principe de fonctionnement :

La première chose à faire est la vérification de la


condition, lorsqu’elle n’est pas valide, on ne peut accéder à
l’intérieur de la boucle. Tandis que lorsque la condition est
valide, la liste d’instructions est exécutée, puis on refait la
vérification et on s’arrête de boucler dès que la condition
n’est plus satisfaite. Que ce soit avec ou sans un compteur, il
faut faire attention à ne pas oublier de modifier dans la boucle
toute variable qui figure dans la condition afin d’éviter les
boucles infinies.

Exemple : On reprend l’exemple précédent

En algorithmique En langage C
i←1 i=1;
Tant que (i<=5) while (i <= 5)
faire {
Ecrire (i*10) printf (" %d ", i*10) ;
i←i+1 i++ ;
FinTQ }

Remarque :
L’expression de la condition est différente de celle
dans la boucle «répéter jusqu’à » en algorithmique et en
langage C. Puisque la vérification se fait au début, la
comparaison doit être non stricte (inférieur ou égale), si l’on
met i<5, lorsque i atteint 5, on sort de la boucle et 50 ne sera

p. 57
Mheni & SGarbouje

pas affiché. Par ailleurs, attention à une erreur très


commune : il n’y pas de « ; » après while dans la boucle en
langage C.

Exercice :

Ecrire un programme qui lit un entier positif n puis


calcule et affiche sa factorielle en utilisant une boucle «Tant
que.. faire», sachant que n!=1×2×3×4….×(n-1) × n

Solution:

/**En algorithmique */
Algorithme Factoriel3
Variables
n, f, i : Entier
Début
Répéter
Ecrire (”Entrer un entier positif : ”)
Lire(n)
Jusqu’à (n>=0)
f←1
i←2
TantQue (i <= n) Faire
f←f * i
i←i + 1
FinTQ
Ecrire (n,”! = ”, f)
Fin.

/**En langage C */

p. 58
Mheni & SGarbouje

Programme Facto.c :

#include <stdio.h>
void main ()
{
int n,i,f=1 ;
do {
printf ("Entrer un entier positif ") ;
scanf ("%d", &n) ;
} while ( n<0 ) ;
i=2 ;f=1;
while ( i<=n )
{ f *= i ;
i++ ;
}
printf ("%d ! = %d\n", n, f) ;
}

V. Exercices d'application

Exercice 1:

Ecrivez un programme qui lit N nombres entiers au


clavier puis affiche leur somme, leur produit et leur moyenne.
Choisissez un type approprié pour les valeurs à afficher. Le
nombre N est à saisir au clavier. Résolvez ce problème :
a) en utilisant la boucle «pour...faire»,
b) en utilisant la boucle «tant que...faire »,
c) en utilisant la boucle «répéter... jusqu'à ».

p. 59
Mheni & SGarbouje

Exercice 2:

Calculez XN par multiplications successives sachant


que X et N sont deux entiers naturels saisis au clavier.

Exercice 3:

Calculez la somme des N premiers termes de la série


harmonique avec N>0:

1 1 1
S=1+ + + ... +
2 3 N

Exercice 4:

Calculez le Nième terme UN de la suite de


FIBONACCI sachant que :
UN=UN-1 + UN-2 (pour
N>2)
U1=1 et U2=1
Exercice 5:

Ecrire un algorithme (et le programme c) qui


détermine tous les nombres premiers inférieurs à un entier n
donné au clavier.

Exercice 6:

Ecrire un algorithme (et le programme c)qui lit deux


entiers A et B puis calcule et affiche leur PGCD (Plus Grand

p. 60
Mheni & SGarbouje

Commun Diviseur) en utilisant la méthode euclidienne


suivante :
– Si A = B ; PGCD (A, B) = A
– Si A > B ; PGCD (A, B) = PGCD (A–B, B)
– Si B > A ; PGCD (A, B) = PGCD (A, B–A)

Exemple :
PGCD(18,45)=PGCD(18,27)=PGCD(18,9)=PGCD(9,9)=9
Exercice 7:

Ecrire un algorithme (et le programme c) qui calcule


le PPCM (Plus Petit Commun Multiple) de 2 entiers A et B
en utilisant la méthode suivante :
– Permuter, si nécessaire, les données de façon à ranger dans
A le plus grand des 2 entiers ;
– Chercher le plus petit multiple de A qui est aussi multiple
de B.
Exemple : PPCM(6,8) = PPCM(8,6) = 24.

Exercice8 : nombres parfaits

Un nombre parfait est un nombre présentant la


particularité d’être égal à la somme de tous ses diviseurs, sauf
lui-même.
Le premier nombre parfait est 6 = 3 + 2 + 1.
Ecrire un algorithme (et le programme c) qui affiche tous les
nombres parfaits inférieurs à 1000.

p. 61
Mheni & SGarbouje

VI. Correction
Exercice 1

/**Algorithme avec boucle pour */

Algorithme nbr1
Variable s
i,N,x,S,P:entier
Début
S←0
P←1
Ecrire ("donner N:")
lire (N)
Pour i de 1 à N faire
Ecrire ("donner un entier ")
lire (x)
S←S+x
P←P*x
FinPour
Ecrire( "la somme est ",S,"le produit est ", P, "la
moyenne est ",S/N)
Fin
/**Algorithme avec boucle Tant que */

Algorithme nbr2
Variables
i,N,x,S,P:entier
Début
S←0
P←1
i←1

p. 62
Mheni & SGarbouje

Ecrire ("donner N:")


lire (N)
Tant que (i≤N)faire
Ecrire ("donner un entier")
lire (x)
S←S+x
P←P*x
i←i+1
FinTQ
Ecrire( "la somme est ",S,"le produit est ", P, "la moyenne
est ",S/N)
Fin
/**Algorithme avec boucle Répéter jusqu'à */
Algorithme nbr3
Variables
i,N,x,S,P:entier
Début
S←0
P←1
i←1
Ecrire ("donner N:")
lire (N)
Répéter
Ecrire ("donner un entier")
lire (x)
S←S+x
P←P*x
i←i+1
Jusqu'à(N<i)
Ecrire( "la somme est ",S,"le produit est ", P, "la moyenne
est ",S/N)
Fin

p. 63
Mheni & SGarbouje

/**programme C avec boucle for */


Programme nbr1.c
#include <stdio.>
main() {
int i,N,x,S,P;
printf ("donner N:");
scanf ("%i",&N);
S=0;
P=1;
for (i=1;i<=N;i++ ) {
printf ("donner un entier x:");
scanf ("%i",&x);
S=S+x;
P=P*x;
}
printf( "la somme est %d le produit est %d la moyenne est
%f \n", S, P, S/N);
}
/**programme C avec boucle while */

Programme nbr2.c
#include <stdio.>
main() {
int i,N,x,S,P;
printf ("donner N:");
scanf ("%i",&N);
S=0;
P=1;
i=1;
while (i<=N) {
printf ("donner un entier x:");
scanf ("%i",&x);
S=S+x;

p. 64
Mheni & SGarbouje

P=P*x;
i++;
}
printf( "la somme est %d le produit est %d la moyenne est
%f\n", S, P, S/N);
}
/**programme C avec boucle do..while */
Programme nbr3.c
#include <stdio.>
main() {
int i,N,x,S,P;
printf ("donner N:");
scanf ("%i",&N);
S=0;
P=1;
i=1;
do {
printf ("donner un entier x:");
scanf ("%i",&x);
S=S+x;
P=P*x;
i++;
}while(i<=N);
printf( "la somme est %d le produit est %d la moyenne est
%f\n", S, P, S/N);
}

p. 65
Mheni & SGarbouje

Exercice 2

/**En algorithmique */

Algorithme Puissance
Variables
X, P : Réel
N, i : Entier
Début
Ecrire(”Entrer la valeur de X : ”) lire(X)
Ecrire(”Entrer la valeur de N : ”) lire(N)
P←1
Pour i de 2à N Faire
P←P * X
FinPour
Ecrire(X,” à la puissance ”,N,” = ”,P)
Fin.
/**En langage C */

Programme Puissance.c

#include <stdio.h>
main()

{float x, p;
int n,i;
printf ("Entrer la valeur de x :");
scanf("%f",&x);
printf ("Entrer la valeur de n :");
scanf("%d",&n);
p=1;
for (i=2;i<=n;i++)
p=p*x;

p. 66
Mheni & SGarbouje

printf ("%f à la puissance %d = %f \n", x, n, p);


}

Exercice 3
/**En algorithmique */

Algorithme Somme_Inverse
Variables
n, i : Entier
s : Réel
Début
Ecrire(”Entrer la valeur de n : ”) Lire(n)
s←0
Pour i de 1 à n Faire
s←s + 1/i
FinPour
Ecrire(”s = ”,s)
Fin
/**En langage C */

Programme Somme_Inverse.c
#include <stdio.h>
main(){
float s;
int n,i;
printf ("Entrer la valeur de n :");
scanf("%d",&n);
s=0;
for (i=1;i<=n;i++)
s=s+1/i;
printf ("somme= %f \n", s);
}

p. 67
Mheni & SGarbouje

Exercice 4
/**En algorithmique */

Algorithme Fibonacci
Variables
U0, U1, U, n, i : Entier
Début
Ecrire(”Nombre de termes à calculer : ”)
Lire(n)
U0←1
Ecrire(”U0 = ”,U0)
U1←1
Ecrire(”U1 = ”,U1)
Pour i de 2 à (n-1) Faire
U←U0 + U1
Ecrire(”U”,i,” = ”,U)
U0 ←U1
U1 ←U
FinPour
Fin.
/**En langage C */

Programme Fibonacci.c

#include <stdio.h>
main(){
int n,i, u0,u1,u;
printf ("Entrer le nombre de termes à calculer:");
scanf("%d",&n);
U0=1;U1=1;
printf ("U0 = %d U1 = %d ",U0,U1);
for (i=2;i<=n;i++)
{

p. 68
Mheni & SGarbouje

U=U0+U1;
printf ("U%d= %d ", i, U);
U0=U1;
U1=U;
}
}

Exercice 5
/**En algorithmique */

Algorithme Premiers
Variables
n, i, j, nb_div : Entier
Début
Ecrire(”Entrer la valeur de n : ”)
Lire(n)
Pour i de 1 à n Faire
nb_div←0
Pour j de 1 à i Faire
Si (i Mod j = 0) Alors
nb_div ←nb_div + 1
FinSi
FinPour
Si (nb_div <= 2) Alors
Ecrire(i)
FinSi
FinPour
Fin
/**En langage C */

Programme Premiers.c

#include <stdio.h>

p. 69
Mheni & SGarbouje

main(){
int n,i,j,nb_div;
printf ("Entrer la valeur de n :");
scanf("%d",&n);
for (i=1;i<=n;i++)
{
nb_div=0;
for (j=1;j<=i;j++)
if (i % j ==0)
nb_div++;
if (nb_div<=2)
printf ("%d ", i);
}
}

Exercice 6
/**En algorithmique */

Algorithme PGCD
Var
a, b : Entier
Début
Ecrire(”Entrer la valeur de a : ”) Lire(a)
Ecrire(”Entrer la valeur de b : ”) Lire(b)
Répéter
Si (a > b) Alors
a ←a – b
FinSi
Si (b > a) Alors
b ←b - a
FinSi
Jusqu'à (a = b)
Ecrire(”PGCD = ”, a)

p. 70
Mheni & SGarbouje

Fin
/**En langage C */

Programme PGCD.c

#include <stdio.h>
main()

{ int a,b;
printf ("Entrer la valeur de a :");
scanf("%d",&a);
printf ("Entrer la valeur de b :");
scanf("%d",&b);
do {
if (a>b)
a=a-b;
if (a<b)
b=b-a;
} while (a!=b);
printf ("PGCD =%d\n", a);
}

Exercice 7
/**En algorithmique */
Algorithme PPCM
Variables
a, b, i, x : Entier
Début
Ecrire(”Entrer la valeur de a : ”) lire(a)
Ecrire(”Entrer la valeur de b : ”) lire(b)
Si(a < b) Alors
x←a
a←b

p. 71
Mheni & SGarbouje

b←x
FinSi
i ←1
TantQue (((i*a) Mod b) <> 0) Faire
i ←i + 1
FinTQ
Ecrire(”PPCM = ”, i*a)
Fin
/**En langage C */

Programme PPCM.c

#include <stdio.h>
main()

{ int a,b,i,x;

printf ("Entrer la valeur de a :");


scanf("%d",&a);
printf ("Entrer la valeur de b :");
scanf("%d",&b);
if (a<b)
{ x=a; a=b; b=x; }
i=1;
while (((i*a) % b) !=0)
i++;
printf ("PPCM =%d\n", i*a);
}

Exercice 8
/**En algorithmique */
Algorithme Parfaits
Variables

p. 72
Mheni & SGarbouje

i, j, n, s : Entier
Début
Pour i de 1 à 1000 Faire
s←0
Pour j de 1 à (i Div 2) Faire
Si((i Mod j) = 0) Alors
s ←s + j
FinSi
FinPour
Si(s = i) Alors
Ecrire(i,” est un nombre parfait”)
FinSi
FinPour
Fin
/**En langage C */
Programme Parfaits.c

#include <stdio.h>
main()
{ int i,j n, s;
for (i=1;i<=1000;i++)
{
s=0;
for (j=1;j<=i/2;j++)
if (i % j ==0)
s=s+j;
if (s==i)
printf ("%d est un nombre parfait \n", i);
}}

p. 73
Mheni & SGarbouje

Fonctions et procédures
L'idée des fonctions et procédures est de diviser un
programme en petits blocs, tel que chacun fournit un résultat
précis ou effectue une fonctionnalité bien déterminée.

Supposant qu'on voudrait développer un programme


qui lit les notes des étudiants, calcule les moyennes, puis
affiche leurs maximum et minimum. L'écriture d'un tel
programme dans un seul bloc rend la manipulation et la
maintenance du programme très délicat.

Si l’on prend par exemple le calcul des moyennes, on


demande les notes de chaque étudiant (on répète la même
procédure pour tous les étudiants) puis on applique une même
formule. On peut alors penser à un sous programme auquel
on fournit les 2 ou 3 notes et qui renvoie directement la
valeur de la moyenne, ça minimise la taille du programme et
ça facilite la manipulation. Ou par exemple, Lorsqu'on a
besoin d'une fonction maximum, on l'appelle directement.

I. Les procédures
Une procédure est un sous-programme qui permet
d’effectuer un certain nombre de traitements afin de réaliser
un ou plusieurs résultats.

p. 74
Mheni & SGarbouje

Prenons l’exemple d'un algorithme qui affiche un


message, les deux programmes donnent le même résultat.

Algorithme Procédure message()


affichage Début
Début
Ecrire ("Bonjour tout le
Ecrire ("Bonjour monde")
tout le monde")
Fin
Fin Algorithme affichage
/*programme principale*/
Début
message()
Fin

Le compilateur commence toujours par exécuter le


programme principal (algorithme principal). Lors de l'appel
d'une procédure (avec son nom, comme le nom message dans
le programme précédent), le compilateur, cherche la
procédure (le sous-programme appelé) l'exécute, utilise le
résultat de cette exécution à ce niveau, puis continue
l'exécution du programme principal.

Dans le cas d'une procédure paramétrée, on doit


fournir dans l’entête de la procédure les paramètres effectifs
(soit des variables contenant des valeurs ou des valeurs) pour

p. 75
Mheni & SGarbouje

remplacer les paramètres formels utilisés dans la définition de


la procédure.
Paramètre formel

Procédure message (n : entier, ch: chaine)


Variables:
i: entier
Début
Pour i de 1 à n faire
Ecrire (ch)
finPour
Fin
/* le programme suivant affiche le message
"ch" un certain nombre de fois choisi par
l'utilisateur*/
Algorithme affichage
Variables
x: entier
c: chaine
Début
Ecrire ("donner un nombre")
Lire(x)
Ecrire ("donner la chaine que vous
désirez afficher") Appel de la procédure avec
Lire(c) paramètre effectif
message(x,c)

Fin

p. 76
Mheni & SGarbouje

La définition de la procédure message, contient la


liste des paramètres formels (les variables n et ch) selon la
syntaxe suivante :

Procédure nom_procédure ( param_formel1: type1,


param_formel2: type2,…)

L'appel de la procédure se fait par son nom, avec des


paramètres effectifs (x et c) selon la syntaxe suivantes :
nom_procédure (param_eff1, param_eff2,…)

N.B: Lors de l'appel il faut respecter l'ordre, le nombre et le


type des paramètres.

Portée des variables


La variable i dans la procédure est appelée variable
locale. Une variable locale est déclarée dans un sous-
programme (fonction ou procédure) et ne peut être utilisé que
dans ce sous-programme. Contrairement à une variable
globale qui est déclarée dans l'algorithme principal et peut
être utilisé dans les différentes parties (algorithme principal et
sous-programmes).
Exemple:
• i : est une variable locale dans la procédure message.
• x et c sont deux variables globales.

p. 77
Mheni & SGarbouje

En langage C :

Définition de procédure Appel de procédure


Syntaxe void nom_procédure nom_procédure(val1,val2,…);
(type param1, type
param2, …)
{
// déclarations des variables
locales
// instructions
}
Exemple void message (char ch[], message ("bonjour", 5) ;
int n)
{
int i ;
for (i=1 ;i<=n ;i++)
printf ("%s \n", ch) ;
}
Passage des paramètres :

La transmission des paramètres formels aux paramètres


effectifs, s'appelle le passage de paramètres. Il faut
différencier entre les paramètres donnée, paramètres résultat
et paramètres donnée-résultat.

Les paramètres donnés, sont des variables utilisées


pour effectuer des traitements sans modifier leurs valeurs.
Quant aux paramètres résultat, ce sont des variables dans

p. 78
Mheni & SGarbouje

lesquelles on enregistre les résultats des traitements, et qui


seront changées après l'exécution de la procédure.

N.B: En algorithmique il faut placer le mot clé Var devant


les paramètres donnée-résultat et résultat sinon, le
changement de leurs valeurs ne sera pas pris en compte dans
le programme principal.

En langage C, il faut placer un * devant les paramètres


formels données-résultat et résultat dans l’entête de la
procédure pour prendre en compte les modifications. En plus,
il faut ajouter le symbole & devant les paramètres effectifs
lors de l’appel de la procédure.

Exemple:

Procédure produit (a,b: Procédure produit (a,b,c:


entier, var c: entier) entier)
Début Début
c ←a × b c ←a × b
Fin
Fin Algorithme résultat
Algorithme résultat Variables:
Variables: x, y, z: entier
x, y, z: entier Début
Début z←1
z←1 Ecrire ("donner les
Ecrire ("donner les valeurs de x et y)
valeurs de x et y) Lire(x,y)
Lire(x,y) Produit(x,y,z)
Produit(x,y,z) Ecrire ( "le produit

p. 79
Mheni & SGarbouje

Ecrire ( "le produit de", x,"et", y ,"est", z)


de", x,"et",y ,"est", z)
Fin Fin
/**la variable z change de /** la variable z ne change pas,
valeur, le programme affiche le programme affiche 1
dans z le résultat du produit quelque soit les valeurs de x et
x×y */
y */

Exemple en langage C :

Passage par adresse Passage par valeur

#include <stdio.h> #include <stdio.h>


void produit (int a, int b, int void produit (int a, int b, int c)
*c) { c= a*b ; }
{ *c= a*b ; } void main()
void main() { int x, y, z=1 ;
{ int x, y, z=1 ; printf ("entrez x et y") ;
printf ("entrez x et y") ; scanf("%i",&x) ;
scanf("%i",&x) ; scanf("%i",&y) ;
scanf("%i",&y) ; produit (x, y, z) ;
produit (x, y, &z) ; printf("le produit de %i et %i =
printf("le produit de %i et %i = %i", x, y, z) ;
%i", x, y, z) ; // z n’a pas changé de valeur, elle
// z change de valeur et contient contient 1
le produit x×y }
}

p. 80
Mheni & SGarbouje

N.B: Un paramètre forme précédé d'un "*" (étoile) en


C est appelé pointeur. Le pointeur est une variable qui
contient l'adresse mémoire dans laquelle est enregistrée la
valeur pointée.

Dans l'exemple précedent, la variable c est un pointeur


contenant l'adresse d'un entier. L'instruction *c= a*b ; permet
de placer dans la zone mémoire dont l'adresse est dans c la
valeur a*b. L'adresse mémoire d'une variable en langage C
est noté par &nom_variable. (Voir chapitre les pointeurs)

Exercice:

Ecrire une procédure qui permet de permuter deux entiers a et


b.

Solution :

/**En algorithmique */
Procédure Permutation (var x : réel, var y : réel)
Variables
z : réel
Début
z x
x y
y z
Fin

/**En langage C */
Programme Permutation.c

p. 81
Mheni & SGarbouje

Permutation (int *x, int *y)


{ int z ;
z = *x ;
*x = *y ;
*y = z ;
}

II. Les fonctions:


Une fonction est une procédure particulière qui permet de
retourner un seul résultat. L'entête de la fonction contient la
liste des paramètres formels. Il faut indiquer aussi le type de
retour pour cette fonction, c'est à dire celui de son résultat.
L'appel d'une fonction se fait généralement dans une
expression (affectation à une variable, ou dans une condition
ou bien dans une instruction d'affichage).

p. 82
Mheni & SGarbouje

Syntaxe:

En Fonction nom_fonction (param_frml1:


algorithmique type1, param_frml2:type2….) :
type_résultat
Variables
Debut
Liste des instructions de la
fonction
Nom_de_la_fonction←résultat
Fin
En langage C type_résultat Nom_fonction (param_frml1:
type1, param_frml2:type2….) {
// déclaration des variables locales dont
variable_résultat
// liste des instructions
return (résultat) ;
}
Exemple:

Ci-dessous un algorithme qui fait appel à une fonction


qui affiche le maximum de deux entiers positifs

p. 83
Mheni & SGarbouje

/**En algorithmique */

Algorithme Fonction_Max Entête de l'algorithme dans lequel on


déclare les types, les variables et les
Variables:
constantes en plus du nom de
x,y,z:entier l'algorithme

Fonction Max (a,b:entier):entier


Début
Si(a<b) alors
Cette partie contient
Max←b les déclarations des
Sinon fonctions et
Max←a procédures à utiliser
FinSi par l'algorithme
Fin

Début Cette partie est le


corps principal
Ecrire ( " Entrez un entier ") Lire (x)
de l'algorithme
Ecrire ( " Entrez un entier ") Lire (y) contenant les
z←Max(x,y) instructions entre
Ecrire("le max entre",x,"et",y,"est",z) autre appels des
/**on peut afficher directement fonctions et
procédures
sans utiliser z:*/
Ecrire("le max entre",x,"et",y,"est",Max(x,y))
Si(Max(x,y)>0) Alors
Ecrire ("le max entre les deux entiers
est positif")
FinSi
Fin

p. 84
Mheni & SGarbouje

/**En langage C */

#include <stdio.h>
// fonction maximum
int maximum (int a, int b)
{ if (a<b)
return (b) ;
else
return (a) ;
}
// programme principal
void main()
{
int x, y, z ;
printf ("Entrez un entier") ;
scanf ("%i", &x) ;
printf ("Entrez un entier") ;
scanf ("%i", &x) ;
z = maximum(x,y) ;
printf ("Le maximum entre %i et %i est %i", x, y,
z) ;
// on peut afficher directement sans utiliser z
printf ("Le maximum entre %i et %i est %i", x, y,
maximum(x,y)) ;
if (maximum(x,y)>0)
printf ("le maximum entre les deux entiers est
positif");
}

p. 85
Mheni & SGarbouje

III. Exercices d'application :


Exercice 1 :
a) Ecrire une fonction qui saisit un entier et renvoie VRAI s'il
s'agit d'un numéro de mois.
b) Ecrire une fonction qui saisit un entier et renvoie VRAI s'il
est composé de 4 chiffres.
c) Ecrire une procédure qui vérifie si le numéro d'un mois et
celui d'une année passés en paramètre sont correctes et
affiche l'âge (année et mois) utilisant la date d'aujourd'hui.
Pour la vérification, utilisez les fonctions des questions
précédentes.

Exercice 2 :
a) Ecrire une fonction qui retourne le prix final d'un produit
acheté après la remise accordée.
b) Ecrire une fonction qui calcule le prix final à payer après
une remise et l'ajout du TVA.
c) Ecrire un algorithme qui demande à l'utilisateur de fournir
le prix, la remise en pourcentage et aussi la TVA en
pourcentage et affiche le prix à payer en utilisant les
fonctions précédentes

Exercice 3 :
a) Ecrire une procédure "saisie" qui permet de saisir un entier
composé de 3 chiffres.
b) Ecrire une procédure "somme" qui permet d'extraire dans
des variables les unités, les dizaines et les centaines à partir
d'un entier composé de 3 chiffres.

p. 86
Mheni & SGarbouje

c) Ecrire une fonction "cubique" qui retourne vrai si l'entier


donné en paramètre est cubique et faux sinon.
Un entier naturel de trois chiffres est dit cubique s'il égal à la
somme des cubes de ses trois chiffres. Exemple: 153 est
cubique car 153 = 13 + 53 + 33.
d) Ecrire un algorithme qui utilise la procédure saisie pour
lire un entier E entre 100 et 999 puis affiche si E est cubique
ou pas.
Exercice 4 :
Ecrire un sous programme qui, à partir du numéro d’un mois,
permet d’afficher la saison. Exp. :Si mois = 2 Alors on
affiche "Hiver"
Si mois = 6 Alors on affiche "Eté"
Si mois = 5 Alors on affiche "Printemps"
Si mois = 11 Alors on affiche "Automne"

Exercice 5
On appelle moyenne olympique d’un ensemble de nombres la
moyenne arithmétique de tous les nombres de cet ensemble
sauf le plus petit et le plus grand.
Exemple : les nombres sont : 5,11,2,7,4,8,3 ==> moyenne
olympique = (5+7+4+8+3)/5=5,4
Ecrire un algorithme permettant de saisir N réels (5 ≤ N ≤ 20)
distincts et d’afficher leur moyenne olympique en utilisant
une procédure et une fonction.

IV. Correction
Exercice 1 :

a)

p. 87
Mheni & SGarbouje

/**En algorithmique */
Fonction verif_mois(m:entier):booléen

Début
verif_mois ←(1<= m ET m<=12 )
Fin

/**En langage C */

int verif_mois(int m)
{
return (m>=1 && m<=12);
}

b)

/**En algorithmique */
Fonction chiffres_4(année:entier):booléen

Début
Chiffres_4←(( année< 10000ET(999< année) ))
Fin

/**En langage C */

int chiffres_4 (int annee)


{
return (10000>annee && 999<annee);
}

p. 88
Mheni & SGarbouje

c)

/**En algorithmique */
Procédure age(mm:entier, aa:entier)

Début
Si(verif_mois(mm)ET chiffres_4(aa))alors
Ecrire ("votre age est ", 2014-aa ,"ans et", 12-mm,"mois")
SiNon
Ecrire("l'année de naissance ou le mois est erroné")
FinSi

/**En langage C */

void age (int mm, int aa)


{
if (verif_mois(mm) && chiffres_4(aa))
printf("votre age est %d ans et %d mois \n",2015-aa, 12-
mm);
else
printf("l'année ou le mois de naissance est incorrecte \n");
}

Exercice 2 :

a)
/**En algorithmique */
Fonction PrixTTC(prixHT: réel, taxe:réel):réel

Début
PrixTTC ←prixHT + (prixHT*taxe)/100

p. 89
Mheni & SGarbouje

Fin

/**En langage C */

float prixTTC (float prixHT, float taxe)


{
return (prixHT + prixHT*taxe/100);
}

b)

/**En algorithmique */
Fonction Prix_Remise(prix: réel, remise:réel):réel

Début
Prix_Remise ←prix - (prix*remise)/100
Fin

/**En langage C */
float prix_remise (float prix, float remise)
{
return (prix - prix*remise/100);
}

c)

/**En algorithmique */
Algorithme PrixFinal

Variables

Prix_f,Prix_i, p_Taxe, p_remise:réel

p. 90
Mheni & SGarbouje

Début
Ecrire ("donner le prix de l'article") lire (prix_i)
Répéter
Ecrire ("donner le pourcentage de taxe")
lire (p_Taxe)
Jusqu'à((1<=p_Taxe ET p_Taxe <=100))
Répéter
Ecrire("donner la remise en pourcentage")
lire(p_remise)
Jusqu'à ((1<=p_remise ET p_remise<=100))
Prix_f← PrixTTC (prix_i,p_Taxe)
Prix_f← Prix_Remise (prix_f,p_remise)
Ecrire("le montant à payer est", Prix_f,"dinars")
Fin

/**En langage C */
Programme PrixFinal.c
#include <stdio.h>

main (){
float prix_f,prix_i,taxe,remise ;
printf("donner le prix de l'article");
scanf(%f",&prix_i);
do {
printf("donner le pourcentage de taxe");
scanf(%f",&taxe);
} while (taxe<1 || taxe>100);
do {
printf("Saisir le pourcentage de remise");
scanf(%f",&remise);

p. 91
Mheni & SGarbouje

} while (remise<1 || remise>100);


prix_f← PrixTTC (prix_i, taxe);
prix_f← Prix_Remise (prix_f, remise);
Ecrire("le montant à payer est %.3f DT", prix_f);
}

Exercice 3

/**En algorithmique */
Procédure Saisie (var e : entier)
Début
Répéter
Ecrire ("Entrer un entier à 3 chiffres :")
Lire (e)
Jusqu’à (e< 1000 ET e>99)
Fin

/**En langage C*/


void saisie (int *e)
{
do {
printf("Entrer un entier à 3 chiffres :");
scanf(%d",e);
} while (e>999 || e<100);
}

b)

/**En algorithmique */
Procédure Extraire (e : entier, var u : entier, var d : entier,
var c : entier)

p. 92
Mheni & SGarbouje

Début
c ← e div 100
d ← (e mod 100) div 10
u ← e div 10
Fin
/**En langage C*/

void extraire (int e, int *u, int *d, int *c)

{
*c = e / 100;
*d = (e % 100) / 10;
*u = e / 10;
}

c)

/**En algorithmique */
Fonction Cubique (e : entier) : entier
Variables
c, d, u : entier
Début
Extraire (e, u, d, c)
Si (e = c*c*c + d*d*d + u*u*u) alors Cubique
←Vrai
SiNon
Cubique ←Faux
FinSi
Fin

/**En langage C*/

p. 93
Mheni & SGarbouje

int cubique (int e)

{
extraire (e, &u, &c, &d);
if (e==c*c*c+d*d*d+u*u*u)
return 1;
else
return 0;
}

d)

/**En algorithmique */
Algorithme EntierCubique
Variables
E : entier
Début
Saisie(E)
Si (Cubique (E)) alors
Ecrire ("L’entier est cubique")
SiNon
Ecrire ("L’entier n'est pas cubique")
FinSi
Fin
/**En langage C*/
Programme entierCubique.c

void main(){
int n;
saisie(&n)

p. 94
Mheni & SGarbouje

if (cubique(n))
printf("L'entier %d est cubique",n);
else
printf("L'entier %d n'est pas cubique",n);
}
Exercice 4 :

/**En algorithmique */
Procédure Saison (M : entier)
Début
Selon (M) faire
12, 1, 2 : Ecrire("Hiver")
3, 4, 5 : Ecrire("Printemps")
6, 7, 8 : Ecrire("Eté")
9, 10, 11 : Ecrire("Automne")
Sinon : Ecrire ("Entrer un entier entre 1 et 12")
FinSelon
Fin

/**En langage C */
void saison (int M)
{
switch (M){
case 12: case 1: case 2: printf ("hiver");
case 6: case 7: case 8: printf ("été");
case 3: case 4: case 5: printf ("automne");
case 19: case 10: case 9: printf ("printemps");
default: printf ("entrer un entier entre 1 et 12");

}}

p. 95
Mheni & SGarbouje

Exercice 5 :

/**En algorithmique*/
Procédure Saisie (var n : entier)
Début
Répéter
Ecrire ("Entrer le nombre de réel :")
Lire (n)
Jusqu’à (n ≥ 5 et n ≤ 20)
Fin
Fonction Moy (n : entier) : réel
Variables
i : entier
x, min, max, s : réel
Début
Ecrire ("Entrer un réel")
Lire (x)
min ← x
max ← x
s ←x
Pour i de 2 à n faire
Ecrire ("Entrer un réel")
Lire (x)
s ←x+s
Si (max < x) alors
max ← x
FinSi
Si (x< min) alors
min ← x
FinSi

p. 96
Mheni & SGarbouje

s←s+x
FinPour
Moy← (s / (n-2))
Fin
Algorithme MoyenneOlympique
Variables
N : entier
Début
Saisie (N)
Ecrire ("La moyenne olympique = ", Moy(N))
Fin

/**En langage C*/


void Saisie(int *n)
{
do {
printf("Entrer le nombre de réel :");
scanf(%d",n);
} while (n<5 ||n>20);
}

float Moy (int n)


{ int i;
float x, s, min, max;
printf("Entrer un réel :");
scanf(%f",&x);
s = x;
max =x;
min = x;
for (i=2;i<=n;i++)

p. 97
Mheni & SGarbouje

{
printf("Entrer un réel :");
scanf(%f",&x);
if (max<x)
max = x;
if (x<min)
min = x;
s = s + x;
}
return (s / (n-2));
}

main ()
{
int n;
saisie(&n);
printf("la moyenne olympique est %f",Moy(n));
}

p. 98
Mheni & SGarbouje

Les chaines de caractères


I. Introduction
Un caractère correspond à un code ASCII compris
entre 0 et 255 (selon l’American Standard Code for
Information Interchange), il peut être une lettre alphabétique
(A…Z, ou a...z), un chiffre (0..9), un caractère spécial
(/,*,?,&,+,-,~,#,',",{,[,|,€,$,£,..etc.) ou aussi un caractère de
contrôle (echap, espace,Tab, backspace, ..etc.).

Une chaine de caractère est une suite de caractères.


Lorsqu’elle ne contient aucun caractère, elle est appelée
chaine vide. En langage C, une chaîne de caractère (même
vide) contient toujours à la fin le caractère "\0" qui marque la
terminaison de celle ci.

II. Déclaration d'une chaîne


Syntaxe :
En algorithmique En langage C
ch1: chaine char ch1[] ;
ch2: chaine[20] char ch2[20] ;

La variable ch1 peut contenir jusqu'à 255 caractères alors que


ch2 au maximum 20 caractères (n doit contenir une valeur).
Ainsi ch[i] désigne le caractère numéro i dans la chaine.

p. 99
Mheni & SGarbouje

III. Opération sur les chaînes


1. Concaténation

C'est l'assemblage de deux chaînes utilisant l'opérateur "+".


Exemple:
ch1←"bonjour"
ch2←" tout le monde"
ch3←ch1+ch2 // ch3 contient "bonjour tout le monde"

p. 100
Mheni & SGarbouje

2. Opération de comparaison

Les opérations de comparaison utilisées dans le cas


des chaînes de caractères sont les mêmes utilisées avec les
autres types simples tel que: <, <=, =, #, >=, >=.

La comparaison se fait caractère par caractère de


gauche à droite, selon le rang des caractères dans la liste du
code ASCII. Ainsi par exemple "informer" > "informatique",
parce que 'e' > 'a'.

IV. Procédures et fonctions standards


1. Procédures standards

En algorithmique nous avons 3 procédures qui


permettent d'effacer une partie de la chaine, insérer une
chaine dans une autre ou convertir un autre type en une
chaîne de caractères.

Procédure Exemple
Efface (chaine, p, n) ch←"Bonjour"
efface(ch,4,4): supprime 4
caractères à partir de la
position 4, ch contient "Bon"

Insert (ch1, ch2, p) ch1←"AZZA"


ch2←"I"
Insert(ch1,ch2, 3)

p. 101
Mheni & SGarbouje

ch1 contient "AZIZA"


Convch(v, ch) V←5468
convch(V,ch1)
ch1 contient "5468"
2. Fonctions standards

Voici les principales fonctions prédéfinies


standards dans le tableau suivant

Fonction Exemple
Long (ch) ch←"Bonjour"
x←Long(ch)
x contient 7
Copy(ch1,p,n) Ch1←"bonjour"
Ch2←Copy (ch1,4,4)
Ch2 contient le mot "jour"
Ch1←"bonjour"
"+" ou bien Ch2←" tout le monde"
Concat Ch3←Ch1+Ch2
(ch1,ch2,…) // Ch3 contient "bonjour tout le
monde"

<,<=,>,>=,#,= "processus" < "processeur"


retourne Faux
3. Fonctions prédéfinies en langage C :

Le tableau suivant contient les fonctions prédéfinies


en langage C pour les chaînes à partir du fichier bibliothèque
string.h :

p. 102
Mheni & SGarbouje

Fonction Rôle Exemple


Retourne la longueur de la chaine L = strlen ("bonjour")
strlen(ch)
ch L=7
strncat (“bonjour“,
Recopie la chaine ch2 à la suite de
strcat (ch1, ch2) “monsieur”)
ch1
bonjourmonsieur
Recopie n caractères de ch2 à la strncat (ch1, ch2, 3)
strncat (ch1, ch2, n)
suite de ch1 bonjourmon
compare deux chaînes et fournit
strcmp ("paris2",
une valeur entière:
strcmp ( chaîne1, "paris10")
- positive si chaîne1 > chaîne2
chaîne2 ) < 0 (résultat
- nulle si chaîne1 = chaîne2,
négatif)
- négative si chaîne1 < chaîne2.

p. 103
Mheni & SGarbouje

procède comme strcmp mais elle


strncmp ("bonjour",
strncmp ( chaîne1, limite la comparaison au nombre
"bon", 2)
chaîne2, lgmax ) maximal de caractères indiqués
=0
par lgmax.
stricmp ( chaîne1,
chaîne2 ) procèdent comme strcmp et
strncmp, mais sans différencier
strnicmp ( chaîne1,
entre majuscules et minuscules
chaîne2, lgmax )

strcpy (ch1, ch2 ) recopie la chaîne ch2 dans ch1.

strncpy ( ch1, ch2, procède comme strcpy, en strncpy (“xxxxxxxxx”,


lgmax ) limitant la recopie au nombre de ”bonjour”, 6);
caractères précisés par lgmax bonjouxxx
strchr ( chaîne, strchr (“bonjour”,’o’);
caractère ) recherche, dans chaîne, la
première position où apparaît le 1 car la chaine
commence à l’indice 0
caractère mentionné.
qui est la lettre b
Procède comme strchr, mais en
strrchr ( chaîne, cherchant dans la chaîne à partir
strrchr (“bonjour”,’o’);
caractère ) de la fin. Elle fournit donc la
4
dernière occurrence du caractère
mentionné.
strstr ( chaîne, sous- recherche, dans chaîne, la strstr
chaîne ) première occurrence complète de (“bonjour”,”jour”);
la sous-chaîne mentionnée retourne 3

p. 104
Mheni & SGarbouje

atoi ( chaîne ) Convertit la chaine en nombre de


n = atoi (“1234”) ;
type int.
atol ( chaîne ) Convertit la chaine en nombre de
l = atol (ch) ;
type long.
atof ( chaîne ) Convertit la chaine en nombre de
x = atof (“12.543”) ;
type double.

V. Exercices d'application :
Exercice 1 :

Ecrire un algorithme (et le programme C ) qui saisit au


clavier 3 chaînes de caractères puis affiche le mot le plus
long.

Exercice 2 :

Une chaîne de caractère est dite palindrome si elle est


symétrique et donc se lit de la même manière de gauche à
droite et vice versa. Exp : radar, anna.

Ecrire une procédure (en algorithmique et en programmation


C) qui affiche si une chaine donnée en paramètre est un
palindrome ou pas.

Exercice 3 :

Soient 3 mots, écrire un algorithme (et le programme C) qui


les saisit au clavier puis affiche la chaîne de caractère ph
obtenue par concaténation de tous les mots.

p. 105
Mheni & SGarbouje

Exercice 4 :

Ecrire une fonction (en algorithmique et en programmation


C) qui calcule le nombre d’occurrence d'une lettre donnée.

Exercice 5 :

Ecrire une procédure (en algorithmique et en programmation


C) qui saisit une chaîne formée uniquement par des chiffres
(entre 0 et 9).

Exercice 6 :

Ecrire une procédure (en algorithmique et en programmation


C) qui affiche une chaine obtenue en insérant un mot dans un
autre par alternance de la façon suivante : un caractère du 1er
mot suivi d’un caractère du 2ème et ainsi de suite.

Exp : 1er mot : pamplemousse


2ème mot : fruit
3ème mot : pfarmupiltemousse

Exercice 7 :

Soit une chaîne de caractères composée de lettres et chiffres.


Ecrire une procédure (en algorithmique et en programmation
C) qui permet d’afficher les nombres obtenus en extrayant les
chiffres de la chaîne, une fois de gauche à droite et une autre
de droite à gauche.

p. 106
Mheni & SGarbouje

Exp : ch = "3hg5f80nb9" N1 = 35809 et N2 = 90853

V. Correction
Exercice 1 :

Algorithme MotPlusLong Programme MotPlusLong.c


Variables #include <stdio.h>
ch1,ch2,ch3:chaine #include <string.h>
Début main()
Ecrire ("Saisir la première {
chaine :") char ch1[20],ch2[20],ch3[20];
Lire (ch1) printf ("Saisir la première
Ecrire ("Saisir la chaine :");
deuxième chaine :") scanf ("%s",ch1);
Lire (ch2) printf ("Saisir la deuxième
Ecrire ("Saisir la chaine :");
troisième chaine :") scanf ("%s",ch2);
Lire (ch3) printf ("Saisir la troisième
Si (long(ch1)>long(ch2) chaine :");
et long(ch1)>long(ch3)) scanf ("%s",ch3);
alors if (strlen(ch1)>strlen(ch2)
Ecrire ("Mot plus long = && strlen(ch1)>strlen(ch3))
",ch1) printf ("Mot plus long =
FinSi %s",ch1);
Si (long(ch2)>long(ch3) et if (strlen(ch3)>strlen(ch1)
long(ch2)>long(ch1)) alors && strlen(ch3)>strlen(ch2))
Ecrire ("Mot plus long = printf ("Mot plus long =
",ch2) %s",ch3);
FinSi if (strlen(ch2)>strlen(ch3)
Si (long(ch3)>long(ch1) et && strlen(ch2)>strlen(ch1))
long(ch3)>long(ch2)) alors printf ("Mot plus long =
Ecrire ("Mot plus long %s",ch2);
=",ch3) }

p. 107
Mheni & SGarbouje

FinSi
Fin

Exercice 2 :

Procédure Palindrome Programme Palindrome.c


(mot: chaine) #include <stdio.h>
Variables #include <string.h>
i,L : entier void palindrome (char mot[20])
Début {
L←Long(mot) int i=0, L;
i←1
Tant que ((i<= l div L=strlen(mot);
2) et mot[i]=mot[L-i- while(i<l/2&&mot[i]==mot[L-i-1])
1]) faire i++;
i← i+1 if (i==L/2)
FinTQ printf ("%s est palaindrome",mot);
Si (i=(L div 2)+1) else
alors printf ("%s n'est pas
Ecrire(mot,"est palindrome",mot);
palindrome") }
Sinon
Ecrire (mot,"n'est
pas palindrome")
FinSi
Fin

p. 108
Mheni & SGarbouje

Exercice 3 :

Algorithme ConcatChaine Programme ConcatChaine.c


Variables #include <stdio.h>
ch1,ch2,ch3:chaine Début #include <string.h>
Ecrire ("Saisir la première
chaine :") main()
Lire (ch1) {char ch1[20],ch2[20],ch3[20];
Ecrire ("Saisir la deuxième
chaine :") printf ("Saisir la première
Lire (ch2) chaine :");
Ecrire ("Saisir la troisième scanf ("%s",ch1);
chaine :") printf ("Saisir la deuxième
Lire (ch3) chaine :");
ch1←ch1+ch2 scanf ("%s",ch2);
ch1←ch1+ch3 printf ("Saisir la troisième
Ecrire ("Mot obtenu =", ch1) chaine :");
Fin scanf ("%s",ch3);
strcat(ch1,ch2);
strcat(ch1,ch3);
printf ("Mot obtenu = %s",
ch1);
}
Exercice 4 :

Fonction occurence (ch : Programme occurrence.c


chaine, c : caractère) : entier #include <stdio.h>
Variables #include <string.h>
i, nb : entier int occurence(char ch*, char c)
Début {
nb←0 int i,nb=0;
Pour i de 0 à Long(ch)-1 for (i=0;i<strlen(ch);i++)
faire if (ch[i]==c)

p. 109
Mheni & SGarbouje

Si (ch[i]=c) alors nb++;


nb←nb+1 return(nb);
FinSi }
FinPour
occurence ←(nb)
Fin

p. 110
Mheni & SGarbouje

Exercice 5 :

Procédure numérique (var Programme numérique.c


ch: chaine) #include <stdio.h>
Variables #include <string.h>
i, nb : entier void numerique (char *ch)
Début { int i, nb;
répéter do
Ecrire ("Saisir une {
chaine :") printf ("Saisir une chaine :");
Lire (ch) scanf ("%s",ch);
nb←0 nb=0;
Pour i de 0 à Long(ch)-1 for (i=0 ; i<strlen(ch) ; i++)
faire if (ch[i]>= '0' && ch[i]<=
Si (ch[i]>= '0' ET ch[i]<= '9') '9')
alors nb++;
nb←nb+1; } while (nb<strlen(ch));
FinSi }
FinPour
jusqu'à (nb=long(ch))
Fin
Exercice 6 :

Procédure alternance (ch1: Programme alternance.c


chaine, ch2:chaine) #include <stdio.h>
Variables #include <string.h>
i,j,L1,L2 : entier void alternance (char ch1[20],
s:chaine char ch2[20])
Début { char s[20];
L1←long(ch1) int i,j,L1,L2;
L2←long(ch2) L1 = strlen(ch1);
j←0 L2 = strlen(ch2);
Si (L1>L2) alors j = -1;

p. 111
Mheni & SGarbouje

Pour i de 0 à L2-1 faire if (L1>L2) {


s[j+1] ←ch1[i] for (i=0;i<L2;i++) {
s[j+2] ←ch2[i] s[j+1]=ch1[i];
j←j+2 s[j+2]=ch2[i];
FinPour j=j+2;
Pour i de L2 à L1-1 faire }
j←j+1 for (i=L2;i<L1;i++) {
s[j] ←ch1[i] j++;
FinPour s[j]=ch1[i];
Sinon }}
Pour i de 0 à L1-1 faire else {
s[j+1] ←ch1[i] for (i=0;i<l1;i++) {
s[j+2] ←ch2[i] s[j+1]=ch1[i];
j←j+2 s[j+2]=ch2[i];
Fin Pour j=j+2;
Pour i de L1 à L2-1 faire }
j←j+1 for (i=L1;i<L2;i++) {
s[j] ←ch2[i] j++;
FinPour s[j]=ch2[i];
FinSi }
Ecrire ("Résultat :",s) }
Fin printf ("Résultat : %s",s);
}
Exercice 7 :

Procédure extraire (var ch: Programme extraire.c


chaine) #include <stdio.h>
Variables #include <string.h>
i,j,n1,n2 : entier void extraire (char ch[20])
s:chaine { char s[20];
Début int i,j,n1,n2;
j←0 j=-1;
Pour i de 1 à long(ch) faire for (i=0;i<strlen(ch);i++)

p. 112
Mheni & SGarbouje

Si (ch[i]>= '0' ET ch[i]<= '9') alors if (ch[i]>= '0' && ch[i]<= '9')
j←j+1; {
s[j] ← ch[i] j++;
FinSi s[j]=ch[i];
FinPour }
convch(n1,ch) n1=atoi(s);
j←0 j=-1;
Pour i de long(ch) à 1 faire for (i=strlen(ch)-1;i>-1;i--)
Si (ch[i]>= '0' ET ch[i]<= '9') if (ch[i]>= '0' && ch[i]<= '9')
alors {
j←j+1; j++;
s[j] ← ch[i] s[j]=ch[i];
FinSi }
FinPour n2=atoi(s);
convch(n1,ch) printf("n1=%d et
Ecrire ("n1 =",n1, " et n2 = ",n2) n2=%d",n1,n2);}
Fin

p. 113
Mheni & SGarbouje

Les Tableaux
I. Introduction
Supposons qu'on nous demande de saisir les notes de
20 étudiants, puis de chercher la meilleure note, afficher les
notes supérieures à 10 et calculer la moyenne de toutes les
notes. Dans ce cas, il faut utiliser une vingtaine de variables
nommées de x1, à x20 afin de manipuler toutes ces valeurs

L'idée des tableaux est d'attribuer un seul nom à cette


vingtaine de valeurs, Tnotes, par exemple. Dans cette
variable, on enregistre toutes les notes et on peut accéder à
n'importe quelle note par le même nom Tnotes, en donnant
l'indice de cette note (une case dans le tableau). Les indices
des cases commencent (obligatoirement) de 0 et finissent à
nombre des notes moins 1 .La note du premier étudiant est
donc Tnotes[0], celle du 15ème est enregistrée dans Tnotes[14]
et le dernier dans Tnotes[19].
Si nous voulons, maintenant, enregistrer les trois
notes pour les 20 étudiants; note du test, note du DS et note
de l'examen afin de calculer les moyennes de la matière.
Dans ce cas, on utilise un autre type de tableau contenant 20
cases en longueur pour les étudiants, et 3 en largeur pour les
trois types de notes. Ce type de tableaux est appelé matrice.
Dans ce cas il faut fournir le nombre de lignes et de colonnes
commençant toujours de 0 à nombre moins 1.On peut accéder
à la note de DS(deuxième ligne) du 8èmeétudiant (8ème

p. 114
Mheni & SGarbouje

colonne) par Tnotes[1][7](puisqu'on commence toujours de 0


donc on doit soustraire 1).
En résumé : On distingue seulement deux types de
tableaux; les tableaux unidimensionnels ou vecteurs (une
seule ligne), dans lequel on enregistre des valeurs accessibles
directement par leurs indices T[i]. Le deuxième type est le
tableau bidimensionnel ou matrice composé de lignes et de
colonnes, contenant aussi des valeurs et chaque une est
accessible par l'indice de la ligne i et de la colonne j noté
T[i][j]. Les indices sont de type entier.

II. Tableau unidimensionnel


1. Syntaxe de déclaration

En algorithmique En langage C

Types
Nom_type_tableau=Tableau[Ind0 Typedef
Syntaxe …Indn-1] de <type> <type>NomTab[nombre
Variables: d'élements]
nom_tableau: Nom_type_Tableau
Typedef float TabNote[20]
Types:
Void main(){
Exemple TabNote: Tableau[0..19] de réels
..
Variables:
TabNote Tab1,Tab2;
Tab1,Tab2: TabNote
..}
Remarque:

Pour accéder à l'ième valeur du tableau on place l'indice


(le numéro) de la case entre crochets devant le nom du
tableau Tab1[i].

p. 115
Mheni & SGarbouje

Les indices doivent être de type entier. Commencent


obligatoirement de 0 et finissent à un nombre entier positif
choisit.
2. Remplissage d'un tableau unidimensionnel
Le remplissage d'un tableau se fait en utilisant une
boucle comme dans la procédure suivante:

En algorithmique En langage C
Procédure remplir (Var T : Tab, n : void remplir (int T[], int n)
entier) {
Variables int i ;
i : Entier for (i=0 ;i<n ;i++){
Début printf ("Entrer un
Pour i de 0 à n-1 Faire entier :") ;
Ecrire(”Entrer un scanf ("%i",&T[i]) ;}
entier : ”) }
Lire(T[i])
FinPour
Fin

3. Affichage d'un tableau unidimensionnel


L'affichage des éléments d'un tableau se fait en
parcourant le tableau comme dans la procédure suivante:
En algorithmique En langage C
Procédure afficher(T : Tab, void afficher (int T[], int n)
n :entier) {
Variables int i ;
i : Entier for (i=0 ;i<n ;i++)
Début printf (" | ",T[i]) ;
Pour i de 0 à n-1 Faire }
Ecrire(T[i])

p. 116
Mheni & SGarbouje

FinPour
Fin

4. Recherche d'un élément dans un tableau


a. Recherche classique
La recherche d'un élément dans un tableau se fait par
la procédure suivante:
En algorithmique En langage C
Procédure Recherche(T : Tab, void Recherche (float T[], int n,
n :entier , x : Réel) float x)
Variables {int i =0;
i : Entier while (T[i]!=x && i <=n)
Début
i= i + 1 ;
i← 0
if (T[i] == x)
TantQue (T[i] ≠ x) et (i ≤ n)
i← i + 1
printf (”\n Indice = ”, i) ;
FinTQ else
Si (T[i] = x) Alors printf(”Elément
Ecrire(”Indice = ”,i) introuvable…”) ;}
Sinon
Ecrire(”Elément introuvable…”)
FinSi
Fin

Cette boucle continue à parcourir le tableau tant qu’on n’a


pas trouvé l’élément et qu’on n’a pas atteint la dernière case.

b. Recherche dichotomique
Cette méthode s’applique sur les tableaux triés à
valeurs uniques. La recherche dichotomique consiste à
découper successivement la structure du tableau en deux, à

p. 117
Mheni & SGarbouje

chaque fois, on garde la moitié susceptible de contenir la


valeur recherchée (le tableau est supposé être trié dans le sens
croissant). On reproduit le même processus jusqu’à trouver
l’élément ou jusqu’à ce que l’intervalle ne contient qu’une
case.

Illustration de la recherche de la valeur x=1.

Ind 0 1 2 3 4 5 6 7
Tab 1 3 5 6 7 8 9 11

On effectue une comparaison entre l’élément du milieu de la


table d’indice 7 div 2 = 3 et l’élément du milieu, c'est-à-dire
Tab[3]=6.

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

Cet élément est plus grand que x=1, on ne va garder que la


partie gauche de la table [0..2], et on reproduit le même
processus : identification du milieu 3 div 2 = 1, puis
comparaison de x et Tab[1].

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

Là aussi, l’élément recherché étant plus petit, on ne va garder


que la partie gauche de la table [0..0], et on reproduit la
recherche 0div 2 = 0, puis on vérifie Tab[0]

p. 118
Mheni & SGarbouje

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

On a trouvé l’élément recherché à la position 0.

Illustration de la recherche de la valeur x= 10.

Identification du milieu : 7 div 2 = 3, puis on vérifie Tab[3] et


x=10.

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

La valeur recherchée est plus grande, on poursuit la recherche


dans la partie droite de la table [4..7]. Identification du
milieu : (7+ 4) div 2 = 5, puis on vérifie Tab[5] et x=10.

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

La valeur recherchée est plus grande, on poursuit la recherche


dans la partie droite de la table [6..7]. Identification du
milieu : (6+ 7) div 2 = 6, puis on vérifie Tab[6] et x=10.

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

La valeur recherchée est plus grande, on poursuit la recherche


dans la partie droite de la table[7..7]. Nouveau milieu : (7 +
7) div 2 = 7, puis on vérifie Tab[7] et x=10.

p. 119
Mheni & SGarbouje

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

Le tableau où l'on doit faire la recherche étant une seule case


qui ne contient pas la valeur recherchée, donc celle-ci
n’existe pas dans la table.

En algorithmique En langage C
Procédure Rechdicho(T : Tab, void RechDicho(int T[], int n, int
n :entier, x : entier) x)
Variables {
prm, mlu, drn : Entier int prm=0, mlu, drn=n-1 ;
trouve : Booléen int trouve=1 ;
Début do {
prm← 0 mlu= (prm + drn) % 2 ;
drn ← n-1 if (x < T[mlu])
trouve← Faux drn= mlu – 1 ;
Répéter else
mlu← (prm + drn) div 2 if (x > T[mlu])
Si (x < T[mlu]) Alors prm= mlu + 1 ;
drn← mlu – 1 else
Sinon trouve=1 ;
Si (x > T[mlu]) Alors } while (trouve==0 || prm <
prm← mlu + 1 drn) ;
Sinon Si (trouve == 1)
trouve← Vrai printf (”Indice = ”,mlu) ;
FinSi else
Jusqu'à (trouve = Vrai) ou (prm > printf (”Elément
drn) introuvable”) ;

p. 120
Mheni & SGarbouje

Si (trouve = Vrai) Alors }


Ecrire(”Indice = ”,mlu)
Sinon
Ecrire(”Elément
introuvable”)
FinSi
Fin

p. 121
Mheni & SGarbouje

5. Les algorithmes de tri


En programmation, il existe divers algorithmes de tri, on peut
citer:

- Algorithme de tri à bulle


- Algorithme de tri par sélection,…
a. Algorithme de tri à bulle
On répète la permutation de deux valeurs successives
mal-ordonnées (si T[i]>T[i+1]) dans le tableau, jusqu'à avoir
un tableau trié (on fait le parcours pour s’en assurer).

En algorithmique En langage C
Procédure Echange(Var a,b void Echange (int *a, int *b)
: entier) {
int aux = a ;
Variables: a=b;
Aux : entier b = aux ;
Début }
Aux←a void Tri_Bulle (int T[])
a←b {
b←Aux int i, x ;
Fin int permut ;
do{
Procédure Tri_Bulle (Var T permut =0;
: Tab) for (i=0 ; i<n-1 ; i++)
Variables if (T[i] > T[i+1])
i, x : Entier {

p. 122
Mheni & SGarbouje

permut : Booléen
Début Echange(T[i],T[i+1]) ;
Répéter permut = 1 ;
permut← Faux }
Pour i de 0 à (n-2) Faire } while (permut == 0) ;
Si (T[i] > T[i+1]) Alors }
Echange(T[i],T[i+1])
permut← Vrai
FinSi
FinPour
Jusqu'à (permut =
Faux)
Fin

b. Tri par sélection

C'est le plus direct des algorithmes de tri, il permet de


chercher la valeur minimale dans le tableau, la placer dans la
case numéro 0, puis considérer le reste du tableau (on
écartant la case numéro 0) et on répète la procédure avec le
reste du tableau et ainsi de suite jusqu'à la dernière case.

Exemple

6 2 3 1 4 7

1 2 3 6 4 7

1 2 3 6 4 7

p. 123
Mheni & SGarbouje

1 2 3 6 4 7

1 2 3 4 6 7

1 2 3 4 6 7

En algorithmique En langage C
Procédure Tri_Selection(Var T : void Tri_Selection (int T[])
Tab) {
Variables int i, j, x, indmin ;
i, j, x, indmin : Entier for (i=0 ; i<n-1 ; i++)
Début { indmin = i ;
Pour i de 0à (n-2) Faire for (j=i ; j<n ; j++)
indmin ← i if (T[j] < T[indmin])
Pour j de (i+1) à n-1 Faire indmin = j ;
Si (T[j] < T[indmin]) Echange(T[i],
Alors T[indmin]) ;
indmin ← j }
FinSi }
FinPour
Echange(T[i], T[indmin])
FinPour
Fin

III. Tableau Bidimensionnel


Les tableaux bidimensionnels sont des matrices formées de
lignes et de colonnes. Plus précisément, chaque ligne est un

m colonnes (j ∈ [1, m])

p. 124
Mheni & SGarbouje

tableau unidimensionnel. Pour accéder à une valeur, on doit


indiquer les deux indices de la ligne et de colonne.

n lignes (i ∈ [1, n])

On commence toujours par l'indice de la ligne puis


l'indice de la colonne. Ainsi T[3,5] désigne l'élément à la 3ème
ligne et 5ème colonne.

a. Déclaration d'un Tableau bidimensionnel:

En algorithmique En langage C
Types
Mat = tableau [1..n][1..m] de typedef<type> Mat
type_valeurs [nbLigne][nbColonne] ;
Syntaxe Variables: void main(){
..
T: Mat Mat T;

typedef float Mat[5][20]


Types
void main(){
Mat = tableau [0..4][ 0..19] de réels
Exemple ..
Variables:
Mat M1,M2;
M1, M2 : Mat
..}
b. Remplissage d'un tableau bidimensionnel
En algorithmique En langage C
Procédure remplir(Var M : Mat) void remplir(int M[][])

p. 125
Mheni & SGarbouje

Variables {
i, j : Entier int i, j ;
Début for (i=0 ; i<n ; i++)
Pour i de 0 à n-1 Faire for (j=0 ; j<m ; j++)
Pour j de 0 à m-1 Faire printf (”Entrer un entier :”) ;
Ecrire(”Entrer un entier :”) scanf ("%d",&M[i][j]) ;
Lire(M[i][j]) }
FinPour
FinPour
Fin

Exercice:

Ecrire un algorithme (et le programme C) qui permet de


mettre dans un tableau T2, le transposé d'un tableau
bidimensionnel T1 (N.B: les deux tableaux sont supposés être
de même dimension).

Solution:

En algorithmique En langage C
Procédure Transpose(T1 : Mat, void Transpose (int T1[][],int T2[][])
Var T2: Mat) {
Variables int i, j ;
i, j : Entier for (i=0 ; i<n ; i++)
Début for (j=0 ; j<m ; j++)
Pour i de 1 à n Faire T2[i][j] = Τ1[j][i];
Pour j de (i+1) à n Faire }
T2[i][j] ← Τ1[j][i]
FinPour

p. 126
Mheni & SGarbouje

FinPour
Fin

Exercice:
Ecrire un algorithme (et le programme C) qui permet de
calculer le produit de deux tableaux bidimensionnels.
Solution
Soient T1 et T2 deux tableaux bidimensionnels ayant
respectivement n lignes et m colonnes, et m lignes et p
colonnes (pour effectuer l'opération de multiplication de deux
matrices il faut que le nombre de colonnes de la première soit
égal au nombre de lignes de la deuxième): la matrice résultat
est une matrice carrée de dimension m (le nombre commun)
m
T3[i, j] = ∑ T 1[i, k ] * T 2[ k , j ]
k =1

(avec i ∈ [0, n-1] et j ∈ [0, p-1])

p. 127
Mheni & SGarbouje

En algorithmique En langage C

p. 128
Mheni & SGarbouje

Procédure ProdMat(T1 : Mat1; T2 : void ProdMat (int T1[][], int T2[][],


Mat2; Var T3 : Mat3) int T3[][])
{
Variables int i, j, k ;
i, j, k : Entier for (i=0 ; i<n ; i++)
Début for (j=0 ; j<p ; j++)
Pour i de 1 à n Faire { T3[i,j] = 0;
Pour j de 1 à p Faire for (k=0 ; k<m ; k++)
T3[i][j] ← 0
Pour k de 1 à m Faire T3[i][j]=T3[i][j]+T1[i][k]*T2[k][j]
}
T3[i][j]←T3[i][j]+T1[i][k]*T2[k][j] }
FinPour
FinPour
FinPour
Fin

IV. Exercices d'application

Exercice 1 :
Un ingénieur en météo a enregistré les températures
maximales et minimales dans la région de Nabeul pendant les
12 mois de l’année 2010. Il aimerait connaître la température
moyenne pour chaque mois.
Ecrire un algorithme (et le programme C) qui saisit au clavier
les deux tableaux Tmax et Tmin puis remplit le tableau Tmoy
à partir des 2 tableaux précédents.

Exercice 2 :

p. 129
Mheni & SGarbouje

Une société agroalimentaire a demandé l’avis de 100


consommateurs à propos de l’un de ses produits sur le
marché (ils l’aiment ou non). Elle a collecté les réponses dans
un tableau et désire déterminer le pourcentage de ceux qui
aiment ce produit.
Ecrire une procédure qui permet de saisir le tableau des
réponses par l’utilisateur puis calcule et affiche le
pourcentage voulu.

Exercice 3 :
Soit un tableau de 10 entiers, écrire une procédure qui le
remplit au clavier de la manière suivante :
Les cases d’indice paire (2,4,6,…) doivent contenir des
valeurs impaires et vice-versa.

Exercice 4 :
24 est un nombre entier divisible par son chiffre de dizaine 2.
Ecrire une procédure qui remplit un tableau par tous les
nombres à deux chiffres qui vérifient cette propriété puis
l’affiche.

Exercice 5
Soit M1 et M2 deux matrices à n lignes et m colonnes.

Ecrire une procédure qui permet de calculer la somme de deux


matrice: M3=M1+M2.

Example:

p. 130
Mheni & SGarbouje

Ont veut écrire une procédure qui calcule les éléments de la


matrice M3=M1+M2.

1 2 3 2 5 3 3 7 6
M1 4 5 6 M2 3 0 1 M3 7 5 7

Données résultat

Exercice 6 : Produit de deux matrices


Soit M1 une matrice ayant n lignes et m colonnes
M2 une matrice ayant m lignes et p colonnes
On veut écrire une procédure qui calcule les éléments de la matrice
carrée M3=M1*M2.
Notons d’abord que le nombre de colonnes de M1 doit être égal au
nombre de lignes de M2.
Le produit M3=M1*M2 est défini comme une matrice ayant n
lignes et p colonnes et dont les éléments sont calculés par la
formule :
M3i,j= M1i,1 * M21,j + M1i,2 * M22,j +……+ M1i,m * M2m,j

m
Soit M 3 i , j = ∑ M1
k =1
i,k * M 2k, j

Où M1i,k , M2k,j et M3i,j sont respectivement les éléments des


matrices M1, M2 et M3.

Exemple :

p. 131
Mheni & SGarbouje

1 2 3 2 1 11 13
M1 4 0 5 M2 3 0 donnent M3= 13 24
1 4

Exercice 7 : Transposé d’une matrice carrée

Une matrice carrée est une matrice à n lignes et n colonnes.

L’opération de transposition consiste à inverser les lignes et les


colonnes en effectuant une symétrie par rapport à la diagonale
principale de la matrice.

On veut écrire une procédure qui calcule la transposition d’une


matrice carrée M.

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

Exercice 8
L’objectif de cet exercice est d’avoir une solution itérative pour la
concaténation de deux matrices A et B tel que les éléments de A
sont donnés par l’utilisateur et les éléments de B sont calculés par
1
la formule B [i, j ] = avec i∈[1,N] et j∈[1,N].
i + j −1

p. 132
Mheni & SGarbouje

Soit C le tableau qu’on veut construire à partir de A et B tel que :


C=[A B]

Exemple : Pour N=2 on a

Travail Demandé
On suppose que la constante Nmax et les Types TAB_1 et TAB_2
ont été déjà déclarés par :

CONST Nmax = 10

TYPE TAB_1 = tableau [0..Nmax-1][ 0..Nmax-1] de


réels

TAB_2 = tableau [1..Nmax][ 1..2*Nmax] de réels


1. Ecrire une procédure itérative saisie (Var N : Entier) qui
permet la saisie de la taille N avec 2 ≤ N ≤ Nmax.

2. Une procédure itérative remplissage (Var A : TAB_1 ; N :


Entier) qui permet le remplissage du tableau A.

p. 133
Mheni & SGarbouje

3. Une procédure itérative création (Var B : TAB_1 ; N :


Entier) qui permet la création du tableau B sachant que
1
B [ i, j ] = avec i∈[1,N] et j∈[1,N].
i + j −1
4. Une procédure itérative construction (Var C : TAB_2 ; A,
B : TAB_1 ; N : Entier) qui permet la construction du tableau
C par la concaténation de A et B.

5. Une procédure itérative affichage (C : TAB_2 ; N : Entier)


qui permet l’affichage des éléments du tableau C.

Exercice 9

Les points cols d’une matrice M sont les éléments du M qui sont
maximum sur leur ligne et minimum sur leur colonne, ou minimum
sur leur ligne et maximum sur leur colonne.

Méthode pour chercher les points cols :


Pour qu’un élément se trouvant à la ligne L et à la colonne C soit
un point col, il faut et il suffit que :
- le maximum de la ligne L soit égale au minimum de la
colonne C et égale à la valeur M[L][C], ou que :
- le minimum de la ligne L soit égale au maximum de la
colonne C et égal à la valeur M[L][C].
Ainsi pour chaque élément M[L][C] on vérifie l’une des deux
conditions indiquées ci-dessous..

p. 134
Mheni & SGarbouje

Travail demandé :
On utilisera la constante Max et le type MAT définis par :

CONSTANTE MAX=100

TYPE MAT = TABLEAU [0..MAX-1,0..MAX-1] REEL

1) Ecrire une procédure LECTURE (VAR NBL, NBC : entier)


qui permet de lire le nombre de lignes et le nombre de colonnes
avec (10 ≤ NBL ≤ MAX et 10 ≤ NBC ≤ MAX).
2) Ecrire une procédure REMPLIR (VAR M : MAT ; NBL,
NBC : entier) qui permet de remplir une matrice M par NBL
lignes et NBC colonnes.
3) Ecrire une fonction MAX_LIGNE (M : MAT ; L, NBC :
entier) : réel, qui permet de retourner le maximum de la ligne L.
4) Ecrire une fonction MIN_LIGNE (M : MAT ; L, NBC :
entier) : réel, qui permet de retourner le minimum de la ligne L.
NBC : le nombre de colonnes.

5) Ecrire une fonction MAX_COLONNE (M : MAT ; C, NBL :


entier) : réel, qui permet de retourner le maximum de la colonne
C.
6) Ecrire une fonction MIN_ COLONNE (M : MAT ; C, NBL :
entier) : réel, qui permet de retourner le minimum de la colonne
C.

p. 135
Mheni & SGarbouje

NBC : le nombre de lignes.

7) Ecrire une fonction VERIF_POINTCOL (M : MAT, NBL,


NBC, L, C : entier) : booléen, qui permet de vérifier si M[L][C]
est un point col ou non.

8) Ecrire un algorithme POINTS_COLS qui permet de :

- Saisir deux entiers NBL et NBC (10 ≤ NBL ≤ MAX et


10 ≤ NBC ≤ MAX),
- Remplir la matrice M de dimension (NBL x NBC) par des
réels (NBL : nombre de lignes, NBC : nombre de
colonnes),
- Utiliser la fonction VERIF_POINTCOL pour chercher et
afficher tous les points cols du matrice M.

V. Correction
Exercice 1

Algorithme Température Programme temperature.c


Variables #include <stdio.h>
Tmin, Tmax, Tmoy : tableau main()
[0..11] réel {
i : entier int i;
Début float Tmax[12], Tmin[12],
Pour i de 0 à 11 faire Tmoy[12];
Ecrire ("Entrer la température for (i=0;i<12;i++) {
maximale :") printf ("Entrer la température
Lire (Tmax[i]) maximale :") ;
Ecrire ("Entrer la température scanf ("%f",&Tmax[i]);

p. 136
Mheni & SGarbouje

minimale :") printf ("Entrer la température


Lire (Tmin[i]) minimale :") ;
Tmoy[i] ← (Tmax[i] + Tmin[i])/2 scanf ("%f",&Tmin[i]);
FinPour Tmoy[i]= (Tmax[i] + Tmin[i])/2;
Fin }
}

Exercice 2

Types: void pourcentage (int t[])


Tab_booleen: tableau[0..99] de {
booléen int i; float p=0;
for (i=0;i<100;i++) {
Procédure Pourcentage (var T : printf ("Entrer la réponse du
tab_booleen) consommateur [0/1] :") ;
Variables scanf ("%d",&t[i]);
i : entier if (t[i])
p : réel p=p+1/100;
Début }
p←0 printf ("Le pourcentage des
Pour i de 0 à 99 faire consommateurs qui aiment le
Ecrire ("Entrer la réponse du produit est %f ", p) ;
consommateur [0/1] :") }
Lire (T[i])
Si (T[i]=VRAI) alors
p ← p+1/100
FinSi
FinPour
Ecrire ("Le pourcentage des
consommateurs qui aiment le
produit est ", p) ;

p. 137
Mheni & SGarbouje

Fin
Exercice 3

Types void paireImpaire (int t[])


Tab_entier: tableau[0..9]de entier {
Procédure PaireImpaire (var T : int i;
tab_entier) for (i=0;i<10;++) {
Variables if (i%2=0)
i : entier do {
Début printf ("Entrer un nombre impair");
Pour i de 0 à 9 faire scanf ("%d",&t[i]);}
Si (i mod 2=0) alors while (t[i] % 2 == 0);
Répéter else
Ecrire ("Entrer un nombre do {
impair") printf ("Entrer un nombre pair");
Lire (T[i]) scanf ("%d",&t[i]);
Jusqu’à (T[i] mod 2 = 1) } while (t[i] % 2== 1);
Sinon }
Répéter }
Ecrire ("Entrer un nombre
pair")
Lire (T[i])
Jusqu’à (T[i] mod 2 = 0)
FinSi
FinPour
Fin
Exercice 4

Procédure propriété (var T : void propriete (int t[], int *n)


tabentier, var n:entier) {

p. 138
Mheni & SGarbouje

Variables int d,i;


d, i : entier
Début *n = 0;
n←0 for (i=1;i<100;i++)
Pour i de 0 à 99 faire {
d ← i div 10 d = i/10;
Si (i mod d=0) alors if (i % d == 0)
n ← n+1 {
T[n] ← i t[n] = i;
FinSi *n ++;
FinPour }}
Fin }
Exercice 5 :

Constantes void somme (int m1[][], int m2[][],


N=50 int m3[][], int n, int m)
M=50 {
Types int i,j;
mat: tableau [0..N][0..M]de entier
Procédure somme (m1, m2 : for (i=0;i<n;i++)
mat , var m3 :mat) for (j=0;j<m;j++)
Variables m3[i][j] = m1[i][j]+ m2[i][j];
i , j:entier }
Début
Pour i de 0 à N-1 faire
Pour j de 0 à M-1 faire
m3[i][j]← m1[i][j]+ m2[i][j]
FinPour
FinPour
Fin

p. 139
Mheni & SGarbouje

Exercice 6

M1 est une matrice ayant N lignes et M colonnes


M2 est une matrice ayant M lignes et P colonnes
M3 est une matrice ayant N lignes et P colonnes
Constantes void produit (int m1[][], int m2[][],
N=20 int m3[][], int n, int m, int p)
M=30 {
P=35 int i,j,k;
Types for (i=0;i<n;i++)
mat1: tableau [0..N][0..M]de for (j=0;j<p;j++)
entier { m3[i][j]=0;
mat2: tableau [0..M][0..P]de for (k=0;k<m;k++)
entier m3[i][j] = m3[i][j] + m1[i][k]*
mat3: tableau [0..N][0..P]de entier m2[k][j];
}
Procédure produit (m1:mat1, m2: }
mat2,var m3 :mat3)
Variables
i , j,k:entier
Début
Pour i de 0 à N-1 faire
Pour j de 0 à P-1 faire
M3[i,j]←0
Pour k de 0 à M-1 faire
M3[i][j]← M3[i][j]+
M1[i][k]*M2[k][j]
FinPour
FinPour
FinPour

p. 140
Mheni & SGarbouje

Fin
Exercice 7

Constantes void transpose (int m[][], int


N=50 tm[][], int n)
Types {
mat: tableau [0..N][0..N]de entier int i,j;

Procédure transpose (m:mat ,var tm :mat) for (i=0;i<n;i++)


Var iables for (j=0;j<n;j++)
i , j:entier tm[i][j] = m[j][i];
Début }
Pour i de 0 à N-1 faire
Pour j de 0 à N-1 faire
TM [i][j]← M[j][i]
FinPour
FinPour
Fin
Exercice 8
1)
Procédure saisie (var N: entier, void saisie(int *N, int NMAX)
NMAX:entier) {
Début do {
Répéter printf ("Entrer un entier entre 2 et
Ecrire ("donner un entier N, avec %d :", NMAX);
2=<N<=", Nmax) scanf(%d",N);
Lire (N) } while (N>NMAX || N<2);
Jusqu'à (N>=2) et (N<=Nmax) }
Fin

p. 141
Mheni & SGarbouje

2)

Procédure remplissage (var A : void remplissage (float A[][], int


TAB_1 ; N: entier) n)
Var iables { int i,j;
i , j:entier
Début for (i=0;i<n;i++)
Pour i de 0 à N-1 faire for (j=0;j<n;j++)
Pour j de 0 à N-1 faire {
Ecrire ("donner A[", i,",",j,"]") printf ("Entrer un réel :");
Lire (A [i, j]) scanf (%f",&A[i][j]);
FinPour }
FinPour }
Fin

3)

Procédure création (var B : void creation (float B[][], int N)


TAB_1 ; N: entier) {
Variables int i,j;
i , j:entier for (i=0;i<N;i++)
Début for (j=0;j<N;j++)
Pour i de 0 à N-1 faire t[i][j]=1/(i+j+1);
Pour j de 0 à N-1 faire }
1
B[i ][ j ] ←
i + j −1
FinPour
FinPour
Fin
4)

p. 142
Mheni & SGarbouje

Procédure construction (var C : void construction (float C[][],


TAB_2 ; A, B : TAB_1; N: entier) float A[][], float B[][], int N)
Variables { int i,j;
i , j:entier
Début for (i=0;i<N;i++)
Pour i de 0 à N-1 faire for (j=0;j<N;j++)
Pour j de 0 à N-1 faire C[i][j]= A[i][j];
C [i][ j]←A[i][ j] C[i][j+N]=B[i][j];
C [i][ j+N]←B[i][ j] }
FinPour
FinPour
Fin

5)

Procédure affiche (var C : TAB_2 ; void affiche (float C [][], int


N: entier) N)
Variables {
i , j:entier int i,j;
Début for (i=0;i<n;i++)
Pour i de 0 à N-1 faire { for (j=0;j<2*N;j++)
Pour j de 0 à 2*N-1 faire print(" %f ",C[i][j]);
Ecrire (C [i][ j], " ") print("\n");
// sans retour à la ligne }
FinPour }
Ecrire ( )
// retour à la ligne
FinPour
Fin

p. 143
Mheni & SGarbouje

Exercice 9
1)

Procédure LECTURE (var NBL, void LECTURE(int *NBL, int


NBC: entier) *NBC)
Début {
Répéter do {
Ecrire ("donner le nombre de printf("Entrer le nombre de
lignes") lignes:");
Lire (NBL) scanf(%d",NBL);
Jusqu'à (NBL>=10) et } while (NBL>MAX ||
(NBL<=MAX) NBL<10);
Répéter do {
Ecrire ("donner le nombre de printf("Entrer le nombre de
colonnes") colonnes:");
Lire (NBC) scanf(%d",NBC);
Jusqu'à (NBC>=10) et } while (NBC>MAX ||
(NBC<=MAX) NBC<10);
Fin }

2)

Procédure REMPLIR (var void REMPLIR (float M[][], int


M : MAT, NBL:entier, NBC: NBL, int NBC)
entier) { int i,j;
Var iables
i , j:entier for (i=0;i<NBL;i++)
Début for (j=0;j<NBC;j++)
Pour i de 0 à NBL-1 faire {
Pour j de 0 à NBC-1 faire printf("Entrer un réel :");

p. 144
Mheni & SGarbouje

Ecrire ("donner un réel:") scanf(%f",&M[i][j]);


Lire (M [i][ j]) }
FinPour }
FinPour
Fin
3)

Fonction MAX_LIGNE (M : float MAX_LIGNE (float


MAT , L:entier, NBC: entier) : réel M[][], int L, int NBC)
Variables { int i;
i:entier float MAX;
MAX:réel MAX = M[L][0];
Début for (i=1;i<NBC;i++)
MAX←M[L][1] if (M[L][i]>MAX)
Pour i de 0 à NBC-1 faire MAX = M[L][i];
Si (M [L, i]>MAX) alors return (MAX);
MAX← M [L][ i] }
FinSi
FinPour
MAX_LIGNE ←(MAX )
Fin

4)

Fonction MIN_LIGNE (M : float MIN_LIGNE(float M[][], int


MAT ,L, NBC: entier) :réel L, int NBC)
Variables { int i;
i:entier float MIN;
MIN:réel MIN = M[L][0];
Début for (i=1;i<NBC;i++)

p. 145
Mheni & SGarbouje

MIN←M [L][1] if (M[L][i]<MIN)


Pour i de 1 à NBC-1 faire MIN = M[L][i];
Si (M [L][ i]<MIN) alors return (MIN);
MIN← M [L][ i] }
FinSi
FinPour
MIN_LIGNE ←MIN
Fin
5)

Fonction MAX_COLONNE float MAX_COLONNE (float


(M : MAT , C: entier, NBL: M[][], int C, int NBL)
entier) :réel { int i;
Variables float MAX;
i:entier
MAX:réel MAX = M[0][C];
Début for (i=1;i<NBL;i++)
MAX←M[1][C] if (M[i][C]>MAX)
Pour i de 1 à NBL-1 faire MAX = M[i][C];
Si (M [i][ C]>MAX) alors return (MAX);
MAX← M [i][C] }
FinSi
FinPour
MAX_COLONNE ←MAX
Fin
6)

Fonction MIN_COLONNE float MIN_COLONNE (float


(M : MAT, C, NBL: M[][], int C, int NBL)
entier) :réel { int i;

p. 146
Mheni & SGarbouje

Variables float MIN;


i:entier
MIN:réel min = M[0][C];
Début for (i=1;i<NBL;i++)
MIN←M[0][C] if (M[i][C]<MIN)
Pour i de 1 à NBL-1 faire MIN = M[i][C];
Si (M [i, C]<MIN) alors return (MIN);
MIN← M [i][ C] }
FinSi
FinPour
MIN_COLONNE ←MIN
Fin
7)

Fonction VERIF_POINTCOL int VERIF_POINTCOL


(M : MAT , NBL: entier, NBC: (float M[][], int NBL, int
entier, L: entier, C: entier) : NBC, int C), int L
booléen {
Début if ((max_ligne (M, L,
Si (((MAX_LIGNE (M, L, NBC)== MIN_COLONNE
NBC) = MIN_COLONNE (M,C, (M,C, NBL) &&
NBL)) et ( MAX_LIGNE (M, L, MAX_LIGNE (M, L,
NBC) = M[L][C]) ) Ou NBC)== M[L,C]) ||
((MIN_LIGNE (M, L, (MIN_LIGNE (M,
NBC) = MAX_COLONNE (M,C, L,NBC)==
NBL)) et ( MIN_LIGNE (M, L, MAX_COLONNE (M,C,
NBC) = M[L][C]))) NBL) && MIN_LIGNE (M,
alors L,NBC)) == M[L,C]))
VERIF_POINTCOL ←Vrai return 1;
Sinon else

p. 147
Mheni & SGarbouje

VERIF_POINTCOL← faux return 0;


FinSi }
Fin
8)

Algorithme POINTS_COLS Programme points_cols.c


Constantes
MAX=100 #include <stdio.c>
Types main ()
MAT = TABLEAU {
(1..MAX,1..MAX) REEL const int MAX=100;
Variables int NBL,NBC;
NBL, NBC: entier, M : MAT float M[MAX][MAX];
Début
LECTURE (NBL, NBC) lecture (NBL,NBC);
REMPLIR (M, NBL, NBC) remplir (M,NBL,NBC);
Ecrire ("les points cols de la printf("les points cols de la
matrice M :") matrice M:");
Pour i de 0 à NBL-1 répéter for (i=0;i<NBL;i++)
Pour j de 0 à NBC-1 for (j=0;j<NBC;j++)
répéter if
Si (VERIF_POINTCOL (verif_pointcol(m,nbl,nbc,i,j))
(M,NBL, NBC, i, j)=vrai) alors printf ("%f ",m[i][j]);
Ecrire (M [i][j]) }
FinSi
FinPour
FinPour
Fin

p. 148
Mheni & SGarbouje

Les enregistrements
I. Introduction
Jusqu'à maintenant nous utilisons 5 types de base:
réel, entier, caractère, chaines de caractère, booléen en plus
des tableaux (structure composé par plusieurs valeurs de
même type). Prenons un exemple de manipulation de n
étudiants. Un étudiant peut être défini par un identifiant
entier, or ce n'est pas suffisant, car l'utilisateur doit à chaque
fois chercher à qui appartient cet identifiant. Puisque le
premier objectif d'utiliser l'informatique est de faciliter les
tâches, les développeurs ont pensé à pouvoir déclarer de
nouveaux types composés appelés structures de données.
Dans le cas d'un étudiant, on définit une structure formée par
le nom, le prénom, l'identifiant, et on peut ajouter d'autres
informations telles que l'âge ou la date de naissance. Cette
dernière aussi peut être de type composé car la date est
formée de jour, mois et années.

II. Déclaration
Un enregistrement est déclaré entre les deux mots clés
enregistrement et finEnregistrement. D'autres versions
utilisent le mot clé struct et finStruct pour se rapprocher du
langage C.

p. 149
Mheni & SGarbouje

En algorithmique En langage C
Types
typedef struct
Nom_type = enregistrement
{
champ1 : type1 <type1> champ1 ;
champ2 : type2
<type2> champ2 ;
Syntaxe … …
champN : typeN
<typeN> champN ;
finEnregistrement } nom_type ;
Variables:
Nom_var : Nom_type nom_type Nom_var ;

Types :
typedef struct
Etudiant = enregistrement {
Id: entier int id ;
Nom: chaine char nom[20] ;
Prenom: chaine char prenom[20] ;
Age: entier int age ;
finEnregistrement } Etudiant ;
Exemple Date = enregistrement typedef struct
Jour: entier {
Mois: chaine int jour, mois, annee ;
Année: entier } Date ;
finEnregistrement

Variables Etudiant E1, E2 ;


E1,E2: Etudiant Date date_naissance ;

p. 150
Mheni & SGarbouje

Date_Naissance: Date

On peut aussi intégrer une structure dans une autre,


par exemple on peut remplacer la variable age dans la
structure Etudiant par Date_Naissance

En algorithmique En langage C
Etudiant : enregistrement typedef struct
Id: entier {
Nom: chaine int id ;
Prenom: chaine char nom[20] ;
Date_Naiss: Date char prenom[20] ;
finEnregistrement Date date_naissance ;
} Etudiant ;

III. Manipulation des enregistrements

Pour accéder aux champs d'un enregistrement en


algorithmique ou bien en langage C, on doit indiquer le nom
de la variable de type enregistrement et le nom du champ en
les séparant par un point. Le remplissage d'une variable de
type enregistrement se fait champs par champs, ou en lui
affectant directement une autre variable de même type
d’enregistrement (à condition que la deuxième soit remplie).

Exemple :

p. 151
Mheni & SGarbouje

E1.nom ←"Ayari"
E1.prénom ←" Bilel"
E1. Age ←34
E1. id←455
E2 ←E1

Dans le cas d'un tableau d'enregistrement, chaque case


devient une variable enregistrement et on utilise les indices.

Exemple:

Types

Tab : Tableau [1..n] de Etudiant

Variables

T:Tab

Dans ce cas, si on veut modifier le nom du 5ème étudiant du


tableau, on utilise cette instruction:

T[5].nom ←"Ayari".

p. 152
Mheni & SGarbouje

IV. Exercices d'applications


Exercice 1
Creer un enregistrement nomme " Etudiant" qui est
caracterisé par un identifiant, un nom et un prénom.
On vous demande d'écrire un algorithme permettant de saisir
10 etudiants, les ranger dans un tableau puis les afficher.

Exercice2
On reprend l’exercice précédent mais on rajoute en plus pour
chaque étudiant ses deux notes.

1. Creer le nouvel enregistrement nomme "Notes"


caractérisé par NoteCc (Note de controle continu) et
NoteEx (Note d’examen).
2. Modifier l’enregistrement "étudiant" afin qu’il puisse
être en relation avec l’enregistrement "Notes".
On vous demande d'écrire :
3. Une procédure de saisie des étudiants ainsi leurs
notes.
4. Une procédure d’afficher des étudiants avec leurs
notes.
5. Une fonction qui renvoie l’étudiant qui a eu la
meilleure note d’examen.
6. Une fonction qui renvoie la moyenne générale de la
classe.
7. Afficher la meilleure note d’examen et la moyenne
générale de la classe sachant que son calcul est fait
comme suit

p. 153
Mheni & SGarbouje

Moyenne=NoteCc*0.3+ NoteEx*0.7
8. Ecrire le programme principal faisant appel aux
différents sous-programmes.

p. 154
Mheni & SGarbouje

V. Correction
Exericie 1

Type #include <stdio.h>


Etudiant :
Enregistrement typedef struct {
Ident : Entier int id,
Nom : char Nom[20], Prenom[20]
chaine[20] ;
Prenom : } etudiant;
chaine[20]
FinEnregistrement void Remplissage (int m,
TAB : Tableau de [0..9] etudiant T[])
Etudiant { int i;
for (i=0;i<m;i++)
Procedure Remplissage (m : {
Entier ; var T : TAB) printf ("Etudiant n°%i :
Variables identifiant =",i);
i : Entier scanf ("%d",&T[i].id);
Debut printf ("Nom =");
Pour i de 0 à m-1 faire scanf ("%s",T[i].Nom);
Ecrire("Etudiant printf ("Prénom =");
n°",i," :") scanf ("%s",T[i].Prenom);
Ecrire("Identifia }
nt : ") }
Lire(T[i].Ident)
Ecrire("Nom : ") void affichage (int m,
Lire(T[i].Nom) etudiant t[])

p. 155
Mheni & SGarbouje

Ecrire("Prenom { int i;
: ")
Lire(T[i].Preno printf ("Identifiant | Nom |
m) Prénom");
Fin Pour for (i=0;i<m;i++)
Fin printf ("%d | %s | %s",
Procedure Affichage(m : t[i].id, t[i].nom,
Entier ; T : TAB) t[i].prenom);
Variables }
i : Entier
Debut main ()
Ecrire("Identifiant | {
Nom | Prénom : ") int n=10;
Ecrire("------------------- etudiant t[n];
-------------") remplissage (n, t);
Pour i de 0 à m faire affichage (n, t);
Ecrire(T[i].Ident," | }
",T[i].Nom," | ",T[i].Prenom)
Fin Pour
Fin

Algorithme GestionEtudiant
Variables
T : TAB
n : Entier
Debut
n ← 10
Remplissage(n,T)
Affichage(n,T)
Fin

p. 156
Mheni & SGarbouje

Exercice 2:

Type #include <stdio.h>


Notes : Enregistrement
noteCc : Reel typedef struct {
noteEx : Reel float notecc, noteex;
Fin Enregistrement } notes;
Etudiant : Enregistrement
Ident : Entier typedef struct {
Nom : chaine[20] int id,
Prenom : char Nom[20], Prenom[20] ;
chaine[20] notes note;
Note : Notes } etudiant;
Fin Enregistrement
TAB : Tableau de [0..9] void saisieNotes (etudiant *E)
Etudiant {
do {
Procedure SaisieNotes(var E : printf ("Note controle
Etudiant) contenu : ");
Debut scanf
Repeter ("%f",E.note.notecc);
Ecrire("Note controle } while (*E.note.notecc ≥
contenu : ") 0 && *E.note.notecc ≤ 20);
Lire(E.Note.NoteCc) do {
Jusqu'à (E.Note.NoteCc ≥ printf ("Note examen :
0 ET E.Note.NoteCc ≤ 20) ");
Repeter scanf
Ecrire("Note examen : ") ("%f",E.note.noteex);
Lire(E.Note.NoteEx) } while (*E.note.noteex ≥

p. 157
Mheni & SGarbouje

Jusqu'à (E.Note.NoteEx ≥ 0 && *E.note.noteex ≤ 20);


0 ET E.Note.NoteEx ≤ 20) }
Fin
void remplissage (int m, etudiant
Procedure Remplissage(m : T[])
Entier ; var T : TAB) { int i;
Variables
i : Entier for (i=0;i<m;i++)
Debut {
Pour i de 1 à m faire printf ("Etudiant n°%i :
Ecrire("Etudiant identifiant =",i);
n°",i," :") scanf ("%d",&t[i].id);
Ecrire("Identifiant : printf ("nom =");
") scanf ("%s",t[i].nom);
Lire(T[i].Ident) printf ("prénom =");
Ecrire("Nom : ") scanf ("%s",t[i].prenom);
Lire(T[i].Nom) saisieNotes (&t[i]);
Ecrire("Prenom : ") }
Lire(T[i].Prenom) }
SaisiNotes(T[i])
FinPour void affichage (int m, etudiant
Fin t[])
{ int i;
Procedure Affichage(m : Entier ;
T : TAB) printf ("Identifiant | Nom |
Variables Prénom | Note controle | Note
i : Entier Examen");
Debut for (i=0;i<m;i++)
Ecrire("Identifiant | Nom | printf ("%d | %s | %s | %.2f |
Prenom Note | Contrôle Continu | %.2f", t[i].id, t[i].nom,

p. 158
Mheni & SGarbouje

Note Examen ") t[i].prenom, t[i].note.notecc,


Pour i de 1 a n faire t[i].note.noteex);
Ecrire(T[i].Ident," | }
",Lire(T[i].Nom," |
",T[i].Prenom," | ", float maxNote (int m, etudiant
E.Note.NoteCc," t[])
|",E.Note.NoteEx) { int i;
FinPour float max=t[0].note.noteex;
Fin
for (i=1;i<m;i++)
Fonction maxNote(m : Entier ; T : if (t[i].note.noteex>max)
TAB) : Reel max = t[i].note.noteex;
Variables return (max);
i : Entier }
NoteMax : Reel
Debut float moyGenerale (int m,
NoteMax etudiant t[])
←T[1].Note.NoteEx { int i;
Pour i de 2 a m Faire float som=0;
Si
(T[i].Note.NoteEx>NoteMax)alors for (i=0;i<m;i++)
NoteMax ← som=som + 0.7*t[i].note.noteex
T[i].Note.NoteEx + 0.3*t[i].note.notecc;
FinSi return (som/m);
FinPour }
maxNote← NoteMax
Fin main ()
{
Fonction MoyenneGenerale(m : int n=10;
Entier ; T : TAB) : Reel etudiant t[n];

p. 159
Mheni & SGarbouje

Variables remplissage (n, t);


i : Entier affichage (n, t);
som : Reel printf ("Meilleure note examen :
Debut %.2f \n Moyenne générale de la
som ←0 classe : %.2f", maxNote(n,t),
Pour i de 1 à m Faire moyGenerale(n,t));
som ← som + 0.3 * }
T[i].Note.noteCc + 0.7 *
T[i].Note.noteEx
Fin Pour
MoyenneGenerale ←som /
m
Fin

Algorithme GestionEtud
Variables
ET : TAB
n : Entier
Debut
n ←10
Remplissage(n,ET)
Affichage(n,ET)
Ecrire("Meilleur note
examen :", MeilleureNote(n,ET),
" Moyenne generale de la
classe :",
MoyenneGenerale(n,ET))
Fin

p. 160
Mheni & SGarbouje

p. 161
Mheni & SGarbouje

Les fichiers
I. Définition
Un fichier est un ensemble d'informations sauvegardé dans
une mémoire secondaire (disque dur, CD-ROM, disque
amovible, etc.). On distingue deux types de fichiers :
• Les fichiers textes : des fichiers non structurés formés
par des caractères imprimables (codes ASCII).
• Les fichiers séquentiels: ce sont des fichiers structurés
contenant des données de même nature, et composés
par des enregistrements. Exemples :
- liste des étudiants d’une faculté
- liste des salariés dans une société
- liste des produits dans un stock de magasin

Pour le système d'exploitation Windows, par exemple, On


attribue à chaque fichier un nom, qui, généralement,
commence par une lettre alphabétique mais peut contenir des
chiffres. Un nom de fichier est formé de trois parties; le
chemin absolue contenant le fichier, le nom du fichier suivi
de l'extention qui précise le type du fichier et l'outil logiciel
pour l'ouvrir et l'éditer (le nom et l'extention sont séparés par
un point).
Exemple: C:\ mes documents\livreAlgo.docx

Il existe deux modes d'accès à un fichier ; le mode d'accès


séquentiel et le mode d'accès direct. Dans un fichier à
organisation séquentielle (F.O.S); pour atteindre un

p. 162
Mheni & SGarbouje

enregistrement on doit parcourir tous les enregistrements qui


le précèdent.
Un fichier possède toujours une zone supplémentaire à la fin
appelée marque de fin de fichier (FDF) permettant de le
borner :

Fichier FDF

Enregistrement

II. Fichier texte


Les fichiers textes contiennent des lignes formées par des
chaines de caractères. Ils sont déclarés de cette façon :
Variables
ftext : Fichier texte

III. Fichier séquentiel


En algorithmique, pour déclarer un fichier séquentiel, il faut
spécifier le nom du fichier et le type des éléments du fichier.
Exemple :
Types
Employe = Enregistrement
Matricule : Entier
Nom : Chaîne[30]
Prénom : Chaîne[30]
Salaire : Réel
FinEnregistrement
FichEmpl = Fichier de Employe
Variables

p. 163
Mheni & SGarbouje

Fe : FichEmpl

En langage C, un fichier est déclarée par une variable


pointeur qui pointe sur une structure contenant les
informations du fichier (de type FILE) et ceci qu'il soit
textuel ou binaire. Le type structuré FILE est défini dans le
fichier d'entête <stdio.h> ainsi que les différentes fonctions
et procédures sur les fichiers.

Exemples : FILE * f;
FILE * fprod;

IV. Manipulation des fichiers

Les différentes opérations qu'on peut appliquer à un fichier


sont les suivantes:

1. Ouverture du fichier :
Ouvrir (NomFichier, mode)
Les modes d'ouverture en algorithmique sont soit en
Lecture "L" ou Ecriture "E". Après l’ouverture, le pointeur
pointe sur le premier enregistrement dans le fichier.
En langage C, l'ouverture d'un fichier se fait avec la
fonction suivante :
fopen (nom_fichier , mode )
fopen renvoie un pointeur sur le début du fichier. Le 1er
argument est une chaîne contenant le nom du fichier (avec
son chemin si nécessaire) et le 2nd est aussi une chaîne qui
précise le mode d’ouverture comme suit :

p. 164
Mheni & SGarbouje

Fichier texte Fichier binaire


Ouverture en lecture "r" "rb"
Ouverture en écriture "w" "wb"
Ouverture en écriture
"a" "ab"
à la fin(ajout)
Ouverture en "r+" "r+b"
lecture/écriture "w+" "w+b"
Ouverture en
lecture/écriture après "a+" "a+b"
la fin

Si l’on ouvre un fichier qui n’existe pas en écriture ou


en ajout, il est créé. Ouvrir un fichier existant en écriture
écrase le contenu précédent alors que l’ouvrir en ajout
conserve ce contenu. Il y a erreur si l'on veut lire un fichier
qui n’existe pas et fopen renvoie NULL.
Exemples : f = fopen ("liste.txt","r+");

2. Lecture d'un fichier :


Lire (NomFichier, var)
Après chaque opération de lecture, le pointeur passe à
l’enregistrement suivant. Si on veut lire un enregistrement
précédent à celui pointé, la réouverture du fichier est
obligatoire.
Pour lire une ligne dans un fichier texte on utilise :
Lire_Ligne(NomFichier,chaine).

p. 165
Mheni & SGarbouje

En langage C, il y a plusieurs fonctions pour lire un


fichier, les plus utilisées sont : fgetc, fgets, fscanf et fread.
N.B: la foonction sizeof(paramètre) retourne la taille
du paramètre.

Description Exemple
Cette fonction retourne un
int : c'est le caractère qui a
été lu. caractere =
fgetc Si la fonction n'a pas pu lire fgetc(fichier);
de caractère, elle retourne
EOF.
<C> = fgetc( <FP> );
Cette fonction lit une ligne
Fichier dans le fichier (elle s'arrête au
textuel premier \n qu'elle rencontre). fgets("bonjour",
fgets On peut définir la taille sizeof(liste.txt),
maximale de la chaîne si la "liste.txt");
ligne est trop longue
fgets(chaine, taille, fichier)
Cette fonction lit dans un
fichier formaté (qui doit avoir fscanf(fichier,
fscanf "%d %d %s", &a,
été écrit d'une manière &b, ch);
précise).
Cette fonction lit dans un
fichier des données de grande fread (&prod,
Fichier
fread sizeof(produit),
binaire taille ou ayant un type 1, fp)
structuré (enregistrement)

p. 166
Mheni & SGarbouje

3. Ecriture dans un fichier


Ecrire(NomFichier, fenêtre)
Il faut noter que l'ajout (l'Ecriture) se fait toujours
après le dernier élément

En langage C, il y a diverses fonctions pour écrire


dans un fichier, les principales sont : fputc, fputs, fprintf et
fwrite.

Description Exemple
Cette fonction écrit un
seul caractère dans le
fputc fichier. fputc('A',
fputc( <C> , <FP> fichier);
);

Fichier Cette fonction écrit une


textuel chaine dans le fichier.
fputs La fonction renvoie fputs(ch,ftxt);
EOF s'il y a eu une
erreur
Cette fonction écrit une fprintf(fichier,
fprintf chaine formatée dans un "%s a %d ans",
fichier. nom, age);

Cette fonction écrit dans fwrite (&emp,


Fichier un fichier des données
fwrite sizeof(employe),
binaire 1, fich) ;
structurées

p. 167
Mheni & SGarbouje

(enregistrement)

4. Fermeture du fichier :
Fermer (NomFichier) en algorithmique.

fclose (pointeur_fichier) en langage C. Exemple : fclose(fp);

5. Fin de fichier

FDF(NomFichier)

Cette fonction est souvent utilisée pour tester si la fin


du fichier est atteinte ou non. Elle retourne un résultat de type
booléen.

En langage C, on utilise feof(fichier) qui renvoie un


entier nul lorsque la fin du fichier n'est pas encore atteinte et
sinon un entier non nul.

V. Création d'un fichier d'organisation


séquentielle:
Voici une procédure permettant de créer et remplir un
fichier d'Employés en algorithmique puis en langage C :

Procédure Creation (Var fe : FichEmpl)


Variables
emp : Employe
rep : caractère
Début
Ouvrir(fe,E)

p. 168
Mheni & SGarbouje

repeter
Ecrire (”Entrer le matricule de l'employé : ”)
Lire (emp. Matricule)
Ecrire (”Entrer le nom de l'Employé : ”)
Lire (emp.Nom)
Ecrire (”Entrer le prénom de Employé : ”)
Lire (emp.Prénom)
Ecrire (”Entrer la salaire de l’Employé : ”)
Lire (emp.Salaire)
Ecrire (fe,emp)
repeter
Ecrire ("Voulez vous saisir un autre employé?
[O/N]")
Lire (rep)
Jusqu'à(majus(rep)< >'O' OU majus(rep)<
>'N')
Jusqu'à (majus(rep)='N')
Fermer(fe)
Fin

void creation (char nomf[30])


{
FILE * fe;
employe emp;
char rep;

fe = fopen(nomf,"wb");
do {
printf ("Entrez le matricule de l'employé :");
scanf ("%d",&emp.mat);

p. 169
Mheni & SGarbouje

printf ("Entrez le nom de l'employé :");


scanf ("%s",emp.nom);
printf ("Entrez le prénom de l'employé :");
scanf ("%s",emp.prenom);
printf ("Entrez le salaire de l'employé :");
scanf ("%f",&emp.sal);
fwrite (&emp, sizeof(employe), 1, fe);
do{
printf ("Voulez vous saisir un autre employé ?
[O/N]")
scanf ("%c",&rep);}while(toupper(rep)!='O' ||
toupper(rep)!='N')
} while (toupper(rep)=='O');
fclose (fe);
}

VI. Parcours d'un fichier

a. Parcours d'un fichier séquentiel

La procédure suivante permet de parcourir un fichier


d'employés et d'afficher les données des enregistrements. La
fin du fichier est repérée utilisant FDF, il faut tester si la fin
est atteinte avant de commencer à lire le fichier, au cas où le
fichier est vide.

Procédure ParcoursFichier(fe : FichEmpl)


Variables
emp : Employé
Début

p. 170
Mheni & SGarbouje

Ouvrir(fe,L)
Lire(fe,et)
Tant que (FDF(fe)) faire
Ecrire("Matricule:",
emp.Matiricule,"Nom:",emp.Nom,"Prenom:",
emp.Prenom,"Salaire:",emp.Salaire)
Fin Tq
Fermer(fe)
Fin

void parcourirFichier (char nomf[30])


{
FILE * fe;
employe emp;

fe = fopen (nomf, "rb");


while (fread (&emp, sizeof(employe), 1, fe) ,
!feof(fe))
{
printf ("Matricule %d de l'employé %s %s,
salaire =%f DT",
emp.mat, emp.nom,
emp.prenom, emp.sal);
}
fclose (fe);
}

b. Parcours d'un fichier texte

p. 171
Mheni & SGarbouje

La procédure suivante permet de lire et afficher le


contenu d’un fichier texte.

Procédure ParcoursFText (ftext : Fichier texte)


Variables
ligne : Chaîne
Début
Ouvrir(ftext,L)
Lire(ftext,ligne)
Tant que (FDF(ftext)) faire
Ecrire(ligne)
Lire(ftext,ligne)
FinTQ
Fermer(ftext)
Fin

void parcourirFichierText (char nomf[30])


{
FILE * fich;
char ligne[256];

fich = fopen (nomf, "r");


while (fgets (ligne, sizeof(ligne), fich) != NULL)
{
printf ("%s",ligne);
}
fclose (fich);
}

p. 172
Mheni & SGarbouje

VII. Exercices d'application

Exercice 1
On souhaite mémoriser des noms de personnes dans un
fichier nommé " pers.dat ".
On vous demande alors de créer les sous-programmes
suivants :
1) Une procédure de création du fichier qui contient les
noms des personnes.
2) Une procédure d’affichage des noms de personnes.
3) Une fonction qui permet de chercher un nom passe en
argument et qui renvoie vrai si ce dernier existe et
faux sinon.
4) Une procédure qui copie les noms sans compter le
nom passe en parametre.
5) Ecrire le programme principal faisant appel aux
differents sous-programmes.

Exercice 2

1) Ecrire une procédure permettant de créer et remplir un


fichier « Fp » qui contient des informations sur le personnel
d’une entreprise (matricule, nom, prénom, grade, salaire).
2) Ecrire une procédure qui affiche la liste des employés de
cette entreprise dont le salaire est compris entre 500 et
700DT.
3) Ecrire une procédure qui recherche un employé dans le
fichier Fp à partir de son matricule.
- Si l’employé est trouvé, l’algorithme affiche son nom, son
prénom et son grade

p. 173
Mheni & SGarbouje

- Sinon, il affiche le message ”ce matricule ne figure pas dans


le fichier…”

Exercice 3
On souhaite mémoriser les étudiants d'une faculté ainsi que
leurs notes dans un fichier nommé "fetud.dat". Un étudiant
est caracterisé par un identifiant, un nom et un prénom et
possède deux notes : une note de contrôle continu et une note
d'examen.
Travail à faire :
1) Créer les enregistrements nécéssaires pour enregistrer
un étudiant.
2) Écrire une procédure permettant de saisir les notes
associees à un &tudiant donné en paramètre.
3) Écrire une procédure permettant de créer le fichier des
etudiants.
4) Écrire une procédure qui permet de copier les
etudiants qui ont eu une moyenne supérieure ou égale
à 10 du fichier "fetud.dat" dans un tableau des
etudiants.
5) Écrire une procedure qui permet de trier un tableau
d'étudiants dans l'ordre décroissant selon leurs
moyennes.
6) Écrire une procédure qui permet de créer le fichier
nomme "result.dat" qui contiendra les étudiants qui
sont réussit, triés dans l'ordre décroissant de leurs
moyennes.
7) Écrire une procédure qui permet d'afficher le contenu
du fichier "result.dat".

p. 174
Mheni & SGarbouje

8) Écrire le programme principal qui fait appel aux


différents sous-programmes.

VIII. Correction
Exercice 1:

Type #include <stdio.h>


Nom : chaine[30] #include <ctype.h>
FichNoms : Fichier
de Nom typedef struct {char nom[30];
} Nom;
Procedure Creation(Var fn
: FichNoms) void creation (char nf[20])
Variables {
n : Nom char n[30], rep='O';
rep : caractere FILE * f;
Debut
//ouverture du fichier f = fopen (nf,"w");
en écriture while (toupper(rep)=='O')
Ouvrir(fn,E) {
Répéter printf ("Nom :");
Ecrire(”No scanf ("%s",n);
m : ”), Lire(n) fwrite (n,sizeof(Nom),1,f);
Ecrire(fn,n) printf ("Voulez vous ajouter
Ecrire(”Vou un autre nom? [O/N]:");
lez-vous ajouter un scanf ("%c",&rep);scanf
autre nom [O/N] : ("%c",&rep);
}
”)
fclose (f);
Lire(rep)
}
Jusqu'à

p. 175
Mheni & SGarbouje

(MAJUS(rep) ≠ ʹOʹ)
Fermer (fn) void affichage (char nf[20])
//fermeture du fichier {
Fin char n[30];
FILE * f;
Procedure Affichage (fn :
FichNoms) f = fopen (nf,"r");
Variables while ( fread (&n,
n : Nom sizeof(Nom), 1, f), ! feof(f) )
Debut printf ("\n%s", n) ;
Ouvrir(fn,L) fclose (f);
Lire(fn,n) }
Tant que
NON(FinDeFichier(fn)) int recherche (char nf[20],
Faire char ch[30])
Ecrire(n) {
Lire(fn,n) char n[30];
Fin Tant que FILE * f;
Fermer(fn) int trouvee=0;
Fin
f = fopen (nf,"r");
Fonction Recherche (x : while (!trouvee && ! feof(f) )
Nom ; fn : FichNoms) : {
Booleen fread (&n, sizeof(Nom), 1, f);
variables if (strcmp(n,ch)==0)
n : Nom trouvee=1;
Trouve : Booleen }
Debut fclose (f);
Trouve ← faux return(trouvee);
Ouvrir(fn,L) }

p. 176
Mheni & SGarbouje

Tant que
(Trouve=faux ET void copier (char ch[30],char
NON(FinDeFichier(fn)) nfsrc[20],char nfdest[20])
Faire {
Lire(fn,n) char n[30];
Trouve ← (n FILE * fe;
= x) FILE * fs;
Fin Tant que
Recherche fe = fopen (nfsrc,"r");
←(Trouve) fs = fopen (nfdest,"w");
Fermer(fn) while ( fread (&n,
Fin sizeof(Nom), 1, fe), ! feof(fe)
)
Procedure Copier(x : Nom ; {
fn : FichNoms ; var ft : if (strcmp(n,ch)!=0)
FichNoms) fwrite (&n, sizeof(Nom), 1,
Variables fs);
n : Nom }
Debut fclose (fe);
Ouvrir(fn,L) fclose (fs);
Ouvrir(ft,E) }
Tant que
(NON(FinDeFichier(fn)) main()
Faire {
Lire(fn,n) char ch[30],
Si (n ≠ x) nomfich[30],nomfich2[30];
Ecrire(ft,n)
FinSi printf ("\nnom du fichier à
Fin Tant que créer : ") ;
Fermer(fn) scanf ("%20s", nomfich) ;

p. 177
Mheni & SGarbouje

Fermer(ft) creation (nomfich);


Fin affichage (nomfich);
printf ("\nentrez le nom à
Algorithme Personne rechercher :");
Variables scanf ("%s",ch);
F1,F2 : FichNoms if (recherche(nomfich,ch))
Debut printf ("\n%s existe dans le
Creation(F1) fichier");
Affichage(F1) else
Si printf ("\n%s n'existe pas
(Recherche("Riadh",F1)) dans le fichier");
Alors printf ("\nnom du fichier où
Ecrire("Riadh copier : ") ;
est existant dans le scanf ("%20s", nomfich2) ;
fichier") copier (ch,nomfich,nomfich2);
Sinon affichage (nomfich2);}
Ecrire("Riadh
est non existant dans
le fichier")
Fin Si
Copier("Riadh",F1,F
2)
Affichage(F2)
Fin

Exercice 2:

1) 1) typedef struct {

p. 178
Mheni & SGarbouje

Types int mat;


Employe = Enregistrement char grade, nom[20],
Matricule : Entier prenom[20];
Nom : Chaîne float sal;
Prenom : Chaîne } employe;
Grade : Caractère
Sal : Réel void creation (char
FinEmploye nf[20])
Fpers = Fichier de Employé { FILE *f;
char rep;
Procédure Création(Var f : Fpers) employe emp;
Variables
rep : caractère f = fopen(nf,"w");
emp: Employe do {
Début printf ("Matricule :");
Ouvrir(f,E) scanf
Répéter ("%d",&emp.mat);
Ecrire(”Matricule : ”) printf ("Nom :");
Lire(emp.Matricule) scanf
Ecrire(”Nom : ”) ("%s",&emp.nom);
Lire(emp.Nom) printf ("Prénom :");
Ecrire(”Prénom : ”) scanf
Lire(emp.Prénom) ("%s",&emp.prenom);
Ecrire(”Grade : ”) printf ("Grade :");
Lire(emp.Grade) scanf
Ecrire(”Salaire : ”) ("%c",&emp.grade);
Lire(emp.Sal) printf ("Salaire :");
Ecrire(f,emp) scanf
Jusqu'à (rep = 'O') ("%f",&emp.sal);
Fermer(f) fwrite (&emp,

p. 179
Mheni & SGarbouje

Fin sizeof(employe),1,f);
}while
2) Procédure Consultation(f : (toupper(rep)!='O');
Fpers) }
Début
Ouvrir(f,L) 2) void consultation
Lire(f,emp) (char nf[20])
TantQue NON(FDF(f)) Faire {
Si (emp.Sal>=500) FILE * fe;
ET (emp.Sal<=700) Alors employe emp;
Ecrire(emp.M
atricule, emp.Nom, fe = fopen (nf, "rb");
emp.Sal) while (fread (&emp,
FinSi sizeof(employe), 1,
Lire(f,emp) fe) , !feof(fe))
FinTant Que {
Fermer(f) if (emp.sal>=200 &&
Fin emp.sal<=700)
printf ("Matricule %d
3) de l'employé %s %s,
Procédure Recherche(Fp : Fpers ; x salaire =%f DT",
: Entier) emp.mat, emp.nom,
Variables emp.prenom,
emp : Employé emp.sal);
Trouve : booléen }
Début fclose (fe);
Ouvrir (Fp,L) }
Trouve ← faux
TantQue (trouve = Faux) ET 3) void recherche
NON(FDF(Fp)) Faire (char nf[20], int x)

p. 180
Mheni & SGarbouje

Lire(Fp,emp) {
Trouve← FILE * fe;
(emp.Matricule = x) employe emp;
FinTantQue int trouve=0;
Si FDF(Fp) Alors
Ecrire(”Ce matricule fe = fopen (nf, "rb");
ne figure pas dans le while (!trouve && !
fichier…”) feof(fe) )
Sinon {
Ecrire(emp.Nom, fread (&emp,
emp.Prénom, emp.Grade) sizeof(employe), 1,
FinSi fe);
Fermer(Fp) if (emp.mat==x)
Fin trouve=1;
}
fclose (f);
if (trouve)
printf ("%s %s grade
%c", emp.nom,
emp.prenom,
emp.grade);
else
printf ("Ce matricule
ne figure pas dans le
fichier");
}

Exercice 3:

p. 181
Mheni & SGarbouje

Type #include <stdio.h>


Notes : #include <ctype.h>
Enregistrement
noteCc : typedef struct {
Reel float notecc, noteex;
noteEx : } notes;
Reel
Fin Notes typedef struct {
Etudiant : int id,
Enregistrement char nom[20], prenom[20] ;
Ident : notes note;
Entier } etudiant;
Nom :
chaine[30] void saisieNotes (etudiant *E)
Prenom : {
chaine[20] do {
Note : Notes printf ("Note controle
Fin Etudiant continu : ");
TAB : Tableau de scanf
100 Etudiant ("%f",E.note.notecc);
FichEtud : Fichier } while (*E.note.notecc
de Etudiant ≥ 0 && *E.note.notecc ≤ 20);
do {
Procedure SaisiNotes(var printf ("Note examen :
E : Etudiant) ");
Variables scanf
noteEntrer : Reel ("%f",E.note.noteex);
Debut } while (*E.note.noteex
Repeter ≥ 0 && *E.note.noteex ≤ 20);
Ecrire("Not }

p. 182
Mheni & SGarbouje

e controle continu :
"),Lire(noteEntrer) void creation (char
Jusqu'à( noteEntrer ≥ 0 nomfich[30])
ET noteEntrer ≤ 20) { char rep ;
E.Note.NoteCc _ etudiant E;
noteEnter FILE *f;
Repeter
Ecrire("Not f = fopen(nomfich,"wb");
e examen : "), do
Lire(noteEntrer) {
Jusqu'à( printf ("Identifiant =");
noteEntrer ≥ 0 ET scanf ("%d",&E.id);
printf ("nom =");
noteEntrer ≤ 20)
scanf ("%s",E.nom);
E.Note.NoteEx _
printf ("prénom =");
noteEnter
scanf ("%s",E.prenom);
Fin
saisieNotes (&E);
Procedure Creation(var fn
fwrite(&E,sizeof(etudiant),1,f);
: FichEtud )
printf ("Voulez vous ajouter un
Variables
autre étudiant? [O/N]");
Et : Etudiant
scanf ("%c",&rep);
rep : caractere
}while (toupper(rep)=='O');
Debut
fclose(f);
Ouvrir(fn,E)
}
//ouverture du fichier en
écriture
void copierDansTab (char
Répéter
nf[30], int *n, etudiant t[])
Ecrire("Iden
{ etudiant E;
tifiant : ")
FILE *f;
Lire(Et.Iden
float moy;
t)

p. 183
Mheni & SGarbouje

Ecrire("No
m : ") f = fopen(nomfich,"rb");
Lire(Et.No *n=0;
m) while (fread (&E,
Ecrire("Pren sizeof(etudiant), 1, f) , !feof(fe))
om : ") {
Lire(Et.Pren moy = 0.7 * E.note.noteex +
om) 0.3 * E.note.notecc;
SaisiNotes( if (moy>=0)
Et) {
Ecrire(fn,Et t[n] = E;
) *n++;
Ecrire(Voul }
ez-vous ajouter un }
autre étudiant fclose(f);
(O/N) : ”) }
Lire(rep)
Jusqu'à void triTab (int n, etudiant t[])
(MAJUS(rep) = ʹNʹ ) { int i, echange;
Fermer(fn) etudiant aux;
//fermeture du fichier float moy1,moy2;
Fin
do
Procedure {
CopierDansTab(fn echange = 0;
:FichEtud; var n:Entier for (i=0;i<n;i++)
;var T : TAB ) { moy1= 0.7*t[i].note.noteex +
Variables 0.3*t[i].note.notecc;
Et : Etudiant moy2= 0.7*t[i+1].note.noteex
Moy : Reel + 0.3*t[i+1].note.notecc;

p. 184
Mheni & SGarbouje

Debut if (moy1<moy2);
Ouvrir(fn,L) { aux = t[i]
Lire(fn,Et) t[i] = t[i+1]
n←0 t[i+1] = aux;
Tant que echange = 1
NON(FinDeFichier(fn)) }
Faire }
Moy ← 0.3 n--;
* Et.Note.noteCc + }while (echange && n>0)
0.7 * }
Et.Note.noteEx
Si (Moy ≥ 10 void resultat (char nf1[30],
)Alors char nf2[30])
n ← n + 1 // {
incrémentation de etudiant t[100];
la taille int i,n;
T[n] ← Et // FILE *f;
affectation de
l’enregistrement au copierDansTab (nf1, &n, t);
tableau triTab (n, t);
Fin Si f = fopen(nf2,"wb");
Lire(fn,Et) for (i=0;i<n;i++)
Fin Tant que fwrite (&t[i],
Fermer(fn) sizeof(etudiant), 1, f)
Fin fclose(f);
Procedure TriTab ( n : }
Entier ; var T :TAB)
Variables void affichage (int m, etudiant
i : Entier t[])
aux : Etudiant { etudiant E;

p. 185
Mheni & SGarbouje

echange : Booleen FILE *f;


moy 1,moy2: Reel float moy;
Debut
Repeter f = fopen(nomfich,"wb");
echange ← faux
Pour i de 1 à n while (fread (&E,
Faire sizeof(etudiant), 1, f) , !feof(fe))
moy1 ← 0.3 * {
T[i].Note.noteCc + 0.7 * moy = 0.7*E.note.noteex +
T[i].Note.noteEx 0.3*E.note.notecc;
moy2 ← 0.3 x printf ("%d | %s | %s | %.2f ",
T[i+1].Note.noteCc + 0.7 * E.id, E.nom, E.prenom, moy);
T[i+1].Note.noteEx }
Si(moy1 < moy2) fclose(f);
Alors }
aux ← T[i]
T[i] ←
T[i+1] main ()
T[i+1]←aux {
echange ← char fentree[30]="fetud.dat";
vrai char fsortie[30]="result.dat";
Fin Si
Fin Pour creation (fentree);
n←n-1 affichage (fentree);
Jusqu'à (echange = resultat (fentree, fsortie);
faux OU n =1) affichage (fsortie);
Fin }

Procédure Résultat(fn
:FichEtud; var fr :

p. 186
Mheni & SGarbouje

FichEtud)
Variables
i,n : Entier
T : TAB
Début
CopierDansTab(fn,
n,T)
TriTab(n,T) //Tri
décroissant de moy
Ouvrir(fr,E) //
Ouverture du fichier
//
résultat en écriture
Pour i de 1 à n
Faire
Ecrire(fr,T[i
])
Fin Pour
Fermer(fr)
//fermeture du fichier
Fin

Procédure Affichage(fr :
FichNoms)
Variables
Et : Etudiant
Moy : Réel
Début
Ouvrir(fr,L)
Lire(fr,Et)

p. 187
Mheni & SGarbouje

Tant que
NON(FDF(fr)) Faire
Moy ← 0.3 *
Et.Note.noteCc +
0.7 *
Et.Note.noteEx
Ecrire(Et.Ident, ″
″,Et.Nom, ″
″,Et.Prénom, ″
″,Moy)
Lire(fr,Et)
Fin Tant que
Fermer(fr)
Fin
Algorithme
GestionEtudiant
Variables
Fn,Fr : FichEtud
Début
Création(Fn)
Affichage(Fn)
Résultat(Fn,Fr)
Affichage(Fr)
Fin

p. 188
Mheni & SGarbouje

La récursivité
I. Introduction
En informatique la notion de récursivité est similaire
à la récurrence en mathématique. Dans la programmation,
on parle de récursivité lorsqu'un programme s’appelle lui-
même. Plus précisément, une fonction ou procédure récursive
c'est un sous-programme qui fait appelle à lui-même une ou
plusieurs fois pour calculer un résultat ou effectuer un
traitement. Les appels récursifs prennent fin lorsqu’on atteint
la condition d’arrêt.

La récursivité peut dans certains cas remplacer les


boucles itératives, dans d'autres cas, il faut utiliser les boucles
itératives selon quelques critères. Les critères de choix d'un
programmeur sont : espace mémoire, facilité de codage,
minimiser le nombre de variables, maintenance du code…

II. Etude de cas


Prenons l'exemple de la fonction factoriel qui est
calculé selon la formule mathématique suivante :

Facto(n) = n* Facto(n-1)

Pour la récursivité, il faut penser toujours à la condition


d'arrêt. Cette condition est généralement placée dans une
structure conditionnelle.

p. 189
Mheni & SGarbouje

Fonction Facto ( n : Entier) : Entier


Début
Si (n = 0) Alors
Facto ← 1
Sinon Appel récursif avec de
Facto← n * Facto(n-1) nouveaux paramètres
FinSi
Fin

Fonctionnement

Facto(4) = 4* Facto(3)
Renvoie 4*6=24

1er appel retourne 6

Facto(3)= 3* Facto(2)

2ème appel retourne 2

Facto(2)= 2* Facto(1)

3ème appel retourne 1

Facto(1)= 1* Facto(0)

=1 (selon la co

p. 190
Mheni & SGarbouje

III. Choix entre structure itérative et la


récursivité
L'exécution d'une version récursive d'un algorithme
est généralement un peu moins rapide que celle de la version
itérative, même si le nombre d'instructions est le même (à
cause de la gestion des appels de fonction). L'algorithme
récursif mal écrit peut conduire à exécuter plus d'instructions
que la version itérative. Pour la fonction factorielle la
différence entre la version itérative et récursive ne se voit pas
clairement, nous prenons l'exemple de la suite de Fibonacci
pour mieux montrer cette différence.
La suite de Fibonacci est définie par :
f0 = 1
f1 = 1
fn = fn-2 + fn-1 pour n > 1
La fonction récursive correspondante est comme suit:

En algorithmique En langage C

Fonction Fibo ( n : Entier) : int Fibo (int n)


Entier {
if (n== 0 || n == 1)
Début
return 1 ;
Si (n = 0) ou (n = 1)
else
Alors
return (Fibo(n -
Fibo← 1
2) + Fibo(n – 1)) ;
Sinon
}
Fibo ←(Fibo(n - 2) + Fibo(n –

p. 191
Mheni & SGarbouje

1))
FinSi
Fin
Le schéma d'exécution d'une telle fonction est présenté sur la
figure suivante:

Fibo(1)
Fibo(0)
Fibo(3)
Fibo(2)
Fibo(4) Fibo(1)
Fibo(1)

Fibo(2)
Fibo(0)

A partir de cette figure, on remarque la répétition


inutile du calcul de Fibo(2), Fibo(1) et Fibo(0). Dans cet
exemple nous avons choisi de calculer Fibo(4), si l’on désire
calculer Fibo(100), cela engendrera un plusieurs calculs et
beaucoup d'appels récursifs. Dans ce cas, la version itérative
est plus simple que la version récursive:

En algorithmique En langage C
Fonction FiboIterative (n : Entier) : int FiboIterative

p. 192
Mheni & SGarbouje

Entier (int n)
Variables { int i, fn, fn_1,
i, fn, fn_1, fn_2 : fn_2 ;
Entier
Début fn_1 = fn_2 = 1 ;
fn_1 ← 1 for (i=2 ; i<n ; i++)
fn_2←1 {
Pour i de 2 à n Faire fn= fn_1 +
fn← fn_1 + fn_2 ;
fn_2 fn_2= fn_1 ;
fn_2← fn_1 fn_1= fn ;
fn_1← fn }
FinPour return (fn) ;
FiboIterative }
←(fn)
Fin

IV. Récursivité indirecte ou croisée


On parle de la récursivité indirecte, si une fonction X
fait appelle à une autre fonction Y et celle-ci fait appelle à X
suivant la figure suivante:

Fonction X ( param formels) : type Fonction Y ( param formels) : type


Début Début
…. ….
Y(param effectifs) X(param effectifs)
Fin… Fin…

p. 193
Mheni & SGarbouje

V. Exercices d'applications:
Exercice 1 :

Ecrire un programme qui permet d’afficher xy, avec x et y


saisis au clavier. Utiliser une fonction récursive exp(x,y)
définie comme suit :

exp(x,0) = 1

exp(x,y+1) = x * exp(x,y)

Exercice 2 :

Ecrire une fonction récursive qui permet de calculer le PGCD


d’un entier selon Euclide. L'algorithme d'Euclide, consiste à
effectuer une suite de divisions euclidiennes :

1. On effectue la division euclidienne a modulo b et on note r


le reste.
2. b devient a et r devient b
3. on recommence les étapes 1 et 2 jusqu'à ce qu'une division
donne un reste égal à 0.

Ainsi, le PGCD est le dernier reste non nul.

Exercice 3 :

p. 194
Mheni & SGarbouje

Ecrire une fonction récursive qui cherche une valeur dans un


tableau et retourne vrai si la valeur est trouvée sinon faux.

Exercice 4:

Soit V ( n ) n∈IN une suites réelle définie par :


*

V0 = −2

V n = 3V n −1 + n
 5 Si n est
 2V + n
Vn = n −1 Si n est paire
 5
impaire

Ecrire une fonction récursive qui calcule le nième terme de la


suite V.

Exercice 5: fonction d’Ackermann

Ecrire une fonction récursive Ack qui calcule Ack(n,m) selon


la formule suivante :

• Ack(0, m) = m + 1
• Ack(n, 0) = Ack(n - 1,1)
• Ack(n, m) = Ack(n - 1, Ack(n, m - 1))

Exercice 6:

p. 195
Mheni & SGarbouje

Ecrire une fonction récursive qui cherche une valeur dans un


tableau trié de réels et retourne sa position par la méthode de
recherche dichotomique.

Principe de la recherche dichotomique :

On divise le tableau en deux parties sensiblement égale et on


compare l’élément x avec le milieu s’ils sont différents on
continue à chercher dans la moitié où x devrait se trouver. On
répète jusqu’à trouver x ou que la partie du tableau devient un
seul élément.

Soit T[mil] l’élément du milieu de la partie qu’on vient de la


diviser, on distingue trois cas :

• si T[mil] = x alors la recherche est terminé.


• si T[mil] >x alors rechercher dans la partie gauche T
[1..mil-1].
• si T[mil] < x alors rechercher dans la partie droite T
[mil+1..n]

Exercice 7:

Soient m et n des entiers. On considère la fonction suivante :

Fonction Toto (m,n : entier) : entier


Début
si m=0 alors Toto ← 0
sinon Toto ←(Toto(m-1,n)+n)
fin si

p. 196
Mheni & SGarbouje

Fin
1. Quel est le résultat de Toto(3,5) ?
2. Que calcule cette fonction ?
3. Quel est le résultat de Toto(-1,4) ?
4. Pour quelles valeurs de m et n l’algorithme de la
fonction se termine-t-il ?
5. Modifier cette fonction récursive pour qu'elle
retourne un résultat quelque soit les valeurs des
entiers m et n.

Exercice 8:

Ecrire une fonction récursive Palind qui vérifie si une chaîne


de caractères est palindrome ou non. Exemples : radar, azza.

Formellement, une chaîne S de n caractères est un


palindrome si et seulement si :

Une condition nécessaire est que les caractères extrêmes


soient identiques et que le sous chaine privée des caractères
extrêmes soit également un palindrome.

VI. Correction d'exercices


Exercice 1:

Fonction int exp(int x, int y)


{

p. 197
Mheni & SGarbouje

exp(x:entier,y:entier):entier if (x==0 && y==0)


printf ("operation
Début impossible");
if (x==0 || y==0)
Si (x=0 et y=0) alors return 1;
Ecrire("operation impossible") else
Si (x=0 ou y=0) alors return (x*exp(x,y-1));
exp ←(1) }
Sinon
exp ←(x*exp(x,y-1))
Fin Si
Fin

Exercice 2:

Fonction PGCD (a:entier, int PGCD (int a, int b)


b:entier) {
if(b!=0);
Début return(PGCD(b,a mod b);
else
Si(b≠0); return (a);
PGCD ←(PGCD(b,a mod }
b);
Sinon
PGCD ←(a);
FinSi

Fin

p. 198
Mheni & SGarbouje

Exercice 3:

Fonction rechRecursive (val : int rechRec (float val, float


réel, t : tabreel, n:entier) : t[], int n)
booléen {
if (n == -1)
Début return 0;
else
Si (n=0) alors if (t[n]==val)
rechRecursive ←(faux) return (1);
Sinon else
Si (t[n]=val) alors return
rechRecursive ←(vrai) (rechRec(val,t,n-1));
Sinon }
rechRecursive
←(rechRecursive(val,t,n-1))
Fin Si
Fin Si

Fin

Exercice 4:

Fonction suite (n:entier) : int suite(int n)


entier {
if (n==0)
Début return (-2);
else
Si (n=0) alors if (n % 2 ==0)
suite ←(-2) { return ((3*suite(n-
Sinon 1)+n)/5);

p. 199
Mheni & SGarbouje

Si (n mod 2 =0) alors else


suite ←((3*suite(n- return ((2*suite(n-
1)+n)/5) 1)+n)/5);
Sinon }
suite ←((2*suite(n- }
1)+n)/5)
Fin Si
Fin Si
Fin

Exercice 5:

Fonction ack(n:entier , m:entier) : entier int ack (int n, int m)


{
Début if (n==0)
return (m+1);
Si (n=0) alors else
ack ←(m+1) if (m==0)
Sinon { return (ack(n-1,1);
Si (m=0) alors else
ack ←(ack(n-1,1)) return (ack(n-1,ack(n,m-1)));
Sinon }
ack ←(ack(n-1,ack(n,m-1))) }
Fin Si
Fin Si

Fin

Exercice 6:

Fonction rechercheDicho (x : réel, int rechercheDicho

p. 200
Mheni & SGarbouje

t : tabreel, binf: entier, (float x, float t[], int


bsup:entier) : entier binf, int bsup)
{
Variables int mil;
mil : entier
if (binf<=bsup)
Début {
Si (binf<=bsup) alors mil = (binf+bsup) / 2;
mil ← (binf+bsup) div 2 if (t[mil]==x)
Si (t[mil]=x) alors return (mil);
rechercheDicho ←(mil) else
Sinon if (t[mil]<x)
Si (t[mil]<x) alors return
rechercheDicho← (rechercheDicho(x,t,mil
(rechercheDicho(x,t,mil+1,bsup)) +1,bsup));
Sinon else
return
rechercheDicho←(rechercheDich (rechercheDicho(x,t,binf
o(x,t,binf,mil-1)) ,mil-1));
Fin Si }
Fin Si else
Sinon return -1;
rechercheDicho ←(-1); }
Fin Si
Fin
Exercice 7:

1) Résultat = 15
2) Elle retourne le résultat de la multiplication de m par n.
3) Cette fonction boucle à l'infini

p. 201
Mheni & SGarbouje

4) Elle se termine lorsque m et n ont des valeurs positives ou


nulles
5)Fonction Multiplier (m : int multiplier (int m, int n)
entier, n : entier) : entier {
Début if (m<0)
Si (m<0) alors Multiplier ←(- return (-1);
1) else
Sinon if (m==0)
Si (m=0) alors Multiplier return 0;
←(0); else
Sinon return(n +
Multiplier multiplier(m-1,n));
←(Multiplier(m-1,n)+n) }
Fin Si
Fin Si
Fin
Exercice 8:

Fonction palind (ch : chaine) : int palind (char ch[30])


booléen {
if (strlen(ch)<2)
Début return 1;
else
Si (longueur(ch)<2) alors if
palind ←(vrai) (ch[1]==ch[strlen(ch)])
Sinon return
Si (ch[1]=ch[longueur(ch)]) (palind(strchr(ch,2,strlen
alors (ch-2)));
palind else
←(palind(souchaine(ch,2,longueu return 0;

p. 202
Mheni & SGarbouje

r(ch)-2))) }
Sinon
palind ←(faux)
Fin

p. 203
Mheni & SGarbouje

Les pointeurs
I. Introduction
Le langage de programmation C, présente l'avantage
de laisser l'utilisateur manipuler lui-même les adresses
mémoires. C'est vrai que ça augmente le temps et le coût de
développement mais on gagne en termes de mémoire et de
temps d'exécution. Avec la notion de pointeur, on parle de
manipulation par adresse (allocation dynamique).

II. Une variable dynamique


Les variables que nous utilisons jusqu'à maintenant
sont des variables statiques. On dit variable statique,
lorsqu’elle est déclarée au début du programme ou du bloc
dans lequel elle sera utilisée. La libération de l'espace
mémoire occupé par cette variable ne se fait qu'à la fin
d'exécution de ce bloc. Et l'accès se fait directement par le
nom de la variable.

Dans cette leçon nous étudions la variable dynamique.


C'est un espace mémoire, qu'on peut allouer et libérer à tout
moment. L'accès au contenu de cet espace mémoire se fait
par l'adresse de la case mémoire (pointeur).

p. 204
Mheni & SGarbouje

En résumé, un pointeur P est une variable statique qui


contient l'adresse mémoire dans laquelle est enregistré la
valeur pointée P^.

P P^

@213 "Tunis"

P est un pointeur sur une chaine de caractère, le


contenu de la case mémoire pointée par P est P^ sa valeur est
"Tunis".

III. Manipulation d'une variable


dynamique
1. Déclaration:

En algorithmique En langage C
Variables:
Syntaxe Nom_var : ^Nom_type nom_type *nom_var ;

Variables:
Ptr1,Ptr2 :^entier int *Ptr1, *Ptr2 ;
Exemple
r=^réel float *r ;

Pour déclarer une variable pointeur, on doit indiquer


son nom et le type, de la case mémoire pointée, précédé de ^

p. 205
Mheni & SGarbouje

en algorithmique. En langage C, pour indiquer qu’une


variable est un pointeur, il suffit de précéder son nom par le
symbole ‘*’. Prenons l'exemple précédent, la déclaration de
P, un pointeur sur une chaîne de caractère est comme suit:

Variable:
P,Q : ^chaine
En langage C :
char **P, **Q ; une * pour indiquer qu’il s’agit d’un
pointeur et une autre * pour indiquer que les deux variables
pointent sur des chaînes de caractères de longueurs
indéfinies.

Remarque :
Après sa déclaration, un pointeur est une case mémoire
qui peut contenir n’importe quelle adresse et donc pointer sur
n’importe quoi. Par conséquent, il faut toujours penser à
initialiser un pointeur juste après sa déclaration. Si l’on veut
que le pointeur pointe sur le vide, il suffit de l’initialiser à
NULL (ou nil) : ptr ← null.

La déclaration d’un pointeur ne suffit pas pour le créer


en mémoire. En effet, la création d’un pointeur signifie
l’allocation effective de l’espace mémoire. Cela se fait grâce
à la syntaxe suivante :

En algorithmique En langage C
Syntaxe Allouer (nom_pointeur) nom_ptr = (type*) malloc (sizeof (type)) ;
Exemple Allouer (ptr) ptr = (int*) malloc (sizeof (int)) ;

p. 206
Mheni & SGarbouje

2. Manipulation des pointeurs:


Prenons l’exemple suivant écrit en algorithmique et
en langage C :

Algorithme pointeur void main()


Variable: {
P,Q:^chaine char **P, **Q ;
Début
1-Allouer(P) 1- P = (char**) malloc (sizeof (char*)) ;
2-Allouer(Q) 2- Q = (char**) malloc (sizeof (char*)) ;
3-P^←"Tunis" 3- *P = "Tunis" ;
4-Q^←"El Kef" 4- *Q = "El Kef" ;
5-P^←Q^ 5- *P = *Q ;
6-P^←"Nabeul" 6- *P = "Nabeul" ;
7-P←Q 7- P = Q ;
8-P^←"Beja" 8- *P = "Beja" ;
Fin }

L'instruction 1 et 2 permettent d’allouer un espace mémoire


de taille une chaine de caractère et d’enregistrer l'adresse de
cet espace dans les pointeurs P et Q.

P P^

@213

Q Q^

@217

p. 207
Mheni & SGarbouje

L'instruction 3 et 4 permettent de remplir le contenu des


pointeurs P^ et Q^.
P P^

@213 "Tunis"

Q Q^

@217 "El Kef"

L'instruction 5 permet d’écraser le contenu de P^ et le


remplacer par celui de Q^.

P P^

@213 "El Kef"

Q Q^

@217 "El Kef"

L'instruction 6 permet de changer le contenu de P^ par


"Nabeul". Suite à l'instruction 5, si on change le contenu de
P^, Q^ ne sera pas changé au contraire de l'instruction 7 qui
suit.

p. 208
Mheni & SGarbouje

P P^

@213 "Nabeul"

Q Q^

@217 "El Kef"

L'instruction 7 permet de changer l'adresse P par celle de Q.


Dans ce cas, P va poiter sur la même adresse de Q. Par
conséquent, le contenu du pointeur P^ devient identique à
celui de Q^, comme il est montré par la figure suivante.

@217 "Nabeul"

Q Q^ P^

@217 "El Kef"

L'instruction 8 modifie le contenu de P^. Or, P et Q pointent


sur la même adresse, ainsi, tout changement du contenu de
P^, signifie le changement du
P contenu de Q^ :

@217

Q Q P^

@217 "Beja"
p. 209
Mheni & SGarbouje

IV. Exercices
Exercice 1 :
Remplir le tableau suivant par le contenu de chaque variable
après chaque instruction :

A, B, C : entier
A B C P1^ P2^ P1 P2
P1, P2 : ^entier
A←1
B←2
C←3
P1←&A
P2←&C
P1^ ←P2^+C

P2 ← &B

B←P2^ - P1^

P1 ← P2

p. 210
Mheni & SGarbouje

P1^← P2^*A

P2 ← &A

B ← A div C

Exercice 2 :
Ecrire une procédure qui copie les éléments positifs d'un
tableau T de 20 entiers (supposé déjà rempli) dans un
deuxième tableau POS en utilisant la notion de pointeur.

V. Correction d'exercices
Exercice 1 :
A, B, C : entier
A B C P1^ P2^ P1 P2
P1, P2 : ^entier
A←1 1 2 3 1 3 &A &C
B←2
C←3
P1←&A
P2←&C
P1^ ←P2^+C 6 2 3 6 3 &A &C

P2 ← &B 6 2 3 6 2 &A &B

B←P2^ - P1^ 6 -4 3 6 -4 &A &B

p. 211
Mheni & SGarbouje

P1 ← P2 6 -4 3 -4 -4 &B &B

P1^← P2^*A*(- 6 8 3 8 8 &B &B


1/3)

P2 ← &C 6 8 3 8 3 &B &C

C ← A div B 6 8 0 8 0 &B &C

Exercice 2 :
Procédure positif (T : tabEntier, var POS : void positif (int T[], int POS[])
tabEntier) { int *p, i=0;
Variables for (p=T;p<&T[20];p++)
i: entier if (*p>=0) {
p: pointeur sur entier; POS[i]=*p;
Début i++; }
i ←0 }
Pour p de &T à &T[20] faire
Si (^p >= 0)
POS[i] ← ^p;
i ← i+1
Fin Si
Fin Pour
Fin

p. 212
Mheni & SGarbouje

p. 213
Mheni & SGarbouje

Les listes chaînées


I. Introduction
Jusqu'à maintenant, pour mémoriser une liste de
données qui concernent des étudiants ou des employés, nous
avons utilisé les tableaux. Ces derniers sont des structures
statiques dont la taille, fixée dès le début, ne varie pas.
D'autre part, au niveau mémoire, si on déclare un tableau de
20 entiers, le compilateur doit trouver une vingtaine de cases
mémoires successives de taille un entier (les cases en bleu
dans la figure a).

-a- -b-

p. 214
Mheni & SGarbouje

Figure 1. Structure de la mémoire vive d'un ordinateur

Les listes chainées sont des structures composées de


cellules. Chaque cellules contient deux champs (ou trois
selon le types de la liste) le premier contient la variable et le
deuxième un pointeur vers la cellule qui suit. De cette façon,
on peut enregistrer les cellules dans n'importe quelle case
mémoire entier (les cases en bleu dans la figure b).
Néanmoins, il faut garder l'adresse de la tête de la liste. Ainsi,
puisque chaque cellule a un lien vers son successeur
(l'adresse de la cellule qui suit), on peut trouver tout le reste
de la liste. Avec les listes chainées, le compilateur n'est pas
obligé de trouver des cases successives vides dans la
mémoire. Ces cases peuvent êtres éparpillées dans toute la
mémoire ce qui constitue un gain considérable.

II. Liste simplement chainée


Les listes chainées sont formées par une ou plusieurs
cellules. Chacune de ces cellules est formée en plus de
l'élément information, d'un deuxième champ qui contient
l'adresse de la cellule successive. Le premier champ peut être
de différents types, soit simple (entier, réel, caractères ou
chaînes de caractères) soit composé (structure de donnée).
Il est précédemment indiqué, qu'il suffit d'avoir
l'adresse de la première cellule pour atteindre pas à pas la
dernière. Donc la liste chaînée est accessible par l'adresse de
la tête. La fin de la liste est indiquée par une adresse de
valeur NULL appelée aussi nil (voir la figure 2).

p. 215
Mheni & SGarbouje

Tête
@ c1 E1 @c2 E2 @c3 E3 null Null

Figure 2. Structure d’une liste chaînée

En supposant que les éléments de la liste sont des


entiers, celle-ci se déclare de la façon suivante :

En algorithmique En langage C
Type typedef struct
Cellule = cellule
Enregistrement {
Elem : int
entier elem ;
Suiv=Liste struct
cellule
FinEnregistrement *suiv ;
Liste =^Cellule } cellule ;

Variables cellule *L ;
L : Liste
1. Création d’une liste chaînée

La procédure suivante permet de créer une liste chaînée de


n éléments de type entier. En paramètre entrée-sortie, on a L une

p. 216
Mheni & SGarbouje

variable de type pointeur sur une cellule. Ce pointeur contiendra


l'adresse de la première cellule de laquelle on accèdera à la liste.

Procédure Création_liste (Var L : Liste , n : entier)


Variables
P : liste
i : entier
Début
L← Null
En algorithmique Pour i de 1 à n faire
Allouer (P)
Ecrire ("Donner un élément "), Lire (P^.Elem)
P^.Suiv←L
L←P
Fin pour
Fin

void Creation_liste (cellule **L, int n)


{
cellule *p ;
int i ;
*L = NULL ;
for (i=1 ; i<=n ; i++)
En langage C
{ p = (cellule*) malloc (sizeof (cellule)) ;
printf ("Donner un élément ") ;
scanf ("%d", p elem) ;
p suiv = *L ;
*L = p ;
}
}
Remarques :

p. 217
Mheni & SGarbouje

• Il est très important lors de la création d’une liste


chaînée, de penser à initialiser la tête de la liste à null,
sinon la liste n’aura jamais de fin et son parcours sera
impossible.

• Il faut noter qu’en langage C, le paramètre L dans


l’entête de la procédure (qui contient la tête de la liste à
modifier) est précédé par deux symboles ‘*’ : *L pour
indiquer qu’il s’agit d’un pointeur, et **L pour indiquer
que le paramètre *L est passé par adresse, ce qui est
représenté par le mot clé « Var » dans la version
algorithmique. Ainsi, à l’intérieur de toute la procédure,
il faut utiliser *L à chaque fois où l’on veut mentionner
ce paramètre.

• Pour accéder à un champ dans la nouvelle structure de


donnée d'une cellule de la liste chaînée, on écrit en
langage C : p elem et bien p suiv. En algorithmique, nous
avons gardé la syntaxe utilisée pour les enregistrements en y
ajoutant la notion de pointeur, d'où on écrit : p^.elem et
p^.suiv. Néanmoins, il est aussi possible de l'écrire sous cette
forme : p elem et p suiv.

2. Parcours d’une liste chaînée


a. Parcours itérative d'une liste chainée

En algorithmique Procedure Affiche_liste_Iter(L :Liste)


Variables

p. 218
Mheni & SGarbouje

P : Liste
Debut
P←L
Tant que (P ǂ Null) faire
Ecrire (P^.Elem)
P←P^.Suiv
Fin Tantque
Fin

void Affiche_liste_Iter (cellule *L)


{
cellule *p ;

p=L;
En langage C
while (p !=NULL)
{
printf (p elem) ;
p = p suiv ;
}
}

b. Parcours récursif d'une liste chainée

Procedure Affiche_liste_Réc(L :Liste)


Debut
Si (L ǂNull) alors
En algorithmique Ecrire (L^.Elem)
Affiche_liste_Réc (L^.Suiv)
Fin si
Fin

p. 219
Mheni & SGarbouje

void Affiche_liste_Rec (cellule *L)


{
if (L !=NULL)
En langage C {
printf (p elem) ;
Affiche_liste_Rec (L suiv) ;
}
}

3. Longueur d'une liste chaînée


La fonction récursive suivante permet de calculer le
nombre de cellules dans une liste chaînée

Fonction Longueur (L : Liste) :entier


Début
Si (L= Null) alors
Longueur ←(0)
En algorithmique
Sinon
Longueur ←(1+ Longueur (L^.Suiv))
Fin si
Fin

int Longueur (cellule *L)


{
En langage C
if (L==NULL)
return 0 ;
else

p. 220
Mheni & SGarbouje

return (1+ Longueur( (L suiv)) ;


}
4. Insertion d’un élément dans une liste
a. Insertion en tête de liste

Tête
@c1 E1 @c2 E2 @c3 E3 null Null

a – Etat initial

Tête
@ c0 E1 @c2 E2 @c3 E3 null Null

E0 c1
@
b- Etat final
Figure 3. Principe d’insertion d’un élément en tête de liste

On suppose que la liste initiale contient au moins une cellule.

Procédure Insert_Tete (Var L : Liste)


Variables
P : Liste
Debut
En algorithmique Allouer (P)
Ecrire ("Donner un entier"), Lire (P^.Elem)
P^.Suiv←L
L← P
Fin

p. 221
Mheni & SGarbouje

void Insert_Tete (cellule **L)


{
cellule *p ;
p = (cellule*) malloc (sizeof (cellule)) ;
En langage C
printf ("Donner un élément ") ;
scanf ("%d", p elem) ;
p suiv = *L ;
*L = p ;
}
b. Insertion d'un élément dans une position précise

Tête
@c1 E1 @c2 E2 @c3 E3 null Null

a – Etat initial
Tête
@ c0 E1 @c2 E2=X @c4 E3 null Null

Q @c2 @c4
E4 @c3
P
b- Etat final
Figure 4. Principe d’insertion d’un élément à l’intérieur d’une
liste

p. 222
Mheni & SGarbouje

Procédure Insert_Liste (Var L : Liste, x:entier)


Variables
P ,Q: Liste
Debut
Q L
Tant que ((Q ǂ Null) et (Q^.elemǂx) faire
Q←Q^.Suiv
Fin Tant que
En algorithmique
Si (Q ǂ Null)
Allouer (P)
Ecrire ("Donner un entier"), Lire (P^.Elem)
P^.Suiv← Q^.Suiv
Q^.Suiv←P
Si non
Ecrire(x, "est introuvable")
Fin

void Insert_Liste (cellule **L, int x)


{
cellule *p, *q ;
q = *L ;
while (q !=NULL && q elem !=x)
En langage C q = q↑suiv ;
if (q !=NULL)
{
p = (cellule*) malloc (sizeof (cellule)) ;
printf ("Donner un élément ") ;
scanf ("%d", p elem) ;
p suiv = q suiv ;
q suiv = p ;

p. 223
Mheni & SGarbouje

}
else
printf ("%d est introuvable", x) ;
}
La procédure précédente permet d'insérer un élément
dans une position précise indiquée par un autre élément x.
Dans la première partie, on cherche l'élément x. Dans la
seconde partie, on teste si la position a bien été trouvée pour
effectuer l’insertion, sinon on affiche un message d’erreur.

5. Recherche d’un élément dans une liste chaînée

Les deux fonctions suivantes récursive et itérative


permettent de chercher un élément x dans la liste, elles
retournent vrai si x appartient à la liste et faux si on atteint la
fin de la liste sans trouver la variable x.

A. Version itérative

Fonction recherche (x : entier , L : liste) : booléen


Variables
P : Liste
Trouve : booléen
Debut
En algorithmique
Trouve←Faux
P L
Tant que ((P ǂ Null) et (Trouve=Faux)) faire
Si (P^.Elem==x) Alors
Trouve ← Vrai

p. 224
Mheni & SGarbouje

FinSi
P←P^.Suiv
Fin Tant que
recherche ←(Trouve)
Fin

boolean recherche (cellule *L, int x)


{
cellule *p ;
boolean trouve=false ;
p=L;
while (p !=NULL && trouve==false)
En langage C
{
if (p elem==x) Alors
trouve = true ;
p = p suiv ;
}
return (trouve) ;
}

B. Version récursive

Fonction rechercheRec (x : entier , L : liste) : booléen


Debut
Si (L =Null) alors
En algorithmique rechercheRec ←(Faux)
Sinon
Si (L^.Elem=x) alors
rechercheRec ←(Vrai)

p. 225
Mheni & SGarbouje

Sinon
rechercheRec ←(recherche (x, L^.Suiv))
Fin si
Fin si
Fin

boolean rechercheRec (cellule *L, int x)


{
if (L==NULL)
return false ;
else
En langage C
if (L elem==x)
return true ;
else
return (rechercheRec (L suiv, x)) ;
}
}

6. Suppression d’un élément d'une liste chaînée

a. Supprimer le premier élément d'une liste


La procédure suivante permet de supprimer la cellule
Tête d'une liste chaînée.

Tête
@c1 E1 @c2 E2 @c3 E3 null Null

p. 226
Mheni & SGarbouje

a – Etat initial

Tête
@c1 E1 @c2 E2 @c3 E3 null Nul

b – Etat final

Figure 4. Principe de suppression d’un élément au début de la


liste

Procédure supprimerDeb (Var L : liste)


Variables
P : Liste
Début
En algorithmique
P←L
L←L^.Suiv
Libérer ( P)
Fin

void supprimerDeb (cellule **L)


{
En langage C
cellule *p ;
p = *L ;
*L = *L suiv;

p. 227
Mheni & SGarbouje

free(p) ;
}

B. Supprimer un élément intermédiaire d'une liste

Tête
@c1 E1 @c2 E2 @c3 E3 null Null

a – Etat initial

Tête
@c1 E1 @c2 E2 @c3 E3 null Null

b – Etat final

Figure 5. Principe de suppression d’un élément à l’intérieur


de la liste

Procédure supprimer (x : entier, Var L : liste)


Variables
En algorithmique
P, Q : Liste
Début

p. 228
Mheni & SGarbouje

Si (L ǂ Null) alors
P←L
Si (L^.Elem=x) alors
L←L^.Suiv
Libérer ( P)
Sinon
Q←P^.Suiv
Tant que (Q ǂ Null) et (Q^. Elemǂx) faire
P←Q
Q←Q^.Suiv
Fin Tant que
Si (Q ǂ Null) alors
P^.Suiv←Q^.Suiv
Libérer ( Q)
Fin si
Fin si
Fin si
Fin
void supprimerDeb (cellule **L, int x)
{
cellule *p, *q ;
if (*L != NULL)
{ p = *L ;
if (L elem == x)
En langage C
{
*L = *L suiv;
free(p) ;
}
else
{

p. 229
Mheni & SGarbouje

q = p suiv ;
while (q !=NULL && q elem !=x)
{
p=q;
q = p suiv ;
}
if (q !=NULL)
{
p suiv = q suiv ;
free (p) ;
}
else
printf("cet élément n’existe pas dans la liste") ;
}
else
printf ("La liste est vide") ;
}

III. Listes doublement chaînées:


Les listes doublement chaînée sont des listes qu'on
peut parcourir dans les deux sens. Elles sont accessibles par
la tête et par la queue. Dans les deux sens parcourus, la liste
se termine par NULL.

1. Structure d’une liste doublement chainée :


La structure générale d'une liste doublement chaînée
est représentée par la figure suivante:

p. 230
Mheni & SGarbouje

Tête c3
@
Q
@c1

Null
null E1 @c2 @c1 E3 @c3 @c2 E3 null

Chaque cellule est composée en plus du champ


information par deux champs pointeurs : le premier pointe sur
l’élément précédent et le second pointe vers l’élément
suivant. Une telle structure peut être traduite en
algorithmique et en langage C comme suit :

En algorithmique En langage C
Type typedef struct
ListeD celluleD
=^CelluleD {
CelluleD = int elem ;
enregistrement struct
Elem : entier celluleD
Pred=Liste *pred ;
Suiv=Liste struct
FinEnregistrement celluleD
*suiv ;
Variables } celluleD ;
L : ListeD
celluleD *L ;

p. 231
Mheni & SGarbouje

2. Création d’une liste doublement chainée :

Procédure CréatListeD (n : Entier ; Var L, Queue :


ListeD)
Variables
P : Liste
i : Entier
Début
L← Null
Queue ← Null
Pour i de 1 à n Faire
Allouer(P)
En algorithmique
Ecrire (”Entrer un entier : ”)
Lire(P^.Elem)
P^.Pred← Null
P^.Suiv ← L
L^Pred← P
L←P
Si (i=1)
Queue← P
FinPour
Fin

void Creation_listeD (celluleD **L, celluleD **Q, int n)


{
En langage C
celluleD *p ;
int i ;
*L = *Q = NULL ;

p. 232
Mheni & SGarbouje

for (i=1 ; i<=n ; i++)


{ p = (celluleD*) malloc (sizeof (celluleD)) ;
printf ("Donner un élément ") ;
scanf ("%d", p elem) ;
p pred = NULL ;
p suiv = *L ;
*L pred = p ;
*L = p ;
if (i==1)
*Q = p ;
}
}

IV. Les Files et les Piles


Les files sont des listes chaînées qui ressemblent
beaucoup aux files d'attentes. En effet, ces dernières suivent
la loi du premier arrivé premier servi, ou encore First In First
Out. Tandis que les piles sont des listes chaînées particulières
dont l'accès est selon la règle dernier arrivé premier servi ou
encore Last In First Out. Elles sont appelées ainsi, en
référence à une pile de livres ou une pile d’assiettes car un
utilisateur ne peut accéder qu’à l’élément au sommet de la
pile.

1. Les files
En mémoire, une file est une liste chaînée dont l'ajout
d'un élément se fait à la fin (en queue) et la suppression se

p. 233
Mheni & SGarbouje

fait de la tête. Les procédures et les fonctions prédéfinies


pour les files sont:
Procédure Initialiser (var F:file) permet d'initialiser
une file vide
Procédure Ajouter (var F:file,x: entier) permet
d'ajouter un élément x à la file
Procédure Extraire (var F:file, var x: entier) permet
d'enregistrer la valeur dans x et supprimer la cellule
correspondante

a. Déclaration d'une file

En algorithmique En langage C
Type typedef struct celluleF
File =^CelluleF {
CelluleF = int elem ;
Enregistrement struct celluleF
Elem : entier *pred ;
Suiv :File struct celluleF *suiv ;
FinEnregistrement } celluleF ;

Variables celluleF *F ;
F : File

b. Procédure d'initialisation d'une file

En algorithmique Procédure Initialiser (Var F: File)

p. 234
Mheni & SGarbouje

Début
F Null
Fin

void Initialiser (celluleF **F)


En langage C {
*F = NULL ;
}
c. Procédure d'ajout
On commence par parcourir la file jusqu'à arriver au
dernier élément, puis on ajoute une cellule à la fin.

Procédure Ajouter (Var F: File, x: entier)


Variables
P,Q: File
Début
Q F
Tant que (Q^. suivǂ Null) faire
En algorithmique Q Q^.Suiv
Fin Tant que
Allouer (P)
P^.Elem x
P^.Suiv Null
Q^.Suiv P
Fin

void Ajouter (celluleF **F, int x)


En langage C {
cellule *p, *q ;
q = *F ;

p. 235
Mheni & SGarbouje

while (q !=NULL)
{
q = q suiv ;
}
p = (celluleF*) malloc (sizeof (celluleF)) ;
p elem = x ;
p suiv = NULL ;
q suiv = p ;
}
d. Procédure d'extraction
On enregistre la valeur du premier élément de la file
puis on supprime cette cellule.

Procédure Extraire (Var F: File, Var x: entier)


Variables
P:File
Début
En algorithmique Q F
F F^.Suiv
x Q^.Elem
Liberer(Q)
Fin

void Extraire (celluleF **F, int *x)


{
cellule *p ;
En langage C
q = *F ;
*x = F elem ;
F = F suiv ;
free (q) ;

p. 236
Mheni & SGarbouje

}
2. Les Piles
La pile est une liste chaînée dont l'ajout et la
suppression se font tous les deux de la tête. Les fonctions et
procédures prédéfinies pour les piles sont:
Procédure Initialiser (Var P : Pile) permet
d'initialiser une pile vide
Fonction PileVide (P : Pile) : booléen permet de
tester si une pile est vide
Procédure Empiler (Var P:Pile, x: Entier) permet
d'ajouter un élément x à la pile
Procédure Depiler (Var P:Pile, Var x: entier) permet
de supprimer le sommet de la pile et d’enregistrer la valeur
dans x
a. Déclaration d'une file

En algorithmique En langage C
Type typedef struct
Pile =^CelluleP celluleP
CelluleF = {
Enregistrement int elem ;
Elem : entier struct
Suiv : Pile celluleP
FinEnregistrement *pred ;
struct
Variables celluleP

p. 237
Mheni & SGarbouje

P : Pile *suiv ;
} celluleP ;

celluleP *P ;

b. Procédure d'initialisation d'une pile

Procédure Initialiser (Var P: Pile)


En algorithmique Début
P Null
Fin

void Initialiser (celluleP **P)


En langage C {
*P = NULL ;
}

c. Fonction pour tester si la pile est vide

Fonction PileVide (P : Pile) : booléen


Début
En algorithmique
PileVide ←(P=Null)
Fin

En langage C boolean PileVide (celluleP **P)


{

p. 238
Mheni & SGarbouje

return(*P ==NULL) ;
}
d. Procédure Empiler
Il s’agit d’une insertion en tête de liste.

Procédure Empiler (Var P: Pile, x: entier)


Variables
Q:Pile
Début
En algorithmique Allouer (Q)
Q^.Elem ←x
Q^.Suiv←P
P←Q
Fin
void Empiler (celluleP **P, int x)
{
cellule *q ;
q = (celluleP*) malloc (sizeof (celluleP)) ;
En langage C
q elem = x ;
q suiv = *P ;
*P = q ;
}
e. Procédure Dépiler
On enregistre la valeur du premier élément de la file
puis on supprime cette cellule.

Procédure Depiler (Var P: File, Var x: entier)


En algorithmique Variables
Q:Pile
Début

p. 239
Mheni & SGarbouje

Si(NON(PileVide(P))
Q←P
P ←P^.Suiv
x←Q^.Elem
Liberer(Q)
Sinon
Ecrire (" la pile est vide")
Fin Si
Fin
void Depiler (celluleP **P, int *x)
{
cellule *q ;
if ( !PileVide(*P))
{
q = *P ;
En langage C
*x = q elem ;
*P = *P suiv ;
free (q) ;
}
else
printf ("La pile est vide") ;}

V. Exercices d'applications
Exercice 1

On désire créer une file formée par n éléments de type


réel :
1. Écrire une procédure Initialiser_File(var F : File) qui
crée une file.

p. 240
Mheni & SGarbouje

2. Ecrire la procédure Enfiler (var F : File) qui ajoute à


la fin de la file un élément saisi au clavier.
3. Fonction Taille (F : File) qui calcule et retourne le nombre
d’éléments dans la file.
Exercice 2

Une société de transport, veut informatiser la liste de


ses véhicules. Pour chaque véhicule on enregistre la date de
mise en circulation, la puissance, la marque et
l’immatriculation

1- Déclarer le type enregistrement Véhicule qui


comporte les champs dateMC, Puissance_CV,
Marque, IMMAT.
2- Déclarer un type cellule, qui comporte deux
champs, l’une contient la structure véhicule et
l’autre contient un pointeur sur la cellule suivante.
3- Ecrire une procédure Creat_LV, qui prend en
paramètre le nombre de cellules et la tête L et
permet de remplir la liste par n véhicules.
4- Ecrire une fonction Nb_PCh qui retourne le nombre
de véhicules dont la puissance est supérieure à 5
chevaux.
5- Ecrire une procédure qui permet de supprimer de la
liste les véhicules dont la date de mise en
circulation est avant 2001.

p. 241
Mheni & SGarbouje

6- Ecrire une fonction Nb_Vehicule qui retourne le


nombre total de véhicules.

Exercice 3

Un restaurant désire informatiser et sauvegarder la liste des


plats de son menu.
1- Déclarez un enregistrement t_plat qui contient les
champs : numero (entier), nom (chaine),
composition (chaine) et prix (réel).
2- Déclarez un enregistrement element composé par
un champ plat de type t_plat et un champ suiv
pointeur sur l’élément suivant.
3- Ecrire une procédure creerMenu qui prend comme
paramètre la tète de la liste chaînée et permet de
créer une liste de 20 plats. Les informations sur
chaque plat sont saisies au clavier sauf le numéro
qui doit être par exemple 1 pour le premier élément
et 20 pour le dernier.
4- Le patron du restaurant désire faire une remise de
1DT sur certains plats.
Ecrire un sous programme remisePlat qui modifie
ainsi le prix de tous les plats qui coûtent plus que
7DT.
5- Ecrire une procédure copierMenu qui a pour
paramètres la tête de la liste chaînée et un tableau T.

p. 242
Mheni & SGarbouje

Ce sous programme permet de copier dans le


tableau T les plats qui ont un numéro impaire
seulement.
NB : Le tableau T est composé par des cases de
type t_plat. Déclarez son type avant d’écrire le sous
programme copieMenu().
6- Ecrire un algorithme principal qui déclare une
variable LP de type element et un tableau Tmenu.
Appelez les sous programmes précédents
respectivement pour créer la liste, effectuer la
remise, puis copier une partie de la liste dans le
tableau Tmenu.
NB : Inutile de déclarer les types enregistrement
encore une fois dans l’algorithme.

Exercice 4

Une société agroalimentaire, veut informatiser la liste


de ses produits. Pour chaque produit on enregistre la date
d'expiration, le libellé, le prix unitaire et la quantité en stock.

1- Déclarer le type enregistrement produit qui


comporte les champs dateEXP,
Libellé,Prix_U,Quantité.

p. 243
Mheni & SGarbouje

2- Déclarer un type cellule, qui comporte deux


champs, l’une contient la structure produit et l’autre
contient un pointeur sur la cellule suivante.
3- Ecrire une procédure Créat_LProduits, qui prend en
paramètre le nombre de cellules et le nom de la liste
et permet de remplir la liste LV par n produits.
4- Ecrire une fonction Nb_ Prix_2_Dinars qui retourne
le nombre de produits dont le prix est supérieur à 2
dinars
5- Ecrire une procédure qui permet de supprimer de la
liste les produits dont la date a expiré (date
d'expiration avant la date actuelle)
6- Ecrire une fonction Nb_Produits qui retourne le
nombre total de produits.

VI. Correction
Exercice 1

p. 244
Mheni & SGarbouje

1) 2) 3)

Procédure Procédure Enfiler (Var F: File) Fonction Taille( F :


Initialiser(Var F : File) Variables File):Entier
Début P,Q: File Variables
F ← Null Début P : Liste
Fin Q F Nb:entier
Tant que (Q^. suivǂ Null) faire Début
Q Q^.Suiv
Fin Tant que P ← F.Tête
Allouer (P) nb←0
Ecrire ("saisir un réel à enfiler :") Tantque (P # Nil) Alors
Lire(P^.Elem) P← P ^.Suiv
P^.Suiv Null nb←nb+1
Q^.Suiv P FinTQ
Fin Taille ←(nb)

Fin

p. 245
Mheni & SGarbouje

void initialiser (file **f) void enfiler (celluleF **F) int taille (celluleF **F)
{ { {
f = NULL; cellule *p, *q ; cellule *p ;
} q = *F ; int nb=0;
while (q !=NULL)
{ p = *F ;
q = q suiv ; while (p !=NULL)
} {
p = (celluleF*) malloc (sizeof nb++;
(celluleF)) ; p = p suiv ;
printf ("saisir un réel à enfiler"); }
scanf ("%f",&p elem) ; return(nb) ;
p suiv = NULL ; }
q suiv = p ;
}

Exercice 2 :

1)

Date:Enregistrement typedef struct {


Jour:entier int jour, mois, annee;
Mois:chaine } date;
Année:entier
fin Enregistrement typedef struct {
Vehicule:Enregistrement date dateMC;
DateMC:Date int puissance_CV;
Puissance_CV:Entier char marque[30], immat[20];
Marque:chaine } vehicule;
IMMAT:chaine

p. 246
Mheni & SGarbouje

fin Enregistrement

2)
Types typedef struct cellule{
Cellule = Enregistrement vehicule elem;
Elem : Vehicule struct cellule *suiv;
Suiv : Liste } cellule;
Fin Enregistrement
Liste = ^Cellule

3)

Procédure Creat_LV (n : void creat_LV (int n, cellule


Entier, Var L : Liste) **L)
Variables {
P : Liste cellule *P;
i : Entier int i;
Début
L← null *L=NULL;
Pour i de 1 à n Faire for (i=1;i<=n;i++)
Allouer(P) {
Ecrire(”Entrer le p = (cellule*) malloc (sizeof
jour de MC du (cellule)) ;
vehicule ”) printf(”Entrer le jour de MC
L du vehicule ”) ;
ire(P^.Elem.DateM scanf("%d",&P elem.dateM
C.jour) C.jour);
Ecrire(”Entrer le printf(”Entrer le mois de MC

p. 247
Mheni & SGarbouje

mois de MC du du vehicule ”) ;
vehicule ”) scanf("%d",&P elem.dateM
L C.mois);
ire(P^.Elem.DateM printf(”Entrer l'année de MC
C.mois) du vehicule ”) ;
Ecrire(”Entrer scanf("%d",&P elem.dateM
l'année de MC du C.annee);
vehicule ”) printf(”Entrer la puissance du
L vehicule ”) ;
ire(P^.Elem.DateM scanf("%d",&P elem.puissa
C.année) nce);
Ecrire(”Entrer la printf(”Entrer la Marque du
puissance du vehicule ”) ;
vehicule ”) scanf("%s",P elem.marque);
L printf(”Entrer
ire(P^.Elem.Puissan l'Immatriculation du vehicule
ce) ”);
Ecrire(”Entrer la scanf("%s",P elem.immat);
Marque du vehicule P suiv = *L;
”) *L = P;
L }
ire(P^.Elem.Marque }
)
Ecrire(”Entrer
l'Immatriculation du
vehicule ”)
L
ire(P^.Elem.IMMA
T)
P^.Suiv ← L

p. 248
Mheni & SGarbouje

L← P
FinPour
Fin

4)

Fonction Nb_Pch (L : Liste) : int Nb_Pch (cellule **L)


Entier
Variables {
P : Liste cellule *p;
nb : Entier int nb=0;
Début
P←L p = *L;
nb ←0 while (p!=NULL)
TantQue(P#Null) if (p elem.puissance>5)
Si(5<P^.Elem.Puissan nb++;
ce) alors return(nb);
nb ←nb+1
FinSi }
FinTQ
Nb_Pch ←(nb)
Fin

5)

Procédure supprimer (Var L void supprimer (cellule **L)


: Liste)

p. 249
Mheni & SGarbouje

Variables {
P, Q : Liste if (*L==NULL)
Début printf ("liste vide");
Si (L = Nil) Alors else
Ecrire ("liste vide") {
Sinon p=*L;
P←L while (p!=NULL)
Tant que (P ≠ null) faire {
Si if
(P^.Elem.DateMC.annee<20 (p elem.dateMC.annee<20
11) Alors 11)
Q←P {
Si (Q=L) Alors aux =p;
L ← L^.Suiv if (aux==*L)
FinSi *L=L suiv;
P←P^.Suiv p = p suiv;
Libérer(Q) free(aux);
Sinon }
P←P^.Suiv else
FinSi p = p suiv;
FinTant que }
FinSi }
Fin }

6)

Fonction Nb_vehicule (L : Liste) : Entier int Nb_ vehicule (cellule **L)


Variables
P : Liste {
cellule *p;

p. 250
Mheni & SGarbouje

nb : Entier int nb=0;


Début
P←L p = *L;
nb ←0 while (p!=NULL)
TantQue(P#Null) nb++;
nb ←nb+1 return(nb);
FinTQ
Nb_vehicule ←(nb) }
Fin

Exercice 3:

1°/ t_plat = 1) typedef struct {


enregistrement int numero;
numero : char nom[30],
entier composition[50];
nom : float prix;
chaine } t_plat;
composit
ion : chaine 2) typedef struct element{
prix : t_plat plat;
réel struct element *suiv;
Fin } cellule;
enregistrement
3) void creerMenu(element **tete)
2°/ element = {
enregistrement int i;
plat : element * aux;
t_plat
suiv : *tete = NULL;

p. 251
Mheni & SGarbouje

^element for (i=0;i<20;i++)


Fin {
enregistrement aux = (element*) malloc
(sizeof(element));
3°/ Procédure aux plat.numero = i;
creerMenu (var tete : printf("Saisir le nom du plat);
^element) scanf("%s",aux plat.nom);
Variables printf("Saisir la composition du
i : entier plat);
aux : ^element scanf("%s",aux plat.composition)
Début ;
tete ← nil printf("Saisir le prix du plat);
Pour i de 1 à 20 scanf("%f",&aux plat.prix);
faire aux suiv=*tete;
allouer (aux) *tete=aux;
}
aux↑plat.numero ← i }
Ecrire ("Saisir
le nom du plat") 4) void remisePlat (element **tete)
Lire {
(aux↑plat.nom) element *cour;
Ecrire ("Saisir
la composition du cour =*tete;
plat") while (cour!=NULL)
Lire {
(aux↑plat.composition) if (cour plat.prix >7)
Ecrire ("Saisir cour plat.prix -= 7;
le prix du plat") cour = cour suiv;
Lire }
(aux↑plat.prix) }

p. 252
Mheni & SGarbouje

aux↑suiv ←
tete 5) void copierMenu(element
tete ← aux **tete, t_plat t[])
Fin Pour {
Fin int i=0;
element *cour;
4°/ Procédure
remisePlat(var tete : cour =*tete;
^element) while (cour!=NULL)
Variables {
cour : ^element if (cour plat.numero%2==1)
Début {
cour ← tete t[i] = cour plat;
Tant que (cour≠ i ++;
nil) faire }
Si cour = cour suiv;
(cour↑plat.prix > 7) }
alors }

cour↑plat.prix ← 7) programme menu.c


cour↑plat.prix–7
main ()
Fin Si
{
cour ←
element *LP;
cour↑suiv t_plat Tmenu[10];
FinTQ
Fin creerMenu(&LP);
remisePlat(&LP);
5°/ tabelem = tableau copierMenu(&LP,Tmenu);
[1..10] de t_plat }
Procédure copierMenu

p. 253
Mheni & SGarbouje

(tete : ^element, var T :


tabelem)
Variables
cour : ^element
i :entier
Début
cour=tete
Tant que (cour≠
nil) faire
Si
(cour↑plat.numero % 2
= 1) alors
i
← i+1
T
[i] ←
cour↑pla
t
FinSi
cour ←
cour↑suiv
FinTQ
Fin

7°/ Algorithme Menu


Variables
LP : ^element
Tmenu :
tabelem
Début

p. 254
Mheni & SGarbouje

creerMenu (LP)
remisePlat (LP)
copierMenu
(LP,Tmenu)
Fin

Exercice 4 :

1)

Date:Enregistrement typedef struct {


Jour:entier int jour, mois, annee;
Mois:chaine } date;
Année:entier
fin Enregistrement typedef struct {
Produit:Enregistrement date dateEXP;
DateExp:Date char libelle[20];
Libellé:chaine float prix_U ;
Prix_U:réel int qnte;
quantite:entier } produit;
fin Enregistrement
2)
Types typedef struct cellule{
Cellule = Enregistrement produit elem;
Elem : Produit struct cellule *suiv;
Suiv : Liste } cellule;
Fin Enregistrement
Liste = ^Cellule

p. 255
Mheni & SGarbouje

3)

Procédure void creat_LProduit (int n,


Creat_LProduit (n : cellule **L)
Entier, Var L : Liste) {
Variables cellule *P;
P : Liste int i;
i : Entier
Début *L=NULL;
L← null for (i=1;i<=n;i++)
Pour i de 1 à n Faire {
Allouer(P) p = (cellule*) malloc (sizeof
Ecrire(”Entrer le (cellule)) ;
jour d'expiration du printf(”Entrer le jour
produit ”) d'expiration du produit : ”) ;
L scanf("%d",&P elem.dateE
ire(P^.Elem.DateM XP.jour);
C.jour) printf(”Entrer le mois
Ecrire(”Entrer le d'expiration du produit : ”) ;
mois d'expiration du scanf("%d",&P elem.dateE
produit ”) XP.mois);
L printf(”Entrer l'année
ire(P^.Elem.DateM d'expiration du produit : ”) ;
C.mois) scanf("%d",&P elem.dateE
Ecrire(”Entrer XP.annee);
l'année d'expiration printf(”Entrer le libelle du
du produit ”) produit ”) ;
L scanf("%s",P elem.libelle);
ire(P^.Elem.DateM printf(”Entrer le prix du

p. 256
Mheni & SGarbouje

C.année) produit”) ;
Ecrire(”Entrer le scanf("%f",&P elem.prix_U
libelle du produit ”) );
L printf(”Entrer la quantité du
ire(P^.Elem.libelle) produit ”);
Ecrire(”Entrer le scanf("%d",&P elem.
prix du produit ”) quantite);
L P suiv = *L;
ire(P^.Elem.prix_U) *L = P;
Ecrire(”Entrer la }
quantité du produit }
”)
L
ire(P^.Elem.quantite
)
P^.Suiv ← L
L← P
FinPour
Fin

4)

Fonction Nb_ Prix_2_Dinars int Nb_ Prix_2_Dinars


(L : Liste) : Entier (cellule **L)
Variables
P : Liste {
nb : Entier cellule *p;
Début int nb=0;
P←L
nb ←0 p = *L;
TantQue(P#Null) while (p!=NULL)

p. 257
Mheni & SGarbouje

Si(5<P^.Elem.Puissance if (p elem.prix>2)
) alors nb++;
nb ←nb+1 return(nb);
FinSi
FinTQ }
Nb_ Prix_2_Dinars
←(nb)
Fin

5)

Procédure supprimer (Var L void supprimer (cellule **L)


: Liste)
Variables {
P, Q : Liste if (*L==NULL)
Début printf ("liste vide");
Si (L = Nil) Alors else
Ecrire ("liste vide") {
Sinon p=*L;
P←L while (p!=NULL)
Tant que (P ≠ null) faire {
Si if
(P^.Elem.DateEXP.annee<= ((p elem.dateEXP.annee<=
2015) ET (p 2015) &&
P^.Elem.DateEXP.mois<=06 (p elem.dateEXP.mois<=06
) ET ) &&
P^.Elem.DateEXP.jour<=15) p elem.dateEXP.jour<=15))
) Alors {
Q←P aux =p;
Si (Q=L) Alors if (aux==*L)
L ← L^.Suiv *L=L suiv;

p. 258
Mheni & SGarbouje

FinSi p = p suiv;
P ←P^.Suiv free(aux);
Libérer(Q) }
Sinon else
P←P^.Suiv p = p suiv;
FinSi }
FinTant que }
FinSi }
Fin

6)

Fonction Nb_produits (L : Liste) : Entier int Nb_ produits (cellule **L)


Variables
P : Liste {
nb : Entier cellule *p;
Début int nb=0;
P←L
nb ←0 p = *L;
TantQue(P#Null) while (p!=NULL)
nb ←nb+1 nb++;
FinTQ return(nb);
Nb_produits ←(nb)
Fin }

p. 259
Mheni & SGarbouje

Les arbres binaires


Certaines données informatiques sont représentées de
manière hiérarchique, telle que l'organisation interne des
fichiers en mémoire. Cette structure arborescente rend l'accès
aux données plus facile et efficace. Ces deux raison font des
arbres une des notions fondamentales en informatiques.
Dailleurs, il existe divers exemples d'arbres : Arbres
syntaxiques, arbres génécologiques, arbres lexicographique…

I. Définition:
Un arbre est un ensemble de nœuds organisés sous
forme d'arborescence, de façon à ce que chaque nœud
possède un ascendant unique sauf le nœud racine qui n'en a
aucun. On appelle arbre binaire, un arbre où chaque noeud ne
peut avoir que deux noeuds fils au maximum.

Un arbre est caractérisé par :


• une racine : un noeud qui n'a aucun parent.
• des noeuds reliés par des arcs
• des feuilles : ce sont les noeuds qui n'ont pas de fils
• une hauteur ou profondeur : c'est le nombre de
niveaux qui existent dans l'arbre

p. 260
Mheni & SGarbouje

Chaque nœud possède une étiquette, qui peut être une


valeur ou bien un enregistrement, et deux pointeurs l'un sur le
fils gauche et l'autre sur le fils droite. On appelle arbre
binaire de recherche (ABR), un arbre binaire trié tel que la
valeur de chaque noeud est:

- inférieure à toutes les valeurs des noeuds du sous


arbres à droite
- supérieure à toutes les valeurs des noeuds du sous
arbre à gauche

Exemple :

p. 261
Mheni & SGarbouje

II. Déclaration d'un arbre binaire


Pour créer un arbre binaire dont le type des valeurs
des nœuds est un entier, on déclare un type composé d'un
champ donné de type entier et deux champs pointeurs sur les
fils gauche et fils droite.

En algorithmique En langage C
Type typedef struct arbre
Nœud = enregistrement {
valeur : entier int val ;
filsG : ^Noeud struct arbre *filG ;
filsD : ^Noeud struct arbre *filD ;
Fin Enregsitrement } arbre ;
Arbre : ^Nœud

p. 262
Mheni & SGarbouje

III. Création d'un arbre binaire de recherche

Pour créer un arbre binaire trié, il suffit d'ajouter les


noeuds un à un à leur emplacement en faisait appel à la
procédure récursive ajouterNoeud qui doit comparer la valeur
à insérer avec celle du noeud actuel. Lorsque la valeur à
ajouter est inférieure, l'insertion se fait dans le sous arbre
gauche, sinon dans le sous arbre droite.

En algorithmique En langage C

Procédure ajouterNoeud (x : Entier , Var B : void ajoutNoeud (int x, arbre **B)


Arbre) {
Variables if (*B==NULL)
aux : Arbre {
Début aux = (arbre*) malloc(sizeof(arbre));
Si (B = Nil) Alors aux val = x;
Allouer (aux) aux filG = NULL;
aux^.valeur ← x aux filD = NULL;
aux^.filsG ← Nil }
aux^.filsD← Nil else
Sinon {
Si (x <= B^.valeur) Alors if (x<= *B x)
ajouterNoeud (x, ajoutNoeud(x, *B filG);
B^.filsG) else;
Sinon ajoutNoeud(x, *B filD);
ajouterNoeud (x, }
B^.filsD) } arbre ;
FinSi

p. 263
Mheni & SGarbouje

FinSi
Fin

Dans l'algorithme principal, on se contenante de


définir une boucle dans laquelle on saisit la valeur à insérer et
on appelle la procédure ajoutNoeud comme suit :

En algorithmique En langage C
Algorithme CreationArbre main()
Variables {
racine : Arbre arbre *racine=NULL;
e : entier int e;
Début
racine = Nil do
Répéter {
Ecrire(”Entrer un entier : ”) printf ("Entrer un entier :");
Lire(e) scanf("%d",&e);
ajouterNoeud (x,racine) ajoutNoeud(e, &racine);
Jusqu'à (e = 0) } while (e!=0);
Fin. }

IV. Parcours d'un arbre binaire

Le parcours d'un arbre binaire se fait toujours de la


racine vers les feuilles et de gauche à droite. On utilise
souvent une procédure récursive mais il est possible de le
faire de manière itérative.
Il existe trois manières de parcourir récursivement un arbre :

p. 264
Mheni & SGarbouje

• méthode préfixe : le noeud est traité en premier


ensuite le fils gauche puis le fils droite.
• méthode infixe : le fils gauche est traité en premier
ensuite le noeud puis le fils droite
• méthode postfixe : le fils gauche est traité puis le fils
droite et enfin le noeud actuel
Exemple : Considérons l'arbre binaire présenté ci-dessous

L'affichage 12 1 91 67 7 82 61 est appelé parcourt préfixe.


L'affichage 91 1 67 12 7 82 61 est appelé parcourt infixe ou
symétrique.
L'affichage 91 67 1 61 82 7 12 est appelé parcourt postfixe.
Voici la description algorithmique des trois procédures de
parcours.

En algorithmique En langage C

p. 265
Mheni & SGarbouje

Procédure Affichage_prefixe (a : Arbre) void prefixe (arbre *a)


Début {
Si (a ≠ nil)alors if (a != NULL)
Ecrire (a^.valeur) {
Affichage_prefixe (a^.filG) printf ("%d", a val);
Affichage_prefixe (a^.filsD) prefixe(a filsG);
FinSi prefixe(a filsD);
Fin }
}
Procédure Affichage_infixe (a : Arbre) void infixe (arbre *a)
Début {
Si (a ≠ nil)alors if (a != NULL)
Affichage_infixe (a^.filG) {
Ecrire (a^.valeur) infixe(a filsG);
Affichage_infixe (a^.filsD) printf ("%d", a val);
FinSi infixe(a filsD);
Fin }
}
Procédure Affichage_postfixe (a : Arbre)
Début void postfixe (arbre *a)
Si (a ≠ nil)alors {
Affichage_postfixe (a^.filG) if (a != NULL)
Affichage_postfixe (a^.filsD) {
Ecrire (a^.valeur) postfixe(a filsG);
FinSi postfixe(a filsD);
Fin printf ("%d", a val);
}
}

p. 266
Mheni & SGarbouje

V. Recherche dans un arbre binaire ordonné

Il existe deux versions de fonction pour chercher un


élément dans un arbre binaire de recherche ; la version itérative et
la version récursive. La recherche consiste à parcourir l'arbre en
commençant par la racine. Ensuite, on parcourt le sous arbre
gauche ou bien le sous arbre droite selon la valeur de la racine puis
de chaque nœud. La recherche s'arrête dès que la valeur est trouvée
ou lorsqu'on atteint toutes les feuilles.

a. Recherche itérative

En algorithmique En langage C
Fonction rechercheIter (a : Arbre , n: entier) :
booléen int rechercheIter (arbre *a, int n)
Variables {
trouvee : booléen int trouvee=0;
Début
trouvee ← faux while (a != NULL && trouvee==0)
Tant que (a ≠ nil ET trouvee = faux) {
faire if (n == a val )
Si (n = a^.valeur) alors trouvee = 1;
trouvee ← vrai else
Sinon if (n < a val)
Si (n < a^.valeur) alors a = a filsG;
a ← a^.filsG else
Sinon a = a filsD;
a ← a^.filsD }
FinSi return (trouvee);
FinSi }

p. 267
Mheni & SGarbouje

FinTantque
rechercheIter ←(trouvee)
Fin.

b. Recherche récursive

En algorithmique En langage C
Fonction rechercheRec (a : Arbre , n: entier) :
booléen int rechercheRec (arbre *a, int n)
Début {
Si (a = nil) alors if (a == NULL)
rechercheRec ←(faux) return 0;
Sinon else
Si (n = a^.valeur) alors {
rechercheRec ←(vrai) if (n == a val )
Sinon return 1;
Si (n < a^.valeur) alors else
rechercheRec ←(rechercheRec(a^.filsG,n)) if (n < a val)
Sinon return(rechercheRec(a filsG, n);
rechercheRec ←(rechercheRec(a^.filsG,n)) else
FinSi return(rechercheRec(a filsD, n);
FinSi }
FinSi }
Fin.

VI. Suppression d'un élément dans un ABR

La suppression d'un noeud dans un arbre binaire de


recherche est une opération délicate. D'abord, il faut identifier

p. 268
Mheni & SGarbouje

le noeud qui porte la valeur à supprimer. Ensuite, nous avons


trois possibilités :

• 1er cas : il ne possède aucun fils (c'est une feuille) : le


noeud est supprimé directement

• 2ème cas : il possède un seul fils, ce fils prendra la place


du noeud à supprimer,

• 3 ème cas : il possède deux fils non nil, dans ce cas, il


faudra chercher dans le sous arbre gauche, le fils qui a la
valeur la plus grande pour prendre la place du noeud à
supprimer. Ainsi, il suffit de copier la valeur de ce fils
dans le noeud et supprimer ce fils comme le montre cette
figure :

p. 269
Mheni & SGarbouje

Voici les procédures et fonctions qui effectuent cette


suppression :

En algorithmique En langage C

Procédure suppression (Var a : Arbre , void suppression (arbre **a, int n)


n:entier) {
if (*a == NULL)
Début printf("Erreur : Arbre vide !");
else
Si (a = nil) alors
{
Ecrire ("Erreur : Arbre vide !")
if (n == *a val )
Sinon // arbre non vide
supprimerNoeud(a);
Si (n = a^.valeur) alors
else
supprimerNoeud(a)
if (n < *a val)
Sinon
suppression(*a filsG, n);
Si (n < a^.valeur) alors
else
suppression (a^.filsG, n)
suppression(*a filsD, n);
Sinon
}
suppression (a^.filsD, n)
}
FinSi
FinSi
FinSi
Fin.
void supprimerNoeud (arbre **a)
{
Procédure supprimerNoeud (Var a : Arbre)
arbre *aux, *f;
Variables
aux, f : Arbre if (*a filsG == NULL)
{
aux = *a;

p. 270
Mheni & SGarbouje

Début *a = *a filsD
free(aux);
Si (a^.filsG = nil) alors }
aux ← a else
a ← a^.filsD {
liberer (aux) if (*a filsD == NULL)
Sinon {
Si (a^.filsD = nil) alors aux = *a;
aux ← a *a = *a filsG
a ← a^.filsD free(aux);
liberer (aux) }
Sinon else
f ← chercherFils (a^.filsG) {
a^.valeur = f^.valeur f = chercherFils(*a filsG);
suppression (a^.filsG, f^.valeur) *a val = f val;
FinSi suppression(*a filsG, f val);
FinSi }
Fin. }
}
Fonction chercherFils (a : Arbre) : Arbre
Début
Si (a^.filsD = nil) alors arbre* chercherFils (arbre *a)
chercherFils ←(a) {
Sinon if (a filsD == NULL)
chercherFils ←(chercherFils(a^.filsD) return(a);
FinSi else
Fin. return (chercherFils(a filsG);
}

p. 271
Mheni & SGarbouje

VII. Exercices
Exercice 1 :

1) Déclarer un type structuré t_arbre qui définit un arbre


binaire de valeurs réelles.
2) Ecrire une fonction récursive hauteur qui prend en
paramètre la racine d'un arbre et retourne la hauteur de cet
arbre.
3) Ecrire une fonction récursive nbNoeuds qui calcule et
retourne le nombre d'éléments (ou noeuds) qui composent un
arbre donné en paramètre.
Exercice 2 :

Soit un arbre binaire composé d’expressions arithmétiques


(voir figure).

1) Ecrire un type enregistrement t_char qui décrit la


structure donnée par la figure.
2) Ecrire une procédure equation qui permet d’afficher
l’arbre à l’écran de la manière suivante : 5 * 3 % 4 + 2

Exercice 3 :

1) Ecrire une fonction existe qui retourne vrai si x (un réel)


est dans l'arbre donné en paramètre.

p. 272
Mheni & SGarbouje

2) Ecrire une procédure insérer qui vérifie si un réel est


dans l'arbre donné en paramètre sinon il l'insère dans le
sous arbre qui possède le moins de noeuds. Exemple : On
voudrait insérer 12 dans un arbre où le sous arbre gauche
de la racine compte 6 élément tandis que le sous arbre
droite de la racine contient 8 éléments. 12 sera inséré à
gauche.
NB : Vous pouvez utiliser les fonctions de l'exercice 1.
3) Ecrire une fonction somme qui retourne la somme des
valeurs de tous les noeuds
4) Ecrire un algorithme ArbreRéel qui crée un arbre
composé de 20 éléments puis affiche la somme de leurs
valeurs.

VIII. Correction exercices


Exercice 1 :

1) Type 1) typedef struct t_arbre


{
t_arbre = float val ;
Enregistrement struct t_arbre *filG ;
val : réel struct t_arbre *filD ;
filsG : } t_arbre ;
^t_arbre
filsD :
^t_arbre 2) int hauteur (t_arbre *A)
Fin Enregistrement {
if (A==NULL)
2) Fonction hauteur (A : return 0;

p. 273
Mheni & SGarbouje

^t_arbre) else
return ( 1 + max ( hauteur
Début (A filsG),
Si (A = nil) alors hauteur(A filsD));
hauteur ←(0) }
Sinon
hauteur ←( 1 + max ( int max (int a, int b)
hauteur (A^.filsG), {
hauteur(A^.filsD)) if (a>b)
FinSi return (a);
Fin else
return (b);
Fonction max (a:entier, }
b:entier)
3) int nbNoeuds (t_arbre *A)
Début {
Si (a>b) alors if (A==NULL)
max ←(a) return 0;
Sinon else
max ←(b) return ( 1 + nbNoeuds
FinSi (A filsG) +
Fin nbNoeuds(A filsD));
}
3) Fonction nbNoeuds (A :
^t_arbre)

Début
Si (A = nil) alors
nbNoeuds ←(0)
Sinon
nbNoeuds ←( 1 +

p. 274
Mheni & SGarbouje

nbNoeuds (A^.filsG) +
nbNoeuds(A^.filsD))
FinSi
Fin

Exercice 2 :

1) Type 1) typedef struct t_char


{
t_char = Enregistrement char val ;
val : char struct t_char *filG ;
filsG : ^t_char struct t_char *filD ;
filsD : ^t_char } t_arbre ;
Fin Enregistrement

2) Procédure equation (A : 2) void equation (t_arbre


^t_char) *A)
{
Début if (A!=NULL)
Si (A ≠ nil) alors equation (A filsG);
equation (A^.filsG) printf ("%c ", A val);
Ecrire (A^.val) equation (A filsD);
equation (A^.filsD) }
FinSi
Fin

Exercice 3 :

1) On utilise le type t_arbre de 1) int existe (t_arbre *A, float


l'exercice 1 x)
{

p. 275
Mheni & SGarbouje

On définit Arbre = ^t_arbre if (A == NULL) alors


return 0;
Fonction existe (A : Arbre, x : else
réel) : booléen { if (A val == x)
return 1;
Début else
Si (A = nil) alors return ( existe
existe ←(faux) (A filsG, x) ||
Sinon existe(A filsD, x));
Si (A^.val = x) alors }
existe ←(vrai)
Sinon }
existe ←( existe
(A^.filsG, x) OU
existe(A^.filsD, x))
FinSi
FinSi 2) void inserer (t_arbre **A,
Fin float x)
{
t_arbre *aux;
if (existe(*A, x))
2) Procédure inserer (var A : printf ("Cette valeur existe
Arbre, x : réel) déjà");
else
Variables {
aux : Arbre if (*A==NULL)
{
Début aux = (t_arbre*) malloc
Si (NON(existe (A, x)) alors (sizeof(t_arbre));
Si (A = nil) alors aux val = x;
allouer (aux)

p. 276
Mheni & SGarbouje

aux^.val ← x aux filsG = nil;


aux^.filsG ← nil aux filsD = nil;
aux^.filsD ← nil A = aux;
A ← aux }
Sinon else
Si(nbNoeuds(A^.filsG)< {
nbNoeuds(A^.filsD)) alors if ( nbNoeuds (
inserer (A^.filsG, x) *A filsG ) <
Sinon nbNoeuds(*A filsD))
inserer (A^.filsG, x) inserer(A filsG, x);
FinSi else
FinSi inserer (A filsD, x);
Sinon }
Ecrire ("Cette valeur existe }
déjà") }
FinSi
Fin

3) Fonction somme (A : 3) int somme (t_arbre *A)


Arbre) : entier {
if (A==NULL)
Début return 0;
Si (A = nil) alors else
somme ←(0) return ( A val + somme
Sinon (A filsG) +
somme ←( A^.val + somme(A filsD));
somme (A^.filsG) + }
somme(A^.filsD))
FinSi

p. 277
Mheni & SGarbouje

Fin 4) main ()

4) Algorithme ArbreReel {
t_arbre * racine;
Type int i;
float x;
t_arbre = Enregistrement
val : réel racine=NULL;
filsG : for ( i = 0 ; i < 20 ; i++)
^t_arbre {
filsD : printf ("Saisir un réel :");
^t_arbre scanf ("%f",&x);
Fin Enregistrement inserer (&racine, x);
}
Arbre = ^t_arbre printf ("La somme des
éléments de l'arbre = ",
Variables
somme (racine));
racine : Arbre
x : réel }
i : entier

Début

racine ← nil
Pour i de 1 à 20 faire
Ecrire ("Saisir un réel :")
Lire (x)
inserer (racine, x)
Fin Pour
Ecrire ("La somme des

p. 278
Mheni & SGarbouje

éléments de l'arbre = ",


somme (racine))
Fin

Problèmes
Dans cette section nous avons choisit un ensemble de
problèmes pris des devoirs de contrôle et des examens durant
toute l'année universitaire.

I. Enoncés

Problème n°1

Thèmes : fonction et procédure, chaîne de caratère

Type : Examen du 1er semestre

Un entier strictement positif K est dit nombre de Kaprekar si


lorsqu'on élève K au carré (C=K2, C est composé de n
chiffres), la somme du nombre composé des m chiffres de
droite de C au nombre composé des n-m chiffres de gauche
de C redonne le nombre d'origine K.

p. 279
Mheni & SGarbouje

Exemples : 9, 45 et 297 sont des nombres de Kaprekar :

K=9 => C= 92 = 81 et 1+8=9

K=45 => C= 452 =2025 => n=4 Les combinaisons


possibles :

m=1 5 + 202 ≠ 45
m=2 25 + 20 = 45
m=3 025 + 2 ≠ 45
L’une des combinaisons vérifie la propriété donc 45 est
un nombre Kaprekar

K=297 => C= 2972 =88209 => n=5 Les


combinaisons possibles :

m=1 9 + 8820 ≠ 297


m=2 09 + 882 ≠ 297
m=3 209 + 88 = 297
m=4 8209 + 8 ≠ 297

L’une des combinaisons vérifie la propriété => donc 297


est un nombre Kaprekar

Travail demandé :

On vous demande d‘écrire les algorithmes des procédures et


des fonctions suivantes :

p. 280
Mheni & SGarbouje

1. Procédure lecture (var K: entier) qui permet de lire un


entier strictement positif K.
2. Fonction longueur (C : entier) : entier qui, étant donné
un entier C, détermine le nombre de ses chiffres.
3. Procédure décompose (C, m : entier, var CD : entier,
var CG : entier)
Qui, étant donné 2 entiers C et m, détermine deux entiers
CD et CG comme suit :
- CD est composé des m chiffres de droite de C.
- CG est composé des chiffres restants.
Exemple :
Si C=1234, m=3 C1=234, C2=1

4. Fonction VERIF KAPREKAR (K : entier): booléen,


qui retourne vrai si K est un nombre de Kaprekar et faux
sinon.

5. Ecrire l’algorithme principal KAPREKAR qui demande


à l'utilisateur de fournir un entier k, et indique s'il s'agit
d'un nombre de Kaprekar.

Problème n°2

Thèmes : fonction et procédure, chaîne de caratère

Type : Examen du 1er semestre

p. 281
Mheni & SGarbouje

Un instituteur cherche à vérifier si ses élèves ont appris à


réciter l’alphabet lettre par lettre dans l’ordre. Pour ceci, il
vous demande de lui développer l’algorithme d’un
programme permettant d’évaluer les élèves de la classe. Cet
algorithme fera appel aux modules cités ci- dessous qu’on
vous demande de développer leurs algorithmes.
Soient les déclarations suivantes :

CONST NMAX=100
tabc : tableau (1..26) caractère
tabe : tableau (1..NMAX) entier
tabpf : tableau (1..26*NMAX) entier
tabf : tableau (1..26*NMAX) caractère
Exemple :
N : nombre d’élèves de la classe.

N=4

L’élève n° 1 a rempli le tableau REPONSE comme suit :


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23

REPONSE A B E D C F G H I J K L N M O P Q R S T U V W

L’élève n° 2 a rempli le tableau REPONSE comme suit :

p. 282
Mheni & SGarbouje

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23

REPONSE A B C D E F G H I J K L M N O P Q R S T U V W

L’élève n° 3 a rempli le tableau REPONSE comme suit :

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

REPONSE A B C D A F G H I J K L M N O P Q S R T U V W X Y Z

L’élève n° 4 a rempli le tableau REPONSE comme suit :

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

REPONSE A B C D A F G H I J K L M N O P Q R S T U V W X Y Z

Le programme produit les tableaux suivants :

1 2 3 4

FAUTE 4 0 3 0

Les fautes de l’élève n°1 Les fautes de l’élève n°3

TF E C N M A S R

1 2 3 4 5 6 7

p. 283
Mheni & SGarbouje

26*NMAX

TP 3 5 13 14 5 18 19

Les positions des fautes de l’élève n°1

Travail demandé :

On vous demande d‘écrire les algorithmes des procédures et


des fonctions suivantes :

1. Procédure lecture (Var N : entier) qui permet de saisir


le nombre d’élèves N. (3≤N≤100).
2. Procédure REMPLIR (VAR REPONSE: tabc) qui
permet à un élève de saisir dans un tableau REPONSE les
lettres de l’alphabet dans l’ordre. Les lettres doivent être
majuscules.
3. Fonction TESTFAUTE (l : caractère, pos : entier) :
booléen qui permet de vérifier si une lettre donnée en
paramètre est bien placée étant donnée sa position dans le
tableau.
La fonction retourne VRAI si la lettre est dans sa place ou
FAUX sinon (une lettre mal placée représente une faute).

Exemple :
Pour l’élève n°1 :
TESTFAUTE ("E", 3) retourne faux car le rang de la
lettre "E" dans l’alphabet est 5≠3.

p. 284
Mheni & SGarbouje

TESTFAUTE ("J", 10) retourne vrai car le rang de la


lettre "J" dans l’alphabet est 10.

4. Fonction NBFAUTE (REPONSE: tabc) : entier qui


permet de retourner le nombre de fautes présentes dans le
tableau REPONSE.
Exemple :
Dans le premier tableau ci- dessus les lettres "E", "C",
"N" et "M" ne sont pas dans ses places, donc il y a 4
fautes.
5. Fonction CALCUL (FAUTE :tabe, N :entier) : entier
qui permet de calculer et de retourner le nombre total de
fautes des élèves dans la classe.
Exemple :
1 2 3 4

FAUTE 4 0 3 0

La fonction devra retourner 7.

6. Procédure AFFICHE (FAUTE :tabe, N :entier) qui


affiche les numéros des élèves qui ont bien récités
l’alphabet.
Exemple :
1 2 3 4

FAUTE 4 0 3 0

Les élèves n°2 et 4 ont bien récités l’alphabet.

p. 285
Mheni & SGarbouje

7. Procédure AJOUTERTFPF (REPONSE :tabc,Var


TF :tabf, Var PF : tabpf, Var j :entier)
Qui permet d’ajouter dans le tableau TF et PF à partir de la
position j pour un élève les fautes commis ainsi que leurs
positions dans le tableau REPONSE.
Exemple :
Pour l’élève n°1 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23

REPONSE A B E D C F G H I J K L N M O P Q R S T U V W

j=1

TF E C N M

1 2 3 4
26*NMAX

TP 3 5 13 14

Pour l’élève n°2 :


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23

REPONSE A B C D E F G H I J K L M N O P Q R S T U V W

j=5

TF E C N M

1 2 3 4
26*NMAX

p. 286
Mheni & SGarbouje

TP 3 5 13 14

Pour l’élève n°3 :


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23

REPONSE A B C D A F G H I J K L M N O P Q S R T U V W

j=5

TF E C N M A S R

1 2 3 4 5 6 7
26*NMAX

TP 3 5 13 14 5 18 19

8. Procédure AFFICHRESULTAT (N : entier, FAUTE :


tabe, TP : tabpf, TF :tabf)
Qui permet d’afficher le nombre de fautes pour chaque
élève, ainsi que la liste de toutes les fautes et leurs
positions respectives. (Respecter le format d’affichage ci-
dessous).
Exemple :
Pour l’élève n°1 : Il a commis 4 fautes :
"E" dans la position 3.
"C" dans la position 5.
"N" dans la position 13.
"M" dans la position 14.
Pour l’élève n°2 : Il a bien récité l’alphabet..

p. 287
Mheni & SGarbouje

9. Ecrire l’algorithme principal qui, en faisant appel aux


modules développés ci- dessus, permet de :
- Saisir le nombre N des élèves de la classe.
- Remplir pour chaque élève le tableau REPONSE
puis calculer son nombre de fautes et le placer le
nombre obtenu dans le tableau FAUTE.
- Calculer puis afficher le nombre total de fautes des
élèves.
- Afficher les numéros des élèves qui ont bien récités
l’alphabet.
- Afficher le nombre de fautes pour chaque élève, ainsi
que la liste de toutes les fautes et leurs positions
respectives.

Problème n°3

Thèmes : fonction et procédure, chaîne de caratère

Type : Examen du 1er semestre

Beaucoup d’applications informatiques proposent un choix


d’actions à l’utilisateur à l’aide d’un menu. L’algorithme à
écrire va afficher un menu, lire le choix de l’utilisateur et
réaliser l’action demandée.

p. 288
Mheni & SGarbouje

Cet algorithme est composé d’un menu qui exécute le choix


de l’utilisateur par le biais d’un caractère, celui-ci doit être
compris entre ′A′ et ′H′.

Après l’affichage du menu, l’utilisateur va choisir l’action à


mener grâce à une structure de type Selon...faire. Par
exemple, si le choix de l’utilisateur est ′C′, le message
affiché sera « Modification d’un élément du tableau ». Après
chaque action l’affichage du menu apparaît de nouveau pour
que l’utilisateur demande une nouvelle action. Lorsque le
choix demandé par l’utilisateur est ′H′, l’algorithme s’arrête.

Le menu affiche sur l’écran :

[A] – Création du tableau

[B] – Affichage du tableau

[C] – Modification d’un élément du tableau

[D] – Ajout d’un élément à la fin du tableau

[E] – Suppression d’un élément du tableau

[F] – Insertion d’un élément dans le tableau

[G] – Affichage de l’élément le plus fréquent dans le


tableau

p. 289
Mheni & SGarbouje

[H] – Quitter

Remarque:

Vous devez traiter les parties suivantes (de A à H), chaque


partie est une question. La question finale [I] est de
regrouper les appels à ces fonctions et procédures afin de
créer un algorithme, qui traite les choix (ci-dessus d'un
utilisateur utilisant la structure selon)

Objectifs :

L’algorithme répète l’affichage du menu et selon le choix de


l’utilisateur exécute le traitement correspondant jusqu'à ce
que le choix soit ‘I’. Notre objectif est d’écrire un algorithme
intitulé MENU permettant de faire les traitements
correspondant aux différents choix possibles du menu.

On utilisera la constante Max et le type tab définis par :

CONSTANTE Max=25

TYPE tab = TABLEAU (1..Max) entier

p. 290
Mheni & SGarbouje

Explication du menu :

[A] – Création du tableau :

Si l’utilisateur tape la lettre ′A′, le message affiché sera


« Création du tableau » : lecture de la taille du tableau
(10≤N≤Max), et remplissage du tableau T par des entiers.

Les entiers du tableau devront appartenir à l’intervalle


[100,1000[.

- Ecrire cette procédure de remplissage

[B] – Affichage du tableau

Si l’utilisateur tape la lettre ′B′, le message affiché sera


« Affichage du tableau» : Affichage des éléments de T
précédés de leur rang.

- Ecrire la procédure d'affichage

[C] – Modification d’un élément du tableau

Si l’utilisateur tape la lettre ′C′, le message affiché sera


« Modification d’un élément du tableau» :

L’utilisateur donne la position pm de l’élément à modifier


(avec 1≤pm≤N) et la nouvelle valeur du nombre (avec
100≤val<1000), puis la range dans le tableau à la place
voulue.

p. 291
Mheni & SGarbouje

Exemple :

N=11, pm=4, val=567

L’état de tableau T avant la modification de T[pm]

T 726 501 898 87 147 501 916 910 223 701 726
1
1 2 3 4 5 6 7 8 9 10 11
L’état de tableau T après la modification de T[pm]

T 726 501 898 56 147 501 916 910 223 701 726
7
1 2 3 4 5 6 7 8 9 10 11
-Ecrire une procédure qui permet de modifier un élément
dans un tableau

[D] – Ajout d’un élément à la fin du tableau

Si l’utilisateur tape la lettre ′D′, le message affiché sera


« Ajout d’un élément à la fin du tableau» :

L’utilisateur donne la valeur val à ajouter (avec


100≤val<1000) et la range dans le tableau à la suite des
valeurs existantes, un nouveau tableau sera généré.

Exemple :

N=11, val=601

L’état de tableau T1 avant l’ajout de val

p. 292
Mheni & SGarbouje

T 804 955 320


80 426 912 249 426 101 861 314
4
1 2 3 4 5 6 7 8 9 10 11
L’état de tableau T2 égal au tableau T1 suivi par
l'élément ajouté

T 804 955 320 80 426 912 249 426 101 861 314 601
4
1 2 3 4 5 6 7 8 9 10 11 12
- Ecrire une procédure qui permet d'ajouter une valeur à la fin
d'un tableau, le résultat est un nouveau tableau de dimension
N+1

[E] – Suppression d’un élément du tableau

Si l’utilisateur tape la lettre ′E′, le message affiché sera


« Suppression d’un élément du tableau» :

L’utilisateur donne la position ps de l’élément à supprimer


(avec 1≤ps≤N) et effectue sa suppression en décalant vers la
gauche tous les éléments suivants.

Exemple :

N=11, ps=8 l’élément à supprimer occupe la position 8

L’état de tableau T avant la suppression de l’élément


numéro 8

T 822 904 256 82 134 609 789 710 646 737 904

p. 293
Mheni & SGarbouje

2
1 2 3 4 5 6 7 8 9 10 11
L’état de tableau T après la suppression de l’élément
numéro 8

T 822 904 256 82 134 609 789 646 737 904


2
1 2 3 4 5 6 7 8 9 10

- Ecrire la procédure qui permet de supprimer l'élément


indiqué du tableau

[F] – Insertion d’un élément dans le tableau

Si l’utilisateur tape la lettre ′F′, le message affiché sera


« Insertion d’un élément dans le tableau» :

L’utilisateur donne la position d’insertion pi (avec 1≤pi≤N)


et la valeur val à insérer (avec 100≤val<1000), crée une place
dans le tableau en décalant vers la droite les éléments qui
suivront cette nouvelle valeur et enfin insère la valeur dans le
tableau.

Exemple :

N=11, pi=7, val= 833

L’état de tableau T avant l’insertion de val

p. 294
Mheni & SGarbouje

T 121 134 411 76 999 517 235 706 134 121 902
7
1 2 3 4 5 6 7 8 9 10 11
L’état de tableau T après l’insertion de val

T 121 134 411 76 999 517 833 235 706 134 121 902
7
1 2 3 4 5 6 7 8 9 10 11 12
- Ecrire une procédure qui permet d'insérer un élément
dans un tableau (on peut utiliser un autre tableau résultat)

[G] – Affichage de l’élément le plus fréquent dans le


tableau

Si l’utilisateur tape la lettre ′G′, le message affiché sera


« Affichage de l’élément le plus fréquent dans le tableau» :

Le programme va calculer le nombre d’occurrence de chaque


élément T[i] dans le tableau T et ranger ce nombre dans un
tableau tabocc, et finalement affiche le premier élément le
plus fréquent. (tabocc[i] contient le nombre d’occurrence de
T[i] dans T).

Exemple :

N=11

T 25 16 89 16 74 89 12 87 89 12 16
5 8 1 8 5 1 3 9 1 3 8

p. 295
Mheni & SGarbouje

1 2 3 4 5 6 7 8 9 10 11

tabocc 1 3 3 3 1 3 2 1 3 2 3
1 2 3 4 5 6 7 8 9 10 11
Pour déterminer le premier élément le plus fréquent, on
cherche ‘’l’indice du premier élément qui a le plus grand
nombre d’occurrence’’ (dans notre exemple l’indice qui
vérifie cette propriété est 2 puisque tabocc[2]=3 donc on
affiche T[2]).

Le premier élément le plus fréquent est 168.

[H] – Quitter

Si l’utilisateur tape la lettre ′I′, le message affiché sera


« Quitter» :
L’algorithme s’arrête. On ne peut pas revenir au menu.

[I]écrire l'algorithme principal contenant la liste des choix


et l'appel des fonctions et procédures précédentes dans la
structure selon...Faire.

Problème n°4

Thèmes : fonction et procédure, tableau d'enregistrement

Type : Examen du 2nd semestre

p. 296
Mheni & SGarbouje

L’orientation universitaire

SUJET :

Le ministère de l'enseignement supérieur, de la


recherche scientifique et de la technologie veut déterminer
l’orientation des titulaires du Baccalauréat 2011 du premier
tour. Pour cela, on vous demande de réaliser un programme
qui permet de résoudre ce problème.

Les bacheliers du premier tour sont considérés comme


candidats à l'orientation. Ainsi, le Ministère de
l’Enseignement Supérieur met à la disposition des candidats
les fiches de choix. Aussi, les bacheliers qui veulent obtenir
une orientation, sont appelés à remplir leurs fiches de choix
(10 choix). Les candidats orientés recevront une fiche
d'affectation; les autres, une fiche de choix de couleur verte et
la capacité restante pour le 2ème tour.

Présentation du problème :

- La liste des candidats :

Chaque candidat est identifié par :

Un numéro de CIN,
Un nom,

p. 297
Mheni & SGarbouje

Un prénom,
Et une formule globale FG.
N : désigne le nombre des élèves (10≤N≤NMAX).
Exemple :
N=100
CIN NOM PRENOM FG

1 "05978687" "SASSI" "RIM" 132.5689

2 "05847147" "KNISSI" "HAZAR" 189.3655

3 "05933178" "HASSEN" "YASSINE" 136.5748

C 4 "05821156" "HAMMA" "AMANI" 93.2478

… … … … …

… … … … …

99 "05674856" "LARIBI" "RANIM" 97.2941

100 "05793871" "FKIH" "HAMED" 156.3572

- La liste des filières :

Chaque filière est identifiée par :

Un nom de filière,
Un score,
Et un nombre de places offertes.
M : désigne le nombre des filières (2≤M≤MMAX).
Exemple :

p. 298
Mheni & SGarbouje

M=40
NOM SCORE NB_PL

1 "MP1 PREP 141.2147 10


GABES"

2 "MEDECINE 188.2647 12
TUNIS"

3 "MEDECINE 180.2547 14
F SOUSSE

4 "PHARMACIE" 172.3541 15

5 "INFO ISET 92.2314 50


KEBILI"

… … … …

… … … …

39 "BG1 PREP SFAX" 146.5712 25

40 "INFO 143.2522 10
GEST SFAX"

- Classement des candidats par ordre de mérite (selon la


Formule Globale):

p. 299
Mheni & SGarbouje

Tous les candidats sont classés par ordre de mérite (selon la


Formule Globale).

CIN NOM PRENOM FG

1 "05847147" "KNISSI" "HAZAR" 189.3655

2 "05793871" "FKIH" "HAMED" 156.3572

3 "05933178" "HASSEN" "YASSINE" 136.5748

C "05978687" "SASSI" "RIM" 132.5689


4

… … … … …

… … … … …

99 "05674856" "LARIBI" "RANIM" 97.2941

100 "05821156" "HAMMA" "AMANI" 93.2478

- Orientation des candidats :

L’orientation des candidats se fait un par un et par ordre, le


1er candidat orienté est celui qui a la meilleure FG, puis le
2ème candidat orienté est celui qui a la 2ème meilleure FG et
ainsi de suite jusqu’au dernier candidat.

Chaque candidat remplit la liste de ses 10 choix (les noms de


filières).

p. 300
Mheni & SGarbouje

Le candidat numéro j est affecté au premier choix numéro i


(CHOIX[i], avec 1≤ i ≤10) qui vérifie la propriété suivante :

« La formule globale de candidat numéro j (C[j].FG) est


supérieure ou égale au score de la filière CHOIX[i] et
aussi le nombre de places offertes NB_PL de CHOIX[i]
est supérieur stricte à 0 ».

On affecte à ORIENTATION[j] l’orientation de candidat


numéro j.

Sinon ORIENTATION[j] "Deuxième Tour"

N’oubliez pas :

- D’utilisez la méthode de recherche séquentielle,

- Et de décrémenter le nombre de places offertes NB_PL


de CHOIX[i] dans le cas où la condition est vraie.

Exemple :

Le candidat numéro 1 a rempli le tableau CHOIX :

CHOIX "MEDECINE "MEDECINE "PHARMAC … "INFO ISET


TUNIS" SOUSSE" IE" KEBILI "

1 2 3 10

C[1].FG= 189.3655
CHOIX [1]= "MEDECINE TUNIS"

p. 301
Mheni & SGarbouje

L’indice de ce choix dans le tableau F est 2.

Le score de ce choix est F[2].SCORE=188.2647

Le nombre de places offertes de ce choix est F[2].


NB_PL =12

La formule globale de candidat numéro 1 est supérieure


au score de choix numéro 1 et le nombre de places offertes
de choix est supérieur stricte à 0.

Le candidat numéro 1 est orienté au choix


numéro 1 ="MEDECINE TUNIS".

Et le nombre de places offertes NB_PL de "MEDECINE


TUNIS" est diminué de 1.

ORIENTATIO "MEDECINE TUN …


N IS"

1 2 3 100

Le candidat numéro 2 a rempli le tableau


CHOIX : C[2].FG= 156.3572

p. 302
Mheni & SGarbouje

CHOIX "PHARMAC "BG1 PREP "INFO ISET … "INFO GEST


IE" SFAX" KEBILI " SFAX "

1 2 3 10

CHOIX [1]= "PHARMACIE"


L’indice de ce choix dans le tableau F est 4.
Le score de ce choix est F[4].SCORE=172.3541
Le nombre de places offertes de ce choix est F[4].
NB_PL=15
La formule globale de candidat numéro 2 est inférieure
au score de choix numéro 1 et le nombre de places
disponible de choix est supérieur stricte à 0.
Alors on passe au choix numéro 2.
CHOIX [2]="BG1 PREP SFAX"
L’indice de ce choix dans le tableau F est 39.
Le score de ce choix est F[39].FG=146.5712
Le nombre de places offertes de ce choix est F[39].
NB_PL=25
La formule globale de candidat numéro 2 est supérieure
au score de choix numéro 2 et le nombre de places offertes
de choix est supérieur stricte à 0.
Le candidat numéro 2 est orienté au choix numéro 2=
"BG1 PREP SFAX".
Et le nombre de places offertes NB_PL de "BG1 PREP
SFAX" est diminué de 1.
ORIENTATION "MEDECINE TUNIS "BG1 PREP …
" SFAX"

1 2 3 100

p. 303
Mheni & SGarbouje

Et ainsi de suite jusqu’au dernier candidat.


- Affichage des orientations des candidats :
L’affichage se fait comme suit :
------------------------------------------
----------------------
Ministère de l'enseignement supérieur, de la recherche
scientifique et de la technologie
Tunis le 21/07/2011
CIN: 05847147
NOM : KNISSI HAZAR
FG : 189.3665
ORIENTATION : MEDECINE TUNIS
------------------------------------------
---------------------
Ministère de l'enseignement supérieur, de la recherche
scientifique et de la technologie
Tunis le 21/07/2011
CIN: 05793871
NOM : FKIH HAMED
FG : 156.3572
ORIENTATION : BG1 PREPA SFAX
------------------------------------------
----------------------
Travail demandé :
Soient les déclarations suivantes :
CONST NMAX=300, MMAX=100
Type

p. 304
Mheni & SGarbouje

Structure CANDIDAT
CIN : Chaîne
NOM : Chaîne
PRENOM : Chaîne
FG : Réel
FinStruct
Structure FILIERE
NOM : Chaîne
SCORE : Réel
NB_PL : Entier
FinStruct

TABC=tableau (1..NMAX) CANDIDAT


TABF=tableau (1..MMAX) FILIERE
TABCH=tableau (1..10) de chaîne
TABO=tableau (1..NMAX) de chaîne
1. Ecrire une procédure Lecture (Var N, M : entier) qui
permet de saisir le nombre des candidats N et le nombre de
filières M avec (10≤N≤NMAX) et (2≤M≤MMAX).
2. Ecrire une procédure Remplir_Liste_Candidats(VAR
C :TABC ; N: entier) qui permet de remplir la liste des
candidats.
N.B :
On suppose que les formules globales des candidats et les
numéros CIN sont tous distincts.
On suppose que les numéros CIN saisis sont corrects.
Les formules globales des candidats FG devront être
supérieures strictes à 50 et inférieures strictes à 200.
3. Ecrire une procédure Remplir_Liste_Filieres(VAR F :
TABF ; M: entier) qui permet de remplir la liste des filières.

p. 305
Mheni & SGarbouje

N.B :
- On suppose que les noms des filières sont tous distincts.
- Les scores des filières doivent être supérieurs stricts à 50 et
inférieurs stricts à 200.
- Le nombre de places offertes pour chaque filière est dans
[1..50].
4. Ecrire une procédure Tri_Candidats (VAR C : TABC ;
N: entier) qui permet de classer par ordre décroissant la liste
des candidats selon les formules globales FG.
N.B : Vous pouvez utiliser n’importe quelle méthode de tri
(tri par sélection, tri par insertion, tri à bulles,…….).
5. Ecrire une procédure Saisir_Choix_Candidat (VAR
CHOIX : TABCH; j : entier) qui permet de saisir les 10
choix de candidat numéro j.
N.B : On suppose que les choix sont corrects et distincts.
6. Ecrire une fonction Pos_Filiere(F : TABF;
nom_filiere :chaine) : entier, qui permet de retourner la
position de la chaîne nom_filiere dans le tableau F.
(Recherche séquentielle par nom).
N.B : On suppose que nom_filiere existe dans le tableau F.

7. Ecrire une fonction Premiere_Pos_Filiere(F : TABF;


CHOIX :TABCH; C : TABC; j :entier) :entier, qui permet
de retourner pour un candidat numéro j, la position i de la
première filière CHOIX[i] qui a un score inférieur ou égal à
C[j].FG (la formule globale de candidat numéro j) et un
nombre de places offertes supérieur stricte à 0. Sinon cette
fonction doit retourner 0.

p. 306
Mheni & SGarbouje

8. Ecrire une procédure Affecte_Orientation_Candidat


(VAR ORIENTATION :TABO; VAR F : TABF;
CHOIX:TABCH; C :TABC; j:entier), qui permet d’ajouter
l’orientation de candidat numéro j au tableau
ORIENTATION. (ORIENTATION[j] contient
l’orientation de candidat numéro j).

9. Ecrire une procédure Affiche_Orientation_Candidat (C:


TABC; ORIENTATION:TABO; j:entier), qui permet
d’afficher l’orientation de candidat numéro j selon le format
indiqué dans l’exemple.

10. Ecrire l’algorithme principal ORIENATATION_UNIV


qui permet de :

Saisir le nombre des candidats N ainsi que le nombre de


filières M,
Remplir la liste des candidats,
Remplir la liste des filières,
Classer les candidats par ordre de mérite (selon la
Formule Globale),
Pour chaque candidat :
• Saisir ses 10 choix,
• Affecter ce candidat selon ses choix et la
disponibilité de filières.
• Afficher le résultat de l’orientation selon le format
indiqué dans l’exemple.

p. 307
Mheni & SGarbouje

Problème n°5

Thèmes : fonction et procédure, chaîne de caratère

Type : Examen du 1er semestre

On dispose d’un tableau T d’entiers à trier par ordre


croissant. Différents algorithmes de tri peuvent être utilisés
parmi lesquels la méthode de Tri de distribution dite aussi tri
postal que nous proposons d’écrire :

A. Principe de la méthode :

• Soit T un tableau d’entier de taille N dont les valeurs


varient entre 1 et 99 :
T 7 9 3 1 5 10 4

1 2 3 4 5 6 7

TB : 1 1 1 1 1 1 1 1 1 1 …… 1

p. 308
Mheni & SGarbouje

1 2 3 4 5 6 7 8 9 10 ……. 99

• On prend par la suite un tableau TB de taille 99 et on


l’initialise à 1 :

• On fait maintenant le remplissage du tableau TB en


utilisant le tableau T selon le principe suivant :
TB[T[i]] ← 0

Exemple :

i = 1,T [1] = 7, ⇒ TB [ 7 ] = 0 ;
i = 2,T [ 2] = 9, ⇒ TB [9] = 0 ; etc…..
Le tableau TB associé au tableau T donné dans
l’exemple présenté ci-dessus est :

TB : 0 1 0 0 0 1 0 1 0 0 …… 1

1 2 3 4 5 6 7 8 9 10 ……. 99

p. 309
Mheni & SGarbouje

• Finalement, on trie le tableau T en utilisant les


transformations effectuées sur le tableau TB, selon le
principe suivant :
T[j]← i si (TB[i]=0) avec i=1,….,10
Remarque : dans cet exemple 10 représente la
valeur maximale du tableau T
Selon ce principe le tableau résultat sera alors :

T: 1 3 4 5 7 9 10

1 2 3 4 5 6 7

Travail demandé :

On utilisera la constante NMAX et le type TAB définis par :

CONST NMAX=99

p. 310
Mheni & SGarbouje

TYPE TAB = TABLEAU [1..NMAX] D’ENTIERS

1) Ecrire une fonction algorithmique, sans paramètres,


appelée TAIL_VECT, qui permet de saisir un entier
compris entre 1 et NMAX puis retourner ce même entier.
2) Ecrire une procédure algorithmique, appelée
SAISIE_VECT qui permet de remplir N cases d’un
tableau T avec des valeurs entières compris entre 1 et
NMAX. Afin d’assurer que tous les éléments de T
soient distincts, cette procédure appelle une fonction
RECHERCHE (T, d, x) qui retourne VRAI si un
élément x existe parmi les d éléments déjà saisis dans
le tableau T et FAUX sinon.
Les paramètres de cette procédure sont :

N : entier paramètre donné passé par


valeur.

T : TAB paramètre résultat passé par


variable.

3) Ecrire une procédure algorithmique, appelée


INIT_VECT qui permet d‘initialiser un tableau TB
de taille 99 à 1. Le paramètre de cette procédure est :
TB : TAB paramètre résultat passé par
variable.

4) Ecrire une fonction algorithmique, appelée


MAX_VECT qui permet de retourner la valeur

p. 311
Mheni & SGarbouje

maximale d’un tableau T contient N éléments. Les


paramètres de cette procédure sont :
N : entier paramètre donné passé par
valeur.

T : TAB paramètre donné passé par


valeur.

5) Ecrire une procédure algorithmique, appelée


REMP_VECT qui permet de remplir un tableau TB
en utilisant un tableau T selon le principe présenté
dans la partie A. Cette procédure fait appel à la
procédure INIT_VECT pour initialiser à 1 le tableau
TB. Les paramètres de cette procédure sont :
N : entier paramètre donné passé par
valeur.

T : TAB paramètre donné passé par


valeur.

TB : TAB paramètre résultat passé par


variable.

6) Ecrire une procédure algorithmique, appelée


TRI_VECT qui permet de transformer un tableau T
en parcourant un tableau TB selon le principe déjà
écrit dans la partie A. cette procédure faits appel à la
fonction MAX_VECT pour déterminer la plus grande
élément du tableau T. Les paramètres de cette
procédure sont :

p. 312
Mheni & SGarbouje

TB : TAB paramètre donné passé par


valeur.

T : TAB paramètre résultat passé par


variable.

7) Ecrire une procédure algorithmique, appelée


AFFICH_VECT qui permet d’afficher les éléments
d’un tableau T de dimension N. Les paramètres de
cette procédure sont :
N : entier paramètre donné passé par
valeur.

T : TAB paramètre donné passé par


valeur

8) En utilisant les procédures et les fonctions


précédemment définies, écrire un algorithme intitulé
Tri_Postal qui permet de :
• Saisir un entier N à partir du clavier. (1 ≤ N ≤
NMAX).
• Remplir le tableau T, par N entier, dont les
valeurs varient entre 1 et 99, et chaque élément
saisi de T ne doit pas être répété.
• Déterminer le plus grand élément de T.
• Remplir le tableau TB en parcourant le tableau
T.

p. 313
Mheni & SGarbouje

• Transformer le tableau T en se basant sur le


tableau TB.
• Afficher le tableau T trié.

II. Solutions
Correction Problème 1 :
1)
Procédure lecture (var k: void lecture (int *k)
entier) {
Début do {
Répéter printf (‘’donner un entier
Ecrire (‘’donner un entier k>=4 : ’’);
k>=4’’) scanf ("%d",&k);
Lire (k) }while (k<4);
Jusqu'à (k>=4) }
Fin
2)
Fonction longueur (k : #include <string.h>
entier) : entier int longueur(int k)
Variables {
ch :chaîne char ch[100];
Début sprintf(ch, "%d", k);
Convch (k, ch) return(strlen(ch));
longueur ←(long(ch)) }
Fin
3)
Procédure décompose void decompose (int c, int
(C:entier, m : entier , var CD : m, int *cd, int *cg)
entier, var CG : entier) {

p. 314
Mheni & SGarbouje

Variables char ch[20], chd[20],


ch,chd, chg:chaîne chg[20];
e :entier
Debut sprintf(ch, "%d", c);
convch(C,ch) chg = strstr(ch,0, strlen(ch)-
chd souschaine(ch, m)
long(ch)-m+1, m) chd = strstr(ch, strlen(ch)-
chg souschaine(ch,1, m+1, m);
long(ch)-m+1) atoi (chg, *cg);
Valeur (chd, CD, e) atoi (chd, *cd);
Valeur (chg, CG, e) }
Fin
4)
Fonction int verif_kaprekar
verif_kaprekar(k :entier):booléen (int k)
Variables { int c, m ;
C, m : entier m = 0;
Début c = k*k;
m 0, C k*k do
Répéter {
m m+1 decompose (c, m,
Décompose(C, m, CD, CG) &cd, &cg);
Jusqu'à (CD+CG=k) ou m = m+1;
(m=longueur(C)) } while (cd+cg!=k ||
Si (m<longueur(C)) m<strlen(c))
verif_kaprekar ←(vrai) if (m<strlen(c))
Sinon verif_kaprekar ←(faux) return 1;
Fin si else
Fin return 0;
}

p. 315
Mheni & SGarbouje

5)
Algorithme principal main ()
Var iables { int k;
k :entier lecture (k);
Début if (verif_kaprekar(k))
Lecture (k) printf ("%d est un nombre
Si verif_kaprekar (k)= kaprekar", k);
vrai alors else
Écrire (k,’’est un printf("%d n'est pas un
nombre kaprekar’’) nombre kaprekar", k);
Sinon }
Écrire (k,’’n’est pas
un nombre kaprekar’’)
Fin si
Fin
Correction Problème 2:
1)
Procédure lecture (Var N : void lecture (int *n, int
entier) NMAX)
Début {
Répéter do {
Ecrire ("donner le nombre printf ("Donnez le nombre
des élèves 3≤N≤NMAX") des élèves compris entre 3 et
Lire (N) %d :", NMAX);
Jusqu'à (3≤N et N≤NMAX) scanf ("%d",n);
Fin }while (*n<3 || *n>NMAX);
}
2)
Procédure REMPLIR (VAR REPONSE: tabc) void remplir (char reponse[])

p. 316
Mheni & SGarbouje

Variables { int i;
i : entier for (i=0;i<26;i++)
Début do {
Pour i de 1 à 26 répéter printf ("donner la lettre numéro %d
Répéter scanf ("%c",&reponse[i]);
Ecrire ("donner la lettre numéro ",i) }while (reponse[i] >'Z' || reponse[i]<
Lire (REPONSE[i]) }
Jusqu'à (REPONSE[i] dans [‘’A’’..’’Z’’])
Fin pour
Fin
3)
Fonction TESTFAUTE (l : caractère, pos : int testFaute(char l,
entier) : booléen int pos)
Début {
Si (ord(L) -65+1=pos) if (l-65+1==pos)
Alors Ou TESTFAUTE return 1;
TESTFAUTE ←( (ord(L)- else
←(vrai) 65+1=pos) return 0;
Sinon }

TESTFAUTE←(faux)
Fin si
Fin
4)
Fonction NBFAUTE int nbFaute(char reponse[])
(REPONSE: tabc) : { int i,nbf=0;
entier for (i=0;i<26;i++)
Variables if (testFaute(reponse[i],i)==0)
i,Nbf : entier nbf++;
Début return nbf;

p. 317
Mheni & SGarbouje

Nbf 0 }
Pour i de 1 à 26
répéter faire
Si (TESTFAUTE
(REPONSE [i], i)=faux)
alors
Nbf Nbf+1
Fin si
Fin pour
NBFAUTE ←(Nbf)
Fin
5)
Fonction int nbTotalFaute (int
NBTOTALFAUTE(FAUTE :tabe , faute[], int n)
N : entier) : entier { int i, nbft=0;
Variables for (i=0;i<n;i++)
i, Nbft : entier nbft += faute[i];
Début return (nbft);
Nbft 0 }
Pour i de 1 à N répéter
Nbft Nbft+FAUTE[i]
Fin pour
NBTOTALFAUTE ←(nbft)
Fin
6)
Procédure AFFICHE void affiche (int faute[], int
(FAUTE :tabe , N :entier) n)
Variables { int i;
i :entier for (i=0;i<n;i++)
Début if (faute[i]==0)

p. 318
Mheni & SGarbouje

Pour i de 1 à N répéter printf ("L'élève n°%i a


Si (FAUTE[i]=0) alors bien récité l'alphabet", i+1);
Ecrire ("l’élève numéro }
",i , "a bien récité l’alphabet")
Fin si
Fin pour
Fin
7)
Procédure void ajouterTFPF (char
AJOUTERTFPF reponse[], char tf[], int pf[], int
(REPONSE :tabc ,Var *j)
TF :tabf , Var PF : tabpf , { int i;
Var j :entier) *j=-1;
Variables for (i=0;i<26;i++)
i :entier if
Début (testFaute(reponse[i],i)==false)
j 0 {
Pour i de 1 à 26 répéter *j++;
Si (TESTFAUTE tf[*j] = reponse[*j];
(REPONSE [i], i)=faux) pf[*j] = i;
alors }
j j+1 }
TF[j]
REPONSE [i]
PF[j] i
Fin si
Fin pour
Fin
8)
Procédure void afficheResultat (int n,

p. 319
Mheni & SGarbouje

AFFICHERESULTAT (N : int faute[], int tp[], char


entier , FAUTE : tabe , TP : tf[])
tabpf , TF :tabf) { int i,j,k=1;
Variables for (i=0;i<n;i++)
i,k,j :entier { if (faute[i]==0)
Début printf ("L'élève n°%i
k 1 a bien récité l'alphabet",
Pour i de 1 à N répéter i+1);
Si (FAUTE[i]=0) alors else
Ecrire ("Pour l’élève { printf ("L'élève n°%i
numéro", i,": il a bien récité a commis %i fautes",i+1,
l’alphabet") faute[i]);
Sinon for (j=k;i<faute[i]+k-
Ecrire ("Pour l’élève 1;i++)
numéro", i ,": il a commis", printf ("* %c dans
FAUTE[i],"fautes") la position %i",tf[j],tp[j]);
Pour j de k à k = k+faute[i];
FAUTE[i]+k-1 faire }
Ecrire ("*", TF[j], }
"dans la position", TP[j]) }
Fin pour
k k+ FAUTE[i]
Fin si
Fin pour
Fin
9)
Algorithme ALPHABET Programme
Const alphabet.c
NMAX=100 #include <stdio.h>
type

p. 320
Mheni & SGarbouje

tabc : tableau (1..26) caractère main()


tabe : tableau (1..NMAX) entier {
tabpf : tableau (1..26*NMAX) const int
entier NMAX=100;
tabf : tableau (1..26*NMAX) int i,j,n,
caractère faute[NMAX],
Variables pf[26*NMAX];
N,j,i ;entier char reponse[26],
REPONSE :tabc tf[NMAX*26];
FAUTE :tabe
TF :tabf ; PF : tabpf lecture (&n);
Début j=0;
Lecture (N) for (i=0;i<n;i++)
j 0 { remplir
Pour i de 1 à N répéter (reponse);
REMPLIR (REPONSE) faute[i] =
nbFaute(reponse);
FAUTE[i] NBFAUTE(REPONSE ajouterTFPF
) (reponse, tf, pf,& j);
}
AJOUTERTFPF(REPONSE,TF,PF, printf ("nombre
j) total de faute = %d",
Fin pour nbTotalFaute(faute,n))
Ecrire ;
(NBTOTALFAUTE(FAUTE,N)) affiche(faute,n);
AFFICHE(FAUTE,N) afficheResultat ( n,
AFFICHRESULTAT faute, pf, tf);
(N,FAUTE,PF,TF) }
Fin

p. 321
Mheni & SGarbouje

Correction Problème 3
1)
Procédure REMPLIR void remplir (int t[], int N)
(VAR T: tab, N:entier) { int i;
Variables for (i=0;i<N;i++)
i : entier do {
Début printf ("Donnez l'entier
Pour i de 1 à N répéter numero %d", i);
Répéter scanf ("%d",&t[i]);
Ecrire ("donner l'entier } while (t[i]<=100 ||
numéro ",i) t[i]>=1000);
Lire (T[i]) }
Jusqu'à (100< T[i ] ET
T[i]<1000)
Fin pour
Fin
2)
Procédure AFFICHE (T:tab, void affiche (int t[], int N)
N:entier) { int i;
Variables for (i=0;i<N;i++)
i :entier printf ("T[%d]= %d", i,
Début t[i]);
Pour i de 1 à N répéter }
Ecrire("T[",i,"]=",T[i])
Fin pour
Fin
3)
Procédure void modif_tableau (int t[],
Modif_Tableau(var T:tab, int pm, int val)
pm: entier, val:entier) {

p. 322
Mheni & SGarbouje

Début t[pm]=val;
T[pm]←val }
Fin
4)
TabN : Tableau [1..N+1]de void ajoutVal (int t1[], int
entier N, int t2[], int val)
Procédure AjoutVal(T1:tab, { int i;
Var T2:TabN,val:entier, for (i=0;i<N;i++)
N:entier) t2[i] = t1[i];
Variables t2[N+1] = val;
i :entier }
Debut
Pour i de 1 à N faire
T2[i]←T1[i]
finPour
T2[N+1]←val
Fin
5)
Procédure suppression (Var void suppression (int t[],
T:tab, ps:entier, N:entier) int N, int ps)
Variables { int i;
i :entier if (ps <=N)
Debut for (i = ps ; i < N ; i++)
Si (ps<=N) alors t[i] = t[i+1];
Pour i de ps à N faire else
T[i]←T[i+1] printf ("%d est supérieur
FinPour à %d", ps, N);
Sinon }
Ecrire ( ps," est supérieur à",
N)

p. 323
Mheni & SGarbouje

FinSi
Fin
6)
TabN : Tableau [1..N+1]de void insertionVal (int t1[],
entier int N, int t2[], int pos, int
Procédure InsertionVal val)
(T1:tab, Var T2:TabN, { int i;
pos:entier, val:entier, if (pos<=N)
N:entier) for (i=0;i<N;i++)
Variables { if (i==pos)
i :entier t2[i] = val;
Debut else
Si(pos<=N) alors t2[i] = t1[i];
Pour i de 1 à N faire }
Si (i=pos) }
T2[pos]←val
Sinon
T2[i]←T1[i]
FinSi
FinPour
FinSi
Fin
7)
Procédure MaxOcc(T:tab, void maxOcc (int t[], int
Tocc:tab, N:entier) N, int tocc[])
Variables { int i, j, nb, max;
Max,Nb,i,j:entier for (i=0;i<N;i++)
Début {
Pour i de 1 à N faire nb=0;
Nb←0 for (j=0 ; j<N ; j++)

p. 324
Mheni & SGarbouje

Pour j de 1 à N faire {
Si (T[i]=T[j]) alors if (t[i] == t[j])
Nb←Nb+1 nb++;
FinSi }
FinPour tocc[i] = nb;
Tocc[i]←Nb }
FinPour max = tocc[0];
Max←Tocc[1] for (i=0 ; i<N ; i++)
Pour i de 1 à N faire if (tocc[i]>max)
Si(Max <Tocc[i]) alors {
Max←Tocc[i] max = tocc[i];
pos←i pos = i;
finSi }
FinPour printf ("L'élément le plus
Ecrire( "L'élement le plus fréquent est %d",t[pos]);
fréquent est ",T[pos]) }
Fin
8)
Algorithme Menu main ()
CONSTANTE N=25 {
TYPE const int N=25;
tab = TABLEAU [1..N] entier char choix;
tab2 = TABLEAU [1..N+1] entier int t[N], t2[N+1];
Variables int pm, val, pos;
Choix:caractère
T:tab, do
T2:tab2 {
Pm,val,pos:entier printf ("Donnez votre
Début choix [tapez un
Répeter caractère]");

p. 325
Mheni & SGarbouje

Ecrire("donner votre choix: taper printf ("[A] – Création


un caractère du tableau \n
[A] – Création du tableau [B] – Affichage du
[B] – Affichage du tableau tableau \n
[C] – Modification d’un élément [C] – Modification d’un
du tableau élément du tableau \n
[D] – Ajout d’un élément à la fin [D] – Ajout d’un
du tableau élément à la fin du
[E] – Suppression d’un élément du tableau \n
tableau [E] – Suppression d’un
[F] – Insertion d’un élément dans élément du tableau \n
le tableau [F] – Insertion d’un
[G] – Affichage de l’élément le élément dans le tableau
plus fréquent dans le tableau \n
[H] – Quitter ") [G] – Affichage de
Lire(choix) l’élément le plus
Selon (choix) faire fréquent dans le tableau
cas 'A': Ecrire("Création du \n
tableau ") [H] – Quitter");
REMPLIR (T, N) scanf ("%c",&choix);
cas 'B' : Ecrire("Affichage du switch (choix)
tableau") {
AFFICHE (T, N) case 'A' : printf
cas 'C' : Ecrire("Modification d’un ("Création du tableau");
élément du tableau") remplir (t,
Ecrire ("donner la position N);
de la case à modifier et la nouvelle case 'B' : printf
valeur") ("Affichage du
Lire(pm) Lire (val) tableau");
Modif_Tableau(T,pm,val,N) affiche (t, N);

p. 326
Mheni & SGarbouje

cas 'D' : Ecrire("Ajout d’un case 'C' : printf


élément à la fin du tableau") ("Modification d'un
Ecrire("donner l'élement à ajouter élément du tableau");
à la fin") lire(val) printf
AjoutVal(T,T2,val,N) ("Donnez la position de
cas 'E' : Ecrire("Suppression d’un la case à modifier et la
élément du tableau ") nouvelle valeur");
Ecrire("donner la position de scanf
l"élement à supprimer") lire(pos) ("%d",&pm);
suppression(T,pos,N) scanf
cas 'F' : Ecrire("Insertion d’un ("%d",&val):
élément dans le tableau") modif_tablea
Ecrire ("donner la position de la u (t, N, pm, val);
valeur à insérer et la nouvelle case 'D' : printf
valeur") ("Ajout d'un élément à
Lire(pos) Lire (val) la fin du tableau");
InsertionVal(T,T2,pos,val) printf
cas 'G' : Ecrire("Affichage de ("Donnez l'entier à
l’élément le plus fréquent dans le ajouter");
tableau") scanf("%d",
MaxOcc(T, T2,N) &val);
cas 'H' : Ecrire("Vous avez choisit ajoutVal (t,
de Quitter") N, t2,val);
FinSelon case 'E' : printf
Jusqu'à (choix='H') ("Suppression d'un
Fin élément du tableau");
printf
("Donnez la position de
l'élément à supprimer");
suppression

p. 327
Mheni & SGarbouje

(t, N, pos);
case 'F' : printf
("Insertion d'un élément
dans le tableau");
printf
("Donnez la position et
la valeur de l'élément à
insérer");
scanf
("%d",&pos);
scanf
("%d",&val):
insertionVal
(t, N, t2, pos, val);
case 'G' : printf
("Affichage de l'élément
le plus fréquent dans le
tableau");
maxOcc (t,
N,t2);
case 'H' : printf
("Vous avez choisi de
quitter");
}

} while (choix != 'H');


}

Correction Problème 4
1.

p. 328
Mheni & SGarbouje

Procédure Lecture (Var N : En lange C, on définit


entier, var M : entier) les structures et les
Début constantes au début du
Répéter programmes (avant les
Ecrire ("Donner le nombre des procédures et fonctions
candidats") qui vont les utiliser)
Lire (N) #define NMAX 300
Jusqu'à (10≤N ET N≤NMAX) #define MMAX 100
Répéter typedef struct {
Ecrire ("Donner le nombre des char cin[10];
filières ") char nom[30];
Lire (M) char prenom[20];
Jusqu'à (10≤M ET M≤MMAX) float fg;
Fin } candidat;
2. typedef struct {
Procédure char nom[30];
Remplir_Liste_Candidats (var float score;
C : TABC , N: entier) int nb_pl;
Var iables } filiere;
i :entier
Début 1) void lecture (int *n,
Pour i de 1 à N répéter int *m)
Ecrire ("Donner le numéro CIN de {
candidat N°", i) do {
Lire (C[i].CIN) printf ("Donnez le
Répéter nombre des
Ecrire ("Donner le nom de candidats");
candidat N°", i) scanf ("%d",n);
Lire (C[i].NOM) } while (n<10 ||
Jusqu'à (long (C[i].NOM)>2) n>NMAX);

p. 329
Mheni & SGarbouje

Répéter do {
Ecrire ("Donner le prénom de printf ("Donnez le
candidat N°", i) nombre des filières");
Lire (C[i]. PRENOM) scanf ("%d",m);
Jusqu'à (long (C[i]. PRENOM)>2) } while (m<10 ||
Répéter m>MMAX);
Ecrire ("Donner la formule }
globale de candidat N°", i)
Lire (C[i]. FG) 2) void
Jusqu'à (C[i]. FG>50) et (C[i]. remplirListeCandidat
FG<200) s (candidat C[], int n)
Fin pour {
Fin for (i=0; i<n ; i++) {
printf ("Donnez le
3. numéro de CIN du
Procédure candidat n°%d", i);
Remplir_Liste_Filieres(VAR F : scanf ("%s", C[i].cin);
TABF ; M: entier) do {
Var iables printf ("Donnez le
i :entier nom du candidat :");
Début scanf ("%s",
Pour i de 1 à M répéter C[i].nom);
Répéter } while
Ecrire ("Donner le nom de la (strlen(C[i].nom) <=
filière N°", i) 2);
Lire (F[i].NOM) do {
Jusqu'à (long (M[i].NOM)>2) printf ("Donnez le
Répéter prénom du candidat :");
Ecrire ("Donner le score de la scanf ("%s",
filière N°", i) C[i].prenom);

p. 330
Mheni & SGarbouje

Lire (F[i]. SCORE) } while


Jusqu'à (F[i]. SCORE>50) et (F[i]. (strlen(C[i].prenom) <=
SCORE<200) 2);
Répéter do {
Ecrire ("Donner le nombre de printf ("Donnez sa
places offertes pour la filière N°", formule globale :");
i) scanf ("%f",
Lire (F[i]. NB_PL) &C[i].fg);
Jusqu'à (F[i]. NB_PL>=1) et (F[i]. } while (C[i].fg) <=50
NB_PL<=50) || C[i].fg>=200);
Fin pour }
Fin }
4.
Procédure Tri_Candidats (VAR 3) void
C : TABC ; N: entier) remplirListeFilieres
Var iables (filiere F[], int m)
Pos ,i, j :entier {
C1 : candidat for (i=0; i<m ; i++) {
Début do {
Pour i de 1 à N-1 répéter printf ("Donnez le
Pos i nom de la filière :");
Pour j de i+1 à N répéter scanf ("%s",
Si (C[j].FG > C[Pos].FG) alors F[i].nom);
Pos j } while
Fin si (strlen(F[i].nom) <= 2);
Fin pour do {
Si (Pos≠i) alors printf ("Donnez le
C1 C[i] score de la filière :");
C[i] C[Pos] scanf ("%f",
C[Pos] C1 &F[i].score);

p. 331
Mheni & SGarbouje

Fin pour } while (F[i].score <=


Fin 50 || F[i].score>=200);
do {
5. printf ("Donnez le
Procédure nombre de places
Saisir_Choix_Candidat (VAR offertes :");
CHOIX : TABCH; j : entier) scanf ("%d",
Var &F[i].nb_pl);
i :entier } while (F[i].nb_pl <1 ||
Début F[i].nb_pl>50);
Ecrire ("donner les 10 choix de }
candidat numéro", j) }
Pour i de 1 à 10 répéter
Ecrire (donner le choix numéro", i) 4) void TriCandidats
Lire (CHOIX [i]) (candidat C[], int n)
Fin pour { int pos, i, j;
Fin candidat c1;
for (i=0; i<n-1 ; i++) {
6. pos = i;
Fonction Pos_Filiere (F : for (j=i+1 ; j<n ; j++)
TABF,nom_filiere : chaine) : entier if (C[j].fg >
Var C[pos].fg)
i :entier pos = j;
Début if (pos !=i) {
i 0 c1 = C[i];
Répéter C[i] = C[pos] ;
i i+1 C[pos] = c1;
Jusqu’à (F[i].NOM= nom_filiere) }
Pos_Filiere ←(i) }
Fin }

p. 332
Mheni & SGarbouje

7.
Fonction 5) void
Premiere_Pos_Filiere(F : TABF; SaisirChoixCandidat
CHOIX :TABCH; C : TABC; (char* choix[], int j)
j :entier) :entier { int i;
Var printf ("Donnez les 10
i ,p:entier choix du candidat
Début n°%d", j);
i 0 for (i=0; i<10 ; i++) {
Répéter printf ("Donnez les 10
i i+1 choix du candidat
p Pos_Filiere(F, CHOIX[i]) n°%d", i);
Jusqu’à ( (F[p].SCORE<=C[j].FG) scanf ("%s",choix[i]);
et (F[p].NB_PL>0) ) ou (i>10) }
Si (i<=10) alors }
Premiere_Pos_Filiere ← (p)
Sinon 6) int posFiliere
Premiere_Pos_Filiere ←(0) (filiere F[], char
Fin si nomFiliere[30])
Fin { int i;

8. i=-1;
Procédure do {
Affecte_Orientation_Candidat(V i++;
AR ORIENTATION :TABO; VAR } while
F : TABF; CHOIX:TABCH; C (strcmp(F[i].nom,nomF
:TABC; j:entier) iliere)!=0);
Var return (i);
k : entier }

p. 333
Mheni & SGarbouje

Début
k 7) int
Premiere_Pos_Filiere(F ,CHOIX , premierePosFiliere
C, j ) (filiere F[], char*
Si (k ≠0) alors choix[], candidat C[],
ORIENTATION[j] F[k].NOM int j)
F[k].NB_PL F[k].NB_PL – 1 { int i=-1, p;
Sinon
ORIENTATION[j] "Deuxième do {
Tour" i++;
Fin si p = posFiliere (F,
Fin choix[i]);
} while ((F[p].score
9. >C[j].fg && F[p].nb_pl
Procédure <1) || i<10) ;
Affiche_Orientation_Candidat if (i<10)
(C: TABC; return (p);
ORIENTATION:TABO; j:entier) else
Debut return 0;
Ecrire ("- - - - - - - - - - - - - - - - - - - }
---------------------")
Ecrire (" Ministère de 8) void
l'enseignement supérieur, de la affecteOrientationCa
recherche scientifique et de la ndidat (char*
technologie ") orientation[], filiere
Ecrire (" F[], char* choix[],
Tunis le 21/07/2015") candidat C[], int j)
Ecrire (" CIN: ", C[j].CIN) { int k;
Ecrire (" NOM :", C[j].NOM)
Ecrire (" PRENOM :", C[j]. k = premierePosFiliere

p. 334
Mheni & SGarbouje

PRENOM) (F, choix, C, j);


Ecrire (" FG : ", C[j].FG) if (k!=0) {
Ecrire (" ORIENTATION : ", orientation[j] =
ORIENTATION [j]) F[k].nom;
Ecrire ("- - - - - - - - - - - - - - - - - - - F[k].nb_pl =
---------------------") F[k].nb_pl-1;
Fin } else
strcpy (orientation[j],
10. "deuxième tour");
Algorithme }
ORIENATATION_UNIV
CONST NMAX=300, 9) void
MMAX=100 afficheOrientationCa
Type ndidat (candidat C[],
Structure CANDIDAT char* orientation, int j)
CIN : Chaîne {
NOM : Chaîne printf ("-------------------
PRENOM : Chaîne ---------------------------
FG : Réel \n Ministère de
FinStruct l'enseignement
Structure FILIERE supérieur, de la
NOM : Chaîne recherche scientifique
SCORE : Réel et de la
NB_PL : Entier technologie\n\t\t Tunis
FinStruct le 21/07/2015");
TABC=tableau [1..NMAX] printf ("CIN : %s
CANDIDAT \nNom : %s \nPrenom:
TABF=tableau [1..MMAX] %s \nFG : %f
FILIERE \nOrientation %s \n-----
TABCH=tableau [1..10] de chaîne ----------------------------

p. 335
Mheni & SGarbouje

TABO=tableau [1..NMAX] de ----------------------------


chaîne --", C[j].cin, C[j].nom,
Var C[j].prenom, C[j].fg,
N, M, j : entier orientation[j]);
C :TABC ; F : TABF ; CHOIX : }
TABCH ; ORIENTATION :TABO
Début 10) main ()
Lecture (N, M) {
Remplir_Liste_Candidats(C , int n, m, j;
N) candidat C[NMAX];
Remplir_Liste_Filieres(F , M) filiere F[MMAX];
Tri_Candidats (C , N) char * choix[10]
Pour j de 1 à N répéter char
Saisir_Choix_Candidat *orientation[NMAX];
(CHOIX , j )
lecture (&n, &m);
Affecte_Orientation_Candidat(ORI remplirListeCandidats
ENTATION ,F , CHOIX, j) (C, n);
Affiche_Orientation_Candidat remplirListeFilieres (F,
(C, ORIENTATION, j) m);
Fin pour TriCandidats (C, n);
Fin for (j=0; j<n ; j++) {
saisirChoixCandidat
(choix, j);

affecteOrientationCand
idat (orientation, F,
choix, C, j);

afficheOrientationCand

p. 336
Mheni & SGarbouje

idat (C, orientation, j);


}
}

p. 337
Mheni & SGarbouje

Correction Problème5 :

p. 338
Mheni & SGarbouje

Algorithmique : Langage C
1)
Fonction TAIL_VECT (): #define NMAX 99
entier 1) int tailleVecteur ()
Var { int n;
N: entier
Début do {
Répéter printf ("saisir un entier : ");
Ecrire (‘’donner un entier scanf ("%d",&n);
N’’), lire (N) } while (n<=1 || n>99);
Jusqu'à (N >1 ET return (n);
N<=NMAX])
TAIL_VECT ←(N) }
Fin 2) void saisieVecteur (int t[],
2) int n)
Procédure SAISIE_VECT { int i;
(var T : VECTE, N: entier) for (i=0 ; i<n ; i++)
Var do {
I : entier printf ("saisir l'élément
Début n°%d : ",i);
Pour i de 1 à N répéter scanf ("%d",&t[i]);
Répéter } while (t[i]<1 || t[i]>99 ||
Ecrire (‘’donner l’élément recherche(t,i-1, t[i]));
numéro ’’,i) }
Lire (T [i]) 3) void initVecteur (int tb[])
Jusqu'à (T [i] >=1 ET T[i]<= { int i;
NMAX]) et (RECHERCHE for (i=0 ; i<n ; i++)
(T, i-1, T[i])=faux) tb[i] = 1;
Fin pour }
Fin 4) int maxVecteur (int t[], int

p. 339
Mheni & SGarbouje

3) Procédure INIT_VECT n)
(VAR TB : VECTE) { int i, max = t[0];
Var for (i=0 ; i<n ; i++)
i :entier if (max<t[i])
Début max = t[i];
Pour i de 1 à 99 Répéter return (max);
TB[i] 1 }
Fin pour 5) void remplirVecteur (int
Fin tb[], int t[], int n)
{ int i;
4) Fonction MAX_VECT (T : initVecteur (tb);
VECTE, N :entier) :entier for (i=0 ; i<n ; i++)
Var tb[t[i]] = 0;
Max,i :entier }
Début
Max T[1] 6) void triVecteur (int t[], int
Pour i de 2 à N répéter tb[], int n)
Si T[i]>Max alors { int i, j=0;
T[i] Max for (i=0 ; i<maxVecteur(t,n) ;
Fin si i++)
Fin pour if (tb[i]== 0) {
MAX_VECT ←(Max) t[j]=i;
Fin j++;
}
5) Procédure REMP_VECT }
(Var TB : VECTE ; T:VECTE, 7) void afficheVecteur (int
N : entier) t[], int n)
Var { int i;
I : entier for (i=0 ; i<n ; i++)
Début printf ("%d |",t[i] );

p. 340
Mheni & SGarbouje

INIT_VECT (TB) }
Pour i de 1 à N répéter 8) main ()
TB[T[i]] 0 { int n, t[NMAX],
Fin pour tb[NMAX];
Fin n = tailleVecteur ();
saisieVecteur-t,n);
6) Procédure TRI_VECT (var remplirVecteur(tb,t,n);
T :VECTE ;TB :VECTE ; triVecteur(t,tb,n);
N :entier) afficheVecteur(t,n);
Var }
J ,i :entier
Début
J 0
Pour i de 1 à MAX_VECT (T,
N) répéter
Si (TB[i]=0) alors
J J+1
T[J] i
Fin si
Fin pour
Fin

7) Procédure AFFICH_VECT
(T : VECTE ; N : entier)
Var
I : entier
Début
Pour i de 1 à N répéter
Ecrire (T[i], " ")
Fin pour

p. 341
Mheni & SGarbouje

Fin

8) Algorithme Tri_Postal
CONST NMAX=99
TYPE VECTE = tableau
[1..NMAX] d'entier
Var
N : entier ; T, TB : VECTE
Début
N TAIL_VECT()
SAISIE_VECT (T, N)
REMP_VECT (TB, T, N)
TRI_VECT (T, TB, N)
AFFICH_VECT (T, N)
Fin

p. 342
Mheni & SGarbouje

Maher HENI Né en 1984 à EL-Kef, Tunisie, Docteur Ingénieur


télécommunication, de l'Ecole Nationale d'Ingénieurs de Tunis (ENIT), (E.C av
Innov'COM Lab à SUP'COM). A eu son diplôme de mastère sp. Systèmes
communication à l'ENIT (E.C avec l’IEF à l’Université Paris-SUD). Maî
Assistant à l'institut Supérieur d’Informatique du KEF, été précédemment assista
universitaire à la faculté des sciences de Gabes.

Sonia Guerbouj est née à Menzel Bou Zelfa, une petite ville du
Cap Bon Tunisien. Elle est enseignante Technologue à l'Institut
Supérieur des Etudes Technologiques de Siliana depuis 2010.
Avant d'entamer sa carrière dans l'enseignement, elle a travaillé
pendant plus de deux ans en tant que consultante technique dans
une entreprise multinationale. Là bas, elle a participé à la
réalisation et la mise en place de divers projets logiciels et
technologiques, mais sa passion pour l'enseignement a pris le
dessus. Elle a obtenu son diplôme national d'ingénieur en 2008
avec mention Bien à l'Institut National des Sciences Appliquées et
de la Technologie et a commencé un mastère de recherche en

p. 343
Mheni & SGarbouje

systèmes électroniques et réseaux de communication à l'Ecole


Polytechnique de Tunis. Elle a publié un article intitulé "A code
analyser for H.264 encoder on a VLIW processor" dans le journal
de TIGERA en 2009.

p. 344