-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathlog1-chapitre-sequentiel.tex
1318 lines (1105 loc) · 47 KB
/
log1-chapitre-sequentiel.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
\chapter{Algorithmes séquentiels}
\marginicon{objectif}
Dans ce chapitre, vous apprendrez à écrire un algorithme séquentiel pour
résoudre un problème informatique. C’est aussi
l’occasion de fixer la syntaxe du pseudo-code que nous
allons utiliser. Nous commençons avec les algorithmes
séquentiels qui sont de simples séquences de suites
d’instructions. Les structures alternatives et
répétitives seront vues dans les chapitres suivants.
\section{Introduction}
Supposons que nous voulions rédiger une marche
à suivre détaillée qui explique comment additionner deux fractions. Une
possibilité de l’écrire en langage «~naturel~» serait la suivante~:
\cadre{
\begin{pseudo}
\Stmt - Rechercher le dénominateur commun des deux fractions
\Stmt - Mettre chaque fraction au même dénominateur
\Stmt - Additionner les numérateurs des deux fractions,
\Stmt \Indent ce qui donne le numérateur de la somme
\Stmt - Simplifier la fraction obtenue
\end{pseudo}
}
Cet algorithme, bien que résultant d’un effort
d’explicitation, est encore très imprécis et risque fort de ne pas
faciliter l’effort de programmation qui en suivrait. N’oublions pas
qu’un ordinateur n’est qu’une machine dépourvue de toute intelligence
et incapable de comprendre les sous-entendus qu’un être humain pourrait
comprendre~!
De plus, les notions de dénominateur commun et
de simplification de fraction, qui vous sont
familières depuis l’école primaire,
ne sont pas immédiates d’un point de
vue algorithmique. Un algorithme proche d’un langage
de programmation ne devrait mentionner que les opérations élémentaires
de calcul telles que $+$, -, $*$, $/$.
Ceci dit, afin d’être plus proche d’un
programme écrit dans un langage compréhensible par l’ordinateur,
l’algorithme ci-dessus pourrait s’écrire~:
\cadre{
\begin{pseudo}
\Stmt - Prendre connaissance du premier numérateur et du premier dénominateur ;
\Stmt - Prendre connaissance du second numérateur et du second dénominateur ;
\Stmt - Multiplier les deux dénominateurs pour obtenir le dénominateur commun ;
\Stmt - Multiplier le premier numérateur par le second dénominateur
\Stmt \Indent et le second numérateur par le premier dénominateur ;
\Stmt - Additionner ces deux produits pour obtenir le numérateur du résultat ;
\Stmt - Communiquer ce résultat ainsi que le dénominateur commun.
\end{pseudo}
}
Notons encore que cet algorithme n’est pas le
plus efficace pour ce type de problème.
Il vaudrait mieux utiliser le PPCM
(\textit{Plus Petit Commun Multiple})
pour le calcul du dénominateur commun, mais la façon
de calculer ce dernier serait très fastidieuse à rédiger en langage
«~naturel~».
On comprend bien, au travers de cet exemple, que
le français n’est pas adapté à la description de problèmes au contenu
mathématique ou scientifique. Le langage naturel est, en effet, un mode
de représentation trop riche des algorithmes. Il faut comprendre par
«~riche~», la présence de synonymes, de nombreux mots aux
significations proches et voisines. L’utiliser amènerait probablement à
une perte de temps (donc d’argent), et à des risques d’erreurs dans la
conception des programmes. Il convient dès lors d’élaborer des méthodes
de représentation plus rigoureuses (donc moins riches) mais nécessitant
un effort moindre de programmation.
Ceci dit, le français peut toujours être
utilisé dans la formalisation d’une première approche de la résolution
d’un problème devant être traduit ensuite en algorithme puis en
programme.
\section{Le pseudo-code}
Les inconvénients de l’utilisation du français dans la représentation
des algorithmes sont dus à la trop grande richesse de ce langage en
comparaison à la pauvreté (mais aussi la rigueur) du langage compris
par la machine. De plus, la lourdeur et la longueur des phrases
risquent de rendre pénible la relecture et le travail d’élaboration des
algorithmes. La solution consiste à édulcorer le langage naturel, d’une
part en remplaçant les noms parfois fastidieux des objets sur lesquels
portent des opérations par des mots (noms de variables) plus courts,
d’autre part, en remplaçant les opérations elles-mêmes par des
opérateurs symboliques suffisamment explicites. De plus, des structures
types remplaceront les multiples possibilités linguistiques signifiant
la même chose.
\marginicon{definition}
Le \textbf{pseudo-code} ou \textit{Langage de Description des
Algorithmes} (LDA en abrégé) est un langage formel et symbolique
utilisant~:
\begin{liste}
\item
des \textbf{noms symboliques} destinés à représenter les objets sur
lesquels s’effectuent des actions ;
\item
des \textbf{opérateurs symboliques} ou des mots-clés traduisant les
opérations primitives exécutables par un exécutant donné ;
\item
des \textbf{structures de contrôle} types.
\end{liste}
Ce langage repose sur des conventions d’écriture. Il est destiné à
servir de vecteur de la compréhension permettant par exemple une
relecture faite par l’élaborateur de l’algorithme lui-même ou faite par
autrui et facilitant le travail de programmation.
C’est de cette dernière exigence que nait la polémique consistant à
savoir jusqu’à quel niveau de détail il convient d’aller dans la
représentation d’un algorithme~! Nous dirons, pour notre part, qu’il ne
doit jamais être aussi détaillé que le programme lui-même, celui-ci
étant, par essence, la description ultime. Point n’est besoin de donner
deux descriptions quasi identiques d’un algorithme, l’une dans un
langage \textit{pseudo-codé}, l’autre exprimée dans un langage de
programmation.
Nous dirons qu’un algorithme \textit{idéal}, appelé \textbf{algorithme
général}, exprimé en pseudo-code, devrait se situer à mi-chemin entre
la démarche globale exprimée dans un langage naturel (langue française)
ou structuré (ordinogramme) et l’algorithme ultime, c’est-à-dire le
\textbf{programme}, exprimé en langage de programmation.
On pourrait d’ailleurs concevoir la possibilité d’établir d’autres
\textbf{algorithmes plus détaillés} se situant entre
l’algorithme général et le programme et qui tiendraient compte de
certaines particularités du langage de programmation dans lequel ils
sont destinés à être traduits.
Enfin, et ce n’est pas la chose la moins importante, la définition d’un
pseudo-code doit être telle qu’il puisse \textbf{faciliter
l’apprentissage de la logique de programmation} par des personnes
désireuses de faire de l’informatique un métier. Dans cette optique, il
est inutile de les embarrasser de contraintes syntaxiques ou autres qui
risquent de les éloigner du but poursuivi.
En conclusion, à partir du moment où des conventions sont prises dans un
contexte bien déterminé (un service informatique d’une entreprise, un
groupe scolaire...), il convient que \textbf{tous} respectent ces
conventions. Ce sera à chacun de juger jusqu’où il ne faut pas aller
trop loin dans la liberté d’écriture.
\section{Variables et types}
Nous savons que les opérations que l’ordinateur devra exécuter portent
sur des éléments qui sont les \textbf{données} du problème. Lorsqu’on
attribue un \textbf{nom} et un \textbf{type} à ces données, on parle
alors de \textbf{variables}. Dans un algorithme, une variable conserve
toujours son nom et son type, mais peut changer de \textbf{valeur}.
Le \textbf{nom} d’une variable permet de la caractériser et de la
reconnaitre. Ainsi, dans l’exemple donné ci-dessus, nous pourrions
donner le nom \textit{num1} au \textit{premier numérateur} et
\textit{num2} au \textit{second numérateur}, ce qui permet déjà de
nommer les objets de l’algorithme de façon tout aussi reconnaissable
mais plus courte et donc plus commode. Quant au \textbf{type} d’une
variable, il décrit la nature de son contenu.
\subsection{Les types autorisés}
Dans un premier temps, les seuls \textbf{types} utilisés sont les
suivants~:
\begin{center}
\tablehead{}
\begin{tabular}[t]{p{1.6cm}|p{11.5cm}}
\raggedleft \textstyleMotCl{entier} &
pour les nombres entiers\\
\raggedleft \textstyleMotCl{réel} &
pour les nombres réels\\
\raggedleft \textstyleMotCl{caractère} &
pour les différentes lettres et caractères (par
exemple ceux qui apparaissent sur un clavier~: ‘a’, ‘1’, ‘\#’, etc.)\\
\raggedleft \textstyleMotCl{chaine} &
{ pour les variables contenant plusieurs
caractères ou aucun (la chaine vide)}
(par exemple~: "Bonjour", "Bonjour le monde", "a", "", etc.)
\\
\raggedleft \textstyleMotCl{booléen} &
les variables de ce type ne peuvent valoir que
\textbf{vrai} ou \textbf{faux}\\
\end{tabular}
\end{center}
On veillera au cours de logique à ne pas utiliser les valeurs 0 et 1
pour les variables booléennes, même si leur emploi est correct dans
beaucoup de langages de programmation.
\begin{Emphase}[exercice]{Exercices}
Quel(s) type(s) de données utiliseriez-vous
pour représenter
\begin{itemize}
\item une date du calendrier~?
\item un moment dans la journée~?
\item le prix d’un produit en grande surface~?
\item votre nom~?
\item vos initiales~?
\item votre adresse~?
\end{itemize}
\bigskip
\end{Emphase}
\subsection{Déclaration de variables}
La déclaration d’une variable est l’instruction
qui définit son nom et son type. On pourrait écrire~:
\cadre{
\begin{pseudo}
\Stmt num1 et num2 seront les noms de deux objets destinés à recevoir
\Stmt les numérateurs des fractions, c’est-à-dire des nombres à valeurs entières.
\end{pseudo}
}
Mais, bien entendu, cette formulation, trop proche du
langage parlé, serait trop floue et trop longue.
Dès lors, nous abrégerons par~:
\cadre{
\begin{pseudo}
\Declare{num1, num2}{entiers}
\end{pseudo}
}
\marginicon{definition}
L’ensemble des instructions de la forme
\cadre{
\begin{pseudo}
\Declare{variable1, variable2,\ldots}{type}
\end{pseudo}
}
forme la partie d’un algorithme nommée
\textbf{déclaration des variables}.
La déclaration des informations apparaitra toujours en
début d’algorithme, ou dans un bloc annexe appelé
\textbf{dictionnaire des variables}
ou encore \textbf{dictionnaire des données}.
Par exemple, pour l’algorithme des fractions, la déclaration des
informations pourrait être la suivante~:
\cadre{
\begin{pseudo}
\Declare{num1, den1, num2, den2, numRes, denRes}{entiers}
\end{pseudo}
}
avec la signification suivante~:
\begin{liste}
\item
\textstyleCodeInsr{num1 (num2)}~: le numérateur
de la première (seconde) fraction ;
\item
\textstyleCodeInsr{den1 (den2)}~: le dénominateur
de la première (seconde) fraction ;
\item
\textstyleCodeInsr{numRes (denRes)}~:
le numérateur (dénominateur) du résultat.
\end{liste}
\marginicon{attention}
Attention, lors de la déclaration d’une variable, celle-ci n’a pas de
valeur~! Nous verrons plus loin que c’est l’instruction
d’\textbf{affectation} qui va servir à donner un contenu aux variables
déclarées. En logique, nous n’envisageons pas d’\textit{affectation par
défaut} consistant à donner une valeur initiale de façon automatique
aux variables déclarées (par exemple 0 pour les variables numériques,
comme c’est le cas dans certains langages informatiques).
\subsection{Comment nommer correctement une variable~?}
Le but est de trouver un nom qui soit suffisamment court tout en restant
explicite (ainsi \textstyleCodeInsr{num1} est plus approprié pour
désigner le \textit{premier numérateur }que \textstyleCodeInsr{zozo1},
\textstyleCodeInsr{tintin}, \textstyleCodeInsr{bidule,
premierNumérateur}) et qui ne prête pas à confusion (par exemple
appeler \textbf{den} la variable représentant le numérateur.
Il faut aussi tenir compte que les
langages de programmation imposent certaines limitations (parfois
différentes d’un langage à l’autre)
ce qui peut nécessiter une modification du nom lors de la traduction.
Voici quelques règles et limitations traditionnelles dans les langages
de programmation:
\begin{liste}
\item
Un nom de variable est généralement une suite de caractères
alphanumériques d’un seul tenant (pas de caractères blancs) et ne
commençant jamais par un chiffre. Ainsi \textstyleCodeInsr{x1} est
correct mais non \textstyleCodeInsr{1x}.
\item
Pour donner un nom composé à une variable, on peut utiliser le «~tiret
bas~» ou \textit{underscore} (par ex. premier\_numérateur) mais on
déconseille d’utiliser le signe «~–~» qui est plutôt réservé à la
soustraction. Ainsi, dans la plupart des langages,
\textstyleCodeInsr{premier-numérateur} serait interprété comme la
soustraction des variables \textstyleCodeInsr{premier} et
\textstyleCodeInsr{numérateur}. (Signalons que le tiret
\textcolor{black}{«~–~»} est autorisé en Cobol, où il récupère son rôle
arithmétique s’il est précédé et suivi d’au moins un blanc).
\item
Une alternative à l’utilisation du tiret bas pour l’écriture de noms de
variables composés est la notation «~chameau~» (\textit{camelCase} en
anglais), qui consiste à mettre une majuscule au début des mots
(généralement à partir du deuxième), par exemple
\textstyleCodeInsr{premierNombre} ou
\textstyleCodeInsr{dateNaissance}.
\item
Les indices et exposants sont proscrits (par ex.
\textstyleCodeInsr{x}\textstyleCodeInsr{\textsubscript{1}},
\textstyleCodeInsr{z}\textstyleCodeInsr{\textsubscript{6}} ou
\textstyleCodeInsr{m²)}
\item
Les mots-clés du langage sont interdits (par exemple
\textstyleMotCl{for}, \textstyleMotCl{if},
\textstyleMotCl{while }pour Java et Cobol) et on déconseille
d’utiliser les mots-clés du pseudo-code (tels que
\textstyleMotCl{\textsf{lire}},
\textstyleMotCl{\textsf{afficher}},
\textstyleMotCl{\textsf{pour}}…)
\item
Certains langages n’autorisent pas les caractères accentués (tels que
\textit{à, ç, ê, ø,} etc.) ou les lettres des alphabets non latins
(tel que ${\Delta}$) mais d’autres oui ; certains font la distinction
entre les minuscules et majuscules, d’autres non. En logique, nous
admettons dans noms de variables les caractères accentués du français,
par ex.~: durée, intérêts, etc.
\end{liste}
Il est impossible de décrire ici toutes les particularités des
différents langages, le programmeur se reportera aux règles spécifiques
du langage qu’il sera amené à utiliser.
\begin{Emphase}[exercice]{Exercice~:~Déclarer une date}
Déclarer le(s) variable(s) permettant de représenter la date
d’anniversaire de quelqu’un.
\end{Emphase}
\begin{Emphase}[exercice]{Exercice~:~Déclarer un rendez-vous}
Déclarer le(s) variable(s) permettant de représenter
l’heure de début, l’heure de fin et
l’objet d’un rendez-vous.
\end{Emphase}
\section{Opérateurs et expressions}
Les opérateurs agissent sur les variables et les constantes pour former
des \textbf{expressions}. Une expression est donc une combinaison
\textbf{cohérente} de variables, de constantes et d’opérateurs,
éventuellement accompagnés de parenthèses.
\subsection{Opérateurs arithmétiques élémentaires}
Ce sont les opérateurs binaires bien connus~:
\begin{center}
\tablehead{}
\begin{supertabular}{m{1cm}|m{12cm}}
\raggedleft \textstyleCodeInsr{+} & addition\\
\raggedleft \textstyleCodeInsr{-} & soustraction\\
\raggedleft \textstyleCodeInsr{*} & multiplication\\
\raggedleft \textstyleCodeInsr{/} & division réelle\\
\end{supertabular}
\end{center}
Ils agissent sur des variables ou expressions à valeurs entières ou
réelles. Plusieurs opérateurs peuvent être utilisés pour former des
expressions plus ou moins complexes, en tenant compte des règles de
calcul habituelles, notamment la priorité de la multiplication et de la
division sur l’addition et la soustraction. Il est aussi permis
d’utiliser des parenthèses, par exemple \textstyleCodeInsr{a – (b + c *
d)/x}. Tout emploi de la division devra être accompagné d’une réflexion
sur la valeur du dénominateur, une division par 0 entrainant toujours
l’arrêt d’un algorithme.
\subsection{DIV et MOD}
Ce sont deux opérateurs très importants qui ne peuvent s’utiliser
qu’avec des variables entières~:
\begin{center}
\tablehead{}
\begin{supertabular}{m{1cm}|m{12cm}}
\raggedleft \textstyleCodeInsr{DIV} & division entière\\
\raggedleft \textstyleCodeInsr{MOD} & reste de la division entière\\
\end{supertabular}
\end{center}
Par exemple, \textstyleCodeInsr{47 DIV 7} donne 6 tandis que
\textstyleCodeInsr{47 MOD 7} donne \textstyleCodeInsr{5}.
\subsection{Fonctions mathématiques complexes}
L’élévation à la puissance sera notée \textstyleCodeInsr{**} ou
\textstyleCodeInsr{\^{}} . Pour la racine carrée d’une variable x nous
écrirons $\sqrt{x}$ \textit{.} Attention, pour ce dernier, de veiller
à ne l’utiliser qu’avec un radicant positif~!
\textbf{Exemple}~:
$(-b+\sqrt{(b\ast \ast 2-4\ast a\ast c)})/(2\ast a)$
Mais on peut aussi accepter la notation mathématique usuelle
$\frac{-b+\sqrt{b^{2}-4\ast a\ast c}}{2\ast a}$
\marginicon{reflexion}
Pourquoi ne pas avoir écrit «~\textstyleCodeInsr{4ac}~» et
«~\textstyleCodeInsr{2a}~»~?
Si nécessaire, on se permettra d’utiliser les autres
fonctions mathématiques sous leur forme la plus courante dans la
plupart des langages de programmation (exemples~:
$sin(x)$, $tan(x)$, $log(x)$, $exp(x)$, ...)
\subsection{Opérateurs de comparaison}
Ces opérateurs agissent généralement sur des variables numériques ou des
chaines et donnent un résultat booléen.
\begin{center}
\tablehead{}
\begin{supertabular}{m{2cm}|m{11cm}}
\raggedleft \textstyleCodeInsr{=} & égal\\
\raggedleft \textstyleCodeInsr{{\textless}{\textgreater}}
ou \textstyleCodeInsr{${\neq}$} & différent de\\
\raggedleft \textstyleCodeInsr{\textless} & (strictement) plus petit que\\
\raggedleft \textstyleCodeInsr{\textgreater} & (strictement) plus grand que\\
\raggedleft \textstyleCodeInsr{${\leq}$} & plus petit ou égal\\
\raggedleft \textstyleCodeInsr{${\geq}$} & plus grand ou égal\\
\end{supertabular}
\end{center}
Pour les chaines, c’est l’ordre alphabétique qui
détermine le résultat (par exemple
\textstyleCodeInsr{{\textquotedbl}milou{\textquotedbl} {\textless}
{\textquotedbl}tintin{\textquotedbl}} est \textbf{vrai} de même que
\textstyleCodeInsr{{\textquotedbl}assembleur{\textquotedbl}
}\textstyleCodeInsr{${\leq}$}\textstyleCodeInsr{
{\textquotedbl}java{\textquotedbl}})
\subsection{Opérateurs logiques}
Ils agissent sur des expressions booléennes (variables ou expressions à
valeurs booléennes) pour donner un résultat du même type.
\begin{center}
\tablehead{}
\begin{supertabular}{m{1cm}|m{12cm}}
\raggedleft \textstyleCodeInsr{NON} & négation\\
\raggedleft \textstyleCodeInsr{ET} & conjonction logique\\
\raggedleft \textstyleCodeInsr{OU} & disjonction logique\\
\end{supertabular}
\end{center}
Pour rappel, \textstyleCodeInsr{cond1 ET cond2} n’est vrai que lorsque
les deux conditions sont vraies. \textstyleCodeInsr{cond1 OU cond2} est
toujours vrai, sauf quand les deux conditions sont fausses.
Veillez à mettre des parenthèses dans le cas de combinaisons de ET et de
OU~: \textstyleCodeInsr{(cond1 ET cond2) OU cond3} étant différent de
\textstyleCodeInsr{cond1 ET (cond2 OU cond3).} En cas
d’oubli de parenthèses, il faudra se rappeler que
\textstyleCodeInsr{ET} est prioritaire sur le \textstyleCodeInsr{OU}.
Pour rappel aussi, pour un booléen \textstyleCodeInsr{ok}~:
\textstyleCodeInsr{ok = faux} est équivalent à \textstyleCodeInsr{NON ok},
\textstyleCodeInsr{ok = vrai} est équivalent à \textstyleCodeInsr{ok} et
\textstyleCodeInsr{NON NON ok} est équivalent à \textstyleCodeInsr{ok}.
Dans les trois cas, nous préconiserons la seconde écriture.
\subsection{Évaluation complète et court-circuitée}
On définit deux modes d’évaluation des opérateurs \textstyleCodeInsr{ET}
et \textstyleCodeInsr{OU}~:
\begin{description}
\item[l’évaluation \textit{complète}]
pour connaitre la valeur de
\textstyleCodeInsr{cond1 ET cond2} (respectivement
\textstyleCodeInsr{cond1 OU cond2}), les deux conditions sont chacune
évaluées, après quoi on évalue la valeur de vérité de l’ensemble de
l’expression.
\item[l’évaluation \textit{court-circuitée}]
dans un premier temps, seule la
première condition est testée. Dans le cas du \textstyleCodeInsr{ET},
si \textstyleCodeInsr{cond1} s’avère faux, il est inutile d’évaluer
\textstyleCodeInsr{cond2} puisque le résultat sera faux de toute façon
; l’évaluation de \textstyleCodeInsr{cond2} et de l’ensemble de la
conjonction ne se fera que si \textstyleCodeInsr{cond1} est vrai. De
même, dans le cas du \textstyleCodeInsr{OU}, si
\textstyleCodeInsr{cond1} s’avère vrai, il est inutile d’évaluer
\textstyleCodeInsr{cond2} puisque le résultat sera vrai de toute façon
; l’évaluation de \textstyleCodeInsr{cond2} et de l’ensemble de la
disjonction ne se fera que si \textstyleCodeInsr{cond1} est faux.
\end{description}
Dans le cadre de ce cours, nous opterons pour la deuxième
interprétation.
Montrons son avantage sur un exemple.
Considérons l’expression
\textstyleCodeInsr{n }\textstyleCodeInsr{${\neq}$}\textstyleCodeInsr{ 0
ET m/n {\textgreater} 10}. Si on teste sa valeur de vérité avec une
valeur de \textstyleCodeInsr{n} non nulle, la première condition est
vraie et le résultat de la conjonction dépendra de la valeur de la
deuxième condition. Supposons à présent que \textstyleCodeInsr{n} soit
nul. L’évaluation court-circuitée donne le résultat \textbf{faux}
immédiatement après test de la première condition sans évaluer la
seconde, tandis que l’évaluation complète entrainerait un arrêt de
l’algorithme pour cause de division par 0~!
Notez que l’évaluation court-circuitée a pour conséquence la
non-commutativité du \textstyleCodeInsr{ET} et du
\textstyleCodeInsr{OU~}: \textstyleCodeInsr{cond1 ET cond2} n’est donc
pas équivalent à \textstyleCodeInsr{cond2 ET cond1}, puisque l’ordre
des évaluations des deux conditions entre en jeu.~Nous conseillons
cependant de limiter les cas d’utilisation de l’évaluation
court-circuitée et d’opter pour des expressions dont
l’évaluation serait similaire dans les deux cas. La justification
d’utiliser l’évaluation court-circuitée apparaitra dans plusieurs
exemples tout au long du cours.
\subsection{Manipuler les chaines}
Pour les chaines, nous allons introduire quelques notations\footnote{
Le lecteur averti reconnaitra la notation modulaire}
qui vont nous permettre de les manipuler plus facilement.
\begin{liste}
\item \textstyleCodeInsr{long(maChaine)}
donne la taille (le nombre de caractères) de la chaine
\textstyleCodeInsr{maChaine}.
\item \textstyleCodeInsr{car(maChaine,pos)}
donne le caractère en position \textstyleCodeInsr{pos}
(à partir de 1) dans la chaine \textstyleCodeInsr{maChaine}.
\item \textstyleCodeInsr{concat(maChaine1,maChaine2)}
concatène les chaines \textstyleCodeInsr{maChaine1}
et \textstyleCodeInsr{maChaine2}.
(ex~:~\textstyleCodeInsr{concat("Bon","jour")} donne \textstyleCodeInsr{"Bonjour"})
Cette fonction \textstyleCodeInsr{concat()} impose l’utilisation d’arguments
mais en admet un nombre indéfini. L’écriture
\textstyleCodeInsr{concat("La ","souris ","mange ","le ","chat.")} est donc valable.
\end{liste}
\subsection{Manipuler les caractères}
Introduisons également quelques notations pour les caractères.
\begin{liste}
\item \textstyleCodeInsr{chaine(car)} transforme le caractère \textstyleCodeInsr{car} en une chaine de taille 1.
\item \textstyleCodeInsr{estLettre(car)} est vrai si le caractère \textstyleCodeInsr{car} est une lettre
(idem pour \textstyleCodeInsr{estChiffre},
\textstyleCodeInsr{estMajuscule},
\textstyleCodeInsr{estMinuscule}).
\item \textstyleCodeInsr{majuscule(car)} donne la majuscule de la lettre \textstyleCodeInsr{car}
(idem pour \textstyleCodeInsr{minuscule}).
\item \textstyleCodeInsr{position(car)} donne la position de \textstyleCodeInsr{car} dans l’alphabet (ex~:~\textstyleCodeInsr{numLettre(’E’)} donne 5,
idem pour \textstyleCodeInsr{numLettre(’e’)}).
\item \textstyleCodeInsr{lettre(num)} l’inverse de la précédente (ex~:~\textstyleCodeInsr{lettre(4)} donne le caractère ’D’).
\end{liste}
\section{L’affectation d’une valeur à une variable}
Cette opération est probablement l’opération la plus importante. En
effet, une variable ne prend son sens réel que si elle reçoit à un
moment donné une valeur. Il y a deux moyens de donner une valeur à une
variable.
\subsection{Affectation externe }
On parle d’\textbf{affectation externe} lorsque la valeur à affecter à
une variable est donnée par l’utilisateur qui la communique à
l’exécutant quand celui-ci le lui demande~:~cette valeur est donc
\textit{externe} à la procédure \ (l’ordinateur ne peut la deviner
lui-même~!)
L’affectation externe est donc la primitive qui permet de recevoir de
l’utilisateur, au moment où l’algorithme se déroule,
une ou plusieurs valeur(s) et de les affecter à des variables en
mémoire. Nous noterons~:
\cadre{
\begin{pseudo}
\Read liste\_de\_variables\_à\_lire
\end{pseudo}
}
{\bfseries Exemples}
\cadre{
\begin{pseudo}
\Read nombre1, nombre2
\Read num1, den1, num2, den2
\end{pseudo}
}
L’exécution de cette instruction provoque une
pause dans le déroulement de l’algorithme~:~l’exécutant demande alors à
l’utilisateur les valeurs des variables à lire. Ces valeurs viennent
donc de l’\textit{extérieur~}; une fois introduites dans le système,
elles sont affectées aux variables concernées et l’algorithme peut
reprendre son cours.
Les possibilités d’introduction de données
sont nombreuses~:~citons par exemple l’encodage de
données au clavier, un clic de souris, le toucher d’un
écran tactile, des données provenant d’un fichier, etc.
\subsection{Affectation interne }
On parle d’affectation interne lorsque la valeur d’une variable est
«~calculée~» par l’exécutant de l’algorithme lui-même à partir de
données qu’il connait déjà~:
\cadre{
\begin{pseudo}
\Let nomVariable \Gets expression
\end{pseudo}
}
Rappelons qu’une \textbf{expression}
est une combinaison de variables et
d’opérateurs. L’expression a une valeur.
\subsubsection*{Exemples d’affectation corrects}
\cadre{
\begin{pseudo}
\Let somme \Gets nombre1 + nombre2
\Let denRes \Gets den1 * den2
\Let cpt \Gets cpt + 1
\Let delta \Gets b**2 – 4*a*c
\Let test \Gets a < b \RComment pour une variable logique
\Let maChaine \Gets "Bon"
\Let uneChaine \Gets concat(maChaine, "jour")
\end{pseudo}
}
\subsubsection*{Exemples d’affectation incorrects}
\cadre{
\begin{pseudo}
\Let somme + 1 \Gets 3
\RComment somme + 1 n’est pas une variable
\Let somme \Gets 3n
\RComment 3n n’est ni un nom de variable correct ni une expression correcte
\end{pseudo}
}
\subsubsection*{Remarques}
\begin{liste}
\item
Il est de règle que le résultat de l’expression à droite du signe
d’affectation ($\gets$) soit de
même type que la variable à sa gauche. On tolère certaines exceptions
:
\begin{liste}
\item
\textstyleCodeInsr{varEntière}{ $\gets$
}\textstyleCodeInsr{varRéelle}~:~dans ce cas le contenu de la variable sera
la valeur \textbf{tronquée} de l’expression réelle.
Par exemple si «~\textstyleCodeInsr{nb}~» est
une variable de type entier, son contenu après l’instruction
«~\textstyleCodeInsr{nb}{ $\gets$ }\textstyleCodeInsr{$15/4$}~»
sera 3
\item
\textstyleCodeInsr{varRéelle}{ $\gets$
}\textstyleCodeInsr{varEntière}~:~ici, il n’y a pas de perte de valeur.
\item
\textstyleCodeInsr{varChaine}{ $\gets$
}\textstyleCodeInsr{varCaractère}~:~équivalent à
\textstyleCodeInsr{varChaine}{ $\gets$ }\textstyleCodeInsr{chaine(varCaractère)}.
Le contraire n’est évidemment pas accepté.
\end{liste}
\item
Seules les variables déclarées peuvent être affectées, que ce soit par
l’affectation externe ou interne!
\item
Nous ne mélangerons pas la déclaration d’une variable et son
affectation interne dans une même ligne de code, donc pas
d’instructions hybrides du genre
\textsf{x}{ $\gets$ }\textstyleCodeInsr{2~:~entier} ou encore
\textsf{x~:~entier(0)}.
\item
Pour l’affectation interne, toutes les variables apparaissant dans
l’\textstyleCodeInsr{expression} doivent avoir été affectées
préalablement. Le contraire provoquerait un arrêt de l’algorithme.
\end{liste}
\section{Communication des résultats}
L’instruction de communication des résultats consiste à donner à
l’extérieur (donc à l’utilisateur) la valeur d’un résultat
calculé au cours de l’exécution de l’algorithme. Nous écrirons~:
\cadre{
\begin{pseudo}
\Write \textit{expression} ou \textit{liste de variables séparées par des virgules}
\end{pseudo}
}
qui signifie que la valeur d’une expression (ou celles des différentes
variables mentionnées) sera fournie à l’utilisateur (par exemple par un
affichage à l’écran ou par impression sur listing via l’imprimante,
etc.).
\subsubsection*{Remarques}
\begin{liste}
\item
Ce ne serait pas une erreur fondamentale de remplacer
\textstyleCodeInsr{lire} par \textstyleCodeInsr{recevoir} ou
\textstyleCodeInsr{afficher} par \textstyleCodeInsr{écrire}. Il n’y a
évidemment pas de confusion possible à partir du moment où l’on sait
qu’il s’agit de primitives d’échange entre l’extérieur et l’ordinateur
exécutant la procédure, mais par principe, il est conseillé d’utiliser
une syntaxe commune et limitée à un petit nombre de mots-clés.
\item
Comme pour l’affectation interne, on ne peut \textstyleCodeInsr{afficher}
que des expressions dont les variables qui la composent ont été
affectées préalablement.
\end{liste}
\section{Structure générale d’un algorithme}
La traduction d’un algorithme en pseudo-code constituera le contenu d’un
\textstyleMotCl{module}. Un module contient donc la solution
algorithmique d’un problème donné (ou d’une de ses parties). Sa
structure générale sera la suivante~:
\cadre{
\begin{pseudo}
\Module{nomDuModule}{}{}
\Stmt \textit{déclaration des variables et constantes utilisées dans le module}
\Stmt \textit{lecture des données}
\Stmt \textit{instructions utilisant les données lues}
\Stmt \textit{communication des résultats}
\EndModule
\end{pseudo}
}
\subsubsection*{Remarques}
\begin{liste}
\item {
Le code d’un algorithme sera toujours compris entre la
première ligne, appelée «~entête~» qui commence par
le mot «~module~»
suivi du nom choisi pour l’algorithme, et la ligne
finale «~fin module~». Le code compris entre l’entête
et la ligne finale sera toujours légèrement décalé vers la droite,
c’est un premier exemple
d’\textbf{indentation} indispensable pour la
lisibilité d’un programme, nous y reviendrons lors de
l’étude des structures alternatives et répétitives.}
\item {
Comme pour les variables, le nomDuModule devra être approprié au
contenu~! Par exemple, \textstyleCodeInsr{sommerNombres)},
\textstyleCodeInsr{additionnerFractions()} plutôt que
\textstyleCodeInsr{goPartez()}!
Le rôle des parenthèses qui suivent le nom du module sera expliqué plus
tard.}
\item {
Il va de soi que toutes les parties de cette structure générale ne
seront pas toujours nécessaires~:~certains algorithmes ne nécessiteront
pas de lecture de données, d’autres ne devront pas
communiquer des résultats...}
\item {
Pour la lisibilité, on veillera toujours à ce qu’un module
tienne sur une vingtaine de lignes (donc, en pratique, sur un écran
de 40 x 80 caractères ou une page). Ceci implique que si le module
devait être plus long, il faudrait le découper, comme nous le verrons
plus loin.}
\end{liste}
\bigskip
Analysons les algorithmes suivants~:
\cadre{
\begin{pseudo}
\Module{exempleValide}{}{}
\Declare{a, b, c}{entiers}
\Let a \Gets 12
\Let b \Gets 5
\Let c \Gets a - b
\Let a \Gets a + c
\Let b \Gets a
\EndModule
\end{pseudo}
}
\clearpage
\begin{center}
\begin{tabular}{*{4}{>{\centering\arraybackslash}m{3cm}}}
&
{a} &
{b} &
{c}\\\hline
\end{tabular}
\begin{tabular}{|m{3cm}|*{3}{>{\centering\arraybackslash}m{3cm}|}}
{\code{a, b, c~:~entiers}} &
{indéfini} &
{indéfini} &
{indéfini}\\\hline
{\code{a}{ $\gets$ } 12} &
{12} &
{indéfini} &
{indéfini}\\\hline
{\code{b}{ $\gets$ } 5} &
{12} &
{5} &
{indéfini}\\\hline
{\code{c}{ $\gets$ } \code{a - b}} &
{12} &
{5} &
{7}\\\hline
{\code{a}{ $\gets$ } \code{a + c}} &
{19} &
{5} &
{7}\\\hline
{\code{b}{ $\gets$ } \code{a}} &
{19} &
{19} &
{7}\\\hline
\end{tabular}
\end{center}
\bigskip
\cadre{
\begin{pseudo}
\Module{exempleInvalide}{}{}
\Declare{a, b, c}{entiers}
\Let a \Gets 12
\Let c \Gets a - b
\Let d \Gets c - 2
\EndModule
\end{pseudo}
}
\begin{center}
\begin{tabular}{*{4}{>{\centering\arraybackslash}m{3cm}}}
&
{a} &
{b} &
{c}\\\hline
\end{tabular}
\begin{tabular}{|m{3cm}|*{3}{>{\centering\arraybackslash}m{3cm}|}}
{\code{a, b, c~:~entiers}} &
{indéfini} &
{indéfini} &
{indéfini}\\\hline
{\code{a}{ $\gets$ } 12} &
{12} &
{indéfini} &
{indéfini}\\\hline
{\code{c}{ $\gets$ } \textstyleCodeInsr{a - b}} &
{12} &
{indéfini} &
{???}\\\hline
{\code{d}{ $\gets$ } \textstyleCodeInsr{c - 2}} &
{12} &
{indéfini} &
{???}\\\hline
\end{tabular}
\end{center}
\textstyleCodeInsr{c} ne peut pas être calculé car b n’a pas été initialisé;
quant à \textstyleCodeInsr{d}, il n’est même pas déclaré~!
\bigskip
À titre d’exemple, récrivons l’algorithme d’addition de fractions décrit
en début de chapitre~:
\cadre{
\begin{pseudo}
\Module{additionnerFractions}{}{}
\Declare{num1, den1, num2, den2, numRes, denRes}{entiers}
\Read num1, den1, num2, den2
\Let denRes \Gets den1 * den2
\Let numRes \Gets num1*den2 + num2*den1
\Write numRes, "/", denRes
\EndModule
\end{pseudo}
}
\textbf{Remarque~:}
rappelons que la fraction affichée n’est sans doute pas simplifiée.
Nous n’avons pas encore tous les atouts suffisants pour réaliser
cela à ce niveau. Patience~!
\section{Commenter un algorithme}
On n’insistera jamais assez sur la nécessité de \textbf{documenter} un
algorithme en y insérant des \textbf{commentaires} judicieux, clairs et
suffisants~! Un commentaire est un texte placé dans
l’algorithme et destiné à faciliter au maximum la
compréhension d’un algorithme par le lecteur (parfois une autre
personne, mais aussi souvent l’auteur qui se perd dans
son propre texte lorsqu’il s’y replonge après une
interruption). Ces commentaires (introduits par
«~\textstyleCodeInsr{//~»}) seront bien entendu ignorés par
l’exécutant de l’algorithme.
\cadre{
\begin{pseudo}
\LComment Lit les contenus de 2 fractions et affiche leur somme
\Module{additionnerFractions}{}{}
\Declare{num1, den1, num2, den2, numRes, denRes}{entiers}
\Read num1, den1, num2, den2
\Let denRes \Gets den1 * den2
\RComment calcul du dénominateur
\Let numRes \Gets num1*den2 + num2*den1
\RComment calcul du numérateur
\Empty \RComment la fraction n’est sans doute pas simplifiée
\Write numRes, "/", denRes
\EndModule
\end{pseudo}
}
Notez qu’un excès de commentaires peut être aussi nuisible qu’un
trop-peu pour la compréhension d’un algorithme. Par exemple, un choix
judicieux de noms de variables peut s’avérer bien plus efficace que des
commentaires superflus. Ainsi, l’instruction
\cadre{
\begin{pseudo}
\Let nouveauCapital \Gets ancienCapital * (1 + taux / 100)
\end{pseudo}
}
dépourvue de commentaires est bien préférable aux lignes suivantes~:
\cadre{
\begin{pseudo}
\Let c1 \Gets c0 * (1 + t / 100) \RComment calcul du nouveau capital
\Empty \RComment c1 est le nouveau capital, c0 est l’ancien capital, t est le taux
\end{pseudo}
}
Nous prendrons l’habitude de commenter chaque module en précisant ce qu’il fait.
\section{Compléments de pseudo-code}
\textstyleMotCl{\textmd{Présentons quelques notions algorithmiques peu
utilisées en première mais qui vous seront peut-être utiles dans
l’un ou l’autre des exercices.}}
\subsection{Constantes}
Une \textbf{constante} est une information pour laquelle nom, type et
valeur sont figés. La liste des constantes utilisées dans un algorithme
apparaitra dans la section déclaration des variables sous la forme
suivante~:
\cadre{
\begin{pseudo}
\Stmt \K{constante} PI = 3,14
\Stmt \K{constante} ESI
= {\textquotedbl}École Supérieure d’Informatique{\textquotedbl}
\end{pseudo}
}
\textstyleMotCl{\textmd{Il est inutile de spécifier leur type, celui-ci
étant défini implicitement par la valeur de la constante.}}
\subsection{Énumération}