Vous êtes sur la page 1sur 124

Machine Translated by Google

Tutoriel langage C

Version 0.042
Mars 1999

Tutoriel MS­DOS original par


Gordon Dodrill, Coronado Enterprises.

Déplacé vers Applix par Tim Ward


Tapé par Karen Ward

Programmes C convertis par


Tim Ward et Mark Harvey avec
l'aide de Kathy Morton pour Visual
Calculator
Joli imprimé par Eric Lindsay

Projet de micro­ordinateur Applix 1616


Applix Pty Ltd
Machine Translated by Google

Introduction
Le langage de programmation C a été initialement développé par Dennis Ritchie des Laboratoires Bell et
conçu pour fonctionner sur un PDP­11 avec un système d'exploitation UNIX . Bien qu'il ait été initialement
prévu pour fonctionner sous UNIX, il y avait un grand intérêt à l'exécuter sur les PC IBM et les systèmes
compatibles, ainsi que sur d'autres systèmes. Le C est excellent pour écrire des programmes au niveau
système, et l'ensemble du système d'exploitation Applix 1616/OS est écrit en C (à l'exception de quelques routines assembleur).
C'est un excellent langage pour cet environnement en raison de la simplicité d'expression, de la compacité du
code et du large éventail d'applicabilités.
Ce n’est pas une bonne langue de « début » car elle est de nature quelque peu énigmatique. Il permet au
programmeur un large éventail d'opérations allant du niveau élevé au niveau très bas se rapprochant du
niveau du langage assembleur. Il semble y avoir aucune limite à la flexibilité disponible. Un programmeur C
expérimenté a déclaré : "Vous pouvez programmer n'importe quoi en C", et cette déclaration est bien étayée
par ma propre expérience du langage. Mais en plus de la liberté qui en résulte, vous assumez de nombreuses
responsabilités. Il est très facile d'écrire un programme qui se détruit lui­même à cause de petites erreurs
idiotes que, par exemple, un compilateur Pascal signalera et appellera une erreur fatale. En C, vous êtes
vraiment seul, comme vous le découvrirez bientôt.
Puisque C n’est pas un langage pour débutants, je suppose que vous n’êtes pas un programmeur débutant
et je n’essaierai pas de vous ennuyer en définissant une constante et une variable. Vous devrez connaître ces
concepts de base. Cependant, on ne s'attend pas à ce que vous connaissiez quoi que ce soit du langage de
programmation C. Je commencerai par le plus haut niveau de programmation C, y compris les concepts
généralement intimidants de pointeurs, de structures et d'allocation dynamique. Pour bien comprendre ces
concepts, cela demandera un bon moment et un travail de votre part, car ce ne sont pas des outils
particulièrement faciles à appréhender, mais ce sont des outils très puissants. Assez parlé de cela, vous
verrez leur pouvoir quand nous y arriverons, mais ne vous permettez pas encore de vous inquiéter pour eux.
La programmation en C est un atout considérable dans les domaines où vous souhaiterez peut­être utiliser le
langage assembleur, mais préférerez qu'il s'agisse d'un programme simple à écrire et facile à maintenir. Il a
été dit qu'un programme écrit en C paierait une augmentation de 50 à 100 % du temps d'exécution, car aucun
langage n'est aussi compact ou rapide que le langage d'assemblage. Cependant, le temps gagné en codage
peut être énorme, ce qui en fait le langage le plus souhaitable pour de nombreuses tâches de programmation.
De plus, comme la plupart des programmes passent 90 % de leur temps de fonctionnement dans seulement
10 % ou moins du code, il est possible d'écrire un programme en C, puis de réécrire une petite partie du code
en langage assembleur et d'approcher la vitesse d'exécution de le même programme s’il était entièrement
écrit en langage assembleur.
Environ 75 pour cent de tous les nouveaux programmes commerciaux introduits pour les PC IBM ont été
écrits en C, et ce pourcentage est probablement en augmentation. Le logiciel système Apple Macintosh était
autrefois écrit en Pascal, mais il est désormais presque toujours écrit en C. L'intégralité du système
d'exploitation Applix 1616 est écrite en C, avec quelques routines assembleur.
Puisque C a été conçu essentiellement par une seule personne, et non par un comité, c'est un langage très
utilisable mais pas trop précisément défini. Il n’existait pas de norme officielle pour le langage C, mais
l’American National Standards Association (ANSI) a développé une norme pour le langage, elle suivra donc
des règles rigides. Il est intéressant de noter, cependant, que même s’il n’existe pas de norme, les différences
entre les implémentations sont généralement minimes. Cela est probablement dû au fait que la définition non
officielle originale a été si bien pensée et soigneusement planifiée que des extensions du langage ne sont pas
nécessaires.
Machine Translated by Google

Même si le langage C bénéficie d'un bon historique lorsque les programmes sont transportés d'une implémentation
à une autre, il existe des différences entre les compilateurs, comme vous le constaterez chaque fois que vous
essayez d'utiliser un autre compilateur. La plupart des différences deviennent apparentes lorsque vous utilisez des
extensions non standard telles que des appels au BIOS MS­DOS ou des appels système Applix 1616/OS, mais
même ces différences peuvent être minimisées par un choix judicieux des moyens de programmation.

Les constructeurs Applix 1616 disposent uniquement du compilateur HiTech C. Cette version du didacticiel est
personnalisée pour s'adapter à HiTech C. La version MS­DOS originale de Gordon Dodrill a été portée sur Applix
1616 (avec beaucoup d'efforts) par Tim Ward et saisie par Karen Ward. Les programmes ont été convertis en
HiTech C par Tim Ward et Mark Harvey, tandis que Kathy Morton a grandement contribué au fonctionnement de
Visual Calculator. Tous ont été testés sur le système d'exploitation multitâche Applix 1616/OS. Les disques de
distribution Applix contiennent le texte original complet de ce didacticiel, ainsi que tout le code source C converti.
Le deuxième disque contient des versions exécutables et relocalisables de tous les programmes, prêtes à être
exécutées sur un Applix 1616. Il existe également un répertoire du code source IBM original, pour ceux qui utilisent
des ordinateurs IBM et qui souhaitent les essayer avec un compilateur différent. Cette version imprimée a été
éditée, indexée et joliment imprimée par Eric Lindsay, qui a ajouté le matériel spécifique à Applix.

Cette version imprimée du didacticiel comprend des copies de tout le code, pour une référence plus facile. Il
comprend également une table des matières complète et un index.
Machine Translated by Google
1
Commencer
Ce tutoriel peut être lu simplement sous forme de texte, mais il se veut interactif. Autrement dit, vous devez compiler, modifier
et utiliser les programmes présentés ici.

Tous les programmes ont été testés à l'aide du compilateur HiTech C, et nous supposons que vous en avez une copie. De
plus, vous devriez disposer d'une copie de diverses mises à jour et fichiers d'en­tête pour le compilateur C, qui apparaissent
sur les disques des utilisateurs Applix.

Vous pouvez utiliser soit l'édition intégrée de l'éditeur Applix 1616/OS, soit l' éditeur Dr Doc à 30 $ en mode non­document.
Dr Doc est un peu plus puissant, mais lorsqu'il se charge à partir du disque, son démarrage est légèrement plus lent. Le
code source a été modifié pour s'adapter à un paramètre de tabulation de 5, alors appelez votre éditeur avec des tabulations
définies sur un espacement de 5. Par exemple, edit sourcecode.c 5 vous permettrait de modifier un fichier appelé
sourcecode.c.

Avant de pouvoir réellement utiliser C, certaines exigences en matière d’équipement doivent être remplies. Vous devez
disposer d'une carte coprocesseur de disque et d'au moins un lecteur de disque. Si vos lecteurs sont inférieurs à 800 Ko,
vous aurez probablement besoin de deux lecteurs de disque. Nous supposons que vous disposez soit du multitâche 1616/
OS version 4, soit d'un MRD d'attribution disponible sur votre disque de démarrage.

Vous devez utiliser XPath et les commandes Assign pour configurer votre disque de démarrage sous une forme adaptée à
une utilisation avec C. Cela doit être fait dans le fichier autoexec.shell sur votre disque de démarrage, comme indiqué ci­
dessous.

1.1 Disque de démarrage C

Créez une nouvelle copie amorçable de votre disque utilisateur 1616, en suivant les instructions de votre manuel d'utilisation.
Pour garantir un espace suffisant, supprimez tous les fichiers manifestement indésirables que vous remarquez sur la copie.

Copiez le contenu de votre disque de distribution HiTech C sur le nouveau disque, en conservant les sous­répertoires
identiques à ceux du disque HiTech.

Si vous avez reçu des fichiers d'en­tête C mis à jour ou d'autres mises à jour, copiez­les également dans leurs sous­
répertoires respectifs sur votre nouveau disque.

En utilisant edit, modifiez le XPath et attribuez des commandes dans votre fichier autoexec.shell dans le répertoire racine de
votre nouveau disque.

Votre XPath doit inclure /F0/bin (s'il n'est pas déjà inclus).

Ajoutez les lignes suivantes à votre autoexec.shell pour recréer l'environnement utilisé par Tim Ward lors de l'exécution
initiale de ces programmes. assign /hitech /f0/bin assign /sys /
f0/include assign /temp /rd Cela permettra
d'écrire du code sans tenir compte de l'endroit
où vous placez réellement vos
fichiers. Si vous utilisez un deuxième lecteur ou un disque dur, modifiez simplement le point d'affectation /hitech sur le lecteur
correct. C a tendance à utiliser largement les fichiers temporaires. Si vous disposez de suffisamment de mémoire disponible
sur votre disque RAM, utilisez /rd pour les fichiers temporaires. Sinon, utilisez le lecteur et le répertoire actuels, comme
indiqué par assign /temp .

Assurez­vous de copier le nouveau préprocesseur C relcc.xrel du disque utilisateur dans le sous­répertoire /bin de votre
nouveau disque C.

Commencer Tutoriel C 1­1


Notez que
Machine Translated byrelcc s'attend par défaut à trouver ses fichiers de bibliothèque C sur le lecteur actuel dans le répertoire /hitech.
Google
Il s'attend également à trouver ses fichiers d'inclusion sur le lecteur actuel dans le répertoire /hitech/include. Nous
expliquerons ce que cela signifie plus tard, et il y a une discussion détaillée du compilateur HiTech C à la fin du didacticiel.

Si tout est correct, vous pouvez maintenant compiler un fichier C en


tapant relcc ­v file.c
L'indicateur ­v consiste à invoquer le mode verbeux, qui produit le maximum d'informations du compilateur.

Si vous expérimentez, vous préférerez peut­être capturer toutes les erreurs rencontrées dans un fichier, pour une étude
ultérieure. Si c'est le
cas, utilisez relcc ­v file.c } errorfile

1.2 Qu'est­ce qu'un identifiant ?


Avant de pouvoir faire quoi que ce soit dans n’importe quelle langue, vous devez au moins savoir comment nommer un identifiant.
Un identifiant est utilisé pour toute variable, fonction, définition de données, etc. Dans le langage de programmation C,
un identifiant est une combinaison de caractères alphanumériques, le premier étant une lettre de l'alphabet ou un
soulignement, et le reste étant n'importe quelle lettre. de l’alphabet, de n’importe quel chiffre numérique ou du soulignement.
Deux règles doivent être gardées à l’esprit lors de la dénomination des identifiants. 1.

Le cas des caractères alphabétiques est significatif. Utiliser « INDEX » pour une variable n’est pas la même
chose que d’utiliser « index » et aucun d’eux n’est la même chose que d’utiliser « InDex » pour une variable. Tous les trois
font référence à des variables différentes.

2. Comme C est défini, jusqu'à huit caractères significatifs peuvent être utilisés et seront considérés comme
significatifs. Si plus de huit sont utilisés, ils peuvent être ignorés par le compilateur. Cela peut être vrai ou non pour votre
compilateur. Vous devriez consulter votre manuel de référence pour savoir combien de caractères sont importants pour
votre compilateur. Le compilateur HiTech C utilisé avec l'Applix 1616 autorise 31 caractères significatifs et ajoute un trait
de soulignement (_)

Il convient de souligner que certains compilateurs C autorisent l'utilisation du signe dollar dans un nom d'identifiant, mais
comme il n'est pas universel, il ne sera utilisé nulle part dans ce tutoriel. Vérifiez votre documentation pour voir si elle est
autorisée pour votre compilateur particulier.

1.3 Qu'en est­il du soulignement ?


Même si le soulignement peut être utilisé dans le nom d'une variable, il semble être très peu utilisé par les programmeurs
C expérimentés. Utiliser des noms descriptifs pour les variables ajoute grandement à la lisibilité d'un programme et il serait
à votre avantage de le faire. Les programmeurs Pascal ont tendance à utiliser des noms descriptifs longs, mais la plupart
des programmeurs C ont tendance à utiliser des noms courts et énigmatiques. La plupart des exemples de programmes
de ce didacticiel utilisent des noms très courts pour cette raison.

1.4 Comment ce didacticiel est rédigé


Tout programme informatique comporte deux entités à considérer : les données et le programme. Ils dépendent fortement
les uns des autres et une planification minutieuse des deux mènera à un programme bien planifié et bien écrit.
Malheureusement, il n’est pas possible d’étudier complètement l’un ou l’autre sans une bonne connaissance pratique de
l’autre. Pour cette raison, ce didacticiel fera des allers­retours entre les méthodes d'enseignement de l'écriture de
programmes et les méthodes de définition des données. Suivez simplement et vous aurez une bonne compréhension des
deux. Gardez à l’esprit que, même s’il semble opportun de passer parfois directement au codage du programme, le temps
passé à planifier les structures de données sera bien dépensé et le programme final reflétera la planification originale.

1­2 Tutoriel C Commencer


En parcourant
Machine Translated les exemples de programmes, vous constaterez que chaque programme est complet. Il n’y a aucun
by Google
fragment de programme qui pourrait prêter à confusion. Cela vous permet de voir toutes les exigences nécessaires
pour utiliser l'une des fonctionnalités de C telles qu'elles sont présentées.

Certains tutoriels que j'ai vus donnent des exemples très peu nombreux et très complexes. Ils servent vraiment
davantage à confondre l'étudiant. Ce tutoriel est tout le contraire car il s'efforce de couvrir chaque nouvel aspect de
la programmation dans un contexte aussi simple que possible. Cette méthode conduit cependant à un manque de
connaissances sur la manière dont les différentes parties sont combinées. Pour cette raison, le dernier chapitre est
entièrement consacré à l’utilisation des fonctionnalités enseignées dans les chapitres précédents. Il illustrera
comment rassembler les différentes fonctionnalités pour créer un programme utilisable. Ils sont donnés pour votre
étude et ne sont pas complètement expliqués. Suffisamment de détails sur leur fonctionnement sont donnés pour
vous permettre de comprendre leur fonctionnement après avoir terminé toutes les leçons précédentes.

1.5 Une discussion de certains fichiers


De nombreux fichiers de ce didacticiel sont indûment spécifiques à IBM. Les détails des versions Applix 1616
complètent normalement ces notes, bien qu'il reste encore quelques discussions sur les fonctionnalités MS­DOS.

1.6 Liste.xrel
Ce fichier répertoriera pour vous les fichiers source avec les numéros de ligne et le nom du fichier. Pour l'utiliser,
tapez simplement "LISTE" suivi du nom de fichier approprié. Tapez list firstex.c maintenant pour un exemple.
Le code source C est donné plus loin dans le chapitre 14 avec une brève description de son fonctionnement.
Les utilisateurs d'Applix 1616 disposent toujours de la commande d'édition intégrée, ce programme n'est donc pas
vraiment essentiel.

Commencer Tutoriel C 1­3


Machine Translated by Google
2
Débuter en C
La meilleure façon de démarrer avec C est de regarder un programme, alors chargez le fichier nommé trivial.c
dans l'éditeur et affichez­le sur le moniteur.

2.1 Votre premier programme C


Vous regardez le programme C le plus simple possible. Il n'y a aucun moyen de simplifier ce programme, ni
d'omettre quoi que ce soit. Malheureusement, le programme ne fait rien. principal() { }

Le mot « main » est très important et doit apparaître une et une seule fois dans chaque programme C.
C'est le point où l'exécution commence lorsque le programme est exécuté. Nous verrons plus tard que cela ne
doit pas nécessairement être la première instruction du programme, mais qu'elle doit exister comme point d'entrée.
Après le nom du programme "principal" se trouve une paire de parenthèses, qui indiquent au compilateur qu'il
s'agit d'une fonction. Nous expliquerons exactement ce qu’est une fonction en temps voulu. Pour l’instant, je
vous suggère d’inclure simplement la paire de parenthèses.
Les deux accolades { }, proprement appelées accolades, sont utilisées pour définir les limites du programme lui­
même. Les instructions du programme elles­mêmes se situent entre les deux accolades et dans ce cas, il n'y a
aucune instruction car le programme ne fait absolument rien. Vous pouvez compiler et exécuter ce programme,
mais comme il ne contient aucune instruction exécutable, il ne fait rien. Gardez cependant à l’esprit qu’il s’agit
d’un programme C valide.

2.2 Un programme qui fait quelque chose


Pour un programme beaucoup plus intéressant, chargez le programme nommé wrtsome.c et affichez­le sur votre
moniteur. C'est le même que le programme précédent sauf qu'il comporte une instruction exécutable entre les
accolades.

main( )

{ printf("Ceci est une ligne de texte à afficher."); }

L'instruction exécutable est une autre fonction. Encore une fois, nous ne nous soucierons pas de ce qu’est une
fonction, mais seulement de la manière d’utiliser celle­ci. Afin d'afficher du texte sur le moniteur, il est placé entre
parenthèses de fonction et délimité par des guillemets. Le résultat final est que tout ce qui est inclus entre les
guillemets sera affiché sur le moniteur lorsque le programme est exécuté.
courir.

Notez le point­virgule ; au bout de la ligne. C utilise un point­virgule comme terminateur d'instruction, le point­
virgule est donc requis pour signaler au compilateur que cette ligne est complète. Ce programme est également
exécutable, vous pouvez donc le compiler et l'exécuter pour voir s'il fait ce que vous pensez qu'il devrait faire.
Avec certains compilateurs, vous pouvez recevoir un message d'erreur lors de la compilation, indiquant que
printf() aurait dû être déclaré comme un entier. Ignorez cela pour le moment.

2­1 Tutoriel C Débuter en C


Machine Translated by Google
2.3 Un autre programme avec plus de résultats
Chargez le programme wrtmore.c et affichez­le sur votre moniteur pour un exemple de sortie supplémentaire et un
autre concept petit mais important. Vous verrez qu'il y a quatre instructions de programme dans ce programme,
chacune étant une instruction de fonction "printf". La ligne du haut sera exécutée en premier, puis la suivante, et ainsi
de suite, jusqu'à ce que la quatrième ligne soit terminée. Les instructions sont exécutées dans l'ordre de haut en bas.

principal( )
{
printf("Ceci est une ligne de texte à afficher.\n"); printf("Et ceci en est un autre
"); printf("ligne de texte.\n\n"); printf("Ceci est la
troisième ligne.\n");

Remarquez le caractère amusant vers la fin de la première ligne, à savoir la barre oblique inverse. La barre oblique
inverse est utilisée dans l'instruction printf pour indiquer qu'un caractère de contrôle spécial suit. Dans ce cas, le « n »
indique qu’un « saut de ligne » est demandé. Ceci est une indication pour ramener le curseur sur le côté gauche du
moniteur et descendre d’une ligne. Il est communément appelé retour chariot/saut de ligne. N'importe quel endroit du
texte que vous désirez, vous pouvez mettre un caractère de nouvelle ligne et commencer une nouvelle ligne. Vous
pouvez même le placer au milieu d'un mot et diviser le mot entre deux lignes.
Le compilateur C considère la combinaison de la barre oblique inverse et de la lettre n comme un seul caractère. Les
caractères exacts utilisés pour indiquer un newlin et un retour chariot sont spécifiques au système d'exploitation.
MS­DOS, Unix, 1616/OS et Macintosh peuvent différer les uns des autres.

Une description complète de ce programme est désormais possible. Le premier printf génère une ligne de texte et
renvoie le chariot. Le deuxième printf génère une ligne mais ne renvoie pas le chariot, donc la troisième ligne est
ajoutée à celle du deuxième, puis suivie de deux retours chariot, ce qui donne une ligne vide. Enfin, le quatrième printf
génère une ligne suivie d'un retour chariot et le programme est terminé.

Compilez et exécutez ce programme pour voir s'il fait ce que vous attendez de lui. Ce serait une bonne idée à ce
stade que vous expérimentiez en ajoutant des lignes supplémentaires d'impression pour voir si vous comprenez
comment fonctionnent réellement les déclarations.

2.4 Pour imprimer certains numéros


Chargez le fichier nommé oneint.c et affichez­le sur le moniteur pour notre premier exemple de travail avec des
données dans un programme C.
main( ) { int

index ; indice =
13 ; printf("La
valeur de l'index est %d\n",index); indice = 27 ; printf("La valve de l'index =
%d\n",index);
indice = 10 ; printf("La valeur de l'index = %d\n",index);

Le point d'entrée "main" devrait maintenant être clair pour vous, ainsi que l'accolade de début. La première nouveauté
que nous rencontrons est la ligne contenant "int index;", qui sert à définir une variable entière nommée "index". Le "int"
est un mot réservé en C, et ne peut donc être utilisé pour autre chose. Il définit une variable qui peut avoir une valeur
de ­32768 à 32767 sur la plupart des implémentations de micro­ordinateur MS­DOS de C. Il définit une variable avec
une valeur de ­2147483648 à 2147483647 dans HiTech C. Consultez le manuel d'utilisation de votre compilateur pour
la définition exacte de votre compilateur. Le nom de la variable, "index", peut être n'importe quel nom qui suit les règles
d'un identifiant

Débuter en C Tutoriel C 2­2


et n'est pas
Machine Translated by l'un des mots réservés pour C. Consultez votre manuel pour une définition exacte d'un identifiant pour votre
Google
compilateur. En HiTech C, la construction des noms d'identifiant est la même que sous UNIX, cependant 31 caractères
et les deux cas sont significatifs. Le compilateur ajoute un trait de soulignement aux références externes lors de la passe
assembleur. Le dernier caractère de la ligne, le point­virgule, est le terminateur d'instruction utilisé en C.

Nous verrons dans un chapitre ultérieur que des entiers supplémentaires pourraient également être définis sur la même
ligne, mais nous ne compliquerons pas la situation actuelle.

En observant le corps principal du programme, vous remarquerez qu'il existe trois instructions qui attribuent une valeur à
la variable "index", mais une seule à la fois. Le premier attribue la valeur 13 à "index" et sa valeur est imprimée. (Nous
verrons dans combien de temps.) Plus tard, la valeur 27 est affectée à "index", et finalement 10 lui est attribuée, chaque
valeur étant imprimée. Il devrait être intuitivement clair que « index » est bien une variable et peut stocker de nombreuses
valeurs différentes. Veuillez noter que les mots « imprimé » sont souvent utilisés pour signifier « affiché sur le moniteur ».
Vous constaterez que dans de nombreux cas, les programmeurs expérimentés prennent cette liberté, probablement à
cause de la fonction "printf" utilisée pour l'affichage du moniteur.

2.5 Comment imprimons­nous les nombres

Pour tenir nos promesses, revenons aux instructions "printf" pour une définition de leur fonctionnement.
Notez qu'ils sont tous identiques et qu'ils commencent tous comme les instructions "printf" que nous avons vues
précédemment. La première différence se produit lorsque nous arrivons au caractère %. Il s'agit d'un caractère spécial
qui signale à la routine de sortie d'arrêter de copier les caractères vers la sortie et de faire quelque chose de différent, à
savoir afficher une variable. Le signe % est utilisé pour signaler le début de nombreux types de variables différents, mais
nous nous limiterons à un seul pour cet exemple. Le caractère qui suit le signe % est un "d", qui signale à la routine de
sortie d'obtenir une valeur décimale et de la sortir. L’origine de la valeur décimale sera abordée sous peu. Après le "d",
nous trouvons le \n familier, qui est un signal pour renvoyer le "chariot" vidéo, et le guillemet fermant.

Tous les caractères entre guillemets définissent le modèle de données à afficher par cette instruction, et après le modèle,
il y a une virgule suivie du nom de variable « index ». C'est là que l'instruction "printf" obtient la valeur décimale qu'elle
affichera en raison du "%d" que nous avons vu plus tôt. Nous pourrions ajouter plus de descripteurs de champ de sortie
"%d" entre parenthèses et plus de variables après la description pour provoquer l'impression de plus de données avec
une seule instruction. Gardez cependant à l'esprit qu'il est important que le nombre de descripteurs de champs et le
nombre de définitions de variables soient les mêmes, sinon le système d'exécution sera confus et s'arrêtera probablement
avec une erreur d'exécution.

Beaucoup plus d’informations seront abordées ultérieurement sur tous les aspects du formatage d’entrée et de sortie.
Une assez bonne compréhension de ce sujet est nécessaire pour tout comprendre du formatage de sortie à l'heure
actuelle, seulement une bonne compréhension des bases.

Compilez et exécutez oneint.c et observez le résultat.

2.6 Comment ajouter des commentaires en C

Chargez le fichier comments.c et observez­le sur votre moniteur pour un exemple de la façon dont des commentaires
peuvent être ajoutés à un programme C.
/* Ceci est un commentaire ignoré par le compilateur */
principal( ) /* Ceci est un autre commentaire ignoré par le compilateur */
{
printf("Nous examinons comment sont les commentaires "); /* Un commentaire est
peut être continué
sur une autre ligne
*/

2­3 Tutoriel C Débuter en C


printf("utilisé
Machine Translated by Google en C.\n");
}
/* Un commentaire supplémentaire pour l'effet */

Des commentaires sont ajoutés pour rendre un programme plus lisible, mais le compilateur doit ignorer les commentaires.
La combinaison slash étoile est utilisée en C pour les délimiteurs de commentaires. Ils sont illustrés dans le programme
présenté. Veuillez noter que le programme n'illustre pas les bonnes pratiques en matière de commentaires, mais est
destiné à illustrer où les commentaires peuvent aller dans un programme. C'est un programme très bâclé.

La première combinaison barre oblique introduit le premier commentaire et l'étoile à la fin de la première ligne termine ce
commentaire. Notez que ce commentaire est antérieur au début du programme, illustrant qu'un commentaire peut précéder
le programme lui­même. Une bonne pratique de programmation inclurait un commentaire avant le programme avec une
brève description introductive du programme.
Le commentaire suivant se trouve après le point d'entrée du programme "main()" et avant l'accolade ouvrante du code du
programme lui­même.
Le troisième commentaire commence après la première instruction exécutable et continue sur quatre lignes. C'est
parfaitement légal car un commentaire peut continuer sur autant de lignes qu'il le souhaite jusqu'à ce qu'il soit terminé.
Notez soigneusement que si quelque chose était inclus dans les espaces vides à gauche des trois lignes de suite du
commentaire, cela ferait partie du commentaire et ne serait pas compilé.
Le dernier commentaire se situe après la fin du programme, illustrant que les commentaires peuvent aller presque
n'importe où dans un programme C.

Expérimentez avec ce programme en ajoutant des commentaires à d'autres endroits pour voir ce qui se passera.
Commentez l'une des instructions printf en plaçant des délimiteurs de commentaires avant et après et veillez à ce qu'elle
ne soit pas imprimée.

Les commentaires sont très importants dans n’importe quel langage de programmation car vous oublierez bientôt ce que
vous avez fait et pourquoi vous l’avez fait. Il sera beaucoup plus facile de modifier ou de corriger un programme bien
commenté dans un an qu'un programme avec peu ou pas de commentaires. Vous développerez très rapidement votre
propre style de commentaire.

Certains compilateurs vous permettent d'« imbriquer » des commentaires, ce qui peut être très pratique si vous devez
« commenter » une section de code pendant le débogage. Vérifiez la documentation de votre compilateur pour connaître
la disponibilité de cette fonctionnalité avec votre compilateur particulier. Compilez et exécutez comments.c à ce moment­là.

2.7 Bon style de formatage


Chargez le fichier goodform.c et observez­le sur votre moniteur.
principal() /* Le programme principal commence ici */
{
printf("Bonne forme "); printf ("peut
aider"); printf ("comprendre un programme.\n");
printf("Et mauvaise forme"); imprimerf imprimerf

("peut créer un programme "); ("illisible.


\n");
}

C'est un exemple de programme bien formaté. Même s'il est très court et donc très peu efficace, il est très facile de voir
d'un seul coup d'œil ce qu'il fait. Avec l'expérience que vous avez déjà acquise dans ce tutoriel, vous devriez être capable
de saisir très rapidement le sens du programme dans sa globalité. Votre compilateur C ignore tous les espaces
supplémentaires et tous les retours chariot, vous donnant une liberté considérable quant à la façon dont vous formatez
votre programme. L'indentation et l'ajout d'espaces dépendent entièrement de vous et sont une question de goût personnel.
Compilez et exécutez le programme pour voir s'il fait ce que vous attendez de lui.

Maintenant, chargez et affichez le programme laidform.c et observez­le.

Débuter en C Tutoriel C 2­4


main( ) by Google
Machine Translated /* Le programme principal commence ici */{printf("Good form ");printf
("peut aider à ");printf(" comprendre un programme.\n") ;printf("Et mauvaise
forme ");printf("peut créer un programme "); printf("illisible.\n");}

Combien de temps vous faudra­t­il pour comprendre ce que fera ce programme ? Le style de format que vous utilisez
n'a pas d'importance pour le compilateur, mais cela vous importera lorsque vous essaierez de déboguer votre
programme. Compilez ce programme et exécutez­le. Vous pourriez être surpris de constater qu'il s'agit du même
programme que le précédent, à l'exception du formatage. Ne vous inquiétez pas encore trop du style de formatage.
Vous aurez tout le temps de développer votre propre style tout en apprenant la langue. Soyez attentif aux styles lorsque
vous voyez les programmes C dans les magazines, les livres et autres publications.

Cela devrait assez bien couvrir les concepts de base de la programmation en C, mais comme il y a beaucoup d'autres
choses à apprendre, nous allons passer à une structure de programme supplémentaire.

2.8 Exercices de programmation


1. Écrivez un programme pour afficher votre nom sur le moniteur.

2. Modifiez le programme pour afficher votre adresse et votre numéro de téléphone sur des lignes distinctes en ajoutant
deux instructions "printf" supplémentaires.

2­5 Tutoriel C Débuter en C


Machine Translated by Google
3
Contrôle du programme

3.1 La boucle While


Le langage de programmation C possède plusieurs structures de bouclage et de branchement conditionnel. Nous les
couvrirons tous dans ce chapitre et nous commencerons par la boucle while. La boucle while continue de boucler tant
qu'une condition est vraie. Lorsque la condition devient fausse, le bouclage est interrompu. Il fait donc exactement ce
qu'il dit, le nom de la boucle étant très descriptif.

Chargez le programme while.c et affichez­le pour un exemple de boucle while.


/* Ceci est un exemple de boucle "while" */ main( ) { int count;
compte =

0 ; while (count
< 6) { printf("La
valeur du count est
%d\n",count); compte = compte + 1 ;

}
}

Nous commençons par un commentaire et le nom du programme, puis définissons une variable entière "count" dans le
corps du programme. La variable est mise à zéro et nous arrivons à la boucle while elle­même.
La syntaxe d'une boucle while est exactement comme indiqué ici. Le mot clé « while » est suivi d’une expression de
quelque chose entre parenthèses, suivie d’une instruction composée entre accolades.
Tant que l’expression entre parenthèses est vraie, toutes les instructions entre accolades seront exécutées.
Dans ce cas, puisque le nombre de variables est incrémenté de un à chaque fois que les instructions sont exécutées,
la boucle sera terminée. Le contrôle du programme reprendra à l'instruction suivant les instructions entre accolades.

Nous aborderons l’expression de comparaison, celle entre parenthèses, dans le prochain chapitre. En attendant,
acceptez simplement les expressions décrivant ce que vous pensez qu’ils devraient faire et vous aurez probablement raison.

Plusieurs choses doivent être soulignées concernant la boucle while. Premièrement, si la variable count était initialement
définie sur un nombre supérieur à 5, les instructions de la boucle ne seraient pas exécutées du tout, il est donc possible
d'avoir une boucle while qui n'est jamais exécutée. Deuxièmement, si la variable n'était pas incrémentée dans la
boucle, alors dans ce cas, la boucle ne se terminerait jamais et le programme ne se terminerait jamais. Enfin, s'il n'y a
qu'une seule instruction à exécuter dans la boucle, elle n'a pas besoin d'accolades mais peut être autonome.

Compilez et exécutez ce programme.

3.2 La boucle Do­While


Une variante de la boucle while est illustrée dans le programme dowhile.c, que vous devez charger et afficher.

/* Ceci est un exemple de boucle do­while */ main( ) { int i; je = 0 ;


do

{ printf("la
valeur
de i
est maintenant %d\n",i);

Contrôle du programme Tutoriel C 3­1


Machine Translated byjeGoogle
= je + 1 ; }
tandis que (i < 5);
}

Ce programme est presque identique au précédent sauf que la boucle commence par le mot réservé "do", suivi
d'une instruction composée entre accolades, puis du mot réservé "while", et enfin d'une expression entre
parenthèses. Les instructions entre accolades sont exécutées de manière répétée tant que l'expression entre
parenthèses est vraie. Lorsque l'expression entre parenthèses devient fausse, l'exécution est terminée et le
contrôle passe aux instructions qui suivent cette instruction.
Plusieurs choses doivent être soulignées concernant cette affirmation. Puisque le test est effectué à la fin de la
boucle, les instructions entre accolades seront toujours exécutées au moins une fois. Deuxièmement, si "i"
n'était pas modifié dans la boucle, la boucle ne se terminerait jamais et donc le programme ne se terminerait
jamais. Enfin, tout comme la boucle while, si une seule instruction doit être exécutée dans la boucle, aucune
accolade n'est requise. Compilez et exécutez ce programme pour voir s'il fait ce que vous pensez qu'il devrait
faire.

Cela ne devrait pas vous surprendre que ces boucles puissent être imbriquées. Autrement dit, une boucle peut
être incluse dans l'instruction composée d'une autre boucle et le niveau d'imbrication n'a pas de limite.

3.3 La boucle For


La boucle "for" n'a vraiment rien de nouveau, c'est simplement une nouvelle façon de décrire la boucle "while".
Chargez et modifiez le fichier nommé forloop.c pour un exemple de programme avec une boucle "for".
/* Ceci est un exemple de boucle for */ main( ) { int index; pour
(index = 0;

index < 6; index


= index + 1)
printf("La valeur de l'index est %d\n",index);
}

La boucle "for" est constituée du mot réservé "for" suivi d'une expression assez grande entre parenthèses. Cette
expression est en réalité composée de trois champs séparés par des points­virgules. Le premier champ contient
l'expression « index = 0 » et est un champ d'initialisation. Toutes les expressions de ce champ sont exécutées
avant le premier passage dans la boucle. Il n'y a essentiellement aucune limite quant à ce qui peut se passer ici,
mais une bonne pratique de programmation exigerait que cela reste simple. Plusieurs instructions d'initialisation
peuvent être placées dans ce champ, séparées par des virgules.
Le deuxième champ, contenant ici "index < 6", est le test qui est effectué au début de chaque boucle du
programme. Il peut s'agir de n'importe quelle expression qui sera évaluée comme vraie ou fausse. (Nous en
dirons davantage sur la valeur réelle de vrai et faux dans le prochain chapitre.)
L'expression contenue dans le troisième champ est exécutée à chaque fois que la boucle est exécutée, mais
elle n'est exécutée qu'après l'exécution des instructions du corps principal de la boucle. Ce champ, comme le
premier, peut également être composé de plusieurs opérations séparées par des virgules.
Après l'expression for() se trouve toute instruction simple ou composée qui sera exécutée comme corps de la
boucle. Une instruction composée est un groupe d'instructions C valides entourées d'accolades. Dans presque
tous les contextes en C, une instruction simple peut être remplacée par une instruction composée qui sera
traitée comme s'il s'agissait d'une instruction unique en ce qui concerne le contrôle du programme. Compilez et
exécutez ce programme.

3.4 L'instruction If
Chargez et affichez le fileifelse.cpour un exemple de notre première instruction de branchement conditionnel, le
"if".

3­2 Tutoriel C Contrôle du programme


/* Ceci est
Machine Translated byunGoogle
exemple des instructions if et if­else */ main() { int data;

for(data = 0;data < 10;data = data + 1) { if (data == 2) printf("Les


données sont
maintenant égales à %d\n",data); if (data < 5) printf("Les données
sont maintenant %d,
ce qui est inférieur à 5\n",data); else printf("Les données sont maintenant %d, ce qui est

supérieur à 4\n",data); } /* fin de la boucle for


*/
}

Notez d'abord qu'il existe une boucle "for" avec une instruction composée comme partie exécutable contenant
deux instructions "if". Ceci est un exemple de la façon dont une instruction peut être imbriquée. Il devrait être
clair pour vous que chacune des instructions « if » sera exécutée 10 fois.
Considérons la première instruction « si ». Il commence par le mot­clé « if » suivi d'une expression entre
parenthèses. Si l'expression est évaluée et trouvée vraie, l'instruction unique qui suit le « if » est exécutée. Si
elle est fausse, l'instruction suivante est ignorée. Ici aussi, l'instruction unique peut être remplacée par une
instruction composée composée de plusieurs instructions délimitées par des accolades.
L'expression "data" == 2" demande simplement si la valeur de data est égale à 2, cela sera expliqué en détail
dans le prochain chapitre. (Il suffit pour l'instant que si "data = 2" était utilisé dans ce contexte , cela signifierait
une chose complètement différente.)

3.5 Maintenant, pour le cas­si­sinon

Le deuxième "if" est similaire au premier, avec l'ajout d'un nouveau mot réservé, le "else", après la première
instruction printf. Cela dit simplement que si l'expression entre parenthèses est évaluée comme vraie, la
première expression est exécutée, sinon l'expression qui suit le "sinon" est exécutée. Ainsi, l'une des deux
expressions sera toujours exécutée, alors que dans le premier exemple, l'expression unique était soit
exécutée, soit ignorée. Les deux trouveront de nombreuses utilisations dans vos efforts de programmation en
C. Compilez et exécutez ce programme pour voir s'il fait ce que vous attendez.

3.6 La pause et continuer


Chargez le fichier nommé breakcon.c pour un exemple de deux nouvelles instructions.

main( ) {int

xx; for(xx
= 5;xx < 15;xx = xx + 1){ if (xx == 8) break;

printf("dans la boucle de rupture, xx est maintenant %d\n",xx);

} for(xx = 5;xx < 15;xx = xx + 1){ if (xx == 8) continuer ;


printf("Dans la
boucle
continue, xx est le maintenant %d\n",xx);
}
}

Notez que dans le premier "for", il y a une instruction if qui appelle un break si xx est égal à 8. Le break sortira
de la boucle dans laquelle vous vous trouvez et commencera à exécuter les instructions qui suivent la boucle,
mettant ainsi fin à la boucle. Il s'agit d'une déclaration précieuse lorsque vous devez sortir d'une boucle en
fonction de la valeur de certains résultats calculés dans la boucle. Dans ce cas, lorsque xx atteint 8, la boucle
se termine et la dernière valeur imprimée sera la valeur précédente, à savoir 7.

Contrôle du programme Tutoriel C 3­3


Machine Translated by"for"
La boucle Google
suivante contient une instruction continue qui n'entraîne pas la fin de la boucle mais sort de l'itération
actuelle. Lorsque la valeur de xx atteint 8 dans ce cas, le programme sautera à la fin de la boucle et continuera à
exécuter la boucle, éliminant ainsi l'instruction printf lors du passage dans la boucle lorsque xx vaut huit. Compilez
et exécutez le programme pour voir s'il fait ce que vous attendez.

3.7 L'instruction Switch


Chargez et affichez le fichier switch.c pour un exemple de la plus grande construction jamais réalisée en langage
C, le switch.
main( )

{ int camion ;
for (truck = 3;truck < 13;truck = truck + 1) { switch (truck) { case 3 :
printf("La valeur est
trois\n"); casser; : printf("La valeur est quatre\n"); casser; cas 5 :
cas 6 :
cas 4 cas 7 : cas 8 : printf("La valeur est comprise entre
5 et
8\n"); casser;
cas 11 :
printf("La
valeur est onze\n"); casser; par défaut : printf("C'est une des valeurs non

définies\n"); casser; } /* fin du commutateur } /* fin de la boucle */

*/

Le changement n’est pas difficile, alors ne vous laissez pas intimider. Il commence par le mot clé "switch" suivi
d'une variable entre parenthèses qui est la variable de commutation, en l'occurrence "camion". Autant de boîtiers
que vous le souhaitez sont ensuite enfermés dans une paire d'accolades. Le mot réservé « case » est utilisé pour
commencer chaque cas saisi suivi de la valeur de la variable, puis de deux points et des instructions à exécuter.

Dans cet exemple, si la variable "truck" contient la valeur 8 lors de ce passage de l'instruction switch, le printf fera
afficher "La valeur est trois", et l'instruction "break" nous fera sortir du champ. changer.

Une fois qu'un point d'entrée est trouvé, les instructions seront exécutées jusqu'à ce qu'un "break" soit trouvé ou
jusqu'à ce que le programme passe par le bas des accolades du commutateur. Si la variable a la valeur 5, les
instructions commenceront à s'exécuter là où se trouve "case 5 :", mais les premières instructions trouvées sont là
où se trouvent les instructions case 8. Celles­ci sont exécutées et l'instruction break dans la partie "case 8" dirigera
l'exécution vers le bas du commutateur. Les différentes valeurs de cas peuvent être dans n'importe quel ordre et si
une valeur n'est pas trouvée, la partie par défaut du commutateur sera exécutée.

Il doit être clair que n'importe laquelle des constructions ci­dessus peut être imbriquée les unes dans les autres ou
placées successivement, en fonction des besoins du projet de programmation particulier en question.

Compilez et exécutez switch.c pour voir s'il fait ce que vous attendez après cette discussion.

3.8 L'instruction Goto


Chargez et affichez le fichier gotoex.c pour un exemple de fichier contenant des instructions "goto".

3­4 Tutoriel C Contrôle du programme


main() by Google
Machine Translated
{ int chien, chat, cochon ;
allez à real_start ;
some_where:
printf("Ceci est une autre ligne de désordre.\n"); allez stop_it ;

/* la section suivante est la seule avec un goto utilisable */


real_start :
for(chien = 1;chien < 6;chien++) {
pour(cat = 1;cat < 6;cat++) {
pour(cochon = 1;cochon < 4;cochon++) {
printf("Chien = %d Chat = %d Cochon = %d\n",chien,chat,cochon); if ((chien + chat +
cochon) > 8 ) ça suffit ;



assez: printf("Ce sont assez d'animaux pour l'instant.\n"); /* c'est la fin de la section avec une
instruction goto utilisable */
printf("\nCeci est la première ligne du code spaghetti.\n"); allez là­bas; où : printf("Ceci est la troisième ligne du
code spaghetti.
\n"); aller
quelque part ; là : printf("c'est la deuxième ligne du code spaghetti.\n"); aller où ; stop_it: printf("Ceci
est la dernière ligne du
désordre.
\n");

Pour utiliser une instruction "goto", vous utilisez simplement le mot réservé "goto", suivi du nom symbolique auquel vous
souhaitez accéder. Le nom est ensuite placé n'importe où dans le programme suivi de deux points. Vous n'êtes pas
autorisé à sauter dans une boucle, mais vous êtes autorisé à sortir d'une boucle. De plus, vous n’êtes pas autorisé à
passer d’une fonction à une autre. Ces tentatives seront signalées par votre compilateur comme une erreur si vous en
tentez une.

Ce programme particulier est vraiment un gâchis, mais c'est un bon exemple de la raison pour laquelle les auteurs de
logiciels tentent d'éliminer autant que possible l'utilisation de l'instruction "goto". Le seul endroit dans ce programme où il
est raisonnable d'utiliser le "goto" est celui de la ligne 17 où le programme saute hors des trois boucles imbriquées en un
seul saut. Dans ce cas, il serait plutôt compliqué de configurer une variable et de sauter successivement hors des trois
boucles, mais une seule instruction "goto" vous permet de sortir des trois.

Certaines personnes disent que l'instruction "goto" ne devrait en aucun cas être utilisée, mais c'est une pensée plutôt
étroite. S'il existe un endroit où un "goto" sera le meilleur, n'hésitez pas à l'utiliser. Il ne faut cependant pas en abuser, car
c'est le cas dans le reste du programme sur votre moniteur.

Des livres entiers sont écrits sur la programmation « gotoless », mieux connue sous le nom de programmation structurée.
Ceux­ci seront laissés à votre étude. Un point de référence est la calculatrice visuelle décrite au chapitre 14 de ce
didacticiel. Ce programme est contenu dans quatre programmes compilés séparément et est un programme complexe
assez volumineux. Si vous passez du temps à étudier le code source, vous constaterez qu'il ne contient aucune instruction
"goto". Compilez et exécutez gotoex.c et étudiez son résultat. Ce serait un bon exercice de le réécrire et de voir à quel
point il est plus lisible lorsque les déclarations sont classées dans l'ordre.

3.9 Enfin, un programme significatif


Chargez le fichier nommé tempconv.c pour un exemple de programme utile, quoique quelque peu limité. Il s'agit d'un
programme qui génère une liste des températures centigrades et Fahrenheit et imprime un message au point de
congélation de l'eau et un autre au point d'ébullition de l'eau.

Contrôle du programme Tutoriel C 3­5


/***************************************************
Machine Translated by Google **********/ /* Il s'agit d'un programme de conversion de
température écrit en */ /* le langage de programmation C. Ce programme génère */ /* */ et affiche un
tableau des températures farenheit et centigrades /*, et répertorie la congélation et l'ébullition */ /* */
de l'eau /**************
farenheit; int*********************************************/
centigrade; /* la température en degrésprincipal( ) { nombre
centigrades */ entier ; int
printf("Tableau des températures centigrades à farenheit\n\n"); for(count = ­2;count <= 12;count =
count + 1 ){degrés
centigrades = 10 * count; farenheit = 32 + (centigrades * 9)/5 ; printf(" C =%4d F =%4d ",
centigrades, farenheit); si (centigrade == 0)

/* une variable de contrôle de boucle /* la */


température en degrés farenheit */

printf("Point de congélation de l'eau"); if (centigrades ==


100) printf(" Point d'ébullition de
l'eau"); printf("\n"); } /* fin de la boucle for */

Le formatage est particulièrement important. L'en­tête est simplement constitué de plusieurs lignes de commentaires décrivant ce
que fait le programme de manière à attirer l'attention des lecteurs tout en restant agréable à l'œil. Vous développerez éventuellement
votre propre style de formatage, mais c’est une bonne façon de commencer.

De plus, si vous observez la boucle for, vous remarquerez que tout le contenu de l'instruction composée est indenté de quelques
espaces à droite du mot réservé "for" et que l'accolade fermante est alignée sous le "f" dans " pour". Cela rend le débogage un peu
plus facile car la construction devient très évidente.

Vous remarquerez également que les instructions "printf" qui se trouvent dans les instructions "if" dans la grande boucle "for" sont
indentées de trois espaces supplémentaires car elles font partie d'une autre construction. C'est le premier programme dans lequel
nous utilisons plus d'une variable. Les trois variables sont simplement définies sur trois lignes différentes et sont utilisées de la même
manière qu'une seule variable était utilisée dans les programmes précédents. En les définissant sur des lignes différentes, nous
avons la possibilité de définir chacune d'entre elles par un commentaire.

3.10 Un autre mauvais exemple de programmation


En vous souvenant de laidform.c du chapitre précédent, vous avez vu un programme très mal formaté. Si vous chargez et affichez
dumbconv.c vous aurez un exemple de mauvais formatage qui est beaucoup plus proche de ce que vous trouverez réellement en
pratique. Il s'agit du même programme que tempconv.c avec les commentaires supprimés et les noms de variables modifiés pour
supprimer l'aspect descriptif des noms. Bien que ce programme fasse exactement la même chose que le précédent, il est beaucoup
plus difficile à lire et à comprendre. Vous devriez commencer à développer de bonnes pratiques de programmation

maintenant.

main( )

{ int x1,x2,x3;
printf("Tableau des températures Celsius à Farenheit\n\n");
pour(x1 = ­2;x1 <= 12;x1 = 1){ x3 = 10 * x1; x2
= 32 + (x3 * 9)/5 ;
printf(" C =%4d F =%4d ",x3,x2);
if (x3 == 0) printf("Point de congélation de l'eau");

3­6 Tutoriel C Contrôle du programme


Machine Translated byif (x3 == 100)
Google
printf("Point d'ébullition de l'eau"); printf("\n");

}
}

Compilez et exécutez ce programme pour voir qu'il fait exactement ce que le dernier a fait.

3.11 Exercices de programmation


1. Écrivez un programme qui écrit votre nom sur le moniteur dix fois. Écrivez ce programme trois fois, une
fois avec chaque méthode de bouclage.
2. Écrivez un programme qui compte de un à dix, imprime les valeurs sur une ligne distincte pour chacun et
inclut un message de votre choix lorsque le compte est de 3 et un message différent lorsque le compte est
de 7.

Contrôle du programme Tutoriel C 3­7


Machine Translated by Google
4
Affectation et comparaisons logiques

4.1 Déclarations d'affectation d'entiers


Chargez le fichier intasign.c et affichez­le pour un exemple d'instructions d'affectation.

/* Ce programme illustrera les instructions d'affectation */


main( ) {int

a,b,c; /* Variables entières pour exemples */


une = 12 ;
b=3;c
= une + b ; /* addition simple */ c = a ­ b; /* soustraction
simple */
c = une *b; /* multiplication simple */ c = a / b; /* addition
simple c = a % b; /* simple modulo (reste) */ c = */
12*a + b/2 ­ a*b*2/(a*c + b*2); c = c/4+13*(une + b)/3 ­ une*b +
2*une*une ; une = une + 1 ; /* incrémentation d'une
variable b = b * 5;
*/

une = b = c = 20 ; /* affectation multiple a = b = c = 12*13/4; */

Trois variables sont définies pour être utilisées dans le programme et le reste du programme n'est qu'une série d'illustrations
de diverses tâches. Les deux premières lignes des instructions d'affectation attribuent des valeurs numériques à « a » et
« b », et les quatre lignes suivantes illustrent les cinq fonctions arithmétiques de base et comment les utiliser. Le cinquième
est l'opérateur modulo et donne le reste si les deux variables étaient divisées. Il ne peut s'appliquer qu'aux variables de
type "int" ou "char", et bien sûr aux extensions "int" telles que "long", "short", etc. A la suite de celles­ci, il y a deux lignes
illustrant comment combiner certaines des variables dans certaines expressions mathématiques complexes. Tous les
exemples ci­dessus ne devraient nécessiter aucun commentaire, sauf pour dire qu'aucune des équations n'est censée être
particulièrement utile, sauf à titre d'illustration.

Les deux expressions suivantes sont parfaitement acceptables telles qu'elles sont données, mais nous verrons plus loin
dans ce chapitre qu'il existe une autre façon de les écrire pour un code plus compact.

Il nous reste donc les deux dernières lignes qui peuvent vous paraître très étranges. Le compilateur C analyse l'instruction
d'affectation de droite à gauche (ce qui peut sembler un peu étrange puisque nous ne lisons pas de cette façon), ce qui
donne une construction très utile, à savoir celle donnée ici. Le compilateur trouve la valeur 20, l'attribue à "c", puis continue
vers la gauche en constatant que le dernier résultat d'un calcul doit être attribué à "b". Pensant que le dernier calcul a
abouti à un 20, il l'attribue également à "b" et continue le balayage vers la gauche en attribuant également la valeur 20 à "a".

C'est une construction très utile lorsque vous initialisez un groupe de variables. La dernière affirmation montre qu'il est
possible d'effectuer certains calculs pour arriver à la valeur qui sera attribuée aux trois variables.

Le programme n'a aucune sortie, donc compiler et exécuter ce programme sera très inintéressant.
Puisque vous avez déjà appris à afficher des résultats entiers à l'aide de la fonction "printf", il serait à votre avantage
d'ajouter des instructions de sortie à ce programme pour voir si les différentes instructions font ce que vous pensez qu'elles
devraient faire.

4­1 Tutoriel C Affectation et comparaisons logiques


Ce serait by
Machine Translated le bon moment pour une définition préliminaire d'une règle à suivre en C. Les définitions de données sont toujours
Google
données avant toute instruction exécutable dans n'importe quel bloc de programme. C'est pourquoi les variables sont définies en
premier dans ce programme et dans tout programme C. Si vous essayez de définir une nouvelle variable après avoir exécuté
certaines instructions, le compilateur générera une erreur.

4.2 Types de données supplémentaires

Le chargement et l'édition de mortotypes.c illustreront comment certains types de données supplémentaires peuvent être utilisés.

/* Le but du fichier est d'introduire des types de données supplémentaires */


main( )

{int a,b,c; char /* ­32768 à 32767 sans point décimal */ /* 0 à 255 sans point
x,y,z; float num, décimal */
jouet, chose ; /* 10E­38 à 10E+38 avec point décimal */
a = b = c = ­27 ; x = y =
z = « A » ; num = jouet
= chose = 3,6792 ;
une = /* a vaut désormais 65 (caractère A) */ /* x sera
oui ; x = désormais un nombre amusant */ /* num sera
b ; num = b; désormais ­27,00 */ /* a sera désormais 3 */
a = jouet ;
}

Une fois de plus, nous avons défini quelques variables de type entier que vous devriez déjà connaître, mais nous avons ajouté
deux nouveaux types, le "char" et le "float".

Le type de données "char" est presque le même que l'entier, sauf qu'on ne peut lui attribuer que des valeurs comprises entre
zéro et 255, car il est stocké dans un seul octet de mémoire. Le type de données « char » est généralement utilisé pour les
données ASCII, plus communément appelées texte. Le texte que vous lisez a été écrit à l’origine sur un ordinateur équipé d’un
traitement de texte qui stockait les mots dans l’ordinateur à raison d’un caractère par octet. En revanche, le type de données
entier est stocké dans deux octets de mémoire informatique sur la plupart des micro­ordinateurs 8 bits et MS­DOS.

L'Applix 1616 utilise une puce 68 000 avec de vrais registres de 32 bits, donc les entiers sont de 32 bits. Cela signifie que la
plage d'un nombre entier n'est pas ±32767, mais ±2147483648, soit plus de deux milliards ! Sur Applix, un int court peut être plus
approprié à certains endroits.

4.3 Mélange de types de données

Il serait intéressant à ce stade de discuter de la manière dont C gère les deux types "char" et "int".
La plupart des fonctions en C conçues pour fonctionner avec des variables de type entier fonctionneront aussi bien avec des
variables de type caractère car elles sont une forme de variable entière. Ces fonctions, lorsqu'elles sont appelées à utiliser une
variable de type "char", transformeront en fait les données "char" en données entières avant de les utiliser. Pour cette raison, il
est possible de mélanger des variables de type "char" et "int" à peu près comme vous le souhaitez. Le compilateur ne sera pas
confus, mais vous pourriez le faire. Il est bon de ne pas trop s’y fier, mais d’utiliser avec précaution uniquement les types de
données appropriés là où ils doivent être utilisés.

Le deuxième nouveau type de données est le type de données « flottant », communément appelé données à virgule flottante. Il
s'agit d'un type de données qui a généralement une très large plage, un grand nombre de chiffres significatifs et un grand nombre
de mots informatiques pour le stocker. Le type de données « float » est associé à un point décimal et, sur la plupart des
ordinateurs, sa plage autorisée est comprise entre 10­38 et 10+38.
Tous les compilateurs n'ont pas la même plage disponible, alors consultez votre manuel de référence pour connaître les limites
de votre compilateur.

Affectation et comparaisons logiques Tutoriel C 4­2


Machine Translated by Google
4.4 Comment utiliser les nouveaux types de données

Les trois premières lignes du programme attribuent des valeurs aux neuf variables définies afin que nous puissions
manipuler certaines données entre les différents types.

Puisque, comme mentionné ci­dessus, un type de données "char" est en réalité un type de données "entier", aucune
considération particulière ne doit être prise pour promouvoir un "char" en variable "int". Dans l'autre sens, il n'y a pas
de norme, vous pouvez donc simplement obtenir des déchets si la valeur est comprise entre zéro et 255. Par
conséquent, dans la deuxième ligne, lorsque vous essayez de définir x (un caractère) sur ­27, vous pouvez ou peut ne
pas obtenir une réponse bien définie, cela dépend de votre implémentation particulière de C.

La troisième ligne illustre la simplicité de traduire un entier en "float", attribuez­lui simplement la nouvelle valeur et le
système effectuera la conversion appropriée. Cependant, dans l’autre sens, il y a une complication supplémentaire.
Puisqu’il peut y avoir une partie fractionnaire du nombre à virgule flottante, le système doit décider quoi en faire. Par
définition, cela va le tronquer.

Ce programme ne produit aucune sortie, et nous n'avons pas expliqué comment afficher les variables de type "char"
et "float", vous ne pouvez donc pas vraiment accéder à ce programme et jouer avec les résultats, mais le programme
suivant couvrira pour vous.

4.5 Caractéristiques des types de variables

Un problème malheureux avec C (et certains autres langages) est que la taille réelle des variables dépend quelque
peu de la machine (et du compilateur) utilisée. Des difficultés sont parfois rencontrées lors du déplacement du code
d’une machine à une autre à cause de cela.

Une règle générale pour les compilateurs modernes est que char est d'au moins 8 bits, short est d'au moins 16 bits,
long est d'au moins 32 bits, int est identique à short ou long (ce qui entraîne le décollage de nombreuses conversions
de code) , float fait au moins 32 bits et double est au moins aussi large que float. En conséquence, vous devez utiliser
short ou long de préférence à int (malgré son utilisation intensive dans ce didacticiel), et éviter de doubler autant que
possible. Notez que l'utilisation de short au lieu de int peut économiser un accès mémoire supplémentaire et contribuer
à accélérer le code, en particulier dans les grandes boucles. caractère entier 8 bits (0 à 255)

32 bits (s'assemble en .l ou ±2147483648)

flotter 32 bits (environ 1 038)


double 64 bits (10 308 maximum)
court 16 bits (s'assemble en .w ou ±32767)

32 bits (s'assemble en .l ou ±2147483648)

L'ordre des octets longs est un autre problème rencontré lors de la conversion de programmes d'une machine à une
autre. Dans le 68000, l'octet de poids faible d'un mot de 16 bits est le deuxième octet impair. Les octets d'une longueur
de 32 bits sont disposés dans l'octet de poids fort à l'adresse, avec l'octet de poids faible en dessous. Les puces Intel
utilisent l'ordre inverse. Ce problème de sexe d’octets donne lieu à des arguments semblables à ceux de la religion et
de la politique, et tout aussi susceptibles de conduire à de vraies solutions.

4.6 Beaucoup de types de variables

Chargez le fichier lottypes.c et affichez­le sur votre écran.

4­3 Tutoriel C Affectation et comparaisons logiques


principal( by
Machine Translated ) Google
{
int un; /* Type entier simple /* Type entier */
long int b; court long /* Type entier court /* Type */
int c; non signé int entier non signé /* Type caractère / */
d ; char e; flotter f; * Type à virgule flottante /* Virgule */
double g; flottante double précision */ */
*/

une = 1023 ;
b = 2222 ;
c = 123 ;
d = 1234 ;
e = 'X';
f = 3,14159 ;
g = 3,1415926535898 ;
printf("a = %d\n",a); printf("a = /* sortie décimale */
%o\n",a); printf("a = %x\n",a); /* sortie octale */
printf("b = %1d\n",b); printf("c = /* sortie hexadécimale */
%d\n",c); printf("d = %u\n",d); /* Sortie décimale longue /* Sortie */
printf("e = %c\n",e); printf("f = décimale courte */
%f\n",f); printf("g = %f\n",g); /* sortie non signée */
printf("\n"); /* sortie de caractères */
/* sortie flottante */
/* sortie double float */

printf("a = %d\n",a); printf("a = /* sortie int simple */


%7d\n",a); printf("a = %­7d\n",a); /* utilise une largeur de champ de 7 */
printf("\n"); /* justifier à gauche dans le champ 7 */

printf("f = %f\n",f); printf("f = /* sortie flottante simple /* utilise */


%12f\n",f); printf("f = %12.3f\n",f); /* une largeur de champ de 12 */
utilise 3 décimales */
printf("f = %12.5f\n",f); /* utilise 5 décimales */
printf("f = %­12.5f\n",f); /* justifier à gauche dans le champ */
}

Ce fichier contient tous les types de données simples standard disponibles dans le langage de programmation C.
Il existe d'autres types, mais ce sont les types composés que nous aborderons en temps voulu.

Observez le dossier. Nous définissons d’abord un simple « int » suivi d’un « long int » et d’un « short int ». Consulter
votre manuel de référence pour une définition exacte de ceux­ci pour votre compilateur, car ils ne le sont pas
cohérente d’une mise en œuvre à l’autre. Le "non signé" vient ensuite et est défini comme
la même taille que le "int" mais sans signe. Le "non signé" couvrira alors une plage de 0 à 65535
sur les micro­ordinateurs MS­DOS, mais comme 0 à 4294967296 dans HiTech. Il convient de souligner que
lorsque "long", "short" ou "unsigned" est souhaité, le "int" est facultatif et laissé de côté par la plupart
programmeurs expérimentés. Nous avons déjà abordé le "char" et le "float", ce qui laisse
seulement le "double". Le « double » couvre généralement une plus grande portée que le « flottant » et a plus de
chiffres significatifs pour des calculs plus précis. Il faut également plus de mémoire pour stocker une valeur
que le simple "flotteur". Consultez votre manuel de référence pour connaître la portée et la précision du « double ».

Une autre diversion s’impose à ce stade. La plupart des compilateurs ont des dispositions pour la virgule flottante
mathématiques, mais seulement mathématiques doubles flottantes. Ils favoriseront un "flottant" en "double" avant de faire
calculs et donc une seule bibliothèque mathématique sera nécessaire. Bien sûr, c'est totalement
transparent pour vous, vous n'avez donc pas à vous en soucier. Vous pensez peut­être qu'il serait préférable de
définissez simplement chaque variable à virgule flottante comme double, car elles sont promues avant d'être utilisées dans n'importe quel
calculs, mais ce n’est peut­être pas une bonne idée. Une variable "float" nécessite 4 octets de stockage et
un "double" nécessite 8 octets de stockage, donc si vous disposez d'un grand volume de données à virgule flottante à
store, le "double" nécessitera évidemment beaucoup plus de mémoire. Votre compilateur peut nécessiter un
nombre d'octets différent de 4 ou 8. Consultez votre manuel de référence pour connaître le nombre correct d'octets.
octets utilisés par votre compilateur.

Affectation et comparaisons logiques Tutoriel C 4­4


Machine Translated by défini
Après avoir Googleles types de données, une valeur numérique est attribuée à chacune des variables définies dans
afin de démontrer les moyens de sortir chacun sur le moniteur.

4.7 Les caractères de conversion


Voici une liste des caractères de conversion et la manière dont ils sont utilisés dans l'instruction "printf".
d notation décimale
Ô notation octale
X notation hexadécimale
dans
mention non signée
c notation des caractères
s notation de chaîne
F notation à virgule flottante
(la fonction Applix printf intégrée a un caractère de conversion %e, qui imprime l'erreur interne
message correspondant à un numéro d'erreur ­ ce n'est pas standard en C.)

Chacun d'entre eux est utilisé après un signe de pourcentage pour indiquer le type de conversion de sortie, et
entre ces deux caractères, les champs suivants peuvent être ajoutés.
­
gauche justification dans son domaine
(n) un nombre spécifiant la largeur minimale du champ
. séparer n de m
(m)l chiffres fractionnaires significatifs pour un flottant
pour indiquer un "long"

Ceux­ci sont tous utilisés dans les exemples inclus dans le programme actuellement affiché sur
votre moniteur, à l'exception de la notation de chaîne qui sera abordée plus loin dans ce didacticiel.
Compilez et exécutez ce programme pour voir quel effet les différents champs ont sur la sortie.

Vous avez maintenant la possibilité d'afficher n'importe quel champ de données dans les programmes précédents et cela
Il serait avantageux de revenir en arrière et de voir si vous pouvez afficher l'un des champs comme vous le souhaitez.

4.8 Comparaisons logiques


Chargez et affichez le fichier nommé compare.c pour de nombreux exemples d'instructions de comparaison en C.
main( ) /* ce fichier illustrera des comparaisons logiques */
{
int x = 11,y = 11,z = 11 ;
caractère a = 40,b = 40,c = 40 ;
flottant r = 12,987,s = 12,987,t = 12,987 ;
/* Premier groupe d'instructions de comparaison */
si (x == y) z = ­13 ; /* Cela définira z = ­13 */
si (x > z) a = 'A' ; /* Cela définira a = 65 */
si (!(x > z)) a = 'B'; /* Cela ne changera rien */
si (b <= c) r = 0,0 ; /* Cela définira r = 0,0 */
si (r != s) t = c/2; /* Cela définira t = 20 */
/* Deuxième groupe d'instructions de comparaison */
si (x = (r != s)) z = 1000 ; /* Cela définira x = du positif
nombre et z = 1000 */
si (x = y) z = 222 ; si (x != 0) z /* Cela définit x = y et z = 222 */
= 333 ; /* Cela définit z = 333 */
si (x) z = 444 ; /* Cela définit z = 444 */
/* Troisième groupe d'instructions de comparaison */

4­5 Tutoriel C Affectation et comparaisons logiques


x = yby
Machine Translated = zGoogle
= 77 ; si ((x
== y) && (x == 77)) z = 33; /* Ceci définit z = 33 */ z = 22; /* Ceci définit z = 22 */ if ((x >y)
|| (z > 12))
&& z) z = 11; if ((x = 1) && (y = 2) && /* Ceci définit z = 11 */ if ((x && y
(z = 3)) r = 12.00; /* Ceci définit x = 1, y = 2, z = 3, r = 12 .00 */ if ((x == 2) && (y = 3) &&
(z = 4)) r = 14.56; /* Ce n'est pas le cas changer
quoi que ce soit */ /* Quatrième groupe de comparaisons */

si (x == x); z = 27,345 ; /* z est toujours modifié */ z = 27,345; /* Rien n'est modifié


*/ if (x = 0) */ if (x != x) z = 27.345; /* Ceci définit x = 0, z est inchangé

Nous commençons par définir et initialiser neuf variables à utiliser dans les instructions de comparaison suivantes.
Cette initialisation est nouvelle pour vous et peut être utilisée pour initialiser des variables pendant qu'elles sont définies.

Le premier groupe d’instructions de comparaison représente les types de comparaisons les plus simples puisqu’elles
comparent simplement deux variables. L'une ou l'autre variable peut être remplacée par une constante tout en restant
valable, mais deux variables sont le cas général. La première comparaison vérifie si « x » est égal à « y » et utilise le
double signe égal pour la comparaison. Un seul signe égal pourrait être utilisé ici mais il aurait une signification différente
comme nous le verrons bientôt. La deuxième comparaison vérifie si « x » est supérieur à « z ».

Le troisième introduit l'opérateur "NON", l'exclamation, qui peut être utilisé pour inverser le résultat de toute comparaison
logique. Le quatrième vérifie si "b" est inférieur ou égal à "c" et le dernier vérifie si "r" n'est pas égal à "s". Comme nous
l'avons appris dans le chapitre précédent, si le résultat de la comparaison est vrai, l'instruction suivant la clause "if" sera
exécutée et les résultats seront donnés dans les commentaires.
Notez que « inférieur à » et « supérieur ou égal à » sont également disponibles, mais ne sont pas illustrés ici.

Il serait bon de mentionner le format différent utilisé pour l'instruction "if" dans cet exemple de programme. Un retour
chariot n'est pas requis comme séparateur d'instructions et en mettant la lisibilité conditionnelle de l'ensemble du
programme.

4.9 Plus de comparaisons


Les comparatifs du deuxième groupe sont un peu plus impliqués. En commençant par la première comparaison, nous
trouvons un ensemble de conditions plutôt étranges entre parenthèses. Pour comprendre cela, nous devons comprendre
exactement ce qu'est un « vrai » ou un « faux » en langage C. Un « faux » est défini comme une valeur nulle et un « vrai »
est défini comme une valeur non nulle. N'importe quel type de variable entier ou char peut être utilisé pour le résultat d'un
test vrai/faux, ou le résultat peut être un entier ou un caractère implicite.

Regardez la première comparaison du deuxième groupe d’instructions de comparaison. L'expression "r is != s" sera
évaluée comme "vrai" puisque "r" a été défini sur 0,0 ci­dessus, donc le résultat sera une valeur non nulle, probablement
1. Même si les deux variables comparées sont " float", le résultat sera de type "entier". Il n'y a pas de variable explicite à
laquelle elle sera affectée, le résultat de la comparaison est donc un entier implicite. Enfin, le nombre résultant, 1 dans
ce cas, est attribué à la variable entière "x". Si des doubles signes égal étaient utilisés, la valeur fantôme, à savoir 1,
serait comparée à la valeur de "x", mais comme le seul signe égal est utilisé, la valeur 1 est simplement attribuée à "x",
comme si l'énoncé était pas entre parenthèses. Enfin, puisque le résultat de l'affectation entre parenthèses était différent
de zéro, l'expression entière est évaluée comme "vrai" et "z" se voit attribuer la valeur de 1000. Ainsi, nous avons
accompli deux choses dans cette instruction, nous avons attribué "x " une nouvelle valeur, probablement 1, et nous
avons attribué à "z" la valeur 1000. Nous avons abordé beaucoup de choses dans cette déclaration, vous souhaiterez
peut­être la consulter avant de continuer. Les choses importantes à retenir sont les valeurs qui définissent « vrai » et
« faux », et le fait que plusieurs choses peuvent être assignées dans une instruction conditionnelle. La valeur attribuée à
"x" était probablement 1, mais différents compilateurs peuvent attribuer une valeur différente tant qu'elle est différente de
zéro.

Affectation et comparaisons logiques Tutoriel C 4­6


L’exemple
Machine Translated bysuivant
Google devrait vous aider à clarifier certains des éléments ci­dessus dans votre esprit. Dans cet exemple,
"x" reçoit la valeur de "y", et comme le résultat est 11, la condition est non nulle, ce qui est vrai, et la variable "z" se
voit donc attribuer 222.

Le troisième exemple, du deuxième groupe, compare « x » à zéro. Si le résultat est vrai, c'est­à­dire que si « x »
n'est pas nul, alors « z » se voit attribuer la valeur 333, ce qui sera le cas. Le dernier exemple de ce groupe illustre
le même concept, puisque le résultat sera vrai si « x » est différent de zéro. La comparaison à zéro n'est pas
réellement nécessaire et le résultat de la comparaison est vrai. Les troisième et quatrième exemples de ce groupe
sont donc identiques.

4.10 Concepts de comparaison supplémentaires


Le troisième groupe de comparaisons introduira quelques concepts supplémentaires, à savoir le « ET » logique et
le « OU » logique. On attribue la valeur de 77 aux trois variables entières simplement pour repartir avec quelques
valeurs définies. La première comparaison du troisième groupe contient le nouveau contrôle "&&", qui est le "ET"
logique. L'instruction entière se lit comme suit : si "x" est égal à "y" ET si "x" est égal à 77, alors le résultat est "vrai".
Puisque cela est vrai, la variable z est définie comme étant égale à 33.

La comparaison suivante dans ce groupe introduit le "||" opérateur qui est le "OU". L'instruction se lit comme suit : si
"x" est supérieur à "y" OU si "z" est supérieur à 12, alors le résultat est vrai. Puisque « z » est supérieur à 12, peu
importe que « x » soit supérieur à « y » ou non, car une seule des deux conditions doit être vraie pour que le résultat
soit vrai. Le résultat est vrai, donc « z » se verra attribuer la valeur 22.

4.11 Évaluation logique


Lorsqu'une expression composée est évaluée, l'évaluation se déroule de gauche à droite et dès que le résultat est
assuré, l'évaluation s'arrête. À savoir, dans le cas d'une évaluation « ET », lorsqu'un des termes est évalué comme
« faux », l'évaluation est interrompue car des termes vrais supplémentaires ne peuvent jamais faire en sorte que le
résultat devienne « vrai ». Dans le cas d'une évaluation « OU », si l'un des termes s'avère « vrai », l'évaluation
s'arrête car il sera impossible que des termes supplémentaires fassent en sorte que le résultat soit « faux ». Dans le
cas de termes supplémentaires imbriqués, les règles ci­dessus seront appliquées à chacun des niveaux imbriqués.

4.12 Priorité des opérateurs


La question se posera concernant la préséance des opérateurs. Quels opérateurs sont évalués en premier et
lesquels en dernier ? Il existe de nombreuses règles sur ce sujet, que votre compilateur définira complètement, mais
je vous suggère de ne pas vous en préoccuper à ce stade. Utilisez plutôt de nombreuses parenthèses pour
regrouper les variables, les constantes et les opérateurs de manière significative pour vous.
Les parenthèses ont toujours la priorité la plus élevée et supprimeront toute question quant aux opérations qui
seront effectuées en premier dans une instruction particulière.

En passant à l'exemple suivant du groupe trois, nous trouvons trois variables simples utilisées dans la partie
conditionnelle de la comparaison. Puisque les trois sont différents de zéro, tous les trois sont « vrais », et donc le
« ET » des trois variables est vrai, ce qui conduit au résultat « vrai » et « z » se voit attribuer la valeur 11. Notez le
puisque les variables "r", "s" et "t" sont des variables de type "float", elles ne pourraient pas être utilisées de cette
façon, mais elles pourraient chacune être comparées à zéro et le même type d'expression pourrait être utilisé.

En continuant avec le quatrième exemple du troisième groupe, nous trouvons trois instructions d'affectation dans la
partie comparaison de l'instruction « if ». Si vous avez compris la discussion ci­dessus, vous ne devriez avoir aucune
difficulté à comprendre que les trois variables se voient attribuer leurs nouvelles valeurs respectives et que le résultat
des trois est différent de zéro, ce qui conduit à une valeur résultante de « VRAI ».

4­7 Tutoriel C Affectation et comparaisons logiques


Machine Translated by Google
4.13 C'est une astuce, soyez prudent
Le dernier exemple du troisième groupe contient une petite astuce, mais comme nous l'avons abordé ci­dessus,
ce n'est pas nouveau pour vous. Notez que la première partie de la comparaison est évaluée à « FALSE ». Les
parties restantes de la comparaison ne sont pas évaluées, car il s'agit d'un "ET" et elle sera définitivement résolue
comme un "FAUX" car le premier terme est faux. Si le programme dépendait de la valeur de "y" étant fixée à 3
dans la partie suivante de la comparaison, il échouera car l'évaluation cessera suite au "FALSE" trouvé dans le
premier terme. De même, "z" ne sera pas mis à 4 et la variable "r" ne sera pas modifiée.

4.14 Domaines problématiques potentiels

Le dernier groupe de comparaisons illustre trois possibilités pour avoir quelques ennuis. Tous les trois ont pour
résultat commun que « z » ne sera pas défini sur la valeur souhaitée, mais pour des raisons différentes.
Dans le cas du premier, la comparaison est évaluée comme "true", mais le point­virgule suivant les secondes
parenthèses termine la clause "if", et l'instruction d'affectation impliquant "z" est toujours exécutée comme
instruction suivante. Le "if" n'a donc aucun effet à cause du point­virgule mal placé. La deuxième affirmation est
beaucoup plus simple car "x" sera toujours égal à lui­même, donc l'inégalité ne sera jamais vraie et l'énoncé dans
son ensemble ne fera jamais rien, mais constitue un effort inutile. La dernière instruction attribuera toujours 0 à "x"
et la comparaison sera donc toujours "false", n'exécutant jamais la partie conditionnelle de l'instruction "if".

L'instruction conditionnelle est extrêmement importante et doit être parfaitement comprise pour écrire des
programmes C efficaces. Si une partie de cette discussion n'est pas claire dans votre esprit, réétudiez­la jusqu'à
ce que vous soyez sûr de bien la comprendre avant de continuer.

4.15 La partie cryptique de C


Il existe trois constructions utilisées en C qui n'ont aucun sens au premier abord car elles ne sont pas intuitives,
mais elles augmentent considérablement l'efficacité du code compilé et sont largement utilisées par les
programmeurs C expérimentés. Vous devez donc y être exposé et apprendre à les utiliser car ils apparaîtront
dans la plupart, sinon la totalité, des programmes que vous voyez dans les publications.
Chargez et examinez le fichier nommé cryptic.c pour obtenir des exemples des trois nouvelles constructions.
main( )

{ int x = 0,y = 2,z = 1025; flottant a =


0,0,b = 3,14159,c = ­37,234 ;
/* incrémentation */ x = x +
1; x++ ; ++x; z /* Cela incrémente x */
= y+ /* Cela incrémente x */
+; z /* Cela incrémente x */ /* z = 2, y = 3
= ++y; */ /* z = 4, y = 4 */

/* décrémentation */ y = y ­
1; /* Cela décrémente y */
/* Cela décrémente y */ y­­;
= y­­; /* Cela décrémente y */ ­­y; y = 3 ; z
z = ­­y;
/* z = 3, y = 2 */ /* z = 1, y =
1 */

/* opération arithmétique */

Affectation et comparaisons logiques Tutoriel C 4­8


une by
Machine Translated = une + 12 ;
Google /* Cela ajoute 12 à un */
une += 12 ; /* Cela ajoute 12 de plus à un */
une *= 3,2 ; /* Cela multiplie a par 3,2 */
une ­= b ; /* Ceci soustrait b de a */
une /= 10,0 ; /* Cela divise a par 10,0 */

/* expression conditionnelle */
une = (b >= 3,0 ? 2,0 ; 10,5 ); /*Cette expression /* Et cette */
si (b >= 3,0) a = 2,0 ; expression */
sinon a = /* sont identiques, les deux */
10,5 ; /* provoquera la même chose */
/* résultat. */
c = (une > b?une:b); c = (a /* c aura le maximum de a ou b */
> b?b:b); /* c aura le min de a ou b */
}

Dans ce programme, certaines variables sont définies et initialisées dans les mêmes instructions pour être utilisées ci­dessous.
Le premier ne devrait pas vous surprendre. Les deux instructions suivantes ajoutent également un à la valeur
de "x", mais il n'est pas intuitif que ce soit ce qui se passe. C'est simplement une définition que cela est vrai.
Ainsi, par définition du langage C, un double signe plus avant ou après une variable
incrémente cette variable de 1. De plus, si les signes plus sont avant la variable, la variable
est incrémenté avant d'être utilisé, et si les signes plus sont après la variable, la variable est utilisée,
puis incrémenté. Dans l'instruction suivante, la valeur de "y" est affectée à la variable "z", puis
"y" est incrémenté car les signes plus se trouvent après la variable "y". Dans la dernière déclaration du
incrémentant un groupe d'exemples d'instructions, la valeur de "y" est incrémentée puis sa valeur est
affecté à la variable "z".

Le groupe d'instructions suivant illustre la décrémentation d'une variable de un. La définition fonctionne
exactement de la même manière pour décrémenter que pour incrémenter. Si les signes moins sont avant
la variable, la variable est décrémentée, puis utilisée, et si les signes moins sont après la variable,
la variable est utilisée, puis décrémentée.

4.16 L'opérateur arithmétique énigmatique


Un autre opérateur utile mais énigmatique est l’opérateur arithmétique. Cet opérateur est utilisé pour modifier
n'importe quelle variable par une valeur constante. La première déclaration du groupe des « opérateurs arithmétiques » de
les instructions ajoutent simplement 12 à la valeur de la variable "a". La deuxième déclaration fait la même chose,
mais encore une fois, il n’est pas intuitif qu’ils soient identiques. N'importe laquelle des quatre fonctions de base de
l'arithmétique, "+", "­", "x" ou "/", peuvent être traités de cette manière, en mettant la fonction souhaitée dans
devant le signe égal et en éliminant la deuxième référence au nom de la variable. Ça devrait être
a noté que l'expression à droite de l'opérateur arithmétique peut être n'importe quelle expression valide,
les exemples restent simples pour votre introduction à ce nouvel opérateur.

Tout comme les opérateurs d'incrémentation et de décrémentation, l'opérateur arithmétique est largement utilisé
par des programmeurs C expérimentés et cela vous rapporterait beaucoup de le comprendre.

4.17 L'expression conditionnelle


L’expression conditionnelle est tout aussi énigmatique que les deux dernières, mais encore une fois elle peut être très utile
donc ça vous paierait de le comprendre. Il se compose de trois expressions entre parenthèses séparées
par un point d'interrogation et deux points. L'expression précédant le point d'interrogation est évaluée comme suit :
déterminer si ce n’est pas vrai, l’expression qui suit les deux points est évaluée. Le résultat du
l’évaluation est utilisée pour le devoir. Le résultat final est identique à celui d'une instruction "if"
avec une clause "sinon". Ceci est illustré par le deuxième exemple de ce groupe. Le conditionnel
L'expression présente l'avantage supplémentaire d'un code plus compact qui sera compilé sur moins de machines.
instructions dans le programme final.

4­9 Tutoriel C Affectation et comparaisons logiques


Machine Translated
Les deuxby Google
dernières lignes de cet exemple de programme sont données pour illustrer une manière très compacte d'attribuer
la plus grande des deux variables "a" ou "b" à "c", et d'attribuer la plus petite des deux mêmes variables
à "c". Remarquez à quel point le code est efficace dans ces deux exemples.

4.18 Être énigmatique ou ne pas être énigmatique


Plusieurs étudiants en C ont déclaré qu'ils n'aimaient pas ces trois constructions énigmatiques et que
ils ne les utiliseraient tout simplement jamais. Ce serait bien s'ils n'avaient jamais à lire celui de quelqu'un d'autre.
programme, ou utiliser tout autre programme dans le leur. J'ai trouvé de nombreuses fonctions que je souhaitais
à utiliser dans un programme mais nécessitait une petite modification pour l'utiliser, ce qui m'obligeait à comprendre
le code d'une autre personne. Il serait donc à votre avantage d'apprendre ces nouvelles constructions,
et utilisez­les. Ils seront utilisés dans la suite de ce tutoriel, vous serez donc constamment
qui leur sont exposés.

Ce chapitre a été long, mais il contenait des éléments importants pour vous aider à démarrer en utilisant C.
Dans le prochain chapitre, nous passerons aux éléments constitutifs du C, les fonctions. À ce stade, vous
vous disposerez de suffisamment de matériel de base pour vous permettre de commencer à écrire des programmes significatifs.

4.19 Exercices de programmation


1. Écrivez un programme qui comptera de 1 à 12 et imprimerez le compte et son carré pour chaque
compter.
1
1 4
9
2 3 etc.

2. Écrivez un programme qui compte de 1 à 12 et imprime le décompte et son inversion à 5 décimales


places pour chaque chef d'accusation. Cela nécessitera un nombre à virgule flottante.
1 1,00000
2,50000
3.33333
4,25000
etc.

3. Écrivez un programme qui comptera de 1 à 100 et imprimera uniquement les valeurs comprises entre 32 et 100.
39, un à une ligne.

Affectation et comparaisons logiques Tutoriel C 4­10


Machine Translated by Google
5
Fonctions et variables

5.1 Notre première fonction définie par l'utilisateur

Chargez et examinez le fichier sumsqles.c pour un exemple de programme C avec des fonctions.
somme entière ; /* Ceci est une variable globale */
main( ) { int

index ;
entête(); pour /* Ceci appelle la fonction nommée header */
(index = 1;index <= 7;index++) carré(index); /* Ceci appelle
la fonction carréeending(); */
/* Ceci appelle la fonction de fin */
}

entête() { /* C'est la fonction nommée header */

somme = 0 ; /* initialise la variable "sum" */ printf("Ceci est l'en­tête du programme carré\n\n");

carré(nombre) nombre /* C'est la fonction carrée */


int ; {

int numq;
numsq = nombre * nombre ; /* Cela produit le carré */ sum += numsq; printf("Le carré de %d est
%d\n",number,numsq);

ending() /* C'est la fonction de fin { */

printf("\nLa somme des carrés est %d\n",somme);


}

En fait, ce n'est pas la première fonction que nous rencontrons, car le programme "principal" que nous
utilisons depuis le début est techniquement une fonction, tout comme la fonction "printf". La fonction
"printf" est une fonction de bibliothèque fournie avec votre compilateur.
Notez la partie exécutable de ce programme. Il commence par une ligne qui dit simplement "header()',
qui est le moyen d'appeler n'importe quelle fonction. Les parenthèses sont obligatoires car le compilateur
C les utilise pour déterminer qu'il s'agit d'un appel de fonction et pas simplement d'une variable mal
placée. Lorsque le Le programme arrive à cette ligne de code, la fonction nommée "header" est appelée,
ses instructions sont exécutées, et le contrôle revient à l'instruction suivant cet appel. En continuant on
arrive à une boucle "for" qui sera exécutée 7 fois et qui appelle une autre fonction nommée "square" à
chaque passage dans la boucle, et finalement une fonction nommée "ending" sera appelée et exécutée.
Pour l'instant ignorez "l'index" entre parenthèses de l'appel à "square". Nous avons vu que ce programme
appelle donc un en­tête, 7 appels carrés et une fin. Il faut maintenant définir les fonctions.

5­1 Tutoriel C Fonctions et variables


Machine Translated by Google
5.2 Définir les fonctions
Après le programme principal, vous verrez un autre programme qui suit toutes les règles énoncées jusqu'à présent
pour un programme "principal", sauf qu'il est nommé "header()". C'est la fonction qui est appelée depuis le programme
principal. Chacune de ces instructions est exécutée et lorsqu'elles sont toutes terminées, le contrôle revient au
programme principal.

La première instruction définit la variable « somme » égale à zéro car nous l'utiliserons pour accumuler une somme
de carrés. Étant donné que la variable « somme » est définie comme une variable de type entier avant le programme
principal, elle peut être utilisée dans l'une des fonctions suivantes. C'est ce qu'on appelle une variable "globale", et
sa portée s'étend à l'ensemble du programme et à toutes les fonctions. Nous en dirons davantage sur la portée des
variables à la fin de ce chapitre. L'instruction suivante génère un message d'en­tête sur le moniteur. Le contrôle du
programme revient ensuite aux programmes principaux au cas où il n'y aurait pas d'instructions supplémentaires à
exécuter dans cette fonction.

Il devrait être clair pour vous que les deux lignes exécutables de cette fonction pourraient être déplacées vers le
programme principal, remplaçant l'appel d'en­tête, et le programme ferait exactement la même chose que ce qu'il fait
actuellement. Cela ne minimise pas la valeur des fonctions, cela illustre simplement que le fonctionnement de cette
fonction simple est d'une manière simple. Vous trouverez des fonctions très utiles dans la programmation C.

5.3 Passer une valeur à une fonction


En revenant au programme principal, et à la boucle "for" en particulier, on retrouve la nouvelle construction de la fin
de la dernière leçon utilisée dans la dernière partie de la boucle for, à savoir le "index++". Vous devriez vous habituer
à voir cela, car vous le verrez souvent dans les programmes C.

Dans l'appel à la fonction "square", nous avons une fonctionnalité ajoutée, à savoir la variable "index" entre
parenthèses. Ceci indique au compilateur que lorsque vous accédez à la fonction, vous souhaitez emporter la valeur
de l'index à utiliser dans l'exécution de la fonction. En regardant la fonction "carré", nous constatons qu'un autre nom
de variable est placé entre parenthèses, à savoir la variable "nombre". C'est le nom que l'on préfère appeler la
variable passée à la fonction lorsque l'on est dans la fonction. Nous pouvons l'appeler comme nous le souhaitons à
condition qu'il respecte les règles de dénomination d'un identifiant. Puisque la fonction doit connaître le type de la
variable, elle est définie après le nom de la fonction mais avant l'accolade ouvrante de la fonction elle­même. Ainsi,
la ligne contenant "int number;" indique à la fonction que la valeur qui lui est transmise sera une variable de type
entier. Une fois tout cela réglé, nous avons maintenant la valeur de l'index du programme principal transmise à la
fonction "square", mais renommée "number", et disponible pour une utilisation dans la fonction.

Après l'accolade ouvrante de la fonction, nous définissons une autre variable "numsq" à utiliser uniquement dans la
fonction elle­même (nous en parlerons plus tard) et procédons aux calculs requis.
Nous définissons "numsq" égal au carré du nombre, puis ajoutons numsq au total actuel stocké dans "sum". N'oubliez
pas que "sum += numsq" est identique à "sum = sum + numsq" de la dernière leçon. Nous imprimons le nombre et
son carré, et revenons au programme principal.

5.4 En savoir plus sur la transmission d'une valeur à une fonction


Lorsque nous avons transmis la valeur de "index" à la fonction, il s'est produit un peu plus de choses qu'il n'y paraît.
Nous n’avons pas réellement transmis la valeur de l’index à la fonction, nous avons en fait transmis une copie de la
valeur. De cette manière, la valeur originale est protégée contre toute corruption accidentelle par une fonction appelée.
Nous aurions pu modifier la variable "numéro" comme nous le souhaitions dans la fonction "carré", et lorsque nous
reviendrons au programme principal, "index" n'aurait pas été modifié. Nous protégeons ainsi la valeur d'une variable
du programme principal contre une corruption accidentelle, mais nous ne pouvons pas renvoyer une valeur au
programme principal à partir d'une fonction utilisant cette technique. Nous trouverons une méthode bien définie pour
renvoyer des valeurs au programme principal ou à toute fonction appelante lorsque

Fonctions et variables Tutoriel C 5­2


nous arrivons
Machine Translated aux tableaux et à une autre méthode lorsque nous arrivons aux pointeurs. Jusque­là, la seule
by Google
façon de communiquer avec la fonction appelante sera avec des variables globales. Nous avons déjà fait
allusion aux variables globales ci­dessus et nous en discuterons en détail plus loin dans ce chapitre.
En continuant dans le programme principal, nous arrivons au dernier appel de fonction, l'appel à "ending". Cet
appel appelle simplement la dernière fonction pour laquelle aucune variable locale n'est définie. Il imprime un
message contenant la valeur « somme » pour terminer le programme. Le programme se termine en revenant
au programme principal et en ne trouvant rien d'autre à faire. Compilez et exécutez ce programme et observez
le résultat.

5.5 Maintenant, il faut avouer un petit mensonge

Je vous ai dit il y a peu de temps que la seule manière de récupérer une valeur dans le programme principal
était d'utiliser une variable globale, mais il existe une autre méthode dont nous discuterons après avoir chargé
et affiché le fichier nommé squares.c.

Dans ce fichier nous verrons qu'il est simple de renvoyer une seule valeur d'une fonction appelée à la fonction
appelante. Mais encore une fois, il est vrai que pour renvoyer plus d’une valeur, il faudra étudier soit des
tableaux, soit des pointeurs.
main( ) {int /* Ceci est le programme principal */

x,y;
pour(x = 0;x < 7;x++) { y = carré(x); /
* va récupérer la valeur de x*x printf("Le carré de %d est %d\n",x,y); */

pour (x = 0;x <= 7;++x)


printf("La valeur de %d est %d\n",x,squ(x));
}

carré(dans) /* fonction pour obtenir la valeur de au carré */


int dans;

{int carré ;
carré = po * po ;
retour(carré); /* Ceci définit squ() = square */
}

Dans le programme principal, nous définissons deux entiers et commençons une boucle "for" qui sera exécutée
8 fois. La première instruction de la boucle for est "y = squ(x);", qui est une construction nouvelle et plutôt
étrange. D'après l'expérience passée, nous ne devrions avoir aucune difficulté à comprendre que la partie
"squ(x)" de l'instruction est un appel à la fonction "squ" prenant la valeur de "x" comme variable. En regardant
la fonction elle­même, nous constatons que la fonction préfère appeler la variable "in" et elle met au carré la
valeur de "in" et appelle le résultat "square". Enfin, un nouveau type d'instruction apparaît, l'instruction "retour".
La valeur entre parenthèses est attribuée à la fonction elle­même et est renvoyée sous forme de valeur utilisable
dans le programme principal. Ainsi, l'appel de fonction "squ(x)" se voit attribuer la valeur du carré et est renvoyé
au programme principal de telle sorte que "y" soit alors égal à cette valeur. Si "x" se voyait donc attribuer la
valeur 4 avant cet appel, "y" serait alors mis à 16 suite à cette ligne de code.

Une autre façon de voir cela est de considérer le regroupement de caractères "squ(x)" comme une autre
variable avec une valeur qui est le carré de "x", et cette nouvelle variable peut être utilisée partout où il est légal
d'utiliser une variable. de son genre. Les valeurs de « x » et « y » sont ensuite imprimées.
Pour illustrer que le regroupement de « squ(x) » peut être considéré comme simplement une autre variable,
une autre boucle « for » est introduite dans laquelle l'appel de fonction est placé dans l'instruction print plutôt
que de l'attribuer à une nouvelle variable.

5­3 Tutoriel C Fonctions et variables


Un dernier
Machine Translated by point
Googledoit être souligné, le type de variable renvoyé doit être défini afin de donner un sens aux données,
mais le compilateur utilisera par défaut le type entier si aucun n'est spécifié. Si un autre type est souhaité, il doit
être explicitement défini. Comment procéder sera démontré dans le prochain exemple de programme.

Compilez et exécutez ce programme.

5.6 Fonctions à virgule flottante


Chargez le programme floatsq.c pour un exemple de fonction avec un retour de type virgule flottante.
flotter z ; /* Ceci est une variable globale */
main( ) { int

index ; float
x,y,sqr(),glsqr();
pour (index = 0;index <= 7;index++){
x = indice ; /* convertir int en float */ y = sqr(x); /* carré x à une
variable à virgule flottante */ printf("Le carré de %d est %10.4f\n",index,y);

pour (index = 0; index <= 7;index++) { z = index; y = glsqr();


printf("Le carré
de %d est
%10.4f\n",index,y);
}
}

float sqr(inval) /* place un float, renvoie un float float inval; { carré flottant ; */

carré = inval * inval ; retour(carré);

float glsql() /* place un flottant, renvoie un flottant */ {

retour(z*z);
}

Cela commence par définir une variable globale à virgule flottante que nous utiliserons plus tard. Ensuite, dans la
partie "principale" du programme, un entier est défini, suivi de deux variables à virgule flottante, puis de deux
définitions étranges. Les expressions "sqr()" et "glsqr()" ressemblent à des appels de fonction et elles le sont. C'est
la manière appropriée en C de définir qu'une fonction renverra une valeur qui n'est pas du type "int", mais d'un
autre type, dans ce cas "float". Cela indique au compilateur que lorsqu'une valeur est renvoyée par l'une ou l'autre
de ces deux fonctions, elle sera de type "float".

Référez­vous maintenant à la fonction « sqr » près du centre de la liste et vous verrez que le nom de la fonction
est précédé du nom « float ». Ceci indique au compilateur que cette fonction renverra une valeur de type "float" à
tout programme qui l'appelle. La fonction est désormais compatible avec son appel. La ligne qui suit le nom de la
fonction contient "float inval;", qui indique au compilateur que la variable passée à cette fonction depuis le
programme appelant sera de type "float".

La fonction suivante, à savoir "glsqlr", renverra également une variable de type "float", mais elle utilise une variable
globale pour la saisie. Il effectue également la mise au carré dans l'instruction return et n'a donc pas besoin de
définir une variable distincte pour stocker le produit.

La structure globale de ce programme ne devrait poser aucun problème et ne sera pas discutée plus en détail.
Comme c'est l'habitude avec tous les exemples de programmes, compilez et exécutez ce programme.

Fonctions et variables Tutoriel C 5­4


Il y aura by
Machine Translated desGoogle
moments où vous aurez besoin d’une fonction pour renvoyer un pointeur à la suite d’un calcul. Il
existe un moyen de définir une fonction pour qu'elle fasse exactement cela. Nous n'avons pas encore étudié les
pointeurs, mais nous le ferons bientôt. Ceci n'est qu'un bref aperçu des choses à venir.

5.7 Portée des variables


Chargez le programme suivant, scope.c et affichez­le pour une discussion sur la portée des variables dans un
programme.
nombre entier ; /* Ceci est une variable globale */
main( )

{ registre int index ; /* Cette variable est disponible uniquement dans main */
tête1();
tête2();
tête3();
/* boucle "for" principale de ce programme */ for (index = 8;index >
0;index­­) {
des trucs int; /* Cette variable n'est disponible qu'entre ces accolades */ for (stuff = 0;stuff <= 6;stuff++)
printf("%d",stuff); printf(" l'index est maintenant %d\n",
index);

}
}

compteur int ; /* Ceci est disponible à partir de ce moment */


tête1() {

indice int ; /* Cette variable est disponible uniquement dans head1 */


indice = 23 ;
printf("La valeur de l'en­tête1 est %d\n",index);
}

head2()

{ nombre int ; /* Cette variable est disponible uniquement dans head2 */ /* et elle déplace le
global du même nom */
compte = 53 ;
printf("La valeur de l'en­tête2 est %d\n",count); compteur = 77 ;

tête3() {

printf("La valeur de l'en­tête3 est %d\n"counter);


}

La première variable définie est une variable globale "count" qui est disponible pour n'importe quelle fonction du
programme puisqu'elle est définie avant n'importe laquelle des fonctions. De plus, il est toujours disponible car
il ne va pas et ne vient pas au fur et à mesure de l'exécution du programme. (Cela aura du sens sous peu.) Plus
bas dans le programme, une autre variable globale nommée "compteur" est définie qui est également globale
mais n'est pas disponible pour le programme principal puisqu'elle est définie après le programme principal. Une
variable globale est toute variable définie en dehors de toute fonction. Notez que ces deux variables sont parfois
appelées variables externes car elles sont externes à toute fonction.
Revenez au programme principal et vous verrez la variable "index" définie comme un entier. Ignorez le mot
« s'inscrire » pour le moment. Cette variable n'est disponible que dans le programme principal car c'est là qu'elle
est définie. De plus, il s'agit d'une variable "automatique", ce qui signifie qu'elle n'existe que lorsque la fonction
dans laquelle elle est contenue est invoquée, et cesse d'exister lorsque la fonction est terminée. Cela ne veut
vraiment rien dire ici car le programme principal est toujours en fonctionnement, même lorsqu'il donne le contrôle
à une autre fonction. Un autre entier est défini

5­5 Tutoriel C Fonctions et variables


entre les by
Machine Translated accolades
Google"pour", à savoir "trucs". Toute paire d'accolades peut contenir une définition de variable qui sera
valide et disponible uniquement pendant que le programme exécute des instructions entre ces accolades. La variable
sera une variable "automatique" et cessera d'exister lorsque l'exécution quittera les accolades. Ceci est pratique à
utiliser pour un compteur de boucles ou une autre variable très localisée.

5.8 En savoir plus sur les variables "automatiques"

Observez la fonction nommée "head1". Il contient une variable nommée "index", qui n'a rien à voir avec "l'index" du
programme principal, sauf que les deux sont des variables automatiques. Lorsque le programme n'exécute pas
réellement d'instructions dans cette fonction, cette variable nommée "index" n'existe même pas. Lorsque "head1" est
appelé, les variables sont générées et lorsque "head1" termine sa tâche, la variable "index" est complètement éliminée
de l'existence. Gardez cependant à l’esprit que cela n’affecte pas la variable du même nom dans le programme
principal, puisqu’il s’agit d’une entité complètement distincte.

Les variables automatiques sont donc automatiquement générées et supprimées en cas de besoin. La chose importante
à retenir est que d'un appel à une fonction au prochain appel, la valeur d'une variable automatique n'est pas conservée
et doit donc être réinitialisée.

5.9 Que sont les variables statiques ?

Un type de variable supplémentaire doit être mentionné à ce stade, la variable « statique ». En plaçant le mot réservé
"static" devant une déclaration de variable dans une fonction, la ou les variables de la déclaration sont des variables
statiques et resteront en existence d'un appel à l'autre de la fonction particulière.

En plaçant le même mot réservé devant une variable externe, en dehors de toute fonction, cela rend la variable privée
et non accessible pour une utilisation dans un autre fichier. Cela implique qu'il est possible de faire référence à des
variables externes dans d'autres fichiers compilés séparément, et c'est vrai. Des exemples de cette utilisation seront
donnés au chapitre 14 de ce tutoriel.

5.10 Utiliser à nouveau le même nom


Reportez­vous à la fonction nommée "head2". Il contient une autre définition de la variable nommée "count". Même si
"count" a déjà été défini comme variable globale, il est parfaitement possible de réutiliser le nom dans cette fonction. Il
s'agit d'une variable complètement nouvelle qui n'a rien à voir avec la variable globale du même nom et qui rend la
variable globale indisponible dans cette fonction. Cela vous permet d'écrire des programmes en utilisant des fonctions
existantes sans vous soucier des variables qui interagissent avec les fonctions.

5.11 Qu'est­ce qu'une variable de registre ?


Maintenant, pour tenir une promesse faite plus tôt sur ce qu'est une variable de registre. Un ordinateur peut conserver
des données dans un registre ou dans une mémoire. Un registre fonctionne beaucoup plus rapidement que la mémoire,
mais il existe très peu de registres disponibles pour le programmeur. Si certaines variables sont largement utilisées
dans un programme, vous pouvez désigner que ces variables doivent être stockées dans un registre si possible afin
d'accélérer l'exécution du programme. En fonction de l'ordinateur et du compilateur, un petit nombre de variables de
registre peut être autorisé et constitue une fonctionnalité souhaitée.
Vérifiez la documentation de votre compilateur pour connaître la disponibilité de cette fonctionnalité et le nombre de
variables de registre. La plupart des compilateurs qui n'ont pas de variables de registre disponibles ignoreront
simplement le mot "registre" et fonctionneront normalement, gardant toutes les variables en mémoire.

Fonctions et variables Tutoriel C 5­6


Les variables
Machine Translated de registre ne peuvent être utilisées qu'avec des variables de type entier et caractère. Cela peut ou non
by Google
inclure certaines des autres variables de type entier telles que non signé, long ou court.
Consultez la documentation de votre compilateur.

Les variables de registre sont autorisées dans HiTech C, avec jusqu'à quatre variables de registre sans pointeur (dans 68
000 registres D4 à D7) et jusqu'à trois variables de registre avec pointeur (dans A3 à A5). Cette utilisation n'est pas en
conflit avec l'utilisation 1616/OS de D0 à D2 et A0 à A2). Comme les compilateurs MS­DOS n'autorisent généralement
que deux variables de registre, de nombreux programmeurs n'utilisent pas beaucoup les variables de registre, vous pouvez
donc souvent gagner un peu plus de vitesse lors de la conversion de programmes en utilisant plus largement les variables
de registre (le compilateur ignorera la demande de variable de registre si aucune variable de registre n'est utilisée). des
registres sont disponibles et traitent la variable comme une variable ordinaire).

5.12 Où définir les variables ?


Passons maintenant à une précision sur une règle générale énoncée plus tôt. Lorsque des variables sont apportées à une
fonction comme arguments de la fonction, elles sont définies immédiatement après le nom de la fonction et avant
l'accolade ouvrante du programme. Les autres variables utilisées dans la fonction sont définies au début de la fonction,
immédiatement après l'accolade ouvrante de la fonction et avant toute instruction exécutable.

5.13 Bibliothèques de fonctions standard


Chaque compilateur est livré avec des fonctions standard prédéfinies qui sont disponibles pour votre usage. Il s'agit
principalement de fonctions d'entrée/sortie, de fonctions de manipulation de caractères et de chaînes et de fonctions
mathématiques. Nous aborderons la plupart d’entre eux dans les chapitres suivants.

De plus, la plupart des compilateurs disposent de fonctions supplémentaires prédéfinies qui ne sont pas standards mais
permettent au programmeur de tirer le meilleur parti de son ordinateur particulier. Dans le cas des IBM­PC et compatibles,
la plupart de ces fonctions permettent au programmeur d'utiliser les services BIOS disponibles dans le système
d'exploitation, ou d'écrire directement sur le moniteur vidéo ou à n'importe quel endroit de la mémoire.
Les équivalents Applix sont inclus dans les fichiers d'en­tête mentionnés ailleurs. Ceux­ci ne seront pas abordés en détail
car vous pourrez étudier par vous­même les aspects uniques de votre compilateur. Beaucoup de ces types de fonctions
sont utilisés dans les versions IBM des exemples de programmes du chapitre 14.

5.14 Qu'est­ce que la récursivité ?

La récursion est une autre de ces techniques de programmation qui semble très intimidante la première fois que vous la
rencontrez, mais si vous chargez et affichez l'exemple de programme nommé recurson.c, nous enlèverons tout le mystère.
C'est probablement le programme récursif le plus simple qu'il soit possible d'écrire et c'est donc un programme stupide
dans la pratique, mais à des fins d'illustration, il est excellent.

main( )

{ int index ;
indice = 8 ;
count_dn(index);
}

count_dn(count) int
compte ; {

compter­­;
printf("La valeur du compte est %d\n",count); si (compte > 0)

5­7 Tutoriel C Fonctions et variables


Machine Translated bycount_dn(compte);
Google
printf("Maintenant, le compte est %d\n",count);
}

La récursivité n'est rien de plus qu'une fonction qui s'appelle elle­même. Il est donc dans une boucle qui doit avoir un
moyen de se terminer. Dans le programme sur votre moniteur, la variable "index" est définie sur 8 et est utilisée comme
argument de la fonction "count_dn". La fonction décrémente simplement la variable, l'imprime dans un message, et si
la variable n'est pas nulle, elle s'appelle elle­même, où elle la décrémente à nouveau, l'imprime, etc. etc. etc. Enfin, la
variable atteindra zéro, et la fonction ne s'appellera plus. Au lieu de cela, il reviendra à l'heure précédente où il s'est
appelé, et reviendra à nouveau, jusqu'à ce qu'il revienne finalement au programme principal et revienne au DOS.

Pour des raisons de compréhension, vous pouvez le considérer comme ayant 8 copies de la fonction "count_dn"
disponibles et il les a simplement toutes appelées une à la fois, en gardant une trace de la copie dans laquelle elle se
trouvait à un moment donné. Ce n’est pas ce qui s’est réellement passé, mais c’est une illustration raisonnable pour
vous permettre de commencer à comprendre ce qu’il faisait réellement.

5.15 Qu'a­t­il fait ?


Une meilleure explication de ce qui s’est réellement passé s’impose. Lorsque vous avez appelé la fonction depuis elle­
même, elle a stocké toutes les variables et tous les indicateurs internes dont elle a besoin pour terminer la fonction
dans un bloc quelque part. La prochaine fois qu'il s'est appelé, il a fait la même chose, créant et stockant un autre bloc
de tout ce dont il avait besoin pour terminer cet appel de fonction. Il a continué à créer ces blocs et à les stocker jusqu'à
ce qu'il atteigne la dernière fonction lorsqu'il a commencé à récupérer les blocs de données et à les utiliser pour
terminer chaque appel de fonction. Les blocs étaient stockés sur une partie interne de l’ordinateur appelée « pile ». Il
s'agit d'une partie de la mémoire soigneusement organisée pour stocker les données comme décrit ci­dessus. Il n'entre
pas dans le cadre de ce didacticiel de décrire la pile en détail, mais il serait bon pour votre expérience en programmation
de lire des documents décrivant la pile. Une pile est utilisée dans presque tous les ordinateurs modernes pour les
tâches ménagères internes.

En utilisant la récursion, vous souhaiterez peut­être écrire un programme avec une récursion indirecte par opposition à
la récursion directe décrite ci­dessus. La récursivité indirecte se produirait lorsqu'une fonction "A" appelle la fonction
"B", qui à son tour appelle "A", etc. Ceci est tout à fait permis, le système se chargera de mettre les éléments
nécessaires sur la pile et de les récupérer en cas de besoin. encore. Il n'y a aucune raison pour que trois fonctions ne
s'appellent pas en cercle, ou quatre, ou cinq, etc. Le compilateur C s'occupera de tous les détails pour vous.

Ce que vous devez retenir à propos de la récursivité, c'est qu'à un moment donné, quelque chose doit aller à zéro ou
atteindre un point prédéfini pour terminer la boucle. Sinon, vous aurez une boucle infinie et la pile se remplira et
débordera, vous donnant une erreur et arrêtant le programme assez brusquement.

5.16 Un autre exemple de récursion


Le programme nommé reverse.c est un autre exemple de récursion, alors chargez­le et affichez­le sur votre écran. Ce
programme est similaire au précédent sauf qu'il utilise un tableau de caractères.

main( )

{ char line_of_char[80]; indice


int = 0 ;
strcpy(line_of_char," ceci est une chaîne.\n"); /* l'espace de début
dans cette */ /* chaîne est requis donc le */ /*
le dernier caractère "t" dans */ /* "this" est
imprimé lorsque */ /* la chaîne est imprimée
*/ /* à l'envers car l'index */ /* est incrémenté
*/

Fonctions et variables Tutoriel C 5­8


/* à by
Machine Translated 1 avant l'instruction */ /* printf pour */ /*
Google
imprimer la ligne en arrière­ */ /* wards */
forward_and_backwards(line_of_char,index);

} forward_and_backwards(line_of_char,index) char
line_of_char[]; indice int ; {

if (line_of_char[index])
{ printf("%c",line_of_char[index]); indice++;

forward_and_backwards(line_of_char,index);

} printf("%c",line_of_char[index]);
}

Chaque appel successif à la fonction nommée "forward_and_backward" provoque l'impression d'un caractère
du message. De plus, chaque fois que la fonction se termine, l'un des caractères est à nouveau imprimé,
cette fois à l'envers à mesure que la chaîne d'appels de fonction récursifs est retracée.
Ne vous inquiétez pas du tableau de caractères défini à la ligne 3 ou des autres nouveautés présentées ici.
Après avoir terminé le chapitre 7 de ce didacticiel, ce programme prendra tout son sens. Il a été estimé qu'il
était important d'introduire un deuxième exemple de récursivité, c'est pourquoi ce fichier est inclus ici.
Une fonctionnalité supplémentaire est intégrée à ce programme dans la version IBM PC. Si vous observez
les deux appels à la fonction et la fonction elle­même, vous verrez que le nom de la fonction est orthographié
de trois manières différentes dans les derniers caractères de la version IBM d'origine. Le compilateur IBM ne
se soucie pas de la façon dont ils sont orthographiés car il n'utilise que les 8 premiers caractères du nom de
la fonction. En ce qui le concerne, la fonction est nommée "forward_". Les caractères restants sont simplement
ignorés. Si votre compilateur utilise plus de 8 caractères comme étant significatifs, comme le fait Hi­Tech,
vous devrez modifier deux des noms afin que les trois noms soient identiques, comme nous l'avons fait.
Compilez et exécutez ce programme et observez les résultats.

5.17 Exercices de programmation


1. Réécrivez tempconv.c, à partir d'un chapitre précédent, et déplacez le calcul de la température
vers une fonction.
2. Écrivez un programme qui écrit votre nom sur le moniteur 10 fois en appelant une fonction pour
effectuer l'écriture. Déplacez la fonction appelée avant la fonction "principale" pour voir si votre compilateur le
permet.

5­9 Tutoriel C Fonctions et variables


Machine Translated by Google
6
Définitions et macros

6.1 Les définitions et les macros sont des aides à la programmation claire
Chargez et affichez le fichier nommé définir.c pour un premier aperçu de certaines définitions et macros.
#define START 0 /* Point de départ de la boucle */ #define ENDING 9 /* Point de fin de la
boucle */ #define MAX(A,B) ((A)>(B)?(A):(B)) / * Définition de macro maximale */ #define
MIN(A,B) ((A)>(B)?(B):(A)) /* Définition de macro minimale */

main( ) { int

index,mn,mx; nombre entier =


pour (index = DÉBUT;index <= ENDING;index++) {


mx = MAX(index, nombre); mn = MIN(index,
nombre); printf("Max est %d et min est
%d\n",mx,mn);
}
}

Notez les quatre premières lignes du programme commençant chacune par le mot "#define". C’est ainsi que toutes les
définitions et macros sont définies. Avant le début de la compilation proprement dite, le compilateur passe par une
passe de préprocesseur pour résoudre toutes les définitions. Dans le cas présent, il trouvera chaque endroit du
programme où se trouve la combinaison "START" et il la remplacera simplement par le 0 puisque telle est la définition.
Le compilateur lui­même ne verra jamais le mot "START", donc en ce qui concerne le compilateur, les zéros étaient
toujours là. Il devrait être clair pour vous maintenant que mettre le mot "START" dans votre programme au lieu du
chiffre 0 n'est qu'une commodité pour vous et agit en fait comme un commentaire puisque le mot "START" vous aide
à comprendre à quoi sert le zéro. pour.

Dans le cas d'un très petit programme, comme celui que vous avez devant vous, peu importe ce que vous utilisez. Si
toutefois vous aviez devant vous un programme de 2000 lignes avec 27 références au START, ce serait une tout autre
affaire. Si vous vouliez changer tous les STARTS du programme par un nouveau numéro, il serait simple de changer
celui #define, mais difficile, et peut­être désastreux si vous manquiez une ou deux des références.

De la même manière, le préprocesseur trouvera toutes les occurrences du mot "ENDING" et les changera en 9, puis
le compilateur fonctionnera sur le fichier modifié sans savoir que "ENDING" a jamais existé.

C'est une pratique assez courante en programmation C d'utiliser toutes les lettres majuscules pour une constante
symbolique telle que "START" et "ENDING" et d'utiliser toutes les lettres minuscules pour les noms de variables. Vous
pouvez utiliser n’importe quelle méthode, car c’est avant tout une question de goût personnel.

6.2 Est­ce vraiment utile ?


Lorsque nous arriverons aux chapitres traitant des entrées et des sorties, nous aurons besoin d'un indicateur pour
nous indiquer quand nous atteignons la fin du fichier d'entrée. Étant donné que différents compilateurs utilisent
différentes valeurs numériques pour cela, bien que la plupart utilisent soit un zéro, soit un moins 1, nous écrirons le
programme avec un "define" pour définir l'EOF (fin de fichier) utilisé par notre compilateur particulier. Si ultérieurement
nous passons à un nouveau compilateur, il suffit de changer celui­ci "define" pour réparer l'ensemble du programme.
La fin de ligne est un autre indicateur qui n’est pas universel. Cela aura plus de sens lorsque nous aborderons les
chapitres sur les entrées et les sorties.

Définitions et macros Tutoriel C 6­1


Machine Translated by Google
6.3 Qu'est­ce qu'une macro ?

Une macro n'est rien de plus qu'une autre définition, mais comme elle est capable au moins de sembler effectuer
certaines décisions logiques ou certaines fonctions mathématiques, elle a un nom unique. Considérez la troisième
ligne du programme sur votre écran pour un exemple de macro. Dans ce cas, chaque fois que le préprocesseur
trouve le mot « MAX » suivi d'un groupe entre parenthèses, il s'attend à trouver deux termes entre parenthèses
et effectuera un remplacement des termes dans la deuxième définition. Ainsi, le premier terme remplacera
chaque « A » dans la deuxième définition et le deuxième terme remplacera chaque « B » dans la deuxième
définition. Lorsque la ligne 12 du programme est atteinte, "index" sera remplacé par chaque "A" et "count" sera
remplacé par chaque "B". Se souvenir de la construction énigmatique que nous avons étudiée il y a quelques
chapitres révélera que "mx" recevra la valeur maximale de "index" ou "count". De la même manière, la macro
"MIN" aura pour conséquence que "mn" reçoive la valeur minimale de "index" ou de "count". Les résultats sont
ensuite imprimés. Il y en a apparemment beaucoup en plus, ils sont essentiels. Nous discuterons des parenthèses
supplémentaires dans notre prochain programme.

Compilez et exécutez definition.c.

6.4 Regardons une mauvaise macro


Chargez le fichier nommé macro.c et affichez­le sur votre écran pour un meilleur aperçu d'une macro et de son
utilisation.

#define FAUX(A) A*A*A /* Mauvaise macro pour le cube */


#define CUBE(A) (A)*(A)*(A) /* Bonne macro pour le cube */ #define SQUR(A) (A)*(A)
/* Macro de droite pour le carré */ #define
START 1 #define STOP
9
main( )

{ int i,offset;
décalage = 5 ; pour
(i = DÉBUT;i <= STOP;i++) {
printf("Le carré de %3d est %4d et son cube est %6d\n", i+offset,SQUR(i+offset),CUBE(i+offset));
printf("Le mauvais de %3d est %6d\n",i+offset,WRONG(i+offset));

}
}

La première ligne définit une macro nommée "WRONG" qui semble obtenir le cube de "A", et c'est effectivement
le cas dans certains cas, mais elle échoue lamentablement dans d'autres. La deuxième macro nommée "CUBE"
récupère le cube dans tous les cas.
Considérez le programme lui­même où le CUBE de i+offset est calculé. Si i vaut 1, ce que c'est la première fois,
alors nous chercherons le cube de 1+5 = 6, ce qui donnera 216.
Lorsque nous utilisons "CUBE", nous regroupons les valeurs comme ceci, (1+5)*(1+5)*(1+5) = 6*6*6 = 216.
Cependant, lorsque nous utilisons FAUX, nous les regroupons comme 1+5*1+5*1+5 = 1+5+5+5 = 16, ce qui est
une mauvaise réponse. Les parenthèses sont donc nécessaires pour regrouper correctement les variables.
Il devrait être clair pour vous que "CUBE" ou "WRONG" aboutiraient à une réponse correcte pour un remplacement
d'un seul terme, comme nous l'avons fait dans le programme précédent. Les valeurs correctes du cube et du
carré des nombres sont imprimées ainsi que les valeurs erronées pour votre inspection.
Le reste du programme est simple et sera laissé à votre inspection et à votre compréhension.

6­2 Tutoriel C Définitions et macros


Machine Translated by Google
6.5 Exercice de programmation
1. Écrivez un programme pour compter de 7 à ­5 en décompteant. Utilisez les instructions *define pour définir
les limites. (Indice, vous devrez utiliser une variable décrémentante dans la troisième partie de la boucle "for"
contrôle.

Définitions et macros Tutoriel C 6­3


Machine Translated by Google
7
Chaînes et tableaux

7.1 Qu'est­ce qu'une chaîne ?


Une chaîne est un groupe de caractères, généralement des lettres de l'alphabet. Afin de formater votre impression de
manière à ce qu'elle soit belle, qu'elle contienne des titres et des noms significatifs et qu'elle soit esthétiquement agréable à
vous et aux personnes utilisant la sortie de votre programme, vous devez pouvoir générer des données texte.
En fait, vous utilisez déjà des chaînes, car le deuxième programme de ce didacticiel, au chapitre 2, génère un message qui
est traité en interne sous forme de chaîne. Une définition complète est une série de données de type "char" terminée par un
caractère NULL, qui est un zéro.

Lorsque C va utiliser une chaîne de données d'une manière ou d'une autre, soit pour la comparer avec une autre, la sortir, la
copier dans une autre chaîne, ou autre, les fonctions sont configurées pour faire ce pour quoi elles sont appelées jusqu'à un
NULL, qui est un zéro, est détecté.

7.2 Qu'est­ce qu'un tableau ?


Un tableau est une série de données homogènes qui sont toutes de même type, mais le type peut être assez complexe
comme nous le verrons lorsque nous arriverons au chapitre de ce tutoriel traitant des structures.
Une chaîne est simplement un cas particulier d’un tableau.

La meilleure façon de voir ces principes est d'utiliser un exemple, alors chargez le programme chrstrg.c et affichez­le sur
votre moniteur. main( ) { nom du
caractère[5];

nom[0] = 'D'; nom[1] /* définit une chaîne de caractères */


= 'un'; nom[2] = 'v';
nom[3] = 'e'; nom[4] =
0; printf("Le nom est
%s\n",name);
printf("Une lettre /* Caractère nul ­ fin du texte */
vaut %c\n",name[2]); printf("Une partie du nom est
%s\n",&name[1]);

La première chose nouvelle est la ligne qui définit une entité de données de type "char". Les crochets définissent un indice
de tableau en C, et dans le cas de l'instruction de définition de données, le 5 entre parenthèses définit 5 champs de données
de type "char", tous définis comme la variable "nom". En langage C, tous les indices commencent à 0 et augmentent de 1 à
chaque pas jusqu'au maximum qui dans ce cas est 4.
Nous avons donc 5 variables de type "char" nommées, "name[0]", "name[1]", "name[2]", "name[3]", et "name[4]". Vous devez
garder à l’esprit qu’en C, les indices vont en réalité de 0 à un de moins que le nombre défini dans l’énoncé de définition.

7.3 Comment utilisons­nous la chaîne ?


La variable "nom" est donc une chaîne pouvant contenir jusqu'à 5 caractères, puisqu'il faut de la place pour le caractère
NULL, il n'y a en réalité que quatre caractères utiles. Pour charger quelque chose d'utile dans la chaîne, nous disposons de
5 instructions, chacune attribuant un caractère alphabétique à l'un des caractères de la chaîne. Enfin, la dernière place de la
chaîne est remplie avec le chiffre 0 comme indicateur de fin et la chaîne est complète. (Un "define" nous permettrait d'utiliser
"NULL" au lieu d'un zéro, et cela ajouterait grandement à la clarté du programme. Il serait très évident qu'il s'agissait d'un
NULL et pas simplement d'un zéro, nous imprimerons simplement avec d'autres données de chaîne

7­1 Tutoriel C Chaînes et tableaux


dans l'instruction
Machine Translated by Google de sortie. Le % est la définition de sortie pour afficher une chaîne et le système affichera les
caractères commençant par le premier de "nom" jusqu'à ce qu'il arrive au caractère NULL, et il s'arrêtera. Notez
que dans l'instruction "printf", seul le nom de la variable "name" doit être donné, sans indice puisque nous
souhaitons commencer par le début. (Il existe en fait une autre raison pour laquelle seul le nom de la variable est
donné sans crochets. La discussion sur ce sujet sera abordée dans le chapitre suivant.)

7.4 Sortie d'une partie d'une chaîne

Le "printf" suivant montre que nous pouvons afficher n'importe quel caractère de la chaîne en utilisant le "%c" et
en nommant le caractère particulier de "name" que nous voulons en incluant l'indice. Le dernier "printf" illustre
comment nous pouvons afficher une partie de la chaîne en indiquant le point de départ à l'aide d'un indice. Le &
spécifie l'adresse de "name[1]". Nous étudierons cela dans le prochain chapitre, mais j'ai pensé que vous
bénéficieriez d'un petit aperçu à venir.

Cet exemple peut vous donner l'impression que les chaînes sont plutôt lourdes à utiliser puisqu'il faut configurer
chaque caractère un par un. C’est une conclusion incorrecte car les chaînes sont très faciles à utiliser, comme
nous le verrons dans le prochain exemple de programme.

Compilez et exécutez ce programme.

7.5 Quelques sous­programmes de chaîne

Chargez l'exemple de programme strings.c pour un exemple de quelques façons d'utiliser les chaînes.
main( )

{ char nom1[12],nom2[12],mixed[25]; titre du


caractère[20] ;
strcpy(nom1,"Rosalinda");
strcpy(nom2,"Zeke");
strcpy(title,"Voici le titre."); printf(" %s\n\n"titre);
printf("Le nom 1 est %s\n",name1); printf(Le
nom 2 est %s\n",nom2);
if(strcmp(name1,name2)>0) /* renvoie 1 si
nom1 > nom2 */ strcpy(mixed,name1); else

strcpy(mixte,nom2); printf("Le
plus grand nom alphabétiquement est %s\n",mixte); strcpy(mixte,nom1); strcat(mixte,"
"); strcat(mixte,nom2);
printf("Les deux noms sont
%s\n",mixte);

Nous définissons d’abord quatre chaînes. Nous arrivons ensuite à une nouvelle fonction qui vous sera très utile, la
fonction "strcpy", ou copie de chaîne. Il copie d'une chaîne à une autre jusqu'à ce qu'il arrive au caractère NULL. Il
est facile de se rappeler lequel reçoit des copies et auquel vous les considérez comme une déclaration de mission.
Ainsi, si vous dites, par exemple, "x = 23;", les données sont copiées de l'entité de droite vers celle de gauche.
Dans la fonction "strcpy", les données sont également copiées de l'entité de droite vers la gauche, de sorte
qu'après l'exécution de la première instruction, name1 contiendra la chaîne "Rosalinda", mais sans les guillemets
doubles, c'est le moyen pour le compilateur de sachant que vous définissez une chaîne.

Chaînes et tableaux Tutoriel C 7­2


De même,
Machine Translated by"Zeke"
Googleest copié dans "name2" par la deuxième instruction, puis le "title" est copié. Le titre et les deux
noms sont ensuite imprimés. Notez qu'il n'est pas nécessaire que la chaîne définie ait exactement la même taille
que la chaîne qu'elle sera appelée à stocker, mais seulement qu'elle soit au moins aussi longue que la chaîne
plus un caractère supplémentaire pour le NULL.

7.6 Tri alphabétique des chaînes


La prochaine fonction que nous examinerons est la fonction « strcmp » ou la fonction de comparaison de chaînes.
Il renverra un 1 si la première chaîne est plus grande que la seconde, zéro si elles ont la même longueur et ont
les mêmes caractères, et ­1 si la première chaîne est plus petite que la seconde. L'une des chaînes, en fonction
du résultat de la comparaison, est copiée dans la variable "mixte" et le plus grand nom est imprimé par ordre
alphabétique. Cela ne devrait pas vous surprendre que "Zeke" gagne parce qu'il est alphabétiquement plus grand,
la longueur n'a pas d'importance, seul l'alphabet. Il serait peut­être judicieux de mentionner que le résultat
dépendra également du fait que les lettres soient majuscules ou minuscules. Il existe des fonctions disponibles
avec votre compilateur C pour changer la casse d'une chaîne en majuscules ou en minuscules si vous le
souhaitez. Ceux­ci seront utilisés dans un exemple de programme plus loin dans ce didacticiel.

7.7 Combinaison de chaînes


Les quatre dernières instructions ont une autre nouvelle fonctionnalité, la fonction « strcat » ou fonction de concaténation de chaînes.
Cette fonction ajoute simplement les caractères d'une chaîne à la fin d'une autre chaîne en prenant soin d'ajuster
le NULL pour que tout aille toujours bien. Dans ce cas, "nom1" est copié dans "mixte", puis deux espaces sont
concaténés à "mixte", et enfin "nom2" est concaténé à la combinaison. Le résultat est imprimé avec les deux
noms dans la variable "mixte".

Les cordes ne sont pas difficiles et sont extrêmement utiles. Vous devriez prendre le temps de vous familiariser
avec eux avant de passer au sujet suivant.

Compilez et exécutez ce programme et observez les résultats pour vérifier leur conformité à cette définition.

7.8 Un tableau d'entiers


Chargez le fichierintarray.c et affichez­le sur votre moniteur pour un exemple de tableau d'entiers.
main( )

{ valeurs int[12]; indice


int ;
pour (index = 0;index < 12;index++)
valeurs[index] = 2 * (index + 4);
for (index = 0;index < 12;index++) printf("La valeur à
l'index = %2d est %3d\n",index,values[in­
dex]);
}

Notez que le tableau est défini à peu près de la même manière que nous avons défini un tableau de caractères
afin d'effectuer les manipulations de chaînes dans la dernière section. Nous avons 12 variables entières à
travailler, sans compter celle nommée "index". Les noms des variables sont "values[0]", "values[1]", ... et
"values[11]". Ensuite, nous avons une boucle pour attribuer des données absurdes, mais bien définies, à chacune
des 12 variables, puis imprimer les 12. Vous ne devriez avoir aucune difficulté à suivre ce programme, mais
assurez­vous de le comprendre. Compilez­le et exécutez­le pour voir s’il fait ce que vous attendez de lui.

7­3 Tutoriel C Chaînes et tableaux


Machine Translated by Google
7.9 Un tableau de données à virgule flottante
Chargez et affichez le programme nommé bigarray.c pour un exemple de programme avec un tableau de
données de type "float".
/* NOTE
Cet exemple a été modifié pour utiliser une autre variable de type entier au lieu d'une variable de type float en
raison de
problèmes dans la bibliothèque float avec le compilateur HI­TECH C. Le compilateur ne renvoie aucune erreur fatale lorsque
la variable de type float est utilisée et que la bibliothèque float est incluse au moment de la liaison, mais le fichier Xrel
produit
une erreur d'adresse. Le code original est commenté afin que vous

Je
peux toujours voir que c'était prévu dans le tutoriel. */ char name1[ ] =

"Titre du premier programme" ; main() { int index ; int trucs[12]; /


* float

bizarre[12]; */
int bizarre[12]; static
char name2[ ] = "Deuxième titre du
programme" ; pour
(index = 0;index < 12;index++) {

trucs[index] = index + 10 ;
/* bizarre[index] = 12.0 * (index + 7); */ bizarre[index] = 12 * (index + 7);

} printf("%s\n",nom1);
printf("%s\n\n",nom2); for (index =
0;index< 12;index++) { printf("%5d %5d
%5d\n",index,stuff[index],bizarre[index]); /* printf("%5d %5d %10.3f\n",index,stuff[index],bizarre[index]);
*/ }

Ce programme a une fonctionnalité supplémentaire pour illustrer comment les chaînes peuvent être
initialisées. La première ligne du programme vous illustre comment initialiser une chaîne de caractères.
Notez que les crochets sont vides, laissant au compilateur le soin de compter les caractères et d'allouer
suffisamment d'espace pour notre chaîne. Une autre chaîne est initialisée dans le corps du programme
mais elle doit être déclarée ici "statique". Cela l'empêche d'être allouée en tant que variable "automatique"
et lui permet de conserver la chaîne une fois le programme démarré. Il n'y a rien d'autre de nouveau ici, les
variables se voient attribuer des données absurdes et les résultats de toutes les absurdités sont imprimés
avec un en­tête. Ce programme devrait également être facile à suivre pour vous, alors étudiez­le jusqu'à ce
que vous soyez sûr de ce qu'il fait avant de passer au sujet suivant.

7.10 Récupération de données à partir d'une fonction


Au chapitre 5, lorsque nous avons étudié les fonctions, je vous ai laissé entendre qu'il existait un moyen de
récupérer les données d'une fonction en utilisant un tableau, et c'est vrai. Chargez le programme passback.c
pour un exemple de cela.
main( )

{ int index ;
matrice int[20] ;
pour (index = 0;index < 20;index++) matrice[index] = /* générer des données */
index + 1;
pour (index = 0;index < 5;index++) /* imprimer les données originales */
printf("Démarrer la matrice[%d] = %d\n",index,matrix[index]);

Chaînes et tableaux Tutoriel C 7­4


dosome(matrice);
Machine Translated by Google /* aller à une fonction et modifier la matrice */
0;index < 5;index++) printf("back matrice[%d] = /* imprimer la matrice modifiée */ for (index =
%d\n",index,matrix[index]);
}

dosome(liste) int /* Ceci illustrera le retour des données */


liste[]; {int je; for

(i = 0;i <
5;i++) printf("Avant marrix[%d] =
%d\n",i,list[i]);
pour (i = 0;i < 20;i++) liste[i] +=10; /* ajoute 10 à toutes les valeurs */

5;i++) printf("After matrice[%d] = /* imprimer la matrice modifiée */ for (i =0;i <


%d\n",i,list[i]);
}

Dans ce programme, nous définissons un tableau de 20 variables nommé "matrice", puis attribuons des données
absurdes aux variables et imprimons les cinq premières. Ensuite, nous appelons la fonction "dosome" en emportant
l'ensemble du tableau en mettant le nom du tableau entre parenthèses.

La fonction "dosome" a également un nom entre parenthèses mais elle préfère appeler le tableau "list".
La fonction doit être informée qu'elle reçoit réellement un tableau qui lui est transmis et que le tableau est de type
"int". La ligne suivante, avant le crochet qui démarre le programme, fait cela en définissant "liste" comme une variable
de type entier et en incluant les crochets pour indiquer un tableau.
Il n'est pas nécessaire d'indiquer à la fonction combien d'éléments se trouvent dans le tableau, mais vous pouvez le
faire si vous le souhaitez. Généralement, une fonction fonctionne avec un tableau jusqu'à ce qu'un marqueur de fin
de données soit trouvé, comme un NULL pour une chaîne, ou d'autres données ou modèles préalablement définis.
Plusieurs fois, une autre donnée est transmise à la fonction avec le nombre d'éléments avec lesquels travailler.
Sur notre illustration actuelle, nous utiliserons un nombre fixe d’éléments pour rester simple.

Jusqu’à présent, rien n’est différent des fonctions précédentes que nous avons appelées, sauf que cette fois, nous
avons transmis plus de points de données à la fonction que jamais auparavant, après avoir transmis 20 valeurs
entières. Nous imprimons à nouveau les 5 premiers pour voir s'ils ont effectivement été transmis ici. Ensuite, nous
ajoutons dix à chacun des éléments et imprimons les nouvelles valeurs. Enfin, nous revenons au programme
principal et imprimons les mêmes 5 points de données. Nous constatons que nous avons effectivement modifié les
données dans la fonction, et lorsque nous sommes revenus au programme principal, nous avons ramené les
modifications. Compilez et exécutez ce programme pour vérifier cette conclusion.

7.11 Les tableaux transmettent les données dans les deux sens

Nous avons déclaré lors de notre étude des fonctions que lorsque nous transmettions des données à une fonction,
le système en faisait une copie à utiliser dans la fonction qui était jetée à notre retour. Ce n'est pas le cas des
tableaux. Le tableau réel est transmis à la fonction et celle­ci peut le modifier comme elle le souhaite. Le résultat des
modifications sera disponible dans le programme appelant. Cela peut vous sembler étrange que les tableaux soient
traités différemment des données à point unique, mais c'est le cas.
Cela a vraiment du sens, mais vous devrez attendre que nous ayons des indications pour le comprendre.

7.12 Un indice pour une leçon future

Une autre façon de récupérer les données d'une fonction vers le programme appelant consiste à utiliser des pointeurs
que nous aborderons dans le chapitre suivant. Une fois sur place, nous constaterons qu’un tableau est en réalité un
pointeur vers une liste de valeurs. Ne vous laissez pas inquiéter maintenant, cela aura du sens lorsque nous y
arriverons. En attendant, concentrez­vous sur les tableaux et comprenez­en les bases, car lorsque nous arriverons
à l'étude des structures, nous pourrons définir des tableaux assez élaborés.

7­5 Tutoriel C Chaînes et tableaux


Machine Translated by Google
7.13 Tableaux à dimensions multiples
Chargez et affichez le fichier nommé multiary.c pour un exemple de programme avec des tableaux doublement
dimensionnés.
main( ) {int

je,j; int gros[8]


[8],énorme[25][12];
pour (i = 0;i < 8;i++)
pour (j = 0;j < 8;j++) big[i][j] = i * j;
/* Ceci est une table de multiplication */
pour (i = 0;i < 25;i++)
pour (j = 0;j < 12;j++) énorme[i][j] = i
+ j; /* Ceci est une table d'addition */

grand[2][6] = énorme[24][10] *22; grand[2][2] =


5; gros[gros][2]
[2]...gros[2][2]. = 177 ; /* c'est gros[5][5] = 177; */
pour (i = 0;i < 8;i++) {
pour (j = 0;j < 8;j++) printf("%5d
",big[i][j]); printf("\n"); /* nouvelle ligne pour
chaque augmentation de i */
}
}

La variable "big" est un tableau de 8 x 8 qui contient 8 fois 8 ou 64 éléments au total. Le premier élément est "big[0]
[0]" et le dernier est "big[7][7]". Un autre tableau nommé « énorme » est également défini, qui n'est pas carré pour
illustrer que le tableau n'a pas besoin d'être carré. Les deux sont remplis de données, l’une représentant une table
de multiplication et l’autre étant transformée en table d’addition.

Pour illustrer que des éléments individuels peuvent être modifiés à volonté, l'un des éléments de « big » se voit
attribuer la valeur de l'un des éléments de « huge » après avoir été multiplié par 22. Ensuite, « big[2][2] » est attribué
la valeur arbitraire de 5, et cette valeur est utilisée pour les indices de la prochaine instruction d'affectation. La
troisième instruction d'affectation est en réalité "big[5][5] = 177" car chacun des indices contient la valeur 5. Ceci est
uniquement fait pour illustrer que toute expression valide peut être utilisée pour un indice. Il ne doit remplir que deux
conditions : il doit s'agir d'un nombre entier (même si un "char" fonctionnera tout aussi bien) et il doit être compris
dans la plage de l'indice pour lequel il est utilisé.

La variable matricielle entière "grande" est imprimée sous forme carrée afin que vous puissiez vérifier les valeurs
pour voir si elles ont été définies comme vous l'espériez.

7.14 Exercices de programmation


1. Écrivez un programme avec trois chaînes courtes, d'environ 6 caractères chacune, et utilisez "strcpy" pour y
copier "un", "deux" et "trois". Concaténez les trois chaînes en une seule chaîne et imprimez le résultat 10 fois.

2. Définissez deux tableaux d'entiers, chacun long de 10 éléments, appelés "array1" et "array2". À l'aide d'une
boucle, mettez une sorte de données absurdes dans chacune et ajoutez­les terme à terme dans un autre tableau de
10 éléments nommé "tableaux".
Enfin, imprimez tous les résultats dans un tableau avec un numéro
d'index. 1 2 + 10
= 12 2 4 + 20 =
24 3 6 + 30 = 36 etc.

Indice; L'instruction print sera similaire à : printf("%4d


%4d + %4d = %4d\n",index,array1[index], array2[index],arrays[index]);

Chaînes et tableaux Tutoriel C 7­6


Machine Translated by Google
8
Pointeurs

8.1 Qu'est­ce qu'un pointeur ?

En termes simples, un pointeur est une adresse. Au lieu d'être une variable, c'est un pointeur vers une variable stockée quelque
part dans l'espace d'adressage du programme. Il est toujours préférable d'utiliser un exemple, alors chargez le fichier nommé
pointer.c et affichez­le sur votre moniteur pour un exemple de programme contenant des pointeurs.

main( ) /* illustration de l'utilisation du pointeur */

{ int index,*pt1,*pt2;
indice = 39 ; pt1 /* n'importe quelle valeur numérique */ /*
= &index; point2 = l'adresse de l'index */
point1 ;
printf("La valeur est %d %d %d\n",index,*pt1,*pt2); *pt1 = 13 ; /* cela change
la valeur de l'index */ printf("La valeur est %d %d %d\n",index,*pt1,*pt2);

Pour le moment, ignorez l'instruction de déclaration où l'on définit "index" et deux autres champs commençant par une étoile. On
l'appelle à proprement parler un astérisque, mais pour les raisons que nous verrons plus tard, convenons de l'appeler une étoile.
Si vous observez la première affirmation, il devrait être clair que nous attribuons la valeur 39 à la variable « index ». Ce n’est pas
une surprise, nous le faisons depuis plusieurs programmes maintenant. Cependant, l'instruction suivante dit d'attribuer à "pt1"
une valeur étrange, à savoir la variable "index" avec une esperluette devant elle. Dans cet exemple, pt1 et pt2 sont des pointeurs
et la variable « index » est une variable simple. Maintenant, nous avons un problème. Nous devons apprendre à utiliser les
pointeurs dans un programme, mais pour ce faire, nous devons d'abord définir les moyens d'utiliser les pointeurs dans le
programme.

Les deux règles suivantes vous paraîtront quelque peu déroutantes au début, mais nous devons énoncer les définitions avant de
pouvoir les utiliser. Prenez votre temps et tout s’éclaircira très vite.

8.2 Deux règles très importantes


Les deux règles suivantes sont très importantes lors de l’utilisation de pointeurs et doivent être parfaitement comprises.

1. Un nom de variable précédé d'une esperluette définit l'adresse de la variable et pointe donc vers la variable. Vous pouvez
donc lire la ligne six comme "pt1 se voit attribuer la valeur de l'adresse de "index".

2. Un pointeur précédé d'une « étoile » fait référence à la valeur de la variable pointée par le pointeur.
La ligne neuf du programme peut être lue comme "La valeur stockée (étoilée) à laquelle pointe le pointeur "pt1" se voit attribuer
la valeur 13". Vous pouvez maintenant comprendre pourquoi il est pratique de considérer l’astérisque comme une étoile, cela
ressemble en quelque sorte au mot magasin.

8.3 Aide­mémoire
1. Considérez & comme une adresse.
2. Considérez * comme une étoile faisant référence au stockage.

8­1 Tutoriel C Pointeurs


Supposons
Machine Translated by pour l'instant que "pt1" et "pt2" soient des pointeurs (nous verrons comment les définir prochainement).
Google
En tant que pointeurs, ils ne contiennent pas une valeur de variable mais une adresse de variable et peuvent être
utilisés pour pointer vers une variable. La sixième ligne du programme attribue au pointeur "pt1" la variable que
nous avons déjà définie comme "index" à "pt1". Puisque nous avons un pointeur vers « index », nous pouvons
manipuler la valeur de « index » en utilisant soit le nom de la variable lui­même, soit le pointeur.

La ligne neuf modifie la valeur en utilisant le pointeur. Puisque le pointeur "pt1" pointe vers la variable "index", alors
mettre une étoile devant le nom du pointeur fait référence à l'emplacement mémoire vers lequel il pointe. La ligne
neuf attribue donc à "index" la valeur 13. Partout dans le programme où il est permis d'utiliser le nom de variable
"index", il est également permis d'utiliser le nom "*pt1" puisqu'ils ont une signification identique jusqu'à ce que le
nom de variable "index" soit utilisé. le pointeur est réaffecté à une autre variable.

8.4 Un autre pointeur


Juste pour ajouter un peu d'intrigue au système, nous avons un autre pointeur défini dans ce programme, "pt2".
Puisque "pt2" n'a reçu aucune valeur avant la septième instruction, il ne pointe vers rien, il contient des déchets.
Bien entendu, cela est également vrai pour n’importe quelle variable jusqu’à ce qu’une valeur lui soit attribuée.
La septième instruction attribue à "pt2" la même adresse que "pt1", de sorte que désormais "pt2" pointe également
vers la variable "index". Donc, pour continuer la définition du dernier paragraphe, n'importe où dans le programme
où il est permis d'utiliser la variable "index", il est également permis d'utiliser le nom "*pt2" car leur signification est
identique. Ce fait est illustré dans la première instruction "printf" puisque cette instruction utilise les trois moyens
d'identification de la même variable pour imprimer trois fois la même variable.

8.5 Il n'y a qu'une seule variable


Notez bien que, même s’il semble y avoir trois variables, il n’y en a en réalité qu’une seule. Les deux pointeurs
pointent vers la variable unique. Ceci est illustré dans l'instruction suivante qui attribue la valeur 13 à la variable
"index", car c'est là que pointe le pointeur "pt1". L'instruction "printf" suivante entraîne l'impression trois fois de la
nouvelle valeur 13.
Gardez à l’esprit qu’il n’y a en réalité qu’une seule variable à modifier, et non trois.

Il s'agit certes d'un concept très difficile, mais comme il est largement utilisé dans tous les programmes C, sauf les
plus triviaux, cela vaut la peine de s'attarder sur ce matériel jusqu'à ce que vous le compreniez parfaitement.

8.6 Comment déclarer un pointeur ?


Maintenant, tenons une promesse et vous expliquons comment déclarer un pointeur. Reportez­vous à la troisième
ligne du programme et vous verrez notre ancienne manière familière de définir la variable "index", suivie de deux
autres définitions. La deuxième définition peut être lue comme "l'emplacement de stockage vers lequel pointe "pt1"
sera une variable de type int". Par conséquent, « pt1 » est un pointeur vers une variable de type int. De même, "pt2"
est un autre pointeur vers une variable de type int.

Un pointeur doit être défini pour pointer vers un certain type de variable. Suite à une définition appropriée, il ne peut
pas être utilisé pour pointer vers un autre type de variable, sinon cela entraînera une erreur « d'incompatibilité de
type ». De la même manière qu'une variable de type "float" ne peut pas être ajoutée à une variable de type "int", un
pointeur vers une variable "float" ne peut pas être utilisé pour pointer vers une variable entière.

Compilez et exécutez ce programme et observez qu'il n'y a qu'une seule variable et que l'instruction unique de la
ligne 9 modifie la variable qui est affichée trois fois.

Pointeurs Tutoriel C 8­2


Machine Translated by Google
8.7 Le deuxième programme avec des pointeurs
Dans ces quelques pages consacrées aux indicateurs, nous avons couvert beaucoup de territoire, mais c’est un territoire
important. Nous avons encore beaucoup de choses à aborder, alors restez à l'écoute pendant que nous poursuivons cet
aspect important du C. Chargez le fichier suivant nommé pointer2.c et affichez­le sur votre moniteur afin que nous
puissions continuer notre étude.
main( )

{ char strg[40],*là,un,deux; int *pt,liste[100],index;

strcpy(strg,"Ceci est une chaîne de caractères.");


un = strg[0] ; deux = /* un et deux sont identiques */
*strg; printf("La
première sortie est %c %c\n",un,deux);
un = strg[8] ; deux = /* un et deux sont identiques */
*(chaîne+8); printf("La
deuxième sortie est %c %c %c\n",un,deux);
là = strg+10 ; /* strg+10 est identique à strg[10] */ printf("La troisième sortie est %c\n",strg[10]); printf("La
quatrième sortie est %c\n",*là);

pour (index = 0;index < 100;index++) liste[index] = index +


100;
pt = liste + 27 ; printf("La
cinquième sortie est %d\n",list[27]); printf("La sixième sortie est %d\n",*pt);

Dans ce programme, nous avons défini plusieurs variables et deux pointeurs. Le premier pointeur nommé "there" est un
pointeur vers une variable de type "char" et le second nommé "pt" pointe vers une variable de type "int". Notez également
que nous avons défini deux variables tableau nommées "strg" et "list". Nous les utiliserons pour montrer la correspondance
entre les pointeurs et les noms de tableaux.

8.8 Une variable chaîne est en fait un pointeur


Dans le langage de programmation C, une variable chaîne est définie comme étant simplement un pointeur vers le début
d’une chaîne. Cela demandera quelques explications. Reportez­vous à l'exemple de programme sur votre moniteur.
Vous remarquerez que nous attribuons d'abord une constante de chaîne à la variable de chaîne nommée "strg" afin que
nous ayons des données avec lesquelles travailler. Ensuite, nous attribuons la valeur du premier élément à la variable
"one", une simple variable "char". Ensuite, puisque le nom de chaîne est un pointeur par définition du langage C, nous
pouvons attribuer la même valeur à "deux" en utilisant l'étoile et le nom de chaîne. Le résultat si les deux affectations sont
telles que « un » a désormais la même valeur que « deux » et que les deux contiennent le caractère « T », le premier
caractère de la chaîne. Notez qu'il serait incorrect d'écrire la neuvième ligne sous la forme "two = *strg[0];" car l’étoile
remplace les crochets.

À toutes fins pratiques, « strg » est un pointeur. Il comporte cependant une restriction qu’un véritable pointeur n’a pas.
Elle ne peut pas être modifiée comme une variable, mais doit toujours contenir la valeur initiale et pointe donc toujours
vers sa chaîne. Cela pourrait être considéré comme une constante de pointeur et, dans certaines applications, vous
souhaiterez peut­être un pointeur qui ne puisse en aucun cas être corrompu. Même s'il ne peut pas être modifié, il peut
être utilisé pour faire référence à d'autres valeurs que celle pour laquelle il est défini, comme nous le verrons dans la
prochaine section du programme.

En passant à la ligne 12, la variable "un" se voit attribuer la valeur de la neuvième variable (puisque l'indexation commence
à zéro) et "deux" se voit attribuer la même valeur car nous sommes autorisés à indexer un pointeur pour accéder à des
valeurs plus avancées. dans la chaîne. Les deux variables contiennent désormais le caractère "a".

8­3 Tutoriel C Pointeurs


Le langage
Machine Translated de programmation C s'occupe automatiquement de l'indexation en ajustant l'indexation en fonction
by Google
du type de variable vers laquelle pointe le pointeur. Dans ce cas, l'indice 8 est simplement ajouté à la variable de
valeur du pointeur avant de rechercher le résultat souhaité car une variable de type "char" fait un octet. Si nous
utilisions un pointeur vers une variable de type "int", l'index serait doublé et ajouté au pointeur avant de rechercher
la valeur car une variable de type "int" utilise deux octets par valeur stockée. Quand nous arriverons au chapitre
sur les structures, nous verrons qu'une variable peut avoir plusieurs, voire des centaines ou des milliers de
caractères par variable, mais l'indexation sera gérée automatiquement pour nous par le système.

Puisque "there" est déjà un pointeur, la valeur du onzième élément de "strg" peut lui être attribuée par l'instruction
de la ligne 16 du programme. N'oubliez pas que puisque "il" existe un vrai pointeur, n'importe quelle valeur peut
lui être attribuée tant que cette valeur représente une adresse de type "char". Il doit être clair que les pointeurs
doivent être « tapés » afin de permettre que l'arithmétique des pointeurs décrite dans le dernier paragraphe soit
effectuée correctement. Les troisième et quatrième sorties seront les mêmes, à savoir la lettre « c ».

8.9 Arithmétique des pointeurs

Toutes les formes d’arithmétique ne sont pas autorisées sur un pointeur. Uniquement les choses qui ont du sens,
étant donné qu’un pointeur est une adresse quelque part dans l’ordinateur. Il serait logique d'ajouter une
constante à une adresse, la faisant ainsi avancer dans la mémoire d'autant de places. De même, la soustraction
est autorisée, en la reculant d'un certain nombre d'emplacements. L’ajout de deux pointeurs n’aurait aucun sens
car les adresses mémoire absolues ne sont pas additives. La multiplication du pointeur n'est pas non plus
autorisée, car ce serait un nombre amusant. Si vous réfléchissez à ce que vous faites réellement, vous
comprendrez ce qui est autorisé et ce qui ne l’est pas.

8.10 Maintenant pour un pointeur entier


Le tableau nommé "list" se voit attribuer une série de valeurs de 100 à 199 afin de disposer de certaines données
avec lesquelles travailler. Ensuite, nous attribuons au pointeur "pt" la valeur du 28ème élément de la liste et
imprimons la même valeur dans les deux sens pour illustrer que le système ajustera réellement l'index pour la
variable de type "int". Vous devriez passer du temps dans ce programme jusqu'à ce que vous sentiez que vous
comprenez assez bien ces leçons sur les pointeurs.
Compilez et exécutez pointer2.c et étudiez le résultat.

8.11 Retour de données de fonction avec un pointeur

Vous vous souviendrez peut­être que dans la leçon sur les fonctions, nous avons mentionné qu'il existait deux
manières de récupérer des données variables à partir d'une fonction. L’une des solutions consiste à utiliser le
tableau, et vous devriez être sur le point de deviner l’autre solution. Si vous devinez grâce à l’utilisation d’un
pointeur, vous avez raison. Chargez et affichez le programme nommé twoway.c pour un exemple.
main( ) { int

noix de pécan, pommes ;

noix de pécan = 100 ;


pommes = 101 ;
printf("Les valeurs de départ sont %d %d\n",noix de pécan,pommes); /* quand on appelle "fixup" */ /* on

prend la valeur des noix de pécan */ /* on prend l'adresse des


correction (noix de pécan et pommes); pommes */ printf("Les valeurs de fin sont %d %d\n",noix de
pécan,pommes);

Pointeurs Tutoriel C 8­4


fixup(noix,fruits)
Machine Translated by Google int /* nut est une valeur entière */
noix,*fruit; { /* le fruit pointe vers un entier */

printf("La valeur est %d %d\n",noix,*fruit); noix = 135 ; *fruits = 172 ;


printf("Les
valeurs sont %d
%d\n",nuts,*fruit);
}

Dans twoway.c, il y a deux variables définies dans le programme principal "noix de pécan" et "pommes".
Notez qu’aucun de ces éléments n’est défini comme un pointeur. Nous attribuons des valeurs à ces deux éléments
et les imprimons, puis appelons la fonction "fixup" en emportant avec nous ces deux valeurs. La variable "noix de
pécan" est simplement envoyée à la fonction, mais l'adresse de la variable "pommes" est envoyée à la fonction.
Maintenant, nous avons un problème. Les deux arguments ne sont pas identiques, le second est un pointeur vers
une variable. Il faut en quelque sorte alerter la fonction du fait qu'elle est censée recevoir une variable entière et un
pointeur vers une variable entière. Cela s'avère très simple. Notez que les définitions des paramètres dans la
fonction définissent « noix » comme un entier et « fruit » comme un pointeur vers un entier. L'appel dans le
programme principal est donc désormais en accord avec l'en­tête de la fonction et l'interface du programme
fonctionnera parfaitement.

Dans le corps de la fonction, nous imprimons les deux valeurs envoyées à la fonction, puis les modifions et
imprimons les nouvelles valeurs. Cela devrait être parfaitement clair pour vous maintenant. La surprise se produit
lorsque nous revenons au programme principal et réimprimons les deux valeurs. Nous constaterons que la valeur
des noix de pécan sera restaurée à sa valeur avant l'appel de la fonction car le langage C fait une copie de l'élément
en question et amène la copie dans la fonction appelée, laissant l'original intact. Dans le cas de la variable
"pommes", nous avons fait une copie d'un pointeur vers la variable et pris la copie du pointeur vers la fonction.
Puisque nous avions un pointeur vers la variable d'origine, même si le pointeur était une copie, nous avions accès
à la variable d'origine et pouvions la modifier dans la fonction. Lorsque nous sommes revenus au programme
principal, nous avons trouvé une valeur modifiée dans "pommes" lorsque nous l'avons imprimé.

En utilisant un pointeur dans un appel de fonction, nous pouvons accéder aux données de la fonction et les modifier
de telle manière que lorsque nous revenons au programme appelant, nous avons une valeur de données modifiée.
Il faut cependant souligner que si vous modifiez la valeur du pointeur lui­même dans la fonction, vous aurez restauré
le pointeur à votre retour car le pointeur que vous utilisez dans la fonction est une copie de l'original. Dans cet
exemple, il n'y avait pas de pointeur dans le programme principal car nous avons simplement envoyé l'adresse à la
fonction, mais dans de nombreux programmes, vous utiliserez des pointeurs dans les appels de fonction. L’un des
endroits où vous aurez besoin de pointeurs dans les appels de fonction sera lorsque vous demanderez la saisie de
données à l’aide de routines d’entrée/sortie standard. Ceux­ci seront abordés dans les deux prochains chapitres.

Compilez et exécutez twoway.c et observez le résultat.

8.12 Les pointeurs sont précieux


Même si vous êtes probablement quelque peu intimidé à ce stade par l'utilisation des pointeurs, vous constaterez
qu'après avoir acquis de l'expérience, vous les utiliserez abondamment de plusieurs manières. Vous utiliserez
également des pointeurs dans chaque programme que vous écrivez, à l'exception des plus triviaux, car ils sont très
utiles. Vous devriez probablement revoir ce matériel attentivement plusieurs fois jusqu'à ce que vous vous sentiez
à l'aise, car il est très important dans le domaine des entrées/sorties qui est le prochain à l'ordre du jour.

8.13 Exercices de programmation


1. Définissez un tableau de caractères et utilisez "strcpy" pour y copier une chaîne. Imprimez la chaîne en utilisant
une boucle avec un pointeur pour imprimer un caractère à la fois. Initialisez le pointeur sur le premier élément et
utilisez le double signe plus pour incrémenter le pointeur. Utilisez une variable entière distincte pour compter les
caractères à imprimer.

8­5 Tutoriel C Pointeurs


2. Modifiez
Machine Translated le programme pour imprimer la chaîne à l'envers en pointant vers la fin et en utilisant un
by Google
pointeur décrémentant.

Pointeurs Tutoriel C 8­6


Machine Translated by Google
9
Entrée/sortie standard

9.1 Le fichier d'en­tête Stdio.H


Chargez le fichier simpleio.c pour notre premier aperçu d'un fichier avec des E/S standard. Les E/S standard font
référence aux endroits les plus courants où les données sont soit lues à partir du clavier, soit écrites sur le moniteur
vidéo. Puisqu'ils sont très utilisés, ils sont utilisés comme périphériques d'E/S par défaut et n'ont pas besoin d'être
nommés dans les instructions d'entrée/sortie. Cela aura plus de sens lorsque nous commencerons réellement à
les utiliser, alors regardons le fichier devant vous.
# inclut "/sys/stdio.h" /* en­tête standard pour les entrées/sorties */
main( )

{ char c;
printf("Entrez n'importe quel caractère, X = arrêt du programme.\n");
faire
{ c = getchar(); /* Récupère un caractère du ko */
putchar(c); } while /* Afficher le caractère sur le moniteur */
(c != 'X'); /* Jusqu'à ce que X soit atteint */

printf("\nFin du programme.\n");
}

La première chose que vous remarquez est la première ligne du fichier, la ligne #include "stdio.h". Cela ressemble
beaucoup au #define que nous avons déjà étudié, sauf qu'au lieu d'une simple substitution, un fichier entier est lu
à ce stade. Le système trouvera le fichier nommé "stdio.h" et lira l'intégralité de son contenu, remplaçant cette
instruction. Évidemment, le fichier nommé "stdio.h" doit contenir des instructions source C valides qui peuvent être
compilées dans le cadre d'un programme. Ce fichier particulier est composé de plusieurs #defines standard pour
définir certaines des opérations d'E/S standard. Le fichier est appelé fichier d'en­tête et vous trouverez plusieurs
fichiers d'en­tête différents sur les disques sources fournis avec votre compilateur. Chacun des fichiers d'en­tête a
un objectif spécifique et tout ou partie d'entre eux peuvent être inclus dans n'importe quel programme.

La plupart des compilateurs C utilisent les guillemets doubles pour indiquer que le fichier "include" se trouvera
dans le répertoire courant. Quelques­uns utilisent les signes « inférieur à » et « supérieur à » pour indiquer que le
fichier se trouvera dans un fichier d'en­tête standard. Presque tous les compilateurs MSDOS C utilisent les
guillemets doubles et la plupart exigent que le fichier « include » se trouve dans le répertoire par défaut. Tous les
programmes de ce didacticiel ont des guillemets doubles dans les instructions "include". Si votre compilateur utilise
l'autre notation, vous devrez les modifier avant de compiler.

9.2 Opérations d'entrée/sortie en C


En fait, le langage de programmation C n'a pas d'opérations d'entrée ou de sortie définies dans le cadre du
langage, elles doivent être définies par l'utilisateur. Puisque tout le monde ne veut pas réinventer ses propres
opérations d'entrée et de sortie, les auteurs du compilateur ont fait beaucoup de choses pour nous et nous ont
fourni plusieurs fonctions d'entrée et plusieurs fonctions de sortie pour nous aider dans le développement de notre
programme. Les fonctions sont devenues un standard et vous trouverez les mêmes fonctions disponibles dans
presque tous les compilateurs.

En fait, le standard industriel de la définition du langage C est devenu le livre écrit par Kernigan et Ritchie, et ils ont
inclus ces fonctions dans leur définition. Vous trouverez souvent, en lisant de la littérature sur C, une référence à
K & R. Cela fait référence au livre écrit par Kernigan et Ritchie. Il vous serait conseillé d’en acheter une copie pour
référence.

9­1 Tutoriel C Entrée/sortie standard


Vous devriez
Machine Translated imprimer le fichier nommé "stdio.h" et passer du temps à l'étudier. Il y aura beaucoup de choses que vous
by Google
ne comprendrez pas, mais certaines parties vous sembleront familières. Le nom "stdio.h" est en quelque sorte énigmatique
pour "en­tête d'entrée/sortie standard", car c'est exactement ce qu'il fait. Il définit les fonctions d'entrée et de sortie
standard sous forme de #defines et de macros. Ne vous inquiétez pas trop des détails pour le moment. Vous pourrez
toujours revenir sur ce sujet plus tard pour une étude plus approfondie si cela vous intéresse, mais vous n'aurez vraiment
pas besoin de comprendre complètement le fichier "stdio.h".
Cependant, vous aurez un immense besoin de l'utiliser, c'est pourquoi ces commentaires sur son utilisation et son objectif
sont nécessaires.

9.3 Autres fichiers d'inclusion

Lorsque vous commencerez à écrire des programmes plus volumineux et à les diviser en parties compilées séparément,
vous aurez l'occasion d'utiliser des instructions communes à chacune des parties. Il serait à votre avantage de créer un
fichier séparé contenant les instructions et d'utiliser le #include pour l'insérer dans chacun des fichiers. Si vous souhaitez
modifier un fichier, vous serez assuré d'avoir toutes les déclarations courantes en accord. Nous sommes un peu en
avance, mais vous avez maintenant une idée de la manière dont la directive #include peut être utilisée.

9.4 Retour au fichier nommé Simpleio.c


Continuons notre tour du dossier en question. La seule variable "c" est définie et un message est imprimé avec la fonction
familière "printf". Nous nous retrouvons alors dans une boucle continue tant que "c" n'est pas égal à X majuscule. Si vous
avez des questions sur le contrôle de la boucle, vous devriez revoir le chapitre 3 avant de continuer. Les deux nouvelles
fonctions au sein de la boucle sont d'un intérêt primordial dans ce programme puisqu'il s'agit des nouvelles fonctions. Ce
sont des fonctions permettant de lire un caractère sur le clavier et de l'afficher sur le moniteur un caractère à la fois.

La fonction "getchar()" lit un seul caractère du périphérique d'entrée standard, le clavier étant supposé car il s'agit du
périphérique d'entrée standard, et l'affecte à la variable "c". La fonction suivante "putchar(c)", utilise le périphérique de
sortie standard, le moniteur vidéo, et génère le caractère contenu dans la variable "c". Le caractère est affiché à
l'emplacement actuel du curseur et le curseur avance d'un espace pour le caractère suivant. Le système prend donc en
charge une grande partie des frais généraux pour nous. La boucle continue de lire et d'afficher des caractères jusqu'à ce
que nous tapions un X majuscule qui termine la boucle.

À ce stade, nous devons mentionner que 1616/OS, Unix et MS­DOS font parfois des choses différentes, même dans des
domaines apparemment simples comme celui­ci. Dans certaines versions de HiTech C pour le 1616/OS, les caractères
sont répétés au fur et à mesure que vous les tapez, mais ne sont pas répétés lorsque vous appuyez sur la touche retour.
Cela est dû au fait que la fonction "getchar()" a été redéfinie comme la fonction 1616/OS "getch()", qui n'est pas exactement
la même.

Compilez et exécutez ce programme sur une machine MS­DOS pour quelques surprises. Lorsque vous tapez sur le
clavier, vous remarquerez que ce que vous tapez s'affiche fidèlement à l'écran, et lorsque vous appuyez sur la touche
retour, la ligne entière est répétée. En fait, nous ne lui avons dit d'afficher chaque caractère qu'une seule fois, mais il
semble sauvegarder les caractères et les réafficher. Une brève explication s’impose.

9.5 Dos nous aide (ou nous gêne)


Nous devons comprendre un peu le fonctionnement de MS­DOS pour comprendre ce qui se passe ici. Lorsque les
données sont lues à partir du clavier, sous contrôle MS­DOS, les caractères sont stockés dans un tampon jusqu'à ce
qu'un retour chariot soit saisi, moment auquel la chaîne entière de caractères est donnée au programme. Cependant,
pendant la saisie des caractères, ils sont affichés un par un sur le moniteur. C'est ce qu'on appelle l'écho et cela se produit
dans de nombreuses applications que vous utilisez.
courir.

Entrée/sortie standard Tutoriel C 9­2


En gardant
Machine Translated byleGoogle
paragraphe ci­dessus à l'esprit, il devrait être clair que lorsque vous tapez une ligne de données dans
"SIMPLEIO", les caractères sont repris par MS­DOS, et lorsque vous retournez le chariot, les caractères sont donnés au
programme. Au fur et à mesure que chaque caractère est donné au programme, il l'affiche à l'écran, ce qui entraîne une
répétition de la ligne saisie. Pour mieux illustrer cela, tapez une ligne avec un X majuscule quelque part au milieu de la
ligne. Vous pouvez taper autant de caractères que vous le souhaitez après le "X" et ils s'afficheront tous car les caractères
sont lus sous MS­DOS, renvoyés sur le moniteur et placés dans le tampon de saisie du clavier MS­DOS. MS­DOS ne
pense pas qu'il y ait quelque chose de spécial à propos d'un X majuscule. Cependant, lorsque la chaîne est donnée au
programme, les caractères sont acceptés par le programme un par un et envoyés au moniteur un à la fois, jusqu'à ce
qu'un message soit envoyé au moniteur. Un X majuscule est rencontré. Une fois le X majuscule affiché, la boucle est
terminée et le programme est terminé. Les caractères de la ligne de saisie qui suivent le X majuscule ne sont pas affichés
car le X majuscule signale la fin du programme.

Dans Applix 1616, la fonction stdio.h getchar() est définie dans stdio.h comme getch(), qui est fournie par 1616/OS, mais
n'est pas exactement identique aux résultats attendus de "getchar()". Le tampon du clavier est lu par getch() et les
caractères sont transmis directement au programme.
Dans le programme, les caractères sont renvoyés à l'écran par putchar() et le 1616/OS n'a qu'à changer la position du
curseur. Si vous omettez le #include "stdi.h", alors le compilateur HiTech C utilisera sa fonction par défaut "getchar()", qui
est correcte, et fonctionnera de la même manière que MS­DOS.

Compilez et exécutez "simpleio.c. Après avoir exécuté le programme plusieurs fois et après avoir été sûrs que vous
comprenez l'explication ci­dessus, nous passerons à un autre programme.

Ne vous laissez pas décourager par le comportement apparemment étrange du système d'E/S ci­dessus. C'est étrange,
mais il existe d'autres moyens d'introduire des données dans l'ordinateur. En fait, vous trouverez la méthode ci­dessus
utile pour de nombreuses applications, et vous trouverez probablement également certaines des méthodes suivantes utiles.

9.6 Une autre méthode d'E/S étrange


Chargez le fichier nommé singleio.c et affichez­le sur votre moniteur pour une autre méthode d'E/S de caractères. Encore
une fois, nous partons du fichier d'en­tête d'E/S standard, nous définissons une variable nommée "c", et nous imprimons
un message de bienvenue. Comme le dernier programme, nous sommes dans une boucle qui continuera à s'exécuter
jusqu'à ce que nous tapions un X majuscule, mais l'action est ici un peu différente.

# inclut "/sys/stdio.h" /* en­tête standard pour les entrées/sorties */


main( )

{ char c;
printf("Entrez n'importe quel caractère, terminez le programme avec X\n");
faire
{c = getch(); /* Obtient un personnage */
putchar(c); } while /* Afficher la touche d'activation */
(c != 'X'); printf("\nFin du
programme.\n");
}

Le "getch()" est une nouvelle fonction qui est une fonction "obtenir un caractère". Il diffère de "getchar()" en ce sens qu'il
n'est pas bloqué sous DOS. Il lit le caractère sans écho et le place directement dans le programme où il est immédiatement
utilisé. Cette fonction lit ensuite un caractère, l'affiche immédiatement à l'écran et continue l'opération jusqu'à ce qu'un X
majuscule soit tapé.
Vous reconnaîtrez que l'utilisation accidentelle de cette fonction "getch()" dans le #include "stdio.h" a causé des problèmes
dans le programme précédent.

Lorsque vous compilez et exécutez ce programme, vous constaterez qu'il n'y a pas de répétition des lignes lorsque vous
appuyez sur un retour chariot, et lorsque vous appuyez sur le X majuscule, le programme se termine immédiatement.
Aucun retour chariot n'est nécessaire pour qu'il accepte la ligne contenant le X. Nous avons un autre problème ici, il n'y a
pas de saut de ligne avec le retour chariot.

9­3 Tutoriel C Entrée/sortie standard


Machine Translated by Google
9.7 Nous avons maintenant besoin d'un saut de ligne

Cela ne vous apparaît pas clairement dans la plupart des programmes d'application, mais lorsque vous appuyez sur
la touche Entrée, le programme fournit un saut de ligne pour accompagner le retour chariot. Vous devez revenir sur
le côté gauche du moniteur et vous devez également dérouler une ligne. Le saut de ligne n'est pas automatique.
Nous devons également améliorer notre programme pour ce faire. Si vous chargez et affichez le programme
nommé bet­terin.c, vous trouverez un changement pour intégrer cette fonctionnalité.
# inclure "stdio.h" # définir CR
13 # définir LF 10 /* cela définit CR comme étant 13 */ /* cela définit
LF comme étant 10 */
main( )

{ char c;
printf("saisissez n'importe quel caractère, appuyez sur X pour arrêter.\n");
faire
{c = getch(); /* récupère un caractère */ /* affiche
putchar(c); si (c la touche hit */ /* s'il s'agit d'un retour
== CR) putchar(LF); chariot, émet également un saut de ligne */

} while (c != 'X');
printf("\nFin du programme.\n");
}

Dans betterin.c, nous avons deux instructions supplémentaires au début qui définiront les codes de caractères pour
le saut de ligne (LF) et le retour chariot (CR). Si vous regardez n'importe quel tableau ASCII, vous constaterez que
les codes 10 et 13 sont exactement tels que définis ici. Dans le programme principal, après avoir sorti le caractère,
nous produisons également un saut de ligne qui est le LF. Nous aurions tout aussi bien pu laisser de côté les deux
instructions #define et utiliser "if (c == 13) putchar(10);" mais cela ne serait pas très descriptif de ce que nous faisons
ici. La méthode utilisée dans le programme représente une meilleure pratique de programmation.

Compilez et exécutez betterin.c pour voir s'il fait ce que nous lui avons dit. Il doit afficher exactement ce que vous
tapez, y compris un saut de ligne à chaque retour chariot, et doit s'arrêter immédiatement lorsque vous tapez un X
majuscule.

Si vous utilisez un compilateur non standard, il se peut qu'il ne trouve pas de « CR » car votre système renvoie un
caractère « LF » pour indiquer la fin de ligne. Ce sera à vous de déterminer quelle méthode utilise votre compilateur.
Le moyen le plus rapide consiste à ajouter une instruction "printf" qui imprime le caractère saisi au format décimal.

9.8 Quelle méthode est la meilleure ?

Nous avons examiné deux méthodes de lecture de caractères dans un programme C et sommes confrontés au
choix de celle que nous devons utiliser. Cela dépend vraiment de l’application car chaque méthode présente des
avantages et des inconvénients. Jetons un coup d'œil à chacun.

Lorsque vous utilisez la première méthode, le 1616/OS fait tout le travail à notre place, en stockant les caractères
dans un tampon d'entrée et en nous signalant lorsqu'une ligne complète a été saisie. Nous pourrions écrire un
programme qui, par exemple, ferait beaucoup de calculs, puis irait chercher des informations. Pendant que nous
faisions les calculs, 1616/OS accumulait une ligne de caractères pour nous, et ils seraient là lorsque nous serions
prêts à les recevoir. Cependant, nous ne pouvions pas lire en une seule frappe car le 1616/OS ne nous rapportait
pas de tampon de caractères tant qu'il n'avait pas reconnu un retour chariot.

Entrée/sortie standard Tutoriel C 9­4


Machine Translated by méthode,
La deuxième Google utilisée dans betterin.c, nous permet d'obtenir un seul caractère et d'agir immédiatement dessus. Nous
n'avons pas besoin d'attendre que 1616/OS décide que nous pouvons avoir une ligne de caractères.
Nous ne pouvons rien faire d'autre pendant que nous attendons un caractère, car nous attendons la frappe du clavier et bloquons
toute la machine. Cette méthode est utile pour les types d'interfaces de programme hautement interactifs. C'est à vous, en tant que
programmeur, de décider ce qui convient le mieux à vos besoins.

Je dois mentionner à ce stade qu'il existe également une fonction "ungetch" qui fonctionne avec la fonction "getch". Si vous
« récupérez » un caractère et constatez que vous êtes allé trop loin, vous pouvez le « récupérer » sur le périphérique d'entrée. Cela
simplifie certains programmes car vous ne savez pas que vous ne voulez pas du personnage tant que vous ne l'avez pas obtenu.
Vous ne pouvez "extraire" qu'un seul caractère sur le périphérique d'entrée, mais cela est suffisant pour accomplir la tâche pour
laquelle cette fonction a été conçue. Il est difficile de démontrer cette fonction dans un programme simple donc son utilisation sera à
vous d'étudier quand vous en aurez besoin.

La discussion ainsi faite dans ce chapitre devrait être une bonne indication que, même si le langage de programmation C est très
flexible, il vous impose une grande responsabilité en tant que programmeur de garder de nombreux détails à l'esprit.

9.9 Maintenant, pour lire quelques entiers


Chargez et affichez le fichier nommé intin.c pour un exemple de lecture de certaines données formatées.
La structure de ce programme est très similaire aux trois derniers sauf que nous définissons une variable de type "int" et que nous
effectuons une boucle jusqu'à ce que la variable acquière d'une manière ou d'une autre la valeur de 100.

#include "/sys/stdio.h"
main( )

{ int valin;
printf("Saisissez un nombre de 0 à 2 milliards, arrêtez avec 100.\n");
faire
{ scanf("%d",&valin); printf("La /* lit une seule valeur entière dans */
valeur est %d\n",valin); } while (valin != 100);

printf("Fin du programme\n");
}

Au lieu de lire un caractère à la fois, comme nous l'avons fait dans les trois derniers fichiers, nous lisons une valeur entière entière
avec un seul appel en utilisant la fonction nommée "scanf". Cette fonction est très similaire à "printf" que vous utilisez depuis un
certain temps maintenant, sauf qu'elle est utilisée pour l'entrée au lieu de la sortie. Examinez la ligne avec le "scanf" et vous
remarquerez qu'elle ne demande pas directement la variable "valin", mais donne l'adresse de la variable puisqu'elle s'attend à ce
qu'une valeur soit renvoyée pour la fonction. Rappelons qu'une fonction doit avoir l'adresse d'une variable pour pouvoir renvoyer la
valeur au programme appelant. Ne pas fournir de pointeur dans la fonction "scanf" est probablement le problème le plus courant
rencontré lors de l'utilisation de cette fonction.

La fonction "scanf" scanne la ligne d'entrée jusqu'à ce qu'elle trouve le premier champ de données. Il ignore les espaces de début et
dans ce cas, il lit les caractères entiers jusqu'à ce qu'il trouve un espace ou un caractère décimal invalide, moment auquel il arrête la
lecture et renvoie la valeur.

En vous souvenant de notre discussion ci­dessus sur la façon dont fonctionne le tampon d'entrée du 1616/OS, il devrait être clair que
rien n'est réellement effectué jusqu'à ce qu'une ligne complète soit entrée et se termine par un retour chariot. À ce moment­là, la
lecture du tampon est entrée et notre programme recherchera sur la ligne en lisant toutes les valeurs entières qu'il peut trouver
jusqu'à ce que la ligne soit complètement analysée. C'est parce que nous sommes dans une boucle et nous lui disons de trouver une
valeur, de l'imprimer, d'en trouver une autre, de l'imprimer, etc. Si vous entrez

9h à 17h Tutoriel C Entrée/sortie standard


plusieursby
Machine Translated valeurs sur une ligne, il les lira successivement et affichera les valeurs. Entrer la valeur 100 entraînera la fin du
Google
programme et la responsabilité accrue que vous devrez assumer en utilisant C plutôt qu'un langage de niveau supérieur
tel que Pascal, Modula­2, etc.

Le paragraphe ci­dessus est vrai pour le compilateur HiTech C pour Applix, qui utilise des entiers 32 bits.
Les compilateurs MS­DOS utilisent généralement une valeur entière de 16 bits et n'acceptent donc que des valeurs
d'entrée allant jusqu'à 32 767. Si votre compilateur est différent, les mêmes principes seront vrais mais à des limites
différentes de celles indiquées ci­dessus.

Compilez et exécutez ce programme, en entrant plusieurs nombres sur une ligne pour voir les résultats, et avec un
nombre variable d'espaces entre les nombres. Essayez de saisir des nombres trop grands pour voir ce qui se passe, et
enfin saisissez des caractères non valides pour voir ce que le système fait avec les caractères non décimaux.

9.10 Saisie d'une chaîne de caractères


Chargez et affichez le fichier nommé stringin.c pour un exemple de lecture d'une variable chaîne.
Ce programme est identique au précédent sauf qu'au lieu d'une variable entière, nous avons défini une variable chaîne
avec une limite supérieure de 24 caractères (rappelez­vous qu'une variable chaîne doit avoir un caractère nul à la fin).

#include "/sys/stdio.h"
main( )

{ char gros[25];
printf("Saisissez une chaîne de caractères, jusqu'à 25 caractères.\n"); printf("Un X dans la
colonne 1 provoque l'arrêt du programme.\n");
faire

{ scanf("%s",grand);
printf("La chaîne est ­> %s\n",big); } while (big[0] !='X');

printf("Fin du programme.\n");
}

La variable dans le "scanf" n'a pas besoin d'un & car "big" est une variable tableau et par définition c'est déjà un pointeur.
Ce programme ne devrait nécessiter aucune explication supplémentaire. Compilez­le et exécutez­le pour voir s'il
fonctionne comme vous le souhaitez.

Vous avez probablement eu une surprise lorsque vous l'avez exécuté car il séparait votre phrase en mots séparés.
Lorsqu'il est utilisé en mode de saisie chaîne, "scanf" lit les caractères dans la chaîne jusqu'à ce qu'elle arrive à la fin
d'une ligne ou à un caractère vide. Par conséquent, il lit un mot, trouve le blanc qui le suit et affiche le résultat. Puisque
nous sommes dans une boucle, ce programme continue de lire les mots jusqu'à épuiser le tampon d'entrée DOS. Nous
avons écrit ce programme pour qu'il s'arrête chaque fois qu'il trouve un X majuscule dans la colonne 1, mais comme la
phrase est divisée en mots individuels, il s'arrêtera chaque fois qu'un mot commence par un X majuscule. Essayez
d'entrer une phrase de 5 mots avec un X majuscule comme le premier caractère du troisième mot. Vous devriez voir les
trois premiers mots affichés et les deux derniers simplement ignorés lorsque le programme s'arrête.

Essayez de saisir plus de 24 caractères pour voir ce que fait le programme. Cela devrait générer une erreur, mais cela
dépendra fortement du système que vous utilisez. Dans un programme réel, il est de votre responsabilité de compter les
caractères et de vous arrêter lorsque le tampon d'entrée est plein. Vous avez peut­être le sentiment qu'une grande
responsabilité vous incombe lorsque vous écrivez en C. C'est vrai, mais vous bénéficiez également d'une grande flexibilité
dans le marché.

Entrée/sortie standard Tutoriel C 9­6


Machine Translated by Google
9.11 Programmation des entrées/sorties en C
Le C n’a pas été conçu pour être utilisé comme un langage permettant de nombreuses entrées et sorties, mais comme un
langage système nécessitant de nombreuses opérations internes. Vous feriez bien d'utiliser un autre langage pour la
programmation intensive en E/S, mais le C pourrait être utilisé si vous le désirez. La saisie au clavier est très flexible, vous
permettant d'accéder aux données de très bas niveau, mais très peu d'aide vous est apportée. C'est donc à vous de vous
occuper de toutes les tâches comptables associées à vos opérations d'E/S requises. Cela peut sembler un vrai casse­tête,
mais dans un programme donné, il vous suffit de définir vos routines de saisie une seule fois, puis de les utiliser selon vos
besoins.

Ne laissez pas cela vous inquiéter. Au fur et à mesure que vous gagnerez en expérience avec le C, vous gérerez facilement
vos besoins en E/S.

Un dernier point doit être fait à propos de ces fonctions d'E/S. Il est parfaitement permis de mélanger les fonctions "scanf" et
"getchar" lors des opérations de lecture. De la même manière, il est également possible de mélanger les fonctions de sortie
"printf" et "putchar".

9.12 E/S en mémoire


La prochaine opération peut sembler un peu étrange au début, mais vous en verrez probablement de nombreuses utilisations
à mesure que vous gagnerez en expérience. Chargez le fichier nommé inmem.c et affichez­le pour un autre type d'E/S, celui
qui n'accède jamais au monde extérieur, mais reste dans l'ordinateur. main( ) { int
nombres[5],

résultat[5], index ; ligne de caractères[80] ;

nombre[0] = 74 ;
nombre[1] = 18 ;
nombre[2] = 33 ;
nombre[3] = 30 ;
nombre[4] = 97 ;
sprintf(ligne,%d %d %d %d %d\n",nombres[0],nombres[1],
nombres[2],nombres[3],nombres[4]);
printf("%s",ligne);
sscanf(ligne,"%d %d %d %d %d",&result[4],&result[3], (résultat+2),
(résultat+1),résultat);
pour (index = 0;index < 5;index++)

printf("Le résultat final est %d\n",result[index]);


}

Dans inmem.c, nous définissons quelques variables, puis attribuons des valeurs à celles nommées "nombres" à des fins
d'illustration, puis utilisons une fonction "sprintf" sauf qu'au lieu d'imprimer la ligne de sortie sur un périphérique, elle imprime
la ligne de la sortie formatée en une chaîne de caractères en mémoire. Dans ce cas, la chaîne va à la variable chaîne "line",
car c'est le nom de chaîne que nous avons inséré comme premier argument dans la fonction "sprintf". Les espaces après le
2ème %d ont été placés là pour illustrer que la fonction suivante recherchera correctement sur toute la ligne. Nous imprimons
la chaîne résultante et constatons que la sortie est identique à ce qu'elle aurait été en utilisant un "printf" au lieu du "sprintf" en
premier lieu. Vous le verrez lorsque vous compilerez et exécuterez le programme sous peu.

Puisque la chaîne générée est toujours en mémoire, on peut désormais la lire avec la fonction "sscanf". Nous disons à la
fonction dans son premier argument que "line" est la chaîne à utiliser pour son entrée, et les parties restantes de la ligne sont
exactement ce que nous utiliserions si nous devions utiliser la fonction "scanf" et lire des données de l'extérieur. l'ordinateur.
Notez qu'il est essentiel que nous utilisions des pointeurs vers les données car nous souhaitons renvoyer les données d'une
fonction. Juste pour illustrer qu'il existe de nombreuses façons de déclarer un pointeur, plusieurs méthodes sont utilisées, mais
toutes sont des pointeurs. Les deux premiers déclarent simplement

9­7 Tutoriel C Entrée/sortie standard


l'adresse by
Machine Translated desGoogle
éléments des tableaux, tandis que les trois derniers utilisent le fait que "result", sans l'indice qui l'accompagne,
est un pointeur. Juste pour que cela reste intéressant, les valeurs sont lues dans l’ordre inverse. Enfin, les valeurs sont
affichées sur le moniteur.

9.13 Est­ce vraiment utile ?


Cela semble un peu idiot de lire des données d’entrée depuis l’ordinateur, mais cela a un véritable objectif.
Il est possible de lire des données en utilisant n'importe laquelle des fonctions standards, puis d'effectuer une conversion de
format en mémoire. Vous pouvez lire une ligne de données, examiner quelques caractères significatifs, puis utiliser ces
routines de saisie formatées pour réduire la ligne de données à une représentation interne. Cela serait certainement préférable
à l'écriture de vos propres routines de formatage de données.

9.14 Sortie d'erreur standard


Il est parfois souhaitable de rediriger la sortie du périphérique de sortie standard vers un fichier. Cependant, vous souhaiterez
peut­être toujours que les messages d'erreur soient envoyés au périphérique de sortie standard, dans notre cas, le moniteur.
Cette fonction suivante vous permet de le faire dans les systèmes MS­DOS. Chargez et affichez special.c pour un exemple
de cette nouvelle fonction. #include "/sys/stdio.h"

main( )

{ int index ;
pour (index = 0;index < 6;index++) {
printf("Cette ligne va vers la sortie standard.\n"); fprintf(stderr,"Cette ligne va au
périphérique d'erreur.\n");
}

sortie(4); /*
Cela peut être testé avec la commande MS­DOS errorlevel dans un fichier batch.
Le numéro renvoyé est utilisé comme suit :

SI NIVEAU D'ERREUR 4, ALLEZ À QUATRE


(continuez ici si moins de 4)
.
.
ALLER À TERMINÉ
:QUATRE
(continuez ici si 4 ou plus)
.
.
:FAIT */

Le programme consiste en une boucle avec deux messages émis, l'un vers le périphérique de sortie standard et l'autre vers
le périphérique d'erreur standard. Le message adressé à la norme inclut le nom du périphérique « stderr » comme premier
argument. A part ces deux petits changements, c'est la même chose que notre fonction standard "printf". (Vous verrez
davantage la fonction "fprintf" dans le prochain chapitre, mais son fonctionnement s'intègre mieux dans le cadre de ce
chapitre.) Ignorez la ligne avec "exit" pour le moment, nous y reviendrons.

Compilez et exécutez ce programme, et vous trouverez 12 lignes de sortie sur le moniteur. Pour voir la différence, exécutez
à nouveau le programme avec la sortie redirigée vers un fichier nommé « STUFF » en entrant la ligne suivante à l'invite 1616/
OS ; F0/ spécial >trucs

Entrée/sortie standard Tutoriel C 9­8


Machine Translated by Google
Vous trouverez plus d’informations sur la redirection d’E/S dans votre manuel d’utilisation du 1616/OS. Cette fois, vous
n'obtiendrez que les 6 lignes de sortie vers le périphérique d'erreur standard, et si vous regardez dans votre répertoire, vous
trouverez le fichier nommé "STUFF" contenant les 6 autres lignes, celles vers le périphérique de sortie standard. Vous pouvez
utiliser la redirection d'E/S avec n'importe lequel des programmes que nous avons exécutés jusqu'à présent, et comme vous
pouvez le deviner, vous pouvez également lire à partir d'un fichier en utilisant la redirection d'E/S, mais nous étudierons une
meilleure façon de lire à partir d'un fichier dans le Chapitre suivant.

9.15 Qu'en est­il de l'instruction Exit(4) ?


Maintenant, tenons notre promesse concernant l'instruction exit(4). Réaffichez le fichier nommé special.c sur votre moniteur. La
dernière instruction quitte simplement le programme et renvoie la valeur 4 à MS­DOS. N'importe quel nombre de 0 à 9 peut être
utilisé entre parenthèses pour la communication DOS. Si vous travaillez dans un fichier BATCH, ce numéro peut être testé avec
la commande "ERRORLEVEL". Notez que ces caractéristiques s'appliquent uniquement à MS­DOS.

La plupart des compilateurs qui fonctionnent en plusieurs passes renvoient un 1 avec ce mécanisme pour indiquer qu'une erreur
fatale s'est produite et que ce serait une perte de temps de passer à une autre passe, ce qui entraînerait
encore plus d'erreurs.

Il est donc judicieux d'utiliser un fichier batch pour compiler les programmes et tester la valeur renvoyée pour
les erreurs.

9.16 Exercice de programmation


1. Écrivez un programme pour lire un caractère à l'aide d'une boucle et affichez le caractère sous sa forme normale "char".
Affichez­le également sous forme de nombre décimal. Recherchez un signe dollar à utiliser comme caractère d'arrêt. Utilisez le
formulaire de saisie "getch" pour qu'il s'imprime immédiatement. Appuyez sur certaines touches spéciales, telles que les touches
de fonction, lorsque vous exécutez le programme pour avoir des surprises. Vous obtiendrez deux entrées à partir des touches
spéciales dans les systèmes MS­DOS, la première étant un zéro qui indique au système qu'une touche spéciale a été appuyée.
Cela n'arrivera pas avec le 1616/OS. Les touches de fonction renvoient des zéros non significatifs (puisque cela est fait par le
microprocesseur situé à l'intérieur du clavier), mais le pilote du clavier 1616/OS ne les transmet pas au programme. La façon
de contourner ce problème est d'utiliser l'appel système .29 pour redéfinir les touches de fonction, afin qu'elles transmettent la
chaîne de caractères que vous désirez au programme. Voir le fichier vc.c function initfk() pour un exemple clair de ceci.

9­9 Tutoriel C Entrée/sortie standard


Machine Translated by Google
dix
Entrée/Sortie de fichier

10.1 Sortie vers un fichier


Chargez et affichez le fichier nommé formout.c pour votre premier exemple d'écriture de données dans un fichier.
#include "/sys/stdio.h" main( ) { FILE
*fp; trucs

de char[25];
indice int ;

fp = fopen("TENLINES.TXT","w"); /* ouvert en écriture */ strcpy(stuff,"Ceci est un exemple de


ligne.");
for (index = 1;index <= 10;index++) fprintf(fp,"%s
Numéro de ligne %d\n",stuff,index);
fclose(fp); /* ferme le fichier avant de terminer le programme */
}

Nous commençons comme avant par l'instruction "include" pour "stdio.h", puis définissons quelques variables à utiliser
dans l'exemple, y compris un nouveau type plutôt étrange.

Le type "FILE" est utilisé pour une variable de fichier et est défini dans le fichier "stdio.h". Il est utilisé pour définir un pointeur
de fichier à utiliser dans les opérations sur les fichiers. La définition de C contient l'exigence d'un pointeur vers un "FILE",
et comme d'habitude, le nom peut être n'importe quel nom de variable valide.

10.2 Ouverture d'un fichier


Avant de pouvoir écrire dans un fichier, nous devons l'ouvrir. Ce que cela signifie réellement, c'est que nous devons indiquer
au système que nous voulons écrire dans un fichier et quel est son nom. Nous faisons cela avec la fonction "fopen" illustrée
dans la première ligne du programme. Le pointeur de fichier, "fp" dans notre cas, pointe vers le fichier et deux arguments
sont requis entre parenthèses, le nom du fichier en premier, suivi du type de fichier. Le nom de fichier est n'importe quel
nom de fichier 1616/OS valide et peut être exprimé en lettres majuscules ou minuscules, ou même mélangé si vous le
souhaitez. Il est entouré de guillemets doubles. Pour cet exemple, nous avons choisi le nom TENLINES.TXT. Ce fichier ne
devrait pas exister sur votre disque pour le moment.
Si vous avez un fichier avec ce nom, vous devez changer son nom ou le déplacer car lorsque nous exécuterons ce
programme, son contenu sera effacé. Si vous n'avez pas de fichier portant ce nom, c'est bien car nous allons en créer un
et y mettre des données.

LECTURE ("r")

Le deuxième paramètre est l'attribut du fichier et peut être l'une des trois lettres suivantes : "r", "w" ou "a", et doit être en
minuscules. Lorsqu'un "r" est utilisé, le fichier est ouvert en lecture, un "w" est utilisé pour indiquer un fichier à utiliser pour
l'écriture et un "a" indique que vous souhaitez ajouter des données supplémentaires aux données déjà présentes dans un
fichier. fichier existant. L'ouverture d'un fichier en lecture nécessite que le fichier existe déjà.
S'il n'existe pas, le pointeur de fichier sera défini sur NULL et pourra être vérifié par le programme.

ÉCRITURE ("w")

Lorsqu'un fichier est ouvert en écriture, il sera créé s'il n'existe pas déjà et il sera réinitialisé s'il existe, entraînant la
suppression de toutes les données déjà présentes.

ANNEXE ("a")

Entrée/Sortie de fichier Tutoriel C 10­1


Lorsqu'un
Machine Translated byfichier
Googleest ouvert pour être ajouté, il sera créé s'il n'existe pas déjà et il sera initialement vide. S'il existe, le point
d'entrée des données sera la fin des données actuelles afin que toute nouvelle donnée soit ajoutée à toutes les données
qui existent déjà dans le fichier.

10.3 Sortie vers le fichier


Le travail de sortie vers le fichier est presque identique à la sortie que nous avons déjà effectuée sur le périphérique de
sortie standard. Les seules vraies différences résident dans les nouveaux noms de fonctions et l'ajout du pointeur de fichier
comme argument de la fonction. Dans l'exemple de programme, "fprintf" remplace notre nom de fonction familier "printf", et
le pointeur de fichier défini précédemment est le premier argument entre parenthèses. Le reste de l'instruction ressemble,
et est en fait identique, à l'instruction "printf".

10.4 Fermeture d'un fichier


Pour fermer un fichier, vous utilisez simplement la fonction "fclose" avec le pointeur de fichier entre parenthèses.
En fait, dans ce programme simple, il n'est pas nécessaire de fermer le fichier car le système fermera tous les fichiers
ouverts avant de revenir au DOS. Ce serait une bonne pratique de programmation que vous preniez l'habitude de fermer
tous les fichiers malgré le fait qu'ils seront fermés automatiquement, car cela vous rappellerait quels fichiers sont ouverts à
la fin de chaque programme.

Vous pouvez ouvrir un fichier en écriture, le fermer et le rouvrir en lecture, puis le fermer et l'ouvrir à nouveau pour l'ajouter,
etc. Chaque fois que vous l'ouvrez, vous pouvez utiliser le même pointeur de fichier ou un autre. un. Le pointeur de fichier
est simplement un outil que vous utilisez pour pointer vers un fichier et vous décidez vers quel fichier il pointera.

Compilez et exécutez ce programme. Lorsque vous l'exécutez, vous n'obtiendrez aucune sortie sur le moniteur car il n'en
génère aucune. Après l'avoir exécuté, recherchez dans votre répertoire un fichier nommé TENLINES.TXT et "tapez­le".
C'est là que sera votre sortie. Comparez la sortie avec celle spécifiée dans le programme. Il faudrait être d'accord.

N'effacez pas encore le fichier nommé TENLINES.TXT. Nous l'utiliserons dans certains des autres exemples de ce chapitre.

10.5 Sortie d'un seul caractère à la fois


Chargez le fichier d'exemple suivant, charout.c, et affichez­le sur votre moniteur. Ce programme illustrera comment afficher
un seul caractère à la fois. #include "/sys/stdio.h" main() { FILE
*point; char d'autres[35]; indexeur int,
nombre ;

strcpy(autres,"Lignes supplémentaires."); point =


fopen("tenlines.txt","a"); /* ouvert pour ajout */ for (count = 1;count <= 10;count++) {

pour (indexeur = 0;autres[indexeur];indexeur++)


putc(autres[indexeur],point); /* affiche un seul caractère */ putc('\n',point); /* affiche un saut de ligne */

} fclose(point);
}

10­2 Tutoriel C Entrée/Sortie de fichier


Le programme
Machine Translated commence par l'instruction "include", puis définit certaines variables incluant un pointeur de fichier. Nous avons
by Google
appelé le pointeur de fichier "point" cette fois, mais nous aurions pu utiliser n'importe quel autre nom de variable valide. Nous
définissons ensuite une chaîne de caractères à utiliser dans la fonction de sortie à l'aide d'une fonction "strcpy". Nous sommes
prêts à ouvrir le fichier pour l'ajouter et nous le faisons dans la fonction "fopen", sauf que cette fois nous utilisons les minuscules
pour le nom du fichier. Ceci est fait simplement pour illustrer que le DOS ne se soucie pas de la casse du nom de fichier. Notez
que le fichier sera ouvert pour être ajouté, nous l'ajouterons donc aux lignes insérées lors du dernier programme.

Le programme est en fait constitué de deux boucles "for" imbriquées. La boucle externe consiste simplement à compter jusqu’à
dix, de sorte que nous parcourrons la boucle interne dix fois. La boucle interne appelle la fonction « putc » à plusieurs reprises
jusqu'à ce qu'un caractère dans « autres » soit détecté comme étant un zéro.

10.6 La fonction "Putc"


La partie du programme qui nous intéresse est la fonction "putc". Il génère un caractère à la fois, le caractère étant le premier
argument entre parenthèses et le pointeur de fichier étant le deuxième et dernier argument. Pourquoi le concepteur de C a créé le
pointeur en premier dans la fonction "fprintf" et en dernier dans la fonction "putc" est une bonne question à laquelle il n'y a peut­
être pas de réponse. Il semble que cela aurait été un bon endroit pour faire preuve de cohérence.

Lorsque la ligne de texte « autres » est épuisée, une nouvelle ligne est nécessaire car une nouvelle ligne n'a pas été incluse dans
la définition ci­dessus. Un seul "putc" est ensuite exécuté qui génère le caractère "\n" pour renvoyer le chariot et effectuer un saut
de ligne.

Lorsque la boucle externe a été exécutée dix fois, le programme ferme le fichier et se termine.
Compilez et exécutez ce programme, mais encore une fois, il n'y aura aucune sortie sur le moniteur.

Suite à l'exécution du programme, "tapez" le fichier nommé TENLINES.TXT et vous verrez que les 10 nouvelles lignes ont été
ajoutées à la fin des 10 qui existaient déjà. Si vous l'exécutez à nouveau, 10 lignes supplémentaires seront ajoutées. Encore une
fois, n’effacez pas ce fichier car nous n’en avons toujours pas fini.

10.7 Lecture d'un fichier


Chargez le fichier nommé readchar.c et affichez­le sur votre moniteur. C'est notre premier programme pour lire un fichier.

#include "/sys/stdio.h"
principal( )
{
FICHIER *drôle ;
int c;
drôle = fopen("TENLINES.TXT","r"); if (drôle == NULL)
printf("Le fichier n'existe pas\n"); else { do { c = getc (drôle); /* récupère un
caractère
du
fichier /* l'affiche sur le moniteur */ putchar(c); } while (c != EOF); /* répéter jusqu'à EOF */
(fin du fichier)
*/

} fclose(drôle);
}

Ce programme commence par le familier "include", quelques définitions de données et l'instruction d'ouverture de fichier qui ne
devrait nécessiter aucune explication, sauf le fait qu'un "r" est utilisé ici parce que nous voulons le lire. Dans ce programme, nous
vérifions que le fichier existe, et si c'est le cas, nous exécutons le corps principal du programme. Si ce n'est pas le cas, nous
imprimons un message et quittons. Si le fichier n'existe pas, le système définira le pointeur égal à NULL que nous pourrons tester.

Entrée/Sortie de fichier Tutoriel C 10­3


Le corps by
Machine Translated principal
Googledu programme est une boucle "do while" dans laquelle un seul caractère est lu à partir du fichier et affiché
sur le moniteur jusqu'à ce qu'un EOF (fin de fichier) soit détecté dans le fichier d'entrée. Le fichier est ensuite fermé et le
programme est terminé.
ATTENTION ATTENTION ATTENTION

À ce stade, nous sommes potentiellement confrontés à l'un des problèmes de programmation les plus courants et les plus
déroutants en C. La variable renvoyée par la fonction "getc" est un caractère, nous pourrions donc utiliser une variable
"char" à cette fin. Il y a cependant un problème avec cela, car sur certaines implémentations de C, sinon la plupart, l'EOF
renvoie un moins qu'une variable de type "char" n'est pas capable de contenir. Une variable de type "char" ne peut avoir
que des valeurs comprises entre zéro et 255, elle renverra donc un 255 pour un moins un sur les compilateurs qui utilisent
un moins un pour EOF. Il s’agit d’un problème très frustrant à rechercher car aucun diagnostic n’est donné. Le programme
ne pourra tout simplement jamais trouver l'EOF et ne terminera donc jamais la boucle. Ceci est facile à éviter, utilisez
toujours une variable de type "int" pour renvoyer un EOF. Vous pouvez savoir ce que votre compilateur utilise pour EOF en
consultant le fichier "stdio.h" où EOF est défini. C'est l'endroit habituel pour définir de telles valeurs.

Il y a un autre problème avec ce programme, mais nous nous en soucierons lorsque nous arriverons au prochain programme
et le résoudrons avec celui qui suit.

Une fois que vous avez compilé et exécuté ce programme et que vous êtes satisfait des résultats, ce serait un bon exercice
de changer le nom de "TENLINES.TXT" et d'exécuter à nouveau le programme pour voir que le test NULL fonctionne
réellement comme indiqué. Assurez­vous de modifier à nouveau le nom car nous n'en avons toujours pas fini avec
"TENLINES.TXT".

10.8 Lire un mot à la fois


Chargez et affichez le fichier nommé readtext.c pour un exemple de la façon de lire un mot à la fois.
#include "/sys/stdio.h"
principal( )
{
FICHIER *fp1 ;
char un mot[100]; int c;

fp1 = fopen("TENLINES.TXT","r");

faire
{ c = fscanf(fp1,"%s",un mot); /* a obtenu un mot du fichier */ printf("%s\n",oneword); /* l'afficher sur
le moniteur */ } while (c != EOF); /* répéter jusqu'à EOF */

fclose(fp1);
}

Ce programme est presque identique au précédent sauf qu'il utilise la fonction "fscanf" pour lire une chaîne à la fois. Étant
donné que la fonction "fscanf" arrête la lecture lorsqu'elle trouve un espace ou un caractère de nouvelle ligne, elle lira un
mot à la fois et affichera les résultats mot par ligne.
Vous le verrez lorsque vous le compilerez et l’exécuterez, mais nous devons d’abord examiner un problème de
programmation.

10.9 C'est un problème

L'inspection du programme révélera que lorsque nous lisons des données et détectons l'EOF, nous imprimons quelque
chose avant de vérifier l'EOF, ce qui entraîne une ligne d'impression supplémentaire. Ce que nous imprimons habituellement
est la même chose imprimée lors du passage précédent dans la boucle, car elle est toujours

10­4 Tutoriel C Entrée/Sortie de fichier


dans le tampon
Machine Translated "oneword". Il faut donc vérifier EOF avant d'exécuter la fonction "printf". Cela a été fait dans readgood.c,
by Google
que vous allez bientôt examiner, compiler et exécuter.

Compilez et exécutez le programme original que nous avons étudié, readtext.c et observez le résultat. Si vous n'avez pas
modifié TENLINES.TXT, vous vous retrouverez avec "Supplémentaire" et "lignes". sur deux lignes distinctes avec des
"lignes" supplémentaires. affiché à cause du "printf" avant de vérifier EOF.

Compilez et exécutez readgood.c et observez que les "lignes" supplémentaires. ne s'affiche pas en raison de la vérification
supplémentaire de l'EOF au milieu de la boucle. C'est également le problème évoqué lorsque nous avons examiné
readchar.c, mais j'ai choisi de ne pas l'exposer ici car l'erreur dans la sortie n'était pas si évidente.

10.10 Enfin, nous lisons une ligne complète


Chargez et affichez le fichierreadline.cpour un exemple de lecture d'une ligne complète. Ce programme est très similaire à
ceux que nous avons étudiés à l'exception de l'ajout d'une nouvelle quantité, le NULL.

#include "/sys/stdio.h"
principal( )
{
FICHIER *fp1 ;
char un mot[100]; char *c;

fp1 = fopen("TENLINES.TXT","r");
faire
{ c = fgets (un mot, 100, fp1); /* récupère une ligne du fichier */ if (c != NULL); printf("%s",un mot); /*
l'afficher sur le moniteur
*/ /* répéter jusqu'à NULL
} while (c != NULL); */

fclose(fp1);
}

Nous utilisons "fgets" qui lit une ligne entière, y compris le caractère de nouvelle ligne, dans un tampon.
Le tampon à lire est le premier argument de l'appel de fonction, et le nombre maximum de caractères à lire est le deuxième
argument, suivi du pointeur de fichier. Cette fonction lira les caractères dans le tampon d'entrée jusqu'à ce qu'elle trouve un
caractère de nouvelle ligne ou qu'elle lise le nombre maximum de caractères autorisés moins un. Il laisse un caractère pour
la fin de la chaîne, le caractère NULL. De plus, s’il trouve un EOF, il renverra une valeur NULL. Dans notre exemple, lorsque
l'EOF est trouvé, le pointeur "c" se verra attribuer la valeur NULL. NULL est défini comme zéro dans votre fichier "stdio.h".

Lorsque nous constatons que "c" a reçu la valeur NULL, nous pouvons arrêter le traitement des données, mais nous devons
vérifier avant d'imprimer, comme dans le programme précédent.

Enfin bien sûr, nous fermons le dossier.

10.11 Comment utiliser un nom de fichier variable


Chargez et affichez le fichier anyfile.c pour un exemple de lecture à partir de n'importe quel fichier. Ce programme demande
à l'utilisateur le nom de fichier souhaité, lit le nom de fichier et ouvre ce fichier en lecture. Le fichier entier est ensuite lu et
affiché sur le moniteur. Cela ne devrait poser aucun problème à votre compréhension donc aucun commentaire
supplémentaire ne sera fait.

#include "stdio.h"

Entrée/Sortie de fichier Tutoriel C 10­5


principal( by
Machine Translated ) Google
{
FICHIER *fp1 ;
char oneword[100],filename[25]; char *c;

printf("entrez le nom du fichier ­> "); scanf("%s",nom


de fichier); fp1 = fopen(nom de /* lit le nom de fichier souhaité */
fichier,"r");
faire
{ c = fgets (un mot, 100, fp1); /* récupère une ligne du fichier */ if (c != NULL) printf("%s",oneword);

/* l'afficher sur le moniteur */ /* répéter jusqu'à NULL


} while (c != NULL); */

fclose(fp1);
}

Compilez et exécutez ce programme. Lorsqu'il demande un nom de fichier, entrez le nom et l'extension de n'importe quel
fichier texte disponible, même l'un des exemples de programmes C.

10.12 Comment imprimons­nous ?

Chargez le dernier fichier d'exemple de ce chapitre, celui nommé printdat.c pour un exemple de comment imprimer. Ce
programme ne devrait pas vous surprendre, nous allons donc le parcourir très rapidement.

#include "/sys/stdio.h"
principal( )
{
FICHIER *drôle,*imprimante ; int c;

drôle = fopen("TENLINES.TXT","r"); /* ouvre le fichier d'entrée imprimante = fopen("PRN","w"); / */


* ouvre le fichier imprimante */
faire
{ c = getc (drôle); /* a obtenu un caractère du fichier */ if (c != EOF) { putchar(c); /* l'afficher sur
le moniteur */
putc(c,printer); /* affiche le caractère */

} } while (c != EOF); /* répéter jusqu'à EOF (fin du fichier) */


fclose(drôle);
fclose(imprimante);
}

Encore une fois, nous ouvrons TENLINES.TXT pour la lecture et nous ouvrons PRN pour l'écriture. L'impression est
identique à l'écriture de données sur un fichier disque, sauf que nous utilisons un nom standard pour le nom de fichier. Il
n'existe pas de normes définies en ce qui concerne le ou les noms à utiliser pour l'imprimante, mais les noms du 1616/OS
sont « CENT : », « SA : » et « SB : ». Vérifiez votre documentation pour votre implémentation particulière.

Certains des compilateurs MS­DOS les plus récents utilisent un pointeur de fichier prédéfini tel que « stdprn » pour le fichier
d'impression. Encore une fois, vérifiez votre documentation.

Le programme est simplement une boucle dans laquelle un caractère est lu, et si ce n'est pas l'EOF, il est affiché et imprimé.
Lorsque l'EOF est trouvé, le fichier d'entrée et les fichiers de sortie de l'imprimante sont tous deux fermés.

Vous pouvez maintenant effacer TENLINES.TXT de votre disque. Nous ne l’utiliserons dans aucun des chapitres suivants.

10­6 Tutoriel C Entrée/Sortie de fichier


Machine Translated by Google
10.13 Exercices de programmation
1. Écrivez un programme qui demandera un nom de fichier pour un fichier lu, demandera un nom de fichier pour un
écrivez le fichier et ouvrez les deux ainsi qu'un fichier sur l'imprimante. Entrez une boucle qui lira un caractère, et
envoyez­le au fichier, à l'imprimante et au moniteur. Arrêtez­vous à EOF.

2. Demander un nom de fichier à lire. Lisez le fichier ligne par ligne et affichez­le sur le moniteur
avec les numéros de lignes.

Entrée/Sortie de fichier Tutoriel C 10­7


Machine Translated by Google
11
Structures et syndicats

11.1 Qu'est­ce qu'une structure ?

Une structure est un type de données défini par l'utilisateur. Vous avez la possibilité de définir un nouveau type de
données considérablement plus complexe que les types que nous utilisons. Une structure est une combinaison de
plusieurs types de données différents préalablement définis, y compris d'autres structures que nous avons définies.
Une définition facile à comprendre est qu'une structure est un regroupement de données liées d'une manière
pratique pour le programmeur ou l'utilisateur du programme. La meilleure façon de comprendre une structure est
de regarder un exemple, donc si vous chargez et affichez struct1.c, c'est exactement ce que nous ferons.
principal( )
{
struct { char
initial ; /* initiale du nom de famille */ int âge; */ note int ; /* note
de l'enfant à l'école */ } garçon,
/* âge de
fille;
l'enfant

garçon.initial = 'R';
garçon.âge = 15 ;
garçon.grade = 75 ;
fille.âge = garçon.âge ­ 1 ; fille.grade /* elle a un an de moins */
= 82 ; fille.initial = 'H';

printf("%c a %d ans et a obtenu une note de %d\n",


fille.initiale, fille.âge, fille.grade);
printf("%c a %d ans et a obtenu une note de %d\n",
garçon.initial, garçon.âge, garçon.grade);
}

Le programme commence par une définition de la structure. Le mot clé « struct » est suivi de quelques variables
simples entre les accolades, qui sont les composants de la structure. Après l'accolade fermante, vous trouverez
deux variables répertoriées, à savoir « garçon » et « fille ». Selon la définition d'une structure, « garçon » est
désormais une variable composée de trois éléments, « initiale », « âge » et « grade ».
Chacun des trois champs est associé à "boy", et chacun peut stocker une variable de son type respectif. La variable
"fille" est également une variable contenant trois champs portant les mêmes noms que ceux de "garçon" mais qui
sont en réalité des variables différentes. Nous avons donc défini 6 variables simples.

11.2 Une variable composée unique


Examinons de plus près la variable « garçon ». Comme indiqué ci­dessus, chacun des trois éléments de "boy" sont
des variables simples et peuvent être utilisés n'importe où dans un programme C où une variable de leur type peut
être utilisée. Par exemple, l'élément "age" est une variable entière et peut donc être utilisé n'importe où dans un
programme C où il est légal d'utiliser une variable entière, dans des calculs, comme compteur, dans des opérations
d'E/S, etc. Le seul problème nous devons définir comment utiliser la variable simple "âge" qui fait partie de la
variable composée "garçon". Nous utilisons les deux noms avec un point décimal entre eux, le nom majeur en
premier. Ainsi "boy.age" est le nom complet de la variable pour le champ "age" de "boy". Cette construction peut
être utilisée n'importe où dans un programme C où l'on souhaite faire référence à ce champ. En fait, il est illégal
d'utiliser le nom « garçon » ou « âge » seuls, car ce ne sont que des définitions partielles du champ complet. Seuls,
les noms ne font référence à rien.

11­1 Tutoriel C Structures et syndicats


Machine Translated by Google
11.3 Attribution de valeurs aux variables
En utilisant la définition ci­dessus, nous pouvons attribuer une valeur à chacun des trois champs de « garçon » et
à chacun des trois champs de « fille ». Notez attentivement que "boy.initial" est en fait une variable de type "char",
car cela lui a été attribué dans la structure, il faut donc lui attribuer un caractère de données. Notez que "boy.initial"
se voit attribuer le caractère "R" conformément aux règles ci­dessus. Les deux champs restants de « garçon » se
voient attribuer des valeurs conformément à leurs types respectifs. Enfin, les trois domaines de fille se voient
attribuer des valeurs mais dans un ordre différent pour illustrer que l'ordre d'attribution n'est pas critique.

11.4 Comment utilisons­nous les données obtenues ?


Maintenant que nous avons attribué des valeurs aux six variables simples, nous pouvons faire tout ce que nous
désirons avec elles. Afin de garder ce premier exemple simple, nous imprimerons simplement les valeurs pour
voir si elles existent réellement telles qu'elles ont été assignées. Si vous inspectez attentivement les instructions
"printf", vous verrez qu'elles n'ont rien de spécial. Le nom composé de chaque variable est spécifié car c'est le
seul nom valide par lequel nous pouvons faire référence à ces variables.

Les structures sont une méthode très utile pour regrouper des données afin de rendre un programme plus facile
à écrire et à comprendre. Ce premier exemple est trop simple pour vous donner ne serait­ce qu'une idée de
l'intérêt de l'utilisation des structures, mais continuez à travers ces leçons et vous finirez par voir l'intérêt de
l'utilisation des structures.

Compilez et exécutez struct1.c et observez le résultat.

11.5 Un éventail de structures


Chargez et affichez le programme suivant nommé struct2.c.
main( )

{ struct
{ char initial ; âge
entier ; note
internationale ; }
enfants[12] ;
indice int ; pour
(index = 0;index < 12;index++) {
enfants[index].initial = 'A' + index; enfants[index].age
= 16 ; enfants[index].grade = 84 ;

} enfants[3].age = enfants[5].age = 17 ;
enfants[2].grade = enfants[6].grade = 92;
enfants[4].grade = 57 ; for
(index = 0;index < 12;index++) printf("%c a %d ans
et a obtenu une note de %d\n", kids[index].initial,kids[index].age, kids[index ].grade);

Ce programme contient la même définition de structure que précédemment mais cette fois nous définissons un
tableau de 12 variables nommées "kids". Ce programme contient donc 12 fois 3 = 36 variables simples, chacune
pouvant stocker une donnée à condition qu'elle soit du bon type. Nous définissons également une variable simple
nommée "index" à utiliser dans les boucles for.

Structures et syndicats Tutoriel C 11­2


Machine Translated by Google
Afin d'attribuer une valeur à chacun des champs, nous utilisons une boucle for et chaque passage dans la boucle
entraîne l'attribution d'une valeur à trois des champs. Un passage dans la boucle attribue toutes les valeurs à l'un des
"enfants". Ce ne serait pas un moyen très utile d'attribuer des données dans une situation réelle, mais une boucle
pourrait lire les données d'un fichier et les stocker dans les champs appropriés. Vous pourriez considérer cela comme
le début brut d’une base de données, ce qui est effectivement le cas.

Dans les prochaines instructions du programme, nous attribuons de nouvelles valeurs à certains champs pour illustrer
la méthode utilisée pour y parvenir. Il doit être explicite, aucun commentaire supplémentaire ne sera donc fourni.

11.6 Une note aux programmeurs Pascal


Pascal vous permet de copier un ENREGISTREMENT entier avec une seule instruction. Ce n'est pas possible en C.
Vous devez copier chaque élément d'une structure un à la fois. Au fur et à mesure que les améliorations du langage
seront définies, ce sera l’un des raffinements. En fait, certains des compilateurs les plus récents autorisent déjà
l'affectation de structure. Vérifiez la documentation de votre compilateur pour voir si votre compilateur dispose déjà
de cette fonctionnalité.

11.7 Nous affichons enfin tous les résultats


Les dernières instructions contiennent une boucle for dans laquelle toutes les valeurs générées sont affichées dans
une liste formatée. Compilez et exécutez le programme pour voir s'il fait ce que vous attendez de lui.

11.8 Utilisation conjointe de pointeurs et de structures


Chargez et affichez le fichier nommé struct3.c pour un exemple d'utilisation de pointeurs avec des structures.
Ce programme est identique au programme précédent sauf qu'il utilise des pointeurs pour certaines opérations.
main( )

{ struct { char
initial ; âge entier ;
note
internationale ; }
enfants[12],*point;
indice int ;
pour (index = 0;index < 12;index++) { point = enfants +
index; point­>initial = 'A' + index ;
point­>âge = 16 ; point ­> note = 84 ;

enfants[3].age = enfants[5].age = 17 ;
enfants[2].grade = enfants[6].grade = 92; enfants[4].grade
= 57 ; pour (index = 0;index <
12;index++) { point = enfants + index; printf("%c a %d ans
et a obtenu une note de %d\n",
(*point).initial,kids[index].age, point­>grade);

}
}

La première différence apparaît dans la définition des variables suite à la définition de la structure.
Dans ce programme, nous définissons un pointeur nommé "point" qui est défini comme un pointeur pointant vers

11­3 Tutoriel C Structures et syndicats


la structure.
Machine Translated Il serait illégal d'essayer d'utiliser ce pointeur pour pointer vers un autre type de variable.
by Google
Il y a une raison très précise à cette restriction en C, comme nous y avons fait allusion plus tôt et que nous
examinerons dans les prochains paragraphes.

La différence suivante réside dans la boucle for où nous utilisons le pointeur pour accéder aux champs de données.
Puisque « kids » est une variable pointeur qui pointe vers la structure, nous pouvons définir « point » en termes de
« kids ». La variable "kids" est une constante, sa valeur ne peut donc pas être modifiée, mais "point" est une variable
de pointeur et peut se voir attribuer n'importe quelle valeur compatible avec sa nécessité de pointer vers la structure.
Si nous attribuons la valeur de « kids » à « point », alors il devrait être clair qu'il pointera vers le premier élément du
tableau, une structure contenant trois champs.

11.9 Arithmétique des pointeurs

L'ajout de 1 à "point" le fera désormais pointer vers le deuxième champ du tableau en raison de la façon dont les
pointeurs sont gérés en C. Le système sait que la structure contient trois variables et il sait combien d'éléments de
mémoire sont nécessaires pour stocker le structure complète. Par conséquent, si nous lui disons d’en ajouter un au
pointeur, il ajoutera en fait le nombre d’éléments de mémoire requis pour accéder à l’élément suivant du tableau. Si,
par exemple, nous devions ajouter 4 au pointeur, cela avancerait la valeur du pointeur de 4 fois la taille de la
structure, ce qui le ferait pointer 4 éléments plus loin le long du tableau. C'est la raison pour laquelle un pointeur ne
peut pas être utilisé pour pointer vers un type de données autre que celui pour lequel il a été défini.

Revenons maintenant au programme affiché sur votre moniteur. Il ressort clairement de la discussion précédente
qu’au fur et à mesure que nous parcourons la boucle, le pointeur pointe à chaque fois vers le début de l’un des
éléments du tableau. On peut donc utiliser le pointeur pour référencer les différents éléments de la structure. Faire
référence aux éléments d'une structure avec un pointeur se produit si souvent en C qu'une méthode spéciale pour
le faire a été conçue. Utiliser "point­>initial" revient à utiliser "(*point).initial", ce qui est vraiment la façon dont nous
l'avons fait dans les deux derniers programmes. N'oubliez pas que *point correspond aux données vers lesquelles
pointe le pointeur et que la construction doit être claire. Le "­>" est composé du signe moins et du signe supérieur.

Puisque le pointeur pointe vers la structure, il faut encore une fois définir à quel élément on souhaite faire référence
à chaque fois que l'on utilise l'un des éléments de la structure. Il existe, comme nous l'avons vu, plusieurs méthodes
différentes pour faire référence aux membres de la structure, et dans la boucle for utilisée pour la sortie à la fin du
programme, nous utilisons trois méthodes différentes. Cela serait considéré comme une très mauvaise pratique de
programmation, mais nous le faisons ici pour vous illustrer qu'ils conduisent tous au même résultat. Ce programme
nécessitera probablement une certaine étude de votre part pour bien le comprendre, mais cela vaudra la peine de
consacrer votre temps et vos efforts à comprendre ces principes.

Compilez et exécutez ce programme.

11.10 Structures imbriquées et nommées

Chargez et affichez le fichier nommé nested.c pour un exemple de structure imbriquée. Les structures que nous
avons vues jusqu’à présent sont très simples, bien qu’utiles. Il est possible de définir des structures contenant des
dizaines, voire des centaines ou des milliers d'éléments mais il serait avantageux pour les programmeurs de ne
pas définir tous les éléments d'un seul coup mais plutôt d'utiliser une structure de définition hiérarchique. Ceci sera
illustré avec le programme sur votre moniteur. main( ) { struct personne { nom de caractère[25]; âge
entier ;

statut de caractère ; } ;

/* M = marié, S = célibataire */

Structures et syndicats Tutoriel C 11­4


struct
Machine Translated byalldat {grade int ;
Google
description de
la personne struct ; déjeuner d'omble
chevalier[25] ; }
étudiant[53];
struct alldat professeur,sub;
professeur.grade = 94 ;
professeur.descrip.age = 34 ;
professeur.descrip.status = 'M';
strcpy(prof.decrip.name,"Mary Smith"); strcpy(prof.lunch,"Sandwich
Baloney"); sous.descrip.age = 87 ; sub.descrip.status = 'M';
strcpy(sub.descrip.name,"Vieille
Dame Brown"); sous­grade = 73 ;
strcpy(sub.lunch,"Yaourt et pain grillé");

étudiant[1][descrip]âge = 15 ; statut d'étudiant[1]


[descrip] = 'S'; strcpy(nom de l'étudiant[1][descrip],"Billy
Boston"); strcpy(déjeuner[1]étudiant,"Beurre de cacahuète"); étudiant[1][grade]
= 77 ;

étudiant[7][descrip]âge = 14 ; étudiant[12]
[grade] = 87 ;
}

La première structure contient trois éléments mais n'est suivie d'aucun nom de variable. Nous n'avons donc défini aucune
variable seulement une structure, mais comme nous avons inclus un nom au début de la structure, la structure est nommée
"personne". Le nom « personne » peut être utilisé pour faire référence à la structure mais pas à une quelconque variable
de ce type de structure. C'est donc un nouveau type que nous avons défini, et nous pouvons utiliser le nouveau type à peu
près de la même manière que nous utilisons "int", "char", ou tout autre type existant en C. La seule restriction est que ce
nouveau nom doit toujours être associé au mot réservé "struct".

La définition de structure suivante contient trois champs, le champ du milieu étant la structure définie précédemment que
nous avons nommée « personne ». La variable qui a le type "personne" est nommée "descrip". Ainsi, la nouvelle structure
contient deux variables simples, "grade" et une chaîne nommée "lunch[25]", et la structure nommée "descrip". Puisque
« descrip » contient trois variables, la nouvelle structure contient en réalité 5 variables. Cette structure reçoit également un
nom « alldat », qui est une autre définition de type. Enfin nous définissons un tableau de 53 variables chacune avec la
structure définie par "alldat", et chacune avec le nom "student". Si cela est clair, vous verrez que nous avons défini un total
de 53 fois 5 variables, chacune étant capable de stocker une valeur.

11.11 Deux variables supplémentaires

Puisque nous avons une nouvelle définition de type, nous pouvons l'utiliser pour définir deux variables supplémentaires.
Les variables "teacher" et "sub" sont définies dans l'instruction suivante comme étant des variables du type "alldat", de
sorte que chacune de ces deux variables contient 5 champs pouvant stocker des données.

11.12 Maintenant, pour utiliser certains champs

Dans les cinq prochaines lignes du programme, nous attribuerons des valeurs à chacun des champs de « professeur ».
Le premier champ est le champ « grade » et est traité comme les autres structures que nous avons étudiées car il ne fait
pas partie de la structure imbriquée. Nous souhaitons ensuite attribuer une valeur à son âge qui fait partie de la structure
imbriquée. Pour aborder ce champ, nous commençons par le nom de la variable "enseignant" auquel nous ajoutons le
nom du groupe "descrip", puis nous devons définir quel champ de

11­5 Tutoriel C Structures et syndicats


la structure
Machine Translated byimbriquée
Googlequi nous intéresse, nous ajoutons donc le nom « age ». Le statut d'enseignante est géré exactement de la
même manière que son âge, mais les deux derniers champs se voient attribuer des chaînes à l'aide de la fonction de copie de
chaîne "strcpy" qui doit être utilisée pour l'attribution de chaînes.

Notez que les noms de variables dans la fonction "strcpy" sont toujours des noms de variables même s'ils sont constitués chacun
de plusieurs parties.

La variable "sub" se voit attribuer des valeurs absurdes de la même manière, mais dans un ordre différent puisqu'elles ne doivent
pas nécessairement apparaître dans un ordre requis. Enfin, quelques­unes des variables « étudiants » se voient attribuer des
valeurs à des fins d'illustration et le programme se termine. Aucune des valeurs n'est imprimée à titre d'illustration puisque plusieurs
ont été imprimées dans les derniers exemples.

Compilez et exécutez ce programme, mais lorsque vous l'exécutez, vous risquez d'obtenir une erreur de « débordement de pile ».
C utilise sa propre pile interne pour stocker les variables automatiques, mais la plupart des compilateurs C n'utilisent qu'une petite
pile (généralement 2048 octets) par défaut. Ce programme a plus que cela dans les structures définies il vous faudra donc
augmenter la taille de la pile. La méthode permettant d'effectuer cette opération pour certains compilateurs MS­DOS est indiquée
dans le fichier COMPILER.DOC qui accompagne ce didacticiel. Consultez la documentation de votre compilateur pour plus de
détails sur votre compilateur, mais cela ne semble pas être présent dans le compilateur HiTech. Utilisez le programme Applix
chmem pour ajuster la taille de la pile du code exécutable après la compilation.

Il existe une autre façon de contourner ce problème : déplacer les définitions de structure en dehors du programme où elles seront
des variables externes et donc statiques. Résultat : ils ne seront pas conservés sur la pile interne et la pile ne débordera donc pas.
Ce serait bien que vous essayiez les deux méthodes pour résoudre ce problème.

11.13 En savoir plus sur les structures


Il est possible de continuer les structures de nidification jusqu'à ce que vous soyez totalement confus. Si vous les définissez
correctement, l'ordinateur ne sera pas confus car il n'y a pas de limite indiquée quant au nombre de niveaux d'imbrication autorisés.
Il existe probablement une limite pratique de trois au­delà de laquelle vous serez confus, mais le langage n'a pas de limite. En plus
de l'imbrication, vous pouvez inclure autant de structures que vous le souhaitez dans n'importe quel niveau de structures, par
exemple en définissant une autre structure avant "alldat" et en l'utilisant dans "alldat" en plus d'utiliser "person". La structure
nommée « personne » pourrait être incluse dans « alldat » deux fois ou plus si vous le souhaitez, tout comme les pointeurs vers
elle.

Les structures peuvent contenir des tableaux d'autres structures qui à leur tour peuvent contenir des tableaux de types simples ou
d'autres structures. Cela peut continuer encore et encore jusqu'à ce que vous perdiez toute raison de continuer. J'essaie seulement
de vous illustrer que les structures sont très précieuses et que vous les trouverez d'une grande aide pour la programmation si
vous les utilisez à bon escient. Soyez conservateur au début et devenez plus audacieux à mesure que vous gagnez en expérience.

Les structures plus complexes ne seront pas illustrées ici, mais vous trouverez des exemples de structures supplémentaires dans
les programmes exemples inclus dans le dernier chapitre de ce tutoriel. Par exemple, consultez le fichier "#include" "STRUCT.H".

11.14 Que sont les syndicats ?


Chargez le fichier nommé union1.c pour un exemple d'union. En termes simples, une union vous permet d'examiner les mêmes
données avec différents types ou d'utiliser les mêmes données avec des noms différents.
Examinez le programme sur votre moniteur. main( )
{ union

{ valeur int
courte ; /* Ceci est la première partie de l'union */
/* Ça doit être un court avec le HI­TECH */
/* Compilateur C car l'int est de 32 bits */
struct { char
en premier ; /* Ces deux valeurs sont les secondes */

Structures et syndicats Tutoriel C 11­6


Machine Translated bychar deuxième ; }
Google
moitié; }
nombre;
index long; pour
(index = 12;index < 300000;index += 35231) { nombre.valeur = index;
printf("%8x %6x
%6x\n",number.value,number[half]first, number[half]second);

}
}

Dans cet exemple, nous avons deux éléments dans l'union, la première partie étant l'entier nommé "valeur", qui est
stocké sous forme de variable de deux octets quelque part dans la mémoire de l'ordinateur. Le deuxième élément
est constitué de deux variables de caractères nommées « premier » et « seconde ». Ces deux variables sont
stockées dans les mêmes emplacements de stockage que la "valeur", car c'est ce que fait une union. Une union
permet de stocker différents types de données dans les mêmes emplacements de stockage physiques. Dans ce
cas, vous pouvez mettre un nombre entier dans "valeur", puis le récupérer dans ses deux moitiés en obtenant
chaque moitié en utilisant les deux noms "premier" et "seconde". Cette technique est souvent utilisée pour regrouper
des octets de données lorsque vous combinez, par exemple, des octets à utiliser dans les registres du
microprocesseur.

L'accès aux champs de l'union est très similaire à l'accès aux champs d'une structure et vous sera laissé à
déterminer en étudiant l'exemple.

Une note supplémentaire doit être donnée ici concernant le programme. Lorsqu'il est exécuté avec la plupart des
compilateurs, les données seront affichées avec deux f en tête en raison de la sortie hexadécimale promouvant les
variables de type char en int et étendant le bit de signe vers la gauche. La conversion des champs de données de
type char en champs de type int avant l'affichage devrait supprimer les premiers f de votre affichage. Cela impliquera
de définir deux nouvelles variables de type int et de leur attribuer les variables de type char.
Cela vous sera laissé en exercice. Notez que le même problème se produira également dans quelques­uns des
fichiers ultérieurs.

Lors de l'utilisation du compilateur HiTech C, les données seront affichées avec plus de deux « f » en tête, en raison
de l'utilisation de la valeur int courte.

Compilez et exécutez ce programme et observez que les données sont lues sous la forme d'une variable "int" et de
deux variables "char". Les variables "char" sont inversées dans l'ordre en raison de la façon dont une variable "int"
est stockée en interne dans votre ordinateur. Ne vous inquiétez pas pour ça. Ce n’est pas un problème mais cela
peut être un domaine d’étude très intéressant si vous le souhaitez.

Les variables 'char' sont dans leur position correcte lorsqu'elles sont compilées avec HiTech C.

11.15 Un autre exemple de syndicat


Chargez et affichez le fichier nommé union2.c pour un autre exemple d'union, qui est beaucoup plus
plus commun.

Supposons que vous souhaitiez créer une grande base de données comprenant des informations sur de nombreux types de véhicules.
Il serait idiot d’inclure le nombre d’hélices sur une voiture ou le nombre de pneus sur un bateau.
Cependant, afin de conserver toutes les données pertinentes, vous aurez besoin de ces points de données pour
leurs types de véhicules appropriés. Afin de créer une base de données efficace, vous auriez besoin de plusieurs
types de données différents pour chaque véhicule, dont certaines seraient communes et d’autres différentes.
C'est exactement ce que nous faisons dans l'exemple de programme sur votre moniteur.
#define AUTO 1
#define BATEAU 2
#define AVION 3
#define NAVIRE 4

11­7 Tutoriel C Structures et syndicats


principal( by
Machine Translated ) Google
{
struct automobile { /* structure pour une automobile int pneus; */

ailes intérieures;
portes intérieures;

typedef struct { /* structure pour un bateau ou un navire */
déplacement int ;
longueur du caractère ;

} BATEAUDEF;
structure {
véhicule de char ; /* quel type de véhicule */
poids entier ; /* /* poids brut du véhicule */
union { /* données dépendantes du type */
partie 1 de la voiture automobile union struct ; */ */
Bateau BOATDEF ; /* partie 2 du syndicat
structure {
moteurs de charbon de bois ;
envergure int;
} avion ; /* partie 3 du syndicat /* partie 4 du */
Navire syndicat */
BOATDEF ; } Type de véhicule;
du propriétaire */ /* valeur du véhicule en dollars valeur int ; /* le nom */
propriétaire de char[32]; }
gué, sun_fish, piper_cub; /* trois structures variables */
/* Définir quelques champs à titre d'illustration */
ford.véhicule = AUTO ;
gué.poids = 2742 ; /* avec un réservoir d'essence plein */
ford.vehicle_type.car.tires = 5 ; /* y compris les pièces de rechange */
ford.vehicle_type.car.doors = 2;
sun_fish.value = 3742 ; /* bande­annonce non incluse */
sun_fish.vehicle_type.boat.length = 20 ;
piper_cub.vehicle = AVION ;
piper_cub.vehicle_type.airplane.wingspan = 27 ;
if (ford.vehicle == AUTO) /* ce dont il s'agit dans ce cas */
printf("?La Ford a %d pneus./n",ford.vechicle_type.car.tires);
if (piper_cub.vehicle == AUTO) /* ce qui n'est pas le cas dans ce cas */
printf("L'avion a %d pneus.\n",piper_cub.vechicle_type.
pneus de voiture);
}

Dans ce programme, nous définirons une structure complète, puis déciderons lequel des différents types peut
entrez­y. Nous commencerons par le haut et descendrons. Tout d'abord, nous définissons quelques constantes
avec le #defines, et démarrez le programme lui­même. On définit une structure nommée "automobile"
contenant plusieurs champs que vous ne devriez avoir aucun mal à reconnaître, mais nous ne définissons aucun
variables à ce moment.

11.16 Un nouveau concept, le Typedef


Ensuite, nous définissons un nouveau type de données avec un "typedef". Cela définit un tout nouveau type qui peut
être utilisé de la même manière que "int" ou "char" peuvent être utilisés. Notez que la structure n'a pas de nom,
mais à la fin, là où il y aurait normalement un nom de variable, il y a le nom "BOATDEF".
Nous disposons désormais d'un nouveau type, "BOATDEF", qui peut être utilisé pour définir une structure n'importe où.
aimerais. Notez que cela ne définit aucune variable, seulement une nouvelle définition de type.
La mise en majuscule du nom est une préférence personnelle uniquement et ne constitue pas une norme C. Cela fait le "typedef"
être différent d'un nom de variable.

Structures et syndicats Tutoriel C 11­8


Nous arrivons
Machine Translated enfin à la grande structure qui définit nos données en utilisant les éléments de base déjà définis ci­dessus.
by Google
La structure est composée de 5 parties, deux variables simples nommées "véhicule" et "poids", suivies de l'union, et
enfin les deux dernières variables simples nommées "valeur" et "propriétaire". Bien sûr, c’est le syndicat que nous
devons examiner attentivement ici, alors concentrez­vous là­dessus pour le moment. Vous remarquerez qu'il est
composé de quatre parties, la première partie étant la variable "car" qui est une structure que nous avons définie
précédemment. La deuxième partie est une variable nommée "boat" qui est une structure du type "BOATDEF"
précédemment définie. La troisième partie du syndicat est la variable « avion » qui est une structure définie en place
dans le syndicat. Enfin on arrive à la dernière partie de l'union, la variable nommée "ship" qui est une autre structure du
type "BOATDEF".

J'espère qu'il est évident pour vous que les quatre auraient pu être définies de l'une des trois manières présentées, mais
les trois méthodes différentes ont été utilisées pour vous montrer que n'importe laquelle pouvait être utilisée. En pratique,
la définition la plus claire aurait probablement été obtenue en utilisant le "typedef" pour chacune des parties.

11.17 Qu'avons­nous maintenant ?


Nous disposons désormais d’une structure qui peut être utilisée pour stocker l’un des quatre types différents de structures de données.
La taille de chaque enregistrement sera la taille de cet enregistrement contenant la plus grande union. Dans ce cas la
partie 1 est la plus grande union car elle est composée de trois entiers, les autres étant composées chacune d'un entier
et d'un caractère. Le premier membre de ce syndicat déterminerait donc la taille de toutes les structures de ce type. La
structure résultante peut être utilisée pour stocker n'importe lequel des quatre types de données, mais c'est au
programmeur de garder une trace de ce qui est stocké dans chaque variable de ce type. La variable « véhicule » a été
conçue dans cette structure pour garder une trace du type de véhicule stocké ici. Les quatre définitions en haut de la
page ont été conçues pour être utilisées comme indicateurs à stocker dans la variable "véhicule". Quelques exemples
d'utilisation de la structure résultante sont donnés dans les prochaines lignes du programme. Certaines variables sont
définies et quelques­unes d'entre elles sont imprimées à des fins d'illustration.

Le syndicat n'est pas utilisé trop fréquemment, et presque jamais par les programmeurs débutants. Vous le rencontrerez
de temps en temps, cela vaut donc la peine de savoir au moins de quoi il s’agit. Vous n’avez pas besoin d’en connaître
les détails pour le moment, alors ne passez pas trop de temps à l’étudier. Lorsque vous avez besoin d’une structure
variable, d’un syndicat, vous pouvez l’apprendre à ce moment­là. Cependant, pour votre propre bénéfice, ne négligez
pas la structure. Vous devriez utiliser la structure souvent.

11.18 Exercices de programmation


1. Définissez une structure nommée contenant un champ de chaîne pour un nom, un entier pour les pieds et un autre
pour les bras. Utilisez le nouveau type pour définir un tableau d'environ 6 éléments. Remplissez les champs avec des
données et imprimez­les comme suit.

Un être humain a 2 jambes et 2 bras. Un chien a 4 pattes et 0 bras. Un téléviseur a 4 jambes et 0 bras. Une chaise a 4
pieds et 2 bras. etc.

2. Réécrivez l'exercice 1 à l'aide d'un pointeur pour imprimer les données.

11­9 Tutoriel C Structures et syndicats


Machine Translated by Google
12
Allocation dynamique

12.1 Qu'est­ce que l'allocation dynamique ?


L'allocation dynamique est très intimidante pour une personne la première fois qu'elle la rencontre, mais ce n'est pas
nécessairement le cas. Détendez­vous simplement et lisez attentivement ce chapitre et vous aurez de bonnes bases
dans une ressource de programmation très précieuse. Jusqu'à présent, toutes les variables de chaque programme
étaient des variables statiques en ce qui nous concerne. (En fait, certaines d'entre elles ont été "automatiques" et ont
été allouées dynamiquement pour vous par le système, mais cela était transparent pour vous.) Dans ce chapitre, nous
étudierons quelques variables allouées dynamiquement. Ce sont simplement des variables qui n'existent pas au
moment du chargement du programme, mais qui sont créées dynamiquement au fur et à mesure de leurs besoins. Il
est possible, grâce à ces techniques, de créer autant de variables que nécessaire, de les utiliser et de libérer leur
espace pour qu'elles soient utilisées par d'autres variables. Comme d'habitude, le meilleur professeur est un exemple,
alors chargez et affichez le programme nommé dynlist.c.
main( )

{ struct animal { nom


de caractère[25];
race d'omble
chevalier[25] ;
âge entier ; } *animal1, *animal2, *animal3;
pet1 = (struct animal *)malloc(sizeof(struct animal)); strcpy(pet1­>name,"Général");
strcpy(pet1­>breed,"Race mixte"); animal1­
>âge = 1 ;

animal2 = animal1; /* l'animal 2 pointe désormais vers la structure de données ci­dessus */


pet1 = (struct animal *)malloc(sizeof(struct animal)); strcpy(animal1­>nom,"Frank");
strcpy(animal1­>race,"Labrador Retriever");
animal1­>âge = 3 ;

pet3 = (struct animal *)malloc(sizeof(struct animal)); strcpy(animal3­>nom,Krystal");


strcpy(animal3­>race,Berger allemand");
animal3­>âge = 4 ;

/* imprime maintenant les données décrites ci­dessus /*


printf("%s est un %s et a %d ans.\n",animal1­>nom,animal1­>race,
animal1 ­> âge);
printf("%s est un %s et a %d ans.\n",animal2­>nom,animal2­>race,
animal2­>âge);
printf("%s est un %s et a %d ans.\n",pet3­>name,pet3­>breed, pet3­>age);

animal1 = animal3; /* pet1 pointe maintenant vers la même structure que pet3 pointe /*
cela libère une */
gratuit(animal3); structure /* cela libère une structure */
gratuit(animal2); supplémentaire */
/* gratuit(animal1); cela ne peut pas être fait, voir l'explication dans le texte } */

Nous commençons par définir une structure nommée « animal » avec quelques champs relatifs aux chiens. Nous ne
définissons aucune variable de ce type, seulement trois pointeurs. Si vous effectuez une recherche dans le reste du
programme, vous ne trouverez aucune variable définie, nous n'avons donc rien dans lequel stocker les données. Tout
ce avec quoi nous devons travailler, ce sont trois pointeurs, chacun pointant vers la structure définie. Pour faire quoi
que ce soit, nous avons besoin de certaines variables, nous allons donc en créer dynamiquement.

Allocation dynamique Tutoriel C 12­1


Machine Translated by Google
12.2 Création de variables dynamiques
La première instruction du programme, qui assigne quelque chose au pointeur "pet1", créera une structure dynamique
contenant trois variables. Le cœur de l’instruction est la fonction « malloc » enfouie au milieu de l’instruction. Il s'agit d'une
fonction "d'allocation de mémoire" qui a besoin des autres éléments pour la définir complètement. La fonction "malloc", par
défaut, allouera un morceau de mémoire sur un "tas" d'une longueur de "n" caractères et sera de type caractère. Le « n »
doit être spécifié comme seul argument de la fonction. Nous discuterons de « n » sous peu, mais nous devons d’abord
définir un « tas ».

12.3 Qu'est­ce qu'un tas ?


Chaque compilateur a un ensemble de limitations quant à la taille du fichier exécutable, au nombre de variables pouvant
être utilisées, à la longueur du fichier source, etc. Dans le 1616, la limite principale est votre mémoire totale de 512 Ko ( ou
4,5 mégaoctets, ou autre).

Une limitation imposée aux utilisateurs par de nombreux compilateurs pour IBM­PC et compatibles est une limite de 64 Ko
pour le code exécutable. En effet, l'IBM­PC utilise un microprocesseur avec une taille de segment de 64 Ko et nécessite
des appels spéciaux pour utiliser des données en dehors d'un seul segment. Afin de garder le programme petit et efficace,
ces appels ne sont pas utilisés et leur taille est limitée mais reste adéquate pour la plupart des programmes. Cette limitation
ne s'applique pas aux utilisateurs du système d'exploitation 1616/OS, car le Motorola 68000 dispose d'un espace mémoire
plat de 16 Mo.

Un tas est une zone à laquelle le programme peut accéder pour stocker des données et des variables. Les données et les
variables sont placées sur le « tas » par le système au fur et à mesure que les appels à « malloc » sont effectués. Le
système garde une trace de l'endroit où les données sont stockées. Les données et les variables peuvent être libérées à
volonté, ce qui entraîne des trous dans le tas. Le système sait où se trouvent les trous et les utilisera pour un stockage de
données supplémentaire à mesure que d'autres appels "malloc" seront effectués. La structure du tas est donc une entité
très dynamique, en constante évolution. Reportez­vous au manuel du programmeur 1616/OS pour plus de détails sur
l'allocation de mémoire dans le 1616.

12.4 En savoir plus sur les segments


Cette section s'applique uniquement aux utilisateurs MS­DOS et est une conséquence de la conception segmentée du
processeur Intel 8086, endommagée par le cerveau. La conception a été imposée à Intel par une exigence commerciale
selon laquelle ils restent semi­compatibles avec leurs premiers microprocesseurs, les 8008 et 8080. Cette segmentation
oblige les utilisateurs MS­DOS à choisir des modèles de mémoire, que leurs compilateurs tentent de rendre un peu plus
facile. Cette limitation n'a été surmontée qu'avec la sortie des processeurs Intel 80386 et versions ultérieures, qui peuvent
avoir de grands segments.

Certains des compilateurs les plus chers offrent à l'utilisateur un choix de modèles de mémoire à utiliser. Les exemples
sont Lattice et Microsoft, qui permettent au programmeur de choisir d'utiliser un modèle avec une limitation de 64 Ko sur la
taille du programme mais une exécution plus efficace, ou d'utiliser un modèle avec une limitation de 640 Ko et nécessitant
des appels d'adresse plus longs conduisant à un adressage moins efficace. L'utilisation d'un espace d'adressage plus
grand nécessite un adressage inter­segments, ce qui entraîne un temps d'exécution légèrement plus lent. Le temps est
probablement insignifiant dans la plupart des programmes, mais il y a d'autres considérations à prendre en compte.

Si un programme MS­DOS n'utilise pas plus de 64 Ko pour le total de son code et de sa mémoire et s'il n'utilise pas de pile,
il peut être transformé en fichier .com. Puisqu'un fichier .com est déjà au format image mémoire, il peut être chargé très
rapidement alors qu'un fichier au format .exe doit voir ses adresses déplacées au fur et à mesure de son chargement. Par
conséquent, un petit modèle de mémoire peut générer un programme qui se charge plus rapidement qu'un programme
généré avec un modèle de mémoire plus grand. Ne vous laissez pas inquiéter, c'est un point délicat qui préoccupe peu de
programmeurs.

12­2 Tutoriel C Allocation dynamique


Grâce à by
Machine Translated l'allocation
Googledynamique, il est possible de stocker les données sur le « tas » et cela peut suffire à vous
permettre d'utiliser le modèle de petite mémoire. Bien sûr, vous ne stockeriez pas de variables locales telles que des
compteurs et des index sur le tas, mais uniquement de très grands tableaux ou structures.

La nécessité de rester dans le modèle de petite mémoire est encore plus importante que la nécessité de rester dans
le cadre de l'ordinateur. Si vous aviez un programme qui utilisait plusieurs grandes zones de stockage de données,
mais pas en même temps, vous pouvez charger un bloc en le stockant dynamiquement, puis vous en débarrasser et
réutiliser l'espace pour le prochain grand bloc de données. Le stockage dynamique de chaque bloc de données
successivement et l'utilisation du même stockage pour chaque bloc peuvent vous permettre d'exécuter l'intégralité de
votre programme sur l'ordinateur sans le diviser en programmes plus petits.

12.5 Retour à la fonction "Malloc"


Espérons que la description ci­dessus du « tas » et le plan global d’allocation dynamique vous ont aidé à comprendre
ce que nous faisons avec la fonction « malloc ». Il demande simplement au système un bloc de mémoire de la taille
spécifiée et obtient le bloc avec le pointeur pointant vers le premier élément du bloc. Le seul argument entre
parenthèses est la taille du bloc souhaité et dans notre cas présent, nous souhaitons un bloc qui contiendra l'une des
structures que nous avons définies au début du programme. Le "sizeof" est une nouvelle fonction, nouvelle pour nous
du moins, qui renvoie la taille en octets de l'argument entre parenthèses. Il renvoie donc la taille de la structure
nommée animal, en octets, et ce numéro est envoyé au système avec l'appel "malloc". À la fin de cet appel, nous
avons un bloc sur le tas qui nous est alloué, avec pet1 pointant vers le premier octet du bloc.

12.6 Qu'est­ce qu'un casting ?

Nous avons toujours une construction amusante au début de l'appel de fonction "malloc". C'est ce qu'on appelle un
"casting". La fonction "malloc" renvoie un bloc avec le pointeur pointant vers lui étant un pointeur de type "char" par
défaut. Très souvent, sinon la plupart du temps, vous ne souhaitez pas un pointeur vers une variable de type "char",
mais vers un autre type. Vous pouvez définir le type de pointeur avec la construction donnée sur la ligne d'exemple.
Dans ce cas, nous voulons que le pointeur pointe vers une structure de type "animal", nous le disons donc au
compilateur avec cette construction étrange. Même si vous omettez le cast, la plupart des compilateurs renverront un
pointeur correctement, vous donneront un avertissement et continueront à produire un programme fonctionnel. Il est
préférable de fournir au compilateur le cast pour éviter de recevoir le message d'avertissement.

12.7 Utilisation du bloc de mémoire alloué dynamiquement


Si vous vous souvenez de nos études sur les structures et les pointeurs, vous vous souviendrez que si nous avons
une structure avec un pointeur pointant vers elle, nous pouvons accéder à n'importe quelle variable de la structure.
Dans les trois lignes suivantes du programme, nous attribuons des données idiotes à la structure à des fins
d'illustration. Cela ne devrait pas vous surprendre si ces instructions d'affectation ressemblent à des affectations à
des variables définies statiquement.

Dans l’instruction suivante, nous attribuons également la valeur de « pet1 » à « pet2 ». Cela ne crée aucune nouvelle
donnée, nous avons simplement deux pointeurs vers le même objet. Puisque "pet2" pointe vers la structure que nous
avons créée ci­dessus, "pet1" peut être réutilisé pour obtenir une autre structure allouée dynamiquement, ce que
nous faisons ensuite. Gardez à l'esprit que "pet2" aurait tout aussi bien pu être utilisé pour la nouvelle allocation. La
nouvelle structure est remplie de données idiotes à titre d'illustration.

Enfin, nous allouons un autre bloc sur le tas à l'aide du pointeur "pet3", et remplissons son bloc de données illustratives.

L'impression des données ne devrait vous poser aucun problème puisqu'il n'y a rien de nouveau dans les trois
instructions d'impression. Il vous reste à étudier.

Allocation dynamique Tutoriel C 12­3


Machine Translated by Google
12.8 Suppression des données allouées dynamiquement
Une autre nouvelle fonction permet de se débarrasser des données et de libérer de l'espace sur le tas pour la réutilisation,
la fonction "free". Pour l'utiliser, il vous suffit de l'appeler avec le pointeur vers le bloc comme seul argument, et le bloc est
libéré.

Afin d'illustrer un autre aspect de l'allocation et de la désallocation dynamiques des données, une étape supplémentaire
est incluse dans le programme sur votre moniteur. Le pointeur "pet1" reçoit la valeur "pet3". En faisant cela, le bloc vers
lequel "pet1" pointait est effectivement perdu puisqu'aucun pointeur ne pointe maintenant vers ce bloc. Il ne pourra donc
plus jamais être consulté, modifié ou éliminé. Cette mémoire, qui constitue un bloc sur le tas, est désormais gaspillée. Ce
n’est pas quelque chose que vous feriez délibérément dans un programme. Ceci n’est fait ici qu’à titre d’illustration.

Le premier appel de fonction « gratuit » supprime le bloc de données vers lequel « pet1 » et « pet3 » pointaient, et le
deuxième appel « gratuit » supprime le bloc de données vers lequel « pet2 » pointait. Nous avons donc perdu l’accès à
toutes nos données générées précédemment. Il y a toujours un bloc de données sur le tas, mais il n'y a aucun pointeur
vers celui­ci puisque nous en avons perdu l'adresse. Essayer de "libérer" les données pointées par "pet1" entraînerait une
erreur car elles ont déjà été "libérées" par l'utilisation de "pet3". Il n'y a pas lieu de s'inquiéter, lorsque nous reviendrons au
système d'exploitation, l'intégralité du tas sera éliminé sans égard à ce que nous y avons mis. Il faut souligner que la perte
d'un pointeur vers un bloc du tas supprime définitivement ce bloc de stockage de données de notre programme et nous
pourrions avoir besoin de ce stockage plus tard.

Compilez et exécutez le programme pour voir s'il fait ce que vous pensez qu'il devrait faire sur la base de cette discussion.

12.9 Cela a fait l'objet de nombreuses discussions

Il a fallu près de quatre pages pour parcourir la discussion du dernier programme, mais ce fut du temps bien dépensé.
Cela devrait être quelque peu passionnant pour vous de savoir qu'il n'y a rien d'autre à apprendre sur l'allocation
dynamique, les quatre dernières pages ont tout couvert. Bien sûr, il y a beaucoup à apprendre sur la technique d'utilisation
de l'allocation dynamique, et pour cette raison, il y a deux autres fichiers à étudier.
Mais il n’en demeure pas moins qu’il n’y a rien de plus à apprendre sur l’allocation dynamique que ce qui a été exposé
jusqu’à présent dans ce chapitre.

12.10 Un tableau de pointeurs


Chargez et affichez le fichier bigdynl.c pour un autre exemple d'allocation dynamique. Ce programme est très similaire au
précédent puisque nous utilisons la même structure, mais cette fois nous définissons un tableau de pointeurs pour illustrer
les moyens par lesquels vous pouvez construire une grande base de données en utilisant un tableau de pointeurs plutôt
qu'un seul pointeur vers chaque élément. . Pour faire simple, nous définissons 12 éléments dans le tableau et un autre
pointeur de travail nommé "point".
main( )

{ struct animal { nom


de caractère[25]; race
d'omble chevalier[25] ;
âge entier ; }
*animal[12], *point; indice int ; /*cela définit 13 pointeurs, aucune variable */

/* d'abord, remplir les structures dynamiques de bêtises */


for (index = 0;index < 12;index++) { pet[index] = (struct
animal *)malloc(sizeof(struct animal)); strcpy(pet[index]­>name,"Général"); strcpy(animal[index]­
>breed,"Race mixte"); animal de compagnie[index] ­>
âge = 4 ;

12­4 Tutoriel C Allocation dynamique


animal[4]
Machine Translated ­> âge = 12 ;
by Google /* ces lignes sont simplement destinées à */
animal[5] ­> âge = 15 ; /* met des données absurdes dans */
animal[6] ­> âge = 10 ; /* /* quelques champs. */
imprime maintenant les données décrites ci­dessus */
pour (index = 0;index <12;index++) {
point = animal[index];
printf("%s est un %s et a %d ans.\n", point­>name,
point­>race, point­>âge);
}
/* les bonnes pratiques de programmation dictent de libérer le */
/* Espace alloué dynamiquement avant de quitter. */
pour (index = 0;index < 12;index++)
free(animal[index]);
}

Le "*pet[12]" est nouveau pour vous donc quelques mots s'imposent. Ce que nous avons défini est un
tableau de 12 pointeurs, le premier étant "pet[0]" et le dernier "pet[11]". En fait, puisqu'un tableau est
lui­même un pointeur, le nom « animal de compagnie » en lui­même est un pointeur vers un pointeur. Ceci est valable en C, et en fait
vous pouvez aller plus loin si nécessaire mais vous serez vite confus. Je ne connais aucune limite quant à la façon dont
de nombreux niveaux de pointage sont possibles, donc une définition telle que "int ****pt" est légale comme pointeur vers
un pointeur vers un pointeur vers un pointeur vers une variable de type entier, si j'ai bien compté. Une telle utilisation est
découragé jusqu'à ce que vous acquériez une expérience considérable.

Maintenant que nous disposons de 12 pointeurs qui peuvent être utilisés comme n’importe quel autre pointeur, il est simple de
écrire une boucle pour allouer dynamiquement un bloc de données à chacun et remplir les champs respectifs avec
toutes les données souhaitables. Dans ce cas, les champs sont remplis de données simples à titre indicatif,
mais nous pourrions lire dans une base de données, des lectures provenant d'un équipement de test ou de toute autre source
de données.

Quelques champs sont choisis au hasard pour recevoir d'autres données afin d'illustrer que des affectations simples peuvent
être utilisé et les données sont imprimées sur le moniteur. Le pointeur "point" est utilisé dans l'impression
boucle uniquement pour servir d'illustration, les données auraient pu être facilement imprimées en utilisant le "pet[n]"
moyen de définition. Enfin, les 12 blocs de données sont libérés avant de terminer le programme.

Compilez et exécutez ce programme pour vous aider à comprendre cette technique. Comme indiqué précédemment, il y a
Il n'y avait rien de nouveau ici en matière d'allocation dynamique, seulement en ce qui concerne un tableau de pointeurs.

12.11 Une liste chaînée


Nous arrivons enfin au grand­père de toutes les techniques de programmation en ce qui concerne l'intimidation.
Chargez le programme dynlink.c pour un exemple de liste chaînée allouée dynamiquement. Ça sonne
terrible, mais après un peu de temps passé avec, vous verrez que c'est simplement une autre programmation
technique composée d’éléments simples qui peuvent être un outil puissant.

#include "stdio.h" /* ceci est nécessaire uniquement pour définir le NULL */


#define ENREGISTREMENTS 6

principal( )
{
structurer animal {
nom du personnage[25]; /* Le nom de l'animal */
race d'omble /* Le type d'animal */
chevalier[25] ; /* Les animaux vieillissent */
âge entier ; struct animal /* un pointeur vers un autre enregistrement de ce type */
*suivant ; } *point, *début, *avant; indice /* ceci définit 3 pointeurs, aucune variable */
int ;
/* le premier enregistrement est toujours un cas particulier */

Allocation dynamique Tutoriel C 12­5


start by
Machine Translated = (struct
Googleanimal *)malloc(sizeof(struct animal));
strcpy(start ­>name,"général");
strcpy(start ­>race,"Race mixte");
début­>suivant = NULL ;
avant = début ;
/* une boucle peut être utilisée pour remplir le reste une fois démarrée */

pour (index = 0;index < ENREGISTREMENTS;index++) {


point = (struct animal *)malloc(sizeof(struct animal));
strcpy(point­>nom,"Frank");
strcpy(point­>race,"Laborator Retriever");
point­>âge = 3 ;
point­>suivant = point /* point dernier "à côté" de cet enregistrement */
point­>suivant = NULL ; /* pointez ce "suivant" sur NULL */
point; /* c'est maintenant l'enregistrement précédent prior = */
}

/* affiche maintenant les données décrites ci­dessus */


point = début ;
faire {
avant = point­>suivant ;
printf("%s est un %s et a %d ans.\n", point­>nom,
point­>race, point­>âge);
point = point­>suivant ;
} while (avant != NULL);
/* les bonnes pratiques de programmation dictent de libérer le */
/* espace alloué dynamiquement avant de quitter */

point = début ; faire { /* premier bloc du groupe */

avant = point­>suivant ; /* prochain bloc de données free(point); /* bloc */


présent libre /* pointer vers le point suivant = prior; } while (avant != NULL); / */
est NULL * quitte quand le prochain */
*/
}

Afin de vous rassurer, pensez à la liste chaînée que vous avez utilisée lorsque vous étiez enfant. Ton
ma sœur t'a offert ton cadeau d'anniversaire, et quand tu l'as ouvert, tu as trouvé une note qui disait : "Regarde
dans le placard du couloir. » Vous êtes allé dans le placard du couloir et avez trouvé une autre note qui disait : « Regardez derrière
le téléviseur. » Derrière le téléviseur, vous avez trouvé une autre note qui disait : « Regardez sous la cafetière. » Vous
avez continué cette recherche, et finalement vous avez trouvé votre paire de chaussettes sous la gamelle du chien.
En réalité, vous avez exécuté une liste chaînée, le point de départ étant le cadeau emballé.
et le point final étant sous la gamelle du chien. La liste s'est terminée au plat à manger pour chiens
puisqu'il n'y avait plus de notes.

Dans le programme dynlink.c, nous ferons la même chose que votre sœur vous a forcé à faire.
Nous le ferons cependant beaucoup plus rapidement et nous laisserons un petit tas de données à chacun des étapes intermédiaires.
points en cours de route. Nous aurons également la possibilité de revenir au début et de revenir en arrière
la liste entière encore et encore si nous le désirons.

12.12 Les définitions des données


Ce programme démarre de la même manière que les deux derniers avec l'ajout de la définition d'une constante à
être utilisé plus tard. La structure est presque la même que celle utilisée dans les deux derniers programmes, à l'exception de
l'ajout d'un autre champ au sein de la structure, le pointeur. Ce pointeur est un pointeur vers un autre
structure de ce même type et sera utilisé pour pointer vers la structure suivante dans l’ordre. Continuer
l'analogie ci­dessus, ce pointeur pointera vers la note suivante, qui à son tour contiendra un pointeur
à la note suivante après cela.

Nous définissons trois pointeurs vers cette structure à utiliser dans le programme, et un entier à utiliser comme
un comptoir, et nous sommes prêts à commencer à utiliser la structure définie dans le but que nous souhaitons.
Dans ce cas, nous générerons à nouveau des données absurdes à des fins d'illustration.

12­6 Tutoriel C Allocation dynamique


Machine Translated by Google
12.13 Le premier champ

A l'aide de la fonction "malloc", nous demandons un bloc de stockage sur le "heap" et le remplissons de données.
Le champ supplémentaire dans cet exemple, le pointeur, se voit attribuer la valeur NULL, qui est uniquement utilisée
pour indiquer qu'il s'agit de la fin de la liste. Nous laisserons le pointeur "start" sur cette structure, afin qu'il pointe
toujours vers la première structure de la liste. Nous attribuons également à "prior" la valeur de "start" pour des
raisons que nous verrons bientôt. Gardez à l’esprit que les points finaux d’une liste chaînée devront toujours être
traités différemment de ceux situés au milieu d’une liste. Nous n'avons maintenant qu'un seul élément de notre liste
et il est rempli de données représentatives.

12.14 Remplissage de structures supplémentaires


Le groupe suivant d'affectations et d'instructions de contrôle est inclus dans une boucle "for" afin que nous puissions
construire notre liste rapidement une fois qu'elle est définie. Nous allons parcourir la boucle un nombre de fois égal
à la constante "RECORDS" définie au début de notre programme. À chaque fois, nous allouons de la mémoire,
remplissons les trois premiers champs de bêtises et remplissons les pointeurs. Le pointeur dans le dernier
enregistrement reçoit l'adresse de ce nouvel enregistrement car le pointeur « précédent » pointe vers l'enregistrement
précédent. Ainsi "avant­>suivant" reçoit l'adresse du nouvel enregistrement que nous venons de remplir.
Le pointeur dans le nouvel enregistrement reçoit la valeur "NULL", et le pointeur "avant" reçoit l'adresse de ce nouvel
enregistrement car la prochaine fois que nous créerons un enregistrement, celui­ci sera le précédent à ce moment­
là. Cela peut paraître déroutant, mais cela prend tout son sens si vous prenez le temps de l’étudier.

Lorsque nous aurons parcouru 6 fois la boucle "for", nous aurons une liste de 7 structures dont celle que nous avons
générée avant la boucle. La liste aura les caractéristiques suivantes. "start" pointe vers la première structure
1. de la liste.
2. Chaque structure contient un pointeur vers la structure suivante.
3. La dernière structure a un pointeur qui pointe vers NULL et peut être utilisée pour détecter la fin comme
indiqué ci­dessous.

start­>struct1 nom race age point­>struct2 nom race age point­>struct3


. .
nom race age point­> . . struct7 nom race âge point­>NULL

Il devrait être clair pour vous, si vous comprenez la structure ci­dessus, qu'il n'est pas possible de simplement sauter
au milieu de la structure et de modifier quelques valeurs. La seule façon d'accéder à la troisième structure est de
commencer par le début et de parcourir la structure, un enregistrement à la fois. Bien que cela puisse sembler un
prix élevé à payer pour la commodité de placer autant de données en dehors de la zone du programme, il s'agit en
réalité d'un très bon moyen de stocker certains types de données.

Un traitement de texte serait une bonne application pour ce type de structure de données car vous n'auriez jamais
besoin d'un accès aléatoire aux données. Dans la pratique, il s'agit du type de stockage de base utilisé pour le texte
dans un traitement de texte avec une ligne de texte par enregistrement. En fait, un programme quel que soit son
degré de sophistication utiliserait une liste doublement chaînée. Il s'agirait d'une liste avec deux pointeurs par
enregistrement, l'un pointant vers l'enregistrement suivant et l'autre pointant vers l'enregistrement juste avant celui
en question. L'utilisation de ce type de structure d'enregistrement permettrait de parcourir les données dans les deux
sens.

12.15 Impression des données


Pour imprimer les données, une méthode similaire à celle utilisée pour générer les données est utilisée. Les
pointeurs sont initialisés et sont ensuite utilisés pour passer d'un enregistrement à l'autre et afficher chaque
enregistrement un à la fois. L'impression se termine lorsque le NULL sur le dernier enregistrement est trouvé, donc le programme

Allocation dynamique Tutoriel C 12­7


Machine Translated
n'a mêmebypas
Google
besoin de savoir combien d'enregistrements se trouvent dans la liste. Enfin, la liste entière est
supprimée pour laisser de la place en mémoire aux données supplémentaires qui pourraient être nécessaires, dans
ce cas aucune. Il faut veiller à ce que le dernier enregistrement ne soit pas supprimé avant la vérification de NULL.
Une fois les données disparues, il est impossible de savoir si vous avez encore terminé.

12.16 En savoir plus sur l'allocation dynamique et les listes liées


Il n’est pas difficile, ni anodin, d’ajouter des éléments au milieu d’une liste chaînée. Il est nécessaire de créer le
nouvel enregistrement, de le remplir de données et de pointer son pointeur sur l'enregistrement que l'on souhaite
faire précéder. Si le nouvel enregistrement doit être installé entre le 3ème et le 4ème par exemple, il faut que le
nouvel enregistrement pointe vers le 4ème enregistrement, et le pointeur dans le 3ème enregistrement doit pointer
vers le nouveau. L'ajout d'un nouvel enregistrement au début ou à la fin d'une liste constitue chacun un cas particulier.
Considérez ce qui doit être fait pour ajouter un nouvel enregistrement dans une liste doublement chaînée.

Des livres entiers sont écrits décrivant différents types de listes chaînées et comment les utiliser, donc aucun détail
supplémentaire ne sera donné. La quantité de détails fournis devrait être suffisante pour une première compréhension
du C et de ses capacités.

12.17 Une autre nouvelle fonction ­ Calloc


Une fonction supplémentaire doit être mentionnée, la fonction "calloc". Cette fonction alloue un bloc de mémoire et
le remet à zéro, ce qui peut être utile dans certaines circonstances. Il est similaire à "malloc" et sera laissé comme
exercice pour que vous puissiez lire et utiliser "calloc" si vous le désirez.

12.18 Exercices de programmation


1. Réécrivez l'exemple de programme struct1.c du chapitre 11 pour allouer dynamiquement les deux
structures.

2. Réécrivez l'exemple de programme struct2.c du chapitre 11 pour allouer dynamiquement les 12


structures.

12­8 Tutoriel C Allocation dynamique


Machine Translated by Google
13
Manipulation des caractères et des bits

13.1 Majuscules et minuscules


Chargez et affichez le programme uplow.c pour un exemple de programme qui fait beaucoup de caractères
manipulation. Pour une description du fichier stdio.h, consultez le programme dosex_1616.c. Plus
plus précisément, uplow.c change la casse des caractères alphabétiques. Il illustre l'utilisation
de quatre fonctions liées au cas. Cela ne devrait poser aucun problème pour vous d'étudier ce programme
par vous­même et comprenez comment cela fonctionne. Les quatre fonctions affichées dans ce programme sont
le tout dans la fonction écrite par l'utilisateur, "mix_up_the_line". Compilez et exécutez le programme avec le
fichier de votre choix. Les quatre fonctions sont :

estupper(); Le caractère est­il en majuscule ?


est plus bas(); Le caractère est­il en minuscule ?
topper(); Mettez le caractère en majuscule.
baisser(); Mettez le caractère en minuscule.
#include "/sys/stdio.h"
#include"/sys/ctype.h" /* Remarque : votre compilateur n'en aura peut­être pas besoin */
principal( )
{
FICHIER *fp;
ligne de caractères [80], nom de fichier [24] ;
char *c;

printf("Entrez le nom du fichier ­> ");


scanf("%s",nom de fichier);
fp = fopen(nom de fichier,"r");
faire {
c = fgets(ligne,80,fp); si (c != NULL) { /* récupère une ligne de texte */

mix_up_the_chars(ligne);
}
} while (c != NULL);

fclose(fp);
}

mix_up_the_chars(line) caractères /* cette fonction transforme toutes les majuscules


en minuscules, et tout
minuscule en majuscule. Il ignore
tous les autres personnages. */
ligne de caractères[];
{
indice int ;
pour (index = 0;ligne[index] != 0;index++) {
if (isupper(line[index])) /* 1 si majuscule line[index] = tolower(line[index]); */

autre {
if (islower(line[index])) /* 1 si minuscule line[index] = toupper(line[index]); */

}
}
printf("%s",ligne);
}

Manipulation des caractères et des bits Tutoriel C 13­1


Machine Translated by Google
13.2 Classification des personnages
Chargez et affichez le programme suivant, charclas.c pour un exemple de comptage de caractères. Nous
J'ai utilisé à plusieurs reprises le caractère antislash n représentant une nouvelle ligne. Il y en a plusieurs autres
qui sont couramment utilisés, ils sont donc définis dans le tableau suivant ;
\n Nouvelle ligne
\t Onglet
\b Retour arrière
\" Double citation
\\ Barre oblique inverse

\0 NULL (zéro)

En faisant précéder chacun des caractères ci­dessus du caractère barre oblique inverse, le caractère peut être
inclus dans une ligne de texte pour affichage ou impression. De la même manière qu'il est parfaitement normal de
utiliser la lettre « n » dans une ligne de texte comme partie du nom de quelqu'un et comme fin de ligne, l'autre
les caractères peuvent être utilisés comme parties de texte ou pour leurs fonctions particulières.

Le programme sur votre écran utilise les fonctions qui peuvent déterminer la classe d'un personnage, et
compte les personnages de chaque classe. Le numéro de chaque classe est affiché avec la ligne
lui­même. Les trois fonctions sont les suivantes :

isalpha(); Le caractère est­il alphabétique ?


isdigit(); Le caractère est­il un chiffre ?
isspace(); Le caractère est­il \n, \t ou vide ?

#include "/sys/stdio.h"
#include "/sys/ctype.h" /*notez que votre compilateur n'en a peut­être pas besoin */
principal( )
{
FICHIER *fp;
ligne de caractères [80], nom de fichier [24] ;
char *c;

printf("Entrez le nom du fichier ­> ");


scanf("%s",nom de fichier);
fp = fopen(nom de fichier,"r");
faire {
c = fgets(ligne,80,fp); /* récupère une ligne de texte */
si (c != NULL) {
count_the_data(ligne);
}
} while (c != NULL);

fclose(fp);
}

count_the_data(ligne)
ligne de caractères[];
{
int blancs, caractères, chiffres ;
indice int ;

blancs = caractères = chiffres = 0 ;


pour (index = 0;ligne[index] != 0;index++) {
if (isalpha(line[index])) /* 1 si la ligne.. est alphabétique */
caractères++;
if (isdigit(line[index])) chiffres++; /* 1 si la ligne.. est un chiffre */

if (isspace(line[index])) /* 1 si la ligne.. est vide, tabulation, */


blancs++; /* ou nouvelle ligne /*fin de la boucle de comptage */ */
}

printf("%3d%3d%3d %s",blancs,caractères,chiffres,ligne);
}

13­2 Tutoriel C Manipulation des caractères et des bits


Ce programme
Machine Translated devrait être simple à parcourir, donc aucune explication ne sera donnée.
by Google
Il fallait donner un exemple avec ces fonctions utilisées. Compilez et exécutez ce programme avec n'importe quel
fichier de votre choix. Voir également dosex1616.c au chapitre 14 pour un autre exemple.

13.3 Les fonctions logiques


Chargez et affichez le programme bitops.c.
main( )

{ masque de
caractères ; numéro de
caractère.6, ; char et,ou,xor,inv,index;
numéro[0] = 0X00 ; numéro[1]
= 0X11 ; numéro[2] = 0X22 ;
numéro[3] = 0X44 ; numéro[4]
= 0X88 ; numéro[5] = 0Xff ;

printf("masque nbr et ou xor inv\n"); masque = 0X0F ; pour (index


= 0;index <= 5;index+
+) { et = masque & nombre[index]; ou = masque l
numéro[index]; xor = masque ^ numéro[index];
inv = ~numéro[index]; printf("%5x %5x %5x
%5x %5x %5x\n",numéro.index.,

masque,et,ou,xor,inv);
}

printf("\n"); masque
= 0X22 ; pour (index
= 0;index <= 5;index++) { et = masque & nombre[index]; ou
= masque l numéro[index]; xor = masque ^
numéro[index]; inv = ~numéro[index];
printf("%5x %5x %5x %5x %5x
%5x\n",numéro[index],
masque,et,ou,xor,inv);

}
}

Les fonctions de ce groupe de fonctions sont utilisées pour effectuer des opérations au niveau des bits, ce qui
signifie que les opérations sont effectuées sur les bits comme s'il s'agissait de bits individuels. Aucun report de bit à
bit n'est effectué comme cela serait le cas avec une addition binaire. Même si les opérations sont effectuées sur un
seul bit, un octet entier ou une variable entière peut être utilisé dans une seule instruction. Les opérateurs et les
opérations qu'ils effectuent sont indiqués dans le tableau suivant ; ET logique, si les deux bits sont 1, le résultat
& est 1.

| OU logique, si l'un des bits est un, le résultat est 1.


^
XOR logique, (OU exclusif), si un et un seul bit est 1, le résultat est 1.
~
Inversion logique, si le bit est 1, le résultat est 0, et si le bit est 0, le résultat est 1.

L'exemple de programme utilise plusieurs champs qui sont combinés de chacune des manières indiquées ci­dessus.
Les données sont au format hexadécimal. On supposera que vous connaissez déjà le format hexadécimal si vous
devez utiliser ces opérations. Si ce n’est pas le cas, vous devrez l’étudier vous­même. L'enseignement du format
hexadécimal des nombres dépasse le cadre de ce didacticiel.

Exécutez le programme et observez le résultat.

Manipulation des caractères et des bits Tutoriel C 13­3


Machine Translated by Google
13.4 Les instructions de quart de travail

Les deux dernières opérations abordées dans ce chapitre sont les instructions de décalage à gauche et de
décalage à droite. Chargez l'exemple de programme shifter.c pour un exemple en utilisant ces deux instructions.
Les deux opérations utilisent les opérateurs suivants : Décalage à gauche
<< n de n places.
>> n Décalage à droite de n places.

main( )

{ int petit, grand, index, compte ;


printf(" small décaler vers la gauche décaler vers la droite\n\n");
= 1; big =
0x4000; for(index =
0;index < 17;index++) {
printf("%8d %8x %8x\n",petit,petit,grand); petit = petit << 1 ;
grand = grand >> 1 ;

printf("\n"); compte
= 2 ; petit = 1 ;
grand =
0x4000 ; for(index =
0;index < 9;index++) { printf("%8d %8x
%8x\n",small,small,big); petit = petit << nombre ; grand = grand
>> compte ;

}
}

Là encore les opérations sont effectuées et affichées au format hexadécimal. Le programme doit être simple à
comprendre par vous­même, il n'y a pas de code compliqué.

13­4 Tutoriel C Manipulation des caractères et des bits


Machine Translated by Google
14
Exemples de programmes

14.1 Pourquoi ce chapitre ?


Bien que chaque programme de ce didacticiel soit un programme complet, chacun d'entre eux est également un très petit
programme destiné à vous apprendre quelques principes de programmation en C. Cela ne vous rendrait pas service de vous
arrêter là sans vous présenter quelques des programmes plus vastes pour illustrer comment rassembler les constructions que
vous avez apprises pour créer un programme majeur. Ce chapitre contient quatre programmes de complexité croissante, chacun
conçu pour vous emmener vers un plateau supérieur de programmation, et chacun conçu pour vous être utile d'une manière ou
d'une autre.

DOSEX était destiné à illustrer comment effectuer des appels système MS­DOS et vous apprendra, grâce à l'auto­apprentissage,
comment le système répond au clavier. DOSEX a été modifié par Tim Ward pour utiliser les appels système Applix 1616 au lieu
des appels MS­DOS.

WHATNEXT lit les commandes saisies sur la ligne de commande et vous aidera à configurer un fichier de commandes variable,
un fichier qui demande une entrée d'opérateur et répond à l'entrée en se connectant à une partie différente du fichier de
commandes.

LIST est le code source du programme que vous avez utilisé pour imprimer les fichiers sources C lorsque vous avez commencé
à étudier le C à l'aide de ce didacticiel. Enfin, nous arrivons à VC, la Calculatrice Visuelle, que vous devriez trouver comme un
programme utile même si vous n'étudiez pas son code source. VC utilise la plupart des techniques de programmation que nous
avons étudiées dans ce cours et quelques­unes que nous n'avons même jamais mentionnées, comme les sous­programmes
compilés séparément.

Nous examinerons les exemples de programmes un par un, mais sans explication complète d'aucun d'entre eux, car vous étudiez
le C depuis un certain temps maintenant et devriez être capable de lire et de comprendre la plupart de ces programmes par vous­
même. Une autre chose doit être mentionnée : ces programmes utilisent de nombreuses constructions non standard et vous
devrez probablement en modifier certaines pour les faire compiler avec votre compilateur particulier. Cela vous sera laissé en
exercice. dosexibm.c ­ L'exemple de programme MS­DOS La copie de MS­DOS que vous avez reçue avec votre IBM­PC ou

compatible comporte de nombreux appels MS­DOS internes que

vous pouvez utiliser en tant que programmeur pour contrôler vos périphériques et lire des informations ou des états. d'eux.
Certains des manuels IBM DOS antérieurs, MS­DOS 2.0 et versions antérieures, répertorient ces appels à la fin du manuel ainsi
que la manière de les utiliser. La plupart des manuels fournis avec les ordinateurs compatibles ne font aucune mention de ces
appels même s'ils sont extrêmement utiles. Ces appels sont accessibles à partir de presque tous les langages de programmation,
mais ils nécessitent une étude initiale pour apprendre à les utiliser. Ce programme est destiné à vous aider dans cette étude.

Affichez le programme sur votre moniteur ou imprimez­le pour référence. Il s'agit simplement d'une boucle guettant une saisie au
clavier ou un changement de temps. Si l’un ou l’autre se produit, il réagit en conséquence. À la ligne 23, la fonction "kbhit()"
renvoie une valeur de 1 si une touche a été appuyée mais pas encore lue dans le tampon d'entrée par le programme. Il s'agit
d'une fonction non standard et peut nécessiter un changement de nom pour votre compilateur particulier. Il y aura probablement
plusieurs appels similaires qui devront être modifiés pour votre compilateur afin de compiler et exécuter les programmes du
chapitre 14.

Regardez la fonction nommée "get_time" pour un exemple d'appel MS­DOS. Une interruption 21 (hex) est appelée après avoir
réglé le registre AH sur 2C (hex) = 44 (décimal). L'heure est renvoyée dans les registres CH, CL et DH. Reportez­vous aux
définitions d'appel MS­DOS dans votre copie de MS­DOS (si disponible). Si les définitions n'y figurent pas, le livre de Peter Norton,
"Programmers Guide

Exemples de programmes Tutoriel C 14­1


au PC IBM"
Machine Translated byest recommandé comme bon manuel de référence pour ces appels et bien d'autres
Google
techniques de programmation. Vous remarquerez qu'il est un peu plus complexe que l'Applix 1616
équivalent.

Une autre fonction utile est la fonction "pos_cursor()" qui positionne le curseur n'importe où sur le
moniteur que vous désirez en utilisant une interruption MS­DOS. Cet appel a été modifié dans l'Applix
Version 1616, pour utiliser un appel système équivalent. Dans le cas MS­DOS, l'interruption utilisée est 10(hex)
qui est l'interruption générale du moniteur. Ce service particulier est le numéro 2 sur environ 10 différents
services de surveillance disponibles. Cette fonction particulière n'est peut­être pas nécessaire à votre compilateur car
certains compilateurs ont une fonction de positionnement du curseur prédéfinie pour votre usage. Cette fonction est
inclus ici comme un autre exemple pour vous.

La fonction suivante, le service numéro 6 de l'interruption 10 (hex) est le service de défilement de fenêtre. Cela devrait
être explicite. Le service de défilement de fenêtre a été supprimé de la version Applix. Complet
les détails de la prise en charge des fenêtres de Conal Walsh sont fournis dans les didacticiels commençant dans
µProblème périphérique 10.

Dans ce programme, le curseur est positionné et certaines données sont sorties sur le moniteur, puis le curseur
est "caché" en le déplaçant vers la ligne 26 qui n'est pas affichée. Après avoir compilé et exécuté le
programme, vous remarquerez que le curseur n’est pas visible sur le moniteur. Ceci est possible dans n'importe quel
programme, mais assurez­vous de mettre le curseur en vue avant de revenir au DOS car le DOS ne le fait pas.
j'aime avoir un curseur "caché" et peut faire des choses étranges.

Un peu de temps passé à étudier ce programme vous sera précieux car il vous dévoilera comment le clavier
les données sont entrées dans l’ordinateur. Il est particulièrement important de savoir comment les touches spéciales telles que la fonction
les touches, les flèches, etc. sont gérées.

dosex_1616.c ­ est le programme Applix 1616 équivalent à celui ci­dessus.

/* ************************************************* **********************/
/* Ceci est un exemple de programme pour illustrer comment ; */
/* 1. Obtenez l'heure et la date d'APPLIX 1616/OS à l'aide d'un appel système */
/* 2. Placez le curseur sur n'importe quelle position sur l'écran à l'aide d'une vidéo 1616/OS*/
/* code d'échappement du pilote */
/* 3. Lire les caractères du clavier et afficher leurs codes */
/* 4. Comment faire défiler une fenêtre vers le haut sur le moniteur */
/* 5. Formater un programme pour faciliter la lecture et la compréhension */
/* ************************************************* **********************/
#include "/sys/stdio.h"
#include "/sys/syscalls.h"
#include "/sys/ctype.h"
principal( )
{
caractère int, x ;
x=2;
draw_box(); /* dessine les cases autour des champs */
pos_cursor(33,19);
printf("Tapez Q pour quitter");
faire {
if (kbhit()) { /* faire défiler /* une touche a­t­elle été appuyée */
si (x <= 16) la sortie dans la fenêtre vers le bas a */
{ pos_cursor(9,x+1); /* doubler. ++x; */

}
sinon si
(x <= 31){
pos_cursor(50,x­14); /* retourne en haut de la fenêtre à droite */
++x; /* côté. */
}
autre {
x=2; /* retour en haut de la fenêtre à gauche */
pos_curseur(9,x+1); /* côté. */
}
caractère = getch(); /* je le lis */

14­2 Tutoriel C Exemples de programmes


disp_char(caractère);
Machine Translated by Google /* l'afficher */
}
obtenir du temps(); /* récupère l'heure de la journée et l'affiche. */

} while (caractère != 'Q'); /* Quitte lorsqu'un Q est trouvé */

pos_curseur(0,0); /* place le curseur en haut de l'écran */


}
/* ************************************************* *********** boîte à tirage */
/* Cette routine dessine une boîte sur l'écran. Les touches frappées, l'heure et */
/* la date est affichée dans ces cases. Rien de spécial à ce sujet */
/* boîtes, ce sont des sorties simples à l'aide de la fonction printf. */
/* ************************************************* ******************* */
draw_box()
{
indice int ;
ligne de caractères[81] ;
pour (index = 0;index < 80;index++) line[index] = line[80] /* trois lignes vides */
= NULL; pour (index ' ';
= 0;index < 3;index++) /* fin de chaîne */

printf("%s",ligne);
ligne[8] = 201 ; pour /* dessine la ligne supérieure de la boîte */
(index = 9;index < 70;index++)
ligne[index] = 205 ;
ligne[70] = 187 ;
printf("%s",ligne);
de boîte[8] = 186; /* dessine les côtés d'une grande ligne */
pour (index = 9;index < 70;index++)
ligne[index] = ligne[70] ' ';
= 186;
pour (index = 0;index <15;index++)
printf("%s",ligne);
ligne[8] = 204 ; pour /* trace une ligne entre les cases */
(index = 9;index < 70;index++)
ligne[index] = 205 ;
ligne[70] = 185 ;
printf("%s",ligne);
ligne[8] = 186 ; pour /* côtés de la boîte heure/date */
(index = 9;index < 70;index++)
ligne[index] = ligne[70] ' ';
= 186;
printf("%s",ligne);
ligne[8] = 200 ; pour /* ligne du bas de la boîte */
(index = 9;index < 70;index++)
ligne[index] = 205 ;
ligne[70] = 188 ;
printf("%s",ligne);
pour (index = 0;index < 80;index++) ligne[index] = pour /* trois lignes vides */
(index = 0;index < ' ';
3;index++)
printf("%s",ligne);
}

/* ************************************************* ********* disp_char */


/* Cette routine affiche les caractères frappés sur le moniteur. Si le premier */
/* le caractère est un zéro, c'est un caractère spécial et le zéro est */
/* affiché. Le caractère suivant est lu et affiché sur le moniteur. */
/* ************************************************* ******************* */
disp_char(houle)
int houle;
{
int c;
c = gonflement ;

Exemples de programmes Tutoriel C 14­3


Machine Translated bysi Google
(c == 13) {
retour;
}
if ( isupper(c) ) printf("%4d {
(%c) Majuscule ",c,c);
}
if ( islower(c) ) printf("%4d {
(%c) Minuscule ",c,c);
}
if ( isspace(c) ) printf("%4d {
(%c) Espace blanc",c,c);
}
if ( ispunct(c) ) printf("%4d {
(%c) Ponctuation",c,c);
}
if ( isdigit(c) ) printf("%4d {
(%c) Chiffre ",c,c);
}
pos_curseur(25,1); /* cache le curseur sur la 26ème ligne */
}
/* ************************************************* ******* pos_cursor */
/* La fonction permet de positionner le curseur sur l'écran à l'aide du */
/* Appel d'échappement vidéo 1616OS */
/* ************************************************* ***************** */
pos_curseur(xpos,ypos)
int xpos, ypos;
{
printf("\033=%c%c", ypos + 32, xpos + 32);
}

/* ************************************************* ********obtenir du temps */


/* La routine appelle l'appel de fonction 1616OS pour l'heure de la journée. Retour */
/* l'heure de la journée à laquelle le programme doit être appelé dans une boucle do while pour que */
/* est facilement mis à jour /* */
******************************************* ******************** */
obtenir du temps()
{
char *temps, BUF[22];
temps = GETTDSTR(BUF); /* Appel système 1616 pour la chaîne timedate */
pos_cursor(10,19); /* fonction de positionnement du curseur */
printf("%s",heure);
pos_cursor(50,19);
printf("%s",heure);
}

14.2 whatnext.c ­ L'interrogateur de fichiers batch


Ceci est un exemple de la façon de lire les données sur la ligne de commande après l'appel de fonction.
Notez qu'il y a deux variables répertoriées entre parenthèses après l'appel main(). Le
la première variable est un nombre de mots dans toute la ligne de commande, y compris la commande elle­même et
la deuxième variable est un pointeur vers un tableau de pointeurs définissant les mots réels de la commande
doubler.

Tout d'abord, la question sur la ligne de commande, composée d'un certain nombre de mots, est affichée sur l'écran.
moniteur et le programme attend que l'opérateur appuie sur une touche. Si la touche frappée est l'une de celles du
dernier "mot" du groupe de mots sur la ligne de commande, le numéro du caractère dans le
Le groupe est renvoyé au programme où il peut être testé avec la commande "errorlevel" dans le
fichier batch. Vous pouvez utiliser cette technique pour créer un fichier de variable AUTOEXEC.BAT ou tout autre
Le fichier batch peut l'utiliser pour une branche à plusieurs voies. Compilez et exécutez ce fichier avec TEST.BAT pour
un exemple de la façon dont cela fonctionne dans la pratique. Vous trouverez peut­être cette technique utile dans l'un de vos lots
fichiers et vous aurez presque certainement besoin de lire les paramètres de ligne de commande un jour. Depuis

14­4 Tutoriel C Exemples de programmes


1616/OS by
Machine Translated n'utilise
Googlepas de fichiers batch comme ceux de MS­DOS, ce programme n'est pas très utile, mais il
est laissé comme exemple de la façon de transmettre des paramètres à partir d'une ligne de commande et de les utiliser dans un
programme.

Une alternative intéressante serait d'écrire un programme nommé "would.c" qui


renvoie un 1 si un "Y" ou un "y" a été tapé et un zéro si une autre touche a été enfoncée. Puis votre fichier batch
pourrait avoir une ligne incluant un tel test.
/* ************************************************* ******************* */
/* Ce programme lit une série de mots depuis la ligne de commande, et */

/* affiche tout sauf le dernier sur le moniteur. Le dernier est une série de */
/* Caractères utilisés comme comparaisons d'entrée. Un caractère est */
/* lecture depuis le clavier. S'il s'agit d'un des caractères du */
/* liste de comparaison, son numéro est renvoyé au DOS comme niveau d'erreur */
/* commande. Si le caractère n'existe pas dans la liste, un zéro est
*/
/* revenu. L'exemple suit : /* /* WHATNEXT Quel */
*/
modèle souhaitez­vous ? ALR%3T /* /* /* /* /* /* /* /* /* La question doit */
Si la touche a ou A est enfoncée, le niveau d'erreur 1 est renvoyé. */
Si la touche l ou L est enfoncée, le niveau d'erreur 2 est renvoyé. */
Si la touche r ou R est enfoncée, le niveau d'erreur 3 est renvoyé. */
Si la clé % est atteinte, le niveau d'erreur 4 est renvoyé. */
Si la touche 3 est activée, le niveau d'erreur 5 est renvoyé. */
Si la touche t ou T est enfoncée, le niveau d'erreur 6 est renvoyé. */
Si une autre touche est atteinte, le niveau d'erreur 0 est renvoyé. */
*/
être sur une seule ligne. */
/* Jusqu'à neuf clés différentes peuvent être utilisées. */
/* Le niveau d'erreur peut être interprété dans un fichier batch. */
/* ************************************************* ************** */

#include "/sys/stdio.h"
#include "/sys/ctype.h"
principal(numéro,nom)
numéro entier ; /* nombre total de mots sur la ligne de commande */
char *nom[];
{
indice int ; int c; /* un compteur et une variable incrémentale */
code /* le caractère lu pour comparaison */
entier ; char /* le niveau d'erreur résultant est renvoyé à */
next_char; char *point; /* utilisé pour la boucle de comparaison */
/* un pointeur factice utilisé pour plus de commodité */

/* Au moins un groupe doit être utilisé pour cela */


/* nom de fichier et un groupe utilisé pour le */
/* champs obligatoires, donc moins de trois permettent */
/* sans questions. */
si (nombre < 3) {
printf("Aucune question posée sur la ligne de commande\n");
sortie(0);
}

/* affiche les mots 2 à n­1, la question */


nombre­­;
pour(index = 1;index < nombre;index++) {
printf("%s ",nom[index]);
}

/* récupère la réponse de l'utilisateur et la met en majuscule */


c = getch();
printf("%c\n",c);
si (est inférieur (c))
c = dessus(c);
point = nom[numéro]; /* pointe vers le dernier pointeur sur les entrées */

Exemples de programmes Tutoriel C 14­17


codeby
Machine Translated = 0Google
;
indice = 0 ;
faire /* recherche parmi les réponses autorisées dans le dernier mot */
{ next_char = *(point + index);
if (est inférieur (next_char))
next_char = toupper(next_char); /* le met en majuscule */
if(next_char == c) code = /* si une correspondance est trouvée */
index + 1; indice++; /* sauvegarde le numéro du match */

} while (*(point + index)); /* renvoie le code /* jusqu'à ce que le terminateur NULL soit trouvé */
quitter(code); d'erreur au système */
}

14.3 List.C ­ Le listeur de programmes


Ce programme est en fait composé de deux fichiers, list.c et listf.c qui doivent être séparés
compilé et lié avec votre éditeur de liens. Il n'y a rien de nouveau ici et vous auriez dû
aucun problème pour compiler et lier ce programme en lisant la documentation fournie avec votre
compilateur.

La façon de les compiler avec HiTech C est la suivante :


relcc ­v ­W1 liste.c listef.c Entrer

/* ************************************************* ******************* */
/* Ce programme lira n'importe quel fichier et le listera sur le moniteur avec */
/* les numéros de ligne et les numéros de page. */
/* ************************************************* ******************* */
#include "/sys/stdio.h" /* fichier d'en­tête d'E/S standard */
#define MAXCHARS 255 /* taille maximale d'une ligne */
FICHIER *point_fichier ; /* pointe vers le fichier à lire */
FICHIER *print_file_point; externe /* pointeur vers le pronter */
top_of_page();
char oneline[256]; /* zone tampon de chaîne d'entrée */
principal(numéro,nom)
numéro entier ; /* nombre d'arguments sur la ligne de commande */
char *nom[]; { /* arguments sur la ligne de commande */

char *c; char /* variable pour indiquer la fin du fichier */


*point;
point = nom[1];
open_file(nombre,point); /* ouvre le fichier pour le lire et l'imprimer */
open_print_file();
faire {
c = fgets(oneline,MAXCHARS,file_point); /* lit une ligne */
si (c != NULL)
print_a_line(); } while (c ! /* affiche une ligne */
=NULL); /* continue jusqu'à EOF */

haut de page(); fermer /* déplace le papier en haut de la page */


(point_fichier); /* ferme le fichier lu /* ferme le */
fermer(print_file_point); fichier imprimante */
}

La seule nouveauté de ce programme est l'inclusion de trois variables "externes" dans le


liste listf.c. Le seul but est de lier ces variables globales au programme principal
et dites au compilateur que ce ne sont pas de nouvelles variables. Le compilateur ne générera donc pas
tout nouvel espace de stockage pour eux, mais utilisez simplement leurs noms pendant le processus de compilation. Au lien
temps, l'éditeur de liens obtiendra leurs emplacements de stockage réels à partir du fichier LIST.OBJ et les utilisera
emplacements pour les variables dans la partie LISTF de la carte mémoire également. Les variables de ceux
les noms dans les deux fichiers sont donc les mêmes variables identiques et peuvent être utilisés comme n'importe quel autre
les variables globales pourraient être utilisées si les deux parties du programme étaient dans un seul fichier.

14­6 Tutoriel C Exemples de programmes


/* *************************************************
Machine Translated by Google ******************** */
/* Le module contient les fonctions appelées par le programme list.c. Si ce */
/* si un programme devait être utilisé dans un but spécifique, il ne le serait probablement pas*/
/* Il serait sage de le diviser en deux modules compilés séparément. Ce n'est que */
/* fait ici à des fins d'illustration. C'est un programme utile.
*/
/* ************************************************* ******************** */
#define MAXLINES 54 nombre maximum de lignes /* par page */
#include "/sys/stdio.h" /* fichier d'en­tête d'E/S standard */
externe FICHIER *file_point; FICHIER /* pointer sur le fichier à lire */
externe *print_file_point; extern char oneline[]; /* pointeur vers l'imprimante */
nom de fichier char[15] ; int /* zone tampon de chaîne d'entrée */
numéro_ligne = 0 ; int /* nom de fichier de l'en­tête ou de l'invite */
numéro_page = 1 ; int /* numéro de ligne initialisé à un */
lignes_this_page = 0; /* numéro de page initialisé à un */
/* lignes sur cette page jusqu'à présent */

/* ************************************************* ******* fichier ouvert */


/* Cette fonction ouvre le fichier d'entrée sur la ligne de commande, s'il y en avait */
/* celui défini. Sinon, demande l'ouverture d'un fichier et ouvre le */
/* fichier demandé. */
/* ************************************************* ***************** */
fichier_ouvert (non, nom)
numéro /* nombre d'arguments sur la ligne de commande */
int ; char *nom; { /* premier argument de la ligne de commande */

strcpy(nom de fichier,nom); /* copier le nom de l'en­tête d'impression */


/* été donné dans la commande */
point_fichier = NULL ; si aucun nom n'a
if (no == 2) { /* ouvre /* Le 2ème champ de la commande est le nom du fichier */
le fichier demandé
file_point = fopen(nom,"r"); */
si (file_point ==
NULL) /* NULL si le fichier n'existe pas */
printf("Le nom de fichier sur la ligne de commande n'existe pas !\n");
}

faire {
if (file_point == NULL) { printf("Entrez le /* pas encore de nom de fichier */
nom du fichier ­> ");
scanf("%s",nom de fichier);
file_point = fopen(nom de fichier,"r"); /* NULL si le /* fichier ouvert */
if (file_point == NULL) printf("Le nom fichier n'existe pas */
de fichier n'existe pas, réessayez.\n");
}
} while (file_point == NULL); /* continue jusqu'à ce que le nom de fichier soit correct */
}

/* ************************************************* ****** fichier_open_print


*/
/* Cette fonction ouvre le fichier d'imprimante sur l'imprimante standard.
*/
/* ************************************************* **********************
*/
open_print_file()
{
print_file_point = fopen("PRN","w"); /* ouvre le fichier imprimante */
}

/* ************************************************* ********* print_a_line


*/
/* Cette routine imprime une ligne de texte et vérifie s'il y a de la place pour
*/
/* un autre sur la page. Sinon, il démarre une nouvelle page avec un nouvel en­tête.
*/
/* Cette routine appelle plusieurs autres routines locales.
*/
/* ************************************************* **********************
*/

Exemples de programmes Tutoriel C 14­7


print_a_line()
Machine Translated { int index;
by Google

entête();
printf("%5d %s",numéro_ligne,oneline);
/* Ceci imprime une ligne de moins de 72 caractères */
if (strlen(oneline) < 72)
fprintf(print_file_point,"%5d %s",line_number,oneline);
/* Ceci imprime une ligne de 72 à 143 caractères */ else if (strlen(oneline) <
144) {
fprintf(print_file_point,"%5d ",line_number); pour (index = 0;index < 72;index+
+)
fprintf(print_file_point,"%c",oneline[index]); fprintf(print_file_point,"<\n "); pour
(index = 72;index < strlen(oneline);index++)

fprintf(print_file_point,"%c",oneline[index]); lignes_this_page++;

}
/* Ceci imprime une ligne de 144 à 235 caractères */
sinon si (strlen(oneline) < 235) {
fprintf(print_file_point,"%5d ",line_number); pour (index = 0;index < 72;index+
+)
fprintf(print_file_point,"%c",oneline[index]); fprintf(print_file_point,"<\n "); pour
(index = 72;index < 144;index++)
fprintf(print_file_point,"%c",oneline[index]);
fprintf(print_file_point,"<\n "); for (index = 144;index < strlen(oneline);index+
+) fprintf(print_file_point,"%c",oneline[index]); lignes_this_page
+= 2;

}
/* la ligne suivante génère une nouvelle ligne s'il n'y en a pas à la fin de la dernière ligne */ if
(oneline[strlen(oneline)­1] != '\n')
fprintf(print_file_point,"%c",'\ n'); numéro_ligne++; lignes_this_page+

/* ************************************************* ********* en­tête */ /* Cette routine vérifie si un en­tête doit être imprimé. Elle
vérifie également */ /* la fin d'une page et espace le papier. */ /* ********************************************** ********************
*/ en­tête() { int index;

/* voir d'abord si nous sommes en bas de la page */ /* espacer le papier à partir du bas */
lines_this_page;index < 61;index++) if (lines_this_page > MAXLINES) { for (index =
fprintf(print_file_point,"\n "); lignes_this_page = 0 ; }

/* afficher un en­tête de moniteur uniquement au tout début */ /* afficher l'en­tête de moniteur */


si (numéro_ligne == 0) {
numéro_ligne Fichier source %s\n",nom de fichier); printf("
= 1;
}
/* vérifie si nous sommes en haut de la page soit */ /* en démarrant un fichier, soit en suivant un
bas de page */ /* en haut de chaque page d'imprimante */ ");
if (lines_this_page == 0)
{ fprintf(print_file_point,"\n\n\n fprintf(print_file_point,"
Fichier source ­ %s fprintf(print_file_point," ",nom de fichier);
Page %d\n\n",numéro_page);

14­8 Tutoriel C Exemples de programmes


Machine Translated bynuméro_page++;
Google
}
}

/* ************************************************* ******** top_of_page */ /* Cette fonction espace le papier en haut de


la page suivante afin qu'un autre */ /* appel à cette fonction démarre correctement. Utilisé uniquement à la fin */ /*
d'une impression complète. */ /* ********************************************** *********************** */ top_of_page() { int
index;

for (index = lines_this_page;index < 61;index++) fprintf(print_file_point,"\n");

Il n'y a aucune raison pour que les variables n'aient pas pu être définies dans la partie listf.c du programme et déclarées
comme "externes" dans la partie list.c. Certaines variables auraient pu être définies dans l’un et d’autres dans l’autre. C'est
simplement une question de goût personnel. Poussé à l'extrême, l'ensemble des variables aurait pu être défini dans un
troisième fichier et nommé "extern" dans ces deux fichiers. Le troisième fichier serait alors compilé et inclus dans le
processus de liaison.

Il serait à votre avantage de compiler, lier et exécuter ce programme pour vous préparer au prochain programme composé
de 5 fichiers distincts qui doivent tous fonctionner ensemble.

14.4 Vc.C ­ La calculatrice visuelle


Ce programme relie finalement presque tout car il utilise presque tous les concepts abordés dans l'intégralité du didacticiel.
Il est si grand que je n’essaierai même pas d’aborder les subtilités de son fonctionnement.
Seuls quelques­uns des points les plus importants seront abordés.

La première chose à faire est de parcourir le didacticiel pour VC inclus dans le fichier VC.DOC.
Vous devez exécuter plusieurs dizaines d'étapes, chaque étape illustrant un aspect de la calculatrice visuelle. Vous aurez
une bonne idée de ce qu'il est capable de faire et rendrez votre étude du code source très rentable. De plus, vous trouverez
probablement de nombreuses façons d'utiliser la calculatrice visuelle pour résoudre des problèmes impliquant des calculs
pour lesquels la simplicité du problème ne justifie pas l'écriture d'un programme.

Notez que les définitions de structure, utilisées dans toutes les parties distinctes du programme, sont définies dans le
fichier STRUCT.DEF (renommé STRUCT.H dans la version Applix 1616). Vous devez inclure STRUCT.H avec les autres
fichiers d'en­tête Applix 1616. Lors du développement du programme, lorsqu'il devenait nécessaire de modifier légèrement
une des structures, il n'était pas nécessaire de la changer dans tous les fichiers, un seul fichier nécessitait une modification
qui était alors "inclus" dans les fichiers sources.
Notez que les données de transcription sont stockées dans une liste doublement chaînée, les données elles­mêmes étant
stockées dans une chaîne de caractères distincte allouée dynamiquement. Cette ligne est pointée par le pointeur "lineloc".

Pour faciliter le développement, les fonctions similaires ont été regroupées et compilées séparément.
Ainsi, toutes les fonctions impliquant le moniteur ont été incluses dans le fichier nommé video.c, et toutes les fonctions
impliquant le stockage de données ont été regroupées dans la collection file.c.
Diviser votre programme d'une manière similaire à celle­ci devrait simplifier le débogage et les modifications futures.

La fonction "monitor()" est particulièrement intéressante. Dans la version Applix 1616, cette fonction est supprimée, car le
1616 prend en charge les moniteurs couleur et monochromes sans changement. Dans le monde MS­DOS, cette fonction
examine le mode vidéo à l'aide d'une commande DOS et s'il s'agit d'un 7, elle suppose qu'il s'agit d'un moniteur
monochrome, sinon elle suppose un moniteur couleur. Les couleurs des différents champs sont établies à ce moment et
utilisées tout au long du programme. La plupart des données sont écrites directement dans la mémoire vidéo, mais
certaines sont écrites via les routines BIOS MS­DOS standard.

Exemples de programmes Tutoriel C 14­9


Le fichierby
Machine Translated definc.c
Google est simplement un catalogue de fonctions pour aider à trouver les fonctions. Ce
Le fichier a été généré comme l'un des premiers fichiers et a été maintenu et mis à jour pour être utilisé pendant la
toute la durée de vie de la conception et du codage.

N'hésitez pas, après avoir compris ce code, à le modifier comme vous le souhaitez pour votre propre usage.

Pour compiler et lier ceci, copiez les cinq fichiers VC (data.c, file.c, vc.c,
video.c, struct.h) dans un répertoire et incluez ce répertoire dans votre XPath. Taper:
relcc ­v ­W1 ­lf vc.c data.c vidéo.c fichier.c
(Notez que l'option ­lf doit être incluse pour que le compilateur utilise la bibliothèque float, tandis que l'option ­lf doit être incluse pour que le compilateur utilise la bibliothèque float, tandis que l'option ­lf doit être incluse pour que le compilateur utilise la bibliothèque float, tandis que l'option

d'autres sont facultatifs.) Ou utilisez le makefile inclus sur le disque de distribution, si vous disposez du
rendre utilitaire.
#include "/sys/ctype.h"
#include "/sys/stdio.h"
#include "/f0/struct.h"
#include "/sys/syscalls.h"
struct vars allvars[12]; int varinuse = 0; /* c'est le stockage principal des variables */
char en ligne[60]; col int ; /* quelle variable est utilisée actuellement */
code d'erreur int ; int /* zone de la ligne d'entrée */
couleur; int /* utilisé pour rechercher dans l'entrée */
printit = 1; int /* numéro du code d'erreur /* */
ignorer; externe colonne où l'erreur s'est produite /* 1 = imprimer */
char strngout[]; lignes de une transcription /* 1 = ignorer les calculs */
structure *top, pour la ligne /* zone de message de sortie */
*bot, *q, *p, *arrow, *trnsend ; */

/* ************************************************* ************* principal */


/* La boucle de contrôle principale du programme. Initialise tout */
/* et lit les instructions jusqu'à ce qu'il n'y ait plus d'erreurs. Continue la lecture jusqu'à */
/* F10 se produit dans une fonction subordonnée où le contrôle est rendu à */
/* Système d'exploitation 1616. */

principal()
{
top = bot = q = p = flèche = trnsend = NULL ;
initfk(); /* configure les touches de fonction */
initdata(&sévérité[0]); bkgndvid(); /* initialise toutes les données */
valusvid(); /* afficher l'arrière­plan vidéo ­ lignes doubles */
/* affiche les valeurs de départ de toutes les variables */
strtrans("Bienvenue dans la Calculatrice Visuelle ­ Applix 1616 ­ Version
1.00",0);transout();
faire {
cours(22,7);
printf(" entrée >
");
printf(" do ");
/* répéter jusqu'à ce qu'il n'y ait plus */
{ readline(); errdis(" d'erreur /* obtenir une ligne */
parse(); if de saisie "); /* effacer le message d'erreur */
(errcode) /* analyser la ligne */

erreur(); } while /* message d'erreur de sortie */


(code d'erreur);
si (ignorer == 1)
strtrans(en ligne,0); autre /* stocke le commentaire dans la transcription */

strtrans(en ligne,1); transout(); /* stocke "en ligne" dans la transcription */

} tandis que (1); /* boucle continue */


}
/* ************************************************* ********* lire la ligne */
/* Cette fonction lit une ligne en saisissant un caractère à la fois et */
/* décider quoi en faire s'il s'agit d'un caractère spécial, ou l'ajouter à */
/* la ligne de saisie s'il ne s'agit pas d'un caractère spécial. La routine s'occupe de*/
/* des choses telles que le retour arrière, le mouvement du curseur et les touches de suppression. Le final*/

14­10 Tutoriel C Exemples de programmes


/* le résultat
Machine Translated by est une ligne de texte stockée dans le buffer "inline" et la ligne */
Google
/* affiché sur le moniteur. */
lire la ligne()
{
indice int ;
int c,temp;
ligne int = 22, col = 17 ;
if (code d'erreur) { index /* la récupération d'erreur autorise la nouvelle saisie */
= colerr ;
code d'erreur = 0 ;
}
sinon /* routine de saisie normale */
{ indice = 0 ;
pour (temp = 0;temp < 60;temp++)
en ligne[temp] = 0 ; /* effacer le tampon d'entrée */
}

poscurs(ligne,col+index); /* emplacement de départ du curseur /* répétez */


do { / cette boucle do jusqu'à ce qu'un retour soit atteint */
* while
obtenir((cune
= getch())
frappe */== EOF); si ((c == 2) || (c ==
3) || (c == 4) || (c == 5) || (c == 12) ||
(c == 24) || (c == 18) || (c == 19) || (c == 127)) {
interrupteur (c) {
cas 19 : if (index) { index = index ­1 ; } /* Flèche gauche */
/* sauvegarder le curseur */

casser;
cas 4 : if (index < 61) { if (inline[index] == 0); /* flèche droite */
inline[index] = index = index + 1; /* zéro trouvé */
' '; /* vide sur 0 */
/* curseur en avant */
}
casser;
cas 5 : movarrow(­1); casser; /* flèche vers le haut */

cas 24 : movarrow(1); casser; /* flèche vers le bas */

cas 18 : movarrow(­8); casser; /* page précédente */

cas 3 : movarrow(8); casser; /* bas de page */

cas 12 : movarrow(­1000); casser; /* maison */

cas 2 : movarrow(1000); casser; /* fin */

cas 127 : temp = index; /* déplace tous /* supprimer la clé */


les caractères vers la gauche d'un espace while (inline[temp]) { */

inline[temp] = inline[temp+1];
putchar(inline[temp++]);
}
putchar(' '); casser; /* vide à la dernière place */

par défaut : poscurs(15,5);


printf("S%3d",c);
}
poscurs(ligne,col+index); /* met réellement le curseur en position*/
}

Exemples de programmes Tutoriel C 14­11


si (c by
Machine Translated == 0) {
Google /* un zéro ici indique qu'une touche spéciale a été enfoncée /* récupérer */
la clé et agir dessus si nécessaire */
spécification int ;
spec = getch(); /* c'est le code spécial trouvé */
commutateur (spéc.) {
cas 59 : helpm(); transout(); /* F1 ­ Aide maths */

casser;
cas 60 : aide(); transout(); /* F2 ­ Système d'aide */

casser;
cas 61 :
casser; /* F3 ­ Rechange */
cas 62 : /* F4 ­ Marquer la transcription */
flèche­>marqué = (flèche­>marqué?0:1);
transout();
casser;
cas 63 : fileout(); casser; /* F5 ­ Transcription du magasin */

cas 64 : filein(); code d'erreur = /* F6 ­ récupérer la trans */



casser;
cas 65 : pause ;
cas 66 : /* F7 ­ Rechange */
pause ; cas
67 : /* F8 ­ Rechange */
/* F9 ­ Modifier une ligne */
strcpy(inline,flèche­>lineloc);
cours(22,17);
printf("%s",en ligne);
casser;
cas 68 : poscurs(22,17); printf("Quitter ? /* F10 ­ Quitter vers 1616OS */
(O/N) ");
c = getch();
si ((c == 'Y') || (c == 'y')) {
clrscrn();
sortie(0);
}
autre {
cours(22,17);
printf(" pause ; ");

}
par défaut : poscurs(15,5);
printf(" S%3d",spéc);
}
poscurs(ligne,col+index); /* met réellement le curseur en position */
}

sinon {int /* lettre ou caractère normal */


curr, suivant ;
si (est inférieur (c)) c = supérieur (c); if ((c >= '\40') /* conversion en majuscules */
&& (c <= '\176')) { poscurs(row,col+index); /* caractère imprimable */

putchar(c);
suivant = en ligne[index];
en ligne[index++] = c;
cours = indice ;
while((next != 0) && (curr <=60)) { /* déplacer le reste */
temp = suivant; /* ligne à droite */
suivant = inline[curr];
inline[curr++] = temp;
putchar(temp);
}
}
autre {
si ((c == 8) && index){ /* retour arrière */

14­12 Tutoriel C Exemples de programmes


Machine Translated by Google indice­­;
poscurs(ligne,col+index); température /* sauvegarder le curseur */
= indice ;
while (inline[temp]) {
inline[temp] = inline[temp+1];
putchar(inline[temp++]);
}
putchar(' ');
}
}
poscurs(ligne,col+index);
}
} tandis que (c != 13); /* nouvelle ligne trouvée, la saisie de la ligne est terminée
*/
}

/* ************************************************* ************ analyser */


/* Cette fonction vérifie la ligne d'entrée pour les erreurs logiques dans */
/* construction, puis confie le contrôle à la fonction "calcdata" pour*/
/* les calculs réels. */
analyser()
{
int index,parcol;
double newval;
nom du personnage[8];

varinus = ­1 ;
code d'erreur = 0 ;
col = 0 ;
ignorer = 1 ; /* ignorer cette ligne */
if (inline[0] == '#') { getnames(); /* récupère la liste des noms de variables */

retour;
}
while (inline[col] == ' ') col++; if (inline[col] == '$') return; /* ignore les espaces de début */
if (inline[col] == 0) return; ignorer = 0 ; /* ignore une ligne de commentaire */
/* ignore une ligne vide */
/* n'ignore pas cette ligne */
nom[0] = inline[col++]; indice = 1 ; /* trouver le nom de la variable */

while ((((inline[col] >= 'A' ) && (inline[col] <= 'Z' )) ||


((inline[col] >= '0' ) && (inline[col] <= '9' ))) &&
(indice <= 5 )) { /* continue la variable ou le nom de la fonction */
nom[index++] = inline[col++];
}
nom[index] = 0;
pour (index = 0;index < 12;index++) {
if ((strcmp(name,allvars[index].varname)) == 0)
index; /* nom de variable trouvé varuse = */
}
si (varinuse < 0)
errchk(3); while /* nom de variable inconnu */
(inline[col] == ' ') col++; if (inline[col] == '=') col++; /* ignore les espaces de début */

sinon errchk(8); parc = /* manque le signe égal */


0; index = col; /* vérifie maintenant la correspondance correcte des parenthèses */

faire {
if (inline[col] == '(') parcol++;
if (inline[col++] == ')') parcol­­;
si (parcol < 0) errchk(1); /* le nombre de parents est devenu négatif */
}
while (inline[col]);
si (parcol)
errchk(2); col = /* reste une parenthèse */
indice ;

Exemples de programmes Tutoriel C 14­13


Machine Translated bycalcdata(&newval);
Google if (errcode /* Maintenant, va évaluer l'expression complète */
== 0) { allvars[varinuse].value /* ne met pas à jour la valeur si une erreur est trouvée */
= newval; disnew(varinuse);
/* affiche la valeur modifiée */
}

} /* ********************************************** **************** errout */ /* C'est la fonction qui affiche les messages d'erreur

clignotants sur le moniteur */ /*. Notez les erreurs supplémentaires pour l’expansion du tableau. */ erreur() {

switch (errcode) { cas 1 :


errdis("parenthèse droite supplémentaire "); casser; cas 2 : errdis("parenthèse
droite
manquante"); casser; cas 3 : errdis("nom de variable inconnu "); casser; cas
4:
errdis("opérateur mathématique invalide"); casser; cas 5 : errdis("valeur
négative
pour SQRT"); casser; cas 6 : errdis("Fonction introuvable"); casser;
cas 7 :
errdis("valeur négative pour LOG"); casser; cas 8 : errdis("signe égal

manquant"); casser; cas 9 : errdis("champ de données invalide");


casser;
cas 10 : errdis("division par zéro"); casser; cas 11 : errdis("Le fichier
n'existe
pas"); casser; cas 12 : pause ; cas 13 : errdis("Mémoire

insuffisante"); casser; cas 14 : errdis("Dash attendu"); casser;


cas 15 :
errdis("Code de format invalide"); casser; cas 16 : errdis("Valeur
négative
pour FACTORIAL"); casser; cas 17 : errdis("Err 17"); casser;

par défaut : errdis("erreur inconnue"); poscurs(21.70);


printf("%d",code d'erreur);

} poscurs(22,12+colerr);

} /* ********************************************** ******* ************** initfk() */

/* Cette fonction est utilisée par APPLIX 1616 pour initialiser les touches de fonction */ /* pour la Calculatrice Visuelle */

char fkey1[] = { 128, 59, 0 }; char fkey2[] =

{ 128, 60, 0 }; char fkey3[] = { 128, 61, 0 }; char


fkey4[] = { 128, 62, 0 }; char fkey5[] = { 128, 63, 0 };
char fkey6[] = { 128, 64, 0 };

14­14 Tutoriel C Exemples de programmes


char fkey7[]
Machine Translated by =Google
{ 128, 65, 0 }; char fkey8[] = { 128, 66,
0 }; char fkey9[] = { 128, 67, 0 }; char fkey10[] =
{ 128, 68, 0 };

initfk() {

DEF_FK(0, fkey1);
DEF_FK( 1, fkey2);
DEF_FK(2, fkey3);
DEF_FK(3, fkey4);
DEF_FK(4, fkey5);
DEF_FK(5, fkey6);
DEF_FK(6, fkey7);
DEF_FK(7, fkey8);
DEF_FK(8, fkey9);
DEF_FK(9, fkey10);
}

/* ************************************************* ****************/

Exemples de programmes Tutoriel C 14­15


Machine Translated by Google
15
La calculatrice visuelle ­ Version 1.00

La calculatrice visuelle a été écrite pour être utilisée pour des calculs rapides de la variété qui serait
se fait généralement avec une calculatrice portative. Il n'y a aucune allocation pour les boucles de programmation,
ou des variables indirectes, ou toute autre fonctionnalité d'un langage de programmation moderne. Là
Il n'y a pas non plus de complications, et ce programme ne devrait pas nécessiter plus de quelques minutes pour
l'utilisateur expérimenté d'un ordinateur pour apprendre à l'utiliser, et seulement un peu plus longtemps pour la personne
inexpérimentée en informatique.

Il est suggéré de commencer par parcourir lentement le didacticiel, en effectuant les opérations suggérées,
puis lisez les commentaires suivants pour une description de la calculatrice visuelle. Ce programme est
destiné à être beaucoup plus complet que les petites calculatrices à l'écran qui sont devenues
populaire, mais il n'est pas résident en mémoire. En raison de la popularité future attendue de ces programmes
Comme "Windows", ce programme peut être aussi pratique que les programmes résidents actuels en mémoire.

15.1 Le didacticiel de la calculatrice visuelle


1. Copiez tous les fichiers sur une autre disquette de travail avec votre système d'exploitation ou sur une seule
répertoire sur votre disque dur.
2. Tapez VC <return> Vous obtiendrez l'écran de démarrage contenant les cases de variables
et la boîte d'aide en haut. Le centre de l'écran contient la zone de transcription, et
en bas, vous trouverez la zone de saisie.
3. Tapez A = 123,45 <retour> Vous constaterez que la valeur est affichée dans la case supérieure
et la valeur sera également affichée à gauche de l'équation d'entrée dans la transcription
boîte.

4. Tapez B = SQRT(A) <retour> Vous trouverez la racine carrée de A affichée dans les deux
places à côté de la variable B. Vous avez peut­être remarqué que le système ne se soucie pas de savoir si
vous utilisez des majuscules ou des minuscules, cela le force à être en majuscules. Vous avez maintenant défini certains
valeurs pour les variables A et B.

5. Tapez D = 1,23*SIN(SQRT(1,2345 + B*B/A)) <retour> Espaces entre les variables


n'a pas d'importance et vous pouvez les placer là où vous désirez pour que ce soit joli. Si tu
obtenez un message d'erreur, utilisez simplement les touches curseur gauche et droite avec la suppression
touche pour corriger l’erreur et appuyez à nouveau sur retour. Tu n'as même pas besoin d'être à la fin
de la ligne pour frapper le retour.

6. Appuyez sur la touche F6 puis <return> Le F6 demande qu'un fichier soit lu et si vous ne le faites pas
spécifiez un nom de fichier, lit­il dans le fichier nommé "HELP". Ce serait un bon endroit
pour stocker une liste de vos autres fichiers de la même manière que ce fichier.
7. Appuyez sur la touche F6 puis tapez AMORT <return> Ceci lit dans le fichier nommé "AMORT"
et calcule chaque ligne au fur et à mesure de sa lecture. Notez qu'il a également modifié les noms des
variables qu'il utilise pour les rendre plus significatives pour vous.
8. Tapez PRINC = 30000 <retour> Cela modifie le montant du prêt. Nous voudrions
pour recalculer le paiement que nous ferons dans les prochaines étapes.
9. Déplacez la flèche vers le haut jusqu'à la ligne commençant par "PMNT=..." en utilisant les flèches haut et bas.
clés. Lorsque la flèche pointe vers la ligne en question,...
dix. Appuyez sur la touche F9. Cela déplace la ligne pointée, par la petite flèche, dans la zone de saisie
où il peut être modifié ou réutilisé tel quel.

15­1 Tutoriel C La calculatrice visuelle ­ Version


1h00
11.
Machine Translated by Google
Appuyez sur la touche <retour>. Cela recalculera le paiement en fonction du nouveau capital
et les anciens taux d’intérêt et délais de remboursement. Ceux­ci pourraient également être modifiés et
le paiement recalculé.
12. (Il s'agissait d'une fonction d'impression non utilisée par la version 1616).
13. Appuyez à nouveau sur la touche F6. Vous recevrez une autre invite pour un nom de fichier.

14. Tapez PAYMENT <return> Ce fichier sera lu et vous donnera les résultats de
votre prêt hypothécaire après le premier versement. Les résultats seront également imprimés.
15. Appuyez à nouveau sur la touche F6 et <retour> Le dernier fichier lu sera réutilisé à nouveau et le
le résultat du deuxième paiement sera affiché sur le moniteur et sur l’imprimante.
16. Répétez l'étape 15 trois ou quatre fois.
17. Appuyez sur la touche F1. Un écran d'aide apparaîtra décrivant les différentes fonctions mathématiques
disponible. Ils peuvent être imbriqués au niveau souhaité.
18. Appuyez sur la touche F2. Un écran d'aide apparaîtra avec une très brève description du système
fonctions disponibles.
19. Appuyez sur la touche "Accueil". Vous serez immédiatement transporté tout en haut du
transcription où le message de bienvenue a été initialement vu. Le Pgup, Pgdn, Accueil,
et Fin vous permettront de parcourir la fenêtre de transcription très rapidement.
20. Déplacez la petite flèche vers la ligne qui commence "# A­PRINC" et appuyez une fois sur la touche F4.
Vous verrez que l'astérisque apparaît devant la ligne. Cela « marquera » la ligne.
Continuer à appuyer sur la touche F4 activera et désactivera l'astérisque.
21. Déplacez la flèche vers la ligne qui commence "# E­EQUITY" et marquez également cette ligne.
22. Appuyez sur la touche F5. Le système vous demande maintenant un nom de fichier vers lequel sortir.
23. Tapez STUFF <return> C'est simplement un nom de fichier. N'importe quel nom de fichier valide peut être utilisé.
Toutes les lignes de la zone de transcription qui sont « marquées » seront sorties dans le fichier « STUFF ».
24. Appuyez sur la touche F6 et tapez STUFF <return> Toutes les lignes qui viennent d'être sorties seront
être lu et tous les calculs seront effectués.

25. (Désactivez l'impression ; non utilisé dans la version 1616).


26. Appuyez sur la touche F6 et <retour> Le fichier sera lu à nouveau sans impression.
27. Appuyez sur la touche F10 et répondez à l'invite avec Y pour mettre fin à la session.
28. Tapez à nouveau VC <return> pour redémarrer le programme.
29. Appuyez sur la touche F6, tapez TEST <return> Un fichier de 50 lignes sera lu et tout
calculs effectués à titre d’exemple des types d’équations qui peuvent être évaluées.
30. Tapez ce qui suit ; # ID JO KH LX <return> Ceci indique au système ce que nous voulons
la variable "I" à imprimer en notation décimale, la variable "J" à imprimer en notation octale
notation, et "K" et "L" pour imprimer en notation HeXadécimale. (Remarque : le # doit
être dans la première colonne.)
31. Type I = 12345 <return> La variable I sera affichée dans les trois notations dans le
case supérieure et en notation décimale dans la case de transcription.
32. Tapez J = 12345 <retour> La variable J sera affichée en notation octale dans le
boîte de transcription et sur l’imprimante si elle est allumée et prête.
33. Tapez K = 12345 <retour> La variable K sera affichée en notation Hex dans le
boîte de transcription.

La calculatrice visuelle ­ Version 1.00 Tutoriel C 15­2


34.
Machine Translated by Google
Tapez I = 012345 <retour> La valeur de I est lue sous forme de valeur octale en raison du zéro non significatif,
mais est toujours affichée sous forme de valeur décimale.
35. Tapez J = 0X12345 <retour> La valeur de J est lue sous forme de valeur hexadécimale en raison du 0X initial.

36. Tapez M = 0XFFFF <retour> La variable M est lue au format hexadécimal et affichée dans les trois formats dans
la zone supérieure, mais sous forme décimale dans la zone de transcription. L'affichage par défaut des entiers est
décimal.
37. Type I = SQRT(48) <retour> La racine carrée est calculée à l'aide de 15 chiffres significatifs et le résultat est
tronqué à la valeur immédiatement inférieure. Tous les calculs sont effectués de cette façon et le résultat est
tronqué à la valeur entière avant affichage.
38. Type A = FACT(170)/FACT(169) ­ 170 <retour> Le très petit résultat vous indiquera une mesure de l'exactitude
des calculs. Il ne vous semble peut­être pas évident que nous utilisons une fonction factorielle. Calculez la valeur
de FACT(170) pour avoir une idée de la plage dynamique disponible avec ce système.

39. Appuyez sur la touche F10 et répondez à l'invite avec Y.


40. Redémarrez le programme et essayez certains de vos exercices mathématiques préférés.

15.2 Commentaires supplémentaires

1. Fichiers sur le disque de distribution.

VC.DOC ­ Le fichier que vous lisez.

VC.XREL ­ Le fichier exécutable de la calculatrice visuelle (la version IBM est .EXE).
AIDE ­ L'index des fichiers des utilisateurs.

AMORT ­ Les équations d'amortissement des prêts.

PAIEMENT ­ Les calculs de paiement mensuels.

TEST ­ Un groupe de 50 équations "non­sens".

2. Saisir des équations.

Toutes les équations sont saisies dans la zone de saisie dans une expression mathématique normale. Seules les expressions à
valeur unique peuvent être évaluées, aucune équation simultanée ne peut être résolue avec ce système.

Pour élever « A » à la puissance « B », utilisez ; C = EXP(B*LOG(A)) $ toutes les variables peuvent être utilisées. Un

signe dollar n'importe où sur une ligne affiche le reste de cette ligne sous forme de commentaire uniquement.

L'imbrication est autorisée à n'importe quelle profondeur, mais l'expression entière doit tenir dans la fenêtre de saisie. Les
expressions plus longues doivent être décomposées en instructions plus petites.

Les variables « I » à « J » peuvent être mélangées avec les variables « A » à « F » de n'importe quelle manière.
Les variables « I » sont tronquées après évaluation et ne peuvent donc être utilisées que pour stocker des valeurs entières, mais
cela serait acceptable dans de nombreux cas, comme la valeur initiale du prêt dans l'exemple ci­dessus.

3. Nommer les variables

Afin de faciliter la lecture des équations, les noms des variables "A" à "F" peuvent être modifiés par n'importe quel nom de votre
choix comportant jusqu'à 6 caractères. Le premier doit être alphabétique et le reste peut être alphabétique ou numérique. Pour
modifier les noms, utilisez le signe # dans la première colonne de l'instruction et n'importe quel ordre de groupes de noms de
variables. Un groupe de variables est composé d'une variable

15­3 Tutoriel C La calculatrice visuelle ­ Version 1.00


Machine Translated
nommez by
« AGoogle
» à « F », puis un signe moins et enfin le nouveau nom sans espaces nulle part dans le groupe. N'importe
quel nombre de blancs peut être utilisé entre les groupes, et vous pouvez en mettre autant que vous le souhaitez sur une
ligne d'entrée et des groupes supplémentaires sur d'autres lignes.

En mélange avec ce qui précède, ou placé sur leur propre ligne d'entrée, vous pouvez mettre autant de groupes "de base"
que vous le souhaitez pour les variables "I" à "N". Un groupe de base se compose du nom de la variable, d'un signe moins
et de l'une des lettres "D", "O", "H" ou "X".

Si, après avoir nommé les variables, vous souhaitez les renommer autrement, les noms d'origine sont utilisés pour les
nouveaux changements de nom. Ainsi, si "A" était nommé "PLACE" et que vous souhaitiez le renommer "WHERE", la
méthode appropriée serait d'utiliser "# A­WHERE".
4. Limites

Cette version de la calculatrice visuelle a une limite quant au nombre de lignes dans la zone de transcription.
Il devrait y en avoir suffisamment pour la plupart des applications. Si vous avez besoin de plus, je vous suggère de changer
de programme.

La limite des nombres est d’environ dix puissances plus ou moins 308. Bien entendu, les nombres positifs et négatifs
peuvent être utilisés partout. La limite pour les variables « I » est d'environ 16 millions et ne peut être que nulle ou positive.
Le nombre exact en 2 à la puissance 24 moins 1. C'est le nombre affiché dans la variable "N" lorsque vous chargez le
système.

La plus grande limitation du système est la limite de votre propre créativité. C'est à vous de l'utiliser de manière productive
ou simplement de lui permettre de prendre la poussière comme tant de vos autres programmes.
Je pourrais ajouter que je possède également de nombreux dépoussiéreurs que je n’ai pas encore appris à utiliser.

La calculatrice visuelle ­ Version 1.00 Tutoriel C 15­4


Machine Translated by Google
16
Messages d'erreur

16­1 Tutoriel C Messages d'erreur


Machine Translated by Google

17 Tuteur Coronado Enterprises C ­ Ver 1.00


Cette documentation et le logiciel qui l'accompagne, y compris tous les exemples de programmes C et de fichiers
texte, sont protégés par la loi américaine sur les droits d'auteur afin de les protéger contre toute commercialisation
non autorisée. L'intégralité de ce tutoriel est distribué sous le concept "Freeware", ce qui signifie que vous n'êtes
pas obligé de payer pour cela. Vous êtes autorisé à copier les disques dans leur intégralité et à les transmettre à
un ami ou une connaissance. En fait, vous êtes encouragé à le faire. Vous êtes autorisé à facturer une somme
modique pour couvrir les coûts mécaniques de duplication, mais le logiciel lui­même doit être distribué gratuitement
et dans son intégralité.
Si vous trouvez le didacticiel et les exemples de programmes qui l'accompagnent utiles, vous pouvez, si vous le
désirez, payer une somme modique à l'auteur pour l'aider à compenser le temps et les dépenses consacrés à sa
rédaction. Un paiement de 10,00 $ est suggéré comme étant raisonnable et suffisant. Si vous estimez que le
tutoriel ne valait pas ce montant, n'effectuez aucun paiement, mais n'hésitez pas à envoyer quand même le
questionnaire.
Que vous envoyiez ou non un paiement, n'hésitez pas à écrire à Coronado Enterprises et à demander la dernière
liste des didacticiels disponibles ainsi qu'une liste des bibliothèques connues du domaine public qui peuvent vous
fournir ce logiciel pour le prix de la copie. Veuillez joindre une enveloppe timbrée à votre adresse, de préférence
de taille commerciale, pour une copie des dernières informations. Consultez le fichier « READ.ME » qui
l'accompagne sur le disque pour plus d'informations.

Je n'ai aucune possibilité d'assistance téléphonique pour ce tutoriel et je n'ai pas l'intention d'en mettre en place.
Si vous rencontrez des problèmes ou si vous avez des suggestions, écrivez­moi à l'adresse ci­dessous.
Gordon Dodrill ­ 30 juin 1986 Copyright

(c) 1986, Coronado Enterprises Coronado


Enterprises, 12501 Coronado Ave NE, Albuquerque, Nouveau­Mexique 87122
Introduction

Chapitre 1 ­ Démarrer firstex.c


Le premier exemple de programme Chapitre 2 ­
Structure du programme trivial.c Le
programme minimum (pas de sortie) wrtsome.c Écrire une
sortie wrtmore.c Écrire plus de sortie
oneint.c Une variable entière
comments.c Commentaires dans C
goodform.c Bon style de programme
laidform.c Mauvais style de programme
Chapitre 3 ­ Contrôle du programme
while.c La boucle While dowhile.c
La boucle Do­While forloop.c La
boucle For ifelse.c La construction If &
If­Else breakcon. c Le
commutateur Break & Continue.c La
construction Switch gotoex.c L'instruction
Goto tempconv.c La conversion de
température dumbconv.c Mauvais style
de programme

Coronado Enterprises C Tuteur ­ Ver Tutoriel C 17­1


1.00
Chapitreby
Machine Translated 4 ­Google
Assignation et comparaison logique
intasign.c Affectations d'entiers (pas de sortie)
morttypes.c Plus de types de données (pas de
sortie) lottypes.c Beaucoup de types
de données compares.c Comparaisons logiques
(pas de sortie) cryptic.c Les constructions cryptiques (pas de sortie) sortir)
Chapitre 5 ­ Fonctions et portée des variables
sumsqres.c Premières fonctions
squares.c Renvoie une valeur
floatsq.c Renvoie flottant scope.c
Portée des variables recurson.c
Programme de récursion simple en arrière.c Un
autre programme de récursion Chapitre 6 ­
Définitions et définition des macros.
c Définit la macro.c
Macros

Chapitre 7 ­ Chaînes et tableaux


chrstrg.c Chaînes de caractères
strings.c Plus de chaînes de caractères
intarray.c Tableau d'entiers
bigarray.c De nombreux tableaux (erreur d'adresse)
passback.c Obtention de données à partir de
fonctions multiary.c Tableaux multidimensionnels
Chapitre 8 ­ Pointeurs
pointer.c Pointeurs simples
pointer2.c Plus de pointeurs
twoway.c Données de fonction
bidirectionnelle Chapitre 9 ­ Entrée/
sortie standard simpleio.c E/S standard la
plus simple singleio.c E/S à caractère
unique betterin.c Meilleure forme d'E/S unique
intin.c Entier input stringin.c
Entrée de chaîne inmem.c
Conversion d'E/S en mémoire spéciale.c
Sortie d'erreur standard Chapitre 10 ­
Entrée/sortie de fichier formout.c
Sortie formatée charout.c Sortie à
caractère unique readchar.c Lire des
caractères uniques readtext.c Lire un seul
caractère mots readgood.c Mieux lire
et afficher readline.c Lire une ligne complète
anyfile.c Lire dans n'importe quel
fichier printdat.c Sortie sur
l'imprimante Chapitre 11 ­ Structures
struct1.c Exemple de
structure minimale struct2.c Tableau de structures
struct3.c Structures avec pointeurs
nested.c Structure imbriquée (pas de sortie)
union1.c Un exemple d'union union2.c Un autre
exemple d'union

17­2 Tutoriel C Coronado Enterprises C Tuteur ­


Ver 1.00
Chapitreby12Google
Machine Translated ­ Allocation dynamique
dynlist.c Allocation dynamique simple bigdynl.c
Allocation dynamique étendue dynlink.c
Programme de liste chaînée dynamique (problèmes)
Chapitre 13 ­ Manipulation de caractères et de
bits uplow.c Texte majuscules/
minuscules charclas.c Classification des
caractères bitops.c Opérations sur les
bits logiques shifter.c Opérations de
décalage de bits Chapitre 14 ­
Exemples de programmes dosex.c Exemples d'appels DOS
(utilisez dosex1616.c à la place) whatnext.c Poser une question
dans un fichier batch (inutile en
1616) list.c Code source Lister vc.c Calculatrice visuelle

Coronado Enterprises C Tuteur ­ Tutoriel C 17­3


Ver 1.00
Machine Translated by Google
18
Mises à jour HiTech C

Ceci est un résumé des notes fournies par Andrew Morton d'Applix Pty Ltd, décrivant les modifications apportées au compilateur
HiTech C. La plupart des modifications apportées à la bibliothèque visent à garantir que le code de sortie coopère avec le
gestionnaire de mémoire.

18.1 Relcc.c
Il s'agit du cc HiTech original modifié par Colin McCormack et Andrew Morton afin qu'il produise directement des fichiers .xrel
relocalisables, au lieu de fichiers .exec à position fixe. L'indicateur ­r produira un fichier .exec. Cet indicateur doit être placé au
début de la ligne de commande relcc, car il y a une petite erreur dans le codage de l'indicateur.

Les fichiers temporaires du compilateur sont placés dans le répertoire /temp. Vous devez attribuer /temp ou un autre endroit sûr
chemins d'inclusion /hitech et /hitech/ avant d'utiliser relcc. Le compilateur a /rd ou assign /temp . a été modifié pour définir les
include vers le préprocesseur. L'identifiant applix1616 est défini pour le préprocesseur, plutôt que pour applix, ce qui a posé des
problèmes lors du remplacement de #include <applix>.

Relcc déclenche les passes du compilateur à l'aide de l' appel système exec , plutôt que de les rechercher.
Les passes du compilateur doivent résider quelque part dans votre chemin de recherche normal (voir la commande xpath dans
votre manuel d'utilisation.)

Relcc a un aperçu de la situation. Tout C indicateur et se termine par un code de sortie de ­1 si un est détecté.
Tout Cpour l'attraper; l'
Vous devrez peut­être vous appuyer Tout C appel système exec efface le drapeau au début
sur chaque passe.

Chaque passe du compilateur ferme les descripteurs de fichiers de sortie, d'entrée et d'erreur standard à la sortie, de sorte qu'ils
ne sont pas disponibles lorsque la passe suivante est invoquée. Relcc modifie l' appel système close pour garder ces fichiers
ouverts.

Le répertoire standard pour les fichiers d'inclusion est /hitech/include. Attribuez­le à l'endroit où vous conservez réellement les
fichiers d'inclusion avant d'utiliser le compilateur. Spécifiez le drapeau ­I/hitech/in­clude pour relcc (en fait le préprocesseur)
pour tout trouver.

Le répertoire standard pour les bibliothèques et le code de démarrage du runtime (crtapp, etc.) est /hitech.
Attribuez­le comme assign /hitech /f0/hitech ou là où se trouvent réellement les bibliothèques.

Relcc.xrel est un code déplaçable, il reste donc en haut de la mémoire lorsque les passes du compilateur sont exécutées. Il est
possible que vous ayez également make.xrel quelque part au­dessus. Si le compilateur plante (probablement pendant la passe
d'assemblage), vous devrez réduire le disque RAM et l'espace de pile à environ 100 000­150 000 au total. Désolé pour ça. Les
détails sur la façon d'utiliser buildmrd pour modifier le fichier mrdrivers sur votre disque de démarrage sont donnés dans le
manuel de référence technique et dans le nouveau manuel des programmes utilisateur.

18.2 Fichiers modifiés


BUF.C
Modifié pour qu'il utilise malloc() au lieu de sbrk().

NETTOYAGE.C
Modifié pour que le code compilé prenne en charge la redirection d'E/S OK.

18­1 Tutoriel C Mises à jour HiTech C


CLOSE.C
Machine Translated by Google
empêche désormais la fermeture des descripteurs hérités pour l'entrée standard, la sortie standard et l'erreur
standard. Ceux­ci sont fermés par 1616/OS.
GETARGS.C
Modifié pour qu'il utilise malloc() au lieu de sbrk().
FAIRE
Un excellent programme de création du domaine public, qui se porte très facilement. Le code source et la
documentation (microscopique) se trouvent sur le disque utilitaire Applix #2.
MALLOC.C
Modifié pour utiliser l' appel getmemsystem, plutôt que sbrk(), et tous ses propres éléments de gestion de la
mémoire.

MRD_CRTAPP.AS Il
s'agit du code de démarrage d'exécution normal piraté afin qu'il n'efface pas le BBS lors de l'entrée dans le code.
Utilisez­le uniquement pour les pilotes résidents en mémoire (MRD) écrits en C. Si le code de démarrage normal
est utilisé, le stockage global du MRD sera supprimé à chaque fois que le MRD est appelé par l' appel système
callmrd . Spécifiez ­jmrd_crtapp.obj sur la ligne de commande pour résoudre ce problème. Ne l'utilisez jamais, sauf
lorsque vous effectuez un MRD.

NEW_CRTAPP.AS Le
code d'exécution modifié pour les programmes C normaux. Il laissait le pointeur d'environnement comme un
pointeur nul. Mais getenv() s'attend à ce qu'il pointe vers un pointeur nul s'il n'y a pas de table d'environnement.
SBRK.AS
La fonction sbrk() tente d'allouer plus de stockage au­delà de la fin du segment BBS du programme. Sous le
système de mémoire du 1616, cela empiètera sur la mémoire réservée, provoquant des crashs époustouflants. La
version modifiée demande ici la mémoire au système avant de l'utiliser. Si le code est un fichier .xrel, alors la
mémoire sera forcément indisponible. Si vous ne pouvez pas retravailler un programme pour utiliser malloc() à la
place de sbrk(), le code ne s'exécutera que sous forme de fichier .exec à 4 000 $, à partir duquel il pourra augmenter
sa mémoire.
SYSCALLS.H Il
s'agit d'un fichier d'en­tête qui $définit chaque appel système 1616/OS en majuscules, avec le même ordre
d'utilisation et d'argument que dans le manuel du programmeur qu'Andrew a également écrit. Notez que les appels
printf(), sprintf() et fprintf() utilisent une astuce qui leur permet de contourner le mécanisme normal des appels
système, afin de pouvoir être utilisés avec n'importe quel nombre d'arguments. Ils fonctionnent également avec la
redirection d'E/S. Vous devez utiliser STDERR et STDOUT avec fprintf(), pas stderr et stdout.
De plus, toute E/S de fichier est un peu compliquée ; ne mélangez pas les descripteurs de fichiers, les lectures, les écritures, etc. du
C avec ceux natifs du système.

TOUPPER.AS
TOLOWER.AS
Évidemment, c'était une mauvaise journée lorsque ceux­ci ont été écrits. Les comparaisons étaient terriblement
fausses. Je les ai réparés. Méfiez­vous des #define'd toupper() et tolower() dans ctype.h. Ils ne vérifient pas que le
caractère est à portée avant d'effectuer l'addition ou la soustraction. Ils sont une nuisance.

Mises à jour HiTech C Tutoriel C 18­2


Machine Translated by Google
19
Lectures complémentaires

19.1 Passer du BASIC au C


Robert J Traister
Publié par Prentice­Hall Inc, Englewood Cliffs, NJ 07632.
ISBN0­13­357799­6

19.2 Programmation en C, édition révisée


Stephen G Kochan
Hayden Books division de Howard W Sams & Co., 4300 West 62nd St, Indianapolis, Indiana 46268 États­
Unis.
ISBN0­672­48420­X

19.3 C avancé
Techniques et applications
Gerald E. Sobelman et
David E Krekkelberg
Que Corp, Indianapolis, Indiana
ISBN0­88022­162­3

19.4

19­1 Tutoriel C Lectures complémentaires


Indiceby Google
Machine Translated

" guillemets doubles, 9­1 break, 3­3


breakcon.c, ordre de
% de sortie variable, 2­3 3­3 octets, sexe de
4­3 octets, 4­3
& adresse, 8­1 &
ET logique, 13­3 Disque de démarrage
C, 1­1 calloc(),
*
magasin, 8­1 12­8 retour chariot, 9­4
casse, 3­4
/* commentaires, 2­4 casse est significatif, 1­2 cast,
12­3 char,
; point­virgule, 2­1 problème
4­2 char, 10­4 manipulation
[ ] tableau de crochets, 7­1 de caractères , 13­1 saisie de chaîne
de caractères, 9­6 caractéristiques
\ barre oblique inverse, des variables, 4­3 charclas.c, 13­2
2­2 \n nouvelle ligne, 2­2 charout.c, 10­2
chmem, 11­6
^ LIBERTÉ, 13­3 chrstrg.c, 7­1
classification des
{} accolades, accolades, 2­1 caractères, 13­ 2 fermer un fichier, 10­2
combiner des chaînes,
| OU, 13­3 7­3 virgule dans printf(), 2­3
comments.c, 2­3 commentaires /
~ inverser, 13­3 *, 2­4 compares.c, 4­5
instructions composées,
adresse &, pointeur 3­2 variable
d'adresse 8­1, 8­1 et, 4­7 composée, 11­1 branchement
AND & conditionnel, 3­1 expression
logique, 13­3 anyfile.c, 10­5 conditionnelle, 4­9 suite, 3­3
Disque utilisateur caractères de conversion, 4­5
Applix, opérateurs cryptic.c, 4­8
arithmétiques 1­1, tableau 4­9, accolades, accolades {}, 2­1
tableau 7­1
de pointeurs, 12­4 tableau de
structures, 11­2 tableau crochets
[ ], 7­1 assign MRD, 1­1 affectation, définitions de données, 4­2
entier, 4­1 Assignment mélange de types de
& Logical Compares, 4­1 données, 4­2 types
autoexec.shell, 1­1 variables automatiques, 5­6 de données, 4­2 types de données,
exemples, 4­4 désallocation de
mémoire, 12­4
décrémentation,
barre oblique inverse 4­8 definition.c, 6­1 définitions et
\, 2­2 reverse.c, 5­8 macros, 6 ­1 fonctions de
betterin.c, 9­4 définition, 5­2 variables de
bigarray.c, 7­4 définition, 5­7 do
bigdyn1.c, 12­4 while, 3­1 dosex.c,
manipulation de bits, 13­1 14­1 dosex_1616.c, 14­2
bitops.c, 13­3 dosexibm.c, 14­1
disque de guillemets doubles ", 9­1
démarrage, 1­1 accolades, accolades dowhile. c, 3­1 Dr
{}, 2­1 crochets [ ] tableau, 7­1 Doc, 1­1

Indice Tutoriel C je
dumbconv.c,
Machine Translated 3­6
by Google K&R, 9­1
allocation dynamique, 12­1
variables dynamiques, 12­2 fonctions de bibliothèque,
dynlink.c, 12­5 5­7 saut de
dynlist.c, 12­1 ligne, 9­4 liste
chaînée, 12­5 list.c,
modifier, 14­1, 14­6 variables
1­1 sinon, locales, 5­6 comparaisons
3­3 fin du marqueur, 7­5 logiques, 4­5 évaluation
Problème EOF, 10­4 logique, 4­7 fonctions
logiques, 13 ­3
false, 4­6 long int, 4­1 boucle utilisant
fgets(), 10­5 while, 3­1 boucles, limites
entrées­sorties de fichiers, d'imbrication, 3­2
10­1 float, lottypes.c, 4­3 minuscules, 13­1
4­2 tableaux à virgule flottante,
7­4 fonctions à virgule flottante, macro, 6­2
5­4 floatsq.c, macro.c, 6­2
5­4 touches de main, 2­1
fonction, 9­ 9 malloc(), 12­2, 12­3
fopen(), 10­3 allocation de mémoire, 12­2
for loop, 3­2 types de données de
forloop.c, 3­2 style de mélange, 4­2
formatage, 2­4, 3­6 modulo, 4­1
formout.c, 10­1 mortotypes.c, 4­2 tableaux
fprintf(), 9­8 multidimensionnels, 7­6 multiary.c, 7­6
free(), 12 ­4
fscanf(), 10­4 structures nommées, 11­4
fonction, 2­1 Fonctions et variables, 5­1 nested.c, 11­4
boucles imbriquées,
variables globales, 5­5 3­2 structures imbriquées,
goodform.c, 2­4 11­4 nouvelle ligne
goto, 3­4 \n, 2­2
gotoex.c, 3­4 non, 4­6 caractère NULL, 7­1

fichiers d'en­tête, oneint.c, 2­2


tas 9­1, 12­2 ouverture d'un fichier,
HiTech C, 1­1, 2­3 10­1 priorité des opérateurs,
4­7 ou,
identifiant, 1­2 4­7 OR |,
instruction if, 3­2 13­3 sortie d'un seul caractère, 10­2
ifelse.c, 3­2 sortie vers un fichier, 10­1
dans les E/S mémoire,
9­7 inclure les fichiers, autre, parenthèses, 2­1
9­2 inclure stdio.h, 9­1 passback.c, 7­4
incrément, 4­8 passage d'une valeur,
initialisation pour boucles, 3­2 5­2 pointeur.c,
inmem.c, 9­7 8­1 adresse du pointeur,
entrée sortie, 9­1 int 8­1 arithmétique du pointeur, 8­4,
entier, 2­2 intarray.c, 11­4 pointeur2.c,
7­3 intasign.c, 8­3 pointeurs ,
4­1 affectation 8­1 pointeurs et structures, 11­3
entière, 4­1 entier int, 2­2 priorité des opérateurs, 4­7 numéros
intin.c, 9­5 inverser d'impression, 2­2, 2­3
13­3 ~, printdat.c, 10­6
printf(), 2­2

Indice Tutoriel C ii
impression
Machine Translated byd'un fichier,
Google struct, 11­1
10­6 comparaisons de struct1.c, 11­1
problèmes, 4­8 contrôle de struct2.c, 11­2
programme, 3­1 promotion de struct3.c, 11­3
char en int, 4­2 putc(), 10­3 programmation structurée, 3­5
structures, 11­1
lire un fichier, 10­3 structures et unions, 11­1 style
lire une ligne, 10­5 de formatage, 2­ 4 tableaux
lire un mot, 10­4 indicés, 7­6 sumsqres.c,
readchar.c, 10­3 5­1 switch, 3­4
readline.c, 10­5 switch.c, 3­4
readtext.c, 10­4 variable de
récursion, 5­7 commutation, 3­4 constante
recurson.c , 5­7 symbolique, 6­1
enregistrer des variables,
5­6 relcc.xrel, tempconv.c, 3­5
1­1 renvoyer, fichiers temporaires,
5­3 renvoyer une 1­1 tenlines.txt, 10­2
valeur, 5­3 renvoyer des données dans des tableaux, 7­4 trivial.c, 2­1
true, 4­6
scanf(), 9­5 twoway.c, 8­4
scope.c, 5­5 typedef, 11­8
portée des variables, 5­5
segments, 12­2 laidform.c, 2­4
point­virgule ;, 2­1 souligné, 1­2
instruction shift, 13­4 union1.c, 11­6
shifter.c, 13­4 union2.c, 11­7
short int, 4­1 unions, 11­6
simpleio.c, 9­1 uplow.c, 13­1
sortie de caractère unique, 10­2 majuscules et minuscules, 13­1
singleio.c, 9­3 fonctions définies par l'utilisateur,
chaînes de tri, 7­3 5­1 type défini par l'utilisateur, 11­1
special.c, 9­8
sprintf(), 9­7 transmission de
crochets [ ] tableau, 7­1 squares.c, valeurs, 5­2 caractéristiques des
5­3 pile, 5­8 variables, 4­3 nom de fichier
débordement variable, 10­5 sortie
de pile, 11­6 bibliothèques variable %, portée de
de fonctions standard, 5­7 entrée­ 2­3
sortie standard, 9­1 étoile * variables, 5­5 vc.c, 14­9
pointeur, 8­1 étoile calculatrice visuelle, 14­9, 15­1 calculatrice visuelle tutoriel, 15­1
barre oblique /* commentaires, 2­
4 terminateur d'instruction ;, 2­1 whatnext.c, 14­4
variables statiques, 5­6 while.c, 3­1
fichier d'en­tête stdio.h, 9­1 while boucle, 3­1
store *, 8­1 wrtmore.c, 2­2
fonction strcat, 7­3 wrtsome.c, 2­1
fonction strcmp, 7­3
strcpy(), 10­3 XOR ^, 13­3
fonction strcpy , 7­2 xpath, 1­1
chaîne se termine par null,
7­1 chaîne variable comme pointeur, zéro, caractère nul, 7­1
8­3 stringin.c,
9­6 chaînes,
7­1 chaînes.c,
7­2 Chaînes et tableaux, 7­1

Indice Tutoriel C iii


Machine Translated by Google Table des matières

1 Mise en route ............................................................ ....................................... 1­1


1.1 Disque de démarrage C .................................................. .................................................................. ...... 1­1
1.2 Qu'est­ce qu'un identifiant ? .................................................................. ...................................... 1­2
1.3 Qu'en est­il du soulignement ? .................................................................. ...................... 1­2
1.4 Comment ce didacticiel est rédigé ............................................ ............................ 1­2
1.5 Une discussion de certains fichiers ............................................ ...................... 1­3
1.6 List.xrel .................................................. .................................................................. ............ 1­3

2 Débuter en C .............................................................. ................................ 2­1


2.1 Votre premier programme C .................................................. ...................................... 2­1
2.2 Un programme qui fait quelque chose ............................................ ...................... 2­1
2.3 Un autre programme avec plus de résultats ............................................ .............. 2­2
2.4 Pour imprimer certains numéros .................................................. ...................................... 2­2
2.5 Comment imprimer les nombres ............................................ ............................... 2­3
2.6 Comment ajouter des commentaires en C .......................................... ...................... 2­3
2.7 Bon style de formatage .................................................. ...................................... 2­4
2.8 Exercices de programmation .................................................. .................................. 2­5

3 Contrôle du programme ............................................... ...................................... 3­1


3.1 La boucle While .................................................. .................................................. 3­ 1
3.2 La boucle Do­While .................................................. ............................................ 3­1
3.3 La boucle For .................................................. .................................................................. .. 3­2
3.4 L'instruction If .................................................. .................................................. 3­2
3.5 Passons maintenant au « if­else » ............................................ ............................................ 3­3
3.6 La pause et la continuation ............................................ .................................. 3­3
3.7 La déclaration Switch .................................................. ...................................... 3­4
3.8 L'instruction Goto .................................................. ........................................ 3­4
3.9 Enfin, un programme significatif ............................................ ...................... 3­5
3.10 Un autre mauvais exemple de programmation .............................................. ........... 3­6
3.11 Exercices de programmation .................................................. ................................ 3­7

4 Affectation et comparaisons logiques .............................................. ........... 4­1


4.1 Déclarations d'affectation d'entiers .............................................. ...................... 4­1
4.2 Types de données supplémentaires .................................................. ...................................... 4­2
4.3 Mélange de types de données .................................................. ...................................................... 4­2
4.4 Comment utiliser les nouveaux types de données .......................................... ...................... 4­3
4.5 Caractéristiques des types de variables ............................................ ...................... 4­3
4.6 De nombreux types de variables ............................................ ...................................... 4­3
4.7 Les caractères de conversion .................................................. ...................... 4­5
4.8 Comparaisons logiques .................................................. ............................................ 4­5
4.9 Plus de comparaisons .................................................. .................................................. 4­6
4.10 Concepts de comparaison supplémentaires .............................................. ...................... 4­7
4.11 Évaluation logique .................................................. ...................................... 4­7
4.12 Préséance des opérateurs .................................................. .................................. 4­7
4.13 Ceci est une astuce, soyez prudent ............................................ ................................ 4­8
4.14 Domaines problématiques potentiels ............................................ ................................ 4­8
4.15 La partie cryptique de C ............................................ ...................................... 4­8
4.16 L'opérateur arithmétique cryptique ............................................ .................. 4­9
4.17 L'expression conditionnelle .................................................. ...................... 4­9
4.18 Être énigmatique ou ne pas être énigmatique ............................................ ............... 4­10
4.19 Exercices de programmation .................................................. ................................ 4­10

Tutoriel C je
5 Fonctions
Machine Translated et variables ....................................................... ........................ 5­1 5.1 Notre première
by Google
fonction définie par l'utilisateur .............. .................................................................. 5­1 5.2 Définir les
fonctions .................................................. ...................................... 5­2 5.3 Passer une valeur à une
fonction . .................................................................. .................. 5­2 5.4 En savoir plus sur la
transmission d'une valeur à une fonction ............... ...................... 5­2 5.5 Maintenant, confessons un
petit mensonge .............. .................................................................. ........ 5­3 5.6 Fonctions à virgule
flottante .............................. .................................................. 5­ 4 5.7 Portée des
variables ............................................ ...................................... 5­5 5.8 En savoir plus Variables
"automatiques" ..................................................... .................... 5­6 5.9 Que sont les variables
statiques ? .................................................................. ...................... 5­6 5.10 Utiliser à nouveau le
même nom .............. .................................................................. .... 5­6 5.11 Qu'est­ce qu'une variable
de registre ? .................................................................. ...................... 5­6 5.12 Où définir les
variables ? .................................................................. .................... 5­7 5.13 Bibliothèques de
fonctions standard ............................ .................................................. 5­7 5.14 Qu'est­ce que la
récursivité ? .................................................................. ................................... 5­7 5.15 Qu'a­t­il
fait ? .................................................................. ........................................ 5­8 5.16 Un autre exemple
de récursion .................................................................. ............ 5­8 5.17 Exercices de
programmation ............................ .................................................................. .5­9

6 Définitions et macros .................................................. ................................ 6­1 6.1 Les définitions et les


macros sont des aides pour effacer la programmation ....... ...................... 6­1 6.2 Est­ce vraiment
utile ? .................................................................. ................................... 6­1 6.3 Qu'est­ce qu'une
macro ? .................................................................. ........................................ 6­2 6.4 Regardons une
mauvaise macro .................................................................. ..................... 6­2 6.5 Exercice de
programmation ....................... .................................................................. .......... 6­3

7 Chaînes et tableaux .................................................. ........................ 7­1 7.1 Qu'est­ce qu'une


chaîne ? .................................................................. ...................................... 7­1 7.2 Qu'est­ce qu'un
tableau ? .................................................................. ...................................... 7­1 7.3 Comment
utilisons­nous la chaîne ? .................................................................. ....................... 7­1 7.4 Sortie
d'une partie d'une chaîne .................. .................................................................. ...... 7­2 7.5 Quelques
sous­programmes de chaîne .................................. ...................................... 7­2 7.6 Tri alphabétique
des Cordes .................................................. ................... 7­3 7.7 Combinaison de
chaînes ............................ .................................................................. ............... 7­3 7.8 Un tableau
d'entiers ............................... .................................................................. ........ 7­3 7.9 Un tableau de
données à virgule flottante ............................... .................................. 7­4 7.10 Récupération de
données à partir d'une fonction ........ 7­4 7.10 Récupération de données à partir d'une
fonction ...... .................................................................. .. 7­4 7.11 Les tableaux transmettent les
données dans les deux sens ....................................... ................................ 7­5 7.12 Un indice pour
une leçon future ........ .................................................................. ............ 7­5 7.13 Matrices à
dimensions multiples ............................... ........................................ 7­6 7.14 Exercices de programmation .. .................................

8 Pointeurs ............................................................ ...................................................... 8 ­1 8.1 Qu'est­ce


qu'un pointeur ? .................................................................. ...................................... 8­1 8.2 Deux
règles très importantes ..... .................................................................. ....................... 8­1 8.3 Aide­
mémoire ....................... .................................................................. ........................ 8­1 8.4 Un autre
pointeur ................ .................................................................. ............................ 8­2 8.5 Il n'y a
qu'une seule variable .............. .................................................................. ........... 8­2 8.6 Comment
déclarer un pointeur ? .................................................................. .................. 8­2 8.7 Le deuxième
programme avec pointeurs ............................ ..................................... 8­3 8.8 Une variable chaîne
est en fait un pointeur .. .................................................................. ... 8­3 8.9 Arithmétique du
pointeur ...................................... ...................................................... 8 ­4 8.10 Maintenant pour un
pointeur entier ............................................ ................................ 8­4 8.11 Retour de données de
fonction avec un pointeur ........ ................................................ 8­4 8.12 Pointeurs Sont
précieux ............................................................ .................................. 8­5

Tutoriel C ii
8.13by
Machine Translated Exercices
Google de programmation .................................................. ................................ 8­5

9 Entrée/Sortie standard .................................................. ...................... 9­1


9.1 Le fichier d'en­tête Stdio.H .............................................. ..................................... 9­1 9.2
Opérations d'entrée/sortie en C ... .................................................................. ............ 9­1 9.3 Autres
fichiers d'inclusion .............................. .................................................................. ............ 9­2 9.4
Retour au fichier nommé Simpleio.c .......................... ................................... 9­2 9.5 Dos nous aide
(ou nous gêne) ) ............................................ 9­2 9.6 Une autre E/S étrange
Méthode ................................................. ........................ 9­3 9.7 Nous avons maintenant besoin
d'un saut de ligne .............. .................................................................. .......... 9­4 9.8 Quelle
méthode est la meilleure ? .................................................................. ................................ 9­4 9.9
Maintenant, pour lire certains nombres entiers ........ .................................................................. ........
9­5 9.10 Saisie d'une chaîne de caractères .............................. .................................................. 9­
6 9.11 Programmation des entrées/sorties en C .......................................... ..................... 9­7 9.12
E/S en mémoire ............... .................................................................. ...................... 9­7 9.13 Est­ce
vraiment utile ? .................................................................. ................................ 9­8 9.14 Sortie
d'erreur standard ........ .................................................................. ................... 9­8 9.15 Qu'en est­il
de l'instruction Exit(4) ? .................................................................. ........ 9­9 9.16 Exercice de
programmation .................................. ...................................................... 9­9

10 Entrée/Sortie de fichier .................................................. .................................. 10­1 10.1 Sortie vers


un fichier ........ .................................................................. .................................. 10­1 10.2 Ouverture
d'un fichier .......... .................................................................. .................................. 10­1 10.3 Sortie
vers le fichier ........ .................................................................. ...................... 10­2 10.4 Fermeture
d'un fichier ....................... .................................................................. ........................ 10­2 10.5 Sortie
d'un seul caractère à la fois ............... .................................. 10­2 10.6 La fonction
"Putc" ....... .................................................................. ........................ 10­3 10.7 Lecture d'un
fichier .............. .................................................................. ...................... 10­3 10.8 Lire un mot à la
fois ........ .................................................................. ........... 10­4 10.9 Ceci est un
problème ............................... .................................................................. ........ 10­4 10.10 Enfin,
nous lisons une ligne complète ................................. .................................... 10­5 10.11 Comment
utiliser un nom de fichier variable ..... 10­5 10.11 Comment utiliser un nom de fichier
variable ... .................................................................. ........ 10­5 10.12 Comment imprimons­
nous ? .................................................................. ..................................... 10­6 10.13 Exercices de programmation ........ ..........

11 Structures et syndicats .................................................. ...................... 11­1 11.1 Qu'est­ce qu'une


structure ? .................................................................. .................................. 11­1 11.2 Une variable
composée unique ......... .................................................................. ........... 11­1 11.3 Attribution de
valeurs aux variables ............................... ................................ 11­2 11.4 Comment utilisons­nous
les données obtenues ? .................................................................. ...... 11­2 11.5 Un tableau de
structures ....................................... ...................................... 11­2 11.6 Une remarque à Programmeurs
Pascal ............................................................ .................. 11­3 11.7 Nous affichons enfin tous les
résultats ............... .................................. 11­3 11.8 Utilisation conjointe de pointeurs et de
structures ....... ...................................... 11­3 11.9 Arithmétique du
pointeur .................................................................. ...................................... 11­4 11.10 Structures
imbriquées et nommées .... .................................................................. ............ 11­4 11.11 Deux
autres variables ............................... .................................................................. .. 11­5 11.12
Maintenant, pour utiliser certains champs ....................................... ........................ 11­5 11.13 En
savoir plus sur les structures ............... .................................................................. ........... 11­6 11.14
Que sont les syndicats ? .................................................................. ..................................... 11­6
11.15 Un autre exemple de syndicat ....... .................................................................. ...................
11­7 11.16 Un nouveau concept, le Typedef ..................... .................................................. 11­8
11.17 Qu'avons­nous maintenant ? .................................................................. ...................... 11­9
11.18 Exercices de programmation .................. .................................................................. ........ 11­9

Tutoriel C iii
12 Allocation
Machine Translated dynamique .................................................. ...................... 12­1
by Google
12.1 Qu'est­ce que l'allocation dynamique ? .................................................................. ...................... 12­1
12.2 Création de variables dynamiques .................................................. ...................... 12­2
12.3 Qu'est­ce qu'un tas ? .................................................................. ...................................... 12­2
12.4 En savoir plus sur les segments ............................................ ...................................... 12­2
12.5 Retour à la fonction "Malloc" .......................................... ...................... 12­3
12.6 Qu'est­ce qu'un casting ? .................................................................. ........................................ 12­3
12.7 Utilisation du bloc de mémoire alloué dynamiquement .................................. 12­3
12.8 Suppression des données allouées dynamiquement 12­4 .......................................
12.9 Cela a fait l'objet de nombreuses discussions .............................................. ...................... 12­4
12.10 Un tableau de pointeurs .................................................. ...................................... 12­4
12.11 Une liste chaînée .................................................. .................................................. 12­ 5
12.12 Les définitions des données .................................................. ...................................... 12­6
12.13 Le premier champ .................................................. .................................................. 12­7
12.14 Remplissage de structures supplémentaires .............................................. ...................... 12­7
12.15 Impression des données .................................................. .................................. 12­7
12.16 En savoir plus sur l'allocation dynamique et les listes liées .............................. 12­8
12.17 Une autre nouvelle fonction ­ Calloc ............................................ ...................... 12­8
12.18 Exercices de programmation .................................................. ................................ 12­8

13 Manipulation des caractères et des bits ............................................ ......... 13­1


13.1 Majuscules et minuscules ............................................ ................................... 13­1
13.2 Classification des personnages .................................................. ...................... 13­2
13.3 Les fonctions logiques .................................................. ...................................... 13­3
13.4 Les instructions de quart de travail ............................................ ...................................... 13­4

14Exemples de programmes .................................................. ................................ 14­1


14.1 Pourquoi ce chapitre ? .................................................................. ...................................... 14­1
14.2 whatnext.c ­ L'interrogateur de fichiers batch .......................................... .... 14­4
14.3 List.C ­ La liste des programmes ............................................ ...................... 14­6
14.4 Vc.C ­ La calculatrice visuelle ............................................ ...................... 14­9

15 La Calculatrice Visuelle ­ Version 1.00 ............................................ .... 15­1


15.1 Le didacticiel de la calculatrice visuelle .............................................. ...................... 15­1
15.2 Commentaires supplémentaires .................................................. ...................................... 15­3

16 Messages d'erreur ............................................ ...................................... 16­1

17 Tuteur Coronado Enterprises C ­ Ver 1.00 ....................................... 17­1

18 mises à jour HiTech C ............................................ ...................................... 18­1


18.1 Relcc.c .................................................. .................................................................. ............ 18­1
18.2 Fichiers modifiés .................................................. ...................................................... 18 ­1

19 Lectures complémentaires ............................................... .................................. 19­1


19.1 Passer du BASIC au C ............................................ ................................... 19­1
19.2 Programmation en C, édition révisée .............................................. .................. 19­1
19.3 Avancé C .................................................. .................................................................. .. 19­1
19.4 ............................................................ .................................................................. ...................... 19­1

Tutoriel C iv
Machine Translated by Google Tableau des figures

Trivial.c ............................................... .................................................................. ...................... 2­1


Wrtsome.c ............................................................ .................................................................. ................... 2­1
Écrit plus.c ............................................... .................................................................. ...................... 2­2
Oneint.c ............................................... .................................................................. ...................... 2­2
Commentaires.c ............................................................ .................................................................. ................. 2­3
Goodform.c ............................................... .................................................................. ................. 2­4
Uglyform.c .................................................. .................................................................. .................. 2­5
Tandis que.c ................................................ .................................................................. ...................... 3­1
Pendant ce temps.c ............................................... .................................................................. ...................... 3­1
Forloop.c ............................................... .................................................................. ...................... 3­2
Siautre.c ............................................... .................................................................. ...................... 3­3
Breakcon.c ............................................................ .................................................................. ................... 3­3
Switch.c ................................................ .................................................................. ...................... 3­4
Aller à ex.c ............................................... .................................................................. ...................... 3­5
Tempconv.c ............................................... . ............................................................... ... .............. 3­5
Dumbconv.c .................................................. .................................................................. ............ 3­7
Intasign.c ............................................... .................................................................. ...................... 4­1
Mortypes.c ............................................................ .................................................................. ................... 4­2
Types de lots.c ............................................... .................................................................. ...................... 4­4
Compare.c ............................................................ .................................................................. .................. 4­6
Cryptic.c .................................................. .................................................................. ...................... 4­9
Sommesqres.c .................................................. .................................................................. ................... 5­1
Carrés.c ............................................................ .................................................................. ...................... 5­3
Floatsq.c ............................................... .................................................................. ...................... 5­4
Portée.c ................................................. .................................................................. ...................... 5­5
Récurson.c ............................................... .................................................................. ................... 5­8
En arrière.c ............................................................ .................................................................. .................. 5­8
Définir.c ............................................... .................................................................. ...................... 6­1
Macro.c ............................................................ .................................................................. ...................... 6­2
Chrstrg.c ............................................... .................................................................. ...................... 7­1
Chaînes.c ............................................................ .................................................................. ...................... 7­2
Intarray.c ............................................... . ............................................................... ... .................. 7­3
Bigarray.c ............................................... . ............................................................... ... ............... 7­4
Renvoi.c ............................................................ .................................................................. ................... 7­5
Multiaire.c ............................................................ .................................................................. ...................... 7­6
Pointeur.c ............................................................ .................................................................. ...................... 8­1
pointeur2.c ............................................... .................................................................. ...................... 8­3
8­5
bidirectionnel.c ............................................................ .................................................................. .......................simpleio.c ............................... ......
singleio.c ............................................... .................................................................. ...................... 9­3
mieuxin.c ............................................... .................................................................. ...................... 9­4
intin.c ............................................... . ............................................................... ... ...................... 9­5
stringin.c ............................................... .................................................................. ...................... 9­6
spécial.c ................................................ .................................................................. ...................... 9­8
format.c ................................................. . .................................................................. ...................... 10­1
charout.c ............................................... . ............................................................... ... ................... 10­2
readchar.c ............................................... .................................................................. ...................... 10­3
readtext.c ............................................................ .................................................................. ...................... 10­4
readline.c ............................................... .................................................................. ...................... 10­5
n'importe quel fichier.c ............................................... .................................................................. ...................... 10­6
printdat.c ............................................... .................................................................. ...................... 10­6
struct1.c ............................................... .................................................................. ...................... 11­1
struct2.c ............................................... .................................................................. ...................... 11­2

Tutoriel C dans
struct3.cby
Machine Translated ...............................................
Google .................................................................. ...................... 11­3
imbriqué.c ............................................... .................................................................. ...................... 11­5
syndicat1.c ................................................. . .................................................................. ...................... 11­7
union2.c ............................................................ .................................................................. ...................... 11­8
dynlist.c ............................................... .................................................................. ...................... 12­1
bigdyn1.c .................................................. .................................................................. ...................... 12­5
dynlink.c ............................................... .................................................................. ...................... 12­6
uplow.c ......................................................................................................................... 13­1
charclas.c ............................................... .................................................................. ...................... 13­2
bitops.c ............................................... .................................................................. ...................... 13­3
levier de vitesse.c ............................................... .................................................................. ...................... 13­4
dosex_1616.c .................................................. .................................................................. ............... 14­4
et après.c ............................................... .................................................................. ................... 14­6
liste.c ............................................................ .................................................................. ...................... 14­6
vc.c ............................................... .................................................................. .. ................................. 14­15

Tutoriel C nous

Vous aimerez peut-être aussi