Algorithme Pro Chap2
Algorithme Pro Chap2
Algorithme Pro Chap2
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
……
……
……
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 :
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>
#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 »
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;}
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.
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
-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
Différents types des constantes peuvent être définis en ajoutant des suffixes.
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>
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
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 :
%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
"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.
L’alignement de ces données dans une mémoire de 64 bits est la
suivante :
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
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
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 TAT1TB
T1
Vrai
Si Cond 2
Faux TAT2TB
T2
Vrai
Si Cond n
Faux TATnTB
Tn
Aucune Cond
TATn+1TB
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 :
Vrai
Si Cn
.
.
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
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)
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
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 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 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
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
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).
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
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+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.
Généralement le nom d’une fonction doit être explicite:
Maximum()
Minimum()
Syntaxe: Exemple
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.
Par contre elles admettent des paramètres d’entrés, de sorties ou
d’entrés/sorties:
Syntaxe: Exemple
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)
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));}
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
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
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);}
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,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.
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
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é
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
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)
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
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
char <nom_chaine>[<dimension>]
Pour le cas spécial des tableaux de caractères, nous pouvons utiliser
une initialisation plus confortable
char T[8]="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
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
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:
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
# 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
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
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
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.
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
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
main()
{
printf("%s ", p1.nom);
printf("%s ", p1.prenom);
printf("%d", p1.no_employe);
}
Les Structures
Saisie des membres d’une structure
On peut affecter une structure à une variable structure de même type,
grâce à l’opérateur d’affectation :
On peut déclarer un pointeur de type structure de la manière suivante :
Si nous voulons écrire une référence à un membre de la structure
pointée par ptr on doit écrire :
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) ...
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
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
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.
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 )
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
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).
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 :
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)
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
ii+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.
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,