Chapitre 5
Le contrôle des programmes.

5.0. Introduction 

Etude des éléments du langage algorithmique / C permettant l'enchaînement et le contrôle d'actions élémentaires formant des processus complexes

5.1. La séquence
 
				instruction1;
                                    ...................
				instructionp;

est la structure de base .
La fin d'une instruction déclenche l'exécution de la suivante.

5.2. Déclarations et définitions en langage C

Une déclaration est une instruction qui donne des indications de typages au compilateur.

Une définition est une déclaration qui précise l'espace mémoire que doit réserver le compilateur pour contenir l'objet déclaré.

// Exemple de déclaration qui n'est pas une définition :

		void afficher();

// Exemples de définitions :
		int x;
		float y=5.3;
		char c='a', lettre;

5.1.2. Les expressions et les instructions en C

-	Une expression est une "phrase grammaticalement correcte" du langage.

-	Une instruction est une instruction qui se termine par ;

// Exemples d'expressions

 y=x+3; 
x++;
sont des instructions.

5.2.3 L'instruction nulle.

C'est une instruction qui ne réalise rien et qui est notée:
				;

5.2.3. Les instructions composées (notion de bloc)

Un bloc est un ensemble inséparable d'actions qui s'enchaînent séquentiellement.

Notation algorithmique
$n°
action1
action2
action3
action4
n°$

En langage C :

groupes d'instructions contenues entre { et }.

{   // début du bloc
instruction1;
instruction2;
instruction3;
instruction4;
// fin du bloc
}

// Exemple :
                    {
			 int i=20;
			int j=2*i;
			int k=i+j;
			cout<<k;
                   }

5.2. Prise de décision.

Il s'agit de sélectionner sur deux alternatives (sélection binaire) ou plusieurs alternatives possibles.

5.2.1. Sélections binaires
 
5.2.1.1. Première forme en notation algorithmique

SI condition ALORS 
$n°1
bloc d'action n°1
n°1$

Si la condition est vraie alors le bloc d'action n°1 est exécuté.

5.2.1.2. Deuxiéme forme en notation algorithmique

SI condition ALORS 
$n°1
bloc d'action n°1
n°1$

SINON

$n°2
bloc d'action n°2
n°2$

Si la condition est vraie alors le bloc d'action n°1 est exécuté, sinon c'est le bloc n°2 qui le sera.

ATTENTION
En langage C, la condition est évaluée à partir d'une expression (expression_entiere) qui sera calculée et dont la valeur est un entier.
Si la valeur retournée par (expression_entiere) est 0, la condition est considérée comme fausse; dans les autres cas, elle est considérée comme vraie.

5.2.1.1.Bis Première forme en notation C

if  (expression_entiere) {
instruction1;
….
instruction n;
}

5.2.1.2. Bis Deuxiéme forme en notation C

if  (expression_entiere) {
instruction11;
….
instruction 1n;
}
else
{
instruction21;
….
instruction 2m;
}

Remarques 
Lorsque les blocs sont réduits à une seule instruction, on peut écrire :
if (expression_entière) instruction;

Pour la deuxième forme :

if (expression_entière) instruction1;
else instruction2;
/ * Exemple :
------------------
maximum de deux nombres a et b */

float a,b,c;
//… après avoir donné des valeurs aux variables a et b….

 if (a<b) c=b;
	else
     c=a;

5.2.2. L'expression conditionnelle du langage C.

En C, l'instruction if autorise le choix entre deux valeurs.

C possède un opérateur ternaire ? qui permet d'effectuer un choix entre deux instructions

Syntaxe

(expression-entiere) ? expression-si-vrai : expression-si-faux

/ * Exemple Bis :
------------------
maximum de deux nombres a et b */

float a,b,c;
//… après avoir donné des valeurs aux variables a et b….

c= (a<b) ? b : a;

5.2.3. La selection multiple.

Il s'agit de faire le choix entre plusieurs blocs possibles, en fonction de la valeur d'une expression.

5.2.3.1. Notation générale algorithmique 

CAS expression VAUT
$n°
valeur1
$n°1
bloc action1
n°1$
valeur2
$n°2
bloc action2
n°1$
…
valeurp
$n°p
bloc actionp
n°p$
AUTRE
	$n°q
bloc actionq
n°q$

Si expression a la valeur valeuri, c'est le bloc n°i
qui est exécuté à l'exclusion de tout autre.

Dans le cas ou la valeur calculée par expression_valeur ne correspond pas avec valeur1, valeur2 ou valeurp, c'est le bloc n°q faisant partie dans la rubrique AUTRE qui est exécuté.

La rubrique AUTRE est optionnelle.

ATTENTION :
valeur1, valeur2 ,valeurp doivent être des valeurs distinctes deux à deux.

5.2.3.2. Selection multiple en C 

ATTENTION
En C, les valeurs a selectionnées doivent être des entiers.
L'expression doit obligatoirement retourner un entier.

A ) Forme 1 de la selection de cas en C.

Attention: 
Le selecteur doit être une expression retournant une valeur entière.
A la différence du cas général algoritmique,
si un cas a été selectionné, tous les autres qui suivent seront pris (sauf default)

switch (expression_entiere)
{ 
case constante_entiere1 : 
	suite_d'instructions1;

case constante_entiere2:
	suite _d'instructions2;
..............................................
case constante_entieren
	suite _d'instructionsn;

default                // optionnel
	suite_d'instructions_autres; // option

#include <stdio.h>
// test de selections multiples
void main() {
 int i;
 printf( "Entrer un entier compris entre 1 et 3 :");
scanf("%d",&i);
switch (i) { 
case 1 : printf('L');
case 2 : printf('O');
case 3 : printf('G');
default :
printf(" fin  !"; 
              }   }

}

B ) Forme 2 de la selection de cas en C.

Cette forme correspond au cas générale algorithmique.

Pour arrêter une sélection , il faut terminer la suite d'instruction par l'instruction break.

#include <stdio.h>
// test de selections multiples
void main() {
 int i;
 printf( "Entrer un entier compris entre 1 et 3 :");
scanf("%d",&i);

switch (i) { 
case 1 : printf('L'); break;
case 2 : printf('O'); break;
case 3 : printf('G'); break;
default :
printf(" fin  !"; 
              } 
  }

5.3. Les itérations.

Contrôle dans le cas d'actions répétitives.

5.3.1. La boucle TANT QUE condition

5.3.1.1. NOTATION ALGORITHMIQUE

TANT QUE condition
$n°
bloc d'actions
n°$

Tant que la condition est vérifiée, on répète l'execution du bloc. Si la condition est initialement fausse, le bloc n'est jamais exécuté. On ne sort du bloc que si celui-ci rende faux la condition.

5.3.1.2. NOTATION EN LANGAGE C : La boucle while.

	while (expression_entier) bloc_instructions;
expression_entier est une expression qui après évaluation retourne la valeur d'un entier. Si la valeur retournée est nulle, expression_entier est considérée comme fausse, sinon vraie.
// Exemple de boucle TANT QUE
#include <stdio.h>
void main() {
int i=1;
while (i<10) {
printf("i=%d\n",i);
i=i+1;
			}
}

5.3.2. La boucle FOR
   
Considérons les blocs suivants  :

{
initialisations_de_variables;
}
while(continuation) {
liste_instructions; // actions
modification_var_de_contrôle;
			 }

Version C

 $n°1
initialisations_de_variables
n°1$
TANT QUE continuation
$n°2
liste_actions
modification_var_de_contrôle
n°2$

Version algorithmique

Le bloc initialisation_de_variables permet souvent d'initialiser des variables, et en particulier les variables de contrôle utilisées comme condition d'arrêt de la boucle et tester par l'expression continuation.
modification_var_de_contrôle permet de changer la valeur des variables de contrôles testées dans l'expression continuation.

for(initialisations_de_variables; condition;modification_var_contrôles) bloc_instructions ;

La boucle for est equivalent à la structure précédente

// Exemple de boucle for
#include <stdio.h>
void main() {
int i;	
for(i=1; i<10; i=i+1) 
printf("i=%d\n",i);
}	     				

// Exemple2 de boucle for :  incrémentations multiples
#include <stdio.h>

void main() {
int i , j;
for ( i=0, j=20;(i<20) && (j>0) ; i++, j--)     printf("%d\t",i*j) ;
}

Remarque : il est possible d'utiliser l'opérateur , (virgule) dans la condition de continuation du while ou du for .
Le champ bloc_instructions peut être vide.

#// Exemple2 de boucle for : incrémentations multiples
#include <stdio.h>
#include <math.h>

void main() {
float r;
  	for (r=0 ;     // initialisation
 printf("Entrer un entier:") , scanf("%f",&r) ,  r>0; // controle
     	printf("racine carrée=%f\n", sqrt(r))                   //modification       
         );  
             // liste d'instructions vide pour ce for        
  printf("Terminé"); 

}

5.3.3. Structure REPETER … TANT QUE condition

5.3.1. NOTATION ALGORITHMIQUE

REPETER
	$n°
bloc_actions
n°$
TANT QUE condition;

On répète l'excution du bloc tant que la condition est vérifiée. Le bloc est exécuté au moins une fois, quelque soit la condition.

5.3.2. NOTATION EN LANGAGE C

do 
bloc_instructions;
while (condition);

# // Exemple3 de boucle do..while
#include <stdio.h>
#include <math.h>
void main() {
double k, pi = 3.1415926535;
   do {

   	printf("k=?");
  	scanf("%lf",&k);
     	printf("%f\n",cos(k*pi));

} while ((int) k); 

printf("Fin.");
	     }

5.4. Test en milieu d'itération.

Il est possible d'introduire un test au milieu d'une itération par un if associé à break;

// Exemple de sortie par break dans une boucle
#include <stdio.h>
#include <math.h>
void main() {
double x;
while (1)
{ printf("Entrer x=");
  scanf("%lf",&x);
 			 if (x<=0) break; //sortie de boucle
 			 printf( "ln=%lf\n", log(x) );    
 }
printf("Fin");
	     }

REMARQUE
La sortie en milieu d’itérations est souvent utilisée dans le cas où les boucles sont infinies :
	while(1)
      {
         ---------------
	if (test) break;
         -------------
}
ou encore
for(;;) {
           // -----------
           if (test) break;
	  //-------------
          }

5.5. La continuation dans une boucle.

On a vu que de l'instruction break arrête une boucle.
Au contraire, pour relancer une boucle en un point il faut utiliser l’instruction  continue.

Structure en langage C

while(condition) {
// …………………..
if (test) continue;
//revient à l'évaluation de la condition
// …………………..
}

Exemple d'utilisation de continue

Dans l'exemple suivant, il est nécessaire de vider le tampon d'entrée qui contient tous les caractères entrés au clavier.
C'est l'instruction :
fflush(stdin);
qui réalise cette action.

// Exemple de continuation par continu dans une boucle
#include <stdio.h>

void main()
{
 unsigned char c; // caractere sur 8 bits
   while (
	   fflush( stdin ), // vidage du tampon d'entree
	   printf("Entrer c="), scanf("%c",&c), c!='\n')
			{
	printf("Code en decimal=%i\n",c);
	if (c<=127) continue;
	printf("Caractere national de code hexadecimal=%X\n",c);
			}
}

6. COMPLEMENTS :

NOTATIONS ALGORITHMIQUES 
 Il est très important de donner une version algorithmique
d'un programme avant d'écrire le codage en langage C
Proche de l'analyse, le méta-langage algorithmique est 
indépendante des contraintes matériels qu'impose la machine. Le langage C permet de programmer une machine.

6.1. Déclaration d'un type.

TYPE nom_du_type=définition du type

6. 2. Déclaration d'une variable

nom_de_la_variable : nom_du_type

6.3. Présentation d'un algorithme

NOM_DE_ALGORITHME(liste objets formels d'entrée; liste objets formels modifiés et de sortie)

$1

         énoncé de l'algorithme

1$

NOM_DE_ALGORITHME est l'entête de l'algorithme.
Il comporte la liste des objets d'entrée et la liste des objets d'entrée modifiés et de sortie. Ces deux listes sont séparées par un point virgule.
Dans chacune des deux listes, les objets sont séparés par des virgules. Si la première liste est vide, la seconde est précedée du point virgule.
Les objets constituant le paramétrage de l'algorithme sont définis dans le texte précédent l'énoncé de l'algorithme.

La définition des paratmètres est résumé de la façon suivante :

Entrée
nom_objet : nom_type
nom_objet : nom_type
…
Sortie
nom_objet : nom_type
nom_objet : nom_type
…

Sauf dans le cas de difficultés particulières, les objets internes ne seront pas présentés.

On pourra commenter les actions de d'un algorithme à l'aide d'un texte entre précedé de //
// Calcul d'une moyenne

6.4. Exemple : résolution d'un système linéaire à n inconnues et à n équations de la forme A X = B

Méthode d'analyse descendante

Deux étapes :

1.	Transformer les système en système triangulaire

2.	Résoudre le système triangulaire

Algorithme GENERAL

Entrée
N : ENTIER
Entrée modifiée ou sortie
A      : TABLEAU [1..N , 1..N]
B , X : TABLEAU [1..N , 1..N]

RESOLUTION(N ; A , B, X)
$1
	TRIANGULATION (N, A, B)  
	RESOLUTION (A, B, N, X)     
1$

Algorithme TRIANGULATION

TRIANGULATION (N ; A, B)
 $1
POUR K=1, N-1
	$11  ELIMINATION(N, K, A, B)  11$
1$

Algorithme RESOLUTION

La résolution d'un système triangulaire repose sur le principe suivante:
•	on part de la Ne équation, on en tire XN 
•	on reporte XN dans la (N-1)e équation, on en tire XN-1
•	Ect…
RESOLUTION (A, B, N ; X)
$1
X(N)  B[N] / A[N,N]
POUR I = N-1 , 1 , -1
// I varie de N-1 à 1 avec un pas de -1
	$11
		R  0
POUR J = I + 1, N
$111   R  R + A[ I , J ] * X [ J ]	111$	
		X [ I ]  ( B[ I ] - R [ I ] ) / A [ I , I] 
	11$
1$

Algorithme ELIMINATION
// Permet d'éliminer les varaibles dans la triangulation …

ELIMINATION (N, K ; A, B)
$1
	POUR I = K + 1 , N
		$11
			R  A[ I, K] / A[K , K]   // voir la remarque (*)
				POUR J = K + 1 , N
			        $111  A [I,J ]  A [I , J] - R * A[ K,J]   111$
			B[I]  B[I] - R* B[K]
		11$
1$

(*) Remarque 
Afin de simplification de l'écriture des algorithmes on ne considère pas les cas de pivots nuls.

6.5. Analyse descendante, analyse ascendante

Analyse descendante 
On part du niveau le plus général et on spécifie le schéma de résolution à l'aide d'actions de niveau sémantique très élévé.
(Voir par exemple 6.4.)

Avantages de la méthode descendante 
•	Approche systématique du général au particulier
•	Aspect hiérarchique de l'analyse permettant la maîtrise des différents niveaux de complexités.

Inconvénients de la méthode descendante
•	Les choix conceptuels faits à des hauts niveaux sont quelques difficiles à réalisés à des niveaux inférieurs.

•	Nécessité de reprendre l'algorithme à tous les niveaux en cas de remise en cause d'un choix initial.
 
Analyse ascendante
Cette méthode permet de composer des outils (algorithmes) déjà disponibles afin de résoudre un problème de plus haut niveau. 

L'application de cette méthode présume que l'on dispose d'une "boite d'outils" importante et que l'on maîtrise la manière d'utiliser et d'assembler les composantes utiles à la résolution du problème à résoudre.
L'analyse ascendante est presque toujours accompagnée par une analyse descendante : de haut vers le bas pour découper le travail en tâches plus élémentaires et de bas en haut pour réaliser ces tâches élémentaires à l'aide d'outils disponibles. 

Avantage de la méthode ascendante

•	Réutilisation des sous-algortithmes déjà réalisés (augmentation de la vitesse de développement et tests plus faciles)
•	Utilisation d'outils déjà validés et donc obtention d'un programme plus sûr.
•	Possibilité de prototypages précisant le cahier des charges spécifiant ce que l'on attend d'un algorithme qui pourra être réutilisable.

Inconvénients de la méthodes ascendantes.

•	L'inconvénient majeur vient du fait que cette démarche ne relève pas d'une démarche systématique dans le processus d'analyse d'un problème à résoudre.

•	Afin de mieux utilisé un outil, il y a risque de dérive dans la résolution d'un problème posé : on tente d'appliquer un déjà outil existant mais inadéquate.