Guide Complet des Langages C et Pascal
Guide Complet des Langages C et Pascal
Sommaire…………………………………………………………………………………………………………………..........................Page 1
Avertissement…………………………………………………………………………………………………………………..........................Page 4
Préface…………………………………………………………………………………………………………………....................................Page 4
............Page 5
1_Définition……………………………………………………………………………………………................................................Page 5
2_Les éléments d'un langage de programmation………………………………………………………………………………………Page 5
3_Historique……………………………………………………………………………………………...............................................Page 6
4_L'intérêt des langages de programmation…………………………………………………………………………………………....Page 6
5_Les différents types de langages de programmation………………………………………………………………………........Page 7
a_Les langages généralistes………………………………………………………………………………………………...................Page 7
b_Les langages spécialisés……………………………………………………………………………………………….....................Page 7
6_Les différents modes de programmation……………………………………………………………………………………………….Page 7
7_Les différentes étapes de l'exécution d'un programme informatique………………………………………………..........Page 8
8_L'occupation de l'espace mémoire lors de l'exécution d'un programme informatique…………………………………Page 13
………...Page 14
Introduction………………………………………………………………………………………………................................………....Page 15
Utiliser le compilateur Borland Pascal 7.0………………………………………………………………...........................….....Page 15
Error 200 : division by zero…………………………………………………………………………………….................................Page 15
PARTIE 1: GÉNÉRALITÉS SUR LE LANGAGE PASCAL………………………………………………………......Page 16
1_Historique………………………………………………………………………………………………………….................................Page 16
2_Architecture standard d'un programme en Pascal………………………………………………………………………............Page 16
3_La grammaire en Pascal………………………………………………………………………………………………........................Page 16
PARTIE 2: LES ÉLÉMENTS DE BASE DU LANGAGE PASCAL……………………………………………..........Page 17
1_L'affectation………………………………………………………………………………………………................................……….Page 17
2_Les incrémentations et décrémentations……………………………………………………………………………………………….Page 17
3_Les commentaires……………………………………………………………………………………………….................................Page 17
4_Les constantes……………………………………………………………………………………………….....................................Page 17
5_Les variables………………………………………………………………………………………………................................………Page 18
6_Les instructions d'entrée / sortie………………………………………………………………………………………………............Page 18
7_Les opérateurs arithmétiques, logiques et relationnels……………………………………………………........................Page 19
PARTIE 3: LES TYPES DE BASE DU LANGAGE PASCAL…………………………………………………..........Page 20
1_Les entiers………………………………………………………………………………………………................................………...Page 20
2_Les réels………………………………………………………………………………………………................................………......Page 20
3_Le type caractère………………………………………………………………………………………………..................................Page 20
4_Le type chaîne de caractère………………………………………………………………………………………………...................Page 21
5_Le type booléen………………………………………………………………………………………………....................................Page 22
PARTIE 4: LES FONCTIONS STANDARDS DU LANGAGES PASCAL…………………………………….….....Page 22
PARTIE 5: LES STRUCTURES ALTERNATIVES ET RÉPÉTITIVES……………………………………………....Page 23
1_La structure if...then………………………………………………………………………………………………..............................Page 23
2_La structure if...then...else……………………………………………………………………………………………….....................Page 23
3_La structure while...do………………………………………………………………………………………………...........................Page 23
4_La structure repeat...until……………………………………………………………………………………………….......................Page 24
5_La structure for...to et for...downto...do………………………………………………………………………………………………..Page 24
6_La structure case...of……………………………………………………………………………………………….............................Page 25
AVERTISSEMENT
Cet ouvrage s’adresse
Aux étudiants BTS dans les filières technologiques:
Informatique de gestion (1ere et 2eme année)
NTIC (1ere et 2eme année)
TELECOM (1ere et 2eme année)
Electronique (1ere et 2eme année)
2IM (1ere et 2eme année),
Aux étudiants Ingénieurs dans les filières technologiques,
A tous ceux qui sont passionnés de la programmation informatique et qui
souhaiteraient en repousser leurs limites.
PREFACE
L'essor de la technologie et son impact sur la vie des êtres humains n'est plus à prouver tant cet impact est au quotidien
et ses services indéniables. Mais cela est en très grande partie liée à l'essor de l'informatique.
Si les fusées sont lancées pour mettre en orbite les satellites nous permettant de communiquer, de suivre les émissions
de télévision, de s'échanger des informations, de prévoir le temps...
Si en industrie, la productivité s'est grandement améliorée et aussi en qualité...
Si en medecine, les analyses sont désormais effectuées dans un temps record, ainsi que les opérations chirurgicales...et
donc permettant de sauver des vies humaines...
Si la protection des biens, des personnes, des données, s'est améliorée et donc nous permettant de préserver nos
biens...
Si les transferts d'argent sont performants de nos jours et donc donnant du tonus à noa affaires...
Si...si...si...et si...Les exemples sont très variés et couvrent tous les domaines d'activité.
Tous ces bienfaits sont dus certes à l'informatique mais surtout à la partie "intelligente" de l'informatique que sont les
logiciels (programmes informatiques). En effet les logiciels permettent à l'ordinateur de s'adapter à nos besoins.
Et pour mettre en oeuvre des logiciels pour répondre à nos besoins, cela nécessite bien sûr un apprentissage. Ce
document a donc pour optique de vous aider dans cet apprentissage.
Ce document renferme deux(2) grandes parties:
TURBO PASCAL
Une partie consacrée aux cours
Une partie reservée aux corrections et traductions des exercices dans ce langage
TURBO C
Une partie consacrée aux cours
Une partie reservée aux corrections et traductions des exercices dans ce langage
1) Définition
Un langage est une façon d'exprimer sa pensée et de la communiquer. Il existe une multitude de langage: les langages
oraux, les langages écrits, les langages de signes (par exemple le langage des sourds-muets), les langages graphiques
(codes de la route), le langage informatique et bien d'autres langages utilisant divers modes de transmission.
Le langage informatique ou langage de programmation se définit comme cette façon d'exprimer sa pensée et de la
communiquer à l'ordinateur pour que celui-ci l'exécute.
Bref, un langage de programmation est un ensemble de mots et de règles à respecter afin d'agencer ces
mots pour former des phrases compréhensibles (instructions) par l'ordinateur et dont l'exécution de ces
phrases par celui-ci (l'ordinateur), exhausse notre volonté.
3) Historique
Les langages de programmation ont connu une évolution dans le temps, matérialisés par des générations. Chaque
génération de langages de programmation possède ses propres caractéristiques.
Le langage de la 1ère génération: Le tout premier langage de programmation, conçu dans les années 40, est le
langage machine (ou langage binaire), langage de base naturel de l'ordinateur. Nécessairement les tout premiers
programmes informatiques étaient en langage machine. Le langage machine consistait en un jeu d'instructions (son
vocabulaire) très détailles et sibylline (obscur, difficile à comprendre, à déchiffrer) qui commandent les circuits internes
de l'ordinateur.
C'était une tâche difficile et exposée aux erreurs car il fallait aligner des séquences de bits (suite de 0 et de 1) dont la
signification n'est pas évidente.
Exemple: 0101 010011 011010 qui signifie additionner (0101) les valeurs situées aux adresses mémoire 010011
et 011010.
Le langage de la 2e génération Par la suite, pour faciliter le travail, les programmes ont été écrits en donnant
directement les noms abrégés des opérations. On les appelés les codes mnémoniques c'est-à-dire les codes faciles à
retenir (par exemple ADD = additionner, DIV = diviser, SUB = soustraire, MOVE = transférer,…): c'est la naissance du
langage d'assemblage en 1950.
Exemple: MOVE.W A0, $5000 qui signifie transférer (MOVE) les 16 premiers bits (.w) du registre d'adresse A0,
vers la cellule mémoire portant l'adresse $5000 ($ pour dire que 5000 est écrit en hexadécimal).
Cependant l'écriture des programmes en langage d'assemblage restait une tâche fastidieuse et de tels programmes
dépendaient de la machine pour laquelle ils ont été conçus, c'est-à-dire pour exécuter sur une machine B un programme
P écrit en langage d'assemblage sur une machine A, il va falloir modifier le programme P pour l'adapter à la machine B.
En plus, il fallait avoir une bonne connaissance du fonctionnement de l'ordinateur utilisé.
Les langages de la 3e génération Très vite est apparu l'intérêt de définir des langages généraux utilisables sur
n'importe quel ordinateur et orientés problème c'est-à-dire permettant aux programmeurs de penser davantage à leur
problème à résoudre qu'à la machine: les langages évolués ou langages de haut niveau. 'Evolués' car leurs jeux
d'instructions sont plus proches de la pensée et du langage humain. Ce sont ces langages que nous utilisons de nos
jours.
Le premier langage « de haut niveau » fut Fortran (« Formula Translation ») conçu par John Backus à IBM en 1954 et
était destiné aux besoins scientifiques. Puis Algol (ALGOrithmic Language) a été développé en 1958 par un consortium
européen (groupe de chercheurs). C'est l'ancêtre du langage Pascal. Ensuite, Cobol (« COmmon Business Oriented
Language », développé en 1959 par un consortium comprenant le Department of Defense) était destiné aux logiciels de
gestion. Par la suite, d'autres langages furent introduits ensuite : Basic ( Beginner's All-Purpose Symbolic Instruction
Code ) en 1964, . Pascal (1970), C (1972), Lisp, Apl, PL/I, Logo, Edison, Simone, Ada, Modula-2, Modula-3,
Portal, Simula, Clu, Euclid, Alphard, Mesa, Gypsy, Peral, Bcpl, B, Objective C, Bliss, Corall, Jovial, Prolog,
Epsimone, Forth, Apt, Rtl-2, mumps, Gpss, tutor, Obéron, Eiffel, Sac…Bref, il en existe une centaine de nos jours
dont seule une dizaine seulement est majoritairement utilisée.
• SAS, SQL, Visual FoxPro, W-Langage: Langages spécialisés pour la communication avec une base de données,
• ASP. JSP (issu de Java, basé sur des Servlets), Python, PHP, XSP (issu de XML, soutenu par Apache), W-
Langage; JavaScript, ECMAScript, VBScript, applets écrites en Java, ActionScript, XSLT: Langages
pour les pages Web dynamiques,
• GPss, CSMP pour faire la simulation,
• Prolog pour l'intélligence artificielle,
• ABEL : langage pour la programmation électronique des PLD,
• Esterel, Lustre, Signal, Lucid Synchrone : langages de programmation synchrones pour les sytèmes réactifs
• R : langage pour l'outil de statistiques du même nom,
• xLispStat : langage pour l'outil de statistiques du même nom,
• VHDL, Verilog, SystemC: langages de description matérielle, permettant de synthétiser de l'électronique
numérique (descriptions de portes logiques) et d'en simuler le fonctionnement,
• VRML, description de scènes en trois dimensions.
a) La programmation impérative
L'on distingue dans cette tendance, les différents modes de programmation suivants:
La programmation séquentielle: Ici l'on définit un ordre chronologique entre les actions et ces actions sont
élémentaires (c'est-à-dire qu'elles sont de bas niveau autrement dite proches de la machine). De surcroît les actions
élémentaires que l'on définit ici, n'ont aucun lien logique entre elles. Elles sont donc indépendantes les unes des autres.
Enfin en programmation séquentielle, les programmes écrits ne convergent pas c'est-à-dire fonctionnent en continue
(l'exécution se fait en boucle, autrement dit, arrivé à la fin, on recommence l'exécution au début et ainsi de suite).
Utilisation: Elle est utilisée pour concevoir les programmes informatiques pour contrôler la partie
automatisme des systèmes de production et aussi leur supervision, pour détecter les pannes et anomalies
dans les avions, les fusées et satellites, en plein vol, dans les engins sous marins…
La programmation structurée: Ici les programmes ont une structure logique (autrement dit les actions
ont un lien entre elles) et convergent (c'est-à-dire l'exécution s'arrête à la fin du programme donc ne boucle
pas). Ici l'on utilise les structures de contrôle (SI….ALORS…SINON, POUR…FAIRE, TANT QUE…FAIRE….). Aussi elle
permet la décomposition des programmes en sous programmes. Selon le mode de découpage des programmes en sous
programmes, l'on distingue deux (2) sous modes de programmation structurée:
• La programmation procédurale qui décompose un programme en fonctions et procédures. Exemple:
Pascal
• La programmation fonctionnelle qui suppose que le programme est une seule fonction donc
découpée en sous fonctions. Exemple: C.
La programmation modulaire dans laquelle un programme peut faire référence à d'autres programmes
(autrement dit, utiliser des éléments se trouvant dans d'autres programmes) et donc utiliser des instructions qui ne sont
pas définies dans le programme en question mais se trouvant dans les programmes référencés. Les programmes
référencés sont les fameuses bibliothèques utilisées dans les programmes.
Exemples: En Pascal: Uses CRT; (* La bibliothèque ici est CRT *)
En C: #include <stdio.h> (* La bibliothèque ici est stdio.h *)
(Voir le 7- du présent chapitre).
La programmation orientée objet: Elle a pour but principal de mieux programmer et vite. Pour cela, elle
utilise des objets (qui sont des structures de données particulières). Un objet = structures de données + l'ensemble des
opérations applicables à cet objet + la définition de ces opérations appelées méthodes.
La programmation système: C'est un type de programmation qui vise au développement de programmes
qui font partie du système d'exploitation d'un ordinateur ou qui en réalisent les fonctions. Elle se distingue de la
programmation des applications en ce qu'elle s'intéresse non pas au traitement des données, mais aux interfaces, aux
protocoles et à la gestion des ressources, telles que le temps et l'espace. Elle inclut, en outre, l'accès aux fichiers, la
programmation du clavier, de l'écran, des modems, la programmation réseau, et, en général, la programmation de tous
les périphériques qui font entrer ou sortir de l'information d'un ordinateur, de la mémoire vive et des processeurs.
La programmation système utilise des instructions de bas niveau c'est-à-dire des instructions qui communiquent
directement avec le matériel.
Programmation événementielle: Le programme sera principalement défini par ses réactions aux différents
événements qui peuvent se produire(clic sur la souris, appui sur telle ou telle touche du clavier...). Bref, le programme
reégit dès que vous exercez une action sur l'ordinateur.
Exemple: En Visual Basic, sous Windows ou dans une page Web, lorsque vous cliquez par exemple sur le bouton
Enregistrer, ce que vous avez saisi s'enregistre automatiquement.
Programmation concurrente ou parallèle: Elle permet de créer des programmes qui lors de l'exécution de
ceux-ci, une partie du programme sera exécutée par un ordinateur A, une autre partie du même programme sera
exécutée par un autre ordinateur B, une autre partie du même programme sera exécutée par un autre ordinateur
C…Bref le même programme sera exécuté par des ordinateurs différents (en raison d'une partie par ordinateur et les
différentes exécutions au iveau des ordinateurs se passent de manière simultanée) et reliés en réseau (c'est ce que l'on
appelle l'informatique distribuée ou repartie). Cela permet d'atteindre une grande performance.
b) La programmation déclarative
L'on distingue dans cette tendance:
La programmation logique, pour laquelle les composants d'une application sont des relations
logiques. Elle est utilisée en Intelligence Artificielle (domaine de l'informatique consistant à tenter de simuler sur un
ordinateur, les comportements dits 'intelligents' de l'être humain). L'intelligence artificielle est utilisée dans les jeux, la
démonstration de théorèmes, la reconnaissance de la parole, de la vision, la résolution des problèmes nécessitant une
expertise liée au domaine spécifique (diagnostic médical par exemple).
Exemples: Prolog, Oz, Python, PyPy.
Edition de texte
Programme
source
Edition de lien
Programme
objet 2
Chargement
Programme
exécutable
Exécution
Résultat
L'édition de texte: C'est à ce niveau que l'on saisit au clavier notre programme (qui n'est que la traduction de
l'algorithme dans le langage de programmation) en lançant le langage de programmation. Cette opération aboutit à
notre programme source.
La traduction: Cette étape consiste d'abord à détecter les éventuelles erreurs syntaxiques et sémantiques qui se
trouvent dans notre programme source. Tant qu'il y a des erreurs dans le programme source, l'exécution reste bloqué à
ce niveau. Puis, s'il n'y a plus d'erreur dans le programme source, à traduire le programme source dans le langage
binaire (le programme binaire ainsi obtenu est appelé programme objet) et cela suivant deux manières distinctes:
Le mode interprété et le mode compilé.
Le mode interprété: Ici, la traduction en langage binaire, lorsqu'il n'y a pas d'erreur, et son exécution, se fait en une
seule étape et ceci ligne par ligne. (Ici on traduit chaque ligne du programme en langage binaire et en même temps on
l'exécute).
Ce mode bien que peu usuel, est utilisé est lors du dépistage de bugs dans le programme (Les erreurs qui sont dans le
programme).
Le mode interprété est réalisé par l'interpréteur, qui est un programme inclus dans le langage de programmation.
Le mode compilé: Ici, l'on traduit d'abord le programme source en langage binaire, lorsqu'il n'y a pas d'erreur. Et si l'on
veut exécuter le programme binaire obtenu (ou programme objet), une deuxième étape est donc nécessaire. (Ici on
traduit dans un premier temps le programme entier en langage binaire. Puis l'on passe à l'exécution de tout le
programme entier dans un second temps). C'est ce mode qui est le plus utilisé.
Le mode compilé est réalisé par le compilateur, qui est un programme inclus dans le langage de programmation.
Fonctionnement du compilateur
Le travail du compilateur se divise en six (6) phases:
• L'analyse lexicale,
• L'analyse syntaxique,
• L'analyse sémantique,
• La génération de code intermédiaire,
• L'optimisation du code,
• La génération de code objet (binaire).
L'analyse lexicale: C'est la première phase de la compilation. Ici le compilateur lit tout le programme source
en entier et regroupe dans un endroit appelé table des symboles, tous les noms de variables, de constantes, des
fonctions et procédures, tous les mots clés, tous les séparateurs, tous les opérateurs arithmétiques, logiques, de
comparaison, des nombres….trouvés dans le programme source. La table des symboles va servir au niveau des étapes à
venir.
Ici également, le compilateur élimine toutes les informations inutiles à la compilation telles que les commentaires. C'est
en effet à ce niveau que le compilateur détecte les erreurs telles que des identificateurs trop longs, des caractères
n'appartenant pas au vocabulaire du langage ou encore des nombres illégaux.
L'analyse syntaxique: L'analyse syntaxique va s'appuyer sur la table des symboles obtenus lors de l'analyse
lexicale pour vérifier si chaque élément qui s'y trouve, est correct par rapport à la syntaxe du langage de programmation
utilisé (par exemple il faut un point virgule entre deux instructions…). C'est en effet ici que le compilateur va vérifier si la
grammaire du langage de programmation utilisé, est appliquée par le programmeur. (Genre Sujet-Verbe-Compléments
par exemple). A la fin de cette étape, le compilateur génère l'arbre syntaxique qui est conçu comme suit: Exemple: Soit
l'instruction ci-après: B ← C + 53;
L'arbre syntaxique généré à partir de cette instruction est:
Programme
……………………………..
Instruction ;
Affectation
Nom Expression
←
C + Nombre Chiffre
Dizaine Unité
5 3
C'est en effet à ce niveau que le compilateur détecte les erreurs telles que parenthèses non fermées, structures de blocs
ou instructions mal construites, manque de délimiteurs (ce sont la virgule, le point virgule…), …
L'analyse sémantique: Ici il s'agit de l'analyse du sens, de la signification des phrases (instructions) que le
programmeur a écrites dans le programme source. Pour cela, le compilateur s'appuie sur l'arbre syntaxique et la tables
des symboles. Sa tâche principale ici est de vérifier la concordance des types, ce qui revient à vérifier que chaque
opérateur travaille sur des opérandes qui sont autorisés par le langage de programmation en question.
Exemples: VAR E, A: ENTIER; B, C: REEL; D:CHAINE [20];
A ← " Mathieu"; est une erreur qui sera détectée à ce niveau car A est un entier et non une chaîne de caractères
E ← B + C; est une erreur qui sera détectée à ce niveau car l'on veut ranger la somme de deux (2) réels (qui est un
réel) dans un entier.
B ← C MOD B; est une erreur qui sera détectée à ce niveau la fonction MOD ne s'applique pas sur les réels.
C'est en effet à ce niveau que le compilateur détecte les erreurs telles que l'utilisation d'identificateurs non déclarés ou
déclarés plusieurs fois, incompatibilité de type entre opérateurs et opérandes…
La génération de code intermédiaire: Ici le programme source est traduit dans un langage intermédiaire,
proche du langage binaire. L'intérêt de cette étape réside dans la portabilité des programmes c'est-à-dire le fait de
pouvoir exécuté le même programme sur une machine A et aussi sur une autre machine B différent, sans modifier le
programme.
L'optimisation du code: Cette étape consiste à améliorer le code intermédiaire généré pour le rendre plus
rapide à l'exécution et moins encombrant dans la mémoire centrale. Pour cela, le compilateur enlève les redondances
pour minimiser le nombre final d'instructions et aussi d'évaluer les expressions qui peuvent l'être. Exemple: P ← 3,145 *
10; C ← P * B; Ainsi au niveau de cette étape de la compilation, les 2 instructions seront remplacées par une seule qui
est:
C ← 31,14 * B;
La génération de code objet (code binaire): Ici le compilateur va enfin traduire le code intermédiaire optimisé
(du corps du programme principal et non des sous programmes) dans le langage binaire du microprocesseur
installé sur l'ordinateur sur lequel vous exécutez le programme.
L'édition de lien: C'est le fait de combiner plusieurs programmes objet en un seul. Cette opération est réalisée par
un programme appelé l'éditeur de lien et inclus dans le programme compilateur. Dans l'écriture d'un programme, l'on
utilise en plus du corps du programme principal, souvent des fonctions, des procédures et des bibliothèques (ce sont
fichiers qui contiennent des codes binaires et qui facilitent la programmation car ils contiennent des fonctions
"prêtes à porter" ( ces instructions ne font pas parties du langage de programmation donc viennent enrichir les
instructions du langage de programmation) que le programmeur peut utiliser sans se préoccuper de la façon dont
ces fonctions ont été conçues. Mais avant d'utiliser ces fonctions, il faut inclure dans le programme la
bibliothèque qui les contient comme ça si le langage de programmation ne connaît pas ces fonctions, il ira
dans ces bibliothèques pour voir comment les utiliser).
Ainsi à ce niveau de l'exécution du programme, les fonctions et les procédures conçues par le programmeur sont
traduites séparément en langage binaire (le corps du programme principal a été déjà traduit en langage binaire
au niveau de l'étape précédente c'est-à-dire au niveau de la génération de code. Les bibliothèques sont
déjà en langage binaire). Une fois la traduction des fonctions et procédures terminée, l'éditeur de lien va ensuite
assembler les codes binaires des fonctions, des procédures, du corps du programme principal et des éventuelles
bibliothèques, pour former un seul tout en langage binaire (ou code objet).
Traduction Traduction
Traduction Code objet de bibliothèque
Edition de lien
Le chargement: Le programme objet obtenu après l'édition de liens, doit encore être chargé en mémoire centrale
pour être mieux exécuté car il faut placer le programme dans une zone de la mémoire centrale de sorte sue
l'exécution soit facilitée.
L'exécution: Ici le microprocesseur exécute les ordres contenus dans les instructions traduits en binaire pour
produire les résultats escomptés.
Tas
(Variables dynamiques)
Pile système
Code du programme
principal
Le tas (heap en anglais) est réservé aux variables gérées dynamiquement grâce aux pointeurs.
La pile (stack en anglais) est réservée aux variables locales des fonctions et procédures ainsi qu'aux valeurs passées par
valeur aux fonctions et procédures.
Ainsi les instructions du programme principal sont à part, celles des fonctions et procédures, également à part; de même
pour les variables globales statiques, les variables dynamiques, les variables locales
INTRODUCTION
Le langage Pascal offre une très bonne approche de la programmation. Très utilisé dans le milieu scolaire, il permet
d'acquérir des notions solides que l'on retrouve dans tous les autres langages. Les éléments de base de la
programmation tels que : pointeurs, types, tableaux, procédures, fonctions, graphismes... et bien d'autres vous sont
expliqués avec le maximum de pertinence, de simplicité et d'efficacité, puisque vous êtes déjà très nombreux à vous fier
à ce cours.
Ce cours sur la programmation en Turbo Pascal 7.0 est destiné à toute personne désireuse d'augmenter ses
connaissances au niveau de la programmation. Que ce soit dans le cadre de l'enseignement ou pour votre propre intérêt
personnel, vous avez décidé d'apprendre ce langage fort archaïque mais qui a néanmoins le mérite de former à la
logique informatique. Le langage Pascal est très structuré et constitue en lui-même une très bonne approche de la
programmation. Vous découvrirez dans les pages qui vont suivre, les bases de la programmation en général : les
structures de boucle et de contrôle, l'utilisation de la logique booléenne, la chronologie d'exécution du code...
Ces notions de base vous servirons si vous décidez de changer de langage de programmation, car les principes de base
(et même les instructions de base) sont les mêmes.
Dans la vie courante, nous n'avons pas pour habitude de nous limiter au strict minimum lorsqu'on communique, ici, ce
principe est bafoué, puisque d'une langue vivante complexe vous allez passer à un langage strict, rigide et pauvre. Issue
des mathématiques, cette langue exacte est par essence optimisée et simplifiée. Par delà, l'apprentissage d'un langage
informatique forme à la systémique mathématico informatique, vous apprendrez à dominer le comportement de la
machine et à être plus clair et précis dans votre manière de construire vos idées.
Utiliser le compilateur Borland Pascal 7.0
Pour ouvrir un fichier, aller dans le menu File/Open... ou taper la touche fonction F3.
Pour exécuter un programme, aller dans le menu Run/Run ou taper la combinaison de touches Ctrl+F9.
Pour compiler "correctement" un exécutable, aller dans le menu Compile/Make (ou /Compile ) ou taper F9 on
obtient ainsi des exécutables de meilleurs qualité qui pourront être utilisés sur d'autres ordinateurs.
Si vous avez omis de mettre une pause à la fin d'un programme, ou si vous désirez tout simplement avoir sous les yeux,
la dernière page d'écran, il vous suffit d'allez dans le menu : Debug/User Screen ou tapez ALT+F5.
Pour une aide, aller dans le menu Help/Index ou taper Shift+F1. Pour obtenir de l'aide sur une instruction qui
apparaît dans un script, placez le curseur de la souris dessus et allez dans le menu Help/Topic Search, une fenêtre
apparaîtra alors.
Si un problème a lieu lors de l'exécution d'un programme, utilisez le débugger : Debug/Watch. Une fenêtre apparaît en
bas de page. Cliquez sur Add et tapez le nom de la variable dont vous désirez connaître la dernière valeur.
Erreur 200 : Division par zéro
Nombreux sont ceux d'entre vous qui ont eut un grave pépin avec le compilateur Turbo Pascal. En effet, l'exécution d'un
programme utilisant l'unité Crt provoque un bug chez les ordinateurs récents du type Pentium III. L'erreur observée est
la suivante : Error 200 : division by zero.
Mais d'où vient cette erreur ?
Les nouveaux microprocesseurs sont devenus incompatibles avec les opérations de bas niveau écrites dans l'unité Crt
(fichier [Link]). En effet, les instructions de cette unité traitent l'heure système dont le codage sur le
microprocesseur a changé dans les récents modèles d'ordinateurs.
Comment y remédier ?
Pour pouvoir utiliser de nouveau l'unité Crt dans vos programmes, il vous faut soit changer quelques fichiers propres au
compilateur soit appliquer un patch à chacun de vos programmes compilés avant de pouvoir les exécuter normalement.
Notez que la compilation du programme ne provoque aucune erreur, c'est seulement son exécution qui provoque cette
erreur de division par zéro.
Où se procurer un patch ?
Sur le site web de Borland (éditeur du compilateur Pascal le plus répandu), ou sur beaucoup d'autres sites que vous
trouverez en effectuant une courte recherche dans un moteur. Par exemple sur [Link], faites la recherche
"Crt+patch" et télécharger les patchs proposés sur les sites trouvés par le moteur de recherche.
Télécharger les patchs :
Ces patchs étant freeware, vous êtes autorisés à vous les proposer en téléchargement. Vous avez deux types de patch à
votre disposition, n'en utilisez qu'un seul.
Le premier patch : [Link] ([Link] contient un fichier à copier dans
le répertoire /BIN de votre compilateur puis à compiler. Les prochains programmes que vous compilerez n'auront alors
plus aucun problème et s'exécuteront normalement.
Le second patch : [Link] ([Link] contient toutes les explications
techniques détaillées (en anglais) sur l'unité Crt ainsi qu'un programme à exécuter en lui envoyant en paramètre votre
programme compilé. Ce dernier sera modifié et marchera très bien. L'inconvénient de ce patch, c'est qu'il faut l'exécuter
sur chaque programme que vous fabriquez.
: Cette partie concerne l'inclusion de bibliothèque ou unité. En effet le langage Pascal, de manière native, n'est pas
riche en instructions. Des personnes ont pensé à l'enrichir en créant elles mêmes leurs propres instructions, qu'elles les
ont mises dans des bibliothèques ou unités (ce sont des fichiers). Ainsi si vous utilisez une ou plusieurs instructions qui
ne sont pas propres à Pascal, il faut signaler à Pascal où ces instructions sont définies pour que Pascal puisse les utiliser.
Cela se fait par uses nom_bibliothèque;
Exemple: uses crt; (* Le nom de la bibliothèque est crt. C'est la plus utilisée *)
uses dos; (* Le nom de la bibliothèque est dos *)
Note: Si dans votre programme, vous utilisez plusieurs bibliothèques, il faudrait les aligner mais séparées par
une virgule, et mettre un point virgule à la fin, comme suit: uses crt, dos;
Note:Cette partie est facultative c'est-à-dire que si vous utilisez des instructions typiquement de Pascal, dans ce cas ne
faites pas figurer cette partie dans le programme.
Comment savoir l'unité d'une instruction? Cliquez à l'intérieur de l'instruction puis Help/Topic Search. Et delà
une fenêtre apparaît vous indiquant le nom de la bibliothèque dans laquelle se trouve l'instruction.
: Cette partie est réservée à la déclaration des constantes. Elle est facultative c'est-à-dire que si dans votre
programme, vous n'avez pas besoin de constante alors ne faites pas figurer cette partie dans le programme.
Exemple: const p = 0; (* Je viens de définir une constante du nom de p *)
T = 11.5; (* Je viens de définir une autre constante du nom de T *)
Note: Si vous utilisez plusieurs constantes, vous pouvez les définir sur la même ligne mais séparées par des
points virgules ou une constante par ligne. Exemple: const p = 10; t = 11.5;
: Cette partie est réservée à la déclaration des types définis par l'utilisateur lui-même (enregistrement, ensemble,
énuméré…). Elle est facultative.
et : Cette partie est destinée à la définition des fonctions et procédures. Elle est facultative.
Cette partie est réservée à la déclaration des variables.
C'est là que débute le corps du programme principal.
3) Grammaire du Pascal
Un nom de programme respecte les règles liées aux identificateurs (cf plus bas) et ne peut pas contenir le caractère
point "."
Un programme principal débute toujours par begin et se termine par end. (avec un point). Alors qu'un sous-
programme (ou fonction, procédure, bloc conditionnel...) commence lui aussi par Begin mais se termine par End ; (sans
point mais avec un point-virgule).
Chaque instruction doit se terminer avec un point-virgule. Il n'y a pas d'exception à la règle hormis Begin et
l'instruction précédent else.
Il est toléré de mettre plusieurs instructions les unes à la suite des autres sur une même ligne du fichier mais il est
recommandé de n'en écrire qu'une par ligne : c'est plus clair et en cas de bogue (erreur), on s'y retrouve plus aisément.
Les noms de constantes, variables, procédures, fonctions, tableaux, etc. (appelés identificateurs) doivent êtres des
noms simples, par exemple, n'appelez pas une variable comme ça: x4v_t3la78yugh456b2dfgt mais plutôt comme
cela : pt ou j ou encore a…Les noms compliqués ne sont pas interdits mais c'est une question de commodité.
Les identificateurs doivent impérativement être différents de ceux d'unités utilisées, de mots réservés du langage
Pascal et ne doivent pas excéder 127 caractères. (une(1) lettre au minimum).
Les identificateurs ne doivent pas contenir de caractères accentués, ni d'espace, ni de point et ni les caractères
suivants : @, $, &, #, +, -, *, /. Mais le caractère de soulignement est autorisé. De plus, Turbo Pascal ne différencie
aucunement les majuscules des minuscules. Les chiffres sont acceptés hormis en première place.
Un identificateur ne peut être égale à un mot réservé du langage pascal !
Mots réservés du langage Pascal
AND, ARRAY, ASM, BEGIN, CASE, CONST, CONSTRUCTOR, DESTRUCTOR, DIV, DO, DOWNTO, ELSE, END, EXPORTS,
FILE, FOR, FUNCTION, GOTO, IF, IMPLEMENTATION, IN, INHERITED, INLINE, INTERFACE, LABEL, LIBRARY, MOD, NIL,
NOT, OBJECT, OF, OR, PACKED, PROCEDURE, PROGRAM, RECORD, REPEAT, SET, SHL, SHR, STRING, THEN, TO, TYPE,
UNIT, UNTIL, USES, VAR, WHILE, WITH, XOR.
Note: Pour leur utilisation, les mots clés de Pascal peuvent être écrits en majuscule ou en minuscule. Peu importe la casse.
3) Les commentaires
N'hésitez pas à insérer des commentaires dans votre code, cela vous permettra de comprendre vos programmes bien
plus tard après les avoir écrits, et ainsi d'autres personnes n'auront aucun mal à réutiliser vos procédures, fonctions...
Procédez ainsi : { ici votre commentaire entre accolades } ou (* ici vos commentaires entre parenthèses et
étoiles *)
Vos commentaires peuvent tenir sur une seule ligne comme sur plusieurs. Vous pouvez aussi mettre en commentaire
une partie de votre programme. Pour un comentaire sur une seule ligne, utiliser (*...*) et pour celui sur plusieurs lignes,
utiliser {....}
4) Les constantes
La déclaration des constantes est toujours précédée du mot clé const.
Syntaxe : Const nom_constante = valeur ;
Exemples :
Const nom = 'CyberZoïde' ;
Const TVA = 20.6 ;
Const d = #66 ; permet d'attribuer à la constante d le caractère dont le code ASCII est 66 c'est-à-dire le caractère B. En
fait cela équivaut à écrire const d ='B';
Le compilateur décide automatiquement d'affecter à la constante le type de base compatible le plus économique. Ceci
est totalement transparent au programmeur. Par exemple, lorsqu'il trouve un nombre à virgule affectée à une constante,
il lui spécifie le type Real. Ou encore si vous affectez un caractère à une constante, celle-ci sera de type Char et non de
type String. Mais il vous reste possible de forcer le type de la constante par les deux points (:) que vous connaissez déjà
pour les variables. De plus, cette déclaration de type à une constante en plus de sa valeur est dans certains cas
indispensable, si vous souhaitez leur donner une valeur qui n'est pas d'un type de base du compilateur (par exemple un
ensemble ou un type que vous avez vous-même défini avant la constante).
Syntaxe :
Const identificateur : type_de_la_constante = valeur ;
Exemples :
Const Nmax : Longint = 60000 ;
Const db: String = '*' ;
Note: Les constantes peuvent être de tout type sauf de type fichier.
On peut tout aussi bien affecter aux constantes des expressions dont le résultat sera évalué à la compilation.
Syntaxe : Const identificateur = expression ;
Exemples :
Const pt = ord('A') ; (* permet de ranger dans pt, le code ASCII du caractère A c'est-à-dire 65 *) ( Voir la dernière page de ce document
concernant les codes ASCII *).
Const taux = (exp(10) - (3*Pi))/100 ;
Const nom = 'Cyber'+'Zoïde' ; (* dans ce cas la constante nom recevra comme valeur 'CyberZoïde' *)
Const mi : integer = chr(length(nom)) ; (* permet de ranger dans mi le caractère dont le code ASCII vaut la longueur de la variable nom *)
( Voir le chapitre 7 concernant les chaînes de caractères).
5) Les variables
Toutes les variables doivent êtres préalablement déclarées avant d'être utilisées dans le programme, c'est-à-dire qu'on
leur affecte un type . On peut les déclarer de divers manières :
Au tout début du programme avec la syntaxe: VAR nom de la variable : type ; elles seront alors valables pour le
programme dans son intégralité (sous-programmes, fonctions, procédures...) (variables globales).
Au début d'une procédure ou d'une fonction, avec la syntaxe précédente. Elles ne seront valables que dans la
procédure ou la fonction où elles ont été déclarées (variables locales).
Exemple: var t: integer; (* Je viens de déclarer une variable du nom de t qui va contenir un entier *).
Note: Dès la déclaration des entiers et réels, Pascal leur attribue de prime abord la valeur zéro (0).
Les instructions d'entrée: Ce sont readln et read. Elles permettent à l'utilisateur de rentrer une valeur qui sera utilisée
par le programme.
L'instruction Readln provoque le retour Chariot c'est-à-dire que le curseur passe au début de la ligne suivante. Par contre
l'instruction read ne provoque pas de retour Chariot, c'est-à-dire que le curseur reste sur la même ligne courante.
Note: Je vous conseillerai d'utiliser l'instruction readln.
Syntaxes : Readln (variable) ; ou Readln (variable1, variable2, …variable n) ;
Read(variable) ; ou Read (variable1, variable2, …variable n) ;
Autre utilisation de l'instruction readln ou read: Elles permettent de marquer une pause afin de permettre à l'utilisateur
de voir afficher à l'écran les informations désirées. Dans ce cas, il faudra les utiliser à la fin du programme comme par
exemple:
Program essai;
Uses crt;
Var nom : String ;
begin
Write('Entrez votre nom : ') ;
Readln(nom) ;
Writeln('Votre nom est ', nom) ;
Readln ; (*Permet de marquer une pause afin de permettre à l'utilisateur de voir ce qui est affiché à l'écran *)
end.
Ce programme exemple1 déclare tout d'abord la variable nommée nom comme étant une chaîne de caractère (String).
Ensuite, dans le bloc programme principal, il est demandé à l'utilisateur d'affecter une valeur à la variable nom qui est
initialisée automatiquement (valeur nulle) à chaque démarrage du programme. Ensuite, il y a affichage de la valeur de la
variable et attente que la touche entrée du clavier soit appuyée (Readln), pour quitter le programme.
L'équivalent de l'instruction Readln est ReadKey qui donne une valeur à une variable de type Char.
Syntaxe : x := ReadKey ; (* Le premier caractère que vous saisirez sera rangé dans la variable x de type caractère *)
Il existe une équivalence à cette commande très utile pour sortir d'une boucle : KeyPressed.
Syntaxe :
Repeat...
Instructions;..
Until KeyPressed ; (* Exécuter les instructions jusqu'à ce qu'on appuie sur n'importe quelle touche du clavier *)
Program mat ;
Uses crt ;
Var I : integer ;
Const bornesup=10000 ;
begin
I:=1;
Repeat
writeln(' La valeur de I, 'est:', I) ;
inc(I,2) ;
Until (i=bornesup) or KeyPressed ; (* Exécuter tout ce qui se trouve entre repeat et until, jusqu'à ce que i soit = à
Readln; bornesup ou bien jusqu'à ce qu'on appuie sur n'importe quelle touche du clavier *)
end.
Ce programme mat répète une boucle jusqu'à qu'une valeur soit atteinte (bornesup) mais s'arrête si on appuie sur une
touche (keypressed). L'instruction inc(I,2); incrémente le contenu de la variable I de 2; cette dernière étant de type
integer (entier).
Types d'entier Caractéristiques Nombre d'octets occupés en mémoire Intervalle des valeurs possibles
integer 2 octets [-32 768; +32 767]
Shortint Entiers signés 1 octet [-128; +127]
Longint 4 octets [-2 147 483 648; +2 147 483 647]
Byte 1 octet [0; +255]
Entiers non
Word 2 octets [0; +65 535]
signés
dword 4 octets [0; +232 - 1]
2) Les réels
Ce sont: single, real, double, extended
Type de réel Nombre d'octets occupés en mémoire Intervalle de valeurs possibles (en valeur absolue)
real 6 octets [ 2,9*10-39 ; 1,71038 ]
single 4 octets [ 1,5*10-45 ; 3,41038 ]
double 8 octets [ 5*10-324 ; 1,710308 ]
extended 10 octets [ 3,4*10-4951 ; 1,1*104932 ]
3) Le type caractère
Le type CARACTERE est noté char en Pascal. Un char occupe 1 octet en mémoire centrale et chaque caractère est
identifié par un numéro unique appelé code ASCII (voir la dernière page de ce document).
En Pascal, une constante ou valeur de type caractère, est placé entre quotte (' ').
a) Déclaration
Elle se fait dans la partie VAR comme suit:
Syntaxe: Exemple
var var
Nom_caractère: char; t: char;
b) Affectation
Exemples :
espace :=' '; permet d'attribuer le point (.) à la variable espace de type caractère.
lettre :=#80; permet d'attribuer à la variable lettre de type caractère, le caractère dont le code ASCII est 80.
lettre:= espace; permet d'attribuer à lettre, le contenu de espace. Dans notre cas, lettre recevra le point (.).
c) Les fonctions utilisables sur les caractères
Ce sont ord, chr, UpCase, pred et succ.
Ord: permet de renvoyer le code ASCII d'un caractère. Syntaxe: ord ('caractère'); ou ord (nom_variable);
Ainsi ord ('A'); va renvoyer 65 (65 est le code ASCII de A).
Chr: permet de connaître le caractère, étant donné son code ASCII. C'est la réciproque de la fonction ord.
Syntaxe: chr (code ASCII) ou #code ASCII simplement.
Ainsi writeln(chr(65)); affichera A.
Writeln (#65); affichera A.
c :=Chr(102); permet d'attribuer à la variable c, le caractère dont le code ASCII est 102, soit c recevra f.
Pred: permet de savoir le caractère qui précède un caractère en question.
Syntaxe: pred(nom_variable); ou pred('caractère');
Ainsi pred('c'); va renvoyer b
Succ: permet de savoir le caractère qui suit un caractère en question. C'est la réciproque de PRED.
Syntaxe: succ(nom_variable); ou succ('caractère);
Ainsi succ('c'); va renvoyer d
Upcase: Convertit un caractère minuscule en MAJUSCULE.
Synatxe: upcase('caractère'); ou upcase (nom_variable);
Exemple: p:=upcase('g'); Ainsi p recevra G.
Remarque: Il y a une autre façon de déclarer une chaîne de caractère par l'utilisation de tableau: Var nom_chaîne: array[1..5] of
char; Dans ce cas précis, pour attribuer une valeur à nom_chaîne, il faut le faire caractère par caractère à travers la boucle for par
exemple..
Exemple
Program alida;
uses crt, strings;
Var nom: array[1..20]of char;
i: integer;
begin
for i:=1 to 5 do
begin
writeln('Entrez le caractère n° ', i);
readln(nom[i]);
end;
writeln(nom);
readln; (* Ici cette instruction permet de voir afficher le résultat *)
end.
b) Affectation
nom_variable:= 'valeur'; ou nom_variable1:=nom_variable2;
Exemple: nom:='NGUESSAN'; pnom:=nom; ainsi pnom va recevoir NGUESSAN.
Note très importante : Le type String est en fait un tableau de caractères à une dimension dont l'élément d'indice zéro contient de la longueur de la
chaîne. Il est donc possible (une chaîne de caractère étant un tableau) de modifier un seul caractère de la chaîne grâce à la syntaxe suivante: chaîne
[index]:=lettre; avec index ∈ [1; longueur de la chaîne].
Exemple:
Program chaine;
Uses crt;
Var nom: string;
begin
nom:='Etiévant';
nom[2]:='Z'; (* Nom contient désormais eZiévant *)
Writeln(nom);
Write(nom,'-tagada'); (* On verra afficher à l'écran: eZiévant-tagada *)
readln; (* Ici cette instruction permet de voir afficher le résultat *)
end.
Delete ( s, i, j ) ; Procédure qui supprime dans la chaîne nommée s, un nombre j de caractères à partir de la position i.
Insert ( s1, s2, i ) ; Procédure qui insert la chaîne s1 dans la chaîne s2 à la position i.
Pos ( s1, s2 ) ; Fonction qui renvoie sous forme de variable byte (entier) la position de la chaîne s1 dans la chaîne mère
s2. Si la chaîne s1 en est absente, alors cette fonction renvoie 0 comme valeur.
Str ( x, s ) ; Procédure qui convertit le nombre (Integer ou Real) x en chaîne de caractère de nom s.
Val ( x, s, err ) ; Procédure qui convertit la chaîne de caractère de nom s en un nombre (Integer ou Real) x et renvoie
un code erreur err (de type integer) qui est égale à 0 si la conversion est possible.
FillChar ( s, n, i ) ; Procédure qui introduit n fois dans la chaîne s la valeur i (de type Byte ou Char).
5) Le type booléen
Applicables dans les structures IF, WHILE, REPEAT… UNTIL, …..
Le mot clé utilisé est boolean.
Syntaxe :
Var nomdevariable : boolean ;
Pour donner une valeur à une variable booléenne, on procède comme pour tout autre type de variable, à l'aide du
commutateur := .
Les deux (2) valeurs attribuables à une variable de type booléen sont: true (vrai) et false (faux).
Syntaxes :
Nom_variable := true ;
Nom_variable := false ;
Note : Par défaut, une variable booléenne est FALSE (tout comme une variable INTEGER est égale à zéro lors du lancement du programme).
Il existe une autre façon de donner la valeur true (ou false) à une telle variable, bien plus simple qu'une structure IF.
Syntaxe : nomdevariable := condition ;
Exemple : test := (x>100) and (u='coucou') ; Ainsi la variable booléenne test prendra la valeur TRUE si x est supérieur à
100 et la variable u vaut 'coucou'. Dans le cas contraire, test prendra la valeur FALSE.
sin(a) sinus
cos(a) cosinus
arctan(a) arc tangente
abs(a) valeur absolue
sqr(a) carré
sqrt(a) racine carrée
exp(a) exponentielle
ln(a) logarithme népérien
trunc(a) Prise de la partie entière du nombre b sans arrondis
trac(a) Prise de la partie entière du nombre réel b sans arrondis
frac(a) Prise de la partie entière du nombre réel b avec arrondi à l'unité la plus proche
Round(b): Prise de la partie entière du nombre réel b avec arrondi à l'unité la plus proche
Odd(b): Renvoie true si le nombre b est impair et false si a est pair
SizeOf(x): renvoie le nombre d'octets occupés par la variable x.
Note: L'argument des fonctions trigonométriques doit être exprimé en radian (Real). A vous donc de faire une conversion si nécessaire. De plus, on
peut voir que les fonctions tangente, factorielle n'existent pas, il faudra donc créer de toute pièce les fonctions désirées.
Instructions;
...
End ;
Exemple
Program test;
uses crt;
const
levraicode = 'password' ;
Var
code : boolean ;
essai : string ;
begin
code:=false ; (* Facultatif, la valeur FALSE est donnée par défaut *)
While code = false do
begin
Write ('Entrez le code secret : ') ;
Readln (essai) ;
If essai ='levraicode' then
begin
code:=true ; (* Pour pouvoir sortir de la boucle *)
writeln('BRAVO! vous avez trouvé le code secret');
end;
end ;
end.
...
Instructions;
Until variable condition valeur ;
Exemple
Program test_boucle ;
uses crt ;
Var i : integer ;
begin
repeat
Inc ( i , 1 ) ;
Writeln ('Boucle itérée ', i, ' fois.') ;
until i > 20 ;
end.
Ce programme test_boucle permet de répéter l'incrémentation de la variable i jusqu'à que i soit supérieure à 20.
Exemple
Program boucle ;
Var i : integer ;
begin
For i := 10 to 53 do
begin
writeln ('Valeur de i est: ', i ) ;
end;
end.
1) Les fonctions
a) Mise en oeuvre d'une fonction
Elle est effectuée dans la partie déclarative du programme principal.
function nom de fonction (variable : type ) : type ;
Var déclaration de variables locales ;
...
begin
Instructions; ...
2) Les procédures
a) Mise en oeuvre d'une procédure
Elle est effectuée dans la partie déclarative du programme principal. Sa syntaxe est la suivante:
procedure nom de la procédure (variable : type ) ;
Var déclaration de variables locales ;
begin
... Instructions; ...
end ;
A l'exécution, on a:
program permutation;
uses crt ;
var e, f: real;
procedure permuter (var x, y: Real ) ; (* Il y a ici la présence de VAR au niveau des arguments *)
NGUESSAN KOFFI MATHIEU INGENIEUR INFORMATICIEN INPHB
FASCICULE DE LANGAGES C ET PASCAL© 28
Var i: real;
begin
i := x;
x:=y;
y:=x;
end ;
begin
clrscr ; (*permet d'effacer l'écran *)
Write('Entrez les réels à permuter :') ;
readln(e, f) ;
writeln('AVANT LA PERMUTATION');
writeln('La valeur de e avant la permutation est: ', e, ' et celle de f est: ', f);
permuter(e, f); (* Appel de la procédure permuter *)
writeln('APRES LA PERMUTATION');
writeln('La valeur de e après la permutation est: ', e, ' et celle de f est: ', f);
readln ;
end.
A l'exécution, on a:
Remarque : Que les bornes d'un tableau soient déclarées par des valeurs de type caractère (Char) n'interdit pas pour
autant de remplir le tableau de nombres à virgules. Car en effet, le type des bornes d'un tableau n'influe aucunement
sur le type des données contenues dans le tableau. Et réciproquement, le type des données d'un tableau ne renseigne
en rien sur le type des bornes ayant servi à sa déclaration (voir l'exemple3 d'en bas).
Un tableau peut avoir plusieurs dimensions. Si toutefois, vous imposez trop de dimensions ou des index trop importants,
une erreur lors de la compilation vous dira : Error 22: Structure too large.
Exemple1 Exemple2
Type var
Tab = array[1..10] of real; ou Tab: array[1..10] of real;
Var
t: tab; (* C'est la variable t qui sera utilise par la suite dans le programme *)
Exemple3: Déclaration d'un tableau indicé
Var
Tab: array['a'..'z'] of longint;
Nous venons de définir un tableau de 26 cases et chaque case sera repérée par une lettre. Ainsi Tab['a']:=2564; permet
d'attribuer la valeur 2564 à la 1ere case du tableau Tab. De même Tab['f']:=150; permet d'attribuer la valeur 150 à la
6eme case du tableau Tab.
Autres exemples:
Var tab1 : Array[0..10] Of Byte ;
Var tab2 : Array[-10..10] Of Real ;
Var tab3 : Array[50..60] Of String ;
Var tab4 : Array['K'..'S'] Of Char ;
c) Affectation
La technique pour introduire des valeurs dans un tableau est relativement simple. Il suffit de procéder comme pour une
variable normale, sauf qu'il ne faut pas oublier de spécifier la position index qui indique la place de la valeur dans la
dimension du tableau.
Syntaxes :
nom_du_tableau[index] := valeur ; (* Pour un tableau à une dimension *)
nom_du_tableau[index1, index2] := valeur ; (* Pour un tableau à deux dimensions *)
Note : la variable index doit nécessairement être du même type énuméré que celui utilisé pour la déclaration
du tableau.
On peut introduire dans un tableau les valeurs d'un autre tableau. Mais pour cela, il faut que les deux
tableaux en question soient du même type (ou de types compatibles), qu'ils aient le même nombre de
dimension(s) et le même nombre d'éléments. Syntaxe: nom_du_premier_tableau:= nom_du_deuxième_tableau ;
Exemple:
Program tableau;
Var tab : Array[1..10] Of Integer ;
i : Integer ;
begin
som:=0;
for i:=1 to 10 do (* Remplissage du tableau tab *)
begin
writeln('Entrez la valeur n° ', i)
readln(tab[i]);
end;
for i:=1 to 10 do (* Utilisation un à un, des éléments du tableau tab *)
begin
Writeln('La raciné carrée de ', tab[i], ' est: ', sqrt(tab[i]));
end;
readln;
end.
d) Imbrication de tableaux
L'on peut retrouver un tableau à l'intérieur d'un autre. Mais il faudrait que ces deux (2) tableaux soient déclarés dans la
partie type
Exemple: Type
Rg=array[1..10] of integer;
Table=array['a'..'z'] of Rg;
Var
Compt: Table;
Ainsi nous venons de déclarer un tableau du nom de Compt contenant 26 cases et chaque case contient 10 éléments de
type ENTIER; soit Compt contient au total 260 cases.
Remarque: Il est possible de déclarer un tableau en tant que constante. Mais cela nécessite de forcer le type (le type
tableau bien sûr) à la déclaration.
Syntaxe :
const a : array[0..3] Of Byte = (103, 8, 20, 14) ;
const b : Array[-3..3] Of Char = ('e', '5', '&', 'Z', 'z', ' ', #80) ;
const c : Array[1..3, 1..3] Of Integer = ((200, 23, 107), (1234, 0, 5), (1, 2, 3)) ;
const d : Array[1..26] Of Char = 'abcdefghijklmnopqrstuvwxyz';
Attention!: Cette forme parenthèsée est réservée aux constantes car elle ne permet pas de passer un tableau
en paramètre à une procédure ou d'initialiser un tableau.
1ère méthode
program somme;
uses crt;
var
mot: string;
S: integer;
function compter( var mt: string): integer; (* Si vous faites function compter (var mt: string[20], Pascal refusera *)
var som, j: integer;
begin (* Début du corps de la fonction compter *)
som:=0;
for j:=1 to length(mt) do
begin
if mt[j] = 'e' then som:= som + 1;
end;
compter:= som;
end; (* Fin du corps de la fonction compter *)
2 Les enregistrements
Le mot clé utilisé pour déclarer les enregistrements est record. Un enregistrement est déclaré dans la partie Type.
Syntaxe :
Type
nom_enregistrement = record
Champ1 : type_champ1 ;
Champ2 : type_champ2 ;
………
Champ n : type_champ n ;
end ;
Note : Les champs sont placés dans un bloc Record ... End ; et un sous-type peut lui-même être de type Record (voir le fascicule ALGO du même
auteur, sur les enregistrements) (imbrication d'enregistrements).
Exemple:
program exemple2 ;
type
Etudiant=record (* Définition de l'enregistrement du nom de Etudiant *)
Nom_p: string[45];
Sexe: char;
end;
var
T: array[1..50] of Etudiant; (* Définition d'un tableau (T) contenant l'enregistrement Etudiant dans chacune de ses cases *)
I: integer;
begin
for I:= 1 to 50 do (* permet de parcourir les étudiants, un à un *)
begin
writeln(' Entrez le nom et prénom de l''étudiant n° ', I);
readln(T[I].nom_p);
writeln(' Entrez le sexe de l''étudiant n° ', I);
readln(T[I].Sexe);
end;
readln;
end.
3 Les intervalles
Les types intervalles très utilisés ici ont rigoureusement les mêmes propriétés que ceux dont ils sont tirés. Ils peuvent
être de type nombre entier (Byte, Integer, ShortInt, LongInt, Long, Word), caractères (Char) ou énuméré. Un intervalle
est forcément ordonné et continu. Un type intervalle est déclaré dans la partie Type comme suit:
Syntaxe :Type
mon_intervalle = borneinf..bornesup ;
On doit obligatoirement avoir : borneinf et bornesup de type entier, caractère ou énuméré et tel que borneinf <=
bornesup.
Exemples :
Type bit = 0..1 ;
Type alpha = 'A'..'Z' ;
Type cent = 1..100 ;
Toutes ces instructions : Inc(), Dec() , Succ() , Pred() , Ord() (renvoie l'index de la variable dans l'intervalle auquel elle
appartient) s'appliquent aux seuls types intervalles qu'ils soient de type nombre entier, caractère ou énumérés.
Exemple:
Program exemple3;
Const Max=100 ;
Type intervalle=1..Max ;
Var x : intervalle ;
begin
x:=1 ;
{...}
If Not(Succ(x)) = Max Then
begin
Inc(x) ;
{...}
end.
4 Le type énuméré
Un type énuméré est un type dont les variables associées n'auront qu'un nombre très limité de valeur (au maximum 256
différentes possibles). La définition d'un type énuméré consiste à déclarer une liste de valeurs possibles (256 au
maximum) associées à un type, c'est-à-dire qu'une variable de type énuméré aura l'une et une seule de ces valeurs et
pas plusieurs à la fois.
La déclaration d'un type énuméré se fait dans la partie Type comme suit:
Nom_type_énuméré = (élément1, élément2,…élément n);
Toutes ces instructions Inc(), Dec() , Succ() , Pred() , Ord() s'appliquent également au type énuméré.
Program exemp ;
Type jours=(dim, lun, mar, mer, jeu, ven, sam) ;
Var dp : jours ;
begin
dp := mar ;
dp:=Succ(dp) ;
Inc(dp, 2) ; (* dp contient désormais ven *)
Case dp Of
dim : Writeln('Dimanche') ;
lun : Writeln('Lundi') ;
mar : Writeln('Mardi') ;
mer : Writeln('Mercredi') ;
jeu : Writeln('Jeudi') ;
ven : Writeln('Vendredi') ;
sam : Writeln('Samedi') ;
else Writeln('autre, ',Ord(dp)) ;
end;
end.
Note : Il est impossible d'utiliser les procédures Write(ln) et Read(ln) avec les variables de type énuméré.
5 Les ensembles
a) Déclaration
Un ensemble est une variable qui contient un nombre fini d'éléments de même type. Ce type ne doit pas être de type
ordinal ( c'est-à-dire qu'il ne doit être ni de type réel, ni de type chaîne de caractères), ni de type enregistrement, ni de
type pointeur (Ce type doit être énuméré) et ne doit pas excéder 256 éléments. La déclaration d'une telle variable se fait
par l'utilisation de la syntaxe Set Of.
Remarque : L'utilisation des ensembles trouve grandement son intérêt pour la programmation des automatismes.
Syntaxes :
VAR identificateur : Set Of type-de-l'ensemble ; ou TYPE identificateur = Set Of type_de_l'ensemble ; ou
VAR identificateur: Set Of (élément1, élément2, élément3...) ; Ici, Le type se résume à une liste d'éléments séparés par
des virgules à l'intérieur d'une parenthèse.
Exemple1: Var mt : Set Of Byte ; Ici, la variable mt est un ensemble de nombres entiers et dont les valeurs possibles
sont dans l'intervalle 0..255.
Exemple2: Type prenom = (Boris, Hugo, Aurore) ;
VAR dt : Set Of prenom ;
Exemple3:
Var ct : Set Of (Boris, Hugo, Aurore) ;
b) Construction d'ensemble
Syntaxe : nom_ensemble := [ élément1, élément2…élément n ] ;
Rappel : L'ordre des éléments dans une affection ou une comparaison n'a aucune espèce d'importance puisque les ensembles ne sont pas ordonnés.
Exemple
TYPE
Voy = set of char;
VAR
T: Voy;
……….
T :=['a', 'f'];
Exemple: Ecrire un programme permettant de compter le nombre de consonnes se trouvant dans un mot saisi au clavier.
program essaid;
uses crt;
type
ens= set of char;
var
voy, cons, ep: ens;
nb,i: integer;
mot: string;
c: char;
begin
nb:=0; (* Initialisation du nombre de consonne à 0 *)
voy:=['a','A','e','E','i','I','u','U','o','O','y','Y']; (* Ensemble des voyelles *)
ep:=['a'..'z']+['A'..'Z']; (* Ensemble de l'alphabet *)
cons:= ep - voy; (* Ensemble des consonnes *)
writeln('Entrez le mot SVP!');
readln(mot);
for i:=0 to length(mot)-1 do (* Je commence à 0 car le mot peut être vide *)
begin
c:=mot[i]; (* Accès aux différents caractères du mot *)
if c in cons then (* teste si les ≠ caractères du mot se trouvent dans l'ensemble des consonnes *)
begin
nb:= nb +1; (* Cette instruction sert à compter le nombre de comsonnes trouvées *)
end;
end;
writeln('Le nombre de consonnes est: ', nb);
readln;
end.
Note : Il est impossible d'utiliser les procédures Write(ln) et Read(ln) avec les variables de type ensemble.
Exemple de programme permettant de saisir un entier et de détecter si un entier a été saisi ou pas.
Program exemple33;
Uses crt;
Var n: integer;
cd: integer;
begin
repeat
write ('Entrez un entier');
{$I-}
readln(n);
{$I+}
cd:=IOResult;
if cd <> 0 then
begin
writeln('----------Donnée erronée-----------');
writeln('Le code d''erreur est ', cd);
end;
until cd = 0;
writeln('Donnée correcte');
end.
Ici, notre instruction readln(n) est répétée jusqu'à ce qu'il n'y ait plus d'erreur, autrement dit, jusqu'à ce que la valeur
fournie soit de type entier. En fait $I et IOResult contrôlent la donnée saisie lors de son acquisition.
2 Les graphismes
a) Affichage à l'écran
En règle générale, les programmes dialoguent avec l'utilisateur : entrées et sorties de données respectivement avec les
commandes read et write. La nécessité pratique ou la volonté de présenter une interface plus conviviale imposent
l'utilisation d'instructions spécifiques. Nous avons:
ClrScr ; Pour effacer tout l'écran et placer le curseur en haut à gauche de l'écran, très utilisé au démarrage de chaque
programme.
DelLine ; Efface la ligne courante c'est-à-dire celle qui contient le curseur.
InsLine ; Insère une ligne vide à la position courante du curseur.
ClrEol ; Pour effacer une ligne à l'écran à partir de la position courante du curseur, mais sans modifier la position du
curseur.
Ayez toujours en tête que la résolution de l'écran texte, en Turbo Pascal, est de 80 colonnes par 25 lignes et de 16 couleurs.
TextBackground ( x ) ; Choix d'une couleur de fond pour le texte qui sera tapé par la suite. x est le numéro (entre 0
et
15) de la couleur.
Numéro Couleur Numéro Couleur
0 Noir 8 Gris foncé
1 Bleu 9 Bleu flou
2 Vert foncé 10 Vert clair
b) Les graphiques
Les instructions qui vont suivre nécessitent l'unité graph. Pour créer des graphismes, il faut tout d'abord initialiser le
mode graphique de la manière suivante pour un écran VGA 640x480x16 :
Uses Graph ;
Var VGA, VGAHi : integer ;
begin
InitGraph (Pilote, Mode, 'chemin_d'accès du pilote') ; Avec Pilote et Mode qui sont des entiers
Pilote graphique Mode graphique Résolution Valeur
Nom Valeur 640 x 200 0
CGA 1 640 x 320 1
EGA 9 640 x 480 2
VGA 3
La plupart des écrans utilisent le pilote VGA. Donc nous allons choisir la valeur 3.
La plupart des écrans sont en mode 640x480 pixels (c'est la résolution de l'écran c'est-à-dire le nombre de petits points
le constituant). Donc nous allons choisir la valeur 2
Tous les pilotes de gestion de l'écran au niveau de Pascal, sont logés dans le répertoire BGI. Sur ma machine, le chemin
d'accès donc du pilote sera: c:\Pascal\BGI
Finalement j'aurai pour l'initialisation, les lignes suivantes::
program int_graphic;
uses graph;
var a, b: integer;
begin
clrscr;
a:=3; b:=2;
initgraph(a, b, 'c:\pascal\bgi');
Note: Ayez toujours en tête que la résolution de l'écran graphique, en Turbo Pascal, est au maximum de 640x480 pixels
et de 16 couleurs.
A noter que l'origine de l'écran graphique se trouve en haut à gauche de l'écran, c'est-à-dire que le point de
coordonnées (0,0) est le premier pixel de l'écran, ainsi le point à l'opposé qui est de coordonnées (629, 479) se trouve
en bas à droite.
SetColor ( couleur ) ; Instruction qui permet de sélectionner une couleur (voir le tableau précédent des couleurs) qui
affectera toutes les commandes graphiques c'est-à-dire de choisir la couleur des traits du graphique. Il vous suffit
d'entrer en paramètre le code ou alors le nom correspondant à la couleur de votre choix. Cette instruction doit être
placée juste après les commandes de graphique, sinon ça ne marchera pas. Exemples setcolor(blue) ou setcolor(8).
SetFillStyle ( style, couleur ) ; Sélectionne un motif de remplissage spécifique (voir tableau ci-après) ainsi qu'une
couleur parmi 16. Ces paramètres ne seront utilisés que par quelques instructions dont celle qui suit (bar).
Style ∈ [0;12] et couleur ∈ [0;15].
FloodFill (x, y, border ) ;Rempli une surface fermée identifiée par sa couleur de bordure : border à partir du point de
coordonnées (x, y). La couleur de remplissage sera celle choisie par un SetColor ou SetFillStyle.
Cette procédure remplit une surface délimitée, sur les écrans gérés par pixel (bitmap). (X, Y) représentent les
coordonnées d'un point situé dans la surface à remplir. Le motif de remplissage utilisé est le motif courant tel qu'il a été
défini par SetFillStyle ou SetFillPattern. La surface est délimitée par la couleur Bord. Si le point (X, Y) se trouve
effectivement à l'intérieur d'une surface délimitée, FloodFill remplit l'intérieur de cette surface. S'il se trouve à l'extérieur
d'une surface délimitée, FloodFill remplit l'extérieur de la surface.
Bar (x1, y1, x2, y2 ) ; Construit un rectangle plein aux coordonnées indiquées. L'axe des x étant croissant de gauche à
droite et celui des y croissant de haut en bas.
Bar3d (x1, y1, x2, y2, z, TopOn ) ; Construit un parallélépipède aux coordonnées indiquées et de profondeur z. L'axe
des x étant croissant de gauche à droite et celui des y croissant de haut en bas. TopOn est une constante signifiant que
les lignes de perspectives supérieures sont activées (pour les cacher : TopOff).
Program dessin1;
uses graph; crt;
var a, b: integer;
begin
clrscr;
a:=3; b:=2;
initgraph(a, b,'c:\pascal\bgi');
Bar3d (200, 150, 220, 180, 10, TopOn )
Line (x1, y1, x2, y2) ;
Construit une ligne débutant au point de coordonnées (x1, y1) et se terminant au point de coordonnées (x2, y2).
Rectangle (x1, y1, x2, y2) ; Construit un rectangle de coin haut-gauche de coordonnées (x1, y1) et de coin bas-droite
de coordonnées (x2, y2).
Circle (x, y, rayon ) ; Construit un cercle de coordonnées et de rayon spécifiés.
Ellipse (x, y, angle1, angle2, axe1, axe2) ; Construit une ellipse de centre (x,y) de largeur axe1 et de hauteur axe2.
On peut ne tracer qu'une partie de l'ellipse en spécifiant l'angle de départ angle1 et l'angle d'arrivé angle2 exprimés en
degrés et dans le sens trigonométrique. Pour tracer une ellipse complète :
angle1=0 et angle2=360.
Arc (x, y, angle1, angle2, rayon) ; Construit un arc de cercle de centre (x,y) et de rayon rayon. On peut tracer un arc
en spécifiant l'angle de départ angle1 et l'angle d'arrivé angle2 exprimés en degrés et dans le sens trigonométrique. Pour
tracer un arc maximum, c'est-à-dire un cercle : angle1=0 et angle2=360.
Exemple de construction graphique
program dessin2;
uses graph, dos, crt;
var a, b: integer;
begin
clrscr;
a:=3; b:=2;
initgraph(a, b,'c:\pascal\bgi');
setcolor(14);
bar(30,210,50,250);
setfillstyle(8, 5);
rectangle(105,140,45,32);
circle(300, 200, 20);
lineto(500,200);
bar3d(200,230,220,250,10, TopOn);
floodfill(104,130,14); (* Le dernier chiffre, ici 14, doit être identique à la valeur dans SetColor *)
readln;
end.
a) Les fichiers textes (Text): L'on mettra dans ce type de fichiers des données au format texte (chaînes de
caractères, nombres) dans lesquels ont peut écrire et lire ligne par ligne ou à la file avec les procédures Write(ln) et
Read(Ln).
Syntaxe : Var f : Text ;
b) Les fichiers typés (File Of): L'on y mettra des données structurées qui contiennent plusieurs champs
(enregistrement). Ce type de fichier est de loin préférable aux autres types de fichiers et donc le plus utilisés.
Syntaxe :
Var f : File Of type ;
Exemple :
Var f : File Of Integer ;
c) Les fichiers tout court ! (File), qui sont des fichiers dont on ne connaît pas le contenu. N'ayant aucune
information sur la structure des données, n'ayant aucune conversion à faire, la lecture et son écriture en sont plus
rapides. Mais leur utilisation est bien maigre : à part faire une simple copie d'un fichier dans un autre...
Syntaxe :
Var f : File ;
Mais nous allons nous intéresser au type de fichier FILE OF qui est le plus intéressant et le plus utilisé.
Exemple: Programme qui permet de savoir si le fichier auquel l'on désire accéder existe ou pas.
Program fic_existant;
uses crt;
type
etud = record
nom: string;
classe: string[15];
end;
Var nom_fich: string[50];
cd: integer;
pd: etud;
ft: file of etud;
begin
repeat
write ('Entrez le nom du fichier');
readln(nom_fich);
assign(ft, nom_fich);
{$I-}
reset(ft); (* Ouverture sans écrasement du fichier, donc supposé que le fichier existe déjà *)
{$I+}
cd:=IOResult;
if cd <> 0 then
begin
writeln('----------DESOLE! Le fichier saisi n''existe pas-----------');
end;
until cd = 0;
writeln('Le fichier saisi existe! Nous pouvons donc y accéder');
end.
PARTIE 14: LES STRUCTURES DE DONNES DYNAMIQUES
Un pointeur est une variable qui contient l'adresse mémoire d'une autre variable stockée en mémoire. La déclaration
d'une variable pointeur réserve 4 octets nécessaires au codage de l'adresse mémoire mais ne réserve aucune mémoire
pour la variable pointée. Jusqu'alors nous avions vu que la déclaration d'une variable provoque automatiquement la
réservation d'un espace mémoire qui est fonction du type utilisé.
D'où l'intérêt des pointeurs car quelque soit la grosseur de la variable pointée, la place en mémoire du pointeur est
toujours la même : 4 octets. Ces quatre octets correspondent à la taille mémoire nécessaire pour stocker l'adresse
mémoire de la variable pointée. La déclaration d'un pointeur permet donc de réserver une petite place de la mémoire qui
pointe vers une autre qui peut être très volumineuse. Il est cependant nécessaire de réserver de la mémoire à la valeur
pointée.
x := Gd^[Max,Max] * Sqr(Max) ;
Writeln(Cos(Gd^[Max,Max])) ;
dispose(Gd);
end.
Program pointeur2;
Type
Point = Record
x, y : Integer ;
couleur : Byte ;
end ;
PPoint = ^Point ;
begin
Randomize; (* Initialisation des nombres aléatoires *)
New(Pixel1);
New(Pixel2);
With Pixel1^ do
begin
x := 50 ;
y := 100 ;
couleur := Random(14)+1;
end ;
Pixel2^ := Pixel1^; (* le 1er enregistrement pointé par Pixel1 reçoit les valeurs du 2e pointé par Pixel2 *)
Pixel2^.couleur := 0; (* Le champ couleur de l'enregistrement pointé par Pixel2, reçoit 0 *)
dispose(Pixel1); (* Libération de l'espace occupé par l'enregistrement pointé par Pixel1 *)
dispose(Pixel2); (* Libération de l'espace occupé par l'enregistrement pointé par Pixel2 *)
end.
Il est possible de combiner les enregistrements, les tableaux et les pointeurs. Cela donne un vaste panel de
combinaisons. Essayons-en quelques unes.
Type TabP = Array[1..100] Of ^Integer ;
Var Tab : TabP ;
Tableau de pointeurs pointant vers des entiers. Tab[i] est un pointeur et Tab[i]^ est un entier.
Type Tab = Array[1..100] Of Integer ;
PTab = ^Tab ;
Var Tab : PTab ;
Pointeur pointant vers un tableau d'entiers. Tab^[i] est un entier et Tab est un pointeur.
Const Max = 20 ;
Type Station = Record
nom : String ;
liaisons : Array[1..10] Of Station ;
End ;
TabStation = Array[1..Max] Of Station ;
PTabStation = ^TabStation ;
Var md : PTabStation ;
md est un pointeur pointant vers un tableau d'enregistrement dont l'un des champs est un tableau et l'autre un
enregistrement (récursif).
Exercice: Proposer un programme permettant de créer une liste chaînée et d'y enregistrer des noms. Les noms seront
saisis jusqu'à ce qu'on ne rentre plus de nom.
program creation_liste_chainee;
uses wincrt;
type
lien = ^donnee; (* Définition d'un pointeur sur la structure donnee *)
donnee = record (* Définition de la structure donnee *)
nom: string[25];
suivant: lien;
end;
var
nomp: string[25];
debut: lien; (* Déclaration d'une variable de type lien (c'est un pointeur sur donnee) *)
procedure creer_liste (var p: lien);
var courant: lien;
i: integer;
begin
i:=1;
p:=nil;
writeln('*************CREATION DE LISTE**************');
writeln('DONNEZ LES NOMS et NOM VIDE POUR TERMINER!');
repeat
writeln('Donnez le nom n°', i);
readln(nomp);
if length(nomp) <> 0 then (* Tant que le nom est non vide *)
begin
new(courant); (* Réservation d'un espace mémoire pointé par le pointeur courant *)
courant^.nom:= nomp; (* Attribution des valeurs à la cellule nouvellement créée *)
courant^.suivant:= p; (* Pour garder le lien sur la cellule en cours qd le pointeur va pointer sur une nouvelle cellule *)
p:= courant; (* Pour pouvoir relier une cellule à celle qui suit: pour enchaîner les cellules *)
end;
i:=i+1;
until length(nomp) = 0;
end; (* A la sortie de cette procédure, les pointeurs P et courant pointent sur la dernière cellule *)
procedure lecture_liste(var t: lien);
var courant: lien;
begin
writeln('************LECTURE DE LA LISTE***************');
courant:=t;
while courant <> nil do (* Parcours de la liste, de la dernière cellule à la premièree *)
begin
writeln(courant^.nom);
courant:= courant^.suivant; (* Pour parcourir la liste, d'une cellule à une autre *)
end;
end;
program somme;
uses crt; (* Permet l'utilisation des instructions writeln et readln*)
VAR
a, i: integer; (* La variables a, va contenir les 3 entiers que l'on va saisir mais entier après entier et i va parcourir les différents
entiers*)
som: real; (* som va contenir le résultat. Elle est de type REEL pour contenir de grandes valeurs *)
begin
som := 0; (* som est initialisée à 0 car sa 1 ère utilisation est som:= som+a; et elle intervient à droite du signe d'affectation. Donc
prend l'élément neutre de l'addition comme 1 ère valeur. *)
for i:= 1 to 3 do
begin
writeln ('Entrez l''entier n°' , i); (* Il faudra doubler la quote ici *)
readln (a);
som := som + a; (* La nouvelle valeur de som = ancienne valeur de som + a *)
end;
writeln ('La somme des 3 entiers est:' , som:10:2); (* Affichage de som sur 10 chiffres dont 2 après la virgule *)
readln; (* Permet de marque une pause afin de voir afficher à l'écran, le résultat *)
end.
EXERCICE 2
Concevoir un algorithme permettant d'afficher les diviseurs d'un nombre entier.
program diviseurs;
uses crt; (* Permet l'utilisation des instructions writeln et readln*)
VAR
r, N, i: integer; (* N va contenir l'entier, r le reste de division entière et i va parcourir les entiers de 1 à N *)
begin
writeln('Entrez l''entier'); (* Ici, il faut doubler la quote *)
readln (N);
if N = 0 then (* Cas particulier *)
begin
writeln ('Il existe une infinité de diviseurs');
end (* Pas de ; à l'instruction qui précède un else *)
else (* C'est à dire N 0. Là, nous sommes dans le cas général maintenant !*)
begin
if N > 0 then (* Cas où N est positif *)
begin
writeln ('Les diviseurs de ' , N, ' sont: ');
for i := 1 to N do
begin
r:= N MOD i;
if r = 0 then
begin
writeln (i)
end;
end;
end (* Pas de ; car précède un else *)
else (* Cas où N est négatif *)
begin
writeln ('Les diviseurs de ' , N, ' sont: ');
for i:= 1 to -N do
begin
r := N MOD i;
if r = 0 then
begin
EXERCICE 3
Proposer un algorithme qui calcule le factoriel d’un nombre entier.
program factoriel;
uses wincrt;
VAR
n, j: integer; (* n va contenir l'entier et j va parcourir les entiers de 1 à n *)
fact: real; (* fact va contenir le factoriel. Elle est de type REEL pour contenir les grandes valeurs *)
begin
repeat
writeln ('Entrez l''entier');
readln (n);
until n >= 0; (* Nous devons veiller à ce que l'utilisateur saisisse une valeur positive *)
if (n = 0) or (n = 1) then (* Cas particuliers *)
begin
fact:= 1;
end
else (* Cas général*)
begin
fact:= 1; (* fact est initialisée à 1 *)
for j := 1 to n do
begin
fact:= fact * j; (* La nouvelle valeur de fact = ancienne valeur de fact * j *)
end;
end;
writeln ('Le factoriel de ' , n , ' est: ' , fact:15:4);
readln;
end.
EXERCICE 4
Proposer un algorithme qui à partir d'un réel noté x et d'une valeur entière appelée n, retourne x à la puissance n.
program puissance;
uses wincrt;
VAR
X, n, j: integer; (* X est l'entier, n est l'exposant et j pour compter le nombre de fois de multiplication *)
puiss: real; (* puiss va contenir Xn. De type REEL pour contenir les grandes valeurs *)
begin
writeln ('Entrez la valeur de X et de n');
readln (X, n);
(* Gestion des cas particuliers *)
if (X=0) and (n=0) then
begin
writeln('OPERATION IMPOSSIBLE!');
end
else (* Gestion des cas où le résultat du calcul existe *)
begin
if (X=0) and (n <>0) then (* Cas particuliers *)
begin
puiss:= 0;
end;
if(X <> 0) and (n=0) then (* Cas particuliers *)
begin
puiss := 1;
end;
EXERCICE 5
Mettre en place un algorithme qui convertit un temps saisi en secondes par l'utilisateur, en heures, en minutes et en
secondes. Exemple: 4000 s = 1 h 06 mn 40 s.
program conversion;
uses crt;
VAR
q1, q2, r1, r2, N: longint; (* N va contenir le temps initial saisi. De type longint pour contenir les grandes valeurs *)
begin
repeat
writeln ('Entrez le temps en secondes');
readln (N);
until N>0;
q1:= N DIV 3600;
r1:= N MOD 3600;
q2 := r1 DIV 60;
r2 := r1 MOD 60;
writeln(N, ' secondes valent: ' , q1, ' heure(s) ', q2, ' minute(s) et ' , r2, ' seconde(s) ' );
readln;
end.
EXERCICE 6
Déterminer un algorithme qui permet de ressortir le PGCD (Plus Grand Commun Diviseur) de deux (2) entiers.
program pgcd;
uses crt;
VAR
a, b, min: integer; (* a et b vont contenir les entiers à saisir et min le plus petit entre a et b *)
begin
writeln('Entrez les 2 entiers') ;
readln(a,b) ;
if a < b then
begin
min := a;
end
else (* b >= a *)
begin
min := b;
end;
while (min <> 1) and ( (a MOD min <> 0) or ( b MOD min <> 0) ) do
begin
min := min - 1;
end;
writeln('Le PGCD de ' , a, ' et de ' , b , ' est: ' , min);
readln;
end.
EXERCICE 7
Une compagnie de chemin de fer pratique ses tarifs en fonction de la catégorie du voyageur:
Voyageur normal (N): plein tarif
Abonné de la compagnie (A): 40% de réduction
Enfant de moins de 10 ans (E): gratuit
Employé de la compagnie (T): gratuit
Parent d'un employé (P): 50% de réduction
Personne âgée de 70 ans et plus (V): 30% de réduction.
Ecrire un algorithme qui permet, connaissant le tarif normal du voyage, de calculer le prix à payer par un voyageur
donné.
program tarif ;
uses crt;
VAR
tarif_N, tarif_Ap : real; (* tarif_N=tarif normal et tarif_Ap= tarif à payer *)
cat: char; (* cat =catégorie *)
begin
writeln ('Entrer le tarif Normal');
readln(tarif_N) ;
repeat
writeln('Entrez la catégorie du voyageur') ;
readln(cat) ;
until (cat='N')or(cat='n')or(cat='A')or(cat='a')or(cat='E')or(cat='e')or(cat='T')or(cat='t')or(cat='P')or(cat='p')or
(cat='V')or(cat='v');
case cat of
'N', 'n' : tarif_Ap:= tarif_N ;
'A', 'a' : tarif_Ap := tarif_N - (tarif_N * 40 /100) ;
'E', 'e', 'T', 't' : tarif_Ap:= 0;
'P', 'p' : tarif_Ap := tarif_N - (tarif_N * 50/100) ;
'V', 'v' :tarif_Ap:= tarif_N - (tarif_N * 30 /100) ;
end;
writeln('Le tarif à payer est : ',tarif_Ap) ;
readln;
end.
EXERCICE 8
Une société de transport compte vingt (20) chauffeurs qui font chacun un versement pendant 26 jours par mois. A
l'issue des 26 jours de versement, le salaire de chaque chauffeur est égal à 20% de sa recette mensuelle.
Concevoir un algorithme qui pourra afficher le salaire de chaque chauffeur et la part globale de la société de transport à
la fin du mois.
program salaire;
uses crt;
VAR
sal, vers, som_vers, part_ent, part_globale : real ;
i, j: integer; (* j pour parcourir les 20 chauffeurs et i pour effectuer les 26 versements *)
begin
part_globale:=0; (* part_globale est initialisée à 0 avant d'entamer la gestion des chauffeurs*)
for j := 1 to 20 do (* Parcours des 20 chauffeurs *)
begin
som_vers := 0; (* som_vers est initialisée à 0 avant d'entamer la gestion des versements*)
for i:= 1 to 26 do (* Gestion des 26 versements *)
begin
writeln(' Entrez le versement n° ' , i, ' du chauffeur n° ' , j);
readln(vers);
som_vers := som_vers + vers;
end; (* A la fin de cette boucle, on aura fini de gérer les 26 versements du chauffeur en cours *)
sal := som_vers *20/100;
writeln('Le salaire du chauffeur n° ' , j, ' est: ' , sal);
part_ent:= som_vers - sal; (* ou part_ent som_vers *80/100; *)
part_globale:= part_globale + part_ent;
end; (* A la fin de cette boucle, on aura fini de gérer tous les 20 chauffeur s *)
writeln('La part globale de la société est: ' , part_globale);
readln;
end.
EXERCICE 9
Réalisez un programme "Distributeur Automatique de billets de banque". L'automate (la machine) contient des billets de
1000F, 2000F, 5000F et de 10 000F. Etant donnée une demande de retrait de l'utilisateur, le programme calcule et
affiche le nombre de billets de chaque valeur. Le programme devra minimiser le nombre de billets distribués.
Réalisez l'algorithme de ce distributeur automatique de billets de banque.
program distributeur_billets ;
uses wincrt;
VAR
Mt: longint; (* Mt= Montant du retrait. Il ne peut être de type real car on ne peut utiliser MOD et DIV sur les réels *)
q1, q2, q3, q4, r1, r2, r3: integer;
begin
writeln('Entrez le montant à retirer');
readln(Mt) ;
q1:= Mt DIV 10000;
r1:= Mt MOD 10000;
q2:= r1 DIV 5000;
r2:= r1 MOD 5000;
q3:= r2 DIV 2000;
r3:= r2 MOD 2000;
q4:= r3 DIV 1000;
writeln('Le nombre de billets de 10 000F est:' , q1);
writeln('Le nombre de billets de 10 000F est:' , q2);
writeln('Le nombre de billets de 10 000F est:' , q3);
writeln('Le nombre de billets de 10 000F est:' , q4);
end.
EXERCICE 10
Le responsable d'un supermarché de la place vous sollicite pour l'aider à mettre en place un programme informatique qui
devra fonctionner comme suit: Lorsqu'un client se présente à la caisse, l'on saisit d'abord le nombre d'exemplaires et le
prix unitaire de chaque catégorie d'article et ce, pour toutes les catégories d'articles présents dans son panier. Ensuite la
somme versée. Après quoi, le programme devra afficher le montant total de toutes les catégories d'articles et le montant
de la monnaie.
Le programme devra gérer tous les clients de la journée et à la fermeture du magasin, afficher le montant de tous les
achats effectués pendant la journée. Puis celui du mois (1 mois = 30 jours).
Exemple de simulation
Nombre d’article 1: 5
Prix unitaire article 1 : 500
Nombre d’article 2: 3
Prix unitaire article 2 1000
Nombre d’article 3: 1
Prix unitaire article 3 850
TOTAL : 6350
Versé : 10 000
Rendu : 3650
TOTAL journée :
program caisse;
uses crt;
VAR
nbc, nba, i,j: integer; (* nbc= nombre total de catégories d'articles, nbc= nombre d'articles dans une catégorie et i= compteur pour parcourir les
catégories d'articles *)
pu, prix, total, totalJ, total_mois, vers, mon: real; (* pu= prix unitaire d'une catégorie d'article, prix= prix d'achat d'une catégorie
d'article, total=Montant total des achats d'un client, totalJ= Montant total de tous les achats effectués dans le magasin pendant la journée, vers= somme versée
par un client et mon = montant de la monnaie d'un client *)
rep: char; (* rep= réponse pour savoir si le magasin est fermé ou pas *)
begin
totalJ := 0;
total_mois:=0;
for j:=1 to 30 do
begin
writeln('Nous sommes au jour n° ', j);
repeat
total:= 0;
writeln('Entrez le nombre de catégories d''article');
readln(nbc);
for i := 1 to nbc do
begin
writeln('Entrez le nombre d''articles de la catégorie n° ' , i);
readln(nba);
writeln('Entrez le prix unitaire de la catégorie d''article n° ' , i);
readln(pu);
prix:=nba * pu;
total:= total + prix;
end;
writeln('Le total des achats du client est: ' , total:10:2);
writeln('Entrez la somme versée par le client');
readln(vers);
mon:= vers - total;
writeln('La monnaie à rendre est: ' , mon:8:1);
totalJ:= totalJ + total;
writeln('Un autre client? O pour OUI et N pour NON');
readln(rep);
until(rep ='N') or (rep ='n');
writeln('Le total de la journée est: ' , totalJ:15:3);
total_mois := total_mois + totalJ;
end;
writeln('Le montant des achats du mois est ' , total_mois:16:3);
readln;
end.
EXERCICE 11
Le professeur principal d'une classe de 25 étudiants vous sollicite pour mettre en place un programme informatique lui
permettant de calculer les moyennes de ses étudiants. Les matières à considérer et leurs différents coefficients sont:
Informatique: coefficient 4, mathématiques: coefficient 3 et l'anglais: coefficient 2.
Pour chaque matière, l'on dispose de deux (2) notes avec des coefficients différents: note de test lourd: coefficient 5 et
note de devoir: coefficient 3.
Le professeur principal voudrait savoir:
La moyenne de classe de chaque étudiant,
Le premier dans chaque matière,
Le premier de la classe,
La moyenne générale de la classe.
Proposer un algorithme lui permettant d'assouvir son besoin.
Note: Les étudiants seront identifiés par des numéros (par exemple n°1, n°2,…).
program moyenne;
uses crt;
VAR
moy, moy_max, som, moy_gle, moy_mat, moy_max_mat, moy_info, moy_max_info, moy_A, moy_max_A, noteTL,
noteD: real; (* moy=Moyenne de classe de l'étudiant, moy_max=moyenne maximale de classe, som=somme de toutes les moyennes,
moy_gle=moyenne générale de la classe, moy_mat=moyenne en math, moy_max_mat=moyenne maximale en math, moy-info= moyenne en informatique,
moy_max_info= moyenne maximale en informatique, moy_A=moyenne en anglais, moy_max_A=moyenne maxi-male en anglais, noteTL= note du test
lourd, noteD= note de devoir *)
I, j, k, l, m: integer; (* i= compteur pour parcourir les étudiants, j, k, l=Pour identifier les 1ers dans les matières et m pour le 1er de classe *)
begin
som:= 0; moy_max_mat:= 0; moy_max_info:= 0; moy_max_A:= 0; moy_max:= 0;
for I:= 1 to 25 do
begin
writeln('ETUDIANT n° ', I);
writeln('Entrez la note de test lourd d''informatique');
readln(noteTL);
writeln('Entrez la note de devoir d''informatique');
readln(noteD);
moy_info:= (noteTL*5 + noted*3)/8;
if moy_info > moy_max_info then
begin
moy_max_info := moy_info;
j:= I;
end;
writeln('Entrez la note de test lourd de mathématiques');
readln(noteTL);
writeln('Entrez la note de devoir de mathématiques');
readln(noteD);
moy_mat:= (noteTL*5 + noted*3)/8;
if moy_mat > moy_max_mat then
begin
moy_max_mat := moy_mat;
k:= I;
end;
writeln('Entrez la note de test lourd d''anglais');
readln(noteTL);
writeln('Entrez la note de devoir d''anglais');
readln(noteD);
moy_A:= (noteTL*5 + noted*3)/8;
if moy_A > moy_max_A then
begin
moy_max_A := moy_A;
l:= I;
end;
(* Calcul de la moyenne de classe de l'étudiant *)
moy := (moy_info*4 + moy_mat*3 + moy_A*2)/9;
writeln('La moyenne de l''étudiant n° ' , i, ' est: ' , moy);
if moy > moy_max then
begin
moy_max := moy;
m := I;
end;
som := som + moy;
end;
moy_gle:= som/25;
writeln('Le 1er en informatique est l''étudiant n° ' , j ,' et il a obtenu ' , moy_max_info);
writeln('Le 1er en mathématique est l''étudiant n° ' , k ,' et il a obtenu ' , moy_max_mat);
writeln('Le 1er en anglais est l''étudiant n° ' , l ,' et il a obtenu ' , moy_max_A);
writeln('Le 1er de classe est l''étudiant n° ' , m ,' et il a obtenu ' , moy_max);
writeln('La moyenne générale de la classe est: ' , moy_gle);
readln;
end.
EXERCICE 12
A partir du "Menu principal" affiché à l'écran:
Effectuer la somme de trois nombres réels,
Effectuer le produit de trois nombres réels,
Effectuer la moyenne de trois nombres réels,
l'utilisateur fera le choix de son opération par la saisie d'une valeur entière.
Proposer un algorithme qui permet à partir du menu principal, d'effectuer les opérations ci-dessus.
program menu;
uses crt;
VAR
a, b, c, op: real ; (* a, b, c pour les 3 réels et op= résultat de l'opération *)
choix: integer; (* choix pour le choix de l'opération *)
function somme (VAR x, y, z: real): real;
VAR
p: real;
begin (* Début du corps de la fonction somme *)
p := x + y + z;
somme := p;
end; (* Fin du corps de la fonction somme *)
function moyenne (VAR q, v, n: real): real;
VAR
k: real;
begin (* Début du corps dela fonction moyenne *)
k := (q + v + n)/3;
moyenne := k;
end; (* Fin du corps de la fonction moyennne *)
function produit (VAR x, y, z: real): real;
VAR
p: real;
begin (* Début du corps de la fonction produit *)
p := x * y * z ;
produit:= p;
end; (* Fin du corps de la fonction produit *)
begin (* Début du corps du programme principal *)
writeln('Entrez 1 pour effectuer la somme des trois nombres') ;
writeln('Entrez 2 pour effectuer le produit des trois nombres') ;
writeln('Entrez 3 pour effectuer la moyenne des trois nombres') ;
repeat
writeln('Faites votre choix') ;
readln(choix) ;
until (choix = 1) or (choix = 2) or (Choix = 3 ) ;
writeln('Entrez les trois nombres réels') ;
readln(a, b, c) ;
if choix = 1 then
begin
EXERCICE 13
Une société de transport compte vingt (20) chauffeurs qui font chacun un versement pendant 26 jours par mois. A
l'issue des 26 jours de versement, le salaire de chaque chauffeur est égal à 20% de sa recette mensuelle.
Concevoir un algorithme qui pourra afficher le salaire de chaque chauffeur et la part globale de la société de transport à
la fin du mois.
program calcul_salaire;
uses crt;
VAR
part_ent, part_globale :real; (* part_ent=ce que la société gagne sur 1 chauffeur et part_global=le total des part_ent *)
j: integer; (* j pour parcourir les 20 chauffeurs et i pour effectuer les 26 versements *)
procedure versements;
VAR
i: integer;
som_vers, salaire, vers: real;
begin (* Début du corps de la procédure versements *)
som_vers:= 0;
for i := 1 to 3 do (* Gestion des 26 versements *)
begin
writeln('Entrez le versement n° ' , i, ' du chauffeur n° ' , j);
readln(vers);
som_vers:= som_vers + vers;
end;
salaire:= som_vers *20/100;
writeln('Le salaire du chauffeur n° ' , j, ' est: ' , salair[Link]);
part_ent:= som_vers - salaire;
end; (* Fin de la procédure versements *)
EXERCICE 14
Réalisez un programme "Distributeur Automatique de billets de banque". L'automate (la machine) contient des billets de
1000F, 2000F, 5000F et de 10 000F. Etant donnée une demande de retrait de l'utilisateur, le programme calcule et
affiche le nombre de billets de chaque valeur. Le programme devra minimiser le nombre de billets distribués.
Réalisez l'algorithme de ce distributeur automatique de billets de banque.
program distributeur_billets ;
uses crt;
VAR
Mt: longint; (* Mt= Montant du retrait *)
procedure nombre_billets (Var N: longint);
VAR
q1, q2, q3, q4, r1, r2, r3: longint;
begin (* Début du corps de la procédure nombre_billets *)
q1:= N DIV 10000;
r1:= N MOD 10000;
q2:= r1 DIV 5000;
r2:= r1 MOD 5000;
q3:= r2 DIV 2000;
r3:= r2 MOD 2000;
q4:= r3 DIV 1000;
writeln('Le nombre de billets de 10 000F est: ' , q1:5);
writeln('Le nombre de billets de 5 000F est: ' , q2:5);
writeln('Le nombre de billets de 2 000F est: ' , q3:5);
writeln('Le nombre de billets de 1 000F est: ' , q4:5);
end; (* Fin du corps de la procédure nombre_billets *)
begin (* Début du corps du programme principal *)
writeln('Entrez le montant à retirer');
readln(Mt) ;
nombre_billets(Mt); (* Appel de la procédure nombre_billets *)
readln;
end. (* Fin du corps du programme principal *)
EXERCICE 15
Le professeur principal d'une classe de 25 étudiants vous sollicite pour mettre en place un programme informatique lui
permettant de calculer les moyennes de ses étudiants. Les matières à considérer et leurs différents coefficients sont:
Informatique: coefficient 4, mathématiques: coefficient 3 et l'anglais: coefficient 2.
Pour chaque matière, l'on dispose de deux (2) notes avec des coefficients différents: note de test lourd: coefficient 5 et
note de devoir: coefficient 3.
Le professeur principal voudrait savoir:
La moyenne de classe de chaque étudiant,
Le premier dans chaque matière,
Le premier de la classe,
La moyenne générale de la classe.
Proposer un algorithme lui permettant d'assouvir son besoin.
Note: Les étudiants seront identifiés par des numéros (par exemple n°1, n°2,…).
program moyenne;
uses crt;
VAR
moy, moy_max, som, moy_gle, moy_mat, moy_max_mat, moy_info, moy_max_info, moy_A, moy_max_A,
noteTL, noteD: real;
I, j, k, l, m: integer;
procedure calcul_moyenne_matieres;
begin (* Début du corps de la procédure calcul_moyenne_matieres *)
writeln('ETUDIANT n° ', i);
writeln('Entrez la note de test lourd d''informatique');
readln(noteTL);
writeln('Entrez la note de devoir d''informatique');
readln(noteD);
moy_info:=(noteTL*5 + noted*3)/8;
writeln('Entrez la note de test lourd de mathématiques');
readln(noteTL);
writeln('Entrez la note de devoir de mathématiques');
readln(noteD);
moy_mat:=(noteTL*5 + noted*3)/8;
writeln('Entrez la note de test lourd d''anglais');
readln(noteTL);
writeln('Entrez la note de devoir d''anglais');
readln(noteD);
moy_A:=(noteTL*5 + noted*3)/8;
end; (* Fin du corps de la procédure calcul_moyenne_matieres *)
procedure moyenne_max_info;
begin (* Début du corps de la procédure moyenne_max_info *)
if moy_info > moy_max_info then
begin
moy_max_info:= moy_info;
j:=I;
end;
end; (* Fin du corps de la procédure moyenne_max_info *)
procedure moyenne_max_mat;
begin (* Début du corps de la procédure moyenne_max_mat *)
if moy_mat > moy_max_mat then
begin
moy_max_mat:= moy_mat;
k:=I;
end;
end; (* Fin du corps de la procédure moyenne_max_mat *)
procedure moyenne_max_A;
begin (* Début du corps de la procédure moyenne_max_A *)
if moy_A > moy_max_A then
begin
moy_max_A:= moy_A;
l:= I;
end;
end; (* Fin du corps de la procédure moyenne_max_A *)
procedure moyenne_max_classe;
begin (* Début du corps de la procédure moyenne_max_classe *)
if moy > moy_max then
begin
moy_max:= moy;
m:= I;
end;
end; (* Fin du corps de la procédure moyenne_max_classe *)
procedure calcul_moyenne_classe(VAR a, b, c: real);
EXERCICE 16
Concevoir un algorithme qui prend en entrée dix (10) réels et qui les retourne triés par ordre croissant.
program tri_croissant;
uses wincrt;
VAR
T: array[1..10] of real; (* Le tableau va servir à contenir les 10 réels *)
procedure saisie_nombres;
VAR
i: integer;
begin (* Début du corps de la procédure saisie_nombres *)
for i := 1 to 10 do
begin
writeln('Entrez le réel n° ' , i);;
readln(T[i]);
end;
end; (* Fin du corps de la procédure saisie_nombres *)
procedure trier_croissant;
VAR
i, j: integer;
temp: real;
begin (* Début du corps de la procédure trier_croissant *)
for i := 1 to 9 do
begin
for j := i+1 to 10 do
begin
if T[j] < T[i] then
begin
temp:=T[i];
T[i]:=T[j];
T[j]:=temp;
end;
end;
end;
end; (* Fin du corps de la procédure trier_croissant *)
procedure affichage;
VAR
k: integer;
begin (* Début du corps de la procédure affichage *)
writeln('Les nombres triés par ordre croissant sont:');
for k:= 1 to 10 do
begin
writeln(T[k]:6:2);
end;
end; (* Fin du corps de la procédure affichage *)
begin (* Début du corps du programme principal *)
saisie_nombres; (* Appel de la procédure saisie_nombres pour le remplissage du tableau T *)
EXERCICE 17
Proposer un algorithme permettant de classer par ordre alphabétique, une liste de cinq noms.
Note: Ne pas utiliser l'opérateur < ou > pour la comparaison des noms.
program ordre_alphabetique;
uses crt;
VAR
T: array[1..5] of string; (* T pour contenir les 5 noms *)
procedure saisir_noms;
VAR
i: integer;
begin (* Début du corps de la procédure saisir_noms *)
for i := 1 to 5 do (* Remplissage du tableau par les différents noms *)
begin
writeln(' Entrez le nom n°' , i);
readln(T[i]);
end;
end; (* Fin du corps de la procédure saisir_noms *)
procedure trier_noms;
VAR
i, j, k, Li, Lj, min: integer;
temp: string;
verifier: boolean;
begin (* Début du corps de la procédure trier_noms *)
for i := 1 to 4 do (* Tri du tableau *)
begin
for j := i+1 to 5 do
begin
Li:= length(T[i]);
Lj :=length(T[j]);
if Li < Lj then
begin
min:= Li;
end
else
begin
min:= Lj;
end;
verifier:= false;
K:= 1;
while(k<= min) and (verifier = false) do
begin
if T[j][k] < T[i][k] then (* Comparaison des caractères n°k *)
begin
temp:= T[i];
T[i]:= T[j];
T[j]:= temp;
verifier:= true; (* Pour arrêter la comparaison *)
end
else (* T[j][k] > T[i][k] ou T[j][k] = T[i][k] *)
begin
if T[j][k] > T[i][k] then
begin
verifier:= true; (* Pour arrêter la comparaison *)
end;
if T[j][k] = T[i][k] then
begin
K:= k+1; (* On continue la comparaison *)
end;
end;
end;
if (k > min) and (Li > Lj) then
begin
temp:= T[i];
T[i]:= T[j];
T[j]:= temp;
end;
end;
end;
end; (* Fin du corps de la procédure trier_noms *)
procedure affichage_resultat;
VAR
i: integer;
begin (* Début du corps de la procédure affichage_resultat *)
writeln ('Le classement par ordre alphabétique est:');
for i := 1 to 5 do
begin
writeln (T[i]);
end;
end; (* Fin du corps de la procédure affichage_resultat *)
begin (* Début du corps du programme principal *)
saisir_noms; (* Appel de la procédure saisir_noms *)
trier_noms; (* Appel de la procédure trier_noms *)
affichage_resultat; (* Appel de la procédure affichage_resultat *)
readln;
end. (* Fin du corps du programme principal *)
EXERCICE 18
La société NEKOMAT a douze (12) employés. Le directeur voudrait pour chaque mois, savoir le salaire le plus élevé et le
moins élevé. De plus, il aimerait avoir le salaire le plus fréquemment payé, c'est-à-dire le salaire reçu par un plus grand
nombre d’employés.
Concevez un algorithme permettant d’assouvir le besoin du directeur.
program salaire;
uses crt;
VAR
tab: array[1..12] of real; (* tab va contenir les 12 salaires *)
procedure saisir_salaires;
VAR
i: integer;
begin (* Début du corps de la procédure saisir_salires *)
for i := 1 to 12 do (* Remplissage du tableau par les différents salaires *)
begin
writeln('Entrez le salaire n° ' , i);
readln(tab[i]);
end;
end; (* Fin du corps de la procédure saisir_salires *)
procedure salaire_max_min;
VAR
i: integer;
sal_max, sal_min: real;
begin (* Début du corps de la procédure salaire_max_min *)
sal_max:= tab [1];
sal_min:= tab[1];
for i := 2 to 12 do (* Détermination du salaire mini et maxi *)
begin
EXERCICE 19
L’école primaire Notre Dame de Treichville voudrait encourager l’excellence en octroyant des prix aux meilleurs élèves.
Notre Dame de Treichville a six (6) classes et chaque classe comporte trente (30) élèves.
La composition de passage est basée sur cinq (5) matières de coefficient chacune. Le classement est effectué par classe
et l’on affiche le nom, la moyenne, le rang et la mention de l’élève par ordre de mérite.
Concevoir un algorithme permettant d’effectuer le classement de cette école.
Note: Pour la mention, nous retiendrons ceci:
<10: Médiocre,
[10; 12[: Passable,
[12; 14[: Assez Bien,
[14; 16[: Bien,
[16; 18]: Très bien,
]18; 20]: Excellent.
program ecole;
uses wincrt;
TYPE
classe = record
nom: string[30];
moyenne: real;
rang: integer;
mention: string[15];
end;
P= array[1..30] of classe; (* Pour gérer les 30 élèves de chaque classe*)
T= array[1..6] of P; (* Pour gérer les 6 classes *)
VAR
cl: T;
i , j: integer;
function calcul_moyenne: real;
VAR
e, cof, C: integer;
som, note: real;
begin (* Début du corps de la fonction calcul_moyenne *)
cof:= 0; som:= 0;
for e := 1 to 30 do
begin
writeln('Entrez la note : ' , e);
readln(note);
writeln('Entrez le coefficient de la note n° ' , e);
readln(C);
som:= som +(C* note); (* Addition des notes coefficientées *)
cof:= cof + C; (* Addition des coefficients *)
calcul_moyenne:= som / cof;
end;
end; (* Fin du corps de la fonction calcul_moyenne *)
procedure attribution_mention (Var P: real);
begin (* Début du corps de la procédure attribution_mention *)
if P < 10 then
begin
cl[i][j].mention:='Médiocre';
end;
if (P >= 10) and (P < 12) then
begin
cl[i][j].mention :='Passable';
end;
if (P >=12) and (P < 14) then
begin
cl[i][j].mention:= 'Assez Bien';
end;
if (P>= 14) and (P < 16) then
begin
cl[i][j].mention:='Bien';
end;
if (P>= 16) and (P<= 18) then
begin
cl[i][j].mention:='Très Bien';
end;
if (P > 18) and (P<= 20) then
begin
cl[i][j].mention:='Excellent';
end;
end; (* Fin du corps de la procédure attribution_mention *)
procedure trier_tableau;
VAR
e, f, k: integer;
t_moy: real;
t_nom, t_mention: string;
begin (* Début du corps de la procédure trier_tableau *)
for e:= 1 to 6 do (* Parcours des 6 classes *)
begin
for f := 1 to 29 do (* Parcours des 30 élèves de la classe en cours *)
begin
for k:= f+1 to 30 do (* Parcours des 30 élèves de la classe en cours *)
begin
if cl[e][f].moyenne < cl[e][k].moyenne then
begin
t_nom:= cl[e][f].nom;
t_moy:= cl[e][f].moyenne;
t_mention:= cl[e][f].mention;
cl[e][f].nom:= cl[e][k].nom;
cl[e][f].moyenne:= cl[e][k].moyenne;
cl[e][f].mention:= cl[e][k].mention;
cl[e][k].nom:= t_nom;
cl[e][k].moyenne:= t_moy;
cl[e][k].mention:= t_mention;
end;
end;
end;
end;
end; (* Fin du corps de la procédure trier_tableau *)
procedure attribuer_rang;
VAR
g, h: integer;
begin (* Début du corps de la procédure attribution_rang *)
for g:= 1 to 6 do (* Attribution du rang. Elle se fait après avoir calculé toutes les moyennes *)
begin
for h:= 1 to 30 do
begin
cl[g][h].rang:= h;
end;
end;
end; (* Début du corps de la procédure attribution_rang *)
procedure afficher_classement;
VAR
p, l: integer;
begin
for p:= 1 to 6 do (* Affichage du classement *)
begin
writeln('CLASSEMENT DE LA CLASSE n° ' , p);
for l:= 1 to 30 do
begin
writeln( cl[p][l].nom, ' est', cl[p][l].rang, ' e avec ' ,
cl[p][l].moyenne, ' comme moyenne et ' , cl[p][l].mention, ' pour mention ');
end;
end;
end;
begin (* Début du corps du programme principal *)
for i:= 1 to 6 do (* Parcours des 6 classes *)
begin
writeln('CLASSE n° ', i);
for j:= 1 to 30 do (* Parcours des 30 élèves de la classe en cours *)
begin
writeln ('Entrez le nom de l''élève ' , j );
readln(cl[i][j].nom );
cl[i][j].moyenne:= calcul_moyenne; (* Calcul de la moyenne *)
attribution_mention(cl[i][j].moyenne); (* Détermination de la mention *)
trier_tableau; (* Tri du tableau afin d'atttribuer les rang *)
attribuer_rang; (* attribution du rang *)
end;
end;
afficher_classement; (* Affichage du classement et seulement après avoir géré tous les élèves des 6 classes *)
readln;
end. (* Fin du corps du programme principal *)
EXERCICE 20
Ecrire un programme en Pascal permettant d'afficher la date et l'heure de la forme: Nous sommes au samedi 13 octobre
2007 et il est 16h 45mn 30s 25 centième.
program essai;
uses windos, crt;
{construction d'un tableau contenant les jours de la semaine}
const
jours : array [0..6] of string[8] = ('dimanche','lundi','mardi','mercredi','jeudi','vendredi','samedi');
(* Construction d'un tableau contenant les mois de l'année *)
mois : array [0..11] of string[9] = ('décembre','janvier','février','mars','avril','mai','juin','juillet',
'août','septembre','octobre','novembre');
( * DECLARATION DES VARIABLES UTILISEES : *)
var a,m,j,jour,heure,min,sec,cent: word;
{ déclaration des variables en WORD (nombres entiers compris dans l'ensemble [0..65535])
a : numéro de l'année [1980..2099]
m : numéro du mois [1..12]
j : numéro du jour dans le mois [1..31]
EXERCICE 21
Le Sous Préfet de OUELLE vous sollicite pour mettre en place une application permettant l’établissement des
extraits d’acte de naissance de sa sous préfecture. L’on retiendra le numéro de l’extrait, le nom et prénom de
l’intéressé, la date et le lieu de naissance, le nom, le prénom de chaque parent.
Cet algorithme permettra à partir d’un menu :
Création d'un fichier (une nouvelle base de données),
Ajout de données,
Modification de données,
Consultations
Suppression de données,
Modification des mots de passe.
Pour sécuriser les données gérées par l'application, l'on a établi 2 catégories d'utilisateurs :
Catégorie 1 : Administrateur; Mot de passe initail : admin1usagerroot
Catégorie 2 : Utilisateur, Mot de passe initial : util2azert45d
La 1ère catégorie a accès à toutes les parties du logiciel, tandis que le 2e catégorie n'a seulement accès qu'à
une partie du logiciel (Ajout de données, Consultations).
Au lancement de l'application, les usagers doivent obligatoirement s'authentifier par la saisie de la catégorie
et du mot de passe. Une fois les 2 informations ci-dessus validées, alors ils ont maintenant accès à leurs
différentes ressources respectives. A part la création de fichier et la modification des mots de passe, les autres
opérations nécessitent l'entrée du nom complet du fichier à exploiter (car il peut exister plusieurs fichiers
créés).
Proposer un algorithme permettant de mettre en œuvre l'application et de la sécuriser par des comptes
utilisateurs (catégorie + mot de passe) munis de droits d'accès.
procedure modifier_donnees;
VAR nom_fichier: string;
p: EXTRAIT;
critere: string[10];
trouver : boolean;
C : char;
i : integer;
begin (* Début du corps de la procédure modifier_donnees *)
trouver:= false;
repeat
writeln('Entrez le nom du fichier déjà existant, à exploiter');
readln(nom_fichier);
assign(f, nom_fichier);
{$I-} (* Permet de vérifier l'existence ou non du fichier à exploire *)
reset( f ); (* Ouverture du fichier cette fois-ci, donc supposé que le fichier existe *)
{$I+}
cd:= IOResult;
if cd <> 0 then
begin
writeln('----------DESOLE! Le fichier saisi n''existe pas-----------');
end;
until cd = 0;
writeln('Entrez le numéro de l''extrait recherché');
readln(critere);
seek(f, 0); (* Permet de positionner le curseur au début du fichier *)
i:= 0;
while (trouver= false) and (not eof(f) ) do
begin
read(f, p);
if p.num_ext = critere then
begin
trouver:= true;
writeln('Les anciennes valeur sont');
writeln('N°extrait ', p.num_ext);
writeln('Nom et prénom de l''interessé ', p.np_int);
writeln('Date et lieu de naissance ', p.dat_nais);
writeln('Nom et prénom des parents: ', p.np_par);
writeln('Entrez le numéro du champ à modifier');
writeln('1 pour n°extrait');
writeln('2 pour nom et prénom de l''intéressé');
writeln('3 pour date et le lieu de naissance');
writeln('4 pour nom et prénom des parents');
writeln('Faites votre choix');
readln(C);
case C of
'1' : begin
writeln('Entrez le nouveau n°de l''extrait');
readln(p.num_ext);
end;
'2' : begin
writeln('Entrez le nom et prénom de l''intéressé');
readln(p.np_int);
end;
'3' : begin
writeln('Entrez la date de naissance l''intéresse');
readln(p.dat_nais);
end;
'4' : begin
writeln('Entrer le nom et prénom des parents');
readln(p.np_par);
end;
end;
end;
i:=i + 1;
end;
if trouver = true then (* Ce qui veut dire qu'on a trouvé le n° de l'extrait recherché *)
begin
seek(f, i - 1); (* Permet de positionner l'index sur l'enregistrement n° i-1 *)
write(f, p);
end
else (* Ce qui veut dire trouver=FAUX. Donc on n'a pas trouvé le n° de l'extrait recherché *)
begin
writeln('Le numéro de l''extrait saisi, n''existe pas dans le fichier');
end;
end; (* Fin du corps de la procédure modifier_donnees *)
procedure consulter;
VAR nom_fichier: string;
E: Extrait; critere: string[10]; trouver: boolean;
begin (* Début du corps de la procédure consulter *)
repeat
writeln('Entrez le nom du fichier déjà existant, à exploiter');
readln(nom_fichier);
assign(f, nom_fichier);
{$I-} (* Permet de vérifier l'existence ou non du fichier à exploire *)
reset( f ); (* Ouverture du fichier cette fois-ci, donc supposé que le fichier existe *)
{$I+}
cd:= IOResult;
if cd <> 0 then
begin
writeln('----------DESOLE! Le fichier saisi n''existe pas-----------');
end;
until cd = 0;
writeln('Entrer le numéro de l''extrait à consulter');
readln(critere);
trouver:=false;
seek(f, 0); (* Permet de positionner l'index au début du fichier *)
while(trouver= false) and ( not eof(f) ) do
begin
read (f, E);
if E.num_ext = critere then
begin
trouver:= true;
writeln('Le numéro de l''extrait est: ' , E.num_ext);
writeln('Le nom et prénom est: ' , E.np_int);
writeln('La date et le lieu de naissance est: ' , E.dat_nais);
writeln('Le nom et prénom des parents: ' , E.np_par);
end;
end;
if trouver = false then (* Ce qui veut dire qu'on n'a pas trouvé l'extrait à consulter *)
begin
writeln('Le numéro de l''extrait à consulter, n''existe pas dans le fichier');
end;
end; (* Fin du corps de la procédure consulter *)
PROCEDURE supprimer_donnees;
VAR nom_fichier: string;
critere : string[10]; pt : file of Extrait; t : Extrait; trouver: boolean;
(* pt va servir de fichier intermédiaire lors de la suppression de la donnée *)
begin (* Début du corps de la procédure supprimer_donnees *)
repeat
writeln('Entrez le nom du fichier déjà existant, à exploiter');
readln(nom_fichier);
assign(f, nom_fichier);
{$I-} (* Permet de vérifier l'existence ou non du fichier à exploire *)
reset( f ); (* Ouverture du fichier cette fois-ci, donc supposé que le fichier existe *)
{$I+}
cd:= IOResult;
if cd <> 0 then
begin
writeln('----------DESOLE! Le fichier saisi n''existe pas-----------');
end;
until cd = 0;
assign(pt, 'C:\[Link]');
rewrite(pt);
seek(f, 0); (* Se positionne au début du fichier f *)
writeln('Entrez le numéro de l''extrait à supprimer');
readln(critere);
trouver:= false;
while not eof(f) do (* Il faut vérifier si l'extrait à supprimer existe dans le fichier *)
begin
read(f, t);
if t.num_ext = critere then
begin
trouver:= true;
end;
end;
if trouver = false then (* C'est que l'extrait à supprimer n'existe pas dans le fichier *)
begin
writeln('L''extrait à supprimer n''existe pas dans le fichier');
end
else (* C'est que l'extrait à supprimer existe dans le fichier *)
begin
seek(f, 0); (* Se positionne à nouveau au début du fichier f *)
while not eof(f) do
begin
read(f, t);
if critere <> t.num_ext then
begin
write(pt,t);
end;
end;
rewrite(f ); (* Ecrasement de tout le contenu du fichier f pour accueillir les nlles données*)
seek(pt, 0); (* Positionnement de l'index sur le début du fichier pt *)
while not eof(pt) do
begin
read(pt, t);
write(f, t); (* On va écrire à nouveau les données dans le fichier f *)
end;
close(pt);
erase(pt); (* On n'a plus besoin de lui .On va l'effacer pour ne pas occuper inutilement d'espace sur le disque dur *)
end;
end ; (* Fin du corps de la procédure supprimer_donnees *)
PROCEDURE modifier_motdepasse;
TYPE
MP = record
categorie : string[15];
mot_passe: string[20];
end;
VAR motpas1, motpas2, cat: string; ok: boolean; motP: MP; compt_util: file of MP; I: integer;
(* oK= pour savoir si les 2 mots de passe saisis sont identiques, I permet suivre l'index du fichier *)
begin (* Début du corps de la procédure modifier_motdepasse *)
ok:= false; I:= 0;
repeat
repeat
writeln('Entrez la catégorie dont on voudrait modifier le mot de passe');
readln (cat);
until (cat ='administrateur') or (cat = 'utilisateur');
writeln('Entrez le nouveau mot de passe');
readln(motpas1);
writeln('Confirmez le nouveau mot de passe'); (* Pour être sûr de ce qu'il a saisi *)
readln(motpas2);
if motpas1 = motpas2 then
begin
ok:= true;
assign(compt_util, 'C:\mot de [Link]'); (* On accède au fichier crée par le 1er programme *)
reset(compt_util); (* Ouverture sans écrasement au fichier crée par le 1er programme *)
read(compt_util, motP); (* Lecture des données contenues dans le fichier crée par le 1er prog *)
I:= I + 1; (* Pour dire que l'index a bougé d'un pas vers l'avant *)
[Link]:= cat;
motP.mot_passe:= motpas1; (* ou motP.mot_passe motpas2; *)
seek(compt_util, I-1); (* I-1 car l'enregistrement à mettre à jour, est le précédent et non celui en cours*)
write(compt_util, motP); (* Ecriture du nouveau mot de passe dans le fichier crée par le 1er prog *)
end
else
begin
writeln('MOTS DE PASSE NON IDENTIQUES! Veillez recommencer SVP!');
end;
until ok =true;
close(compt_util); (* Fermeture du fichier compt_util car on a fini de l'utiliser *)
end; (* Fin du corps de la procédure modifier_motdepasse *)
function verifier_compte(VAR cg, mt: string ): boolean; (* Note: verifier_compte(VAR cg: string[15] ): boolean; par exemple n'est pas
accépté *)
TYPE
MP = record
categorie : string[15];
mot_passe: string[20];
end;
VAR trouver: boolean; com: MP; compt_util: file of MP;
begin (* Début du corps de la fonction verifier_compte *)
trouver:= false;
assign (compt_util, 'C:\mot de [Link]'); (*On accède au fichier crée par le 1er programme *)
reset(compt_util);
while(not eof(compt_util)) and (trouver = false) do
begin
read(compt_util, com); (* Lecture du fichier pour avoir accès à ses données *)
if([Link] = cg) and (com.mot_passe = mt) then (* Les 2 doivent être vraies à la fois *)
begin
trouver:= true;
verifier_compte:= true;
end;
end;
if trouver = false then (* Le compte utilisateur saisi n'existe pas dans le fichier des mots de passe*)
begin
verifier_compte:=false;
end;
close(compt_util); (* Fermeture du fichier compt_util car on a fini de l'utiliser *)
end; (* Fin du corps de la fonction verifier_compte *)
begin (* Début du corps du programme principal *)
test:=true;
repeat
writeln ('Entrez votre catégorie');
readln(categ);
writeln('Entrez votre mot de passe');
readln(mpas);
valide:= verifier_compte(categ, mpas);
if valide = false then
begin
writeln ('COMPTE UTILSATEUR INEXISTANT !');
end;
until valide = true; (* Saisie du compte jusqu'à ce qu'il soit valide *)
(* A la sortie de REPETER…JUSQU'A, le compte utilisateur saisi est nécessairement valide *)
if categ = 'utilisateur' then (* On affiche les opérations qu'il peut effectuer *)
begin
writeln('LE MENU PRINCIPAL');
writeln('2 pour l''ajout des données dans le fichier');
writeln('4 pour la consultation des données du fichier');
writeln('---------------------------------------------------');
end;
if categ = 'administrateur' then (* On affiche les opérations qu'il peut effectuer (elles toutes) *)
begin
writeln('LE MENU PRINCIPAL');
writeln('1 pour la création d''un nouveau fichier');
writeln('2 pour l''ajout des données dans le fichier');
writeln('3 pour la modification des données du fichier');
writeln('4 pour la consultation des données du fichier');
writeln('5 Pour la suppression de données dans le fichier');
writeln('6 Pour la modification des mots de passe');
writeln('---------------------------------------------------');
end;
repeat
if categ = 'utilisateur' then
begin
repeat
writeln('Faites le choix de l''opération à effectuer');
readln(choix);
until(choix = 2) or (choix = 4);
end;
if categ = 'administrateur' then
begin
repeat
writeln('Faites le choix de l''opération à effectuer');
readln(choix);
until(choix = 1) or (choix = 2) or (choix = 3) or (choix = 4) or (choix = 5) or (choix = 6);
end;
case choix of
1 : creer_fichier; (* Appel de la procédure creer_fichier *)
2 : ajouter_donnees; (* Appel de la procédure ajouter_donnees *)
3 : begin
if test = true then
begin
modifier_donnees; (* Appel de la procédure modification *)
end
else
begin
writeln('OPERATION IMPOSSIBLE ! car le fichier est vide');
end;
end;
4 : begin
if test = true then
begin
consulter; (* Appel de la procédure consulter *)
end
else
begin
writeln('OPERATION IMPOSSIBLE! car le fichier est vide');
end;
end;
5 : begin
if test = true then
begin
supprimer_donnees; (* Appel de la procédure supprimer_donnees *)
end
else
begin
writeln('OPERATION IMPOSSIBLE ! car le fichier est vide');
end;
end;
6 : begin
if test = true then
begin
modifier_motdepasse;; (* Appel de la procédure modifier_motdepasse *)
end
else
begin
writeln('OPERATION IMPOSSIBLE ! car le fichier est vide');
end;
end;
end;
writeln('Voulez-vous continuer effectuer une autre opération ? O OUI et N NON ?');
readln(rep);
until(rep = 'N') or (rep = 'n');
close(f); (* A la fin, fermer le fichier f car on a fini de l'utiliser *)
end. (* Fin du corps du programme principal *)
L'exécution donne:
EXERCICE 22
Proposer un algorithme permettant de:
Créer une liste chaînée avec un nombre quelconque de cellules,
De lire le contenu de la liste créée,
D'ajouter des éléments à la fin de la liste,
Supprimer un élément quelconque de la liste, par la connaissance du nom.
Note: La cellule de base sera constituée des champs suivants: nom, prénom et le pays.
program creation_liste_chainee;
uses crt;
type
lien = ^cel; (* Déclaration d'un pointeur sur la structure cel *)
cel = record (* Définition de la structure cel *)
nom: string[20];
prenom: string[40];
pays: string[20];
suivant: lien;
end;
var
r: char;
t: lien; (* Déclaration d'une variable de type lien (c'est un pointeur sur cel *)
I, choix: integer;
procedure afficher_liste(var f: lien);
begin
if I=0 then
begin
writeln('OPERATION IMPOSSIBLE CAR LA LISTE EST VIDE');
end
else
begin
writeln(f^.nom);
writeln(f^.prenom);
writeln(f^.pays);
writeln('--------------------'); (* Pour séparer les différents affichages *)
if f^.suivant <> nil then
begin
afficher_liste(f^.suivant);
end;
end;
end;
procedure creer_liste (var e: lien);
var rep: char;
begin
new(e);
writeln('Donnez le nom');
readln(e^.nom);
writeln('Donnez le prénom');
readln(e^.prenom);
writeln('Donnez le pays');
readln(e^.pays);
e^.suivant:=nil;
I:=1; (* Pour dire qu'il y a désormais au moins une cellule dans la liste. C'est une valeur au choix. *)
writeln('Désirez-vous continuer ?');
readln(rep);
if(rep='O') or (rep='o') then
begin
creer_liste(e^.suivant);
end;
end; (* A la sortie de cette procédure, e pointe sur le première cellule *)
procedure ajouter_element(var pt: lien);
var temp: lien;
reponse: char;
begin
if I <> 0 then
begin
temp:=pt;
while temp^.suivant <> nil do (* Permet de se positionner à la fin de la liste *)
begin
temp:=temp^.suivant;
end; (* A la fin, temp pointera sur la dernière cellule *)
repeat
new(temp^.suivant);
writeln('Entrez le nom');
readln(temp^.suivant^.nom);
writeln('Entrez le prénom');
readln(temp^.suivant^.prenom);
writeln('Entrez le pays');
readln(temp^.suivant^.pays);
temp^.suivant^.suivant:=nil;
writeln('Continuez?');
readln(reponse);
if (reponse = 'O') or (reponse= 'o') then
begin
temp:= temp^.suivant;
end;
until (reponse='N') or (reponse='n');
writeln('Le nouveau contenu de la liste est:');
afficher_liste(pt);
end
else
begin
writeln('OPERATION IMPOSSIBLE CAR LA LISTE EST VIDE');
end;
end;
procedure supprimer_element(var sp: lien);
var n: string[25];
temp, tp: lien;
j: integer;
begin
if I = 0 then
begin
writeln('OPERATION IMPOSSIBLE CAR LA LISTE EST VIDE');
end
else
begin
writeln('Entrez le nom à supprimer');
readln(n);
tp:=sp;
j:=0;
while(tp^.nom <> n) and (tp^.suivant <> nil) do
begin
temp:=tp; (* Pour pointer sur la cellule précédente *)
tp:=tp^.suivant;
j:=j + 1;
end;
if(tp^.nom = n) and (j = 0) then (*j=0: C'est que c'est la première cellule qui contient l'élément à supprimer *)
begin
if tp^.suivant = nil then (* C'est qu'il y a une seule cellule dans la liste *)
begin
dispose(tp);
tp:=nil;
sp:=nil;
writeln('La liste est désormais vide');
I:= 0; (* pour signifier que la liste est désormais vide *)
end
else (* C'est qu'il y a plusieurs cellules dans la liste *)
begin
sp:= tp^.suivant;
dispose(tp);
tp:=sp;
writeln('L''élément a été supprimé avec succès');
afficher_liste(sp); (* Ici sp car sp pointe sur le début de la liste *)
end;
end
else (* IMPORTANT! Sans le else et si tp pointe sur nil(voir plus haut), l'on va continuer l'exécution du programme sur la 2e ligne plus bas.
Dans ce cas tp^.nom n'a plus de sens. On recevra donc un message d'erreur *)
begin
if(tp^.nom = n) and (j <> 0) then (*Ce n'est pas la première celule qui est à supprimer *)
begin
temp^.suivant:=tp^.suivant;
dispose(tp);
writeln('L''élément a été supprimé avec succès');
afficher_liste(sp);
end
else
begin
if(tp^.nom <> n) and (tp^.suivant = nil) then
begin
writeln('L''élément à supprimer n''existe pas dans le fichier');
end;
end;
end;
end;
end;
Historique
Le langage C fut développé en 1972 par DENNIS RITCHIE et BRIAN KERNIGHAN aux laboratoires BELL (devenus AT & T
BELL), aux USA. Il dérive du langage B, conçu lui à l'aide du langage d'assemblage.
Le but du langage C était de reprogrammer le système d'exploitation UNIX, conçu à l'aide du langage d'assemblage par
KEN THOMPSON et DENNIS RITCHIE en 1970, aux laboratoires BELL, pour lui donner ses caractéristiques de multitâche,
de multi utilisateur…et surtout de multi plateforme (c'est-à-dire le même code source du système d'exploitation UNIX
peut être recompilé pour créer des versions différentes d'UNIX adaptées au jeu d'instruction de chaque
microprocesseur).
Le succès d'UNIX donna succès au langage C.
Le langage C existe de nos jours sous différentes distributions et ces différentes distributions, après la normalisation de
ANSI (American National Standard Institute) sont compatibles entre elles mais à une infime différence. Ce sont Turbo C,
Turbo C++ de BORLAND, Microsoft C de Microsoft, Visual C++ de Microsoft…
C'est l'un des langages de programmation les plus utilisés de nos jours dans le monde si bien que la plupart des
nouveaux langages de programmation naissant de nos jours, ont pour racine, le langage C.
Explications
1*: Cette partie concerne l'inclusion des fichiers (ou bibliothèques ou librairies ou unités) dans le code source avant la
compilation car ces fichiers contiennent la définition des certaines instructions (fonctions) que nous voulons utiliser dans
notre programme. L'inclusion se fait selon la syntaxe suivante:
#include <nom_bibliothèque> ou #include "nom_bibliothèque"
Note: Si lors de la compilation, vous recevez un message stipulant que la bibliothèque spécifiée n'a pas été trouvée, il
faudra dans ce cas lors de l'inclusion, préciser tout le chemin d'accès de la bibliothèque.
Exemples:
#include <stdio.h> ou #include "stdio.h" ou
#include <c:\tcp\include\stdio.h> Ici avec précision du chemin d'accès
Remarque: Pour connaître la bibliothèque d'une fonction (instruction) connue de C, l'on se positionne à l'intérieur de
ladite instruction (à l'aide du curseur) et l'on fait CTRL-F1 (on maintient la touche CTRL du clavier enfoncé et sans
relâché, l'on appuie sur la touche F1). De là une boîte de dialogue s'affiche vous indiquant la bibliothèque dans laquelle
se trouve ladite instruction.
2* C'est ici que l'on déclare les constantes. C'est également ici que l'on déclare les macros ou l'on les définit. Si les
macros ont été déclarées simplement ici sans avoir été définies alors leur définition se fera au 7*.
3* C'est ici que l'on déclare les structures de données statiques (enregistrement, énuméré, union…).
4* C'est en effet ici que l'on déclare les variables globales.
5* C'est ici que l'on déclare ou définit les sous programmes. En effet l'on peut déclarer un sous programme sans le
définir. Dans ce cas, la déclaration se fait ici et la définition au 7*. Comme l'on peut déclarer un sous programme et le
définir en même temps. Dans ce cas les deux se feront ici.
6* C'est ici débute le corps du programme principal. Il est matérialisé par la syntaxe ci-après:
main() ou void main() ou void main(void).
Note:
Certaines distributions de C acceptent la 1ere syntaxe, certaines la 2e syntaxe et d'autres la 3e syntaxe. Dans tous les
cas, essayez l'une ou l'autre des syntaxes.
Le programme principal peut ramener une valeur ou pas, peut avoir des arguments ou pas.
A l'intérieur du corps du programme principal, l'on peut déclarer des variables. Dans ce cas ces variables sont dites
locales au programme principal.
7* Si les macros et les sous programmes ont été simplement déclarées (et non pas définies) respectivement au 2* et au
5* alors c'est ici que l'on va maintenant les définir. Mais si d'aventure les macros et les sous programmes ont été
déclarées et définies respectivement au 2* et au 5*, dans ce cas le 7* ne va pas exister.
2) Caractéristiques du langage C
Le langage C respecte la casse c'est-à-dire fait la différence entre les majuscules et les minuscules (contrairement au
langage Pascal). Ainsi nom ≠ Nom ≠ noM ≠ NOM.
Lors de l'utilisation des instructions de C, il faudra les écrire tels que c'est stipulé. Exemple: l'instruction d'affichage
est printf. Mais si vous écrivez Printf ou pRintf ou printF…le langage C ne les reconnaîtra pas.
Les règles de nomination des variables, constantes et autres, sont celles vues au chapitre 4 du fascicule d'algorithme
du même auteur. En aucun moment les objets du programme doivent porter comme nom, les mots clés du langage C
(voir le prochain paragraphe).
Le langage C est permissif, c'est-à-dire que contrairement au langage Pascal où la plupart des erreurs sémantiques
sont signalées lors de la compilation; le langage C ne les signale pas, mais il va vous produire un résultat surprenant lors
de l'exécution. Donc vigilance!.
Remarque: Pour certains compilateurs, les types int et short int sont identiques. D= [-32 768; +32 767].
Exemple de déclarations d'entiers:
int a;
short b;
long int d;
unsigned int nb;
b) Le type réel
Les types "flottants" permettent de représenter, de manière approchée, une partie des nombres réels. Pour ce faire,
ils s'inspirent de la notation "scientifique" (ou "exponentielle") bien connue qui consiste à écrire un nombre sous la forme
1.5.1022 ou 0.472.10-8; dans une telle notation, on nomme "mantisses" les quantités telles que 1.5 ou 0.472 et
"exposants" les quantités telles que 22 ou -8. Ainsi donc un réel est exprimé sous deux formes: sous forme décimale ou
sous forme exponentielle (pour les grands nombres).
Sous forme décimale: 1.5 1.0
Sous forme exponentielle: 1.5e+3 (= 1,5*103 ), 1.2 e-15 (=1,2*10-15 ).
La déclaration se fait suivant la syntaxe ci-après: mot_clé nom_variable;
Pour les réels, les mots clés sont: float, double, long double. Malheureusement la norme ANSI ne spécifie pas leurs
caractéristiques. En plus leur représentation diffère d'un microordinateur à un mini ordinateur et d'un mini ordinateur à
un super ordinateur. Néanmoins, l'on peut retenir typiquement sur les micro-ordinateurs, les valeurs ci-après:
Types de réel Espace occupé en mémoire centrale Espace des valeurs
float 4 octets [-3.4*1038; 3.4*1038]
double 8 octets [-1.7*10308; 1.7*10308]
long double 10 octets [-3.4*104932; 3.4*104932]
Exemple de déclarations de réels:
float som;
double pop;
long double d;
c) Le type caractère
Il est noté char.
Exemple: char c; char rep;
La valeur d'un caractère est placée entre quote( ' ')
Exemple: c='p'; rep='N';
Note importante: Pour pouvoir utiliser une variable de type char*, il faudra nécessairement l'initialiser à la
déclaration, avant toute utilisation. Exemple d'initialisation char* prenom ="";
Les différents caractères d'une chaîne de caractère (que la déclaration de la chaîne soit faite avec un tableau de
caractère ou avec un pointeur vers une chaîne de caractère) peuvent être accédés individuellement grâce à un indice
allant de 0 à n-1 (n représentant le nombre total de caractère de la chaîne de caractère) et placé entre [].
Exemple: Au regard de l'exemple précédent, nous pouvons avoir:
nom[0] qui ramène N
nom[3] qui ramène E
nom[6] qui ramène A.
L'avantage de char* sur le tableau de caractères, est que lors de la saisie, le type char* n'est pas limité en nombre de
caractère contrairement au tableau de caractères où l'on ne peut excéder la taille du tableau-1.
Remarque: Lorsqu'on déclare char nom [30]; en réalité la variable nom pourra contenir au plus 29 caractères. Le 30e
caractère est réservé au caractère de fin de chaîne de caractère: '\0' (caractère nul). Donc vigilance!
Remarque importante: Les opérateurs >, >=, <, <=, = et != ne sont pas applicables sur les chaînes de caractères, en
langage C. Ainsi pour comparer deux chaînes de caractères, il utiliser la fonction strcmp (Voir plus loin).
e) Le type booléen
Le type booléen n'existe pas en C: 0 est faux et ≠ 0 représente vrai.
Exemple: if (i) instruction1; Cela veut dire que si i ≠ 0 alors on exécute l'instruction1.
NB: Une variable peut être déclarée et être initialisée lors de cette déclaration, en langage C.
Exemple: int chiffre = 0;
2) L'incrémentation et la décrémentation
Incrémentation: En algorithme, p ← p+1; deviendra en C: p = p+1;
Décrémentation: En algorithme, e ← e -2; deviendra en C: e = e-1;
3) Les opérateurs ++ et --
Ce sont d'autres formes d'incrémentation (++) et de décrémentation (--).
a) L'opérateur ++
L'on peut utiliser chacun de ces opérateurs en:
En pré incrémentation: Syntaxe: ++ nom_variable;
Explication: En utilisation isolée: Cela consiste à incrémenter le contenu de la variable mentionnée de 1.
Exemple: ++i; Cela stipule d'incrémenter la variable i de 1
Exemple: ++p; Cela stipule d'incrémenter la variable p de 1
En utilisation expressive: Cela consiste à incrémenter d'abord le contenu de la variable mentionnée de 1
puis à transférer la valeur ainsi obtenue à l'expression.
Exemple:
I=2;
J=5*++I; Cela stipule d'abord d'incrémenter le contenu de la variable I de 1 puis de multiplier
cette valeur ainsi obtenue de I par 5 et finalement d'attribuer la valeur ainsi obtenue à J. Donc finalement I va valoir 3 et
J aura la valeur 15.
Exemple:
P=7;
D=3*P++; Cela stipule de multiplier 3 par la valeur actuelle de P (qui est 7). Puis de ranger ce
résultat dans la variable D. Ainsi D recevra 21. Et enfin d'incrémenter le contenu de P de 1; soit P vaudra 8.
b) L'opérateur --
En pré incrémentation: Syntaxe: - - nom_variable;
Explication: En utilisation isolée: Cela consiste à décrémenter le contenu de la variable mentionnée de 1.
Exemple: --i; Cela stipule de décrémenter la variable i de 1
Exemple: --p; Cela stipule de décrémenter la variable p de 1
En utilisation expressive: Cela consiste à décrémenter d'abord le contenu de la variable mentionnée, de
1 puis à transférer la valeur ainsi obtenue à l'expression.
Exemple:
A=3;
L=4*--A; Cela stipule d'abord de décrémenter le contenu de la variable A de 1 puis de multiplier
cette valeur ainsi obtenue de A par 4 et finalement d'attribuer la valeur ainsi obtenue à L. Donc finalement A va valoir 2
et L aura la valeur 8.
En post incrémentation: Syntaxe: nom_variable --;
Explication: En utilisation isolée: Cela consiste à décrémenter le contenu de la variable mentionnée de 1.
Exemple: F--; Cela stipule de décrémenter la variable F de 1
Exemple: E--; Cela stipule de décrémenter la variable E de 1
En utilisation expressive: Cela consiste d'abord à transférer le contenu de la variable à l'expression pour
calcul et après cela, à décrémenter le contenu de la variable mentionnée de 1.
Exemple:
mt=6;
h=2*mt--; Cela stipule de multiplier 2 par la valeur actuelle de mt (qui est 6). Puis de ranger ce
résultat dans la variable h. Ainsi h recevra 12. Et enfin de décrémenter le contenu de mt de 1; soit mt vaudra 5.
4) Les commentaires
Les commentaires commencent par /* et se terminent par */ ou simplement // commentaires. Mais la forme /*….*/
permet de faire un commentaire sur plusieurs lignes et // permet un commentaire sur une seule ligne.
Exemple de commentaires:
int p; /* Déclaration d'une variable de type entier*/
char rep; // Déclaration d'une variable de type caractère
5) La troncature des phrases longues
Pour tronquer des phrases trop longues en toute circonstance, y compris à l’intérieur d’une chaîne de caractères, l'on se
sert du caractère anti-slash \. Par exemple, le texte message = "anti\
constitutionnellement"; est compris comme ceci : message = "anti constitutionnellement" ;
FIN: }
SI…ALORS: if (condition) Exemple if ( a>=b)
{ {
Instructions; k=0; e++;
} }
Note: Les parenthèses autour de la condition sont obligatoires même s'il y a une seule condition.
SI…ALORS…SINON: if (condition) Exemple: if ((a!=b) && (d==0))
{ {
Instructions; c=1;
} e*=3;
else }
{ else
Instructions; {
} i=j*++n;
}
REPETER…JUSQU'A: do Exemple: do
{ {
Instructions; a = b + 1;
} d = 0;
While (condition); m=d + a;
}
While (m!=10);
Note: Ici do…while (condition) stipule d'exécuter le bloc d'instructions tant que la condition est vraie. Or en algorithme, REPETER…JUSQU'À
(condition) stipule d'exécuter le bloc d'instruction jusqu'à ce que la condition soit vraie. Donc do…while prend la négation de la condition et des
éventuels opérateurs logiques, mentionnés en algorithme.
Exemple1: Exemple2:
En algorithme En C En algorithme En C
REPETER do REPETER do
a ← b+1; { a = b+1; } AFFICHER('Continuer?'); { printf("Continuer?");
JUSQU'À n = 10; while (n!=10); SAISIR(rep); scanf("%c", &rep);
JUSQU'À (rep ='N') OU (rep = 'n'); }
While(( rep != 'N') && (rep!='n'));
Exemple3:
En algorithme En C
b ← 1; b = 1;
REPETER do
b ← b + 1; { b = b + 1;
AFFICHER('Continuer?'); printf("Continuer?");
SAISIR(rep); scanf("%c", &rep);
JUSQU'À (rep = 'n') ET (b =10); }
While ((rep != 'n') || (b != 10));
POUR…FAIRE: for (expression1; expression2; expression3)
{
Instructions;
}
Où expression1 a pour rôle d'initialiser le compteur de la boucle; expression2 représente la condition à satisfaire pour
continuer l'exécution de la boucle et expression3 sert à modifier la valeur du compteur, du moins sert à faire évoluer la
valeur du compteur initialisé par expression1.
Note: Dans l'exemple en langage C, le compteur I évolue par pas de 1, c'est-à-dire qu'il passe de 2 à 3 puis à 4 et ainsi de suite. Mais l'on pouvait le
faire évoluer par pas différent de 1. Pour le choix d'un pas de 2 par exemple, l'on écrirait I=I+2 dans la boucle for, à la place de I=I+1.
Remarque concernant les instructions alternatives et repétitives:
S'il y a une seule instruction dans le bloc d'instruction, l'on n'est dans ce cas pas obligé de mettre les accolades
ouvrantes ({) et fermante ( }). Mais s'il y a plus d'une instruction, les accolades sont obligatoires.
Exemples: while (a>=5)
if(i==0) {
{ Peut s'écrire if(i==0) b=b+1; ++a; Peut s'écrire while (a>=5) ++a;
b=b+1; }
}
8) Le test condition
C'est en fait un if…else mais qui a une valeur.
Syntaxe: (expression1 ? expression2 : expression3);
Explication: Si la condition figurant dans expression1 est vraie alors l'on exécute expression2 sinon l'on exécute
expression3.
Exemples:
( (a>0) ? a = a + 1 : a = a – 1 ); Si a>0 alors a=a+1 sinon a=a+2.
Des caractères appelés séquences d'échappement permettent de contrôler l'affichage des données. Ce sont:
Exemple: printf("La moyenne générale est: %10.3f", moy); Permet d'afficher la valeur de la variable moy sur 10
chiffres dont 3 après la virgule.
b) La directive d'entrée
Elle se nomme scanf. Elle permet de lire une liste de valeurs suivant un format donné.
Syntaxe: scanf("format", &nom_variable); Ceci lorsqu'on désire effectuer une seule saisie.
OU scanf("format1format2…format n", &nom_var1, &nom_var2,…, &nom_var n); Ceci lorsqu'on désire
effectuer plusieurs saisies.
Exemple1: int a; Exemple2: int a;
………………….. float b;
printf("Entrez un nombre\n"); printf("Entrez un entier et un réel\n");
scanf('%d", &a); scanf("%d%f", &a, &b);
……………………….. Ici la 1ere valeur saisie sera mise dans a et la 2e dans
b.
L'on peut limiter la longueur de la valeur à saisir par des nombres placés entre % et la lettre de spécification des
formats (pour tous les formats).
Exemple1: scanf("%3d", &b); signifie que l'on voudrait que la valeur de la variable b à entrer, tienne sur 3 chiffres
maximum. Ainsi si à l'exécution, l'utilisateur saisit par exemple 12546, dans ce cas seule la valeur 125 qui sera mise dans
la variable b. Les chiffres restants c'est-à-dire 46, seront perdus.
Exemple2: Soit scanf("%3d%3d%3d", &a, &b, &c); Et soit les saisies suivantes:
123 456 789 ainsi a=123 b=456 et c=789.
123456789 ainsi a=123 b=456 et c=789
1234 5678 9 ainsi a=123 b=4 c=567 puis 8 et 9 seront perdus.
Note: Le séparateur des nombres (entiers et réels) est l'espace et le retour chariot (=appui sur la touche ENTREE du
clavier=validation=fin de ligne et a pour symbole ¶).
c) Les caprices de la directive d'entrée (concernant les caractères (%c)et les chaînes (%s) )
Concernant les caractères (le code %c): Le code %c ne saute aucun séparateur et prend le 1er caractère qui se
présente (y compris les caractères espace et fin de ligne (validation) qui a pour symbole ¶ et pour valeur réelle \n). Ce
qui engendre très souvent des désagréments.
Exemple1: char c1, c2, c3;
printf("Entrez 2 caractères");
scanf("%c%c", &c1, &c2);
printf("Entrez un autre caractère);
scanf("%c", &c3);
………………………..
1er cas:
A l'exécution, l'utilisateur saisit par exemple: ab¶ . Ainsi c1 = a , et c2 = b et le caractère ¶ introduit par la validation
reste disponible pour une prochaine lecture, dans la mémoire tampon créée par scanf; car en effet pour recueillir les
données saisies par l'utilisateur, la fonction scanf crée une zone tampon dans la mémoire centrale de l'ordinateur..
A l'affiche de " Entrez un autre caractère", l'ordinateur va regarder dans la zone tampon créée par le 1er scanf et il y
verra ¶, qu'il va prendre soins de l'attribuer à c3 (donc c3 = ¶) et donc ne laissera pas l'utilisateur saisir le caractère (la
valeur de c3) puis il passera aux instructions suivantes. VOYEZ-VOUS LE DESAGREMENT!
2e cas:
A l'exécution, l'utilisateur saisit par exemple: a b¶ . Ainsi c1 = a , et c2 = (l'espace entre a et b) et les informations
restantes (b¶) demeurent disponibles dans la mémoire tampon créée par scanf, pour une prochaine lecture.
A l'affiche de " Entrez un autre caractère", l'ordinateur va regarder dans la zone tampon créée par le 1er scanf et il y
verra b¶, qu'il va prendre soins d'attribuer à c3 la valeur b (c3=b). Et là encore l'ordinateur ne laissera pas l'utilisateur
saisir le caractère (la valeur de c3) car c3 a déjà une valeur, puis il passera aux instructions suivantes. En plus le
caractère ¶ reste disponible dans la zone tampon pour une prochaine lecture.
printf("Entrez 2 caractères\n");
scanf("%c%c", &c1, &c2);
printf("Entrez un entier\n");
scanf("%d", &c3);
printf("La valeur de c3 est: %d\n", c3);
a = 5;
printf("La valeur de a est: %d", a);
getch(); // Permet de voir afficher le résultat. L'on pourrait utiliser aussi while(!kbhit());
}
A l'exécution, on a:
Explication: A l'invitation" Entrez les 2 caractères", l'utilisateur a saisi: a b¶ (et a validé). Ainsi c1 = a, c2 = (l'espace). Il
est donc resté b¶ dans la mémoire tampon pour les prochaines lectures. Ainsi au prochain scanf("%d", &c3), l'ordinateur
sans laisser le temps à l'utilisateur, a attribué la valeur b à c3, bien qu'étant un entier et est passé aux instructions
suivantes. A l'affichage de la valeur de c3, vous vous rendez compte qu'il a affiché 8775. Valeur erronée! (Une valeur
aléatoire car à chaque exécution du même programme il affiche des valeurs différentes pour c3)! Vous vous souvenez
dans les lignes précédentes, j'avais dit que le langage C est permissif?
Concernant les chaînes de caractères (le code %s): Le code %s ne saute non plus aucun séparateur et prend le 1er
caractère qui se présente (y compris les caractères espace et fin de ligne (validation) qui a pour symbole ¶ et pour
valeur réelle \n). Ce qui engendre très souvent des désagréments.
A l'exécution, vous vous rendez compte que l'ordinateur d'abord n'a pas laissé la main à l'utilisateur pour saisir la valeur
du mot et en plus il a attribué la valeur espace à la variable c2 et la valeur b à nom! Ce qui n'est pas du goût de
l'utilisateur!
Comment faire sauter les séparateurs au code %c? (Il s'agit de l'espace et la validation)
Il suffit de faire précéder le code %c d'un espace comme suit:
#include <stdio.h> //Permet d'utiliser les fontions printf() et scanf()
#include <conio.h> //Permet d'utiliser la fontion getch()
void main()
{ char c1, c2 ;
printf("Entrez le 1er caractère\n");
scanf(" %c", &c1); // Faites précéder le code %c d'un seul espace
printf("Entrez le 2e caractère\n");
scanf(" %c", &c2); // Faites précéder le code %c d'un seul espace
printf("La valeur du 1er caractère est: %c", c1);
printf("La valeur du 2e caractère est: %c", c2);
getch();
}
l'exécution, on aura:
Ou bien ce programme:
#include <stdio.h> //Permet d'utiliser les fontions printf() et scanf()
#include <conio.h> //Permet d'utiliser la fontion getch()
void main()
{ char c1, c2 ;
char nom[30];
printf("Entrez 2 caractères\n");
scanf(" %c %c", &c1, &c2); // Un espace précède le 1er %c et un autre espace précède le 2e %c
printf("La valeur de c1 est: %c\n", c1);
printf("La valeur de c2 est: %c\n", c2);
printf("Entrez un mot\n");
scanf("%s", &nom);
printf("La valeur de nom est: %s\n", nom);
getch(); // Permet de marquer une pause pour nous permettre de voir le résultat (c'est le readln de Pascal).
}
A l'exécution, on a:
Une autre solution au problème posé par les caractères et chaînes de caractère est de vider la mémoire tampon
avant une prochaine entrée de donnée. Pour le faire, l'on utilise la fonction gets(). Syntaxe: gets(nom_chaîne); où
nom_chaîne un tableau de caractères ou un pointeur vers une chaîne de caractères.
Note: Utiliser gets() lorsqu'on saisit des caractères ou des chaînes de caractères.
Soit ce programme:
#include <stdio.h> //Permet d'utiliser les fontions printf() et scanf()
#include <conio.h> //Permet d'utiliser la fontion getch()
void main()
{ int n; char rep;
char s[5];
do
{ printf("Entrez une valeur\n");
scanf("%d",&n);
printf("Voulez-vous continuer?\n");
scanf("%c",&rep);
}
while ( (rep!='n') && (rep!='N') );
getch();
}
A l'exécution, on a:
Vous voyez bien que dès la saisie de la valeur et la validation, l'ordinateur ne nous laisse même pas répondre à la
question posée et il passe à autre chose. En fait après la saisie de la valeur 25 et la validation (¶), la valeur 25 est mise
dans la variable n ( ¶ n'est pas aussi mis dans n car n est un entier) et il reste ¶ dans le tampon, qui reste disponible
pour la prochaine lecture. Au prochain scanf (scanf("%c",&rep); ), l'ordinateur se rend compte qu'il s'agit d'un caractère
qui est dans le scanf, et il lui attribue le ¶ qui est resté dans le tampon. Raison pour laquelle il nous a pas laissés
répondre à la question (pour lui nous avons déjà répondu à la question).
Comment y remédier? La solution est donc de vider la mémoire tampon avant une prochaine lecture c'est-à-dire de
mettre dans une variable de type chaîne, les données qui sont en attente dans le tampon, pour qu'il soit vide.
Remarque: Pour vider le tampon, on peut utiliser un tableau de caractères ou un pointeur vers une chaîne de caractère. Mais
pour manipuler une chaîne recueillie par gets, il faut que cette chaîne soit un tableau de caractères sinon ça ne marche pas.
Le programme solution est le suivant:
#include <stdio.h> //Permet d'utiliser les fontions printf() et scanf()
#include <conio.h> //Permet d'utiliser la fontion getch()
void main()
{ int n; char rep; char s[5];
do
{ printf("Entrez une valeur\n");
scanf("%d",&n);
gets(s); //Permet de vider le contenu du tampon dans la chaîne s
printf("Voulez-vous continuer?\n");
scanf("%c", &rep);
}
while (rep!='n');
getch();
}
Ou bien, on peut aussi appliquer gets sur un pointeur vers une chaîne de caractère:
#include <stdio.h> //Permet d'utiliser les fontions printf() et scanf()
#include <conio.h> //Permet d'utiliser la fontion getch()
void main()
{ int n; char rep;
char * s=""; // A initialiser obligatoirement, au choix
do
{
printf("Entrez une valeur\n");
scanf("%d",&n);
gets(s); //Permet de vider le contenu du tampon dans la chaîne s
printf("Voulez-vous continuer?\n");
scanf("%c", &rep);
}
while (rep!='n');
getch();
}
A l'exécution, on a désormais:
Nous remarquons que l'utilisateur a bien saisi comme valeur du nom: NGUESSAN Koffi Mathieu et à l'affichage,
l'ordinateur a affiché seulement NGUESSAN comme valeur saisie! Il y a encore là problème avec l'affichage des chaînes
de caractères.
Que s'est-il passé? En effet la fonction scanf lorsqu'elle parcourt une valeur saisie, s'arrête dès qu'elle rencontre un
délimiteur (espace, retour chariot(¶) ). Ainsi après NGUESSAN, lorsqu'elle a rencontré l'espace, elle s'est dit que la
chaîne est terminée et donc a affecté NGUESSAN seulement à la variable nom. En effet le scanf(..%s) ne saute pas
les espaces donc arrête la lecture dès qu'il rencontre un espace.
Comment y remédier? Il faudra utiliser gets à la place de scanf. En effet gets prend en compte les espaces
donc n'arrête pas la lecture à la rencontre d'un espace.
#include <stdio.h> //Permet d'utiliser les fontions printf() et scanf()
#include <conio.h> //Permet d'utiliser la fontion getch()
void main()
{ char c1, c2 ;
char nom_P[45], s[10];
printf("Entrez 2 caractères\n");
scanf(" %c %c", &c1, &c2);
printf("La valeur de c1 est: %c\n", c1);
printf("La valeur de c2 est: %c\n", c2);
gets(s); // Ici gets permet de vider le tampon
printf("Entrez le nom et prénomn");
gets(nom_P); // Ici gets permet la saisie du nom même contenant des espaces
printf("La valeur de nom est: %s\n", nom);
getch();
}
A l'exécution, on a désormais:
Voici un autre programme permettent d'utiliser char* et la fonction strcpy. En effet l'on ne peut pas attribuer une
valeur à un tableau de caractères, en utilisant le signe d'affectation(=). Il faut utiliser une fonction
nommée strcpy.
#include <stdio.h> //Permet d'utiliser les fontions printf() et scanf()
#include <conio.h> //Permet d'utiliser la fontion getch()
#include <string.h> // permet d'utiliser la fonction strcpy
void main()
{ char* nom = ""; // pointeur vers une chaîne
char prenom[20]; // tableaux de caractère
char t[15];
char P[2];
strcpy(t, "MATHIEU"); // Permet d'attribuer la valeur MATHIEU au tableau de caractètres, nommé t
printf("La valeur de t est:%s", t);
printf("\nEntrez le nom\n");
scanf("%s", nom); // pas de & avant le nom
gets(P); // Permet de vider le tampon dans la chaîne P
printf("Entrez le prénom\n");
gets(prenom); // Permet de saisir la valeur du prénom, avec des espaces. Exemple: Koffi Mathieu
printf("Le nom est: %s", nom);
printf("\nLe prénom est: %s", prenom);
getch();
}
Vous voyez bien que l'utilisateur a saisi 2 et toutes les instructions qui suivent y compris celle du default, ont été
exécutées. Dans de tel cas, ça ne nous permet pas de faire un meilleur choix. Comment y remédier?
C'est ce que nous allons voir dans la partie qui suit.
Exemple de programme:
#include <stdio.h>
void main()
{ int P, i, j, k;
P=(i=1, j=2), k=3;
printf("P vaut %d", P);
}
A l'exécution, on aura P vaut 2
*getch( ): Permet de saisir un caractère unique mais l'on ne voit pas à l'écran, le caractère qu'on a saisi. De
surcroît, dès la saisie du caractère, l'ordinateur passe automatiquement à l'instruction suivante sans qu'on ait a appuyé
sur la touche entrée du clavier.
#include <stdio.h> //Permet d'utiliser les fontions printf() et scanf()
#include <conio.h> //Permet d'utiliser la fontion getch()
void main()
{ char c;
printf("Entrez une valeur: ");
c=getch();
putc(c, stdout);
getch();
}
*getche( ): Exactement comme getch( ) mais ici l'on voit le caractère saisi.
#include <stdio.h> //Permet d'utiliser les fontions printf() et scanf()
#include <conio.h> //Permet d'utiliser la fontion getch()
void main()
{ char c;
printf("Entrez une valeur: ");
c=getche();
puts("\nle caractère saisi est: ");
putc(c, stdout);
getch();
}
……………………………………..
……………………………………
}
Type_renvoyé_par_la_fonction nom_fonction (type_paramètre1 nom_paramètre1,…, type_paramètre n nom_paramètre n)
{ Déclaration
Instruction(s);
return(n); // Instruction permettant de renvoyer le résultat de la fonction
}
Exemple:
#include <stdio.h>
………………………………….
int essai (char a, long int b, float c); //Déclaration de la fonction essai. Présence de point virgule à la fin.
………………………..
Void main( )
{
……………………..
}
int essai (char d, long int p, float q) // Définition de la fonction essai après le main(). Pas de ; à la fin de main()
{ int e;
…………………….
return (e);
}
Exemple: Proposer une fonction permettant de calculer le carré d'un nombre réel.
#include <stdio.h>
int a;
float b;
char c;
double carre(float e);
Void main( )
{
……………………………..
}
double carre (float e) // La variable e est fictive. Notre fonction s'appelle carre et retourne un réel.
{ double t; // Variable qui va nous servir à recueillir le résultat de la fonction
t=e*e;
return(t); // Recueil du résultat.
}
b) Fonctions "action"
Idems aux fonctions "calcul" mais cette fois-ci, l'on met:
Void à la place du type renvoyé par la fonction,
A la fin de définition de la fonction, l'on ne met plus de return.
Exemple:
#include <stdio.h>
int a;
void optimist(int c); // Déclaration de la fonction optimist
void main( )
{ printf("Entrez le nombre de fois que l'on doit répéter");
scanf("%d", &a);
optimist(a); // Appel de la fonction optimist
} // Fin de la fonction principale
4) Appel de fonction
a) Fonction "calcul"
Syntaxe: nom_variable = nom_fonction(paramètres effecitfs); Avec nom_variable de même type que le type renvoyé
par la fonction.
Exemple:
#include <stdio.h>
float c, t;
float cube(int e) // La variable e est fictive. Notre fonction s'appelle cube et retourne un réel.
{ float f; // Variable qui va nous servir à recueillir le résultat de la fonction
f=e*e*e;
return(f); // Recueil du résultat.
}
void main( )
{
printf("Entrez le réel\n");
scanf("%f", &t);
c = cube(t); // Appel de la fonction cube
printf("Le cube de %f est %f", t, c);
b) Fonction "action"
Syntaxe: nom_fonction(paramètres effecitfs);
Exemple:
#include <stdio.h>
int a;
void optimist(int c) // Déclaration et définition combinées, de la fonction optimist
{ int i;
for(i=0;i<n_fois; i=i+1)
{ printf("Il fait beau \n");
}
}
void main( )
{ printf("Entrez le nombre de fois que l'on doit répéter");
Scanff("%d", &a);
optimist(a); // Appel de la fonction optimist
} // Fin de la fonction principale
Remarque: Même si la fonction n'a pas de paramètre, il faudra lors de la déclaration, de la définition ou de l'appel,
conserver la paire de parenthèses. Exemple: essai ( ).
5) Passage de paramètres
a) Par valeur
Lors de la déclaration ou de la définition:
Type_renvoyé_par_la_fonction nom_fonction (type_paramètre1 nom_paramètre1,…, type_paramètre n nom_paramètre n);
Ou void nom_fonction (type_paramètre1 nom_paramètre1,…, type_paramètre n nom_paramètre n); pour les fonctions "action".
Lors de l'appel: nom_variable = nom_fonction(argument1, argument2,… argument n); ou
nom_fonction(argument1, argument2,… argument n); pour les fonctions "action".
b) Par adresse
Lors de la déclaration ou de la définition:
Type_renvoyé_par_la_fonction nom_fonction (type_paramètre1 *nom_paramètre1,…, type_paramètre n *nom_paramètre n);
Ou void nom_fonction (type_paramètre1* nom_paramètre1,…, type_paramètre n* nom_paramètre n); pour les fonctions "action".
Exercice: Proposer un programme permettant d'échanger les contenus de deux (2) variables:
Avec le passage par valeur
Avec le passage par adresse.
Passage par valeur Passage par adresse
#include <stdio.h> #include <stdio.h>
int n=10, p=20; int n=10, p=20;
void echange (int e, int f); void echange (int* e, int* p);
void main( ) // Début de main() void main( ) // Début de main()
{ printf("Avant appel n=%d et p=%d", n, p); { printf("Avant appel n=%d et p=%d", n, p);
echange(n, p); echange(&n, &p);
printf("Après appel n=%d et p=%d", n, p); printf("Après appel n=%d et p=%d", n, p);
} // Fin de main() } // Fin de main()
Void echange (int a, nt b) Void echange (int* a, nt* b)
{ int c; { int c;
printf("Début échange n=%d et p=%d", a, b) printf("Début échange n=%d et p=%d", *a, *b);
c=a; c=*a;
a=b; *a=*b;
b=c; *b=c;
printf("Fin échange n=%d et p=%d", a, b); printf("Fin échange n=%d et p=%d", *a, *b);
} }
A l'exécution de , on a:
A l'exécution de , on a:
7) Les macros
Une macro est une petite portion de code qui substitue son code à l'emplacement où elle est mentionnée dans le
programme (où elle est appelée); contrairement aux fonctions qui une fois appelées, l'on sort du programme appelant
pour leur exécution et l'on y retourne seulement à la fin de l'exécution.
L'exécution d'une macro fonctionne plus rapidement que celle d'une fonction.
Une macro est mise en œuvre dans la partie déclarative du programme principale.
Syntaxe: #define nom_macro(arguement) code de la macro (* pas de ; à la fin *)
Exemple1
#include <stdio.h>
#include <conio.h>
#define max(a,b) ( (a>b) ? a : b) // Définition de la macro max
int n=10, e, f, g;
void main( )
{ printf("\nEntrez 2 valeurs");
scanf("%d%d", &e, &f);
g=max(e, f); // Appel de la macro max
printf("\nLe maximum est: %d", g);
getch();
}
Ainsi à l'appel de la macro max, l'ordinateur va remplacer la ligne par g=( (e> f )? e: f)
Exemple2
#include <stdio.h>
#include <conio.h>
#define permut(a, b, t) ( t=a, a=b, b=t) // Pas de point virgule entre les expressions
int e, f, t;
void main( )
{ printf("\nEntrez 2 valeurs");
scanf("%d%d", &e, &f);
printf("\nLa valeur de e avant permutation est: %d", e);
printf("\nLa valeur de f avant permutation est: %d", f);
permut(e, f, t); // Appel de la macro permute
printf("\nLa valeur de e après permutation est: %d", e);
printf("\nLa valeur de f après permutation est: %d", f);
getch();
}
Ainsi à l'appel de la macro permut, l'ordinateur va remplacer la ligne par t=e, e=f, f=t (Il s'agit de 3 affectations).
void main( )
{ float nb;
char* nom
printf("Avant appel n=%d et p=%d", n, p);
echange(n, p);
printf("Après appel n=%d et p=%d", n, p);
……………………………………
……………………………………
getch();
}
void echange (int a, nt b)
{ int c;
printf("Début échange n=%d et p=%d", a, b);
c=a;
a=b;
b=c;
printf("Fin échange n=%d et p=%d", a, b);
}
Les variables n et p sont des variables globales. Elles peuvent par conséquent être utilisées partout dans le
programme y compris à l'intérieur des fonctions.
Les variables nb et nom ne sont utilisables seulement qu'à l'intérieur de la fonction principale main().
La variable c n'est utilisable seulement qu'à l'intérieur de la fonction echange et nulle part ailleurs.
9) La recursivité
Dans une fonction recursive, il faut toujours mentionner la condition d'arrêt, auquel cas l'exécution du programme ne va
jamais s'arrêter.
Exemple: Proposer un programme permettant de déterminer le factoriel d'un entier mais en utilisant une fonction
recursive.
#include <stdio.h>
#include <conio.h>
int n;
float res;
float factoriel(int a)
{ float fact;
if ((a == 0) || (a==1)) // Condition d'arrêt
{ fact =1;
}
else
{ fact = a*factoriel(a -1); // L'expression de la récursivité
}
return(fact);
}
void main()
{ printf("Entrez l'entier dont on voudrait calculer le factoriel \n");
scanf("%d", &n);
res = factoriel(n);
printf("Le factoriel de %d est: %f ", n, res);
getch();
1) Les tableaux
Un tableau est une variable pouvant contenir plusieurs à la fois, de même type.
a) Les tableaux à une dimension
Déclaration: Syntaxe: type_éléments nom_tableau[nombre d'éléments];
Exemple: int tab[5]; Ainsi nous venons de déclarer un tableau de 5 cases et chaque case va contenir un entier. Les
numéros des différentes cases du tableau débute par 0 (zéro) en C. Dans cet exemple, nous irons de l'indice 0 à l'indice
4.
Remarque: tab[3] tout simplement, indique l'élément se trouvant dans la case d'indice 3 c'est-à-dire le 4e élément du
tableau tab.
Note: Un tableau peut contenir un type quelconque: entier, réel, caractère, chaîne de caractère, pointeurs, tableaux,
enregistrement.
Ecriture des éléments dans un tableau à une dimension
Syntaxe: scanf("format", &nom_tableau[indice]); ou nom_tableau[indice]= valeur;
Lecture des éléments d'un tableau à une dimension: printf("format", nom_tableau[indice]); ou nom_variable =
nom_tableau[indice];
Exemple:
#include <stdio.h>
#include <conio.h>
int i, tab[5];
void main( )
{
for(i=0; i<=4; i++)
{ printf("Entrez la valeur n°%d\n", i+1);
scanf("%d", &tab[i]); // Ecriture des éléments dans le tableau
}
printf("Les valeurs du tableau sont:\n");
for(i=0; i<=4; i++)
{
printf("%d\n", tab[i]); // Lecture des éléments du tableau
}
getch( );
}
b) Les tableaux à deux (2) dimensions
Déclaration: Syntaxe: type-éléments nom_tableau[nombre de lignes][nombre de colonnes];
Exemple: float tab[5][8]; Ainsi nous venons de déclarer un tableau de 5 lignes et 8 colonnes (soit 5*8=40 cases) et
chaque case va contenir un réel
Remarque: tab[3][2] tout simplement, indique l'élément se trouvant dans la case qui est à l'intersection de la ligne n°3
et la colonne n°2.
Ecriture des éléments dans un tableau à deux (2) dimensions
Syntaxe: scanf("format", &nom_tableau[n°linge][n°colonne]); ou nom_tableau[n°ligne][n°colonne]= valeur;
Lecture des éléments d'un tableau à deux (2) dimensions: printf("format", nom_tableau[n°ligne][n°colonne]); ou
nom_variable = nom_tableau[n°ligne][n°colonne];
Note: Le remplissage d'un tableau à deux(2) dimensions se fait ligne par ligne.
Exemple:
#include <stdio.h>
#include <conio.h>
int i, k=0, j;
float t[3][4];
void main( )
{ // REMPLISSAGE DU TABLEAU A DEUX DIMENSIONS
for(i=0; i<=2; i++) // Parcours des lignes
{ for(j=0; j<=3; j++) // Parcours des colonnes
{ printf("Entrez la valeur n°%d\n", k+1);
scanf("%f", &t[i][ j]);
k++;
}
}
// LECTURE DES ELEMENTS DU TABLEAU A DEUX DIMENSIONS
printf("Les valeurs du tableau sont:\n");
for(i=0; i<=2; i++) // Parcours des lignes
{ for(j=0; j<=3; j++) // Parcours des colonnes
{ printf("%f\n", t[i][ j]);
}
}
getch( );
}
strcpy (STRings CoPY): Permet de copier une chaîne dans une autre. Syntaxe: strcpy(chaîne1, chaîne2);
Fonctionnement: Cette fonction recopie toute la chaîne2 dans la chaîne1
Exemple: Un programme qui permet d'utiliser 2 variables pour gérer 3 valeurs de type chaîne
#include <stdio.h>
#include <conio.h>
#include <string.h>
void main( )
{ char nom[20];
char nom_p[60];
printf(" Entrez le nom\n");
gets(nom);
strcpy(nom_p, nom); // Copie du contenu de nom dans nom_p
printf("\n Entrez le prénom\n");
gets(nom);
printf("\nLe nom et prénom saisi est:%s %s", nom_p, nom); / * Mettre un espace entre les 2 %s, afin d'avoir une
getch(); séparation lors de l'affichage de la valeur du nom et celle de prénom */
}
strncpy : Analogue à STRCPY, mais qui permet grâce à un paramètre supplémentaire, de limiter le nombre de
caractères copiés.
Syntaxe: strncpy(chaîne1, chaîne2, n) // permet de copier les n 1er caractères de chaîne2, dans chaîne1.
Exemple1:
#include <conio.h>
#include <string.h>
int e;
void main( )
{ char nom[20];
char nom_p[60];
printf(" Entrez le nom\n");
gets(nom);
printf("Le nom saisi est: %s", nom);
strncpy(nom_p, nom, 5); // Permet de copier les 5 1er caractères de nom, dans nom_p
printf("\n Le contenu de la copie est:%s", nom_p);
printf("\n Entrez le prénom\n");
gets(nom);
printf("Le prénom saisi est: %s", nom);
printf("\nLe nom et prénom saisi est:%s%s", nom_p, nom);
getch();
}
A l'exécution, on a:
strlen (STRing LENgth): Permet de renvoyer la longueur d'une chaîne. Syntaxe: strlen(chaîne);
#include <stdio.h>
#include <conio.h>
#include <string.h>
int e;
void main( )
{ char nom[20];
printf(" Entrez le nom\n");
gets(nom);
printf("Le nom saisi est: %s et sa longueur est %d", nom, strlen(nom));
getch();
}
strcat (STRings conCATenation): Cette fonction permet de fabriquer une chaîne en mettant bout à bout 2 autres
chaînes. Par exemple, le résultat de la concaténation de "mon" et de "sieur" serait "monsieur".
Syntaxe: strcat(chaîne1, chaîne2); Permet de copier tout le contenu de la chaîne2 à la fin de la chaîne1. Ainsi donc la
chaîne1 va contenir le résultat de la concaténation.
Exemple:
#include <stdio.h>
#include <conio.h>
#include <string.h>
int e;
void main( )
{ char nom[50];
char nom_p[60];
printf(" Entrez le nom\n");
gets(nom);
printf("\n Entrez le prénom\n");
gets(nom_p);
strcat(nom, nom_p);
printf("\nLe nom et prénom saisi est:%s", nom);
getch();
}
Tel que c'est, à l'affichage, le nom et le prénom seront collés. Pour les séparer, il faudra mettre un espace entre eux,
comme ci:
#include <stdio.h>
#include <conio.h>
#include <string.h>
int e;
void main( )
{ char nom[50];
char nom_p[60];
printf(" Entrez le nom\n");
gets(nom);
strcat(nom, " "); // Permet de séparer le nom du prénom lors de l'affichage.
printf("\n Entrez le prénom\n");
gets(nom_p);
strcat(nom, nom_p);
printf("\nLe nom et prénom saisi est:%s", nom);
getch();
}
strncat: Analogue à strcat mais ici l'on a la possibilité de limiter le nombre de caractères à concaténer.
Syntaxe: strncat(chaîne1, chaîne2, n); Permet de copier les n 1er caractères de la chaîne2 à la fin de la chaîne1.
Exemple:
#include <stdio.h>
#include <conio.h>
#include <string.h>
int e;
void main( )
{ char nom[50];
char nom_p[60];
printf(" Entrez le nom\n");
gets(nom);
strcat(nom, " "); // Permet de séparer le nom du prénom lors de l'affichage.
printf("\n Entrez le prénom\n");
gets(nom_p);
strncat(nom, nom_p, 8); //Permet de concaténer les 8 1er caractères de nom_p, à la fin de nom.
printf("\nLe nom et prénom saisi est:%s", nom);
getch();
}
Remarques importantes:
Pour comparer 2 tableaux de caratères, il ne faut utiliser == , mais plutôt la fonction strcmp ou strcmpi.
Exemple: char nom[20];
printf("Entrez le nom");
gets(nom);
if (nom == "YAO")…..Interdit! Mais plutôt if ( !strcmp(nom, "YAO") );
Pour affecter une constante de type chaîne de caractères à un tableau de caractères, il ne faut pas utiliser = mais plutôt la
fonction strcpy.
Exemple: char P[15];
…………………….
P = "NTIC"; Interdit! Mais plutôt strcpy(P, "NTIC");
Pour affecter une constante de type chaîne de caractères à un tableau de caractères, il ne faut pas utiliser = mais plutôt la
fonction strcpy Pour les comparaisons, il faut le faire, les tableaux de caractères entre eux et les pointeurs de chaînes entre
eux. Mais ne jamis comparer un tableau de caractères et un pointeur vers une chaîne; auquel cas le résultat sera decevant.
Exemple: char *s; char t[20];
.........................................
If ( s == t) ......Interdit!
3) Le type énuméré
Le mot clé utilisé est enum. Syntaxe: enum nom_type_énuméré {identificateur1, identifcateur2,…,identifcateur n};
Exemple: enum jours {lundi, mardi, mercredi, jeudi, vendredi, samedi, dimanche};
enum jour jr; // Déclaration de la variable jr de type jour
e) Tableaux de struct
Il est possible de definir des tableaus d'enregistrements.
Exemple:
struct point
{ char nom;
int x;
int y;
};
struct point courbe[25];
Ainsi courbe[i].nom représente le nom de la case de rang i du tableau courbe. ( [Link][i] n'a aucun sens car nom
n'est pas un tableau).
courbe[4] représente tout l'enregistrement logé dans la case n°4 du tableau courbe.
A l'exécution, on a:
Vous remarquez bien qu'après avoir sorti de la fonction, le champ mention a perdu la valeur qui lui avait été attribuée
dans la fonction attrib_mention. C'est normal! Car ici nous sommes en transmission de paramètre par valeur.
5) Le type Union
Il est noté union. Il est identique au type enregistrement mais à la seule différence que ses différents éléments
partagent tous une même et unique zone mémoire et dont la capacité de celle-ci est celle occupée par le type occupant
le plus d'espace mémoire. Le type union permet d'optimiser l'occupation de l'espace mémoire.
Syntaxe: union etiquette
{ char couleur;
Int taille;
};
union etiquette chemise; // Ici la variable chemise a une taille de 2 octets.
Ainsi [Link] = 'B';
[Link] = 2; // Et le 2 écrase le 'B'.
Autre fonction: flushall(): Elle permet de vider tous les tampons associés aux flux ouverts, afin de permettre une
meilleur lecture et écriture dans les fichiers.
fopen:
Renvoie un pointeur sur le flux ouvert en cas de succès,
Renvoie NULL en cas d'échec
fwrite
Renvoie le nombre d'objets écrits (et non le nombre d'octets écrits) en cas de succès,
Renvoie une faible valeur (ou même 0) en cas d'échec
fread
Renvoie le nombre d'objets lus (et non le nombre d'octets lus) en cas de succès,
Renvoie une valeur < n (donc <1 généralement) en cas d'échec..
pointeurs car une écriture hors des limites de l'allocation de mémoire est très vite arrivée. Ce genre d'écriture provoque
généralement un plantage du programme.
4 L'opérateur &
L'opérateur adresse & retourne l'adresse d'une variable en mémoire.
Exemple: int i = 8;
printf("VOICI i: %d\n", i);
printf("VOICI SON ADRESSE EN HEXADECIMAL: %p\n", &i);
On remarque que le format d'une adresse est %x (hexadécimal) ou %d (décimal) dans printf.
Exercice V_1: Exécuter l’exemple précédent, et indiquer les cases-mémoire occupées par la variable i. (corrigé un peu
plus loin).
C STANDARD
int *pi;
char *pc;
*pi = 0;
*pc = 0x0a;
pi 00
00
pi+1 00
00
pc 0a
pc+1
PLAN MEMOIRE
Remarque: *pc = 0x0A; // La case pointée par pc reçoit A en hexadécimal, d'où le 0x.
Exemples: (1 entier occupe 2 octets, 1 réel, 4octets et 1 caractère, 1 octet)
*pi = 421; /* 421 est le contenu de la case mémoire pointée par pi et de celle qui suit; car 1 entier occupe 2 octets */
*(pi+1) = 53; /* On range 53 dans les 3e et 4e cases à partir de la case pointée par pi */
*(pi+2) = 0xabcd; /* On range 0xabcd dans les 5e et 6e cases à patir de celle pointée par pi */
*pr = 45.7; /* 45,7 est rangé dans la case mémoire pointée par pr et dans les 3 autres qui suivent celle pointée par pr */
pr++; /* Incrémente la valeur du pointeur pr de 4. Désormais pr pointe sur la 5e case à partir de la case mémoire pointée auparavant */
printf("L'ADRESSE pr VAUT: %p\n",pr); /* Affichage de la valeur de l'adresse contenue dans le pointeur pr */
*pc = 'j'; /* Mettre la lettre J dans la case mémoire pointée par le pointeur pc */
pc--; /* Décrémente la valeur du pointeur pc d'une valeur. Donc désormais, pc va pointer sur la case mémoire qui précède celle qu'elle pointait*/
7 Allocation dynamique
Lorsque l'on déclare une variable char, int, float .... un nombre de cases mémoire bien défini est réservé pour cette
variable. Il n'en est pas de même avec les pointeurs.
Exemple:
char *pc;
*pc = 'a'; /* le code ASCII de a est rangé dans la case mémoire pointée par pc */
*(pc+1) = 'b'; /* le code ASCII de b est rangé une case mémoire plus loin */
*(pc+2) = 'c'; /* le code ASCII de c est rangé une autre case mémoire encore plus loin */
*(pc+3) = 'd'; /* le code ASCII de d est rangé une case mémoire plus loin */
Dans cet exemple, le compilateur a attribué une valeur au pointeur pc, les adresses suivantes sont donc bien définies;
mais le compilateur n'a pas réservé ces places: il pourra très bien les attribuer un peu plus tard à d'autres variables. Le
contenu des cases mémoires pc, pc+1, pc+2, pc+3 sera donc perdu. Ceci peut provoquer un blocage du système sous
WINDOWS.
A retenir: Lorsqu'on déclare un pointeur, il faut par la suite réserver une zone mémoire pour les objets
pointés.
Il existe en langage C, des fonctions permettant d'allouer de la place en mémoire qui sera pointé par un pointeur.
Il faut absolument les utiliser dès que l'on travaille avec les pointeurs. Ce sont: malloc et callloc. Calloc, à la différence
de malloc, initialise la zone mémoire allouée("" pour les chaînes de caractères, '' pour les caractères, 0 pour les entiers
et réels).
__malloc:
Syntaxe1: nom_pointeur = malloc(n); retourne un pointeur de type char* sur une zone de n octets contigus non initialisés.
Ainsi si l'on veut pointer sur un objet différent d'une chaîne de caractère, il va donc falloir faire la conversion de type
(transtypage)
Exemple: char *s; s = malloc(20); // permet de réserver un espace pour contenir 10 caractère, et qui sera pointé par s.
int *p; p = (int*) malloc(25); // permet de réserver un espace pour contenir 25 entiers et qui sera pointé par p. Ici vous
voyez qu'on a fait une conversion de type car p est un pointeur sur un entier et non sur une chaîne de caractère.
Synatxe2: nom_pointeur = malloc(n, sizeof(type)); Permet d'allouer un espace dont la capacité vaut n multiplier par sizeof(type); et qui
sera pointé par p.
Exemple: int *p; p = (int*)malloc(3, sizeof(int)); Permet de réserver un espace dont la capacité vaut 3*2octets, soit 6 octets; et qui sera
pointé par p.
float *t; t = (float*)malloc(sizeof(float)); Permet de réserver un espace dont la capacité vaut 1*4octets, soit 4 octets; et qui
sera pointé par t.
Exercice V_2:
adr1 et adr2 sont des pointeurs pointant sur des réels. Le contenu de adr1 vaut -45,78; le contenu de adr2 vaut 678,89.
Ecrire un programme qui affiche les valeurs de adr1, adr2 et de leur contenu (corrigé un peu plus loin).
On peut cependant être amené à définir par programmation la valeur d'une adresse. On utilise pour cela l'opérateur de
"cast", jeu de deux parenthèses.
- Par exemple pour adresser un périphérique (adressage physique),
Exemples:
char *pc;
pc = (char*)0x1000; /* pc va contenir, l'adresse 0x1000 et pointe sur un caractère */
int *pi;
pi = (int*)0xfffa; /* pi va contenir, 0xfffa et pointe sur un entier */
Lorsqu'on utilise une fonction d'allocation dynamique on ne peut affecter de valeur au pointeur à l'aide de
l'opérateur de cast.
Ces 2 premiers exemples sont à proscrire sous WINDOWS.
Exercice V_3:
pi est un pointeur sur un entier; pi vaut 0x5000 et le contenu de la cellule qu'il pointe vaut 300. Ecrire le programme
correspondant (programme dangereux sous WONDOWS car l'exécution de ce programme peut écraser des doonées du
système se trouvant à l'adresse mémoire 0x5000 (corrigé un peu plus loin).
L'opérateur de "cast", permet d'autre part, à des pointeurs de types différent de pointer sur la même adresse.
*adr2 = 678.89;
printf("adr1 = %p adr2 = %p r1 = %f r2 = %f\n", adr1, adr2, *adr1, *adr2);
free(adr1); //Libération de l'espace mémoire pointée par adr1
free(adr2); //Libération de l'espace mémoire pointée par adr2
printf("\nPOUR CONTINUER FRAPPER UNE TOUCHE ");
getch();
}
Exercice V_3:
#include <stdio.h>
#include <conio.h>
#include <alloc.h>
void main()
{
int *i;
i = (int*)malloc(4);
*i = 300;
printf(" adresse = %p variable = %d\n", i, *i);
free(i); //Libération de l'espace mémoire pointée par i
printf("\nPOUR CONTINUER FRAPPER UNE TOUCHE ");
getch();
}
Exercice V_4:
#include <stdio.h>
#include <conio.h>
#include <alloc.h>
void main()
{
char *adr_c;
int *adr_i, i=0x12345678; // Pour dire que 12345678 est écrite en hexadécimal
adr_i = &i;
adr_c = (char*)adr_i;
printf("ADRESSE: %p CONTENU: %c\n", adr_c, *adr_c);
printf("ADRESSE: %p CONTENU: %c\n", adr_c+1 ,*(adr_c+1));
printf("ADRESSE: %p CONTENU: %c\n", adr_c+2, *(adr_c+2));
printf("ADRESSE: %p CONTENU: %c\n", adr_c+3, *(adr_c+3));
getch();
}
L'analyse de l'exécution en BORLAND C++, montre que les microprocesseurs INTEL rangent en mémoire d'abord les
poids faibles d'une variable.
Exercice V_5:
#include <stdio.h>
#include <conio.h>
#include <alloc.h>
void main()
{
char *adr_deb,c;
int i,imax,compt_e = 0,compt_sp = 0;
adr_deb = (char*)malloc(30); /* texte d'au plus 30 caracteres */
/* saisie et rangement du texte */
printf("\nADRESSE DU TEXTE: %p (ATTRIBUEE PAR LE COMPILATEUR)", adr_deb);
printf("\nENTRER UN TEXTE: ");
for (i=0; ((c=getchar())!='\n'); i++) *(adr_deb + i) = c;
imax = i; /* borne superieure */
/* lecture de la memoire et tri */
for (i=0; i<imax; i++)
{
c = *(adr_deb+i);
EXERCICE 2
Modifier l’algorithme précédent afin que vous puissiez calculer la somme de trois (3) nombres entiers, en afficher le
résultat et cela autant de fois que vous voudrez.
#include <stdio.h>
#include <conio.h>
void main()
{ int a, b, c;
float som;
char rep;
char *s=""; // Initialisation de s
do
{ printf("Entrez les trois entiers\n");
scanf("%d%d%d", &a, &b, &c);
gets(s); // Permet de vider le tampon
som = a + b + c;
printf("La somme des trois entiers est: %f\n", som);
printf("Voulez-vous continuer? O pour OUI et N pour NON\n");
scanf("%c", &rep);
}
while( (rep != 'n') && (rep!='N') );
getch();
}
EXERCICE 3
Concevoir un algorithme permettant d'afficher les diviseurs d'un nombre entier.
#include <stdio.h>
#include <conio.h>
void main()
{ int r, N, i;
printf("Enrez l'entier");
scanf("%d", &N);
if (N == 0) // Ca s particulier
{ printf(" Il existe une infinité de diviseurs");
}
else // C'est à dire N != 0. Là, nous sommes maintenant dans le cas général maintenant
{ if (N > 0) // Cas où N est positif
{ for (i =1; i<=N; i=i+1)
{ r=N % i;
if (r==0)
{ printf("%d est un diviseur de %d\n", i, N);
}
}
}
else // Cas où N est négatif
{ for (i=1; i <= -N; i=i+1)
{ r= N % i;
if (r==0)
{ printf("%d est un diviseur de %d\n", -i, N);
}
}
}
}
getch();
}
EXERCICE 4
Proposer un algorithme qui à partir d'un réel noté x et d'une valeur entière appelée n, retourne x à la puissance n.
#include <stdio.h>
#include <conio.h>
void main()
{ int X, n, j;
float puiss;
printf("Entrez la valeur de X et de n \n");
scanf("%d%d", &X, &n);
// Gestion des cas particuliers
if ((X==0) && (n==0))
{ printf("OPERATION IMPOSSIBLE\n");
}
else // Gestion du cas où le résultat existe cad x!=0 et/ou n!=0
{ if ((X==0) && (n!=0)) // Cas particulier
{ puiss = 0;
}
if (( X!=0) && (n==0)) // Cas particulier
{ puiss = 1;
}
// Gestion à présent du cas général
if (( X!=0) && (n!=0)) // Cas particulier
{ if (n > 0 ) // Cas où l'exposant est positf
{ puiss = 1;
for (j=1; j <= n; ++j)
{ puiss = puiss*X;
}
}
else // Cas où l'exposant est négatif
{ puiss = 1;
for (j=1; j<= -n; ++j)
{ puiss = puiss*X;
}
puiss = 1 / puiss;
}
}
printf("%d à la puissance %d est %f", X, n, puiss);
}
getch();
}
EXERCICE 5
Une compagnie de chemin de fer pratique ses tarifs en fonction de la catégorie du voyageur:
Voyageur normal (N): plein tarif
Abonné de la compagnie (A): 40% de réduction
Enfant de moins de 10 ans (E): gratuit
Employé de la compagnie (T): gratuit
Parent d'un employé (P): 50% de réduction
Personne âgée de 70 ans et plus (V): 30% de réduction.
Ecrire un algorithme qui permet, connaissant le tarif normal du voyage, de calculer le prix à payer par un voyageur
donné.
#include <stdio.h>
#include <conio.h>
void main()
{ float tarif_N, tarif_Ap;
char* s=""; // C'est dans s que nous allons vider le tampon
char cat;
printf("Donnez le tarif normal\n");
scanf("%f", &tarif_N);
EXERCICE 6
Le responsable d'un supermarché de la place vous sollicite pour l'aider à mettre en place un programme informatique qui
devra fonctionner comme suit: Lorsqu'un client se présente à la caisse, l'on saisit d'abord le nombre d'exemplaires et le
prix unitaire de chaque catégorie d'article et ce, pour toutes les catégories d'articles présents dans son panier. Ensuite la
somme versée. Après quoi, le programme devra afficher le montant total de toutes les catégories d'articles et le montant
de la monnaie.
Le programme devra gérer tous les clients de la journée et à la fermeture du magasin, afficher le montant de tous les
achats effectués pendant la journée.
Exemple de simulation
Nombre d’article 1: 5
Prix unitaire article 1 : 500
Nombre d’article 2: 3
Prix unitaire article 2 1000
Nombre d’article 3: 1
Prix unitaire article 3 850
TOTAL : 6350
Versé : 10 000
Rendu : 3650
TOTAL journée :
#include <stdio.h>
#include <conio.h>
void main()
{ int nbc, nba, i;
float pu, prix, total, totalJ, vers, mon;
char rep;
char* d = "";
totalJ = 0;
do
{ total = 0;
printf("Donnez le nombre de catégories d'articles ");
scanf("%d", &nbc);
for (i=1; i<=nbc; ++i)
{ printf("Entrez le nombre d'articles de la catégorie n° %d\n ", i);
scanf("%d", &nba);
printf("Entrez le prix unitaire de la catégorie d'article n° %d \n", i);
scanf("%f", &pu);
prix=nba*pu;
total = total + prix;
}
printf("Le total des achats du client est: %f\n" , total);
printf("Entrez la somme versée par le client\n ");
scanf("%f", &vers);
mon = vers - total;
printf("La monnaie à rendre est: %f \n" , mon);
totalJ = totalJ + total;
printf("Un autre client? O pour OUI et N pour NON\n ");
gets(d); // Permet de vider le tampon
scanf("%c", &rep);
}
while((rep !='N') && (rep !='n'));
printf("Le total de la journée est: %f " , totalJ);
getch();
}
EXERCICE 7
Dans le cadre de la répartition du budget de l'année alloué à son ministère, M. le Ministre de l'enseignement supérieur
fait le partage comme suit:
Service de l'orientation: 10% du budget global,
Service des examens et concours: le 1/3 du budget restant,
Service d'évaluation des établissements scolaires: les ¾ du budget alloué au service des examens et
concours,
Service du mobilier et de l'immobilier: le reste du budget.
Etant donné le budget alloué audit ministère, concevoir un algorithme permettant à M. le Ministre de faire sa répartition.
#include <stdio.h>
#include <conio.h>
void calcul_budget (float p) // Début de la fonction calcul_budget.Pas de ; à la fin
{ float r, bud_sec, bud_se, bud_smi, bud_so;
bud_so = p * 10/100;
r= p - bud_so;
bud_sec = r*1/3;
bud_se = bud_sec *3/4;
bud_smi = p - (bud_so + bud_sec + bud_se);
printf("Le budget alloué au service de l'orientation est: %f\n" , bud_so);
printf("Le budget alloué au service des examens et concours est: %f\n" , bud_sec);
printf("Le budget alloué au service d'évaluation est: %f\n" , bud_se);
printf("Le budget alloué au service du mobilier et de l'immobilier est: %f" , bud_smi);
} // Fin de la fonction calcul_budget
EXERCICE 8
#include <stdio.h>
#include <conio.h>
float somme (float x, float y, float z) // Ici bien que x, y et z soit du même type, il faut néanmoins mentionner float pour chacun
{ float p;
p = x + y + z;
return (p);
} // Fin du corps de la fonction somme
float moyenne (float q, float v, float n) // Ici bien que x, y et z soit du même type, il faut néanmoins mentionner float pour chacun
{ float k;
k = (q + v + n)/3;
return (k);
} // Fin du corps de la fonction moyennne
float produit (float i, float j, float k) // Ici bien que x, y et z soit du même type, il faut néanmoins mentionner float pour chacun
{ float e;
e= i*j*k;
return (e);
} // Fin du corps de la fonction produit
void main() // Début du corps du programme principal
{ float a, b, c, op; // a, b, c pour les 3 réels et op= résultat de l'opération
int choix; // choix pour le choix de l'opération
printf("Entrez 1 pour effectuer la somme des trois nombres") ;
printf("Entrez 2 pour effectuer le produit des trois nombres") ;
printf("Entrez 3 pour effectuer la moyenne des trois nombres") ;
do
{ printf("Faites votre choix") ;
scanf("%d", &choix) ;
}
while( (choix != 1) && (choix != 2) && (choix != 3 )) ;
printf("Entrez les trois nombres réels") ;
scanf("%f%f%f", &a, &b, &c) ;
if ( choix == 1)
{
op = somme(a, b, c); // Appel de la fonction somme
}
if (choix ==2)
{
op = produit(a, b, c); // Appel de la fonction produit
}
if (choix == 3)
{
op = moyenne(a, b, c); // Appel de la fonction moyenne
}
printf("Le résultat de l'opération est: %f", op);
getch();
} // Fin du programme principal
EXERCICE 9
Concevoir un algorithme permettant de calculer et d'afficher année par année, le montant du capital et des intérêts
acquis pour une somme S francs, placée à T% pendant N années.
#include <stdio.h>
#include <conio.h>
void calcul_cap_int (float a, float b, int c)
{ int I;
float interet;
for(I=1; I<=c; ++I)
{ interet = a * b/100;
a = a + interet;
printf("Le montant des intérêts à la fin de l'année n° %d est: %f\n" , I, interet);
printf("Le montant du capital à la fin de l'année n° %d est: %f\n" ,I, a);
}
} // Fin du corps de la fonction *)
void main() // Début du corps du programme principal
{ float S, T; // S= Somme initiale placée, T=taux d'intérêt
int N;
printf("Entrez le capital initial ");
scanf("%f", &S);
printf("Entrez le taux d'intérêt en % ");
scanf("%f", &T);
printf("Entrez le nombre d'année de placement ");
scanf("%d", &N);
calcul_cap_int(S, T, N); // Appel de lafonction calcul_cap_int
getch();
} // Fin du corps du programme principal
EXERCICE 10
Le professeur principal d'une classe de 25 étudiants vous sollicite pour mettre en place un programme informatique lui
permettant de calculer les moyennes de ses étudiants. Les matières à considérer et leurs différents coefficients sont:
Informatique: coefficient 4, mathématiques: coefficient 3 et l'anglais: coefficient 2.
Pour chaque matière, l'on dispose de deux (2) notes avec des coefficients différents: note de test lourd: coefficient 5 et
note de devoir: coefficient 3.
Le professeur principal voudrait savoir:
La moyenne de classe de chaque étudiant,
Le premier dans chaque matière,
Le premier de la classe,
La moyenne générale de la classe.
Proposer un algorithme lui permettant d'assouvir son besoin.
Note: Les étudiants seront identifiés par des numéros (par exemple n°1, n°2,…).
#include <stdio.h>
#include <conio.h>
float moy, moy_max, som, moy_gle, moy_mat, moy_max_mat, moy_info, moy_max_info, moy_A, moy_max_A,
noteTL, noteD; // Variables globales utilisabes partout dans le programme
int I, j, k, l, m; // Variables globales utilisabes partout dans le programme
scanf("%f", ¬eD);
moy_mat = (noteTL*5 + noteD*3)/8;
printf("Entrez la note de test lourd d'anglais \n");
scanf("%f", ¬eTL);
printf("Entrez la note de devoir d'anglais \n");
scanf("%f", ¬eD);
moy_A = (noteTL*5 + noteD*3)/8;
} // Fin du corps de la fonction calcul_moyenne_matieres
void moyenne_max_info() // Début du corps de la fonction moyenne_max_info
{ if (moy_info > moy_max_info)
{ moy_max_info = moy_info;
j = I;
}
} // Fin du corps de la fonction moyenne_max_info
void moyenne_max_mat() // Début du corps de la fonction moyenne_max_mat
{ if (moy_mat > moy_max_mat)
{ moy_max_mat = moy_mat;
k = I;
}
} // Fin du corps de la fonction moyenne_max_mat
void moyenne_max_A () // Début du corps de la fonction moyenne_max_A
{ if (moy_A > moy_max_A)
{ moy_max_A = moy_A;
l = I;
}
} // Fin du corps de la fonction moyenne_max_A
void moyenne_max_classe () // Début du corps de la fonction moyenne_max_classe
{ if (moy > moy_max)
{ moy_max = moy;
m = I;
}
} // Fin du corps de la fonction moy enne_max_classe
void calcul_moyenne_classe(float a, float b, float c) // Début du corps de la fonction calcul_moyenne_classe *)
{ moy = (a*4 + b*3 + c*2)/9;
printf("La moyenne de l'étudiant n° %dest: %f \n", I, moy);
} // Fin du corps de la fonction calcul_moyenne_classe
void main() // Début du corps du programme principal
{ som = 0; moy_max_mat = 0; moy_max_info = 0; moy_max_A = 0; moy_max = 0;
for (I=1; I<=25; ++I)
{
calcul_moyenne_matieres(); // Pour le calcul des moyennes dans les matières
moyenne_max_info(); // Pour déterminer la moyenne maximale en informatique
moyenne_max_mat(); // Pour déterminer la moyenne maximale en mathématiques
moyenne_max_A(); // Pour déterminer a moyenne maximale en anglais
calcul_moyenne_classe(moy_info, moy_mat, moy_A); // Pour le calcul de la moyenne de classe de l'étudiant
moyenne_max_classe(); // Appel de la fonction moyenne_max_classe pour déterminer le 1er de la classe
som = som + moy;
}
moy_gle = som/25;
printf("Le 1er en informatique est l'étudiant n° %d et il a obtenu %f \n", j, moy_max_info);
printf("Le 1er en mathématique est l'étudiant n° %d et il a obtenu %f \n", k , moy_max_mat);
printf("Le 1er en anglais est l'étudiant n° %d et il a obtenu %f \n", l , moy_max_A);
printf("Le 1er de classe est l'étudiant n° %d et il a obtenu %f \n", m, moy_max);
printf("La moyenne générale de la classe est: %f" , moy_gle);
getch();
} // Fin du corps du programme principal
EXERCICE 11
Concevoir un algorithme qui prend en entrée dix (10) réels et qui les retourne triés par ordre croissant.
#include <stdio.h>
#include <conio.h>
float T[10]; // Le tableau va servir à contenir les 10 réels. C'est une variable globale
void saisie_nombres () // Début du corps de la fonction saisie_nombres
{ int i;
for(i=0; i<=9; ++i) // En C, les indices de tableau débute toujours par 0
{ printf("Entrez le réel n° %d \n" , i);
scanf("%f", &T[i]);
}
} // Fin du corps de la fonction saisie_nombres
EXERCICE 12
Concevoir un algorithme permettant à un utilisateur de saisir une phrase terminée par un point et de:
Remplacer une lettre par une autre,
Compter et éditer le nombre de mots que compte cette phrase.
Remarque:
Cette phrase ne comportera que des virgules et un point comme ponctuation.
L'utilisateur saisira la lettre à remplacer et la lettre remplaçante
#include <stdio.h>
#include <conio.h>
#include <string.h> // Pour pouvoir utiliser la fonction strlen
char Tab[3]={' ', '.', ','}; //ENSEMBLE de CARACTERE
char phrase[80]; // Phrase à saisir
char lettre_R, lettre_AR, C; // lettre_R=lettre remplaçante, lettre_AR=lettre à remplacer
int d; // Va nous servir de booléen, pour tester si l'exactitude de la phrase saisie
char* s=""; // pour pouvoir vider le tampon
void saisie_donnees()
{
do
{ printf("Entrez la phrase \n");
gets(phrase); // Car la phrase va contenir des espaces entre les mots
printf("Entrez la lettre remplaçante \n");
scanf("%c", &lettre_R);
gets(s); // Vide le tampon
printf("Entrez la lettre à remplacer \n");
scanf("%c", &lettre_AR);
}
while (phrase== ""); // Jusqu'à ce que l'utilisateur saisisse quelque chose
printf("La phrase saisie est: %s \n", phrase);
}
int verifier_phrase( char* m) // Vérifie si la phrase saisie est correcte ou pas
{ int e, npt;
npt = 0; // Compte le nombre de point dans la phrase
e = 0; // e=0 car les indices des chaîines débutent par 0, tout comme ceux des tableaux
while ( (e <= strlen(m)-1) && (npt <= 1) )
{ if (m[e] == '.') // Pour savoir s'il y a plus d'1 point dans la phrase
{ npt = npt + 1;
if (e+2 <= strlen(m)) // La phrase continue après le point
{ npt = 2; // En tout cas donner à npt, une valeur >1 afin de sortir de la TQ…FAIRE
}
}
e = e +1;
}
if ( (npt >1) || (npt == 0) ) // n>1=Il y a plus d'1 point dans la phrase et n= 0, pas de point
{
return(0); // Pour dire que ce qui a été saisi n'est pas une phrase correcte. Lui donner la valeur 0
}
else
{
return (1); // Pour dire que ce qui a été saisi est une phrase correcte. Lui attribuer une valeur diffétente de 0
}
} // Fin de la fonction verifier_phrase
void compte_mots() // Début de la fonction compte_mots
{ int nbre_mot, i, j, k; // i pour parcourir la phrase, nbre_mot= nombre de mot
nbre_mot = 0;
for (i=0; i<= strlen(phrase)-1; ++i)
{ C = phrase[i]; k=0;
for (j=0; j<=2;++j) // Pour savoir si la lettre rencontrée est une ponctuation
{ if ( C == Tab[j])
{ k = 1; // k est le témoin
}
}
if (k ==1)
{
if ((phrase[i-1] != ' ') && (phrase[i-1] != ',') )
{
nbre_mot = nbre_mot + 1;
}
}
}
printf("Le nombre de mots contenu dans la phrase est: %d \n" , nbre_mot);
} // Fin de la fonction compte_mots
ver = 0;
for (i=0; i<=strlen(phrase)-1; ++i)
{ if (phrase[i] == lettre_AR)
{ phrase[i] = lettre_R;
ver = 1;
}
}
if (ver ==0)
{
printf("La lettre à remplacer n'existe pas dans la phrase saisie \n");
}
else
{
printf("La nouvelle phrase obtenue est: %s \n" , phrase);
}
} // Fin de la fonction remplacement_lettre
void main() // Début du corps du programme principal
{
saisie_donnees(); // Appel de la fonction saisie_donnees
d = verifier_phrase(phrase); // Appel de la fonction verifier_phrase
if (d ==0)
{
printf("Vous n'avez pas saisi une phrase correcte");
}
else
{
compte_mots(); // Appel de la fonction compte_mots
remplacement_lettre(); // Appel de la fonction remplacement_lettre
}
getch();
} // Fin du corps du programme principal
EXERCICE 13
Une grande école, dans le cadre du paiement des droits d'examen de ses étudiants en 2e année, a ouvert un guichet
spécialement pour recueillir ces droits d'examen. Les filières au sein de l'établissement sont: IG, NTIC, ELN et TLCOM.
Les effectifs sont:
IG: 25
NTIC: 50
ELN: 30
TLCOM: 45.
La paie des droits d'examen est fixée à une date précise et pendant toute cette journée, le guichet est mis à la
disposition des étudiants.
Chaque étudiant qui paie ses droits, est enregistré par la saisie de son nom, son prénom, sa filière et son matricule.
A la fin de la journée, l'administration voudrait savoir:
Le nombre total des étudiants qui ont payé leur droit,
Le nombre d'étudiant s'ayant acquitté de leur droit d'examen et ceux ne l'ayant pas fait; ceci par filière.
NB: Pour ceux qui ont payé, afficher leur nom, leur prénom, leur matricule et leur filière.
Le nombre total des étudiants qui n'ont pas payé leur droit.
Concevoir un algorithme répondant aux besoins de l'administration.
#include <stdio.h>
#include <conio.h>
#include <string.h> // Pour pouvoir utiliser strcpy et strcmp
struct etudiant // Définition de l'enregistrement etudiant
{ char nom[25];
char prenom[50];
char filiere[15];
char matricule[15];
};
etudiant T[150]; // Définition du tableau d'enregistrement. 150 = nombre total de tous les étudiants
int ntp;
void affichage_info ( char n[]) // Début du corps de la fonction affichage_info
{ int i;
printf("Leur nom, prénom et matricule sont: \n");
for(i=0; i<= ntp; ++i) // Ici ntp et non 150 car il se peut que tout le monde n'ait pas payé
{ if (!strcmp(T[i].filiere, n))
{ printf("%s \n", T[i].nom);
printf("%s \n", T[i].prenom);
printf("%s \n", T[i].matricule);
}
}
} // Début du corps de la fonction affichage_info
Void saisir_info() // Début du corps de la fonction saisir_info
{ int nbIG, nbNTIC, nbELN, nbTLCOM;
char rep;
char C[50];
ntp = -1; // ntp =-0 pr pvoir avoir 0 dans le DO car les indices débutent par 0
nbIG = 0; nbNTIC = 0; nbELN = 0; nbTLCOM = 0;
do
{ ntp = ntp + 1;
printf("Entrez le nom de l'étudiant n° %d \n" , ntp);
gets(T[ntp].nom);
printf("Entrez le prénom de l'étudiant n° %d \n", ntp);
gets(T[ntp].prenom);
printf("Entrez la filière de l'étudiant n° %d \n", ntp);
gets(T[ntp].filiere);
printf("Entrez le matricule de l'étudiant n° %d \n", ntp);
gets(T[ntp].matricule);
if (!strcmp(T[ntp].filiere, "IG" ) )
{ nbIG = nbIG + 1;
}
if (!strcmp(T[ntp].filiere, "NTIC" ))
{
nbNTIC = nbNTIC + 1;
}
if (!strcmp(T[ntp].filiere, "ELN" ) )
{
nbELN = nbELN + 1;
}
if (!strcmp(T[ntp].filiere, "TLCOM" ))
{
nbTLCOM = nbTLCOM + 1;
}
printf("Y a t il un autre étudiant? O pour OUI et N pour NON \n");
scanf("%c", &rep);
gets(C); // Vide le tampon
}
while ( (rep != 'N') && (rep !='n') ) ;
printf("Le nombre total des étudiants s'ayant acquitté de leur droit d'examen est: %d \n", ntp+1); // Car ntp a débuté par 0
printf("Le nombre total des étudiants n'ayant pas payé leur droit d'examen est: %d \n" , 150-(ntp+1) );
printf("Le nbre total des étudiants n'ayant pas payé leur droit en IG est: %d \n" , 25-nbIG);
printf("Le nombre total des étudiants ayant payé leur droit d'examen en IG est: %d \n" , nbIG);
strcpy(C,"IG"); // Pour mettre la valeur "IG" dans C. C'est une affectation. Ne pas faire ça: C = "IG"
affichage_info (C); // Appel de la fonction affichage_info avec pour paramètre C qui vaut "IG"
printf("Le nbre total des étudiants n'ayant pas payé leur droit en NTIC est: %d \n" , 50-nbNTIC);
printf("Le nombre total des étudiants ayant payé leur droit en NTIC est: %d \n" , nbNTIC);
strcpy(C,"NTIC"); // Pour mettre la valeur "IG" dans C. C'est une affectation. Ne pas faire ça: C = "NTIC";
affichage_info (C); // Appel de la fonction affichage_info avec pour paramètre C qui vaut "NTIC"
printf("Le nbre total des étudiants n'ayant pas payé leur droit en ELN est: %d \n" , 30-nbELN);
printf("Le nombre total des étudiants ayant payé leur droit d'examen en ELN est: %d \n" , nbELN);
strcpy(C,"ELN"); // Pour mettre la valeur "IG" dans C. C'est une affectation. Ne pas faire ça: C = "ELN";
affichage_info (C); // Appel de la fonction affichage_info avec pour paramètre C qui vaut "ELN"
printf("Le nbre total des étudiants n'ayant pas payé leur droit en TLCOM est: %d \n" , 45-nbTLCOM);
printf("Le nombre total des étudiants ayant payé leur droit en TLCOM est: %d \n" , nbTLCOM);
strcpy(C,"TLCOM"); // Pour mettre la valeur "IG" dans C. C'est une affectation. Ne pas faire ça: C = "TLCOM";
affichage_info (C); // Appel de la procédure affichage_info avec pour paramètre C qui vaut "TLCOM"
} // Fin du corps de la fonction saisir_info
EXERCICE 14
L’école primaire Notre Dame de Treichville voudrait encourager l’excellence en octroyant des prix aux meilleurs élèves.
Notre Dame de Treichville a six (6) classes et chaque classe comporte trente (30) élèves.
La composition de passage est basée sur cinq (5) matières de coefficient chacune. Le classement est effectué par classe
et l’on affiche le nom, la moyenne,le rang et la mentio de l’élève par ordre de mérite.
Concevoir un algorithme permettant d’effectuer le classement de cette école.
Note: Pour la mention, nous retiendrons ceci:
<10: Médiocre,
[10; 12[: Passable,
[12; 14[: Assez Bien,
[14; 16[: Bien,
[16; 18]: Très bien,
]18; 20]: Excellent.
#include <stdio.h>
#include <conio.h>
#include <string.h> // Pour pouvoir utiliser strcpy et strcmp
struct classe // Définition de l'enregistrement
{ char nom[30]; // Pas char * nom car ds le prog principal, on va l'utiliser avec gets(cl[j].nom). Or gets accepte seulement tableau de
caractères
float moyenne;
int rang;
char* mention;
};
struct classe cl[30]; // Pour gérer les 30 élèves de chaque classe. C'est un tableau de 30 cases et chaque case contient l'enregistrement classe
int i , j;
float calcul_moyenne() // Début du corps de la fonction calcul_moyenne
{ int e, cof, C;
float som, note, k; char s[25];
cof = 0; som = 0;
for(e=1; e<=5; ++e)
{ printf("Entrez la note n° %d \n" , e);
scanf("%f", ¬e);
gets(s);
printf("Entrez le coefficient de la note n° %d \n" , e);
scanf("%c", &C); gets(s);
som = som +(C* note); // Addition des notes coefficientées
cof = cof + C; // Addition des coefficients
}
k = (som / cof); // Calcul de la moyenne et seulement après la saisie des notes et de leurs coefficients
return(k);
} // Fin du corps de la fonction calcul_moyenne
{ printf ("%s est %d e avec %f comme moyenne et %s pour mention \n\n" , cl[l].nom, cl[l].rang,
cl[l].moyenne, cl[l].mention );
}
} // Fin du corps de la fonction afficher_classement
void main() // Début du corps du programme principal
{ for (i=0; i<=5; ++i) // Parcours des 6 classes
{ printf("CLASSE n° %d \n", i);
for ( j= 0; j<=29; ++j) // Parcours des 30 élèves de la classe en cours
{ printf("Entrez le nom de l'élève n° %d \n" , j );
gets(cl[j].nom );
cl[j].moyenne = calcul_moyenne(); // Calcul de la moyenne
attribution_mention(cl[j].moyenne); // Détermination de la mention
trier_tableau(); // Tri du tableau afin d'atttribuer les rang
attribuer_rang(); // attribution du rang
}
afficher_classement(); // Affichage du classement et cela classe après classe.
}
getch();
} // Fin du corps du programme principal
while((choix=='o')||(choix=='O'));
fclose(f);
} // Fin de la fonction crer_fichier
void lire_fichier(FILE *f, char n[])
{ carte fiche;
int compteur=0;
clrscr();
printf("LECTURE DU FICHIER\n\n");
printf("NOM DU FICHIER A LIRE: ");
gets(n);
flushall(); // Permet de vider le tampon de données.
f = fopen(n, "r"); // Ouverture du fichier déjà existant, en lecture uniquement.
if (f == NULL) printf("\nERREUR, CE FICHIER N'EXISTE PAS\n\n");
else // C'est-à-dire que le fichier dont le nom a été saisi existe.
{ printf("\nLISTING DU FICHIER\n\n");
while(fread(&fiche, sizeof(carte), 1, f) != 0) // !0 = Tant qu'on trouve des données à lire dans le fichier
{ printf("fiche n°%d: \n",compteur);
compteur++;
printf("%s %s %d an(s)\n\n",[Link], [Link], [Link]);
}
fclose(f);
}
printf("POUR CONTINUER FRAPPER UNE TOUCHE ");
getch();
} // Fin de la fonction lire_fichier
clrscr();
printf("RECHERCHE DE FICHE\n\n");
printf("NOM DU FICHIER: ");
gets(n);
flushall(); // Permet de vider le tampon de données.
f = fopen(n, "r");
if (f == NULL) printf("\nERREUR, CE FICHIER N'EXISTE PAS\n\n");
else
{ printf("\nFICHE A RETROUVER:\n");
printf("NOM: ");
gets(nn);
printf("PRENOM: "); gets(pp);
flushall();
while((fread(&fiche, sizeof(carte), 1, f) > 1) && (trouve=='0') )
{ if((strcmp([Link], nn)==0 )&& (strcmp([Link], pp)==0))
{ trouve='1';
printf("FICHE RETROUVEE: FICHE n°%2d\ n", compteur);
}
compteur++;
}
if (trouve=='0') printf("CETTE FICHE N'EXISTE PAS\n");
fclose(f);
printf("POUR CONTINUER FRAPPER UNE TOUCHE ");
getch();
} // Fin de la fonction recherche
En effet, le langage C refuse qu'on déclare un type fichier (FILE*) à l'intérieur des fonctions. Raison pour laquelle
nous l'avons déclaré comme variable globale et passé en argument aux ≠ fonctions .Et comme ça, on aura plus à les
déclarer comme variable locale.
Note: La manipulation des pointeurs est souvent capricieuse et même complexe parfois.
Conseil: Ne pas utiliser de fonctions recursives lorsqu'on à affaire aux pointeurs car la gestion devient très complexe(le C réagit bizarement!)
#include <stdio.h>
#include <conio.h>
#include <alloc.h> // Pour pouvoir utiliser la fonction malloc()
#include <string.h> // Pour pouvoir utiliser strcmpi
struct cel
{ char nom[20];
char prenom[40];
char pays[20];
struct cel *suivant;
};
char r;
struct cel * t; // Déclaration d'une variable de type cel (c'est un pointeur sur cel) *)
int I, j, choix;
gets(temp->suivant->prenom);
printf("Entrez le pays \n");
gets(temp->suivant->pays);
temp->suivant->suivant=NULL;
printf("Continuez?");
scanf("%c", &reponse);
gets(s); // Pour vider le tampon
if ((reponse == 'O') ||(reponse== 'o'))
{
temp = temp->suivant;
}
}
while((reponse!='N') && (reponse!='n'));
printf(" \n Le nouveau contenu de la liste est:\n");
afficher_liste(pt);
}
else
{
printf("OPERATION IMPOSSIBLE CAR LA LISTE EST VIDE \n");
}
}
void supprimer_element(struct cel **sp) // Car la valeur de pointeur sur le début de la liste, change ici donc pour conserver
{ //ce changement dès le retour au programme principal, il ft passer le pointeur du pointeur comme argument.
char n[20];
struct cel *temp, *tp;
int k;
if (I == 0)
{
printf("OPERATION IMPOSSIBLE CAR LA LISTE EST VIDE \n");
}
else
{
printf("Entrez le nom à supprimer \n");
gets(n);
tp = *sp;
k = 0;
while((strcmpi(tp->nom, n)!=0) && (tp->suivant != NULL) )
{ temp=tp; // Pour pointer sur la cellule précédente
tp=tp->suivant;
k++;
}
if((strcmpi(tp->nom, n)==0) && (k == 0)) //k=0: C'est que c'est la 1ère cellule qui contient le nom à supprimer
{
if (tp->suivant == NULL) // C'est qu'il y a une seule cellule dans la liste
{ free(tp);
tp=NULL;
sp=NULL;
printf("La liste est désormais vide \n");
I= 0; // pour signifier que la liste est désormais vide
}
else // C'est qu'il y a plusieurs cellules dans la liste
{ *sp= tp->suivant; // La valeur de sp change ici
free(tp);
tp=*sp;
printf("L'élément a été supprimé avec succès \n");
}
}
else /* IMPORTANT! Sans le else et si tp pointe sur nil(voir plus haut), l'on va continuer l'exécution du prog
sur la 2e ligne plus bas. Dans ce cas tp^.nom n'a plus de sens. On recevra donc un message d'erreur */
{
if( (strcmpi(tp->nom, n)==0) && (k != 0)) //Ce n'est pas la première celule qui est à supprimer
{
temp->suivant = tp->suivant;
free(tp);
printf("L'élément a été supprimé avec succès \n");
}
else
{
if((strcmpi(tp->nom, n)!=0) && (tp->suivant ==NULL))
{
printf("L'élément à supprimer n'existe pas dans la liste \n");
}
}
}
}
}