| Les candidats doivent être capables de : | Notes et orientations |
|---|---|
| Comprendre ce qu'on entend par un paradigme de programmation | |
| Montrer la compréhension des caractéristiques de plusieurs paradigmes de programmation : | |
| • Bas niveau | Programmation bas niveau : • compréhension et capacité à écrire du code bas niveau utilisant divers modes d'adressage : immédiat, direct, indirect, indexé et relatif |
| • Impératif (Procédural) | Programmation impérative (procédurale) : • Connaissances supposées et compréhension de la programmation structurée (voir détails dans la section contenu AS 11.3) • compréhension et capacité à écrire du code de programmation impératif (procédural) utilisant des variables, des structures, des procédures et des fonctions. Voir détails dans le contenu AS |
| • Orienté objet | Programmation Orientée Objet (POO) : • compréhension de la terminologie associée à la POO (incluant objets, propriétés/attributs, méthodes, classes, héritage, polymorphisme, contenances (agrégation), encapsulation, getters, setters, instances) • compréhension de la façon de résoudre un problème en concevant des classes appropriées • compréhension et capacité à écrire du code démontrant l'utilisation de la POO |
| • Déclaratif | Programmation déclarative : • compréhension et capacité à résoudre un problème en écrivant des faits et des règles appropriés basés sur les informations fournies • compréhension et capacité à écrire du code capable de satisfaire un objectif en utilisant des faits et des règles |
Programmation avancée
Informatique A-Level · Sujet 20
13:52
Paradigmes de programmation
Voici une tâche : lister tous les élèves ayant une note A. Un programmeur écrit une boucle — commencer au premier enregistrement, vérifier la note, ajouter le nom à une liste, avancer…
Narration en anglais · Sous-titres anglais + 中文 incrustés
20.1
Paradigmes de programmation
Programme
Source : Programme Cambridge International
Un paradigme de programmation 编程范式 est un style de programmation — une façon de structurer les programmes, avec ses propres idées et fonctionnalités langagières. Quatre paradigmes de programmation figurent dans ce programme.
"Décrivez ce que signifie un langage impératif (procédural)" (deux points). Un langage dans lequel le programme est une séquence d'instructions exécutées dans l'ordre et qui modifient l'état du programme ; le programmeur dit comment la tâche est réalisée, en utilisant des procédures, une séquence, une sélection et une itération. "Décrivez ce que signifie un langage déclaratif" : *le programme énonce des faits et des règles (ce qui est connu et ce qui est souhaité) et le moteur d'inférence du langage détermine comment trouver la réponse ; le programmeur ne donne pas la séquence d'étapes.
Identifier le paradigme à partir d'un exemple de code (une question régulière de Paper 3) : LDD 200, ADD #5, STO 201 sont de bas niveau (mnémoniques, registres, adresses mémoire) ; FOR Count ← 1 TO 10 … NEXT Count avec procédures et affectations est impératif ; CLASS Dog … PRIVATE Name : STRING … PUBLIC PROCEDURE NEW(…) est orienté objet ; type(lion, wild). et dangerous(X) IF type(X, wild) est déclaratif (logique). Dans la question d'appariement : bas niveau correspond à « mnémoniques qui correspondent directement aux instructions machine », impératif à « une séquence d'instructions qui modifient l'état », POO à « objets qui combinent attributs et méthodes », déclaratif à « faits et règles, sans ordre d'exécution donné ».

Programmation bas niveau
Programmation proche du matériel en code machine 机器码 ou langage assembleur 汇编语言, où chaque instruction correspond à ce que le CPU exécute. Elle offre un accès direct aux registres 寄存器 et aux adresses mémoire 内存地址, en utilisant différents modes d'adressage 寻址方式 (immédiat, direct, indirect, indexé et relatif). C'est très rapide et compact, mais spécifique à l'architecture, fastidieux et difficile à maintenir. C'est la programmation bas niveau 低级, utilisée pour les pilotes, le firmware et les chargeurs de démarrage.
Les cinq modes d'adressage. Le programme demande du code bas niveau utilisant chaque mode d'adressage (l'ensemble d'instructions se trouve au Topic 4). L'oprande d'une instruction de chargement peut être lu de cinq façons, et l'examen donne le contenu de la mémoire et demande ce que contient l'accumulateur :

- immédiat (
LDM #105) : l'oprande est la valeur ; ACC devient 105. - direct (
LDD 105) : l'oprande est l'adresse de la valeur ; ACC devient le contenu de 105, ici 27. - indirect (
LDI 105) : l'oprande est l'adresse d'une adresse ; ACC devient le contenu de 27, ici 91. Utilisé pour les pointeurs et pour les données dont la position est décidée à l'exécution. - indexé (
LDX 105) : l'adresse est l'oprande plus le registre indexé IX ; avec IX = 2, ACC devient le contenu de 107. Utilisé pour parcourir un tableau en incrémentant IX. - relatif (
JMR +65) : la cible est un décalage par rapport à l'adresse de l'instruction actuelle, ce qui rend le code relocalisable.
Exemple résolu. Mémoire : 105 contient 27, 106 contient 64, 200 contient 0. Écrire du code pour additionner les contenus de 105 et 106, stocker le résultat dans 200 et l'afficher. LDD 105 (ACC = 27), ADD 106 (ACC = 91), STO 200, OUT. Pour doubler la valeur dans 105 au lieu de cela : LDD 105, ADD 105, STO 105. Indiquer le contenu des registres après chaque ligne lorsqu'on demande de tracer l'exécution.
Programmation impérative (procédurale)
En programmation impérative 命令式编程, le programmeur écrit une série de commandes qui changent l'état du programme — affectations, conditions, boucles, appels de fonctions. Les variables 变量 stockent l'état ; les instructions le modifient ; le code est organisé en procédures et fonctions (aussi appelées programmation structurée ou structurale). C'est le style des Topics 9 et 11 (Python, C). Fort lorsque l'algorithme a des étapes séquentielles claires.
Programmation orientée objet (POO)
En programmation orientée objet 面向对象编程, les programmes sont construits à partir d'objets 对象 — des unités combinant des données (attributs 属性) et des opérations (méthodes 方法). Les objets sont des instances 实例 de classes 类. Les quatre piliers :
- encapsulation 封装 — les données d'un objet sont cachées derrière ses méthodes ; le code extérieur n'utilise que les méthodes publiques, pas les données directement. Cela protège l'objet et permet de modifier son interne sans casser les appelants. Par exemple, un
BankAccountcache sesbalance; vous ne les modifiez qu'à traversdeposit()etwithdraw(), ce qui peut imposer une règle comme "ne jamais descendre sous zéro". - héritage 继承 — un sous-classe 子类 spécialise une superclasse 父类, héritant de ses attributs et méthodes et ajoutant ou redéfinissant 重写 ces derniers. Modélise "est-un" ("un Manager est un Employee").
- polymorphisme 多态 — différents objets répondent à la même appel de méthode différemment ; l'appelant ne doit pas connaître le type exact. Chaque
ShapepossèdeArea(), et unCircleet unRectanglel'implémentent chacun à leur manière. - abstraction 抽象 — montrer une interface simple et cacher l'implémentation.
Autres termes :
- non constructeur 构造函数 est une méthode spéciale exécutée lors de la création d'un objet, pour initialiser ses attributs.
- les getters et setters lisent et écrivent les attributs d'un objet (ses propriétés) via des méthodes.
- l'agrégation 聚合 et l'containment 包含 construisent un objet à partir d'autres objets (une relation "a-un").
La POO est utilisée pour les grands systèmes, les interfaces graphiques, les simulations et les jeux.
*Polymorphisme : le même appel de méthode exécute le code propre de chaque objet
*Un diagramme de classes pour Shape : attributs privés et méthodes publiques
*Héritage : partTime et fullTime sont des sous-classes de employee
*Encapsulation : les données d'un objet sont privées, atteintes uniquement via ses méthodes publiques
POO selon la correction de l'examineur
Définitions. Classe : non modèle (plan) qui définit les attributs et méthodes des objets de ce type. Objet : une instance d'une classe, créée à partir d'elle, avec ses propres valeurs pour les attributs ("une occurrence d'un objet" est l'expression de l'examen pour une instance). Attribut (propriété) : un élément de données appartenant à une classe. Méthode : une procédure ou fonction appartenant à une classe qui agit sur ses attributs. Encapsulation : combiner les attributs et méthodes dans une classe et restreindre l'accès externe aux données : les attributs sont privés et ne peuvent être lus ou modifiés que via des méthodes publiques. Héritage : une sous-classe acquiert les attributs et méthodes de sa classe parente (super) et peut ajouter les siennes ou les redéfinir. Polymorphisme : des méthodes avec le même nom qui se comportent différemment dans différentes classes ; typiquement une sous-classe redéfinit une méthode de son parent, et la bonne version s'exécute pour chaque objet. Containment : une classe possède un objet d'une autre classe comme attribut (une voiture a un moteur). "Identifier la caractéristique qui restreint l'accès externe aux données" est l'encapsulation ; "le terme pour une occurrence d'un objet" est l'instance.
"Esquisser la structure d'une classe" (trois points) : les attributs (propriétés) qui stockent les données de l'objet, généralement déclarés privés ; les méthodes (procédures et fonctions) qui agissent sur ces attributs, généralement publiques ; et un constructeur, une méthode qui s'exécute lors de la création d'un objet pour initialiser les attributs. "Donner trois avantages de la POO" : le code est réutilisé grâce à l'héritage ; les données sont protégées par l'encapsulation, donc elles ne peuvent être modifiées que par les méthodes propres à la classe ; un grand programme est divisé en classes écrites et testées indépendamment, ce qui facilite l'entretien et l'extension ; les classes modélisent des entités réelles, donc la conception est plus facile à comprendre ; le polymorphisme permet au même appel de fonctionner pour différents objets.
La classe en pseudocode, tel que défini par Paper 3 :
CLASS Car
PRIVATE Registration : STRING
PRIVATE Year : INTEGER
PRIVATE Mileage : INTEGER
PUBLIC PROCEDURE NEW(NewReg : STRING, NewYear : INTEGER)
Registration ← NewReg
Year ← NewYear
Mileage ← 0
ENDPROCEDURE
PUBLIC FUNCTION GetMileage() RETURNS INTEGER
RETURN Mileage
ENDFUNCTION
PUBLIC PROCEDURE AddMileage(Extra : INTEGER)
Mileage ← Mileage + Extra
ENDPROCEDURE
ENDCLASS
Un objet est créé avec MyCar ← NEW Car("AB12 CDE", 2020) et utilisé avec MyCar.AddMileage(150) et OUTPUT MyCar.GetMileage(). Une sous-classe réutilise le constructeur parent via SUPER :
CLASS ElectricCar INHERITS Car
PRIVATE BatteryCapacity : REAL
PUBLIC PROCEDURE NEW(NewReg : STRING, NewYear : INTEGER, NewCapacity : REAL)
SUPER.NEW(NewReg, NewYear)
BatteryCapacity ← NewCapacity
ENDPROCEDURE
ENDCLASS
La même classe en Python, tel que attendu par Paper 4 : les attributs sont rendus privés avec un double underscore, le constructeur est __init__, et une sous-classe nomme son parent entre parenthèses et appelle super().__init__(…) :
class Car:
def __init__(self, reg, year):
self.__registration = reg
self.__year = year
self.__mileage = 0
def get_mileage(self):
return self.__mileage
def add_mileage(self, extra):
self.__mileage = self.__mileage + extra
class ElectricCar(Car):
def __init__(self, reg, year, capacity):
super().__init__(reg, year)
self.__capacity = capacity
cars = []
cars.append(Car("AB12 CDE", 2020))
cars.append(ElectricCar("EV21 XYZ", 2023, 75.0))
cars[1].add_mileage(150)
print(cars[1].get_mileage())
En Java, les mêmes concepts sont private/public champs, un constructeur portant le nom de la classe, extends et super(…) ; en VB.NET Private/Public, Sub New, Inherits et MyBase.New. Une méthode polymorphe est écrite dans la classe parente et redéfinie (override) dans la classe enfant avec le même nom ; un appel via une variable de type parent exécute la version de l'enfant.
Structures de données comme objets. Paper 4 construit une pile, une liste chaînée ou un arbre binaire à partir d'une classe Node dont les attributs sont les données et une ou deux références vers d'autres nœuds ; une classe Tree (ou LinkedList) contient la racine (ou le début) et les méthodes.
*Un arbre binaire construit à partir d'objets : chaque Node contient Data plus les références Left et Right, et Tree contient Root ; l'insertion parcourt les références
CLASS Node
PUBLIC Data : INTEGER
PUBLIC Left : Node // NULL when there is no child
PUBLIC Right : Node
PUBLIC PROCEDURE NEW(NewData : INTEGER)
Data ← NewData
Left ← NULL
Right ← NULL
ENDPROCEDURE
ENDCLASS
CLASS Tree
PRIVATE Root : Node
PUBLIC PROCEDURE Insert(NewData : INTEGER)
DECLARE NewNode, Current : Node
DECLARE Placed : BOOLEAN
NewNode ← NEW Node(NewData)
IF Root = NULL THEN
Root ← NewNode
ELSE
Current ← Root
Placed ← FALSE
WHILE NOT Placed
IF NewData < Current.Data THEN
IF Current.Left = NULL THEN
Current.Left ← NewNode
Placed ← TRUE
ELSE
Current ← Current.Left
ENDIF
ELSE
IF Current.Right = NULL THEN
Current.Right ← NewNode
Placed ← TRUE
ELSE
Current ← Current.Right
ENDIF
ENDIF
ENDWHILE
ENDIF
ENDPROCEDURE
ENDCLASS
Une méthode find parcourt le même chemin et retourne TRUE lorsque Current.Data = Target, FALSE lorsqu'elle atteint NULL ; une méthode de sortie en ordre infixe est récursive : elle affiche le sous-arbre gauche, puis le nœud, enfin le sous-arbre droit. Pour une liste chaînée, le nœud possède une référence, Next, et la classe de liste détient Start ; pour une pile construite à partir d'une liste, les opérations push et pop s'effectuent toutes deux à Start.
Exemple résolu. Un jeu a des personnages. Chacun a un nom, une santé (commençant à 100) et une position donnée par X et Y. Écrire une classe Character avec un constructeur et une méthode Move(DX, DY) ; puis une sous-classe Wizard qui ajoute Mana (commençant à 50) et une méthode CastSpell() qui prend 10 mana et retourne TRUE s'il y en avait assez.
CLASS Character
PRIVATE Name : STRING
PRIVATE Health : INTEGER
PRIVATE X : INTEGER
PRIVATE Y : INTEGER
PUBLIC PROCEDURE NEW(NewName : STRING, StartX : INTEGER, StartY : INTEGER)
Name ← NewName
Health ← 100
X ← StartX
Y ← StartY
ENDPROCEDURE
PUBLIC PROCEDURE Move(DX : INTEGER, DY : INTEGER)
X ← X + DX
Y ← Y + DY
ENDPROCEDURE
ENDCLASS
CLASS Wizard INHERITS Character
PRIVATE Mana : INTEGER
PUBLIC PROCEDURE NEW(NewName : STRING, StartX : INTEGER, StartY : INTEGER)
SUPER.NEW(NewName, StartX, StartY)
Mana ← 50
ENDPROCEDURE
PUBLIC FUNCTION CastSpell() RETURNS BOOLEAN
IF Mana >= 10 THEN
Mana ← Mana - 10
RETURN TRUE
ELSE
RETURN FALSE
ENDIF
ENDFUNCTION
ENDCLASS
Les points sont pour les attributs privés, un constructeur qui définit chaque attribut, la ligne d'héritage, l'appel au constructeur parent, et une méthode qui utilise et modifie les données propres de l'objet. Quand la question demande un diagramme de classes, dessiner une boîte en trois parties (nom ; attributs avec - pour privé ; méthodes avec + pour public) et relier une sous-classe à son parent avec une flèche pointant vers le parent.
Programmation déclarative
En programmation déclarative 声明式编程, vous dites ce que calculer, pas comment — l'exécutant détermine les étapes. Deux sortes :
- programmation fonctionnelle 函数式编程 — construite à partir de fonctions pures 纯函数 (pas d'effets secondaires 副作用 ; même entrée donne toujours même sortie) composées ensemble. Exemples : Haskell, Lisp.
- programmation logique 逻辑编程 — définit des faits et des règles ; le moteur répond à un objectif (requête) par inférence. Exemple : Prolog.
Un exemple déclaratif familier est SQL 结构化查询语言 : SELECT * FROM Customer WHERE Country = 'UK' dit ce que vous voulez, pas comment parcourir les enregistrements.
Faits, règles et objectifs sont ce que l'examen teste dans le paradigme déclaratif. Étant donné ces faits 事实 (déclarations qui sont vraies) et une règle 规则 (une conclusion qui est vraie lorsque ses conditions sont remplies) :
01 type(leopard, wild).
02 type(lion, wild).
03 type(tabby, domestic).
04 size(leopard, large).
05 size(lion, large).
06 size(tabby, small).
07 dangerous(X) IF type(X, wild) AND size(X, large).
"Écrivez le résultat de l'objectif type(X, wild)" : X = leopard, X = lion. Le moteur fait correspondre l'objectif avec chaque fait à tour de rôle ; chaque correspondance est une solution, et une lettre majuscule est une variable que la correspondance remplit. "Écrivez un fait pour montrer qu'un guépard est sauvage" : type(cheetah, wild). "Expliquez ce que fait la ligne 07" : elle définit une règle dont la conclusion est dangerous(X), qui est vraie pour tout X qui est à la fois sauvage et grand, donc dangerous(A) retourne A = leopard, A = lion. "Écrivez une règle : une caractéristique F peut être disponible pour un style de carrosserie B si F est une caractéristique et B est un style de carrosserie et F n'est pas indisponible pour B" : may_be_available(F, B) IF feature(F) AND body_style(B) AND NOT unavailable(F, B). Copiez les noms de prédicat et l'ordre des arguments exacts utilisés dans les faits de la question ; un nouveau fait se termine par un point, et les conditions d'une règle sont jointes par AND.
Comparaison des paradigmes
| Paradigme | Force | Langages typiques |
|---|---|---|
| Bas niveau | contrôle maximal, vitesse | assembleur |
| Impérative | directe, intuitive | C, Python |
| Orientée objet | modulaire, modèle des entités | Java, C#, Python |
| Fonctionnelle | claire, sans effets secondaires | Haskell, F# |
| Logique | inférence, règles | Prolog |
| Base de données | requêtes sur données | SQL |
Les langages modernes mixent souvent les paradigmes — Python prend en charge tous ceux-ci : procédural, POO et fonctionnel. Le bon dépend du problème.
Laboratoire de concepts de programmation
Reliez les exemples au concept de programmation qu'ils illustrent.
| Anglais | Chinois | Pinyin |
|---|---|---|
| programming paradigm/ˈprəʊɡræmɪŋ ˈpærədaɪm/ | 编程范式 | biān chéng fàn shì |
| facts/fækts/ | 事实 | shì shí |
| rule/ruːl/ | 规则 | guī zé |
| low-level/ləʊ ˈlevl/ | 低级 | dī jí |
| registers/ˈredʒɪstəz/ | 寄存器 | jì cún qì |
| memory addresses/ˈmeməri əˈdresɪz/ | 内存地址 | nèi cún dì zhǐ |
| objects/ˈɒbdʒekts/ | 对象 | duì xiàng |
| attributes/ˈætrɪbjuːts/ | 属性 | shǔ xìng |
| methods/ˈmeθədz/ | 方法 | fāng fǎ |
| machine code/məˈʃiːn kəʊd/ | 机器码 | jī qì mǎ |
| assembly language/əˈsemblɪ ˈlæŋɡwɪdʒ/ | 汇编语言 | huì biān yǔ yán |
| addressing modes/əˈdresɪŋ məʊdz/ | 寻址方式 | xún zhǐ fāng shì |
| array/əˈreɪ/ | 数组 | shù zǔ |
| imperative programming/ɪmˈperətɪv ˈprəʊɡræmɪŋ/ | 命令式编程 | mìng lìng shì biān chéng |
| Variables/ˈveərɪəblz/ | 变量 | biàn liàng |
| object-oriented programming/ˈɒbdʒekt ˈɔːrɪəntɪd ˈprəʊɡræmɪŋ/ | 面向对象编程 | miàn xiàng duì xiàng biān chéng |
| instances/ˈɪnstənsɪz/ | 实例 | shí lì |
| classes/ˈklæsɪz/ | 类 | lèi |
| encapsulation/ɪnˌkæpsjʊˈleɪʃn/ | 封装 | fēng zhuāng |
| inheritance/ɪnˈherɪtəns/ | 继承 | jì chéng |
| subclass/ˈsʌbklæs/ | 子类 | zi lèi |
| superclass/ˈsuːpəklæs/ | 父类 | fù lèi |
| overriding/ˌəʊvəˈraɪdɪŋ/ | 重写 | chóng xiě |
| polymorphism/ˈpɒlɪmɔːfɪzəm/ | 多态 | duō tài |
| abstraction/əbˈstrækʃn/ | 抽象 | chōu xiàng |
| constructor/kənˈstrʌktə/ | 构造函数 | gòu zào hán shù |
| aggregation/ˌæɡrɪˈɡeɪʃn/ | 聚合 | jù hé |
| containment/kənˈteɪnmənt/ | 包含 | bāo hán |
| declarative programming/dɪˈklærətɪv ˈprəʊɡræmɪŋ/ | 声明式编程 | shēng míng shì biān chéng |
| functional programming/ˈfʌŋkʃənl ˈprəʊɡræmɪŋ/ | 函数式编程 | hán shù shì biān chéng |
| pure functions/pjʊə ˈfʌŋkʃnz/ | 纯函数 | chún hán shù |
| side effects/saɪd ɪˈfekts/ | 副作用 | fù zuò yòng |
| logic programming/ˈlɒdʒɪk ˈprəʊɡræmɪŋ/ | 逻辑编程 | luó jí biān chéng |
| SQL/ˌes kjuː ˈel/ | 结构化查询语言 | jié gòu huà chá xún yǔ yán |
20.2
Traitement de fichiers
Programme
| Les candidats doivent être capables de : | Notes et orientations |
|---|---|
| Écrire du code pour effectuer des opérations de traitement de fichiers | Ouvrir (en mode lecture, écriture, ajout) et fermer un fichier Lire un enregistrement depuis un fichier et écrire un enregistrement vers un fichier Effectuer des opérations de traitement de fichiers sur des fichiers série, séquentiels, aléatoires |
| Montrer la compréhension d'une exception et de l'importance de la gestion des exceptions | Savoir quand il est approprié d'utiliser la gestion des exceptions Écrire du code de programme pour utiliser la gestion des exceptions |
Source : Programme Cambridge International
Cela étend la gestion des fichiers 文件 depuis le Sujet 10, traitant des fichiers série, séquentiels et aléatoires (accès direct). Opérations en pseudocode : OPENFILE name FOR READ | WRITE | APPEND (READ ouvre un fichier existant, WRITE crée/supprime, APPEND ajoute à la fin) ; READFILE name, line ; WRITEFILE name, value ; CLOSEFILE name ; et EOF(name) qui est VRAI à la fin.
Lire un fichier entier :
OPENFILE "names.txt" FOR READ
WHILE NOT EOF("names.txt") DO
READFILE "names.txt", thisName
OUTPUT thisName
ENDWHILE
CLOSEFILE "names.txt"
Rechercher dans un fichier (s'arrêter quand trouvé) :
found ← FALSE
OPENFILE "people.txt" FOR READ
WHILE NOT EOF("people.txt") AND NOT found DO
READFILE "people.txt", line
IF line = target THEN
found ← TRUE
ENDIF
ENDWHILE
CLOSEFILE "people.txt"
Mise à jour d'un fichier in-place
La plupart des langages ne peuvent pas éditer un fichier texte in-place. Au lieu de cela : ouvrir l'original en READ et un fichier temporaire en WRITE ; pour chaque ligne, écrire la nouvelle version si elle doit changer, sinon l'originale ; fermer les deux ; puis remplacer l'original par le fichier temp. Ce même motif gère la suppression de lignes (les sauter) et l'insertion de lignes.

Enregistrements et fichiers à accès aléatoire
Modes d'ouverture. READ : le fichier doit exister et la lecture commence au début. WRITE : un fichier nouveau est créé, et un fichier existant de ce nom est écrasé. APPEND : l'écriture ajoute à la fin d'un fichier existant. Tout fichier ouvert est fermé avec CLOSEFILE, et EOF(name) est TRUE quand le dernier élément a été lu.
Trois organisations de fichiers. Dans un fichier série, les enregistrements sont dans l'ordre où ils ont été ajoutés ; dans un fichier séquentiel, ils sont dans l'ordre de la clé ; les deux se lisent depuis le début. Un fichier aléatoire 随机文件 (fichier à accès direct) stocke chaque enregistrement à une adresse calculée à partir de sa clé via une fonction de hachage 哈希, donc un seul enregistrement est trouvé sans lire les autres. Les enregistrements sont déclarés comme un type défini par l'utilisateur :
TYPE AccountRecord
DECLARE AccNo : INTEGER
DECLARE Name : STRING
DECLARE Balance : REAL
DECLARE Active : BOOLEAN
ENDTYPE

Les opérations de fichier aléatoire en pseudocode sont OPENFILE "Acc.dat" FOR RANDOM, SEEK "Acc.dat", Address (déplacer le curseur du fichier vers cet enregistrement), GETRECORD "Acc.dat", Rec (lire l'enregistrement à cet endroit) et PUTRECORD "Acc.dat", Rec (écrire l'enregistrement à cet endroit). Trouver un client par numéro de compte, tel que défini dans Paper 3 :
DECLARE Rec : AccountRecord
DECLARE Target, Address : INTEGER
INPUT Target
Address ← Target MOD 1000 // the hashing function
OPENFILE "Acc.dat" FOR RANDOM
SEEK "Acc.dat", Address
GETRECORD "Acc.dat", Rec
WHILE Rec.AccNo <> Target AND Rec.AccNo <> 0 // 0 marks an empty slot
Address ← Address + 1 // a collision: try the next slot
SEEK "Acc.dat", Address
GETRECORD "Acc.dat", Rec
ENDWHILE
IF Rec.AccNo = Target THEN
OUTPUT Rec.Name, Rec.Balance
ELSE
OUTPUT "No such account"
ENDIF
CLOSEFILE "Acc.dat"
Pour stocker un enregistrement, hachez sa clé, SEEK vers l'adresse et PUTRECORD, en passant devant toute case déjà occupée. Les marques vont au hachage, au SEEK avant le GET ou PUT, à la comparaison avec la cible, à la gestion d'une collision, et à la fermeture du fichier.
Exemple résolu. ActiveFile.dat contient AccountRecord enregistrements. Écrivez un pseudocode qui copie tous les enregistrements dont le champ Active est FALSE à la fin de ArchiveFile.dat.
DECLARE Rec : AccountRecord
OPENFILE "ActiveFile.dat" FOR READ
OPENFILE "ArchiveFile.dat" FOR APPEND
WHILE NOT EOF("ActiveFile.dat")
READFILE "ActiveFile.dat", Rec
IF Rec.Active = FALSE THEN
WRITEFILE "ArchiveFile.dat", Rec
ENDIF
ENDWHILE
CLOSEFILE "ActiveFile.dat"
CLOSEFILE "ArchiveFile.dat"
Fichiers texte en Python (Paper 4) : file = open("HighScore.txt", "r"), puis for line in file: avec line.strip() et line.split(",") pour séparer les champs, int(…) pour convertir une note, et file.close() ; pour écrire, open(name, "w") (ou "a" pour ajouter) et file.write(str(score) + "\n"). Une table des meilleurs scores est lue dans une liste d'enregistrements, la nouvelle note est insérée à sa place, et toute la liste est réécrite. L'examinateur marque l'ouverture avec le mode correct, une boucle qui lit chaque ligne, la conversion du texte en nombres, et la fermeture.
Pièges
Oublier de fermer un fichier (données peuvent être perdues) ; ouvrir en WRITE au lieu d'APPEND (écrase tout) ; lire au-delà de EOF ; chemins codés en dur — un chemin comme /Users/Admin/data.txt casse sur une autre machine, donc utilisez une constante relative telle que DataFile = "./data/scores.txt".
Voie d'accès au fichier
Suivre un fichier depuis le stockage jusqu'au programme et retour en toute sécurité.
| Anglais | Chinois | Pinyin |
|---|---|---|
| file/faɪl/ | 文件 | wén jiàn |
| random file/ˈrændəm faɪl/ | 随机文件 | suí jī wén jiàn |
| hashing/ˈhæʃɪŋ/ | 哈希 | hā xī |
20.2
Gestion des exceptions
Une exception 异常 est une erreur ou une condition inattendue pendant l'exécution — division par zéro, fichier non trouvé, panne réseau, indice de tableau 数组 hors limites. La gestion des exceptions 异常处理 permet à un programme de la détecter et d'y répondre gracieusement au lieu de planter.
Cela importe parce que les vrais programmes font face à des erreurs qui ne peuvent pas être évitées à l'avance (fichiers déplacés, réseaux coupés, mauvaise saisie) ; sans cela, chaque opération nécessite sa propre vérification IF ; et cela sépare le flux normal de la gestion des erreurs, afin que le chemin principal reste clair. Par exemple, un fichier peut être supprimé par un autre utilisateur entre le moment où votre programme vérifie son existence et celui où il l'ouvre réellement — vous ne pouvez pas empêcher cela, seulement gérer l'échec quand il survient.
"Décrivez, avec un exemple, ce qu'est une exception (deux marks). Un événement inattendu ou une erreur qui survient pendant l'exécution d'un programme (à l'exécution) et interrompt son flux normal ; par exemple diviser par zéro, ouvrir un fichier qui n'existe pas, convertir une saisie non numérique en entier, un indice de tableau hors limites, ou épuiser la mémoire. "Identifier deux causes possibles d'exceptions" s'answer à partir de cette liste, plus "un périphérique ou un réseau n'est pas disponible" et "type de données invalide saisi".
"Énoncez les raisons d'inclure la gestion des exceptions (trois marks). Empêcher le programme de planter (se terminer inopinément) ; afficher un message significatif à l'utilisateur plutôt qu'une erreur système ; permettre au programme de se récupérer et de continuer, par exemple en demandant la saisie à nouveau, ou de fermer les fichiers en sécurité avant de se terminer ; et parce que certaines erreurs ne peuvent pas être prédites quand le programme est écrit. "Décrivez comment éviter la terminaison du programme due à une exception" : placer les instructions qui pourraient lever une exception dans un bloc TRY ; écrire un bloc EXCEPT (catch) pour cette exception qui la gère, par exemple en affichant un message, afin que l'exécution continue après le bloc au lieu de s'arrêter. "Expliquez ce qu'est la gestion des exceptions" : détecter une exception quand elle survient et exécuter du code (le gesteur) qui s'en occupe afin que le programme continue.
Motif
TRY
OPENFILE "data.txt" FOR READ
READFILE "data.txt", line
OUTPUT line
CLOSEFILE "data.txt"
EXCEPT FileNotFound
OUTPUT "Sorry, the file does not exist."
EXCEPT ReadError
OUTPUT "Sorry, error reading the file."
ENDTRY
Le bloc TRY contient le code susceptible d'échouer ; le premier bloc EXCEPT correspondant s'exécute. Les vrais langages ont aussi un catch-all EXCEPT et un bloc FINALLY qui s'exécute qu'il y ait eu une exception ou non — utile pour le nettoyage (fermer les fichiers).

Lever une exception
Une sous-routine qui détecte une erreur peut lever 抛出 une exception afin que l'appelant la gère :
PROCEDURE Divide(a : INTEGER, b : INTEGER) RETURNS INTEGER
IF b = 0 THEN
RAISE DivideByZero
ENDIF
RETURN a DIV b
ENDPROCEDURE
Où gérer les exceptions
Gérez-les près de l'erreur si la réponse est simple (un message, une rétentative), ou plus haut dans la pile d'appels 调用栈 si seul le code externe sait quoi faire (une boucle GUI de niveau supérieur log l'erreur et affiche une boîte de dialogue amicale). Ne jamais absorber silencieusement les exceptions — au moins loguez-les, sinon le débogage devient impossible.
Exceptions courantes : FileNotFound, IOError, DivisionByZero, IndexOutOfRange, InvalidArgument, NullReference, OutOfMemory. Envelopper chaque opération défaillante dans un TRY avec les gestionnaires EXCEPT appropriés permet d'obtenir un programme qui se dégrade gracieusement au lieu de planter.
Exemple résolu (Paper 4). Écrivez une fonction qui lit des nombres entiers, un par ligne, depuis un fichier dont le nom est passé en paramètre et les retourne dans une liste. Elle ne doit pas planter si le fichier n'existe pas ou si une ligne n'est pas un nombre entier.
def read_scores(filename):
scores = []
try:
file = open(filename, "r")
for line in file:
scores.append(int(line))
file.close()
except FileNotFoundError:
print("The file", filename, "does not exist")
except ValueError:
print("A line in the file was not a whole number")
return scores
Le bloc try contient le code susceptible de provoquer une erreur (l'ouverture et la conversion) ; chaque except nomme une exception spécifique et effectue une action utile ; la fonction retourne toujours une liste, permettant ainsi au programmeur appelant de poursuivre son exécution. En Java, la même structure correspond à try { … } catch (FileNotFoundException e) { … } catch (NumberFormatException e) { … } ; en VB.NET, elle correspond à Try … Catch ex As FileNotFoundException … End Try. Points attribués : les instructions risquées à l'intérieur du bloc try, les noms corrects des exceptions, un message pour chacune, et la poursuite de l'exécution du programme par la suite ; un bloc catch-all except: entraîne la perte de points pour le plantage, mais pas celle pour la mention « exception appropriée ».
Exemple résolu. Un fichier texte de membres nécessite la modification du numéro de téléphone d'un membre. Pourquoi le programme ne peut-il pas simplement écraser cette ligne, et quel est le motif ? Les lignes d'un fichier texte ont des longueurs différentes, et le fichier ne contient pas d'espaces pour absorber une différence : un remplacement plus long empiéterait sur l'enregistrement suivant, et un remplacement plus court laisserait une partie de l'ancienne ligne en arrière-plan. Le motif consiste donc à ouvrir l'original en mode READ (lecture) et un fichier temporary (temporaire) en mode WRITE (écriture), lire chaque ligne successivement, écrire la version new (nouvelle) pour la ligne modifiée et la ligne original (originale) pour toutes les autres, fermer les deux fichiers, puis replace (remplacer) l'original par le fichier temporaire. La même structure gère la suppression (sautez la ligne) et l'insertion (écrivez la ligne supplémentaire). Notez que every (chaque) ligne est écrite, pas seulement celle qui a changé - écrire uniquement le nouveau record et perdre le reste du fichier constitue une erreur classique.
Comment la gestion des exceptions s'écoule
Passez en revue ce qui se passe quand le code échoue. L'exception saute hors du flux normal vers un handler, FINALLY nettoie des deux côtés, et le programme continue au lieu de planter.
| Anglais | Chinois | Pinyin |
|---|---|---|
| exception/ekˈsepʃn/ | 异常 | yì cháng |
| exception handling/ekˈsepʃn ˈhændlɪŋ/ | 异常处理 | yì cháng chǔ lǐ |
| raise/reɪz/ | 抛出 | pāo chū |
| call stack/kɔːl stæk/ | 调用栈 | diào yòng zhàn |
20.2
Définitions acceptées par l'examinateur
Une question de définition est notée selon un libellé fixe. Apprenez-les exactement et ne donnez qu'une seule réponse.
| Terme | Définition |
|---|---|
| paradigme de programmation | un style ou une façon de programmer, avec sa propre méthode de structuration d'un programme |
| langage impératif | le programme est une séquence d'instructions qui changent l'état du programme ; le programmeur décrit comment la tâche est réalisée |
| langage déclaratif | le programme énonce des faits et des règles, et le moteur d'inférence détermine comment trouver la réponse |
| classe | un modèle définissant les attributs et les méthodes des objets de ce type |
| objet (instance) | une occurrence d'une classe, avec ses propres valeurs pour les attributs |
| attribut | un élément de données appartenant à une classe |
| méthode | une procédure ou une fonction appartenant à une classe et agissant sur ses attributs |
| encapsulation | regrouper les attributs et les méthodes dans une classe et restreindre l'accès externe aux données, afin qu'elles soient modifiées uniquement via des méthodes publiques |
| héritage | une sous-classe acquiert les attributs et les méthodes de sa classe parente et peut les ajouter ou les redéfinir |
| polymorphisme | méthodes portant le même nom mais se comportant différemment selon les classes |
| constructeur | une méthode qui s'exécute lors de la création d'un objet et initialise ses attributs |
| contenance | une classe possède un objet d'une autre classe comme l'un de ses attributs |
| fait | une affirmation dans un programme déclaratif qui est vraie |
| règle | une conclusion qui est valide lorsque ses conditions sont remplies |
| fichier séquentiel, linéaire, aléatoire | enregistrements dans l'ordre d'ajout ; enregistrements triés par clé ; chaque enregistrement à une adresse calculée à partir de sa clé |
| exception | une erreur inattendue ou un événement pendant l'exécution qui interrompt le flux normal |
| gestion des exceptions | détecter une exception lorsqu'elle survient et exécuter du code capable de la gérer afin que le programme poursuive son exécution |
20.2
Conseils d'examen
- Paradigmes : connaître la description en une ligne de chacun et être prêt à nommer le paradigme à partir d'un échantillon de code ; les questions de bas niveau portent sur les cinq modes d'adressage et ce que reçoit l'accumulateur.
- Les définitions POO reviennent à chaque session : classe, objet, attribut, méthode, encapsulation, héritage, polymorphisme, constructeur. Écrire une classe en pseudocode avec des attributs PRIVATE (privés), un PUBLIC NEW (public) et des getters ; une sous-classe avec INHERITS (hérite) et SUPER.NEW.
- Déclaratif : un objectif avec une variable retourne tous les faits correspondants ; une règle est une conclusion IF (si) les conditions sont réunies avec AND (et) ; copier exactement les noms de prédicat de la question.
- Fichiers : les trois modes et ce que chacun fait à un fichier existant ; READFILE dans une boucle WHILE NOT EOF ; les fichiers aléatoires utilisent un hash, SEEK, GETRECORD et PUTRECORD, avec un risque de collision.
- Exceptions : définition avec exemple, trois raisons de les gérer, et TRY avec un EXCEPT nommé permettant au programme de continuer.
Erreurs courantes
- Décrire un programme déclaratif comme « une séquence d'étapes donnant la réponse » ; il énonce ce qui est vrai et ce qui est souhaité, pas comment.
- Confondre un objet avec une classe, ou une instance avec un attribut ; la question « une occurrence d'un objet » attend « instance ».
- Déclarer les attributs PUBLICS, ou y accéder depuis l'extérieur de la classe au lieu d'utiliser un getter, ce qui annule l'encapsulation.
- Constructeur de sous-classe qui définit directement les attributs parents au lieu d'appeler SUPER.NEW.
- Expliquer le polymorphisme comme « beaucoup d'objets » ; c'est le même nom de méthode se comportant différemment pour différentes classes.
- Ouvrir un fichier FOR WRITE (pour écriture) pour ajouter un enregistrement, ce qui détruit le contenu existant ; utiliser APPEND (ajouter).
- Lire un fichier aléatoire à partir du début ; faire un SEEK vers l'adresse hachée d'abord.
- Placer le gestionnaire d'exception autour du code qui ne peut pas échouer, ou capturer tout sans message, ou décrire la gestion des exceptions comme « vérifier l'entrée avec IF ».
Leçons interactives sur ce sujet
Traversez-le étape par étape, avec des exercices à vérification instantanée.