# Programmation Pascal/Version imprimable

* Si vous imprimez cette page, choisissez « Aperçu avant impression » dans votre navigateur, ou cliquez sur le lien Version imprimable dans la boîte à outils, vous verrez cette page sans ce message, ni éléments de navigation sur la gauche ou en haut.
* Cliquez sur Rafraîchir cette page pour obtenir la dernière version du wikilivre.
* Pour plus d'informations sur les version imprimables, y compris la manière d'obtenir une version PDF, vous pouvez lire l'article Versions imprimables.
Une version à jour et éditable de ce livre est disponible sur Wikilivres, une bibliothèque de livres pédagogiques, à l'URL : https://fr.wikibooks.org/wiki/Programmation_Pascal

# Introduction

* Wikipédia propose un article sur : « Pascal (langage) ».
Le langage de programmation Pascal (dont le nom vient du mathématicien français Blaise Pascal) a été inventé par Niklaus Wirth dans les années 1970. Il a été conçu pour servir à l'enseignement de la programmation de manière rigoureuse mais simple, en réaction à la complexité de l'ALGOL 68. Le Pascal est donc principalement utilisé dans l'enseignement et notamment dans les universités.
Ce livre explique comment implémenter un algorithme impératif en Pascal pour ensuite l'exécuter sur une machine. Ce livre n'enseigne pas comment créer des algorithmes et résoudre des problèmes mais comment, à partir d'un algorithme impératif créer un programme informatique.
Prérequis cognitif :
* Algorithmique impérative, nécessaire pour créer des algorithmes avant de les implémenter.
* Utilisation simple de l'ordinateur (édition de texte, shell simple)
Prérequis matériels :
* un ordinateur, n'importe lequel et de n'importe quelle architecture du moment que les prérequis logiciels sont respectés.
Prérequis logiciels :
* un éditeur de texte : le plus simple suffit. Un Environnement de développement pascal serait un plus.
* un compilateur Pascal fonctionnant pour cet ordinateur.
Exemple d'environnement de travail classique :
* Lazarus (créé en... Pascal) pour éditer le code source
* Free Pascal comme compilateur
* Le tout sous le système d'exploitation Linux, Microsoft Windows, ou Mac OS
* Sur un ordinateur de type PC ou Macintosh.

# Environnement de développement

Un simple éditeur de texte et un compilateur Pascal en ligne de commande peuvent suffire à un usage simple. Cependant l'utilisation d'un environnement de développement intégré facilite les tâches, notamment le débogage des programmes. Il existe aussi des compilateurs spécifiques pour des applications embarquées (sur téléphone mobile par exemple).

## Lazarus et Free Pascal

* Free Pascal est un compilateur multiplateformes (PC, Mac, Téléphone mobile, Consoles...) pour divers processeurs (x86, ARM, PowerPC...) en 32 et 64 bits.
* Lazarus est un environnement de développement intégré pour la création rapide d'application (RAD : Rapid Application Development).
* Lazarus : https://www.lazarus-ide.org/
* Free Pascal : https://www.freepascal.org/
* Wiki à propos de Lazarus et Free Pascal https://wiki.freepascal.org/

## MIDletPascal

* MIDletPascal est un environnement de développement intégré et un compilateur fait pour la création d'applications sur téléphones mobiles. Le compilateur génère du bytecode Java pour JavaME, qui peut tourner sur différents appareils.
* https://sourceforge.net/p/midletpascal/code/HEAD/tree/

# Un premier programme
## Le fichier source

Le classique Hello world en Pascal, enregistrez le code suivant dans un fichier texte nommé hworld.pas :
Compilez ce programme, et lancez-le. Le message suivant doit normalement s'afficher :

## Le code source en détail

Le code source commence par déclarer qu'il s'agit d'un programme nommé hworld
Remarque:
Le nom du programme pourrait être Hello_World et comporter ici 11 caractères par exemple, même sous DOS : la chaine de caractères n'est pas trop longue car il ne s'agit pas là du nom du fichier DOS en format 8.3, mais simplement du nom du programme pour le compilateur. Par contre, le fichier quant à lui devra ne comporter que 8 caractères, par exemple hworld.pas.
Début de la routine principale, appelée au démarrage du programme.
Appel à la procédure writeln (write line) pour afficher la chaîne Hello world! sur la sortie standard.
Fin de la routine principale et du programme.
Donc,
se compile et s'exécute très bien avec n'importe quel compilateur Pascal, y compris les anciens depuis Turbo Pascal 3 sous DOS.

# Structure d'un programme
## Instructions et blocs

Une instruction séquence d'instructions regroupe plusieurs instructions en une seule. Celle-ci commence par le mot clé begin et se termine par end. Le ; sert à séparer deux instructions. Voici un exemple :
Cette instruction Pascal sera traduite par un bloc en Java

## Catégorie

Un fichier source Pascal débute toujours par un mot clé indiquant le type de code :
* Un programme, c'est à dire une application indépendante (program) ;
* Un module utilisable dans un programme ou un autre module (unit).
Ce mot clé doit être suivi d'un identifiant (un nom) afin de pouvoir faire référence à ce module ou ce programme.
Afin que le compilateur trouve les modules à partir de leur nom, il faut que le nom du fichier source soit identique : un module nommé par :
doit être enregistré dans un fichier nommé my_unit.pas.

### Exemple 3 : un programme utilisant le module de l'exemple 2

Le mot clé uses spécifie la liste des modules utilisés :

## Compilation

L'extension des fichiers produits par la compilation varie selon la plateforme utilisée et le compilateur (natif ou P-code).
Cependant, la plupart des compilateurs ne gère pas la compilation en chaîne : chaque module et programme doit être compilé séparemment et deux modules ne peuvent donc s'utiliser mutuellement.

## Commentaires

Les commentaires sont encadrés par les accolades :
Alternativement, on peut utiliser les parenthèses-étoiles :
Ce qui était plus pratique avec les anciens claviers ne comportant pas les accolades.
Le compilateur Turbo Pascal utilise certains commentaires spéciaux pour préciser des directives de compilations. Ceux-ci débutent par un caractère $, par exemple {$R-,I-} pour désactiver la vérification des erreurs d'intervalle (Range errors) et des erreurs d'entrée-sortie (I/O errors).

## Structure générale d'un module

Le module est divisé en deux grandes parties :
* La partie interface expose les fonctions, procédures, variables et types publiques, c'est à dire accessibles depuis les modules et programmes qui utilisent ce module.
* La partie implementation contient le code implémentant les fonctions et procédures publiques, et peut contenir d'autres variables, types, fonctions et procédures internes au module.

# Variables

Une variable sert à stocker une donnée. Elle a un nom, et un type (entier, chaîne de caractères, tableaux d'entiers, ...).

## Déclaration des variables

Les variables peuvent être déclarées en début de programme ou de module. Dans ce cas, elles sont globales, car accessibles à toutes les procédures et fonctions qui suivent.
Les variables peuvent également être déclarées en début de procédure ou de fonction, où elles seront locales à celle-ci.
Les déclarations de variables commencent par le mot clé var, puis chaque variable est déclarée selon la syntaxe suivante :
Il est également possible de regrouper les variables ayant le même type :
Par exemple :

## Affectation

Pour affecter une valeur constante ou le résultat d'une expression à une variable, il faut utiliser l'opérateur := (caractère deux-points suivi du caractère égal).
Par exemple :

## Affectation à la déclaration

Il est possible d'affecter une valeur à la déclaration d'une variable, en utilisant l'opérateur égal ( = ), le caractère deux-points étant déjà utilisé pour déclarer le type :

# Procédures et fonctions

Une procédure ou une fonction est une sous-routine, en général appelée plusieurs fois. Ceci permet de regrouper un code utilisé plusieurs fois, de diviser le programme en sous-programmes.

## Différences procédure/fonction

Procédures et fonctions acceptent des paramètres, seule une fonction retourne une valeur. La procédure n'en retourne pas.

## Déclaration d'une procédure

La déclaration d'une procédure se fait avec le mot clé procedure suivi du nom de la procédure, et de la liste des paramètres entre parenthèses. Cette liste de paramètres est déclarée avec la même syntaxe que les variables.
Ensuite, les variables locales sont déclarées, puis les instructions sont comprises dans un bloc begin ... end;
Par exemple :

## Déclaration d'une fonction

La syntaxe est similaire à celle d'une procédure, excepté que le mot clé utilisé est function et que le type de retour doit être déclaré.
Par exemple :
Retourner une valeur se fait en affectant celle-ci au nom de la fonction.

## Interface et implémentation dans un module

Dans un module, la partie implementation contient le code des sous-routines en utilisant la syntaxe des paragraphes précédant. La partie interface ne reprend que la première ligne.
Par exemple :

## Ordre de déclaration

La compilation en une passe implique que chaque fonction ou procédure appelée doit être définie avant. L'ordre des sous-routines est donc important.
L'exemple suivant produit une erreur de compilation :
L'ordre correct est le suivant :
Cette restriction ne s'applique pas aux sous-routines publiques d'un même module, car elles sont pré-déclarées dans la partie interface.
Il existe des cas où deux procédures s'appellent mutuellement. Aucune ne peut être située avant/après l'autre. Dans ce cas, il faut en prédéclarer une avec le mot clé forward.
Par exemple :

# Dépendances mutuelles et références circulaires
### Dépendances mutuelles et références circulaires

Parfois, on est amené à faire deux unités où chacune fait références aux fonctions de l'autre. Il s'agit d'une dépendance mutuelle. Dans certains cas, cela peut poser des difficultés.

#### Dépendance au niveau implémentation

Pour commencer, il y a un cas où cela marche sans problème, c'est quand la clause uses qui fait référence à l'autre unité se trouve dans la section d'implémentation. Dans ce cas, l'ensemble des déclarations de types, de procédures et de fonctions sont lues dans chacune des deux unités. En effet, ces déclaration se trouve dans la section interface, c'est-à-dire avant que la question de la dépendance mutuelle soit soulevée. Quand, dans l'implémentation, on fait référence à l'autre unité, tous les membres publics sont déjà définis.

#### Dépendance mixte interface-implémentation

Il se peut qu'une unité A fasse référence à une unité B par une cause uses dans sa partie implémentation, tandis que l'unité B fasse référence l'unité A dans sa partie interface. Dans ce cas, le compilateur va d'abord lire l'interface de A parce qu'elle est nécessaire à l'interprétation de l'interface de l'unité B. Par exemple, l'unité B peut proposer des fonctions qui prennent en paramètre un type défini dans l'unité A. Une fois l'interface de B déterminée, le compilateur va s'occuper des implémentations. Par la suite, l'unité A et l'unité B peuvent utiliser dans leur implémentation les fonctions de l'autre. Référence circulaire ou dépendance interface-interface
Maintenant, si l'on fait deux unités qui font référence l'une à l'autre, mais avec une clause uses dans leur interface, on obtient l'erreur de référence circulaire. En effet, pour pouvoir interprêter correctement l'interface d'une unité, il faut que le compilateur ait lu l'interface de l'autre unité, et vice-versa. Certains compilateurs ne génère pas d'erreur dans ces cas-là, mais en Pascal, pour le moment, une telle chose est impossible.

#### Fausse référence circulaire et vraie référence circulaire

Il se peut qu'en réalité, il ne soit pas nécessaire de déclarer la dépendance au niveau de l'interface de l'unité. Dans ce cas, il suffit de déplacer une partie de la clause uses dans la partie implémentation, pour les unités ne faisant appel seulement à ce moment à des procédures, des fonctions, ou à des types déclarés dans d'autres unités. C'est le cas le plus fréquent fort heureusement.
Sinon, c'est généralement que certains objets définis dans une unité A contiennent des champs ou des méthodes utilisant des objets définis dans une unité B, qui eux-même contiennent des champs ou des méthodes utilisant des objets définis dans l'unité A. Par exemple :

##### Solution par la fusion

On peut régler le problème de la référence circulaire en mettant les deux objets dans une seule et même unité et en prédéclarant les types. Cela se fait de la manière suivante :
Bien entendu, il se peut que, de fil en aiguille, on obtiennent des fichiers de code très gros, ce qui est l'inconvénient de cette méthode.

##### Solution par le non-typage

Enfin, on peut résoudre le problème en ne typant pas les champs ou les paramètres et les valeurs de retour des procédures et des fonctions.
Bien que la solution ne soit pas très élégante, elle permet de contourner le problème. Lors de l'appel des fonctions DonneObjetA et DonneObjetB, il faudra faire un transtypage pour avoir un objet bel et bien identifié comme étant de type TObjetA ou TObjetB. Par exemple :

# Créer de nouveaux types
## Déclaration des types

Les déclarations de types commencent par le mot clé type, puis chaque nouveau type est déclaré selon la syntaxe suivante :
Par exemple :
Ensuite, les variables peuvent utiliser ces types :

## Structure

Une structure est appelée record (enregistrement) en Pascal. Ce type regroupe plusieurs données, chacune portant un nom. Elle ne nécessite pas d'allocation de mémoire particulière, au contraire des objets (type class).

### Exemple

Une variable de ce type :
possède deux membres accessibles par l'opérateur point ( . ) :

# Exercices
## Exercice « Fractions égyptiennes »

(Niveau difficile)
Toute fraction peut s’écrire comme une somme de fractions ayant 1 comme numérateur. Cette décomposition est appelée décomposition en fractions égyptiennes. En voici un exemple : 7/8 = 1/2 + 1/3 + 1/24
Écrire un programme Pascal prenant en entrée le numérateur N et le dénominateur D d’une fraction et affiche sa décomposition en fraction égyptiennes.

## Exercice « Nombre premier »

(Niveau moyen)
Écrire un programme qui demande à l'utilisateur de saisir un entier N et qui affiche le énième nombre premier.

## Exercice « Nombres super premiers »

(Niveau moyen)
Un nombre est dit super premier s'il est premier et si, en supprimant des chiffres à partir de sa droite, le nombre restant est aussi premier.
Exemple : Le nombre 59399 est super premier car les nombres 59399, 5939, 593, 59 et 5 sont tous premiers.
Écrire un programme Pascal qui permet de : Saisir un entier n tel que 40000 < n < 100000, Chercher tous les nombres premiers inférieurs ou égaux à n, les afficher à raison d'un nombre par ligne en mentionnant devant chaque nombre super premier la note « super premier ».

## Exercice « Nombres binaires »

(Niveau facile)
On se propose d’écrire un programme Pascal intitulé conversion permettant de saisir un nombre binaire de longueur minimale 2 puis de le convertir en décimal. Pour ce faire, on multiplie la valeur de chaque bit* 2 puissance «le poids du bits (ordre-1)».
N.B : On rappelle qu’un nombre binaire est composé uniquement par des 0 et des 1.
Exemple :
(1001101)2= 1*2$^6$+0*2$^5$+0*2$^4$+1*2$^3$+1*2$^2$+0*2$^1$+1*2$^0$ = 64+0+0+8+4+0+1 = (77)10.

## Exercice « Jeu des allumettes »

(Niveau facile)
Écrire un programme Pascal permettant de simuler le jeu suivant :
Au départ on dispose quelques allumettes sur une table. Chaque joueur peut choisir de prendre 1, 2 ou 3 allumettes en même temps. Le perdant est celui qui retire la dernière allumette.

## Exercice « Nombres colombiens »

(Niveau moyen)
Un nombre colombien, ou auto-nombre, est un entier naturel qui, dans une base donnée, ne peut pas s'écrire sous la forme d'un nombre ajouté à la somme des chiffres de ce nombre. Exemples : 23 n'est pas un nombre colombien, puisqu'il peut être généré par la somme de 16 et de ses chiffres, c’est-à-dire, 23 = 16 + 1 + 6.
20 est un nombre colombien car il n'existe pas une telle somme pour 20.
Écrire un programme Pascal qui permet d’afficher tous les nombres colombiens < 1000.

## Exercice « Nombres vampires »

(Niveau moyen)
Un nombre Vampire est un nombre qui est égal à un produit de ses chiffres.
Exemple : 126 = 21 x 6
Écrire un programme Pascal qui permet de déterminer tous les nombres Vampires de trois chiffres.

## Exercice « PGCD et PPCM »

(Niveau difficile)
Le PGCD de deux nombres entiers M et N supérieurs ou égaux à 2 a pour décomposition en facteurs premiers le produit des facteurs premiers apparaissant à la fois dans la décomposition de M et de N munis du plus petit des exposants trouvés dans la décomposition de M et de N.
Ainsi, si M = 2$^3$ x 3$^4$ x 5$^2$ x 7 et N = 2$^2$ x 3$^5$ x 7$^3$ x 11
alors pgcd (m, n) = 2$^2$ x 3$^4$ x 7
Le PPCM de deux nombres entiers M et N supérieurs ou égaux à 2 a pour décomposition en facteurs premiers le produit des facteurs premiers apparaissant dans M ou dans N munis du plus grand des exposants trouvés dans la décomposition de M et de N.
Ainsi, si M = 2$^3$ x 3$^4$ x 5$^2$ x 7 et N = 2$^2$ x 3$^5$ x 7$^3$ x 11
alors ppcm (m, n) = 2$^3$ x 3$^5$ x 5$^2$ x 7$^3$ x 11
Écrire un programme effectuant les actions suivantes :
* demander deux nombres entiers positifs (a et b) strictement supérieur à 1 à l'utilisateur ;
* déterminer le plus grand des deux nombres (m = max(a,b)) ;
* construire un tableau de tous les nombres premiers inférieurs ou égal à m ;
* construire un tableau de la même taille pour le nombre a donnant l'exposant de chaque nombre premier entrant dans la décomposition en facteurs premiers du nombre a ;
* construire un tableau de la même manière pour le nombre b ;
* créer une fonction prenant en argument le tableau de nombre premiers et un tableau d'exposant et retournant le nombre correspondant ;
* calculer le PPCM par la construction d'un tableau d'exposants en utilisant ceux des nombres a et b, et utiliser la fonction créée précédemment pour afficher le PPCM ;
* calculer le PGCD par la construction d'un tableau d'exposants en utilisant ceux des nombres a et b, et utiliser la fonction créée précédemment pour afficher le PGCD.

## Exercice « Nombres riches »

(Niveau moyen)
Un nombre est riche si un de ses facteurs au moins est répété deux fois ou plus.
Exemples :
4 = 2$^2$
90 = 2 x 3$^2$ x 5
540 = 2$^2$ x 3$^3$ x 5
Écrire un programme Pascal qui affiche tous les nombres riches <1000.

## Exercice « Expression »

(Niveau moyen)
Donner une approche directe pour déterminer la formule de l'expression.
Exemple d’exécution :