Cours 4: Instructions suite
Objectif: Instruction cas. Instruction de boucle.
Exemples: calcul de la date du lendemain entre 1901 et 2099.
Calcul de xn (itération bornée sans compteur).
Calcul de n! (itération bornée avec compteur en progression).
Décalage à droite des éléments d'un tableau (itération bornée avec compteur en régression).
Fusion d'un tableau trié (itération non bornée à sortie en milieu de corps).
Racine carrée entière (itération non bornée à sortie en début de corps).
Logarithme entier en base 2 (sortie en fin de corps).
L'instruction case se compose d'une expression d'un type discret et d'un ensemble de cas.
Chaque cas est gardé par un ensemble de valeurs du type de l'expression.
Un éventuel dernier cas est gardé par la valeur symbolique other.
Les cas doivent être deux à deux disjoints.
Extrait du manuel de référence (RM95):
case_statement ::=
case expression is
case_statement_alternative
{case_statement_alternative}
end case;
case_statement_alternative ::=
when discrete_choice_list =>
sequence_of_statements
discrete_choice_list ::= discrete_choice {| discrete_choice}
discrete_choice ::= expression | discrete_range | others
L'expression est évaluée.
Si sa valeur figure parmi l'une des gardes, la suite d'instructions du cas est exécutée.
Sinon, et si un cas other est proposé, sa suite d'instructions est exécutée.
Extrait du manuel de référence (RM95):
case Sensor is
when Elevation => Record_Elevation(Sensor_Value);
when Azimuth => Record_Azimuth (Sensor_Value);
when Distance => Record_Distance (Sensor_Value);
when others => null;
end case;
case Today is
when Mon => Compute_Initial_Balance;
when Fri => Compute_Closing_Balance;
when Tue .. Thu => Generate_Report(Today);
when Sat .. Sun => null;
end case;
case Bin_Number(Count) is
when 1 => Update_Bin(1);
when 2 => Update_Bin(2);
when 3 | 4 =>
Empty_Bin(1);
Empty_Bin(2);
when others => raise Error;
end case;
Autre exemple:
case Mois_Aujourdhui is
when Avril | Juin | Septembre | Novembre =>
Fin_de_Mois := 30;
when Fevrier =>
if Bissextile(Annee_Aujourdhui) then
Fin_de_Mois := 29;
else
Fin_de_Mois := 28;
end if;
when others =>
Fin_de_Mois := 31;
end case;
if (Quantieme_Aujourdhui /= Fin_de_Mois) then
Quantieme_Demain := Quantieme_Aujourdhui + 1;
Mois_Demain := Mois_Aujourdhui;
Annee_Demain := Annee_Aujourdhui;
else
Quantieme_Demain := 1;
if (Mois_Aujourdhui /= Decembre) then
Mois_Demain := Mois'Succ(Mois_Aujourdhui);
Annee_Demain := Annee_Aujourdhui;
else
Mois_Demain := Janvier;
Annee_Demain := Annee_Aujourdhui + 1;
end if;
end if;
L'instruction de boucle comprend un éventuel schéma d'itération fixant les conditions de répétition du corps de boucle.
Lorsqu'aucun schéma n'est présent, le corps de boucle peut contenir une instruction de sortie.
Un schéma while c répète le corps de boucle tant que la condition c est vraie.
Un schéma for i in range répète le corps de boucle pour chacune des valeurs de i dans l'intervalle range.
La variable i est implicitement déclarée du type de l'intervalle range.
loop_statement ::=
[loop_statement_identifier:]
[iteration_scheme] loop
sequence_of_statements
end loop [loop_identifier];
iteration_scheme ::= while condition
| for loop_parameter_specification
loop_parameter_specification ::=
defining_identifier in [reverse] discrete_subtype_definition
Extrait du manuel de référence (RM95):
Examples
Example of a loop statement without an iteration scheme:
loop
Get(Current_Character);
exit when Current_Character = '*';
end loop;
Example of a loop statement with a while iteration scheme:
while Bid(N).Price < Cut_Off.Price loop
Record_Bid(Bid(N).Price);
N := N + 1;
end loop;
Example of a loop statement with a for iteration scheme:
for J in Buffer'Range loop -- works even with a null range
if Buffer(J) /= Space then
Put(Buffer(J));
end if;
end loop;
Example of a loop statement with a name:
Summation:
while Next /= Head loop
Sum := Sum + Next.Value;
Next := Next.Succ;
end loop Summation;
Autres exemples
Ite'ration borne'e sans compteur:
function "**"(X: Integer; N: Natural) return Integer is
P: Integer:= 1;
begin
for I in 1..N loop -- I de'clare'
P:= P*X; -- Corps inde'pendant de I
end loop;
return P; -- I n'existe plus
end "**";
Ite'ration borne'e avec compteur en progression:
function Factorielle(N: Natural) return Positive is
-- Factorielle(0)=1
P: Positive:= 1;
begin
for I in 1..N loop
P:= P*I; -- Corps de'pendant de I
end loop;
return P;
end Factorielle;
Ite'ration borne'e avec compteur en re'gression:
procedure Decale_a_droite(T: in out Table) is
begin
for I in reverse Indice'Succ(Table'First)..Table'Last loop
T(I):= T(Indice'Pred(I));
end loop;
end Decale_a_droite;
Ite'ration non borne'e a` N tours et demi:
procedure Fusion(T: in out Table; Nb: Indice; Nb_restants: out Indice) is
-- Fusionner un tableau trie' pour en e'liminer les doublons
-- Nb est le nombre de places occupe'es dans le tableau avant fusion
-- Nb_restants est le nombre de places occupe'es dans le tableau apre`s fusion
Lecture, Ecriture: Indice:= T'First;
begin
loop
T(Ecriture):= T(Lecture);
while Lecture<=Nb and then T(Lecture)=T(Ecriture) loop
Lecture:= Indice'Succ(Lecture);
end loop:
exit when Lecture>Nb;
Ecriture:= Indice'Succ(Ecriture);
end loop;
Nb_restants:= Ecriture;
end Fusion;
Ite'ration non borne'e a` au moins un tour:
function Log2(N: Positive) return Natural is
L: Natural:= 0;
begin
loop
L:= L+1;
exit when 2**L>N;
end loop;
return (L-1);
end Log2;
Ite'ration non borne'e a` ze'ro tour ou plus:
function Racine(X: Natural) return Natural is
R: Natural:= 1;
begin
while R*R<=X loop
R:= R+1;
end loop;
return (R-1);
end Racine;