Algorithmique Procédurale

Slides:



Advertisements
Présentations similaires
La programmation orientée objet avec Java L3-MIAGE Plan
Advertisements

Premier programme en C :
La boucle for : init7.c et init71.c
Chapitre annexe. Récursivité
Initiation à la programmation et algorithmique cours 4
Portée des variables VBA & Excel
La classe String Attention ce n’est pas un type de base. Il s'agit d'une classe défini dans l’API Java (Dans le package java.lang) String s="aaa"; // s.
Algorithmique Résume.
(Classes prédéfinies – API Java)
Cours n°2M2. IST-IE (S. Sidhom) UE 303 Promo. M2 IST-IE 2005/06 Conception dun système d'information multimédia Architecture trois-tiers : PHP/MySQL &
C.
Tableaux Certains problèmes nécessitent beaucoup de variables du même type. Exemple : relevé de températures matin et soir dans 10 villes pour 10 jours.
Chap. 1 Structures séquentielles : listes linéaires
ESIEE Paris © Denis BUREAU I N Initiation à la programmation avec le langage Java.
8. Les tableaux P. Costamagna – ISEN N1.
Introduction à la programmation (420-PK2-SL) cours 15 Gestion des applications Technologie de linformation (LEA.BW)
Les sous-programmes Chapitre n° 5: Objectifs : Activité:
Initiation à la programmation et algorithmique cours 3
Lycée Louis Vincent SEANCE 6 Python Les listes Lundi 25 novembre 2013.
Les bases de l’Algorithmique
Principes de programmation (suite)
CPI/BTS 2 Programmation Web Introduction au PHP
Cours 7 - Les pointeurs, l'allocation dynamique, les listes chaînées
Structures de données linéaires
Introduction à la programmation (420-PK2-SL) cours 12 Gestion des applications Technologie de linformation (LEA.BW)
OCaml - Les listes L3 MI.
Récursivité.
44 Contrôle du déroulement du programme. 4-2 Objectifs A la fin de ce cours, vous serez capables de : Utiliser les constructions de prise de décision.
Les méthodes en java Une méthode est un regroupement d’instructions ayant pour but de faire un traitement bien précis. Une méthode pour être utilisée.
Les éléments de base de l’algorithmique
RESUMES Module II1 SOMMAIRE CYCLE 1 : Saisir – Afficher – Données
Python La structure itérative
Introduction à la programmation (Java)
Master 1 SIGLIS Java Lecteur Stéphane Tallard Chapitre 5 – Héritage, Interfaces et Listes génériques.
Les pointeurs Enormément utilisé en C/C++ ! Pourquoi? A quoi ça sert?
FICHIERS : Définition : Algorithme général:
Les Fonctions. Définir une fonction Sections de code indépendantes que lon peut appeler à nimporte quel moment et dans nimporte quel ordre. Bout de code.
Principes de programmation
Contrôle de types Les types en programmation Expressions de types Un contrôleur de types Equivalence de types Conversions de types Généricité.
IFT 6800 Atelier en Technologies d’information
LIFI-Java 2004 Séance du Jeudi 9 sept. Cours 1. La notion de langage Décrire une tâche à effectuer –programme Écrire à un haut niveau –facile pour lutilisateur.
Chapitre 9 Les sous-programmes.
Chapitre 3 Syntaxe et sémantique.
8PRO100 Éléments de programmation Les types composés.
Plan cours La notion de pointeur et d’adresse mémoire.
Types de données fondamentaux
Animateur : Med HAIJOUBI
Structures des données
LE LANGAGE JAVASCRIPT LES TABLEAUX ET LES FONCTIONS.
2.1 - Historique Chapitre 2 : Introduction au langage C++
LES PILES ET FILES.
Les Pointeurs et les Tableaux Statiques et Tableaux Dynamiques
JavaScript.
Algorithmes de tri et de recherche
Décomposition et paramétrage des algorithmes
Créer des packages.
Un survol du language C.
Master 1 SIGLIS Java Lecteur Stéphane Tallard Les erreurs communes en Java.
 Syntaxe du langage PHP
Tutorat en bio-informatique
Tutorat en bio-informatique Le 14 novembre Au programme… Les objets –Propriétés (attributs) –Constructeurs –Méthodes.
Cours LCS N°4 Présenté par Mr: LALLALI
Introduction au langage C : Structures de contrôle 1 ère année Génie Informatique Dr Daouda Traoré Université de Ségou
Scripts et fonctions Instructions de contrôle
Chapitre 4 La représentation des nombres.
Introduction à l’utilitaire
Philippe Gandy - 8 septembre 2015 Basé sur les notes de cours de Daniel Morin et Roch Leclerc.
Algorithmique Boucles et Itérations
L ES INSTRUCTIONS DE L ECTURE, E CRITURE ET A FFECTATION Réalisé par : OUZEGGANE Redouane Département de Technologie Faculté de Technologie – Université.
Transcription de la présentation:

Algorithmique Procédurale IUP GMI 1ère année Denis Robilliard

Sommaire Introduction Premier programme Historique La machine de Turing Langages de programmation Arbres programmatiques et Ada Syntaxe, expressions régulières Premier programme Premier programme en Ada Instructions

Structures de contrôle du flux d ’instructions Commentaires Variables, affectations Types de base Opérations arithmétiques de base Entrées/sorties sur les types de base Inclure des bibliothèques Conversions de types Structures de contrôle du flux d ’instructions Structure d'alternative AP / ADA Expressions booléennes, opérateurs relationnels

Types tableaux Structure de cas AP / ADA Expression statique ou dynamique Phases d'écriture d'un programme Structure de boucle AP /ADA Boucle "pour" AP / ADA Boucle avec sortie Résumé des différentes structures de boucle en ADA Bloc déclaratif AP /ADA Types tableaux Tableaux AP / ADA

Les sous-programmes : procédures et fonctions Exemple sur les tableaux Règles, opérations et attributs de tableaux Les tranches Les agrégats Les chaînes de caractères AP / ADA Entrées / sorties sur les chaînes Attributs relatifs aux chaînes et aux caractères Les tableaux à plusieurs dimensions Les sous-programmes : procédures et fonctions Paramètres et valeur de retour

Retour sur les types, enregistrements Paramètres par défaut Position des procédures et des fonctions Déclarations préliminaires Portée et visibilité Récursivité Retour sur les types, enregistrements

Introduction Algorithmique : "art" d ’écrire des algorithmes ou programmes. Synonyme : programmation. Algorithme : procédé opératoire qui permet, à partir de données, d ’obtenir un résultat précis. Ex : algo de l ’addition de deux nombres.

Algo procédurale (ou encore impérative) : les programmes sont conçus comme une liste d ’ordres / instructions, qui doivent s ’exécuter un par un, dans un ordre chronologique défini à l ’avance. Il existe d ’autres formes d ’algo : parallèle, objet, fonctionnelle, déclarative, ...

Historique Premiers algorithmes dès l ’Antiquité : Euclide, Eratosthène, … Premières machines à calcul : Pascal, Descartes (17ème), algorithme "codé" par des engrenages. Premier véritable ordinateur : la machine de Babbage (19ème), non achevée. Nouveauté : elle est programmable.

Première personne à programmer : Lady Ada Lovelace, "assistante" de Babbage. Théorisation : Turing, Church (années 30), définition de la notion mathématique de "fonction calculable" = ce qui peut être réalisé par un "ordinateur universel". Premiers ordinateurs électroniques mis au point pendant la 2nde guerre mondiale.

La machine de Turing Un "ordinateur" de papier : une bande de papier, finie mais aussi longue qu ’on le souhaite, divisée en cases qui peuvent contenir les symbole 0 ou 1 une "tête" de lecture/écriture qui pointe sur une case, qui peut lire ou écrire un 0 ou un 1 dans la case, et qui peut se déplacer d ’une case à droite ou à gauche … (voir page suivante)

un programme, composé de règles de la forme : <q, s> ~ <q ’, s ’, p> avec {q, q ’} des états de la machine de Turing, dont le nombre, toujours fini, est dépendant du programme que l ’on exécute {s, s ’} dans {0,1} les symboles que l ’on peut écrire sur la bande p dans {g,d} une direction indiquant vers quelle case voisine (gauche ou droite) se déplace la tête de lecture pour exécuter la prochaine instruction

Représentation de la machine de Turing ... q0 Tête de lecture dans la configuration de départ 1 ... Position de la tête de lecture et état de la bande après application de la règle : <q0, 0> ~ <q1, 1, d> q1

Exemple de programme Objectif : le programme va lire un nombre en base 1 composé de 2 chiffres au plus. Il va écrire le double de ce nombre, en base 1, plus loin sur la bande. Note : la bande sera donc divisée (virtuellement) en une zone de données de deux cases suivie d ’une zone de résultat. La donnée en entrée est écrite sur la bande par l ’utilisateur.

Le programme : Note : <q0, 0> ~ <q10, 0, d> <q20, 0> ~ <qF, 0, d> <q21, 0> ~ <q311, 1, d> <q311, 0> ~ <qF, 1, d> <q22, 0> ~ <q321, 1, d> <q321, 0> ~ <q422, 1, d> <q422, 0> ~ <q523, 1, d> <q523, 0> ~ <qF, 1, d> Note : q0 est l ’état initial de la machine qF est l ’état final : quand la machine passe dans l ’état qF elle s ’arrête

Tout ce qui peut être calculé par une machine de Turing = ensemble des fonctions calculables Tous les ordinateurs actuels sont des machines de Turing, à la restriction près que leur mémoire est finie. Il existe des fonctions non calculables !!! Un ordinateur ne peut pas tout faire...

Langages de programmation Pour communiquer l ’idée d ’un algo, à une personne ou à un ordinateur, nécessité d ’un langage. En général les langages informatiques sont universels (ils permettent de coder tous les programmes possibles). Cependant, ils favorisent souvent une certaine approche des problèmes : Pascal, C : programmation procédurale Smalltalk, Eiffel, Java : programmation objet Prolog : programmation déclarative

Arbres Programmatiques et Ada Nous utiliserons 2 langages : Un langage pédagogique, en partie graphique, noté AP : les Arbres Programmatiques. Note : ce ne sont pas des organigrammes. Un langage "de la vraie vie" : ADA. C ’est un langage de programmation procédurale, créé en 1983 sur appel d ’offre du Département de la Défense américain. Il possède, depuis 1995, des extensions objets, que nous n ’utiliserons pas.

Pourquoi les arbres programmatiques ? C ’est une notation "papier" (nous n ’exécuterons pas un AP sur machine). Nous nous permettrons une syntaxe plus souple. Les APs forcent le programmeur à une approche hiérarchique, descendante du problème. C ’est la "programmation structurée" : On part des idées générales et on va progressivement de plus en plus dans le détail. Les branches d'un arbre programmatique sont assez indépendantes les unes des autres (au moins en ce qui concerne le déroulement des instructions).

La programmation procédurale structurée marche très bien pour concevoir de petites applications (- de 5000 lignes). D ’autres approches, notamment la conception objet, seront vues plus tard dans le cursus pour les applis plus importantes. Note : le code de la navette spatiale américaine fait plus de 1.000.000 de lignes...

Syntaxe, expressions régulières Pas de langage sans syntaxe (ou orthographe) Nous utiliserons une forme restreinte des « expressions régulières » pour définir précisément la syntaxe autorisée, particulièrement en Ada. Exemple : identifiant ::= lettre { [ _ ] / lettre | chiffre / } Ce qui signifie qu ’un identifiant commence forcément par une lettre et se continue par une suite, éventuellement vide, de lettres et/ou chiffres, qui peuvent chacun être précédé d'un "blanc souligné".

Symboles formant les expressions rationnelles ::= introduit l ’expression rationnelle qui définit la syntaxe associée au concept;  [ ] délimitent une sous-expression facultative; { } délimitent un motif qui peut être répété; … désigne un terme identique au terme précédent; | (barre verticale) "ou bien" dans une énumération; \ \ délimitent une série d'option d'options parmi lesquelles il faut choisir une; en_gras dénote un mot réservé (mot clé) de ADA ou un symbole à prendre littéralement.

Premier programme Nom de l ’unité/programme bonjour Déclaration de nb : entier Déclaration de variable Connecteur séquence d ’instructions seq saluer demander nombre afficher nombre Nom de bloc d ’instructions sortir("entrer votre nombre : ") entrer(nb) sortir("bonjour") sortir("le nombre est : ") sortir(nb) instruction Bloc d ’instructions

Premier programme en Ada with text_io, integer_text_io; use text_io, integer_text_io; procedure bonjour is nb : integer; begin -- saluer put_line("bonjour"); -- demander nombre put("entrez votre nombre : "); get(nb); -- afficher nombre put("le nombre est : "); put(nb); end bonjour; -- le rappel du nom d'unité est facultatif

Instructions Un programme est composé d ’instructions. Une instruction peut elle-même contenir d ’autres instructions. Par défaut, les instructions s'exécutent en séquence. En Ada les instructions sont terminées par un point virgule (facultatif en AP). Une instruction peut s ’étendre sur plusieurs lignes. Pas de différence entre majuscules et minuscules

Commentaires Les commentaires ont pour objectif de faciliter la compréhension du programme. Les noms de bloc d ’instructions AP seront toujours reportés comme commentaires en Ada. Des commentaires supplémentaires seront évidemment les bienvenus. Les commentaires débutent par -- et se poursuivent jusque la fin de ligne.

Variables, affectation Chaque donnée (nombre, caractère, …) que l ’on veut réutiliser ultérieurement doit être stockée dans un emplacement mémoire appelé "variable". Les 2 langages, AP et ADA, sont "fortement typés" : une variable ne peut contenir qu ’une seule sorte ou "type" de données (soit un caractère, soit un nombre entier, …)

L ’affectation est une instruction. Elle sera noté := en AP et en ADA. Les variables utilisées par un programme doivent être "déclarées" avant leur utilisation : on précise leur nom et l ’unique type de valeur qu ’elles peuvent contenir. L ’affectation est une instruction. Elle sera noté := en AP et en ADA. nb := 2; -- range la valeur 2 dans nb

Types de base Nous utiliserons 4 types de base entier (Ada : integer) : nombres sans virgule flottant (Ada : float) : nombres avec virgule. Un flottant s'écrit toujours :flottant ::= chiffre+ "." chiffre+ ex : 0.0 0.5 123.45 ctr-ex : .0 3 324. Notation exponentielle pour les flottants 1.23e2 = 1.23E2 = 1.23 * 10^2 = 123.0

caractère (Ada : character) : 'A', 'b', '?', ... booléen (Ada : boolean) : valant Vrai ou Faux (Ada : True, False)

Opérations arithmétiques de base Les 4 opérations + - * / Attention, sur des entiers le résultat est arrondi à l ’entier le plus proche nb := 3 / 2; -- nb contient 1 Il est interdit de mélanger des types différents dans une opération quelconque nbf := 3.0 / 2; -- erreur de compilation nbf := 3.0 / 2.0; -- ok, nb vaut 1.5

Reste et modulo de la division entière de 2 nombres : rem, mod nb := 3 rem 2; -- nb vaut 1 nb := 10 mod 5; -- nb vaut 0 Exponentiation (entiers et flottants) : ** nb := 3 ** 2; -- nb vaut 9 fonctionne aussi sur les flottants Valeur absolue (entiers et flottants) : abs() nb := abs(-3); -- nb vaut 3

Entrées/sorties sur les types de base Lecture (ou saisie) d ’une donnée AP : entrer (nom_de_variable) Ada : get (nom_de_variable); Ada permet de spécifier le nombre maximum de caractères (largeur de champ) à prendre en compte : get (nom_variable, largeur_champ) Le programme s ’arrête, l ’utilisateur tape une donnée au clavier suivie d ’un retour chariot. Une donnée est toujours saisie dans une variable.

Ecriture (ou sortie) d ’une donnée AP : sortir (variable | donnée ) Ada : put (variable | donnée ); Ada permet de donner un format à la donnée : nombre de chiffres, … entiers : put (variable | donnée , nb_chiffres); flottants : put (variable | donnée, nb_chiffres_avant_virg , nb_chiffres_apres_virg , nb_chiffres_exposant);

Exemples de sorties put(123); put(12345678); put(123,2); put('A'); put('A'); -- écrit 123 12345678123AA Note : le format par défaut des entiers est 8 caractères de large. Un format trop petit est ignoré. put(123.456); -- écrit 1.23456E2 put(123.456, 2, 2, 0); -- écrit 123.45 Note : par défaut les flottants sont écrits en notation scientifique. Si la mantisse est trop grande, le format est partiellement ignoré.

Inclure des bibliothèques En Ada, les entrées/sorties ne sont pas intégrées au langage : il est nécessaire d ’inclure les bibliothèques spécifiques qui contiennent ces instructions optionnelles. Text_io : saisie et sortie de caractères Integer_text_io : d ’entiers Float_text_io : de flottants Note : d'autres constructions peuvent nécessiter d'inclure d'autres bibliothèques...

Inclusion de biblis : with bibli_1, bibli_2; les instructions contenues dans la bibli sont accessible en les préfixant du nom de la bibli: with text_io; procedure aaa is begin text_io.put('A'); end aaa;

Si on utilise fréquemment une instruction en provenance d'une bibli, le préfixage devient vite fatiguant, on le supprime avec "use" : with text_io; use text_io; … put('A');

Pourquoi devoir préfixer par défaut ? Utile si 2 biblis apportent des instructions de même nom bibli1 programme mon_put with bibli1, bibli2; ... mon_put(123); lequel est-ce ? bibli2 mon_put

Conversions de types AP et Ada sont fortement typés : on ne peut pas mélanger des données de types différents dans une même expression. Il est nécessaire de pouvoir convertir des données d ’un type dans un autre : conversion de type (ou changement de type ou transtypage). conversion_de_type ::= nom_de_type ( donnée | variable ) nb := integer(3.5); -- nb vaut 3

Structures de contrôle du flux d'instructions Il est souvent nécessaire que l'état d'un programme (contenu des variables, …) puisse influer sur l'ordre d'exécution des intructions. C'est le rôle des structures de contrôle de préciser comment et à quelles conditions l'ordre d'exécution des instructions peut varier.

Structure d'alternative AP si condition bloc "si" instructions bloc "sinon" instructions Les instructions du bloc "si" ne sont exécutées que si la condition est vérifiée. Les instructions du bloc "sinon" sont exécutées seulement dans le cas contraire.

Structure d'alternative ADA if condition then bloc instr. else -- facultatif end if; if condition_1 then bloc instr. elsif condition_2 then elsif condition_3 then ... else -- facultatif end if;

Expressions booléennes, opérateurs relationnels Une condition est une expression booléenne. Elle est vérifiée si elle vaut vrai (true). Opérateurs relationnels : <, <=, >, >=, =, /= et (and), ou (or), non (not) ou exclusif (xor) et alors (and then), ou sinon (or else) dans (in), dehors (not in)

Structure de cas AP cas : expression expr_1 expr_2 ... expr_n défaut bloc_1 instructions bloc_2 instructions bloc_n instructions bloc_défaut instructions

La valeur de expression doit correspondre à une et une seule des valeurs données dans les losanges. Seul le bloc situé sous la bonne valeur est exécuté. Après exécution de ce bloc, on sort de la structure de cas, les autres blocs sont ignorés.

Structure de cas ADA case expr is when \ expr | interv_discr | others \ {| …} => statement {…} {…} end case; Exemple : case nb is -- nb est une variable entiere when 1 | 2 | 3 => put("1,2 ou 3); new-line; when 5..10 => put("entre 5 et 10"); new_line; when others => null; -- instruction vide

3 règles à retenir pour l'ensemble des choix : il doit être exhaustif (d'où l'utilisation fréquente de others) il ne doit pas y avoir de répétitions les choix doivent être "statiques" (c'est à dire évaluables lors de la compilation)

Expression statique ou dynamique Une expression "statique" est une expression dont la valeur peut être calculée lors de la compilation du programme. Une expression "dynamique" dépend, à priori, de l'exécution du programme. Ex : le contenu d'une variable est susceptible de changer lors de l'exécution d'un programme (par définition…). Par conséquent, toute expression qui comporte une variable est considérée comme dynamique, même si l'auteur du programme sait que le contenu de la variable en question ne sera pas changé !

Phases d'écriture d'un programme Écriture du source Compilation : traduction du source en objet Préprocesseur (nettoie le source) Compilateur (traduit en assembleur) Assembleur (traduit en code machine) Éditeur de liens : traduction de l'objet en exécutable, regroupement en un seul fichier des différents modules qui constituent le programme Chargeur : installe l'exécutable en mémoire, puis l'exécute

Structure de boucle AP tantque condition nom_bloc instructions Le bloc d ’instruction est exécuté tant que la condition est vraie.

Structure de boucle ADA while condition loop bloc_instr end loop; Exemple : while (nb < 12) loop put(nb); nb := nb + 1;

Boucle « pour » AP pour variable de boucle nom_bloc variable dans envers a..b instructions facultatif intervalle Le bloc d ’instruction est exécuté autant de fois que d'éléments dans l ’intervalle discret [a..b]. La boucle "pour" n'est à utiliser que si on connait à l'avance le nombre de tours à effectuer.

La variable de boucle : Attention : Ne doit pas être déclarée. Masque toute autre variable déjà déclarée de même nom, dans tout le sous-arbre du bloc d'instruction. Contient la valeur courante dans l ’intervalle. Est considérée comme une constante dans le bloc d ’instruction : on ne peut pas la modifier. Attention : Si b < a, l ’intervalle est vide, on ne le parcourt pas ! Si on souhaite parcourir l ’intervalle à l ’envers, utiliser le mot-clé « envers ».

Boucle « pour » ADA for variable in reverse intervalle loop bloc_instr end loop; Exemples : for i in 1..10 loop put(i); end loop; for i in character'('A')..character'('Z') loop put(i); end loop;

-- n ’affiche rien ! for i in 10..1 loop put(i); end loop; -- affiche de 10 à 1 for i in reverse 1..10 loop -- affiche 1 à 10, puis 3 ! i := 3; for i in 1..10 loop put(i); end loop; -- ne compile pas ! i := i + 1;

Boucle avec sortie loop instr {…} exit when condition; -- facultatif end loop;

Exemple : -- compte une séquence de nombres terminée par 0 -- nb et compteur sont des variables entières put("Entrez vos nombres, terminez par 0"); new_line; loop get(nb); exit when nb = 0; compteur := compteur + 1; end loop; put("Decompte = "); put (compteur); new_line;

De plus, les boucles ADA peuvent recevoir un identifiant de boucle, qui peut se combiner avec l'instruction exit. Bcl1: loop {…} Bcl2: loop exit Bcl1; end loop;

Résumé des différentes structures de boucle en ADA [id:] [while bool_expr | for id in [reverse] discrete_range] loop statement {…} end loop [id]; exit [loop_id] [when bool_expr];

Bloc déclaratif AP Il peut être utile de déclarer des variables pour un usage momentané : leur portée peut être réduite au bloc d'instruction où elles servent. En AP : nom_bloc var1, var2 : type1; var3, var4, var5 : type2; bloc_instr

Bloc déclaratif ADA [id:] declare declarative_item begin handled_statement end [id]; handled_statement ::= statement {…} [exception_handler]

Exemple de bloc déclaratif : Le "handled_statement" est un simple bloc d'instructions, qui se termine par un traitant d'exceptions : des instructions servant à rattraper d'éventuelles erreurs lors de l'exécution. Exemple de bloc déclaratif : declare tmp : integer; begin tmp := A; A := B; B := tmp; end;

Types tableaux De nombreuses applications nécessitent de mémoriser des séries de variables : composantes de vecteurs ou de matrices, tables de température ou de pression, … On peut stocker ces données dans une structure simple appelée tableau, à l'intérieur de laquelle chaque donnée est associée à un ou plusieurs numéros appelé indices. On accède à une donnée en rappelant le nom du tableau et son ou ses indices.

Tableaux AP Représentation d'un tableau à 1 dimension : indices 16 14 13 12 1 2 3 4 5 6 7 8 temperatures nom du tableau temperatures(1) temperatures(6) variables Une variable de type tableau doit être déclarée, en précisant le type unique des valeurs contenues dans le tableau et les bornes du tableau : temperatures : tableau (1..8) d'entiers;

Tableaux ADA On peut les déclarer comme des variables : tab1 : array(1..8) of integer; tab2 : array(1..8) of integer; Attention, tab1 et tab2 sont considérés comme étant de types différents : pas d'affectation possible au niveau tableau sans une conversion. pas de possibilité de les passer en paramètre à une fonction ou à une procédure (voir plus loin).

Pas de problème d'affectation, ni de passage en paramétre. En général, on déclare un type tableau avant de déclarer les variables : type tab_int_8 is array(1..8) of integer; tab1, tab2 : tab_int_8; Pas de problème d'affectation, ni de passage en paramétre. Les déclarations de types se placent dans la partie déclarative d'une unité de compilation ou d'un bloc déclaratif. Nous utiliserons la même convention en AP.

Exemple sur les tableaux max_tab max : entier type tab20int est tableau(1..20) d'entiers tab : tab20int; seq saisie déterminer_max afficher_max pour seq Sortir(max) i dans 1..taille Entrer(tab(i)) initialiser Comparer avec tous pour max := tab(1) i dans 2..taille si max < tab(i) max := tab(i)

-- comparer avec tous for i in 2..Taille loop if max < tab(i) then max := tab(i); end if; end loop; -- afficher max put("le max est :"); put(max); new_line; end max_tab; Procedure max_tab is Taille : constant := 20; type Tab20Int is array(1..Taille) of integers; max : integer; tab : Tab20Int; begin -- saisie put_line("entrez le tableau"); for i in 1..Taille loop get(tab(i)); end loop; -- determiner max -- initialiser max := tab(1);

Règles, opérations et attributs de tableaux un tableau ne peut contenir qu'un seul type d'éléments; on ne peut pas utiliser un indice en dehors des bornes définies à la déclaration du tableau, sous peine de "plantage"; on peut affecter un tableau à un autre tableau s'ils sont compatibles : même taille, même type d'éléments (une conversion de type peut être nécessaire) : a, b : tab_int; a := b;

On peut concaténer des tableaux avec & Un tableau connaît ses bornes : a'first, a'last l'intervalle des indices corrects : a'range (équivalent à a'first..a'last) la longueur de cet intervalle : a'length On peut comparer des tableaux (<, >, <=, >=) selon le principe de l'ordre lexicographique quand tout est égal, un tableau plus court est considéré comme plus "petit" ou "avant" dans l'ordre. On peut concaténer des tableaux avec & a(1..10) := b(1..5) & c(2..6);

Les tranches On peut extraire un "morceau" de tableau, il suffit que les indices soient contigus : a, b : tab_int; a(1..5) := b(6..10); Attention lors d'une telle affectation à vérifier que les 2 tranches soient de même taille. Les tranches peuvent se superposer : a(1..5) := a(2..6) -- décale la tranche 2..6 d'une case

Les agrégats Permettent d'initialiser les tableaux : declare type TABLE is array(4..9) of integer; t : TABLE := (1, 2, 3, 4, 5, 6); begin t := TABLE'(4 | 6 => 1, others => 0); t := TABLE'(4..7 => 2, 8..9 => 3); end;

Les chaînes de caractères AP Les chaînes de caractères sont des données très utilisées : il existe un type chaine prédéfini. Le type chaine est un en fait un tableau de caractère, avec une syntaxe raccourcie : ch1, ch2 : chaine(1..8); -- conseillé ch3 : tableau(1..8) de caractères; -- déconseillé Attention, dans l'exemple précédent ch1 et ch2 sont de même type, mais pas ch3, bien que ces 3 objets soient représentés de manière identique en mémoire.

Les chaînes de caractères ADA En ADA, on dispose du type STRING : ch1, ch2 : string(1..8); -- conseillé ch3 : array(1..8) of character; -- déconseillé Comme en AP, ch1 et ch2 sont de même type, mais pas ch3, bien que ces 3 objets soient représentés de manière identique en mémoire. Accès : ch1(1) := ch2(8); ch1(1..5) := ch2(1..2) & ch2(2..4);

Entrées/sorties sur les chaînes get(ch1); -- attention, taper exatement 8 caractères!!! get_line(ch1, lng1); -- le nombre de cars tapés sera -- rangé dans lng1, qu'il faut déclarer (var. entière). Sortie : put(ch1); put_line(ch1); -- passe à la ligne suivante -- !!! Put_line ne fonctionne qu'avec des chaînes !!!

Attributs relatifs aux chaînes et aux caractères Image : renvoie la représentation d'un type sous forme de chaîne. Value : renvoie la "valeur" d'une chaine. Pred, Succ : le précédent et le suivant. Pos, Val : la position et son inverse Integer'image(300) = "300" Character'image('z') = "z" Integer'value("300") = 300 Character'value(" 'z' ") = 'z' Character'pred('2') = '1' Character'succ('A') = 'B' Character'pos('0') = 48 Character'val(48) = '0'

Les tableaux à plusieurs dimensions Array_type_def ::= array (discrete_range {, …}) of type Exemple : type MATRICE is array(1..10, 1..10, 1..10) of float; type TAB_2D is array(1..5, -1..0) of integer; m1, m2 : MATRICE; t : TAB_2D;

Accès : Agrégats : m1(1,1,1) := m2(1,1,10); get(m1(i,j,k)); t := TAB_2D'((1,1), (2,2), (3,4), (4,5), (5,5)); t := TAB_2D'((1,1), (2,2), others => (3,3)); t := TAB_2D'(1 | 3 => (1,1), others => (0,0 ); t := TAB_2D'(others => (-1 => 1, others => 0)); t := TAB_2D'(others => (others => 0));

Attributs : first(i), last(i), range(i), length(i) où i est le numéro de la dimension : t'first(1) = 5 t'first(2) = -1 t'range(1) = 1..5 t'range(2) = -1..0 first(1), last(1), range(1), length(1) se notent aussi first, last, range, length.

Les sous-programmes : procédures et fonctions Subprogram_body ::= subprogram_spec is {declarative_item} begin handled_statement end; Subprogram_spec ::= procedure [parent_name.]id [formals] | function [parent_name.]id [formals] return subtype_name

Formals ::= Exemples : (id {, id} : [in | in out | out] subtype_name [:= expr] {; …}) Exemples : procedure efface_ecran is … procedure passe_lignes (x : integer) is … function lire_entier return integer is … function perimetre (rayon : float) return float is … procedure peri_surf (rayon : in float; perimetre, surface : out float) is ...

Un sous-programme est exécuté à chaque appel Lors de l'appel, le paramètre formel prend la valeur du paramètre effectif Paramètre effectif Paramètre formel Flux des instructions procedure exemple is … begin passe_lignes(2); N := 10; passe_lignes(N); end exemple; procedure passe_lignes(X : integer) is begin for cpt in 1..X loop new_line; end loop; end passe_lignes; Spécification de sous-programme Appels de sous-programme

Les sous-programmes servent : à éviter les répétitions inutiles de code, lorsqu'un ensemble d'instructions sert à plusieurs endroits. à structurer le programme en isolant des fonctionnalités spécifiques dans des sous-programmes séparés : c'est comme si on ajoutait de nouvelles instructions de base. Les sous-programmes doivent : éviter au maximum d'utiliser des variables déclarées en dehors d'eux-mêmes : utiliser les paramètres pour communiquer les données. conserver une taille raisonnable pour pouvoir être compris et mis au point sans pb : au maximum 60 lignes

Position des procédures et fonctions 1) Dans des fichiers séparés, un par procédure/fonction : On les inclus dans le programme principal avec "with nom_proc" (le fichier doit avoir le même nom). La clause "use" n'est pas nécessaire. Elles ne connaissent pas les types/variables du programme principal ! 2) Dans la procédure principale, dans la section déclarative (là où on place les déclarations de types, de variables, …) Elles connaissent les déclarations placées avant.

Déclarations préliminaires Une procédure ne peut en appeler une autre qui soit déclarée après : C'est génant, obligation de bouger le morceau de code à la bonne place. C'est parfois inextricable : si p1 appelle p2 et p2 appelle p1, bouger le code n'est pas la solution. On recourt à une déclaration préliminaire, que l'on place le plus haut possible : Même syntaxe qu'une déclaration ordinaire, sauf qu'on s'arrête au "is", qui est remplacé par ";" procedure lire_somme (s : out integer) ; -- decl. prelim.

Paramètres et valeur de retour Les paramètres des sous-programmes et la valeur de retour des fonctions servent à échanger des données avec le programme appelant. dans la déclaration du ss-prog : paramètres formels dans l'appel au ss-prog : paramètres effectifs Une procédure ne retourne pas de valeur, mais elle peut prendre des paramètres qui peuvent être modifiés. Une fonction retourne obligatoirement une unique valeur. Ses paramètres ne peuvent être modifiés (penser aux fonctions mathématiques).

La valeur d'une fonction est retournée par l'instruction : return expression; Si le flux d'instruction atteint le "end" final d'une fonction sans rencontrer de "return", l'exception "program_error" est levée. On peut utiliser return ; dans une procédure : on quitte la procédure en cours et on revient à l'appelant (rien n'est retourné).

Les modes des paramètres : in : lecture seule (comme une constante) out : écriture seule in out : lecture / écriture (comme une variable) Si on n'indique pas de mode, c'est le mode "in" par défaut. Une fonction a toujours ses paramètres en mode "in". Attention, en mode "out" on ne peut pas consulter (lire) la valeur du paramètre, ce qui peut être déconcertant.

Procedure lire_somme (s : out integer) is -- met dans s la somme des entiers saisis par l'utilisateur n, tmp : integer := 0; begin put_line("entrer vos entiers (terminer par -1)"); get(n); while n /= -1 loop -- s := s + tmp; est interdit (car mode "out") tmp := tmp + n; end loop; s := tmp; -- on a seulement le droit d'ecrire dans s end;

Paramètres par défaut Les paramètres peuvent recevoir une valeur par défaut : on n'est alors pas obligé de les fournir. Dans text_io, "new_line" est déclaré ainsi : procedure new_line (spacing : positive := 1) is … On peut appeler new_line sans paramètre, dans ce cas new_line passe 1 seule ligne.

Portée et visibilité Portée d'une entité (type, variable, constante…) : partie du code où sa déclaration est effective, c'est à dire où l'entité existe. Visibilité d'une entité : partie du code où l'entité est accessible. La visibilité est toujours incluse dans la portée : on ne peut accéder qu'à une entité qui existe. La visibilité est souvent plus réduite que la portée : masquages temporaires par des entités portant le même nom et plus locales.

Toute entité déclarée dans la partie déclarative d'un sous-programme ou d'un bloc "declare" : n'est visible que dans ce sous-programme ou ce bloc. disparaît une fois le sous-programme ou le bloc terminé.

With … ; use … ; Procedure portee_visibilite is A : constant := 123; B : integer := A + 1; -- debut de la visibilite de A C : integer := 12; -- debut de la visibilite de B function f (B : character := integer'image(C)(2)) -- debut visibilite C return integer is C : integer := 0; -- debut de la visibilite de B de f begin -- debut de la visibilite de C de f return character'pos(B) + C; end; begin -- retour de la visibilite de B et C après masquage dans f put(A); put(f('A')); put(f); put (B); put(C); put(integer'image(C)); -- affiche : 123 65 49 124 12 12 end portee_visibilite;

Récursivité Un sous-programme peut s'appeler lui-même : function factorielle(N : integer) return integer is begin if N = 0 then return 1; -- condition d'arrêt else return N * factorielle(N - 1); -- appel récursif end if; end factorielle;

CE QU'IL FAUT COMPRENDRE : chaque niveau d'appel récursif crée sa propre copie des paramètres formels et des variables locales. lors du retour d'un appel récursif on retrouve donc intactes les valeurs des paramètres et des variables (sauf si elles ont été passées récursivement en mode "out", bien entendu !) dans le code du sous-programme, il doit y avoir une alternative où on ne relance pas un appel révursif, sinon la récursion est infinie (concrètement ça plante après avoir saturé la mémoire de la machine).

Plusieurs sous-programmes peuvent s'appeler les uns les autres : function syracuse1(N : integer) return integer is begin if N /= 1 and N % 2 = 0 then return syracuse1(N / 2); elsif N /= 1 then return syracuse2(N); else return N; end if; end; -- conjecture de syracuse get(N); put(syracuse1(N)); function syracuse2(N : integer) return integer is begin if N /= 1 and N % 2 /= 0 then return syracuse2(3 * N + 1); else return syracuse1(N); end if; end;

Comment aborder un problème récursif ? Attention, dans l'exemple précédent on a besoin de déclarations préliminaires pour compiler. Comment aborder un problème récursif ? Il faut avoir l'intuition qu'il se traite récursivement. Si on ne sait pas le traiter de manière classique, ça ne coûte rien de se poser la question… Il faut déterminer sur quelle "variable" (ex: N) on fait la récurrence. Il faut avoir une solution d'arrêt de la récursivité (quand N est petit). Supposant avoir la solution au rang N-1, trouver ce qu'il faut faire pour passer au rang N.

Retour sur les types Type / Sous-type une déclaration de type est statique type mon_entier is range 1..100; -- ok N : integer := 100; -- variable, non statique type mon_entier2 is range 1..N; -- interdit !!! une déclaration de sous-type peut être dynamique, elle s ’appuie sur un type pré-existant N : integer := 100; -- variable subtype mon_entier3 is integer range 1..N;

Types entiers with ada.text_io; use ada.text_io; procedure test_instanciation is type mon_entier is range 1..100; package mon_entier_io is new ada.text_io.integer_io(mon_entier); use mon_entier_io; -- autorise les E/S sur ce nouveau type n : mon_entier; begin put("entrer un entier : "); get(n); -- raise DATA_ERROR si pas dans 1..100 put(n * 2); -- raise CONSTRAINT_ERROR si pas dans 1..100 end;

Types énumératifs with ada.text_io, ada.integer_text_io; use ada.text_io, ada.integer_text_io; procedure test_type_enumere is type JOUR is (LUNDI, MARDI, MERCREDI, JEUDI, VENDREDI, SAMEDI, DIMANCHE); package jour_io is new ada.text_io.enumeration_io(jour); use jour_io; n : integer; begin put("entrer un entier : "); get(n); put(JOUR'VAL(n mod 7)); end;

Attributs pour types énumérés jour'first # LUNDI jour'last # DIMANCHE jour'succ(LUNDI) # MARDI jour'pred(MARDI) # LUNDI jour'pos(LUNDI) # 0 jour'val(0) # LUNDI jour'value("LUNDI") # LUNDI jour'image(LUNDI) # "LUNDI"

Type booléen Types flottants type boolean is (FALSE, TRUE); -- type énuméré Types flottants On peut préciser le nombre de chiffres significatifs : digits N = précision au 1/10^N On peut limiter l'intervalle des valeurs possibles type REEL is digits 6; type VOLTAGE is digits 5 range 0.0 .. 1.0E+9; Attributs type FL is digits D range I..S FL'digits # D FL'first # I FL'last # S E/S : instancier ada.text_io.float_io(nom_type)

Types tableaux contraints / non contraints type vecteur1 is array(1..10) of float; v1, v2 : vecteur1; toutes les variables de type vecteur1 ont mêmes dimensions tableaux non contraints type vecteur2 is array(integer range <>) of float; v1 : vecteur2(1..10); v2 : vecteur2(-5..15); v1 et v2 sont de même type, mais de dimensions différentes on doit fournir les bornes lors d'une déclaration de variable de type vecteur2

Intérêt des tableaux non contraints Quand ils apparaissent en tant que paramètres formels, il n'est pas nécessaire de préciser leur taille (car ce n'est pas une déclaration de variable) : Procedure truc(v : in out vecteur2) is … On utilise les attributs de tableau pour connaître l'intervalle des indices. Rappel : les chaînes de caractères En fait le type STRING est simplement un type tableau de caractères non contraint : type STRING is array(integer range <>) of character;

Type Article / Enregistrement (record) Si un tableau est une collection de variables de même type accessibles via leur numéro, un article est une collection de variables de types qui peuvent être différents, accessibles par leur nom. Les différentes variables de l'article s'appellent des champs. La variable de type article possède son propre nom, on accède à ses champs par la notation pointée : nom_d_article.nom_de_champ

Exemple : type MOIS is (Janvier, Fevrier, …, Decembre); type DATE is record jour : integer range 1..31; mois : MOIS; an : integer; end record; d : DATE; d := (14, Juillet, 1789); d := (jour => 14, an => 1789, mois => Juillet); d.mois := Mars; d.jour := 12; d.an := d.an + 1;

Type Article avec partie variante type Genre_Figure is (un_cercle, un_point, un_carre); type Point is record X, Y : Integer; end record; type Figure (Sorte : Genre_Figure := un_point) is record Position : Point; case Sorte is when un_cercle => Rayon : Integer; when un_carre => Coin_Inf_Droit : Point; when others => null; end case; F : Figure := (un_point, (10,15)); F := (un_cercle, position => (20, 25), rayon => 50);

Partie variante : comment ça marche ? Entre les différents contructions rendues possibles dans la partie variante, le compilateur calcule celle qui occupe le plus de place et alloue cette place à la variable. Dans l'exemple, c'est le carré qui prend le plus de place. Si on charge la variable avec un point ou un cercle, une partie de la mémoire reste inutilisée, tout simplement. On ne peut changer le discriminant (variable qui sélectionne la partie variante) que si on change tout le reste de l'article.