Algorithme Pro Chap2

Télécharger au format pdf ou txt
Télécharger au format pdf ou txt
Vous êtes sur la page 1sur 243

Chapitre-2 

Algorithmique et programmation C
Les Variables, les pointeurs, les constantes, 
Fonctions Entrés/Sortie
Les algorithmes
 Un  algorithme  est  un  ensemble  de règles logiques  et 
chronologiques  qu’on  doit  suivre  pour  aboutir  à  la 
résolution d’un problème particulier.
 Ces règles sont constituées  d’un nombre fini d’opérations
élémentaires (Arithmétique & Logique).
 Ces  opérations  seront exécutées dans un ordre bien 
déterminé.
 Un algorithme peut  être  assimilé  à  un  raisonnement  que 
l’on  peut    traduire  avec  un langage  que  toute  personne 
peut comprendre :

o LDA : Langage de Description d’Algorithme 
Les algorithmes
 Le LDA n’est pas un langage informatique.

 Le programme informatique est à la traduction du LDA à 
un  autre  langage  compréhensible  pour  la  machine 
(Pascal, Visual Basic, C, C++, C#, Java…)
Langage traduisant la pensée de manière
compréhensible pour toute personne :
Algorithme

LDA
……
……
……

Raisonnement logique Programme


et chronologique C, C++,…

Langage traduisant le LDA de manière


compréhensible pour l’ordinateur :
Programme

Compilateur Programme C, 
Langage Machine
C++
Exemple 1. Recherche d’un mot dans un
Exemple 3: Plan de l’algorithme
dictionnaire
Recherche d'un mot dans un dictionnaire
      Méthode 1 : Recherche séquentielle
 
a. Début algorithme.
b. Retenir (saisir, lire) le mot à rechercher.
c. Ouvrir le dictionnaire à la première page.
d. Tant que le mot ne se trouve pas sur la page courante
et la page courante n'est pas la dernière exécuter l'étape
e) sinon passer à l'étape f).
e. Passer à la page suivante.
f. Si le mot s'y trouve lire la définition sinon ce mot ne se
trouve pas dans le dictionnaire.
g. Fin de l'algorithme.
Exemple 1. Recherche d’un mot dans un
Exemple 3: Plan de l’algorithme
dictionnaire
Recherche d'un mot dans un dictionnaire
 Méthode 1 : Recherche dichotomique

a. Début algorithme.
b. Retenir (saisir, lire) le mot à rechercher.
c. Ouvrir le dictionnaire à la page du milieu.
d. Tant que le mot ne se trouve pas sur la page courante et
la page courante n'est pas la dernière exécuter l'étape e)
et f) sinon passer à l'étape g).
e. Si le mot se trouve dans la partie droite ouvre la page du
milieu de cette partie
f. Sinon ouvre la page du milieu de la partie gauche
g. Si le mot s'y trouve lire la définition sinon ce mot ne se
trouve pas dans le dictionnaire.
h. Fin de l'algorithme.
• Conclusion

– Plusieurs algorithme peuvent donner le 
même résultats
– Evaluation des algorithmes en fonction du 
temps d’exécution et de la mémoire utilisée   
* Structure d’un
Algorithme
Déclaration du nom  algorithme nom de l’algorithme
de l’algorithme
const
liste des constantes

Déclaration des  var
constantes, des variables liste des variables
et des structures
struct
liste des structures 

début algorithme
action 1  // commentaire 1
action 2  // commentaire 2
Le corps de l’algorithme .
.
.
action n  // commentaire n
fin algorithme
* Structure d’un
Algorithme
 Nom de l’algorithme :
o Il permet tout simplement d’identifier un algorithme 
parmi d’autres.
 Les déclarations :
o C’est une liste exhaustive de variables utilisées et 
manipulées dans le corps de l’algorithme.
 Le corps de l’algorithme :
o Dans cette partie de l’algorithme, sont placées les 
tâches à exécuter (instructions, opérations, …).
 Les commentaires :
o Pour permettre une lecture plus aisée et plus 
compréhensive de l’algorithme
* Les
Déclarations
Les Constantes :
o Elles représentent des chiffres, des nombres, des caractères, des chaînes de 
caractères, … dont la valeur ne peut pas être modifiée au cours de l’exécution 
de l’algorithme.
Les Variables :
o Elles  peuvent  stocker  des  chiffres  des  nombres,  des  caractères,  des  chaînes 
de  caractères,…  dont  la  valeur  peut  être  modifiée  au  cours  de  l’exécution  de 
l’algorithme.
Les Tableaux :
o Elles  permettent  de  rassembler  plusieurs  valeurs  ou  constantes  de  même 
type sous un même identificateur.
Les Structures :
o Elles  permettent  de  rassembler  plusieurs  variables  ou  constantes  sous  un 
même identificateur, on parle également d’entités ou d’objets.
* Les Déclarations des variables et des
constantes
Pour  pouvoir  accéder  aux  données,  le  programme  (quel  que  soit  le 
langage  dans  lequel  il  est  écrit)  fait  usage  d’un  grand  nombre  de 
variables de différents types.

Une VARIABLE possède :

Un nom (identificateur) : Un variable apparaît en programmation sous 


un nom de variable.
Un type : Pour distinguer les uns des autres les divers contenus possibles, 
on utilise différents types de variables (entiers, réels, chaîne de 
caractères..).
Une valeur : Une fois la variable définie, une valeur lui est assignée, ou 
affectée.
Une adresse : C’est l’emplacement dans la mémoire de l’ordinateur, où 
est stockée la valeur de la variable.
* Langage de programmation C
Le langage « C » est le plus utilisé dans la
programmation. Des langages informatiques plus 
modernes comme C++, Java et PHP reprennent des aspects 
de C.
• Structure générale d’un programme C
Un programme C comporte une série d’instructions structurées en bloc, il 
peut être constitué de plusieurs sous-programmes ou fonctions. 
* Langage de programmation C
* Structure générale d’un programme C
La fonction principale main()
Un programme C comporte une série d’instructions structurées en bloc, il 
peut être constitué de plusieurs sous-programmes ou fonctions. 

Un programme C comporte toujours une fonction principale dans 


laquelle on peut appeler les autres fonctions définies dans le fichier ou 
bien prédéfinies dans la bibliothèque du langage.    
La syntaxe de cette fonction principale est donnée par :

main(void)
{
……
}

C’est une fonction sans argument en général d’où le mot void (rien) entre 
les parenthèses. 
* Langage de programmation C
* Structure générale d’un programme C
Les Inclusion de source #include<nonfichier.h>

Pendant l’exécution d’un programme C, Le compilateur a besoin d’être informé 
sur :
les structures de données et de variable externes 
l’aspect des fonctions prédéfinies utilisées dans le programme. 

Ces informations sont contenues dans des fichiers d’extension « .h ». 
Ces fichiers doivent introduits dans le programme principal à travers la directive 
« #include ». 

Sa syntaxe est la suivante :

#include <nomfichier.h>

La directive #include permet d’incorporer dans le fichier source le code du fichier 
<nomfichier.h> 
* Langage de programmation C
* Structure générale d’un programme C
Les Inclusion de source #include<nonfichier.h>

Nom fichier Rôle


<math.h>  pour utiliser les fonctions mathématiques usuelles
<stdio.h>  pour utiliser les fonctions d’entrées/sortie « printf() »
<stdlib.h>  Pour la gestion de la mémoire, conversions et les fonctions système
<string.h>  Pour manipuler des chaines de caractère.
<conio.h> Pour utiliser les fonctions de contrôle l’affichage à l’écran : « getchar() »
<complex.h> Pour manipuler les nombres complexes
<ctype.h> pour utiliser les fonctions de manipulation des caractères (fonction test) 
: « islower() » : test si un caractère est majuscule.
* Langage de programmation C
* Structure générale d’un programme C
Les Inclusion de source #include<nonfichier.h>

#include <stdio.h>
int main(void)
{
  printf("bonjour tout le monde\n");
  return(0);
}
* Langage de programmation C
* Structure générale d’un programme C
Les variables et les constantes :

Les constantes et les variables sont définies dans la partie déclarative
par deux caractéristiques essentielles, à savoir :
 L’ identificateur :
o Il  représente  le  nom  de  la  variable,  de  la  constante  ou  de  la 
structure.  Il  est  composé  généralement  de  lettres  mais  peut 
également contenir et de chiffres.
 Il ne doit pas commencer par des chiffres
 Il ne doit pas contenir d’espaces, de caractères de ponctuation 
ou de caractères accentués.

 Le type :
o Il représente la nature de la variable ou de la constante (entier, 
réel, booléen, chaîne de caractères…)
* Langage de programmation C
* Structure générale d’un programme C
Les variables :

Une variable est caractérisée par :

Un nom : Une variable apparait en programmation sous un nom de variable.

Un type : On utilise différents types de variables (entiers, réels, chaine de 
caractères …).

Une valeur : Une fois la variable définie, une valeur lui est assignée, ou affectée.

Une adresse : C’est l’emplacement dans la mémoire de l’ordinateur, ou est 
stockée la valeur de la variable.
* Langage de programmation C
* Structure générale d’un programme C
Les Types des variables :

Toute données, quelle que soit sa nature, devra être codée sous forme 
binaire
Le type de donnée permet de donner un sens à une données qui est 
stockée dans un emplacement mémoire d’adresse N.

Cette données peut représenter un entier 
naturel, un entier signé, un caractère, un réel  .
ou une instruction mémoire.  
.
On doit connaitre la manière dont chaque  N 1 0 0 0 1 1 0 1
donnée été codée c-a-d son type
C manipule deux types de base: 
Les entiers et les nombres flottants
* Langage de programmation C
* Structure générale d’un programme C
Les Types des variables : Les Entiers

Sont désigné par « int ». Ils peuvent être affectés de deux types 
d’attributs : un attribut de précision et un attribut de représentation.

Les attributs de précision sont «short » et « long ».
L’attribut de représentation « unsigned »

Type de données Type de codage Mémoire occupée


int (entier signé) Complément à 2 4 octets
short int 2 octets
long int 4 octets
unsigned int (entier non signé) Binaire pur 4 octets
Unsigned long int
* Langage de programmation C
* Structure générale d’un programme C
Les Types des variables : Les caractères

Sont désigné par « char ». Il contient le code de n’importe quel caractère 
de l’ensemble des caractères utilisé sur la machine. 
Le codage utilisé est le codage ASCII. À chaque caractère correspond un 
codage binaire d’un entier.
Donc en « C » si a est char on peut effectuer l’opération a+1  
main(){
char x, y; Ce programme donnera le caractère 
suivant de ‘a’ 
x=‘a';
y=x+1;}

Type de données Type de codage Mémoire occupée


char (caractère) ASCII 1 octets
* Langage de programmation C
* Structure générale d’un programme C
Les Types des variables : Les flotants

Il existe trois types de flottants correspondants à trois précisions possibles. 
En allant de la précision la plus faible vers la plus forte, on dispose des 
types float, double et long double.

Type de données Type de codage Mémoire occupée


float (flottant réel) Normalisation IEEE 4 octets
Double (flottant double) 8 octets
long double (flottant double long) 12 octets

sizeof(type) : Fonction permettant de renvoyer la taille occupée dans 
la mémoire d’un certain type de données.
* Les types de variables en langage C
Plage de valeurs
Type de donnée Signification Taille (en octets)
acceptée
char Caractère 1 -128 à 127
unsigned char Caractère non signé 1 0 à 255
short int Entier court 2 -32 768 à 32 767

unsigned short int Entier court non signé 2 0 à 65 535

-32 768 à 32 767
2 (sur processeur 16 bits)
int Entier
4 (sur processeur 32 bits)
-2 147 483 648 à 2 147 
483 647

2 (sur processeur 16 bits) 0 à 65 535
unsigned int Entier non signé
4 (sur processeur 32 bits) 0 à 4 294 967 295

-2 147 483 648 à 2 147 
long int Entier long 4
483 647
unsigned long int Entier long non signé 4 0 à 4 294 967 295

float Flottant (réel) 4 3.4*10-38 à 3.4*1038


double Flottant double 8 1.7*10-308 à 1.7*10308
long double Flottant double long 12 3.4*10-4932 à 3.4*104932
* Langage de programmation C
* Structure générale d’un programme C
Les constantes :
Les constantes sont des variables qui vont prendre une valeur fixe 
Variable déclarée avec le qualificateur «const » 
Ce sont des variables dont la valeur n'est pas modifiable pendant 
l’exécution du programme. Le qualificateur « const » permet de 
protéger la valeur de la variable. 

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


main() main()
{ {
int b=8; const int b=8;
b=b+2; b=b+2;
printf("b= %d", b); printf("b= %d", b);
} }
Erreur b est protégé
Read only variable ‘b’
* Langage de programmation C
* Structure générale d’un programme C
Les constantes entières
Elles peuvent s'exprimer
 en notation décimale: 123, -123, etc...
 en notation octale avec un 0 en première position: 0123
 en notation hexadécimale avec les caractères 0x ou 0X en première position : 
0x1b, 0X2c, 0X1B,

Différents types des constantes peuvent être définis en ajoutant des suffixes.

forme de la constante liste de types


pas de suffixe, décimal int, unsigned int, long int, unsigned long int
pas de suffixe, octal ou hexadécimal int, unsigned int, long int, unsigned long int
suffixé par u ou U unsigned int, unsigned long int
suffixé par l ou L long int, unsigned long int
suffixé par (u ou U) et (l ou L) unsigned long int
* Langage de programmation C
* Structure générale d’un programme C
Les constantes flottant

Une constante flottante se présente sous la forme d'une partie entière, un 
point qui joue le rôle de virgule, une partie fractionnaire, une des deux 
lettres e ou E, le signe + ou - suivi de la valeur absolue de l'exposant

#include <stdio.h>
main()
{
double b=12.345e123;
b=b+2;
printf("b= %e", b);
return(0);
}
* Langage de programmation C
* Structure générale d’un programme C
Les constantes caractère

Les constantes de type caractère se note entre apostrophes: 'a'  '2' 

#include <stdio.h>
#include <stdlib.h>
Int main(void)
{
char b='a';
b=b+5;
printf("b= %c\n", b);
system("pause");
return(0);
}
* Langage de programmation C
* Structure générale d’un programme C
Les constantes caractère

Les caractères non imprimables 

\n  nouvelle ligne
\t  tabulation horizontale
\v  tabulation verticale
\b  retour d'un caractère en arrière
\r  retour chariot
\f  saut de page
\a  beep
\'  apostrophe
\"  guillemet
* Langage de programmation C
* Structure générale d’un programme C
Les pointeurs

Un pointeur est une variable qui stock une adresse mémoire. Cette 
adresse peut être celle d’une autre variable d’un certain type ou celle 
d’un espace mémoire alloué dynamiquement. 
Un pointeur typé permet de pointer une adresse d’un espace 
mémoire ou on peut stocké des valeurs d’un certain type. 
Un pointeur générique permet de pointer une adresse d’un espace 
mémoire ou on peut stocké des valeurs de n’importe quel type. 
La syntaxe de déclaration d’un pointeur est :
  char *p1
type *identificateur ; int *P2
Double *p3
* Langage de programmation C
* Structure générale d’un programme C
Les pointeurs Opérateur « & »

L’opérateur « & » appliqué à une variable délivre l’adresse de celle-ci ; cette 
adresse pourra être affectée à une variable de type pointeur. On peut 
écrire par exemple :

Main{
int i;
int *pi; // pi pointeur vers un int /
pi = &i; / /le pointeur pi repère la variable i /
}
* Langage de programmation C
* Structure générale d’un programme C
Les pointeurs (l’Opérateur d’indirection « * »)

« * » utilisé en opérateur préfixé est un opérateur d’indirection qui, appliqué 
à une valeur de type pointeur, délivre la valeur pointée.
main()
{
int i, j;
int *pi;
pi = &i; // on affecte l’adresse de i au pointeur « pi »/
*pi = 2; //on stocke la valeur 2 dans la zone mémoire dont l’adresse est
// donnée par pi
j = i + 1;/ on ajoute 1 à la valeur de i qui est pointée par « pi ».}

L’opérateur * peut être opérateur de multiplication ou opérateur 
d’indirection.     (*x * *y)
* Langage de programmation C
* Structure générale d’un programme C
Les pointeurs (l’Opérateur d’indirection « * »)

#include <stdio.h>
#include <stdlib.h>
main()
{
int i;
int *pi;
i=5;
pi = &i;
*pi = 2;
printf("i=%d", i);
system("pause");}
* Langage de programmation C
* Structure générale d’un programme C
Les pointeurs

Type *nom_pointeur

Donc lorsqu’on déclare un pointeur  on peut identifier trois objets 
différents :
  &nom_pointeur : contient l’adresse mémoire propre au pointeur
nom_pointeur : contient l’adresse mémoire pointée
*nom_pointeur : contient la valeur contenue dans l’adresse pointée
* Langage de programmation C
* Structure générale d’un programme C
Arithmétique sur les pointeurs

Quand on incrémente un pointeur typé, il n'est en fait pas forcément 
incrémenté de un, mais de la taille du type pointé.
L’arithmétique des pointeurs se fait en fonction de la taille de l’objet pointé. 
#include <stdio.h>
#include <stdlib.h>
main()
{
int *p1, *p2, a;
p1=&a;
p2=p1+2; // Equivalent à P2 = P1 + 2*sizeof(int)
printf("pi=%x\n", p1);
printf("pi=%x\n", p2);
system("pause");}
* Langage de programmation C
* Structure générale d’un programme C
Allocation Dynamique de la mémoire
Lorsqu’on déclare un pointeur il est initié par 0 :

Type *P = NULL (Si P==0 Alors Ecrire(« p ne pointe vers aucun objet »)

Après on peut lui affecter :
l’adresse d’une autre variable déjà déclarée

l’adresse du premier octet d’une zone mémoire réservée au cours de 
l’exécution du programme afin de stocker une valeur  d’un certain type.

Allocation Mémoire Memory ALLOCation   malloc()
* Langage de programmation C
* Structure générale d’un programme C
Allocation Dynamique de la mémoire: Fonction malloc()

Appartient à la librairie standard stdlib.h

La syntaxe :

(Type*)malloc(sizeof(Type))
Cette fonction retourne un pointeur d’un certain type (Type *) pointant vers 
un objet de taille sizeof(Type) octets. 

#include <stdlib.h> On peut donc affecter directement 


une valeur entière à *p puisqu’on 
int *p;
a réservé 4 octets à l’aide de la 
p = (int*)malloc(sizeof(int)); fonction malloc().
* Langage de programmation C
* Structure générale d’un programme C
Allocation Dynamique de la mémoire: Fonction malloc()

#include <stdlib.h>
main()
{
int i = 3;
int *p=NULL;

 p= (int*)malloc(sizeof(int));
*p = 6;}
* Langage de programmation C
* Structure générale d’un programme C
Allocation Dynamique de la mémoire: Fonction malloc()

#include <stdlib.h>
main()
{
int i = 3;
int *p=NULL;
p = &i;
*p = 6
}
* Langage de programmation C
* Structure générale d’un programme C
Allocation dynamique d’un espace pour plusieurs objets
contigus en mémoire

#include <stdio.h>
#include <stdlib.h>
main()
{
int i = 3;
int j = 6;
int *p;
p = (int*)malloc(2 * sizeof(int));
*p = i;
*(p + 1) = j;
}
* Langage de programmation C
* Structure générale d’un programme C
Les opérateurs et les expressions

L'opération par laquelle on attribue une valeur à une variable s'appelle 
affectation. Dans un algorithme (pseudo-code) "←". 
Dans le langage C par le signe " = ".

#include <stdio.h>
main()
{ i : variable (Adresse, type , valeur)
int i;
i = i*2+5; i*2+5 : expression (type, valeur) 
printf("b= %d", i);
}
* Langage de programmation C
* Structure générale d’un programme C
Les opérateurs Arithmétique, de comparaison & logique

Arithmétique Comparaison
Opérateur C Opérateur C
Addition + Supérieur stricte > 
Soustraction - Inférieur stricte < 
Multiplication * Supérieur ou égal >=
Division / Inférieur ou égal <=
Modulo (reste de la  Egal ==
%
division entière) Différent !=

Logique
Opérateur C
ET Logique &&
OU Logique ||
Négation Logique  !
* Langage de programmation C
* Structure générale d’un programme C
Les opérateurs Arithmétique, de comparaison & logique
Priorité croissante de bas vers le haut
Opérateur C
Opérateur de multiplication *
Opérateur de division /
Opérateur d'addition +
Opérateur de soustraction -
Opérateur d'infériorité stricte < 
Opérateur de supériorité stricte > 
Opérateur d'infériorité ou d'égalité <=
Opérateur de supériorité ou d'égalité >=
Opérateur d'égalité = =
Opérateur d'inégalité !=
Opérateur et logique ET &&
Opérateur ou logique OU | |
Opérateur d'affectation 
* Langage de programmation C
* Structure générale d’un programme C
Les Opérateurs d’incrémentations & de décrémentation
++ incrémentation
 -- décrémentation
On dit que ++ est :
- un opérateur de pré incrémentation lorsqu'il est placé à gauche de la variable
- un opérateur de post incrémentation lorsqu'il est placé à droite de la variable

a++;  a = a+1;
b = a++; b = a; 
a = a+1;
b = ++a; a = a+1;
b = a;
* Langage de programmation C
* Structure générale d’un programme C
Les Opérateurs d’incrémentations & de décrémentation

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


#include <stdlib.h> #include <stdlib.h>
int main() int main()
{ {
int a, b, c; int a, b, c;
a = 5; a = 5;
b = a + 4; b = a + 4;
b = a++ - 7; b = ++a - 7;
b = a - b - 7; b = a - b - 7;
printf("a= %d\n", a); printf("a= %d\n", a);
printf("b= %d\n", b); printf("b= %d\n", b);
system("pause"); system("pause");
return(0); return(0);
} }
* Langage de programmation C
* Structure générale d’un programme C
Les opérateurs d’affectation élargie
C dispose d'opérateurs encore plus puissants.
i += k   (i = i + k ) #include <stdio.h>
i -= k    (i = i – k) main()
a *= b  (a = a*b ) {
a /= b   (a = a/b ) int a, b, c;
a %= b (a = a%b ) a = 5;
b = 2;
a += 4;
b *= a;
b = a++ - 7;
b += a - 7;
a %= b;
printf("a= %d\n", a);
printf("b= %d\n", b);
system("pause");
}
* Langage de programmation C
* Structure générale d’un programme C
Les fonctions d’entrée et sortie (printf() et scanf())

représentation à partir  Scanf() représentation 


d’une chaîne de caractères  manipulable par la 
(vision humaine)  Printf() machine (vision machine), 

Pour réaliser ces transformations ces fonctions sont guidées par des
formats qui décrivent le type des objets manipulés et la 
représentation en chaîne de caractères cible. 

Par exemple, un format du type %x signifie d’une part que la variable 
manipulé ou représenté est de type entier et d’autre part que la 
chaîne de caractères qui la représente est exprimée en base 16 
(hexadécimal).
* Langage de programmation C
* Structure générale d’un programme C
Les fonctions d’entrée et sortie (printf()

Le premier argument une chaîne de caractères qui spécifie à la fois 
des caractères à afficher tels quels 
des "codes de format" repérés par % (tel que %c, %d ou %f) et qui précisent le 
type de l'information à afficher.
 
L'appel àde printf se présente comme ceci :

printf (‘’format’’, liste_d'expressions )

%d entier décimal
%f réel
%e Réel flottant
%c caractère (1 seul)
%s chaîne de caractères
* Langage de programmation C
* Structure générale d’un programme C
Les fonctions d’entrée et sortie scanf()

D'une manière générale, l'appel de scanf se présente ainsi :
 
scanf(« format », liste d’adresses)
* Langage de programmation C
* Structure générale d’un programme C
Les fonctions d’entrée et sortie scanf()
* Langage de programmation C
* Structure générale d’un programme C
Les fonctions d’entrée et sortie getchar() et putchar()

"getchar()" fonction sans paramètre qui « capte » la valeur d’un seul caractère

 x=getchar() joue le même rôle que : scanf(« %c », &x).

"putchar()" fonction écrit le caractère passé en argument sur la sortie standard 
(l'écran). Le paramètre à placer entre les () doit être de type caractère. 

putchar(x) joue le même rôle que : printf(« %c », x)
* Langage de programmation C
* Structure générale d’un programme C
Occupation mémoire

Chaque octet dans la mémoire 
est repéré par un numéro 
écrit en hexadécimal. 

Chaque donnée va être 
repérée par son adresse qui 
représente le numéro de 
son premier octet.
* Langage de programmation C
* Structure générale d’un programme C
Occupation mémoire : Alignement des données

Pour augmenter leurs performances, les processeurs sont souvent reliés à 
la mémoire vive par un bus de données plus large que la granularité de 
leur adressage (ensemble des bits adressable).
Données de même type
Dans ce cas les données seront bien aligner sur chaque emplacement. 

#include <stdio.h> Après exécution on trouve : 


main()
{int a, b, c, d; &a=28FF44
printf("adresse de a = %X\n",&a); &b=28FF40
printf("adresse de b = %X\n",&b); &c=28FF3C
printf("adresse de c = %X\n",&c); &d=28FF38.
printf("adresse de d = %X\n",&d);
system("pause");}
* Langage de programmation C
* Structure générale d’un programme C
Occupation mémoire : Alignement des données

L’alignement de ces données dans une mémoire de 64 bits est la 
suivante :

  Octet 0 Octet 1 Octet 2 Octet 4 Octet 5 Octet 6 Octet 7 Octet 8


28FF38 d c
28FF40 b a
* Langage de programmation C
* Structure générale d’un programme C
Occupation mémoire : Alignement des données
Cas des données de différents types
nécessaire, de laisser des trous entre elles afin qu'elles soient toutes bien 
alignées. 
L’ordre appliqué dans la séquence de déclaration des variables va 
influencer sur la quantité totale de mémoire utilisée. 
main()
{int a, b;
double x, y, z;
}

  Octet 0 Octet 1 Octet 2 Octet 4 Octet 5 Octet 6 Octet 7 Octet 8


28FF28 z
28FF30 y
28FF38 x
28FF40 b a
* Langage de programmation C
* Structure générale d’un programme C
Occupation mémoire : Alignement des données
Cas des données de différents types main()
{double x;
int a;
double y;
int b;
double z;

  Octet 0 Octet 1 Octet 2 Octet 4 Octet 5 Octet 6 Octet 7 Octet 8


28FF20 z
28FF28         b
28FF30 y
28FF38         a
28FF40 x
Structures de contrôles
 La structure linéaire Traitement 1

Traitement 2
se caractérise par une suite d’actions 
à exécuter dans l’ordre où elles sont énoncées Traitement 3

Traitement 4
 Les structure de contrôle

Permettent de contrôler l’exécution d’une suite 
d’instructions

o Structures de contrôle alternatives

o Structures de contrôle répétitives
* Les structures
Alternatives

Une structure alternative offre la possibilité de donner des issues 
différentes à la poursuite d’un algorithme. 
   Ces issues s’excluent mutuellement.
   On peut rencontrer plusieurs formes de structures alternatives :
* Les structures
Alternatives
Forme alternative réduite :
 Contrôle d’un seul bloc d’instruction
 Dans cette structure, l’exécution du traitement T2 ne dépend que 
la réalisation de la condition qui le précède :

Traitement 1
si la condition est vérifiée  si la condition n’est pas 
Si Vrai vérifiée les traitements se 
les traitements se font  Condition
dans cet ordre : (T1 T2  font dans cet ordre : (T1 
 T3). Si Faux T3).
Traitement 2

Traitement 3
* Les structures
Alternatives
Forme alternative complète :
 Contrôle de plusieurs bloc d’instruction
 Dans cette structure, l’exécution de l’un des deux 
traitements distincts possibles T2 et T3 ne dépend que la 
réalisation de la condition qui les précède :

Traitement 1
Si Vrai Si Faux
si la condition est  Condition si la condition n’est 
vérifiée les  pas vérifiée les 
traitements se font  traitements se font 
dans cet ordre : Traitement 2 Traitement 3 dans cet ordre : 
 (T1 T2  T4). (T1 T3  T4).

Traitement 4
* Les structures
Alternatives
Forme réduite

La structure SI ... ALORS….FIN SI


Langage C

IF ( <condition> )
{
[<bloc
d'actions-1>]
}
[<bloc d'actions-2>]
 Le bloc d’actions 1 est exécuté seulement au cas où la condition 
prend  la  valeur  Vrai.  Dans  le  cas  contraire  le  programme  passe 
directement le bloc 2 . 
 Avec cette structure on ne peut contrôler qu’un seul bloc d’action
* Les structures
Alternatives
Forme complète

La structure SI ... ALORS…SINON….FIN SI

IF ( <condition> )
{
[<bloc d'actions 1>]
}
ELSE
{
[<bloc d'actions 2>]
}

 Au cas où la condition est vraie seul le bloc d'instruction-1 est 
exécuté. Dans le cas contraire seul le bloc d'instructions-2 est 
exécuté.
 Avec cette structure on peut contrôler plusieurs bloc d’action
* Les structures
Alternatives
Forme complète

Lorsqu’il y a ambiguïté sur la structure « if » dont dépend une partie 
else, l’ambiguïté est levée en faisant dépendre le « else » de 
l’instruction « if » la plus proche.

if (a > b)
if (a > b) {
if (c < d) if (c < d)
u = v; u = v;
else }
i = j; else
i = j;
* Les structures
Alternatives
* Les structures
Alternatives
Vrai
Si Cond 1

TA Faux TAT1TB
T1

Vrai
Si Cond 2
Faux TAT2TB
T2

Vrai
Si Cond n
Faux TATnTB
Tn

Aucune Cond

TATn+1TB
T n+1

TB
* Les structures
Alternatives
if <condition1>
{Traitement 1;}
else { if <condition1>
if <condition2> {Traitement 1;}
{Traitement 2;} else if <condition2>
else { {Traitement 2;}
if <condition3> else if <condition3>
{Traitement 3;} {Traitement 3;}
else { else if <condition4>
if <condition4> {Traitement 4;}
{Traitement 4;} else
else { {Traitement 5;}
Traitement 5;
}
}
}
* Les structures
Alternatives
• Structure de choix multiple (selon que)  
Au lieu de faire des « Si » imbriqués ou des Sinon Si, il suffit d’indiquer 
quoi faire quand telle ou telle valeur d’une expression est rencontrée. 
En algorithmique

switch(variable)
Le mot clé « break » indique la 
{
sortie de la structure 
case valeur 1 : liste intruction; break;
conditionnelle. 
case valeur 2 : liste intruction; break;
case valeur 3 : liste intruction; break;
Le mot clé « default » précède 
case valeur 4 : liste intruction; break;
la liste d'instructions qui sera 
.
exécutée si l'expression n'est 
.
jamais égale à aucunes 
.
valeurs des « case ».
case valeur n : liste intruction;break;
default: liste intruction;
}  
* Les structures
Alternatives
Forme alternative : (Cas des conditions non disjointes)
contrôle deux traitements (T et T’)
dans  ce  cas  on  va  combiner  les  conditions  Ci  avec  les  opérateurs 
logiques (AND, OR, XOR). 
Exemple : 

If (C1 && C2 && C3 && ……&& Cn)


{trairement 1;}
Else
{trairement 2;}
* Les structures
Alternatives
Forme alternative multiple : (Cas des conditions non disjointes)
Contrôle de plusieurs traitements
dans ce cas on va imbriquer les structures alternatives. 
Exemple : 
* Les structures
Alternatives
Vrai
Si C1
TA Si Cond 2 Vrai
Si C2
Vrai
Si C3
Faux
Faux
Faux

Vrai
Si Cn

Aucune Cond Faux


Tn
T n+1 T’n
T’3
T’2
T’1
TB
* Les structures
if <condition1> 
Alternatives
        if<condition2>
            if <condition3> 
Tn : Si C1 AND C2 AND …… AND Cn
.
.
if <condition(n)>
                  {Traitement n}
                  else 
                  {Traitement n’}

.
.
else  
            {Traitement 3’}
else
      {Traitement 2’}
else
{Traitement 1’}
• Si (a=0) AND (b=0) AND (c=0)     alors «la solution est IR »

• Si (a=0) AND (b=0) AND (c#0)     alors  «impossible»

• Si (a=0) AND (b#0)                     alors   x1  -c/b

• Si (a#0)                                      alors calcul de Delta 
#include <math.h>
main(){ {
float a, b,c; delta=b*b-4*a*c;    
float delta; printf("DELTA=%f\n", delta);     
printf("resolution de l'eq  if (delta>0)
ax²+bx+c=0\n"); {
printf("a=");     printf("la solution est:%f\n", (-b-
scanf("%f", &a); sqrt(delta))/2*a);
printf("b=");     printf("la solution est:%f\n", (-
scanf("%f", &b); b+sqrt(delta))/2*a);
printf("c="); }
scanf("%f", &c); else if (delta == 0)
if (a==0)         printf("la solution est:%f\n", -
   if (b==0) b/(2*a));
      if (c==0)     else
      printf("la solution est : IR");          printf("pas de solution dans IR");    
      else }
      printf("résolution impossible");
    else
    printf("la solution est : %f", -c/b);
else
Structures de contrôle itératives

Les structures itératives permettent de répéter l’exécution d’un 
ensemble d’instructions une ou plusieurs  fois.
  
Ces structures sont regroupées sous deux grandes familles 
selon si : le nombre de répétitions est connu ou pas.

Nombre  Nombre 
connu de  inconnu de 
répétitions répétitions
Structures de contrôle itératives
Cas ou le nombre de répétition est connu :

Dans  cette  structure,  la  sortie  de  la  boucle  d’itération  s’effectue 
lorsque le nombre souhaité de répétition est atteint.
On utilise donc une variable d’itérations caractérisée par :

• sa valeur initiale,
• sa valeur finale,
• son pas de variation.
Structures de contrôle itératives
Cas ou le nombre de répétition est connu :

Faire la somme de N valeurs

Var V, S entiers
int V, S, N,i
S  0
S = 0
Lire (V)
Printf(« V (N)
S  S + V
for (i=1; i<=N; i++)
Lire (V)
{
S  S + V
• Lire (V)
Lire (V)
• S  S + V
S  S + V
}
Lire (V)
Printf(‘’S= %d’’, S)
S  S + V
.
.
.
Afficher (S)
Structures de contrôle itératives
Pour….allant….suivant

 Si la valeur finale de l’indice est inférieure à sa valeur
initiale le pas de variation est négatif, la structure est
dite «décroissant »
 dans le cas contraire, le pas est positif et la
structure est dite «croissant »
i0 < if
For(i=i0; i<=if; i++) For(i=if; i>=i0; i--)
{ {
. .
. .
} }
Structures de contrôle itératives

Pseudo - code Language C


Pour i Vi à Vf [pas  p] for(i = Vi ; i <= Vf ; i = i + 1)
[<bloc d’actions >] {
Suivant  i [<bloc d’actions >]
}

Le bloc d'instructions est exécuté un nombre de fois connu à


l’avance contrôlé par un compteur allant de la valeur Vi
(valeur initiale) à la valeur Vf(valeur finale).

Attention :
le traitement ne doit pas modifier la variable itérative (compteur)
Structures de contrôle itératives
Exemples Pour….allant….suivant
Cet algorithme fait la somme d’un certain nbre de valeurs saisies)

Pseudo - code Language C


Var i, S, var : entiers int i, S, var;
S  0 S = 0;
Pour i allant de 0 à 3 for (i=0; i<=3; i++)
  Afficher ("var ="  ) {
  Lire (var)   printf("var =");
  S  S + var   scanf("%d",&var);
Suivant i   S = S + var;
Afficher("La somme est :", S) }
Afficher(i) printf("la somme est :%d", S); 
Structures de contrôle itératives
Exemples Pour….allant….suivant

int i, S, var; SIMULATION
S = 0;
for (i=0; i<=3; i++) i=0 var=2 S=0+2 2
{ i=1 var=-3 S=2-3 -1
  printf("var =");
i=2 Var=4 S=-1+4 3
  scanf("%d",&var);
  S = S + var; i=3 Var=-8 S=3-8 -5
} i=4 Arrêt des itérations
printf("la somme est :%d", S); 
EN MEMOIRE
i = 4 S = -5
Structures de contrôle itératives
Exemples Pour….allant….suivant

int A,B,C ; A=6; B=4; C=-2
A=6;
itératio Test logique A=6 B=4 C=-2
B=4;
n (A>B)
C = -2;
i=1 Vrai 6-2= 4 -2 -2
for(i=1; i<= 5; i++)
if (A > B){ i=2 Vrai 4-2 = 2 -2 -2
        A = A + C; i=3 Vrai 2-2 = 0 -2 -2
        B = C;} i=4 Vrai 0-2 = -2 -2 -2
Else{
i=5 Faux -2 -2+2 = 0 0
       B = B – C;
       C = B; i=6 Arrêt des itérations
}
printf(‘’A=%d’’, A); En mémoire
printf (‘’B=%d’’, B); i=6 A=-2 B=0 C=0
printf (‘’C=%d’’, C);
Structures de contrôle itératives
Pour….allant….suivant

Cas des boucles imbriquées

Pseudo - code Visual Basic


Pour i allant de  Vi à Vf [pas  p] for(i = Vi ; i <= Vf ; i = i + 1)
{
     Pour j allant de  Wi à Wf [pas  p] for(j = Vi ; j <= Vf ; j = j + 1)
   [<bloc d’actions >] {
Suivant  j [<bloc d’actions >]
}
Suivant i }
Structures de contrôle itératives
Exemples Pour….allant….suivant

Int S, i;  j;
j=1 j=2 j=3
S  0; i=1 S=0+1+1=2 S=2+1+2=5
i=2 S=5+2+1=8 S=8+2+2=12
for(i=1; i<=3; i++)   
{  i=3 S=12+3+1=16 S=16+3+2=21
    for(j=1; j<=2; j++)       i=4 Arrêt des itérations
       {S = S + i + j}

EN MEMOIRE
printf (“la somme est %d”, S)
i = 4 S = 21
j = 3
Structures de contrôle itératives
Cas ou le nombre de répétition est inconnu
:
While

 Dans  cette  structure,  la  sortie  de  la  boucle  d’itération 


s’effectue lorsqu’une condition n’est plus vérifiée.
 Tant que la condition est vérifiée on répète l’exécution du 
bloc d’instruction contrôlé
 Le  nombre  des  itérations  est  donné  après  la  sortie  de  la 
boucle
Structures de contrôle itératives
Tant que …. faire

Pseudo - code Langage C


i  Vi i  i0
Tant que <condition> faire While <condition>
[<bloc d’actions >] {
i  i+1 [<bloc d’actions >]
Fin tant que i  i+1
}

Dans ce cas la vérification de la condition se fait avant 
l’exécution du bloc d’instruction

Le bloc d’instruction peut ne jamais être exécuté
Structures de contrôle itératives
Exemples Tant que …. faire
Cet algorithme fait la somme des valeurs saisies, arrêt lorsque var = -1)

Language C
int S, var;
i = 1;
S = 0;
printf("saisir la valeur", i);
scanf("%d",&var);
while (var!=-1)
{
   S = S + var;
   i = i + 1;
   printf("saisir la valeur %d", i);
   scanf("%d",&var);
}
printf("la somme est :%d",S);
printf("le nbre de valeur est :%d",i-1);
Structures de contrôle itératives
Tant que …. faire

int S, var; SIMULATION
i = 0;
var=2 i=1 S=0+2 2
S = 0;
printf("saisir la valeur", i); var=-3 i=2 S=2-3 -1
scanf("%d",&var); Var=4 i=3 S=-1+4 3
while (var!=-1) Var=-8 i=4 S=3-8 -5
{
   S = S + var; Var=-1 i=5 Arrêt des itérations
   i = i + 1;
   printf("saisir la valeur", i); EN MEMOIRE
   scanf("%d",&var);
i = 5 S = -5
}
printf("la somme est :%d",S);
printf("le nbre de valeur est :%d",S);
Comparaison boucles pour et tant que

• Implicitement, l’instruction for:
 initialise un compteur
 incrémente le compteur à chaque pas
 vérifie que le compteur ne dépasse pas la borne 
supérieure
• Explicitement, l’instruction While il faut
 initialiser un compteur {amorçage}
 incrémenter le compteur à chaque pas {relance}
 vérifier que le compteur ne dépasse pas la borne 
supérieure {test de boucle}
Structures de contrôle itératives
Cas ou le nombre de répétition est inconnu
:
Do …..While

 Dans  cette  structure,  la  sortie  de  la  boucle  d’itération 


s’effectue lorsqu’une condition n’est plus vérifiée.
 Tant que la condition est vérifiée on répète l’exécution du 
bloc d’instruction contrôlé
 Le  nombre  des  itérations  est  donné  après  la  sortie  de  la 
boucle
Structures de contrôle itératives
Répéter …….tant que

Pseudo - code Visual Basic


i  Vi i=i0
Répéter do
   [<bloc d’actions >] {
i  i+1 [<bloc d’actions >]
Tant que <condition> i=i+1
}
while ([condition]);

Dans ce cas la vérification de la condition se fait après  
l’exécution du bloc d’instruction

Le bloc d’instruction s’exécute au moins une fois
Structures de contrôle itératives
Exemples Répéter …….tant que
Cet algorithme fait la somme des valeurs saisies, arrêt lorsque S>=1000)

Language C
int S, i, var;
i = 0;
S = 0;
do
{
  printf("Saisir la valeur" , i);
  scanf("%d",&var);
  S = S + var;
  i = i + 1;
}
while (S<1000);
printf("la somme est :%d",S);
printf("le nbre de valeur est :%d",i);
Comparaison boucles répéter et tant que

• boucle While
 condition vérifiée avant chaque exécution du traitement 
 le traitement peut donc ne pas être exécuté
 la condition porte surtout sur la saisie de nouvelles 
variables (relance)

• boucle Do While
 condition vérifiée après chaque exécution du traitement 
 le traitement est exécuté au moins une fois
 la condition porte surtout sur le résultat du traitement

Remarque: la boucle répéter est typique pour les saisies 
avec vérification. 
Choisir pour... tant que… répéter…

Boucle Tant que
n
No
Traitement 
exécuté au 
moins une 
Non fois
Oui
Nombre 
d’itération 
connu ? Boucle Répéter

Oui

Boucle Pour
L’algorithme du Max et du Min
Trouver la max d’un certain nombre connu de valeur

int x, Max, Nmax;


printf(« saisir la valeur 1 »);
Scanf(«%d», &x);
Max = X
Nmax = 1
for (i=2; i<=10 ; i++){
printf(« saisir la valeur 1 »);
Scanf(«%d», &x);}
if (x>Max){
Max = x
Nmax = 0
}
if Max = X {
Nmax=Nmax+1}
}
printf(« la valeur Max est : %d», Max)
printf(« le nbre des Max est : %d», Nmax)
int x, Max, Nmax
i=1
printf (« donner la valeur  %d», i)
L’algorithme du Max
Trouver&x)
scanf(« %d», la max et le min d’un certain nombre inconnu de valeur. La
if (X==0) { saisie s’arrête lorsqu’on saisie une valeur égale à zéro
printf(« saisie terminée »)
printf(« le nombre de valeur est: %d», i - 1)}
Sinon
Max = X
       Nmax = 1
Tantque (X!=0)
if (X>Max){
          Max  x
          Nmax  0
        }
       if (Max == X){
         Nmax = Nmax+1
       }
       i++
printf (« donner la valeur %d», i)
scanf(« %d», &x)
}
printf(« saisie terminée »)
printf(« le nombre de valeur est: %d», i - 1)
printf(« la plus grande valeur est: %d», Max)
printf(« ce maximum est saisie : %d fois», Nmax)
}
Les tableaux

Exemple de problème :
Saisir une suite de nombres, puis afficher cette suite après 
avoir divisé tous les nombres par la valeur maximale de la 
suite.

Nécessité de conserver les nombres en mémoire

Variable contenant une valeur  Variable contenant plusieurs valeurs 

var 132

var 23 -12 -11 2 23 23 21 12 123 132


Les tableaux
Un tableau est une variable qui peut contenir plusieurs données de même type:
Tableau d’entiers
Tableau de réels
Tableau de caractère

Un tableau possède des dimensions
 Tableau à une dimension (ligne) (liste de données)
 Tableau à deux dimensions (ligne colonne) (traitement d’image)
 Tableau à trois dimensions (ligne, colonne profondeur) (données spatiales)
 Tableau à quatre dimensions (ligne, colonne, profondeur, temps) (données 
spatiales qui évolue dans le temps)
 …..
 L’espace mémoire réservé pour une tableau augmente fortement avec le nombre de 
dimension. Problème de la taille limité de la mémoire
Les tableaux Accès aux données
L’accès à une donnée (case) dans un tableau nécessite un ou plusieurs indices:
- Tableau à une dimension : un seul indice utilisé 
- Tableau à deux dimensions : deux indices utilisés (indice ligne et indice colonne)
- Tableau à trois dimensions : trois indices utilisés.

 les "cases" sont numérotées à partir de zéro, autrement dit que le plus 
petit indice est zéro. 

 Lors de la déclaration d'un tableau, on précise la plus grande valeur de 
l'indice qui est différente du nombre de cases du tableau.

 si on veut stoker 12 valeurs, le plus grand indice sera 11). 

En pseudo-code on écrit Var tab1(11) : entiers


Var Tab2(19)(29) : réels
Les tableaux Accès aux données
Nom du tableau indice
0 1 2 3 4
Tab1 12 3 4 -56 -8
valeurs

Indice ligne
Indice colonne
0 1 2 3 4
1 3 4 -56 -8
2 3 4 6 7 valeurs
3 2 12 32 43
4 2 6 7 9

Nom du tableau Tab2

Tab1(3)=-56 Tab2(3)(2)=12
Les tableaux Accès aux données
0 1 2 ….. 499
12 1 2 …… 5

P 0 0 0 0 1 1 0 0

P+1 0 0 0 0 0 0 0 1
P+2 0 0 0 0 0 0 1 0
……. ... … … … … … … …
P+499 0 0 0 0 0 1 0 1

T un pointeur qui pointe l’adresse mémoire où on stock la première 
valeur
T+0=&T[0]
*(T+0)=T[0]
T+1=&T[1]
*(T+1)=T[1]
T+2=&T[2]
*(T+2)=T[2]

..
T+499=&T[499]
*(T+499)=T[499]
Les tableaux Accès aux données

main()
main()
{
{
int *T, i, n;
int T[9], i;
printf("n= ");
for(i=0; i<=9; i++)
scanf("%d", &n);
{
T=(int*)malloc(n*sizeof(int));
printf("T[%d]= ", i);
for(i=0; i<=n-1; i++)
scanf("%d", &T[i]);
{
}
printf("T[%d]= ", i);
system("PAUSE");
scanf("%d", T+i);
return 0;
}
}
system("PAUSE");
return 0;
}
Les tableaux Accès aux données
 En mémoire un tableau occupe un seul bloc.
 Ce bloc est linéaire.
 Dans un tableau à plusieurs dimensions, l’accès à une données (case) 
provoque un déplacement en mémoire à partir du début.
0 1 2 ….. 499
0 12 1 2 …… 5
1 23 12 21 …… 56
2 44 34 23 …… 54
3 3 5 4 …… 23
….. …… ….. …… …… …..
999 4 3 6 …… 4

Ligne 0 Ligne 1 Ligne 2


0 1 2 ….. 499 0 1 2 ….. 499 0 1
12 1 2 …… 5 23 12 21 ….. 56 44 34
Les tableaux Accès aux données
On peut considérer un tableau T[n-1][p-1] comme 
un tableau unidimensionnel T[n*p-1] 
0 1 2 ….. 499
0
1
2
3
…..
999

Pour accéder  à T[3][2] il faut 500*3+2 déplacements

Tableau(n)(p) déplacement de (Nmax+1)*n+p

Augmentation du temps d’exécution des algorithmes
Les tableaux Accès aux données
On procède par un accès directe aux lignes du tableau via leur adresse 
mémoire.
Il faut donc calculer les adresses de toutes les lignes à l’avance et les conserver 
dans un tableau de pointeurs..

*(T+0) 12 1 2 …… 5
*(T+1) 23 12 21 …… 56
*(T+2) 44 34 23 …… 54

*(T+3) 3 5 4 …… 23

*(T+4) …… ….. …… …… …..

*(T+5) 4 3 6 …… 4

Pour accéder  à T[3][2] il faut 2 déplacements
Les tableaux Accès aux données
Chaque ligne est un tableau unidimensionnel
Adresses valeurs
Un tableau de pointeur
P0
*(T+0) *(*(T+0)+0)  = 12
*P0 = 12
T[0] = *(T+0) = P0 P0+1
*(T+0) +1 *(*(T+0) +1) = 1
*P0+1 = 1
T[1] = *(T+1) = P1 P0+2
*(T+0) +2 *(*(T+0) +2)  = 2
*P0+2  = 2
T[2] = *(T+2) = P2
P0+j
*(T+0) +j ......
….. *(T+1)
P1 *(*(T+1)+0)  = 12
*P1 = 123
T[i] = *(T+i) = Pi
*(T+1) +1
P1+1 *(*(T+1) +1) = 1
*P1+1 = 14
P1+2
*(T+1) +2 *P1+2  = 26
*(*(T+1) +2)  = 2
P1+j
*(T+1) +j ...

P2
*(T+2) *P2 = 129
*(*(T+2)+0)  = 12
P2+1
*(T+2) +1 *P2+1 = 145
*(*(T+2) +1) = 1
P2+2
*(T+2) +2 *P2+2  = 23
*(*(T+2) +2)  = 2
P2+j
*(T+2) +j ...
Les tableaux Accès aux données
main()

main() int **T, i, j, n, m;
{  printf("n= ");
int T[2][2], i, j; scanf("%d", &n);
for(i=0; i<=2; i++) printf("m= ");
{ scanf("%d", &m);
         for(j=0; j<=2; j++) T=(int**)malloc(n*sizeof(int));
         { for(i=0; i<=n-1; i++)
         printf("T[%d][%d]= ", i, j); {
         scanf("%d", &T[i][j]);          *(T+i)=(int*)malloc(m*sizeof(int));
         }          for(j=0; j<=m-1; j++)
}          {
system("PAUSE");          printf("T[%d][%d]= ", i, j);
return 0;              scanf("%d", *(T+i)+j);
}          }
}
printf("T[2][1]= %d", *(*(T+2)+1));
system("PAUSE");
return 0;    
}
Les tableaux Accès aux données
main()

int *T, i, n, m;
printf("n= ");
scanf("%d", &n);
printf("m= ");
scanf("%d", &m);
T=(int*)malloc(n*m*sizeof(int));

for(i=0; i<=(n*m-1); i++)
{
printf("T[%d]= ", i);
scanf("%d", (T+i));
}

system("PAUSE");
return 0;    
}
malloc() & realloc()

La syntaxe de la fonction malloc() est :
 
(Type*)malloc(Nbre_case*sizeof(Type))
 
Cette fonction retourne un pointeur d’un certain type (Type*) pointant vers un 
objet de taille (Nbre_case)*sizeof(Type) octets. 

La syntaxe de la fonction remalloc() est : 

(Type*)malloc(pointeir, Nbre_case*sizeof(Type))
 
Cette fonction permet de modifier la taille de la zone mémoire pointé par 
« pointeur »   
malloc() & realloc()

(type*)Malloc(6*sizeof(type)

P *P P *P
*(P+1) *(P+1)
*(P+2) (type*)Realloc(P, 8*sizeof(type) *(P+2)
*(P+3) *(P+3)
*(P+4) *(P+4)
*(P+5) *(P+5)
*(P+6)
*(P+7)
Les Tableaux
Insertion d’un élément :
Ecrire un programme qui saisit la dimension N d’un tableau de int 
remplit le tableau par des valeurs entrées au clavier. Insérer 
ensuite une valeur « e » à une position « pos » du même tableau. 
Afficher enfin le tableau avec la valeur insérée.
Insérer un élément dans la case 2

0 1 2 3 4 5
12 4 11 78 15
Les Tableaux
suppression d’un élément :
Ecrire un programme qui saisit la dimension N d’un tableau de int 
remplit le tableau par des valeurs entrées au clavier. Supprimer 
ensuite la valeur d’une position « pos » du même tableau. Afficher 
enfin le tableau de N-1 éléments.
Suppression de l’élément de la case 2

0 1 2 3 4
12 4 11 78 15
Les Tableaux
Union de tableau:
Ecrire un programme qui saisit deux tableaux de dimension  # et de 
créer un troisième dont les éléments représentent l’union des 
deux tableaux.

0 1 2 3 0 1 2
12 4 13 6 12 4 13

0 1 2 3 4 5 6
12 4 13 6 12 4 13
Les Tableaux
Intersection de tableaux:
Ecrire un programme qui saisit deux tableaux de dimension  # et de 
créer un troisième dont les éléments représentent l’intersection 
des deux premiers tableaux.

0 1 2 3 0 1 2
12 4 13 6 12 4 9

0 1
12 4
Exercice:
Donner un algorithme qui stocke un certain nombre inconnu de notes dans un tableau 
de valeur et calcule et affiche la moyenne. L’utilisateur peut arrêter la saisie en 
entrant (-1).
Algo & Prog C-2

Fonctions et Procédures

Chaines de caractère

Les Structures

Les Fichiers
Les fonctions & les procédures
On  peut  dans  une  application  procéder  aux  mêmes 
traitements,  ou  à  des  traitements  similaires,  à  plusieurs 
endroits de son déroulement.

Ces traitements vont être écrite dans des algorithmes à part
 Fonctions
 procédures

Dans l’algorithme principale on peut appeler plusieurs fois 
une fonction ou une procédure
Une fonction ou une procédure peut elle-même appeler 
une ou plusieurs fonctions et procédures.
Les fonctions & les procédures

Structuration
Diviser pour
mieux régner
Les fonctions et les procédures permettent de décomposer 
un programme complexe en une série de sous-
programmes plus simples, lesquels peuvent à leur tour 
être décomposés eux-mêmes en fragments plus petits, et 
ainsi de suite.
Intérêts Les fonctions & les 
procédures
 Regrouper un ensemble d’instruction dans le même 
algorithme afin de pouvoir y faire appel autant de fois que 
nécessaire.
 Lisibilité et identification des erreurs, réutilisation
 On peut ne pas connaître comment est définie une 
fonction ou une procédure pour y faire appel. Par contre il 
est nécessaire de connaître sa déclaration (son manuel 
d’utilisation):
 Quel est son rôle?
 Quels sont les arguments à fournir?
 Quelles est la valeur retournée?
Les fonctions & les procédures
Les procédures et fonctions peuvent nécessiter éventuellement zéro un 
ou plusieurs paramètres d’entrée ou de sortie. 

Un paramètre d’entrée est la référence à une variable manipulée 


par la procédure ou la fonction. Dans ce cas la valeur d’une variable 
du programme principal est copiée dans ce paramètre.

Un paramètre de sortie est une variable dont la valeur est affectée par 


les instructions du sous-programme

Un paramètre d’entrée-sortie Un paramètre peut jouer à la fois le rôle 


de paramètre d’entrée et de sortie.  
  
On peut avoir des fonctions qui nécessite pas de paramètres pour qu’ils 
soient exécutées. On parle de fonction sans argument
Les fonctions
 Les fonctions sont des sous-programmes admettant des paramètres et 
retournant un seul résultat (comme les fonctions mathématiques y=f(x,y,. . .))
les paramètres sont en nombre fixe (n>=0)
une fonction possède un seul type, qui est le type de la valeur retournée
la valeur de retour est spécifiée par l'instruction Return

 Généralement le nom d’une fonction doit être explicite:
Maximum()
Minimum()
Syntaxe: Exemple

type NomFonction (type a, type b, type c, …){


Type res ;

Return res }

type NomFonction (type *a, type *b, type c, …){


Type res ;

Return res }

type * NomFonction (type a, type b, type c, …){


Type res ;

Return res }
Syntaxe: Exemple

type NomFonction (type a, type b, type c, …){


Type res ;

Return res } Paramètres Formels

Main()
{ type P, x, y, z ……;
………
P = NomFonction (x, y, z, …)
……}

Paramètres effectifs
Les fonctions
Exemple : fonction qui renvoi le maximum de deux variables a et b 
(paramètres d’entrés).

• #include <stdio.h>
• int Max(int a, int b) main()
• { { int M, x, y;
•   int res;   printf("x = ");
•   res=a;   scanf("%d", &x);
•   if(b>res)   printf("y = ");
•   res=b;   scanf("%d", &y);
•   return(res);   M=Max(x, y);
• }   printf("Max = %d", M);
}
Les fonctions
Exercice : Ecrire une fonction int FMax(int *T, int n) qui permet de trouver le 
maximum d’un tableau d’un certain nombre de valeurs. Ecrire un algorithme 
test qui appelle cette fonction.

#include <stdio.h> main(){


#include <stdlib.h> int i, n, *tab, M;
int Fmax(int *T, int printf("donner le nombre de
n) valeur n = ") ;
{int Max, i; scanf("%d",&n);
Max=T[0]; tab=(int*)malloc(n*sizeof(int));
for(i=0; i<n; i++) for (i=0; i<n; i++)
{if(T[i]>Max) {printf("tab(%d) = ", i);
Max=T[i];} scanf("%d", tab+i);}
return(Max);} M=Fmax(tab, n);
printf("maximum est : %d", M;}
Les Procédures
 Les procédures sont des sous-programmes qui ne retournent aucun 
résultat

 Par contre elles admettent des paramètres d’entrés, de sorties ou 
d’entrés/sorties:

Syntaxe: Exemple

void NomProcédure (type a, type b, type c, …. )


{ Type  variablesLocals;

…}
Syntaxe: Exemple

void NomProcédure (type a, type b, type c, …){


Type res ;
…}
Paramètres Formels

Main()
{ type P, x, y, z ……;
………
NomProcédure (x, y, z, …)
……}

Paramètres effectifs
Exercices: Ecrire une procédure qui permet d’afficher le Max et le Min d’un 
tableau d’entier.  void MaxMin(int *V, int n)

int Fmax(int *T, int n) int Fmin(int *T, int n)


{int Max, i; {int Min, i;
Max=T[0]; Min=T[0];
for(i=0; i<n; i++) for(i=0; i<n; i++)
{if(T[i]>Max) {if(T[i]<Min)
Max=T[i];} Min=T[i];}
return(Max);} return(Min);}

void MaxMin(int *V, int n)


{
printf("max = %d\n", Fmax(V, n));
printf("min = %d\n", Fmin(V, n));
}
Exercice

 Ecrire une procédure permute(a, b) qui permute les 
valeurs de ceux variables entiers.
 Ecrire un algorithme d’essai. Transmission de valeurs
#include <stdio.h> Pas de permutation
void permute(int a, int b)
{int k;
main(){
k = a;
int x, y;
a = b;
printf("x = ");
b = k;}
scanf("%d", &x);
&a a printf("y = ");
scanf("%d", &y);
&b b
permute(x, y);
&x x printf("x = %d\n", x);
printf("y = %d", y);}
&y y
Exercice

 Ecrire une procédure permute(a, b) qui permute les 
valeurs de ceux variables entiers.
 Ecrire un algorithme d’essai. Transmission d’adresse
#include <stdio.h>
void permute(int *a, int *b)
{int k;
main(){
k = *a;
int x, y;
*a = *b;
printf("x = ");
*b = k;}
scanf("%d", &x);
printf("y = ");
a=&x a scanf("%d", &y);
permute(&x, &y);
b=&y b
printf("x = %d\n", x);
printf("y = %d", y);}
Exercice
Ecrire une procédure permute(a, b) qui permute les valeurs de ceux 
variables entiers. Ecrire une autre procédure Tri (x, y, z) qui tri dans 
l’ordre décroissant en appelant la procédure permute(a, b).
#include <stdio.h>
void permute(int *a, int *b){
int k; main(){
k=*a; int z1,z2,z3;
*a=*b; printf("donner trois
*b=k;} valeurs\n");
void tri(int x, int y, int z){ scanf("%d", &z1);
if (x<y) scanf("%d", &z2);
permute(&x,&y); scanf("%d", &z3);
if (y<z) tri(z1, z2, z3);}
permute(&y,&z);
if (x<y)
permute(&x,&y);
printf("%d%d%d", x, y, z);}
Exercice
Créer une fonction max(a,
#include <stdio.h> b) qui renvoi le maximum de deux 
variables:
int Max(int a, int b){
Créer une fonction VMAX(T) qui permet trouver le maximum des 
intéléments d’un vecteur de 4 valeurs et ceci en appelant la fonction 
res;
res=a; main(){
max(). Créer un algorithme d’essai.
if(b>a) int V[5], i;
{res=b;} for (i=0; i<=4; i++){
return (res);} printf("V[%d]=", i);
scanf("%d", &V[i]);}
printf("le maximum est: %d\n", VMAX(V));}

int VMAX(int *V){


int i, M;
for (i=0; i<=4; i++)
M=Max(Max(Max(Max(V[0], V[1]),V[2]),V[3]),V[4]);
return (M);}
Processus d’analyse

La décomposition en sous traitement

Le processus d’analyse permet de décomposer un traitement complexe en 
sous  traitement  « plus  simples »  mais  différent  du  précédent.  À  leur 
tour,  ces  sous  problèmes  seront  à  leur  tour  décomposés  jusqu’à  un 
niveau d’opération « élémentaires » faciles à réaliser.
Processus d’analyse

La décomposition récursive

Dans  certain  cas,  le  sous  traitement  est  une  illustration  du  problème  initial, 
mais pour un cas « plus simple ». Par conséquent, la solution du problème 
s’exprime  par  rapport  à  elle-même!  On  appelle  ce  phénomène 
récursivité.
 
Dans  un raisonnement par récurrences :  pour  résoudre  un  problème 
complexe  on  appelle  e  même  traitement  initial  mais  avec  un  cas  plus 
simple.
Traitement complexe
 Sous Traitement 1
Sous traitement 2
Traitement élémentaire
 
Méthode itérative et récursive

Méthode itérative : un traitement élémentaire qui progresse grâce à une boucle. 


Le dernier traitement donne le résultat final.

Méthode récursif: le calcul final est exprimé en fonction du calcul précédent. Donc 


pour faire un traitement revient à faire le même traitement mais pour un cas plus 
simple jusqu’a arrivé au traitement élémentaire. 

X0
        * X X4 =

X               * X
1 X * X3

X                          * X
2 X * X2

X                                         * X
3 X * X1

X                                                    * X
4
X * X0
= X4
Raisonnement par récurrence
Exemple de Récursivité

la factoriel de n est : 
n! = 1*2*3…..*n : traitement itératif
n! = n*(n-1)*(n-2)*(n-3)*…..*1 
n! = n*(n-1)! : traitement récursif

Pour calculer la valeur de n!, il suffit donc de savoir calculer 
(n-1)! Et ensuite de multiplier cette valeur par n. 
Le  sous  problème  du  calcul  (n-1)!  Est  le  même  problème 
initial, mais pour un cas « plus simple » car (n-1 < n)
Fonction récursive

Dans les algorithmes

 Pendant le traitement d’une fonction nous pouvons 
appeler d’autres fonctions déjà déclarées (décomposition 
en sous problèmes)
 Nous pouvons aussi, Pendant le traitement d’une 
fonction, appeler la même fonction initiale mais avec des 
arguments plus simples (décomposition récursive) 
 Une fonction récursive est une fonction qui s’appelle 
elle-même dans son traitement. 
 Si la fonction appelée n’est autre que la fonction qui 
appelle, on déclenche une boucle.
Fonction récursive
Type F(type a, type b){ Type RF(type z){
float res; Type Var x, res
….. …..
Return res } Res = RF(x)
Return res
• Type NF(type z ){
• Type x, y, res2 RF(x)
• …..
• res2 = F(x, y)
• return res2 }
RF() est fonction une récursive
Fonction – Factorielle

 On peut écrire la factorielle de N par une suite:

Avec Un = n!. Sous cette forme Un dépend de n et Un-1.
Ecrire l'algorithme de la fonction factorielle en employant la 
récursivité.
Fonction itérative – Factorielle 
Résonnement itérative Résonnement récursive
#include <stdio.h> #include <stdio.h>
int fact(int n){ int fact(int n){
int res, i; int res, i;
res=1; if(n==0)
for(i=1; i<=n; i++) res = 1;
res=res*i; else
return(res);} res=n * fact(n-1);
return(res);}

main(){
int x;
printf("x = ");
scanf("%d", &x);
printf("%d! = %d", x, fact(x));}
Fonction récursive – Factorielle
#include <stdio.h>
int fact(int n){ Simulation: Pour N = 5
int res, i; Fact(5)=5*Fact(4)
            =5*4*Fact(3)
if(n==0)             =5*4*3*Fact(2)
res = 1;             =5*4*3*2*Fact(1)
else             =5*4*3*2*1
res=n * fact(n-1);
return(res);}
Fonction– Racine carrée
 La valeur de la racine carrée d'un nombre A peut être 
approximée en employant la suite récurrente d'ordre 1 
suivante:
La récursivité ne porte pas sur la variable 
principale du problème A (variable dont 
on cherche la racine : A) mais la 
récursivité porte sur une autre variable 
X
 Version  Version récursive
itérative
float float racine(float A,float e,
racine(floatA,floate){ float X){
float X; float res;
X=A; if(abs(X*X-A)<=e)
while(abs(X*X-A)>e) res = X;
X=(X+A/X)/2; else
return(X);} res = racine(A,e,(X+A/X)/2);}
main(){ return (res);}
float Y, e;
printf("Y=");
scanf("%f", &Y);
printf("e=");
scanf("%f", &e);
printf("Racine(%f)=%f", Y, racine(Y,e));}
 Version récursive du calcul de la racine carrée

float racine(float A,float e,


float X){
Simulation A=2, X=1
float res; Res=racine(2, 1.5)
if(abs(X*X-A)<=e)            2,25 – 2 = 0,25 > 0,001
res = X; Res=racine(2, 1.416)
Res=racine(2, 1.414)
else          |(1,414)2 – 2| = 0,0006 < 0,001
res = racine(A,e,(X+A/X)/2);}
return (res);}
Exercice: trouver le Maximum de V avec une fonction récursive
Soit la fonction Max(a, b).
Ecrire une fonction récursive qui renvoi le maximum des valeurs d’un 
tableau V de dimension n. cette fonction aura pour argument les 
éléments du vecteur V et la dimension n « RecMax(V, n) » 
Cette fonction récursive doit renvoyer la valeur suivante:

Pour n=5 on doit renvoyer

Donc trouver le max des éléments d’un vecteur V de dimension N revient à 
trouver le Max des éléments d’un vecteur V de dimension N-1 et V(N-1)
int Max(int a, int b){
int res;
res = a;
if(b>res)
res=b;
return(res);}

int Fmax(int *T, int n){


int M, i;
if (n==1)
M=T[0];
else
if(n==2)
M=Max(T[0], T[1]);
else
M=Max(Fmax(T, n-1), T[n-1]);
return(M);}
Recherche du Max Méthode de 
diviser pour régner
Etape-1 : diviser le tableau en deux sous-tableaux. 

Etape-2: trouver récursivement le maximum dans chaque demi-tableau 
Max1 et Max2. Si la taille du demi-tableau est réduite à deux éléments, 
on appelle la fonction Max(a,b). 

Etape-3: retourner le maximum des deux maximums trouvés. 
0 1 2 3 4 5 6 7 8 9
5 6 9 8 -4 12 -13 1 2 7

Deb=0 =Max(v(1),v(0))=6
Fin = 2
(2-0=2)
Mid=2/2=1
Max1=Fmax(v, 0, 1)
Deb=0 Max2 = Fmax(v, 2, 2)
= Max(v(2),v(2))=9
Fin = 4 Max(6,9)=9
Deb=0 (4-0=4)
Fin = 9 Mid=4/2=2
(9-0=9) Max1=Fmax(v, 0, 2)
Mid=9/2=4,5 Max2 = Fmax(v, 3, 4)
Max1=Fmax(v, 0, 4) Max(v(4),v(3))=8
Max2 = Fmax(v, 5, 9) Max(9,8)=9

Max(12,9)=1 Deb=5 Deb=5


2 Fin = 9 Fin = 7
(9-5=4) (7-5=2)
= Max(v(5),v(6))=12
Mid=14/2=7 Mid=12/2=6
Max1=Fmax(v, 5, 7) Max1=Fmax(v, 5, 6)
Max2 = Fmax(v, 8, 9) Max2 = Fmax(v, 7, 7) = Max(v(7),v(7))=1

Max(12,7)=12 Max(12,1)=12

Max(v(8),v(9))=7
Récursivité croisée
Deux fonctions récursive qui s’appelle mutuellement
float U(int n, float A) float V(int n, float A)
{ {
float V(int, float); float z;
float z; if (n==0)
if (n==0) z=A;
z=1; else
else z=(U(n-1, A)+V(n-1, A))/2;
z=2/(1/U(n-1, A)+1/V(n-1, A)); return(z);
return(z); }
main(){
float A;
int n;
printf("A = ");
scanf("%f", &A);
n=20;
printf("la racine carre de %.2f est %.2f\n", U(n, A), V(n, A));
printf("\n");}
Algorithmes de tri
 Les tableaux permettent de stocker plusieurs éléments de 
même type au sein d'une seule entité,
 Trier  un  tableau  c'est  donc  ranger  les  éléments  d'un 
tableau en ordre croissant ou décroissant
 Il existe plusieurs méthodes de tri qui se différencient par 
leur  complexité  d'exécution  et  leur  complexité  de 
compréhension pour le programmeur.
 Nous exposons deux méthodes :
 le tri par sélection (minimum (maximum) successif )
 Le tri à bulles
 Le tri par insertion
Algorithmes de tri
Dans les deux premières méthodes de tri, on doit utiliser une 
procédure qui permet d'échanger (de permuter) la valeur de 
deux variables.

void permute(int *a, int *b)
{
    int k;
    k=*a;
    *a=*b;
    *b=k;
}
Tri par sélection
Tri par Min ou Max successif
on parcourt le tableau de gauche à droite, on cherche le plus 
petit  élément  puis  on  le  positionne  dans  l’indice  i  du 
tableau. On recommence la même opération pour le sous-
tableau de droite qui commence par l’indice i+1.

plus  généralement  :  Pour  trier  le  sous-tableau 


t[i..nbElements] il suffit de positionner  au rang i le plus 
petit élément de ce sous-tableau et de trier le sous-tableau 
t[i+1..nbElements]
• Tri par maximum successif

r=0 r=1 r=2 r=3 r=4 r=5


i=0;  12 14 11 3 34 10

i=1; 34 14 11 3 12 10

i=2; 34 14 12 3 11 10

i=3; 34 14 12 11 3 10

i=4; 34 14 12 11 10 3
• Tri par max successif
void permute(int *a, int *b)

int posmax(int *T, int n, int r)

void Tri(int *V, int n)
Le tri à bulles
Principe de la méthode :
 
Sélectionner le minimum du tableau en parcourant le tableau 
du début à la fin et en échangeant tout couple d'éléments 
consécutifs non ordonnés.
Le tri à bulles
Par exemple, pour trier [130, 156, 213, 230, 300] suivant un 
ordre décroissant,  on va avoir les boucles suivantes :
i=0;  130 156 213 230 300
k=0;   156 130 213 230 300
k=1;   156 213 130 230 300
k=2;   156 213 230 130 300
k=3;   156 213 230 300 130

i=1;  156 213 230 300 130

k=0;   213 156 230 300 130


k=1;   213 230 156 300 130
k=2;   213 230 300 156 130
Le tri à bulles
void permute(int *a, int *b)

void Tri(int *T, int n)
Le tri par insertion
Ce tri s’inspire d’un processus naturel utilisé dans le tri des cartes qu’un 
possédé dans sa main, le joueur prend chaque carte et l’insère à sa 
place en décalant les autres. 

void Tri_Insert(int *T, int n)
Le tri par insertion
Les algorithmes de Recherche
Recherche linéaire dans un ensemble non trié

 On  procède  par  une recherche  linéaire:  on  parcoure  le 


tableau et lorsque qu’on trouve le nombre recherché (t(i)=X) 
on renvoi l’indice correspondant.
 Si  on  parcourt  tous  le  tableau  sans  trouver  la  valeur 
recherchée on déclare que le nombre n’existe pas. 
Les algorithmes de Recherche
Recherche dans un ensemble non trié

Fonction Recherche (T(), X, Nb)
Var i, R : entier
i  0
Tant que (i<=Nb-1 ET T(i) <> X) Alors
    i  i+1
Fin tant que
Si (i = Nb) alors
   Ecrire (« le nombre est introuvable »)
Sinon
   Ecrire (« le nombre de trouve dans l’indice »)
   Renvoyer (i)
Fin
Les algorithmes de Recherche
Recherche linéaire dans un ensemble trié suivant un ordre
croissant

 On  procède  par  une recherche  linéaire:  on  parcourt  le 


tableau  et  tant  que  l’élément  du  tableau  est  inférieur  au 
nombre recherché (t(i) < X) on continu la recherche.
 Si  on  parcourt  tous  le  tableau  sans  trouver  la  valeur 
recherchée on déclare que le nombre n’existe pas. 
Les algorithmes de Recherche

Recherche dans un ensemble trié suivant un ordre croissant


Fonction Recherche (T(), X, Nb)
Var i, R : entier
i  0
Tant que (i<=Nb-1 ET T(i) < X) Alors
    i  i+1
Fin tant que
Si (i = Nb) alors
   Ecrire (« le nombre est introuvable »)
Sinon
   Ecrire (« le nombre de trouve dans l’indice »)
   Renvoyer (i)
Fin
Les algorithmes de Recherche
Recherche par Dichotomie

La recherche séquentielle demande plus de temps d’exécution.

L’algorithme de Dichotomie est basé sur le principe de « diviser pour 
résoudre ».  

On divise l’ensemble de recherche en deux sous-ensembles égaux. On 
détermine ensuite dans quel sous-ensemble doit se trouver la valeur 
recherchée. Puis on poursuit la recherche d’une manière récursive 
dans les sous-ensembles jusqu’à ce qu’on trouve la valeur recherché 
ou on arrive à un sous-intervalle où la borne inférieure coïncide avec 
la borne supérieure et donc on conclut que la valeur n’existe pas 
dans cette ensemble. 
Les algorithmes de Recherche
Recherche par Dichotomie (fonction récursive)

void Rech_Dico(int *T, int deb, int fin, int x) {


int i, mid, z;
if(deb>=fin)
printf("valeur introuvable");
else {
mid=(deb+fin)/2;
if(T[mid]==x)
printf("valeur trouvee a %d", mid);
else {
if(x<T[mid])
fin=mid;
else
deb=mid+1;
Rech_Dico(T, deb, fin, x); } }
}
Les algorithmes de Recherche
Recherche par Dichotomie (fonction itérrative)
void Rech_Iterra(int *T, int deb, int fin, int x) {
int i, n, mid;
fin=n;
mid=(deb+fin)/2;
while(T[mid]!=x && deb<fin) {
if(x<T[mid])
fin=mid;
else
deb=mid+1;
mid=(deb+fin)/2; }
if(T[mid]==x)
printf("la valeur est trouvee a i = %d", mid);
else
printf("la valeur non trouvable");
}
Utilisation de la dichotomie
résolution de f(x)=0
f est une fonction définie sur l’intervalle [a, b] et strictement 
monotone sur [a; b]. On cherche à résoudre numériquement 
l’équation f(x) = 0.
l’existante d’une racine sur [a, b] se traduit par le fait que 
f(a) et f(b) sont de signe contraires, c-a-d f(a)*f(b)<0, et 
que f est continue sur [a, b].
Si p est un réel sur [a, b], la racine x0 par rapport à p peut 
être testée par l’algo suivant:

Si f(a)*f(p)<=0 alors
Rechercher x0 dans [a,p]
Sinon
Rechercher x0 dans [p,b]
FinSi
Utilisation de la dichotomie
résolution de f(x)=0
Var X, N, P, Min, Max : réel
Lire(Min) P2 P3 P1
Min Min
Lire(Max)
Si (f(Max)*f(Min)>0) Alors
    Ecrire("pas de solution")
Sinon
f(Min)
     P=(Max+Min)/2;
     Ecrire(P)
     tant que (abs(f(P)) > 0.001) faire
         si (f(Min) * f(P)<=0) Alors
            Max  P f(P2)
         sinon P2 P3 P1

            Min  P f(P3) Min Max

         Fin Si f(P1)

       P=(Max+Min)/2; 
      Fin tant que f(Max)

     Ecrire(« la solution est:", P);
Fin Si
Fin
Chapitre – 2 Les chaines de caractère

 Dans un programme informatique, les chaînes de caractères servent à 
stocker les informations non numériques comme par exemple une liste 
de nom de personne ou des adresses.

 En langage C Il n'existe pas de type spécial chaîne ou string. Une
chaîne de caractères est traitée comme un tableau à une
dimension de caractères (vecteur de caractères).

 Pour marquer la fin de la chaine de caractère le symbole ‘\0’ doit être 
saisi et stocké dans la dernière case du tableau.
Chapitre – 2 Les chaines de caractère

Déclaration d’une chaîne

char <nom_chaine>[<dimension>]

Initialiser d’un tableau d’entier

int tab[5] = {12, 23, 5, 0, 123};

Initialiser d’un tableau de char

char T[7]={'b', 'o', 'n', 'j', 'o', 'u', 'r'};

Initialiser d’une chaine char

char T[8]={'b', 'o', 'n', 'j', 'o', 'u', 'r', '\0'};


Chapitre – 2 Les chaines de caractère

Initialiser d’une chaine char

Pour le cas spécial des tableaux de caractères, nous pouvons utiliser 
une initialisation plus confortable 

char T[8]="bonjour";

char CH[ ] = "bonjour";

Lors de l'initialisation par [], l'ordinateur réserve automatiquement 
le nombre d'octets nécessaires pour la chaîne, c.-à-d.: le 
nombre de caractères + 1 (ici: 8 octets). 
Chapitre – 2 Les chaines de caractère

Initialiser d’une chaine char

main()
{int i; main(){
CH[]="bonjour"; char CH[]="bonjour";
for(i=0; i<=7; i++) printf("%s", CH);}
printf("%c", CH[i]);
}

le code format %s permet d’afficher toute la chaine de caractère. 
Chapitre – 2 Les chaines de caractère
Initialiser d’une chaine char

Ci-dessous un programme C qui permet de visualiser la mémorisation 
d’une chaine de caractère :

# include <stdio.h>
main(){
char CH[8]="bonjour";
int i;
printf("\tCaractere | ASCII | Adresse\n");
printf("-----------------------------------\n");
for(i=0; i<8; i++)
printf("CH[%d] = %5c | %4d | %6x\n", i, CH[i], CH[i], &CH[i]);}
Chapitre – 2 Les chaines de caractère
Initialiser d’une chaine char

char A[ ] = "Bonjour !"; /* déclaration par un tableau */


char *B = "Bonjour !"; /* déclaration par un pointeur */

A est un tableau Les caractères de la chaîne peuvent être changés, 
mais le nom A va toujours pointer sur la même adresse en 
mémoire.
B est un pointeur pointe sur une chaîne de caractères constante 
stockée quelque part en mémoire. Elle peut être lue, copiée ou 
affichée, mais pas modifiée. Le pointeur peut être modifié et 
pointer sur autre chose. 
Chapitre – 2 Les chaines de caractère
Initialiser d’une chaine char
char *A = "Petite chaîne";
char *B = "Deuxième chaîne un peu plus longue";
A = B;

A et B pointent sur la même chaîne; la "Petite chaîne" est perdue:

char A[45] = "Petite chaîne";


char B[45] = "Deuxième chaîne un peu plus longue";
A = B; /* IMPOSSIBLE -> ERREUR !!! */
Chapitre – 2 Les chaines de caractère
Initialiser d’une chaine char
Donc dans le cas d’une initiation d’une chaine par un tableau on pourra 
modifier (réinitialiser) cette chaine. 
# include <stdio.h>
main(){
char CH[]= "bonjour", t='B';
*CH=t;
printf("%s\n", CH);}

Par contre cette dernière sera constante (non modifiable) dans le cas 
d’une initiation par pointeur.
# include <stdio.h>
main()
{ char t;
char *CH= "bonjour", t='B'; // Impossible: Erreur //
*CH=t;
printf("%s\n", CH);}
Chapitre – 2 Les chaines de caractère
Initialiser d’une chaine char

Dans les chaînes de caractères, nous pouvons utiliser toutes les 
séquences d'échappement définies comme caractères constants:

# include <stdio.h>
main(){
char CH[9]="bon\njour";
printf("%s", CH);}

Remarque
'c' est un caractère contant qui a une valeur numérique qui correspond 
au code ASCII

''c'' est un tableau de caractères qui contient deux caractères la lettre 
'c' et le caractère NULL: '\0'
Chapitre – 2 Les chaines de caractère

Saisie d’une chaîne de caractères

• Saisie dans un tableau statique

• Utilisation de scanf("%s", CH)

# include <stdio.h>
main() !!!!!!!! Utilisation facile mais avec
{ beaucoup de précaution
char CH[20];
scanf("%s", CH);
printf("%s\n", CH);
}
Chapitre – 2 Les chaines de caractère
Saisie d’une chaîne de caractères
• Saisie dans un tableau statique

Utilisation de scanf("%s", CH)

 cette fonction s'arrête si elle tombe au cours de sa lecture sur un 
espace, une tabulation ou une entrée. il sera impossible de récupérer 
toute la chaine de caractère. 
 cette fonction ne contrôle pas la taille de la mémoire initialement 
réservée pour le stockage de la chaine. Dépassement de la mémoire. 

# include <stdio.h>
main(){
char CH[20];
printf("donner votre nom et prenom ");
scanf("%s", CH);
printf("votre nom et prenom est : %s\n", CH);} 
Chapitre – 2 Les chaines de caractère
Saisie d’une chaîne de caractères
• Saisie dans un tableau statique

Utilisation de scanf("%c", CH+i)

main()
 Ici la saisie se fait caractère par caractère dans une boucle « while ».
{
 Tant que l’utilisateur n’a pas tapé « Return » (\n) la saisie des caractères 
continue.  char CH[20];
int p=0;
 Le caractère « Null » est stocké à la fin de la chaine pour marquer la fin 
printf("donner votre nom et prenom ");
de cette dernière.  
scanf("%c", CH+p);
 La récupération de la chaine sera complète même si on introduit un 
while(CH[p++]!='\n')
espace dans la chaine initiale. 
scanf("%c", CH+p);
CH[p]='\0';
printf("votre nom et prenom est : %s\n", CH);}
Chapitre – 2 Les chaines de caractère
Saisie d’une chaîne de caractères
Saisie dans un tableau dynamique

La réservation de la mémoire sera dynamique en utilisant les fonctions 
# include <stdio.h>
malloc() et realloc().
main(){
char *CH, c;
int p=0, i;
printf("donner votre nom et prenom ");
CH=(char*)malloc(sizeof(char));
scanf("%c", CH+p);
while(CH[p++]!='\n')
{
CH=(char*)realloc(CH,(p+1)*sizeof(char));
scanf("%c", CH+p);
}
CH[p]='\0';
printf("votre nom et prenom est : %s\n", CH);}
Chapitre – 2 Les chaines de caractère

• Parcourir une chaîne de caractères :


On peut utiliser un pointeur pour parcourir une chaine de caractère.

int main(void){ int main(void){ int main(void)


char *ptr; int i=0; {
char CH[] = "Bonjour"; char *ptr; char *ptr;
ptr=CH; // <=> char CH[] = "Bonjour"; char CH[] = "Bonjour";
ptr=&CH[0]; ptr=CH; // <=> ptr=CH;
while (*ptr!='\0') ptr=&CH[0]; printf("%s\n",ptr);}
printf("%c",*ptr++);} while (ptr[i]!='\0'){
printf("%c",ptr[i++]);}}
Chapitre – 2 Les chaines de caractère

• Manipulations de chaînes de caractères


Fonction de lecture getchar() et d’écriture putchar()

getchar() est une fonction sans paramètre qui « capte » la valeur du 
caractère lu à la position courante de l'entrée standard (le clavier) 
et le retourne. scanf(« %c », &x).

putchar()  écrit le caractère passé en argument sur la sortie standard 
(l'écran). printf(« %c », x)

#include <stdio.h>
int main(){
char c;
c = getchar();
 // le programme suspend son fonctionnement jusqu'à ce que l'utilisateur tape
 // au moins un caractère puis la touche <return>
putchar(c);}
Chapitre – 2 Les chaines de caractère
• Manipulations de chaînes de caractères
fonction de saisie d'une chaîne de caractères fgets()
C’est une fonction qui appartient au fichier « stdio.h ». Elle a  besoin de 
trois paramètres et revoie une chaine de caractère.

char * fgets ( char * CH, int num, FILE * strdin );


CH : de type pointeur vers un tableau de caractères.
num : taille est la taille en octets du tableau de caractères pointé par chaîne.
Stdin : flux d’entrée. Il pointe vers le fichier à partir duquel se fait la lecture.

Cette fonction lit les caractères stdin et les place dans la chaîne CH tant 
que le caractère lu est différent du caractère de saut de ligne ('\n') (ce 
caractère est copié en fin de chaîne). La fin de la chaîne de caractères 
est marquée par l'ajout d'un caractère nul (\0). 

Cette fonction retourne le pointeur chaîne CH en cas de succès, et un 
pointeur NULL en cas de fin de flux.
Chapitre – 2 Les chaines de caractère
• Manipulations de chaînes de caractères
Recopie d'une chaîne de caractères strcpy, strncpy

C’est une fonction qui appartient au fichier « string.h ». 

char * strcpy ( char * destination, char * source );

Copie la chaîne pointée par source vers la chaîne pointée par destination. 
Attention au débordements de mémoire

char * strncpy ( char * destination, char * source,  num );

Copie les num premiers caractères de source vers destination.
Chapitre – 2 Les chaines de caractère
• Manipulations de chaînes de caractères
Concaténation de chaînes strcat(), strncat()
C’est une fonction qui appartient au fichier « string.h ». 
 
char * strcat ( char * destination, const char * source );
 
Ajoute une copie de la chaîne source à la chaîne destination. Le caractère de fin de 
chaîne de destination est remplacé par le premier caractère de source, et un 
nouveau caractère de fin de chaîne est ajouté à la fin de la nouvelle chaîne 
résultante destination. 

char * strncat ( char * destination, char * source, size_t num );
 
Ajoute les num premiers caractères de source à destination, plus un caractère fin de 
chaîne. 
Chapitre – 2 Les chaines de caractère
• Manipulations de chaînes de caractères
Comparaison de chaînes strcmp(), strncmp()
C’est une fonction qui appartient au fichier « string.h ». 
 
int strcmp ( const char * str1, const char * str2 );

Compare les chaînes str1 et str2. 
Un zéro signifie que les deux chaînes sont égales 
Une valeur positive indique que le premier caractère différent a une plus 
grande valeur dans str1 que dans str2 
Une valeur négative indique l'inverse.

int strncmp ( const char * str1, const char * str2, size_t num );

Un zéro signifie que les num premiers caractères des deux chaînes sont égaux. 
Une valeur positive indique que le premier caractère différent a une plus 
grande valeur dans str1 que dans str2 
Une valeur négative indique l'inverse.
Chapitre – 2 Les chaines de caractère
• Manipulations de chaînes de caractères
Recherche d'une chaîne dans une autre strstr()

C’est une fonction qui appartient au fichier « string.h ». 
 
char * strstr ( const char * str1, const char * str2); 
 
Cette fonction retourne un pointeur sur la première occurrence de la chaîne 
str2 dans la chaine str1, ou un pointeur NULL si str2 n'est pas une partie de str1. 
La comparaison ne porte pas sur le caractère fin de chaîne.
Chapitre – 2 Les chaines de caractère

• Tableau de chaine de caractère


main(){
  char **T, c;
  int i, k, n;
  n=0;
  printf("saisir le nombre d'enregitrement");
  scanf("%d", &n);
  getchar(); 
T=(char**)malloc(n*sizeof(char));
  for (i=0; i<n; i++)
  {
      k=0;
      printf("donner la chaine %d ", i);
      T[i]=(char*)malloc(sizeof(char));
      scanf("%c",T[i]+k);
      while(*(T[i]+k)!='\n')
      {
          k++;
         *(T+i)=(char*)realloc(*(T+i), (k+1)*sizeof(char));
           scanf("%c",T[i]+k);
      }
      T[i][k]='\0';
  }
 for (i=0; i<n; i++)
  printf("%s\n", T[i]);
Les Structures
besoin d’un mécanisme permettant de grouper un certain nombre de 
variables de types différents au sein d’une même entité. 

Champs ou membre ou élément

Référence Désignation Prix Stock

Une structure un ensemble d’éléments de types différents repérés par 


un nom. Les éléments sont appelés des champs ou membre d’une 
structure. 
Déclarer une structure c’est créer un certain type de variable qui
va nous permettre de sélectionner plusieurs d’autre variables
conventionnel de différents types
Structure test
Type1 V1 Type3 V3

P1
P2

Type2 V2

struct test{
Type1 V1
Type2 V2
Type3 V3};
typedef struct test str;
Str P1, P2;
Les Structures
Déclaration de structure
Elle se fait en deux étapes :
Définir le type structure avec les membres
struct personne
{ On préfère utiliser l’instruction « deftype »
char nom[20];
char prenom[20]; Typedef struct personne str
int no_employe;
};

Déclarer des variables de ce type

struct personne p1, p2;


Ou bien

str p1, p2;


Les Structures
struct Produit
char nom1[20]; {
char nom2[20]; char nom[20];
float Prix1; float Prix;
float Prix2; int Stock;
int Stock1; };
int Stock2; Deftype struct Produit Prod
Prod p1, p2;
Nom1[9] Produit1
Nom2[9] Produit2 p1
Prix1 25,50
Prix2 21,20
p2
Stock1 500
Stock2 100
Les Structures
Initiation d’une structure et
Accès aux membres de structure avec l’opérateur (.)
struct personne
{
char nom[20];
char prenom[20];
int no_employe;
};
struct personne p1={"ALAOUI", "Ahmed", 23}, p2;

main()
{
printf("%s ", p1.nom);
printf("%s ", p1.prenom);
printf("%d", p1.no_employe);
}
Les Structures
Saisie des membres d’une structure

typedef struct personne str;


La saisie des champs d’une structure se fait avec les méthode déjà vu de saisie 
struct personne{
des variables classiques.
char nom[20];
Données simple (int, float, char, ….);
Tables de donnée; char prenom[20];
int no_employe;};
main(){
//saisie des champs
str p1;
gets(p1.nom);
gets(p1.prenom);
scanf("%d", &p1.no_employe);
//Affichage des données
printf("%s ", p1.nom);
printf("%s ", p1.prenom);
printf("%d", p1.no_employe);
}
Les Structures
Affectation de structures

On peut affecter une structure à une variable structure de même type, 
grâce à l’opérateur d’affectation :

typedef struct personne str;


struct personne{
char nom[20];
char prenom[20];
int no_employe;};

str p1, p2;


……
p2=p1;
Les Structures
Pointeurs vers une structure

On peut déclarer un pointeur de type structure de la manière suivante :

typedef struct personne str;


struct personne{
char nom[20];
char prenom[20];
int no_employe;};

str p1, *ptr;


……
ptr = &p1;
Les Structures
Pointeurs vers une structure

Si nous voulons écrire une référence à un membre de la structure 
pointée par ptr on doit écrire :

(*ptr).nom ou ptr  nom

l’indirection (*) a une priorité inférieure à celle de la sélection (.).


Les Structures
Structure et les pointeurs
struc test struc test struc test
{ { {
   type1 champ1    type1 champ1    type1 champ1
   type2 champ2    type2 champ2    type2 champ2
   ….    struc test *P    type3  *P
}   ….    ….
struc test var1, var2, *P } }
struc test var1, var2 struc test var1, var2
Pointeurs
vers une un des un des
structure membres est membres est
Pointeurs vers Pointeurs vers
une une
structure du Variable de
même type type different
Les Structures
Les Tableaux de structure
Dés que l’on a besoin de stocker plusieurs valeurs d’une variable de type 
structure on déclare un tableau de structure 

struct personne
{
char nom[20];
char prenom[20];
int no_employe;
};
struct personne tab_personne[100];

tab_ensemble[i].nom représente le nom de la personne de rang i du 
tableau « tab_personne »

tab_ensemble [i].nom[k] représente le kème caractère du nom de la 
ième personne. 
Les Structures
Les Tableaux de structure
Excrire un prog C qui permet de saisir et de stocker le nom, le prénom 
ainsi que le code des clients dans une strructure « client ».  
struct client
{
char *nom;
char *prenom;
int code;
};
typedef struct client client;
main()
{
int i, n;
client Tabclient[20], *P;
printf("donner le nombre de client a saisir ");
scanf("%d", &n);
getchar();
for(i=0; i<n; i++)
{
printf("saisir le client %d\n", i+1);
Tabclient[i].nom = saisirChaine();
Tabclient[i].prenom=saisirChaine();
scanf("%d", &Tabclient[i].code);
getchar();
}
Les Structures
Les Tableaux de structure
Allocation dynamique d’un tableau de structure

struct NomStruct
{
…….
};
typedef NomStruct Struct;
main()
{
int n ;
Struct *Tab ;
scanf("%d », &n) ;

Tab=(Struct*)malloc(n*sizeof(Struct)) ; 
…….
}
Les Fonctions d’entrées-Sorties

Dans un programme C on stock dans des adresses mémoire (mémoire centrale) 
des valeurs qui proviennent d’une flot de données (stream):
- Saisie à partir du clavier scanf()
- Lecture à partir d’un fichier fscanf()

Dans un programme C on récupère les résultats d’un traitement par: 
- Une affichage sur Ecran (les données sont dans la RAM. Perdue après fermeture 
du programme. printf()
- Une Ecriture dans un fichier fprintf() (les données sont le HD)
Les Fonctions d’entrées-Sorties
fputc()
fputs()
fprintf()

Ecriture dans un fichier

Programme C Fichier
Main Texte
{ 2334
……… 12/12/2015
} HD
RAM
Lecture à partir d’un fichier

fgetc()
fgets()
fscanf()
Les Fonctions d’entrées-Sorties

Pour manipuler un fichier, un programme a besoin d'un certain nombre 
d'informations : 

l'adresse de l'endroit de la mémoire-tampon où se trouve le fichier
le mode d'accès au fichier (lecture ou écriture) ... 

Ces informations sont rassemblées dans une structure dont le type, FILE*, définie 


dans stdio.h. 
Un objet de type FILE * est appelé flot de données (en anglais, stream).
Les Fonctions d’entrées-Sorties
Ouverture et fermeture de fichiers

FILE *fopen (char *nom-de-fichier , char *mode)
Paramètres

if(fopen(nom-de-fichier , mode)==NULL)
nom-de-fichier : le nom du fichier auquel on veut accéder.
printf(‘’Ouverture impossible’’) ;
Mode : est une chaîne de caractères qui spécifie le mode d'accès au fichier. Les 
else
modes d'accès diffèrent suivant le type de fichier considéré. On distingue : les 
{
fichiers textes, les fichiers binaires (caractères de contrôle sont interprétés ou pas.
//…Utilisation du contenu du fichier…//
Valeur rendue
}
Si l’ouverture a réussi, la valeur retournée permet de repérer le fichier
Si l’ouverture est impossible, fopen rend la valeur NULL.
Les Fonctions d’entrées-Sorties
Ouverture et fermeture de fichiers

"r" ouverture d’un fichier texte en lecture.
"w"  ouverture d’un fichier texte en écriture.
"a"  ouverture d’un fichier texte en écriture à la fin.
"rb" ouverture d’un fichier binaire en lecture.
"wb" ouverture d’un fichier binaire en écriture.
"ab"  ouverture d’un fichier binaire en écriture à la fin.
"r+"  ouverture d’un fichier texte en lecture/écriture.
"w+"  ouverture d’un fichier texte en lecture/écriture.
"a+"  ouverture d’un fichier texte en lecture/écriture à la fin.
"rb+  ouverture d’un fichier binaire en lecture/écriture.
"wb+  ouverture d’un fichier binaire en lecture/écriture.
Les Fonctions d’entrées-Sorties
Ouverture et fermeture de fichiers

int fclose ( FILE * stream );

Paramètres
stream est le flot de type FILE* retourné par la fonction fopen() correspondant.

Valeur rendue
La fonction fclose() retourne un entier qui vaut zéro si l'opération s'est déroulée 
normalement (et une valeur non nulle en cas d'erreur).

FILE *fi;
fi=fopen(nomfichier, mode)
fclose(f);
Lecture et écriture par caractère sur fichier

Lecture par caractère sur fichier

int fgetc (FILE * stream)   

Paramètres
#include <stdio.h>
Stream ou flot-de-données : est de type pointeur vers FILE. Il pointe vers le fichier à 
partir duquel se fait la lecture.
int c;
Valeur rendue FILE *fi;
while ((c = fgetc(fi)) != EOF)
rend le caractère lu. 
{
rend la valeur EOF S’il y a erreur d’entrée-sortie, ou rencontre de fin de fichier. 
... /* utilisation de c */
}
Lecture et écriture par caractère sur fichier
Ecriture par caractère sur fichier

int fputc (int carac , FILE *flot-de-données)  

Paramètres
FILE *fo;
– carac est de type int, c’est le caractère à écrire.
char c;
– flot-de-données est de type pointeur vers FILE. Il pointe vers le fichier sur lequel se 
fait l’écriture.. fo=fopen("testecrire", "w");
do
Valeur rendue {c=getchar();
La fonction fputc() rend le caractère écrit si l’écriture s’est faite sans erreur, ou EOF 
fputc(c, fo);}
en cas d’erreur.
while(c!='\n');

C:\Users\G6\Documents\Données\Cours FST\Algorithmique C\MIP S3\CoursAlgoC
Lecture et écriture par lignes sur fichier
Lecture par lignes sur fichier

char *fgets(char *chaine, int max, FILE *stream) 
lit max -#include <stdio.h>
1 caractère  s  d’une  chaînes  sur  le  fichier les  stocke  dans  la  chaîne 
#define LONG ...
« chaine ». elle s'arrête dès qu'elle rencontre un caractère de passage à la ligne et 
place unchar
\0 à ligne[LONG];
la fin de la chaîne.  Lorsqu'elle  rencontre  la  fin  de  fichier,  elle 
retourne la chaîne NULL.
FILE *fi;
while (fgets(ligne,LONG,fi) != NULL) //stop sur fin
Paramètres
de fichier ou erreur//
– chaîne : est de type pointeur vers char et doit pointer vers un tableau de caractères.
{
– taille : est la taille en octets du tableau de caractères pointé par chaîne.
... // utilisation de ligne //
– flot-de-données : est de type pointeur vers FILE. Il pointe vers le fichier à partir 
}
duquel se fait la lecture.

Valeur rendue
La fonction fgets rend le pointeur chaîne en cas de lecture sans erreur, ou NULL 
dans le cas de fin de fichier ou d’erreur.
Lecture et écriture par lignes sur fichier

Écriture par chaîne : fputs()

int fputs (char *chaîne , FILE *flot-de-données)
Fputs()  écrit  sur  le  fichier  le  contenu  du  tableau  dont  la  fin  est  indiquée  par  un 
caractère null. C-a-d écrire une ligne ou une chaîne quelconque 

Paramètres
FILE *fo;
– chaîne est de type pointeur vers char. Pointe vers un tableau de caractères contenant 
char c, T[20];
une chaîne se terminant par un null.
fo=fopen("testecrire", "w");
– flot-de-données est de type pointeur vers FILE. Il pointe vers le fichier sur lequel se 
fait l’écriture.
gets(T);
Valeur rendue
fputs(T, fo);
La fonction fputs rend une valeur non négative si l’écriture se passe sans erreur, et 
EOF en cas d’erreur.
Lecture et Ecriture formatées sur fichiers
Écriture formatée : fprintf()
int fprintf (FILE *stream ,  chaineformat , param1 , param2 , ... , paramn )

Paramètres
– flot-de-données : est de type pointeur vers FILE. Il pointe vers le fichier sur lequel 
se fait l’écriture.
–  chaineformat :  Elle  contient  des  caractères  ordinaires  qui  doivent  être  copiés  tels 
for(i=0; i<n; i++)
quels, et des séquences d’échappement (introduites par le caractère %), décrivant la 
{
manière dont doivent être écrits les paramètres param1, param2,... paramn.
printf("%d\n",fprintf(fo, "%s %s %d\n", Tabclient[i].nom,
– param : est une expression délivrant une valeur à écrire.
Tabclient[i].prenom, Tabclient[i].code));
} rendue
Valeur
La fonction fprintf retourne le nombre de caractères écrits, ou une valeur négative s’il 
y a eu une erreur d’entrée-sortie.
Lecture et Ecriture formatées sur fichiers
Lecture formatée : fscanf()
fscanf (FILE *stream , chaineformat , param1 , param2 , ... , paramn )

Paramètres
FILE *fo;
– flot-de-données : est de type pointeur vers FILE. Il pointe vers le fichier à partir 
duquel se fait la lecture.
int i=0, n=4;
– chaineformat : est une chaîne de caractères qui spécifie la forme de l’entrée 
client Tabclient[20];
admissible dans flot-de-données.
fo=fopen("testecrire",
– les parami : "r");
sont des pointeurs. Ils pointent des variables dans lesquelles fscanf 
while(fscanf(fo, "%s %s %d\n", Tabclient[i].nom, Tabclient[i].prenom,
dépose les valeurs lues dans flot-de-données, après les avoir converties en binaire.
&Tabclient[i].code)!=EOF)
i++; rendue
Valeur
fscanf retourne le nombre de param_i affectés. S’il y a eu rencontre de fin de 
fichier ou erreur d’entrée-sortie avant toute affectation à un param_i, fscanf retourne 
EOF.
Lecture et Ecriture formatées sur une chaine
Ecriture formatée : sprintf()
main()
int sprintf (char *chaine , format , param1 , param2 , ... , paramn )
{
char CH[20], T[20], x;
La fonction sprintf() réalise le même traitement que la fonction fprintf(), avec 
int y;
la différence que les caractères émis par sprintf() ne sont pas écrits dans 
printf("saisir
le  tableau  de  un charUn 
caractères  chaîne.  : ");
null  est  écrit  dans  chaîne  en  fin  de 
traitement. scanf("%c", &x);
getchar();
printf("saisir une chaine : ");
gets(T);
printf("saisir entier : ");
scanf("%d", &y);
printf("la chaine formatee est : ");
sprintf(CH, "%c/%d/%s", x, y, T);
puts(CH);
}
Lecture et Ecriture formatées sur une chaine
Lecture formatée : sscanf()
sscanf (char *chaine , chaineformat , param1 , param2 , ... , paramn )

La fonction sscanf réalise le même traitement que la fonction fscanf, avec la 
différence que les caractères lus par sscanf ne sont pas lus depuis un 
fichier, mais du tableau de caractères chaîne. 

Valeur renvoyée
Scanf()  retourne  le  nombre  de  param-i  affectés  c-a-d  le  nombre  de 
paramètre qui sont conforme à si la chaine format. 
Lecture et Ecriture formatées sur une chaine
Les directives pour les lectures formatées
Caractères blancs :il s’agit des six caractères suivants : espace, tab, line feed, new 
line, vertical tab et form feed. Ce sont des caractères très utilisés dans les lectures 
formatées.

Les Directives (format) : 
une suite de caractères blancs qui est un modèle d’un nombre quelconque de 
caractères blancs.  

une suite de caractères ordinaires qui est un modèle pour elle-même. Exemple : 


la chaîne « -/- » est un modèle de la seule chaîne « -/- ».

des séquences d’échappement  introduites  par  le  caractère  %.    Exemple 


« %d\n »
Lecture et Ecriture formatées sur une chaine
Les directives pour les lectures formatées

main()
{
FILE *fi;
char x[20], y[20], *z="ABCD xyz";
sscanf(z, "%s %s", x,y); // ou sscanf(z, "%s%s", x,y);
printf("%s\n", x);
printf("%s", y);
}
Lecture et Ecriture formatées sur une clavier
Affichage formatée sur Ecran : printf()
int printf (chaineformat , param1 , param2 , ... , paramn )

Lecture formatée à partir du clavier scanf()

Int scanf (chaineformat , param1 , param2 , ... , paramn )

Valeur renvoyée
Scanf() retourne le nombre de param-i affectés c-a-d le nombre de 
paramètre qui sont conforme avec la chaine format. 
On dira qu’une chaîne format est conforme à un modèle quand elle 
appartient à l’ensemble des chaînes décrites par le modèle. Exemple : 
123 est conforme au modèle %d.

Sprintf() retourne le nombre de caractère écrit.
Les constantes nommées
les énumérations
• Les #define
On peut définir une constante nommée avec l’instruction #define.  
Si par exemple on veut  remplacer dans toute la suite du programme, toute 
nouvelle occurrence de Pi par 3.14159 on peut écrire :
 
#define PI 3.14159

• Les
énumérations
On peut aussi définir des constantes nommées de la manière suivante :

enum { liste-d’identificateurs }

liste-d’identificateurs : des constantes de type « int » 
 
Les constantes nommées
les énumérations
Les #define
On peut définir une constante nommée avec l’instruction #define.  
Si par exemple on veut  remplacer dans toute la suite du programme, toute 
nouvelle occurrence de Pi par 3.14159 on peut écrire :
 
#define PI 3.14159

Les énumérations
On peut aussi définir des constantes nommées de la manière suivante :

enum { liste-d’identificateurs }

liste-d’identificateurs : des constantes de type « int » 
 
Les constantes nommées
les énumérations
Déclaration de variable de type énumérations

enum test {a=2, b=4, c=6};


main()
{
enum test x1, x2, x3;
int y;
x1=a;
x2=b;
x3=c;
y=x1+x2+x3;
printf("y= %d", y);}
Les Unions
Il est parfois nécessaire de manipuler des variables auxquelles on désire 
affecter des valeurs de type différents. 

union nombre
{
int i;
float f;
}

union nombre N;
N . a = 10;
N . F = 3.14;
Complexité
Comment évaluer les performances d'un algorithme ?

 différents algorithmes ont des couts différents en termes 
de temps d'exécution (nombre d'opérations effectuées par 
l'algorithme), taille mémoire (taille nécessaire pour stocker 
les différentes structures de données pour l'exécution).

 Ces deux concepts sont appelés la complexité en temps


et en espace de l'algorithme.
Complexité
 La  complexité  algorithmique  permet  de  mesurer  les 
performances  d'un  algorithme  et  de  le  comparer  avec 
d'autres  algorithmes  réalisant  les  mêmes 
fonctionnalités.

 La complexité algorithmique est un concept fondamental 
pour tout programmeur, elle permet de déterminer si un 
algorithme  a  et  meilleur  qu’un algorithme  b  et  s’il  est 
optimal ou bien il ne doit pas être utilisé 
Le temps d'exécution d'un programme dépend :
1. du nombre de données,
2. de la taille du code,
3. du type d'ordinateur utilisé (processeur, mémoire),
4. de la complexité en temps de l'algorithme.

 Soit n la taille des données du problème et T(n) le temps 
d'exécution de l'algorithme. On distingue :
o Le temps du plus mauvais cas Tmax(n) qui correspond 
au temps maximum pris par l'algorithme pour un 
problème de taille n
o Comportement de T(n) pour un n est grand.
Règles générales :

1. le  temps  d'exécution TE  d'une affectation,  d’une 


incrémentation,  d’une opération élémentaire ou  d'un test  est 
considéré comme constant c.
2. Le  temps  d'une séquence  d'instructions est  la  somme  des TE 
des instructions qui la composent.
3. le temps d'un branchement conditionnel est égal au TE du test 
plus  le max des deux TE correspondant aux deux alternatives 
(dans le cas d'un temps max).
4. Le  temps d'une  boucle est  égal  au  coût  du test de sortie de 
boucle plus le corps de la boucle.
Exemple-1: Calcul d'une somme
{début}
R <-- 0 aff : temps d’affectation
i <-- 1 test : temps du test logique
TantQue i <= n Faire som : tems de la somme
• R <-- R+T[i] inc : temps
• i <-- i+1 d’incrémentation
FinTantQue
{fin}
L’algorithme est donc asymptotiquement linéaire en n.
Notion de landau O(…)
Définition

Soient f et g deux fonctions dans IR+*
Exemple-2: Calcul d'une somme
R <-- 0
i <-- 1 aff : affectation
TantQue i <= N Faire test : test
• R <-- R+T[i] som : somme
•    Si R>1000  inc : incrémentation
Alors mult : multiplication
•        R<-- 2*R
•    FinSi
• i <-- i+1
FinTantQue
Exemple-3 : calcul du factorielle (fonction récursive)

Fonction factorielle(n :naturel ) : naturel


Début
• Si n  0 alors
•     res  1 test: temps test
mult: multiplication 
• Sinon
•      res  n*factorielle(n-1)
• Finsi
• Renvoyer (res)
Fin

Dans le cas d’un traitement récursif les deux branchements vont être 
exécutés 
T(n) = test + aff + mult + T(n-1)

T(n) = (n+1)*test+ n*aff + n*mult = (test + aff + mult)*n + test 

Complexité linéaire O(n)
Exemple-4 (deux boucles imbriquées).
B<--0
aff: affectation
i <--1 som: somme
Pour i <-- 1 à n Faire test: test
       B<--B+2 mult: multiplication
Pour j <-- 1 à m Faire inc: incrémentation
T[i,j] <-- (1+T[i,j])*B
Suivant j
Suivant i

Cette algorithme à une complexité O(n2). 
Exemple-5 algorithme de Recherche du Max
Var : X, i, Max : entiers
Ecrire(« donner la valeur », 0)
Lire X c1:affectation
Max  X c2: incrémentation
i  1 c3: test
Tant que (X <> -1) faire
      si(X > Max) alors
           Max  X
       FinSi
 Ecrire(« donner la valeur », i)
 lire X
 ii+1 La complexité est en O(n)
 Fin tant que
Ecrire(‘’Max=‘’, Max)
Exemple-7 Fonction Echange

1. Fonction échanger (E/S a, b : Entier)
2. Déclaration T : Entier
3. Début
4.    T a
5.    a  b
6.    b  T
7. fin

T(n) = 3*aff                    (aff : affectation)

Complexité constante en O(1)
Algorithmes de recherche linéaire
Fonction Recherche (T(), X, Nb)
Pire des cas, élément 
Var i, R : entier
cherché absent du 
i  0
tableau
Tant que (i<=Nb-1 ET T(i) <> X) Alors
On va effectuer n tests: 
    i  i+1
T(n)=n*C
Fin tant que
complexité linéaire : O(n)
Si (i = Nb) alors
   Ecrire (« le nombre est introuvable ») Le temps d’exécution est 
Sinon proportionnel aux 
   Ecrire (« le nombre de trouve dans l’indice ») nombres de données.
   Renvoyer (i) Naïf il existe un 
Fin algorithme plus 
efficace 
Fonction Recherchedico(T() : entier, Nb :  T(n) = 3*aff + test +T(n/2) 
entier, X : entier): entier T(n) = C+T(n/2)
Var m : entier On pose n=2k   log(n)=k*log(2)
Min  0; T(2k) = C+T(2k-1)
Max  Nb-1; T(2k) = C+C+T(2k-2)
m  (Max+Min)/2; T(2k) = C+C+C+T(2k-3)
Tant que (T(m) <> X) faire T(2k) = C+C+C+…..+C+T(2k-k)
    Si (T(m) > X) Alors T(2k) = k*C+T(1)
       Max  m-1 T(n) = C*log(n)/log(2)+T(1)
   Sinon T(n) ~ C’*log(n)
      Min  m+1  
    Fin Si La complexité de l’algorithme est 
P=(Max+Min)/2;  logarithmique
Fin tant que La complexité est en O(log(n))
Renvoyer (m);
Les  algorithmes  usuels  peuvent  être  classés  en  un  certain  nombre  de  grandes 
classes de complexité. 

Les algorithmes sous-linéaires, dont la complexité est en général en O(logn). sont 
considérés comme les plus rapides. C'est le cas de la recherche d'un élément dans 
un ensemble ordonné fini de cardinal n.

Les  algorithmes  linéaires  en  complexité O(n)  ou  en O(nlogn)  sont  considérés 


comme rapides, comme l'évaluation de la valeur d'une expression composée de n 
symboles  ou  les  algorithmes  optimaux  de  tri.

Plus lents sont les algorithmes de complexité située entre O(n2) et O(n3), c'est le 
cas de la multiplication des matrices et du parcours dans les graphes.

Au delà, les algorithmes polynomiaux en O(nk) pour k > 3 sont considérés comme 
lents, sans parler des algorithmes exponentiels (dont la complexité est supérieure à 
tout  polynôme  en n)  que  l'on  s'accorde  à  dire  impraticables  dès  que  la  taille  des 
données est supérieure à quelques dizaines d'unités.
Ordre de grandeur du temps nécessaire à l'exécution
d'un algorithme d'un type de complexité
Conclusion
Qualités d'un algorithme :

1. Maintenable (facile à comprendre, coder, déboguer),
2. Rapide

Conseils :
1.  Privilégier  le  point  2  sur  le  point  1  uniquement  si  on 
gagne en complexité.
2. «ce que fait» l'algorithme doit se lire lors d'une lecture 
rapide : Une idée par ligne.
3. Faire également attention à la précision, la stabilité et la 
sécurité.
La rapidité d'un algorithme est un élément essentiel  pour 
définir les qualités de celui-ci.
Méthodologie
Comment trouver un algorithme?

Prenez un exemple 

tentez de voir intuitivement comment résoudre le problème.
 
Tentez alors de généraliser ces opérations pour obtenir les
principes généraux de votre algorithme. 

traduisez ces principes en pseudo-code.

Si besoin, décomposez le problème en sous problèmes que vous 
traitez indépendamment,

Vous aimerez peut-être aussi