Histoire du langage
• Ada remontent au début des années 1980.
• Son développement a commencé au début des
années 1980 pour donner
Ada 83
.
• Ada 83 a été ensuite repris et amélioré au milieu
des années 1990 pour donner
Ada 95
, le
premier langage objet normalisé de manière
internationale.
• Ada 95 est souvent utilisé pour
l'apprentissage de l'informatique, car il est
clair et structuré,
• Une autre raison pour adopter Ada 95 est
qu'il est gratuit.
• On appelle aussi Ada 95
le langage vert :
– Lors de
l’appel d’offre
du
DoD
(Departement
of Defense), les différentes propositions
étaient désignées par des
couleurs
, et
l’équipe qui l’a conçu était
l’équipe verte
.
• Il a été créé par l'équipe de Jean
Ichbiah et résulte d'un cahier des
charges extrêmement précis fourni par
le
Département
de
la
Défense
américaine.
• Son nom a été choisi en l'honneur
d'Ada Lovelace
, une femme qui est
supposée être la première à avoir écrit
un programme informatique.
• Ada Lovelace,
officieusement Augusta Ada King,
comtesse Lovelace, née le
10 décembre 1815 et morte
le 27 novembre 1852 à Londres, est principalement connue pour avoir traduit et annoté une description de la machine analytique de Charles Babbage, un ancêtre de l'ordinateur. • Dans ses notes, on trouve le
premier algorithme publié Woolley 1, destiné à être exécuté par une machine, ce qui fait considérer Ada Lovelace comme une programmeuse, voire « le premier programmeur du monde »
Programmez avec AdaGide et Gnat
• Nous utiliserons les logiciels suivants :
• comme éditeur de texte, ADAGide ;• comme compilateur, Gnat.
• ADAGide
nous servira donc de support afin
d'y écrire notre code ADA.
Créer un fichier et l'enregistrer avec
ADAGide
• Pour créer un nouveau fichier avec ADAGide
– Il suffit tout simplement d'aller dans le menu File
et de cliquer sur New (raccourci : Ctrl + n).
• Pour sauvegarder un fichier, allez dans le
menu File et cliquez sur Save as.... Là,
choisissez le nom de votre fichier et cliquez
sur Enregistrer
Compilation
• En informatique, la compilation est le travail réalisé
par un compilateur qui consiste à transformer un
code source lisible par un humain en un fichier
binaire exécutable par une machine.
Le code source
• Le code source est le code que vous taperez dans
votre éditeur de texte (ADAGide ou autre). Il est
donc compréhensible par un humain. Bien
entendu, afin d'en faire un exécutable (un fichier de
type *.exe), il faudra
le compiler
.
Compilez un programme écrit avec ADAGide !
• Imaginez maintenant que vous ayez tapé un
programme ADA et qu'il soit entièrement correct
(qu'il ne comporte aucun problème).
• Pour le compiler suivez les instructions ci-dessous:
– appuyez sur F2 : ceci compilera le programme ; – appuyez sur F3 : ceci terminera la compilation.
• Vous disposez maintenant d'un fichier exécutable,
et afin de voir son rendu (c'est-à-dire comment il va
apparaître à l'écran), il vous suffit d'effectuer
La structure d'un programme ADA
• Un programme ADA se compose de quatre parties principales:
1. La clause de contexte contient tous les outils
nécessaires au programmeur. On les appelle
"paquetages". Voici comment "appeler" un paquetage :
with Ada.Text_IO; use Ada.Text_IO;
Ce paquetage est nécessaire pour afficher des caractères à l'écran ou encore pour récupérer du texte entré par l'utilisateur.
» Pour appeler un paquetage. Tout d'abord, nous avons le mot réservé with. Ensuite, vient le nom du langage : ADA. Suivie du nom du paquetage (ici Text_IO, qui signifie Text Output
Input ou "texte en entrée et sortie").
» La partie après le ";" et commençant par le mot réservé use signifie que nous allons utiliser ce paquetage. En français, nous pourrions traduire la ligne de commande comme suit :
• Il reste un type différent des deux présentés
ci-Paquetage permettant de faire intervenir des nombres entiers relatifs :
2. L'
en-tête du programme
, où est spécifié le
nom du programme. Voici l'en-tête de notre
programme :
procedure Exemple1 is
3. La
partie déclarative
, comprise entre
l'en-tête
et le mot réservé
begin
. C'est cette
partie qui contient les déclarations
(constantes, lettres, etc.).
4. la
partie instructions
, comprise entre les
mots
begin et end et qui contient les
instructions du programme, c'est-à-dire
les actions à entreprendre.
Les commentaires
--
Cette ligne de code est un commentaire
with Ada.Text_IO; use Ada.Text_IO;
--
Cette ligne est elle aussi un commentaire,
mais pas celle située au-dessus
PROGRAMME AFFICHANT
BONJOUR A L’ECRAN
-- EKARI
--FERVRIER 2013
-- Description : programme affichant le mot
"bonjour" dans une console
with Ada.Text_IO; use Ada.Text_IO;
procedure afficheBonjour is
begin
Exercice
Écrire un programme affichant ceci :
Coucou
tout le
monde
! ! !
Solution
With ada.text_io ;
use ada.text_io ;
procedure
Hello2
is
begin
Put("
Coucou
") ; New_line ;
Put("
tout le
") ; New_line ;
Put("
monde
") ; New_line ;
Put("
! ! !
")
;
Deuxième solution
With ada.text_io ;
use ada.text_io ;
procedure
Hello3
is
begin
Put_line("
Coucou
") ;
Put_line("
tout le
") ;
Put_line("
monde
") ;
Variables I : Typage et affectation
Une déclaration se fait toujours de la façon suivante :
NOM_DE_LA_VARIABLE : TYPE ;
Il est possible de déclarer plusieurs variables d'un coup de la manière suivante :
NOM_DE_LA_VARIABLE1 , NOM_DE_LA_VARIABLE2 : TYPE ;
Il est aussi possible, aussitôt la variable déclarée, de lui
affecter une valeur à l'aide du symbole ":=". On écrira alors :
Exemple
Procedure VotreAge is
NOM_DE_LA_VARIABLE1 : TYPE1 := VALEUR ;
--zone réservée aux déclarations
NOM_DE_LA_VARIABLE2 : TYPE2 ;
begin
Put("Quel age avez-vous ?") ;
Déclaration d’une variable
Exemple:
Age: Integer; --Age est de type Integer
On remarque aisément qu'il y a d'un côté le nom de cette variable, et après les ":" son type.
Syntaxe:
NOM de la variable :TYPE
Affectation:
Age: Integer:=18; --Age, de type Integer, possède la valeur 18
Comment récupérer une saisie ?
L'instruction Get
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO; procedure DemandeAge is
Age:Integer; --Age est donc un nombre begin
Put("Entrez votre age : "); --On demande l'âge de l'utilisateur Get(Age); --On récupère ce qu'il a entré à l'aide de son clavier New_Line;
Put(Age); --On affiche l'âge entré end DemandeAge;
Que fais ce programme et quel
est le rôle de skip_line?
with Ada.Text_IO, Ada.Float_Text_IO ; use Ada.Text_IO, Ada.Float_Text_IO ;
Procedure TaillePoids is
Taille, Poids : float ;
Begin
Put("Quelle est votre taille ?") ; Get(Taille) ; Skip_line ;
Put("Vous mesurez ") ; Put(Taille) ;
Déclaration d’une constante
with Ada.Text_IO, Ada.Float_Text_IO ; use Ada.Text_IO, Ada.Float_Text_IO ;
Procedure TaillePoids is
Taille, Poids : float ;
Begin
MaVariable : Constant Integer := 15 ;
Comment obtenir le plus petit et le plus grand Integer ? Comment savoir quel est le 93ème character ? Grâce aux attributs, bien sûr. Ce sont des sortes
d'instructions qui s'appliquent aux types.
WITH Ada.Text_Io ;USE Ada.Text_Io ;
WITH Ada.Integer_Text_IO; USE Ada.Integer_Text_IO;
with ada.Characters; use ada.Characters;
PROCEDURE attri IS
N,M,p : Integer; c : character;
BEGIN
N := integer'first ; --N sera le premier des integer M := integer'last ; --M sera le dernier des integer
C := character'val(93) ; -- C sera la 93ème valeur des character
Exercice :
Rédiger un programme appelé Multiple qui demande à l'utilisateur de saisir un nombre entier et lui retourne son double, son triple et son quintuple. J'ajoute une difficulté ! Vous n'aurez le droit qu'à deux multiplications pas une de plus !
Solution :
WITH Ada.Text_IO, Ada.Integer_Text_IO ; USE Ada.Text_IO, Ada.Integer_Text_IO ; PROCEDURE Multiple IS N : Integer ; Double, Triple : Integer ;
BEGIN
Put("Saisissez un nombre entier : ") ; Get(N) ; Skip_Line ;
Double := 2*N ; Triple := 3*N ;
Put("Le double de ") ; Put(N) ; Put(" est ") ; Put(Double) ; New_Line ; Put("Le triple de ") ; Put(N) ; Put(" est ") ; Put(Triple) ; New_Line ;
Exercice :
Rédiger un programme appelé Euclide qui
demande deux nombres entiers à l'utilisateur puis
renvoie le quotient et le reste de leur
division euclidienne (c'est à dire la division entière
telle que vous l'avez apprise en primaire).
Solution :
WITH Ada.Text_IO, Ada.Integer_Text_IO ; USE Ada.Text_IO, Ada.Integer_Text_IO ;
PROCEDURE Euclide IS N,M : Integer ; BEGIN Put("Saisissez le dividende : ") ; Get(N) ; Skip_Line ; Put("Saisissez le diviseur : ") ; Get(M) ; Skip_Line ;
Les conditions :
Procedure Questionnaire is
Reponse : Character := 'n' ; --on définit Reponse et on lui
--attribue par défaut la valeur n (pour non)
begin
Put("Avez-vous plusieurs ordinateurs ? (o/n) ") ; Get(Reponse) ; Skip_line ;
--On saisit la réponse et on vide la mémoire tampon if Reponse = 'o' --SI Reponse est égal à o
then Put("Vous avez bien de la chance.");
--ALORS on affiche la phrase.
Conditions multiples avec CASE :
case Reponse is
--on indique que l'on va regarder les différents cas --possibles pour Reponse
when 'o' => Put("Vous avez bien de la chance.") ; -- si oui
when 'n' => Put("Ah ... dommage. ") ; -- si non
when 'p' => Put("Reponses normandes non valides") ;
when 'f' => Put("J'aurais pas du prendre Allemand ...") ;
when others => Put("C'est pas une reponse.") ;
Les opérateurs de comparaison
Exemple :
Procedure Questionnaire2 is
Reponse : integer := 0 ; --on définit la réponse et on l'initialise à 0 begin
Put("Combien d'ordinateurs avez-vous?") ; Get(Reponse) ; Skip_line ;
if Reponse >= 2
then Put("Genial!") ;
else Put("C'est toujours ca") ; end if ;
Les boucles en ADA
case Nb is
when 0 => Null ; --ne rien faire when 1 => Put("#") ;
when 2 => Put("##") ; when 3 => Put("###") ; when 4 => Put("####") ; when 5 => Put("#####") ;
when others => Put("######") ; end case ;
Compteur : integer := 0;
loop
if Compteur = 6 then exit ; else Put('#') ;
Compteur := Compteur +1 ; end if ;
Les boucles en ADA
loop
exit when Compteur = Nb ;
--comme tout à l'heure, on sort si on a affiché assez de dièses Put('#') ;
--on peut tranquillement afficher un dièse, car si le nombre était atteint, la boucle serait déjà cassée
Compteur := Compteur +1 ; --et on n'oublie pas d'incrémenter
La boucle while en ADA
while
Compteur /= Nb
loop
Compteur := Compteur +1 ;
Put('#') ;
end loop ;
---while
Nb /= 0
loop
Nb := Nb - 1 ;
Put('#') ;
end loop
;
La boucle FOR en ADA
FOR
i
IN
1
..
Nb
loop
put("#") ;
end loop ;
---
Et si on voulais faire le décompte "en sens inverse" ? En décrémentant plutôt qu'en incrémentant ?
La boucle FOR en ADA
FOR
i
IN
1
..
Nb
loop
put("#") ;
end loop ;
---
Et si on voulais faire le décompte "en sens inverse" ? En décrémentant plutôt qu'en incrémentant ?
FOR
i
IN reverse
1
..
nb
loop
La boucle GOTO en ADA
<<debut>>
if Compteur <= Nb
then Put('#') ;
Compteur := Compteur + 1 ;
goto
debut
;
end if ;
---Solution avec une seule boucle :
with ada.Text_IO, ada.Integer_Text_IO ; use ada.Text_IO, ada.Integer_Text_IO ;
procedure Carre is
Nb : integer ; Begin
Put("Quel est le cote de votre carre ? ") ; Get(Nb) ; Skip_line ;
for i in 1..Nb**2 loop --Nb**2 est la notation du carré, Put('#') ; --on affiche le dièse
if i mod Nb = 0 --Si i est multiple de Nb then New_line ; --On retourne à la ligne end if ;
end loop ;
Solution avec deux boucle :
with ada.Text_IO, ada.Integer_Text_IO ; use ada.Text_IO, ada.Integer_Text_IO ;
procedure Carre is
Nb : integer ; Begin
Put("Quel est le cote de votre carre ? ") ; Get(Nb) ; Skip_line ;
for i in 1..Nb loop --Boucle chargée d'afficher toutes les lignes for j in 1..Nb loop --Boucle chargée d'afficher une ligne Put('#') ;
Les procédures
Procédure sans paramètre:
Procedure Nom_De_Votre_Procedure is
--Partie pour déclarer les variables
begin
--Partie exécutée par le programme
Procédure avec un paramètre (ou argument):
with Ada.Text_IO, Ada.Integer_Text_IO ; use Ada.Text_IO, Ada.Integer_Text_IO ; procedure Figure is
Procedure Affich_Ligne(nb : natural) is begin for j in 1..nb loop put('#') ; end loop ; new_line ; end Affich_Ligne ; --- nb_lignes, nb_colonnes : natural;
begin
Put("Combien de lignes voulez-vous dessiner ? ") ; get(nb_lignes ) ; skip_line ;
Put("Combien de colonnes voulez-vous dessiner ? ") ; get(nb_colonnes ) ; skip_line ;
Procédure avec deux arguments :
Procedure Affich_Rect(nb_lignes : natural ; nb_colonnes : natural) is
begin
for i in 1..nb_lignes loop
Affich_Ligne(nb_colonnes);
end loop ;
Les fonctions:
C'est la même chose que les procédures. La différence, c'est que les fonctions renvoient
un résultat.
Exemple
function A_Rect(larg : natural, long : natural) return natural is A : natural ;
begin
A:= larg * long ; return A ;
end A_Rect ; ---
Par return, il faut comprendre "résultat". Dans la première ligne,
« return natural is » indique que le résultat de la fonction sera de type
natural. En revanche, le "return A" de la 5ème ligne a deux actions : •Il stoppe le déroulement de la fonction (un peu comme exit pour une
Utilisation de la fonction :
Exemple :
...
if choix=1
then Put("Combien de colonnes voulez-vous dessiner ? ") ; get(nb_colonnes ) ; skip_line ;
Affich_Rect(nb_lignes, nb_colonnes) ;
Aire := A_Rect(nb_lignes, nb_colonnes) ;
Put("L'aire du rectangle est de ") ; Put(Aire) ; put_line(" dieses.") ; else Affich_Tri(nb_lignes) ;
end if ; ...
Mode : In, Out, In Out
procedure Affich_Rect(nb_lignes : in natural, nb_colonnes : in natural) is
Les instructions in indiquent que nos paramètres sont uniquement des paramètres d'entrée. Les emplacements-mémoire qui contiennent leur valeur
peuvent être lus mais il vous est interdit d'y écrire : ils ne sont accessibles qu'en lecture. Donc impossible d'écrire "nb_lignes := 5" au cours de cette procédure.
procedure Affich_Rect(nb_lignes : out natural, nb_colonnes : out natural) is
vos paramètres deviendront des paramètres de sortie. Il sera possible d'écrire dans les emplacements-mémoire réservés à nb_lignes et nb_colonnes. Sauf qu'il vous sera impossible de lire la valeur initiale, donc impossible d'effectuer des
tests par exemple. Vos paramètres ne sont accessibles qu'en écriture.
Les tableaux
Type
T_Tableau
is
array(0..5) of integer
;
Scores : T_Tableau ;
Ou encore
TailleMax :
constant natural
:= 5 ;
Type
T_Tableau
is array(0..TailleMax) of integer ;
Affectation globale
Maintenant que nous avons déclaré un tableau d'entiers (Scores de type T_Tableau), encore faut-il lui affecter des valeurs. Cela peut se faire de deux façons distinctes. Première façon, la plus directe possible :
Scores := (15,45,27,8,19,27) ; Ou bien Scores := (1|3 => 17, others => 0) ; C’est équivalent à : Scores := (17,0,17,0,0,0) ; Ou encore : Scores := (17,0,17,4..6 => 0) ;
Affectation valeur par valeur
C'est pourquoi on utilise souvent la seconde méthode :
Scores(1) := 15 ; Scores(2) := 45 ; Scores(3) := 27 ; Scores(4) := 8 ; Scores(5) := 19 ; Scores(6) := 27 ;
En utilisant des boucles :
Attributs pour les tableaux
for i in T'range loop
T(i) := 0 ;
end loop ;
---
Tableaux multidimensionels
Tableaux bidimensionnels
La déclaration se fait très facilement de la manière suivante :
Le premier intervalle correspond au nombre de lignes, le second au nombre de colonnes.
Exercice
Énoncé
Créer un programme TriTableau qui crée un tableau unidimensionnel avec des valeurs entières aléatoires, l'affiche, trie ses valeurs par ordre croissant et enfin affiche le tableau une fois trié.
EXERCICE
FAITES VARIER LE DELAY DANS LA TACHE UN_TYPE QUE REMARQUEZ VOUS
EXERCICE
Écrire un programme qui contient deux tâches. La première tâche calcule et affiche les éléments de la suite
La tâche doit attendre une seconde entre le calcul/affichage de deux éléments successifs.
La deuxième tâche calcule et affiche les éléments de la suite
La tâche doit attendre deux secondes entre le calcul/affichage de deux éléments successifs.
1 2 0 1 U avec U Un n 0 2 0 1 U avec U Un n
Exercice : Décollage d’une Fusée
Prenons comme exemple un domaine très friand de programmation temps réel : l'aérospatiale ! Vous devez rédiger un programme d'aide au pilotage pour la fameuse fusée Z123. Votre programme doit vérifier régulièrement l'altitude et la vitesse et afficher les valeurs lues.
POUR FINIR IL FAUT TEMPORISER LES TACHES :
Notre programme prend fin, le décollage de la fusée de Zozor a bien eu lieu mais on n'a le temps de rien voir. Quand le programme prend fin, on voit seulement que l'altitude est de 10 000 mètres et la vitesse de 1000 km/H
POUR FINIR IL FAUT TEMPORISER LES TACHES :
Et pour éviter que le décollage ne soit terminé avant que le moindre affichage n'ait eu lieu, nous allons également temporiser le décollage en attendant un centième de seconde avant l'incrémentation :
POUR FINIR IL FAUT TEMPORISER LES TACHES : Temporiser jusqu'à ...
Une autre possibilité est d'utiliser la combinaison de deux instructions : delay until ### ; où ### est de type Time. Cela signifie "attendre jusqu'à une date précise". Vous aurez alors besoin soit du package Ada.calendar soit de Ada.Real_Time. Tous deux définissent un type Time et une fonction clock vous permettant
Exemple de synchronisation par Rendez-vous Round-Robin ou "l'effet tourniquet"
Exemple de synchronisation par Rendez-vous
Round-Robin ou "l'effet tourniquet"
Exercice
Écrire un programme qui crée deux tâches qui doivent se synchroniser par rendez-vous en vue de convertir des caractères. La tâche cliente produit un caractère et demande à la tâche serveur de convertir son caractère en majuscule.
Une fois le caractère converti, il est retourné à la tâche cliente qui l’affiche. Le point de RDV est représenté à l’aide de la procédure service().
La tâche serveur doit définir un point d’entrée avec le nom de cette procédure.
Priorités, Complément sur le tourniquet
• La
priorité d'une tâche peut être fixée de manière statique grâce à une directive de compilateur : Lesfameux pragma. Nous ferons appel ici le pragma priority.
Celui-ci permet de fixer la priorité d'une tâche de manière statique : nous définirons la priorité lors des spécifications de la tâche une fois pour toute. Le langage Ada accepte des niveaux de priorités allant de 0 à 30, 30 étant le niveau de priorité maximal. Nous allons également faire appel à un nouveau package : System. Attention ! Pas Ada.system, mais System tout court ! Ce
Priorités, Complément sur le tourniquet
Autre exemple :
task Tspeed i s
pragma P r i o r i t y ( 1 0 ) ;
Déclaration d’un type tâche :
task type T i s