Transcription
[MUSIQUE JOUANT] DAVID J. MALAN : Très bien. Ceci est CS50. Ceci est la semaine un, car bien sûr, la semaine dernière était la semaine zéro. Et c'est la semaine où nous allons réellement commencer à programmer d'une manière beaucoup plus traditionnelle, ce langage de programmation que nous avons promis appelé C. Bien sûr, nous avons commencé par ceci. Et j'espère que d'ici maintenant, avec l'ensemble de problèmes 1, vous vous êtes un peu amusés, même si vous y avez déjà joué. Et les objectifs de Scratch, au-delà de rendre les choses très accessibles et conviviales, sont vraiment d'élucider certains des concepts fondamentaux que nous reverrons aujourd'hui, et vraiment chaque semaine par la suite, comme les fonctions, les conditions, les boucles, les variables et bien plus encore. Et en fait, parmi les objectifs de Scratch, il y a, encore une fois, de planter ces visuels dans votre esprit. Donc, même si aujourd'hui et par la suite ressemble encore plus à un tuyau d'incendie, surtout en ce qui concerne la syntaxe textuelle vraiment étrange et cryptique, les idées seront toujours les mêmes. Donc aujourd'hui, ce programme, Bonjour, le monde, devient ceci à la place. Et en fait, juste pour coder temporairement les choses par couleur, j'ose dire que ce que j'ai codé ici en orange, qui semble probablement, pour ceux d'entre vous qui n'ont jamais programmé, assez cryptique, est l'équivalent de quand le drapeau vert est cliqué, pièce de puzzle orange comme ceci. Ce qui reste, c'est juste une ligne en violet avec un peu de blanc, qui est ce qui va finalement faire dire à l'écran, Bonjour, le monde sur l'écran. Et bien sûr, nous avions un nom pour quelque chose en violet. En fait, si nous revenons à la semaine zéro, ce bloc en violet représentait quel type de fonctionnalité ? AUDIENCE : [INAUDIBLE]. DAVID J. MALAN : Une fonction elle-même, une action, un verbe qui fait faire quelque chose à l'ordinateur. Donc ce qui ressemblait à ceci la semaine dernière va ressembler à ceci. Enlèvons le codage couleur et concentrons-nous vraiment sur ce que nous allons maintenant appeler le code source. C'est donc ce que font les programmeurs dans le monde réel. C'est ce que font les développeurs de logiciels, les ingénieurs logiciels dans le monde réel. Ils écrivent du code qui ressemble à ceci. Et clairement, c'est un peu comme l'anglais, mais ce n'est pas de l'anglais de la manière dont vous composeriez un essai ou un e-mail. Clairement, il y a des motifs et une syntaxe spéciale qui seront mis en évidence aujourd'hui. Le problème, cependant, est que les ordinateurs, bien sûr, ne comprennent pas le code source. Ils ne comprennent, comme la semaine dernière, que les zéros et les uns. C'est tout, le soi-disant système binaire. Donc, d'une manière ou d'une autre, nous devons transformer ce qui ressemble déjà à du cryptique en quelque chose qui ressemble à première vue encore plus à du cryptique, les zéros et les uns que les ordinateurs comprennent. Et pour les besoins d'aujourd'hui, sachez simplement qu'il est intégré à vos Mac, PC et téléphones, une compréhension intégrée de ce que signifient ces motifs. Peut-être que cela signifie un nombre, peut-être que cela signifie une lettre. Mais aujourd'hui, peut-être que cela signifie une instruction, comme imprimer quelque chose à l'écran, ou sauvegarder quelque chose, ou charger quelque chose. C'est-à-dire que les ordinateurs utilisent des motifs de bits non seulement pour représenter tout ce dont nous avons parlé la semaine dernière - nombres, lettres, couleurs, images, sons, et tout cela, ils utilisent également des motifs de bits pour représenter des fonctionnalités fondamentales. Imprimer des choses, jouer des choses, un peu comme ces mêmes blocs Scratch. Mais aucun informaticien vraiment, à moins qu'il ne prenne un papier et un crayon ou n'écrive un programme ou n'utilise un site Web pour convertir cela, ne peut lire cela et savoir ce qui se passe. C'est pourquoi nous, les humains, allons en fait utiliser non pas du code machine, comme on l'appelle, les zéros et les uns que les ordinateurs comprennent, nous allons commencer à écrire du code source. Et la semaine dernière, vous avez déjà écrit du code source, mais sous forme de glisser-déposer de ces pièces de puzzle. Donc, cela aussi sera le paradigme qui nous guidera tout au long du semestre. La résolution de problèmes de programmation consiste vraiment à transformer l'entrée en sortie. Et nous nous concentrerons aujourd'hui sur un certain type d'entrée devenant une sortie. Quelqu'un doit prendre le code source, écrit dans un langage comme C, et le transformer en code machine, les zéros et les uns que l'ordinateur comprend réellement. Donc, le code source aujourd'hui sera notre entrée. Le code machine sera notre sortie. Et nous allons vous donner aujourd'hui un programme spécial appelé compilateur, dont le but dans la vie est de traduire l'un en l'autre. Et il existe des compilateurs pour différentes langues dans le monde. Nous allons nous concentrer sur un qui prend en charge la langue d'aujourd'hui, connue sous le nom de C. Et voici, comme promis, l'environnement de programmation que nous allons utiliser. Il est adapté à CS50, ce qui signifie que nous avons préinstallé certains logiciels qui pourraient vous être utiles pendant le semestre. Mais à toutes fins utiles, l'outil que vous utiliserez pour les ensembles de problèmes CS50 à partir de maintenant est un outil standard de l'industrie très populaire appelé Visual Studio Code, ou VS Code en abrégé. Nous utilisons une version basée sur le cloud de celui-ci qui se trouve littéralement à cette URL, cs50.dev. Vous pouvez vous y connecter tant que vous avez un compte GitHub gratuit, pour lequel vous vous êtes probablement déjà inscrit. Et cela vous donnera accès non seulement à un environnement de programmation standard de l'industrie, mais encore une fois, à un environnement qui a certaines choses spécifiques à CS50 préinstallées. Et à la fin du semestre, ou même au milieu, si vous êtes si enclin, vous pouvez en fait télécharger gratuitement VS Code sur votre Mac, PC. Vous pouvez vous déconnecter d'Internet et vous pouvez en fait programmer sur votre propre ordinateur. Le bémol, cependant, est que vous avez tendance à rencontrer des maux de tête de support technique au tout début du semestre, nous vous suggérons donc de le faire plus tard dans le semestre une fois que vous serez déjà à l'aise avec cet environnement basé sur le cloud ici. Et le voici. C'est ainsi que ressemblera la programmation, que nous utilisions C maintenant ou Python dans quelques semaines ou JavaScript ou SQL par la suite. Voici donc ce qui ressemble - ce que VS Code est configuré comme suit. En haut à droite, vous aurez généralement un ou plusieurs onglets pour le code, un peu comme les onglets d'un navigateur. Et c'est là que vous écrirez du code qui ressemble un peu à ceci. Et en fait, c'est exactement le code que vous avez vu il y a un instant. Ce que fait VS Code, entre autres choses, c'est qu'il met en surbrillance votre code pour vous. Il le colorise d'une manière généralement éclairante. Donc, je n'ai pas choisi de rendre ceci rouge. Je n'ai pas choisi de rendre ceci bleu et ceci violet. L'ordinateur le fait automatiquement pour vous, comme nous le verrons bientôt, pour attirer votre attention sur différentes idées dans le programme lui-même, tout cela se produit automatiquement. En bas ici, vous utiliserez une interface plus avancée à partir d'aujourd'hui, connue sous le nom d'interface en ligne de commande sous la forme d'une fenêtre de terminal. Vous pouvez donc toujours utiliser votre souris ou votre trackpad et cliquer et faire glisser et faire des choses comme ça dans cet environnement. Mais vous constaterez, et de nombreux programmeurs préfèrent que cela soit beaucoup plus efficace à terme d'utiliser votre clavier plus souvent que la souris ou le trackpad. Nous vous présenterons donc cette fenêtre de terminal textuelle là-bas. En haut à gauche, vous aurez un explorateur de fichiers. Ce qui est bien avec VS Code, c'est que vous aurez non seulement des commandes textuelles, avec lesquelles vous vous familiariserez, mais vous aurez également un Mac ou un PC ou un téléphone normal de nos jours, comme littéralement des fichiers et des dossiers apparaîtront visuellement pour vous, afin que vous puissiez jouer avec ou les manipuler là-bas. Et puis, enfin, c'est un peu comme le menu, la soi-disant barre d'activité qui contient juste des icônes pour diverses fonctionnalités, y compris le canard de CS50. Donc, en fait, si vous explorez, vous verrez finalement une icône de canard lorsque vous vous connecterez, qui est votre propre chatbot spécifique à CS50 auquel vous pouvez poser des questions tout au long du processus. Maintenant que nous avons VS Code ici, allons-y et considérons ce qu'il représente. C'est donc généralement, pour le jargon, une interface utilisateur graphique, ce qui signifie des boutons, des icônes, des menus et tout cela. Nous prenons tous cela pour acquis sur la plupart des appareils aujourd'hui. Cela est abrégé, juste pour que vous le sachiez, en GUI, G-U-I. Mais intégré à VS Code, encore une fois, il y a non seulement la fenêtre de terminal par son nom, mais conceptuellement, c'est une interface en ligne de commande. Donc, pas une interface utilisateur graphique, mais une interface en ligne de commande, où il n'y a pas d'icônes sur lesquelles cliquer ou double-cliquer. Plutôt, si vous voulez exécuter un programme, vous utilisez l'interface en ligne de commande, ou CLI, pour taper le nom du programme que vous voulez exécuter. Et donc cela semblera un pas en arrière initialement aujourd'hui, car nous tapons et pointons et double-cliquons sur les choses de nos jours. Mais encore une fois, cela nous donnera plus de puissance, plus d'efficacité à terme au-delà de cela. Cela dit, allons-y et utilisons-le pendant un moment. Pendant le cours, vous êtes invités à suivre. Mais il suffit de dire que nous allons généralement assez vite. Vraiment, vous apprendrez à programmer par le biais des ensembles de problèmes chaque semaine. J'introduirai et me concentrerai sur les concepts, les idées, les primitives qui vous permettront de commencer, mais ce n'est qu'en faisant réellement les ensembles de problèmes que la mémoire musculaire et la pratique viendront. Alors ne vous inquiétez pas si tout ne se passe pas facilement la première fois. Voici donc le code que je prétends être équivalent au programme Bonjour, le monde de la semaine dernière. Faisons-le réellement dans l'environnement de programmation. Je vais donc passer à VS Code lui-même, qui fonctionne maintenant sur mon Mac ici. Ce n'est pas juste une capture d'écran. Et je vais faire ce qui suit pour commencer à programmer. Je vais écrire littéralement dans ma fenêtre de terminal, le mot code, et je devrai peut-être lui donner le focus en cliquant dans ce quadrant de l'écran. Et ensuite, je vais donner le nom du fichier que je veux coder. Et dans ce cas, je vais proposer que nous l'appelions hello.c. Dans le monde de Scratch, lorsque vous le téléchargiez, vous avez peut-être remarqué que les fichiers sont tous appelés SB3 ou une extension de fichier similaire. Lorsque vous écrivez du code en C, vous nommez littéralement le fichier quelque chose point C par convention. Mais remarquez d'autres détails. Surtout si je zoome, tout ce que j'ai tapé jusqu'à présent est en minuscules. Il n'y a pas d'espaces. Et donc cela sera important. Et malheureusement, les ordinateurs ne pardonnent pas. Et il y a de fortes chances que l'une des premières erreurs stupides que vous ferez soit de mal capitaliser quelque chose, de mal orthographier quelque chose, d'ajouter trop d'espaces ou quelque chose de similaire. Ne vous inquiétez pas. Avec le temps, cette mémoire musculaire viendra avec la pratique. Alors laissez-moi dézoomer. Laissez-moi maintenant appuyer sur Entrée et vous verrez en haut à droite l'onglet Code que j'ai promis. Je vais donc taper ce programme assez rapidement, car je l'ai déjà fait. Include stdio.h, int main void, puis quelques accolades, comme on les appelle, puis printf guillemets guillemets. Bonjour, virgule, monde, barre oblique inverse n, fermer guillemets, point-virgule. Très bien. C'est beaucoup. Mais cela viendra aussi avec le temps et la pratique. Mais c'est le code exact que nous avons vu il y a un instant. En effet, si je zoome, il est codé par couleur comme dans la capture d'écran, et j'ai donc écrit mon premier programme. VS Code enregistrera automatiquement pour vous, mais vous pouvez également appuyer sur Contrôle ou Commande S pour vous assurer qu'il est enregistré. Mais remarquez ce qui s'est passé en haut à gauche. Non seulement vous voyez mon code ici, mais vous voyez une icône visuelle, tout comme sur un Mac ou un PC, oui, ce fichier existe maintenant dans votre compte. Et c'est aussi ce que vous obtenez avec VS Code pour CS50. Vous obtenez votre propre serveur dans le cloud. On l'appelle un conteneur de nos jours. Il y a donc de l'espace disque virtuel quelque part dans le cloud, à la iCloud ou Google Drive, qui stockera tous vos fichiers. Et pour le moment, comme j'ai actualisé mon compte avant le cours, je n'ai qu'un seul fichier dans mon compte. Qu'est-ce que c'est ? Qu'est-ce que c'est ? Eh bien, c'est comme mon numéro d'identification pour GitHub. Pas vraiment un gros problème. C'est juste généré aléatoirement par GitHub. Urban Adventure est le nom de mon environnement de programmation aujourd'hui, autrement connu sous le nom de code space. C'est juste une chose GitHub qui est, encore une fois, l'une de ces entreprises cloud. Au lieu de choisir des lettres et des chiffres aléatoires pour identifier de manière unique tous nos environnements de programmation, il est populaire dans l'industrie technologique de nos jours de simplement assembler des mots anglais aléatoires qui sonnent parfois plutôt cool. Mais c'est juste par coïncidence, pas quelque chose que j'ai choisi. Le vôtre sera différent. Très bien, j'ai donc écrit du code. J'ai créé hello.c. J'ai tapé tout ce code. J'ai confirmé visuellement à gauche qu'il a été créé. Je vais cacher mon explorateur de fichiers à partir de maintenant, juste pour que nous puissions nous concentrer sur le code. Comment puis-je exécuter ce programme ? Eh bien, sur un Mac ou un PC, nous aurions l'habitude d'ouvrir le dossier et de double-cliquer dessus. Ou sur votre téléphone, vous le sortiriez et taperiez sur une icône. Mais pas ici. Ici, nous nous concentrons principalement sur l'interface en ligne de commande dans cet environnement. Je vais donc devoir introduire quelques commandes. Vous avez déjà vu la commande code, qui pour nos besoins est spécifique à VS Code, qui crée simplement un nouveau fichier appelé hello.c dans ce cas. Mais j'ai besoin de deux autres commandes pour réellement exécuter ce programme. La première s'appelle gentiment make, puis je spécifie quel programme je veux créer. Et puis un peu bizarrement, je dois taper point slash hello. Mais juste pour prendre du recul, make hello. Si c'est sur le point d'être ma deuxième commande que je tape, que représente cette étape, peut-être ? Compte tenu de ce que j'ai dit il y a une minute ou deux. AUDIENCE : Cela va traduire votre code source en uns et zéros. DAVID J. MALAN : Parfait. Donc make représente le compilateur, pour ainsi dire, le programme qui convertit le code source en code machine. Je dois le faire pour l'instant manuellement en exécutant make hello. Maintenant, make est plutôt intelligent, et même si je dis make hello, pas make hello.c, make est intelligent, et il va dire, si vous voulez créer un programme appelé hello, je vais supposer qu'il y a quelque part dans ce dossier un fichier appelé hello.c. Donc vous ne devriez pas taper make hello.c. Vous tapez juste make hello. Et puis cette troisième commande, encore plus cryptique, que pourrait-elle faire ? Si c'est l'étape trois sur trois. Cela va exécuter le code machine. Cela va dire à l'ordinateur dans ce dossier, le point implique ce dossier actuel, et point slash signifie juste quelque chose dans ce dossier actuel. Exécutez le programme appelé Hello. C'est donc tout. Il y a trois étapes pour écrire un programme en C. Vous créez le fichier, comme avec la commande code. Mais il existe d'autres moyens de le faire aussi. Et vous n'avez même pas besoin d'utiliser VS Code. Vous pouvez utiliser des dizaines d'autres programmes alternatifs dans le monde. Vous exécutez le compilateur, qui, dans ce cas, s'appelle make. Petit mensonge blanc, make n'est pas réellement le compilateur, mais nous en parlerons plus la semaine prochaine. Mais make va déclencher la compilation de ce code. Et la dernière étape trois est d'exécuter, ou de lancer le programme appelé Hello. Alors retournons à VS Code ici. Et vous verrez que mon code est toujours en haut. Ma fenêtre de terminal est en bas. J'ai caché mon explorateur de fichiers, juste parce que ce n'est plus très intéressant. Et je vais faire ce que vous avez proposé, qui était M-A-K-E espace hello. Tout en minuscules. Entrée. Et ironiquement, heureusement, rien ne s'est passé. Et c'est en fait une bonne chose dans cet environnement. Si rien ne semble se passer, vous avez probablement bien fait. Si quelque chose semble se passer à l'écran, vous avez probablement fait une erreur et vous avez fait une erreur. Donc, ne rien voir est généralement une bonne chose. Mais qu'est-ce qui s'est passé ? Eh bien, laissez-moi revenir en arrière et ouvrir mon explorateur de fichiers. Et remarquez, il n'y a pas seulement hello.c, mais il y a un deuxième fichier maintenant. Hello, qui est le nom du programme. Donc Hello est le programme que je veux exécuter. Je vais retourner à mon terminal ici et pour exécuter ce programme, je vais faire point slash H-E-L-L-O. Je vais croiser les doigts, comme je le ferai souvent maintenant, et voilà, mon tout premier programme en C. Comment d'autre pouvons-nous voir ce fichier ? Eh bien, ici dans ma fenêtre de terminal. Laissez-moi zoomer. Vous continuez à voir un signe dollar. Cela n'a rien à voir avec la monnaie. C'est juste une convention étrange et geek que votre invite dans une fenêtre de terminal, là où vous tapez des commandes, commence généralement par un signe dollar. Parfois, c'est un symbole dièse. Parfois, c'est une accolade angulaire. Cela dépend du système sur lequel vous êtes. Mais le signe dollar est très courant. Il signifie simplement tapez vos commandes ici. Eh bien, j'ai tapé code, j'ai tapé make, et j'ai tapé point slash hello. Mais je peux aussi taper d'autres choses. Et nous en parlerons plus tard. Comme ls, qui n'épelle pas réellement quelque chose, mais est l'abréviation de list, L-I-S-T. Les programmeurs ont tendance à être aussi concis que possible, donc la plupart des commandes ne sont pas des mots complets. Ce sont souvent des abréviations. Si j'appuie sur Entrée maintenant, vous verrez également deux choses. Vous verrez hello.c. Et vous verrez en vert, juste pour attirer l'attention dessus, hello aussi. L'astérisque ici signifie juste que dans l'environnement de programmation, ce programme est exécutable. Comme vous pouvez réellement l'exécuter en faisant point slash hello. Le fait que ce soit juste blanc ici, cela signifie juste que c'est un fichier texte. C'est en fait du code source. En d'autres termes, ls liste le fichier dans mon dossier actuel. Ou vous pouvez utiliser vos yeux humains dans l'explorateur de fichiers en haut à gauche et simplement regarder quels fichiers existent. Ce sont un et le même. L'un est une GUI, l'autre est une CLI. Ligne de commande graphique. Et ainsi de suite. Et nous commencerons bientôt à prendre ces types de paradigmes pour acquis. Mais laissez-moi faire une pause ici et voir jusqu'à présent, maintenant que nous avons écrit notre premier de nombreux programmes C, des questions ? Ou des confusions que nous pouvons clarifier ? Ce n'est pas grave si vous ne comprenez pas la plupart des lignes de code. C'est le but d'aujourd'hui. Oui. AUDIENCE : Je ne comprends pas bien la différence entre hello et hello.c. DAVID J. MALAN : Quelle est la différence entre hello et hello.c ? Alors hello.c est littéralement mon code source. C'est un fichier qui existe quelque part dans le cloud et qui contient tout le code que j'ai moi-même écrit. Le fichier hello est le fichier que le compilateur a créé pour moi en convertissant le code source en code machine. Donc, à l'intérieur de hello, théoriquement, il y a un tas de zéros et de uns. Nous ne pouvons pas vraiment les voir. Mais si je fais ceci, laissez-moi dézoomer. Laissez-moi cliquer sur hello. Et remarquez que VS Code va me crier dessus. Ce fichier - le fichier n'est pas affiché dans l'éditeur de texte car il est soit binaire - c'est-à-dire des zéros et des uns - soit utilise un encodage de texte non pris en charge, quoi que cela signifie. Si je l'ouvre quand même, mais je ne le recommande pas. Comme tenez compte de ces avertissements. Vous ne verrez pas de zéros et de uns, mais vous verrez du non-sens. Et c'est parce que VS Code essaie d'interpréter ces zéros et ces uns de manière incorrecte, comme du texte ASCII, comme du texte anglais. Mais ce n'est pas le cas. Ce sont des instructions pour l'ordinateur. Donc, dès que vous voyez des trucs rouges effrayants comme ça, comme annuler, fermer l'onglet que vous avez ouvert, car il y a de fortes chances que vous ne puissiez que casser le programme que vous venez de créer. Ce n'est pas grave. Vous pouvez le recréer. Mais c'est ce qu'il y a à l'intérieur de ces fichiers. Oui. AUDIENCE : Et si [? vous ne ?] [INAUDIBLE] ? DAVID J. MALAN : Très bonne question. Et si nous ne tapons pas point slash hello, juste hello. Eh bien, laissez-moi faire ceci. Laissez-moi cacher mon explorateur de fichiers à nouveau car ce n'est plus très intéressant à partir de maintenant. Je vais effacer ma fenêtre de terminal en appuyant sur Contrôle L, juste pour être propre et rangé en classe. Ou vous pouvez littéralement taper clear et cela l'effacera. Mais encore une fois, c'est juste pour garder les choses rangées. Vos TFs pourraient faire cela en section 2. Si je tape juste Hello, entrée. Je vais obtenir ceci, bizarrement. Bash, hello, commande introuvable. Donc, plus sur bash plus tard. Mais cela signifie simplement littéralement que la commande hello n'est pas trouvée car vous devez dire à l'ordinateur où elle se trouve. Donc point slash hello signifie exécuter le programme hello qui est, en fait, juste ici. Par contraste, vous n'exécutez pas point slash pour code, pour make, ou d'autres commandes que nous verrons bientôt, comme ls, parce que pourquoi ? Ceux-ci sont installés dans le système pour tout le monde, pas seulement dans votre dossier individuel. C'est donc la différence. Tous les programmes que nous écrirons, ce sera point slash quelque chose. Très bien, décomposons ce qui se passe réellement et voyons si nous pouvons nous appuyer fortement aujourd'hui sur Scratch, surtout lorsque la syntaxe devient étrange, peut-être un peu écrasante. Toujours la même idée. Donc, la dernière fois, bien sûr, c'était notre programme Scratch qui disait simplement Bonjour, le monde. Je prétends aujourd'hui que c'est l'équivalent le plus proche que tout programmeur puisse convertir Scratch en C. Si nous le codions par couleur en conséquence, en effet, cela correspond à quand le drapeau vert est cliqué, c'est l'orange. Et puis le violet est juste l'équivalent du bloc dire. Donc, le bloc dire, nous l'avons dit plus tôt, était une fonction. Comparons donc ces choses côte à côte car il y a en fait une certaine logique dans ce que MIT a fait avec Scratch, quant à pourquoi ces formes ressemblent à ce qu'elles font, etc. Donc, dans Scratch, il y a une fonction appelée say. Rappelez-vous qu'elle prend une entrée, autrement connue sous le nom d'argument, ou un paramètre est un autre nom. Et cela est toujours fourni dans ces ovales blancs, zéro ou plusieurs ovales blancs. En C, nous l'avons déjà vu, mais faisons-le un peu plus pédant, le dire équivalent est essentiellement le mot print. Pourquoi MIT a-t-il dit dire ? Juste parce que c'est un peu plus adapté aux enfants. Mais print est l'idée dans notre environnement. Ce n'est en fait pas print, c'est printf, car nous allons pouvoir formater notre texte de manière intéressante. Nous en parlerons plus tard. Mais remarquez, les parenthèses ouvrantes et fermantes ici évoquent l'idée de cet ovale blanc. C'est donc intentionnel de la part de MIT. Qu'est-ce qui, cependant, en C va entre ces parenthèses ? Eh bien, littéralement l'entrée ou l'argument que vous voulez passer à la fonction, comme Bonjour, le monde. Mais en C, vous devez être un peu plus pédant car vous n'avez pas de joli petit graphique comme ce bloc violet avec l'ovale blanc. Vous devez entourer tout dans des guillemets doubles. Ceux d'entre vous qui ont une expérience préalable en programmation, en C, vous avez besoin de guillemets doubles, pas de guillemets simples dans ce contexte. Et puis il y a ce détail archaïque ici, la barre oblique inverse n, sur lequel nous reviendrons dans un instant. Mais c'est essentiellement ce qui se passe, ligne par ligne de Scratch à C, il y a une sorte d'égalité entre les deux, même si, bien sûr, elles ont l'air un peu différentes. Eh bien, voyons ce que fait cette barre oblique inverse n, juste pour mettre en évidence certains détails ici. Laissez-moi donc zoomer un peu ici et laissez-moi remonter à mon code. Et laissez-moi simplement supprimer imprudemment la barre oblique inverse n. Je vais laisser l'enregistrement automatique. Je vais dézoomer. Dans ma fenêtre de terminal maintenant, je vais exécuter make hello pour recompiler le code du code source au code machine, car j'ai modifié le code source. Rien ne semble se passer. C'est bien. Maintenant, je vais taper point slash hello, entrée. Et il y a un bug subtil. Depuis que j'ai fait ce changement. Qu'est-ce qui semble mal à vos yeux maintenant ? AUDIENCE : Le signe dollar [INAUDIBLE]. DAVID J. MALAN : Oui, le signe dollar, notre soi-disant invite est à la fin de la ligne au lieu d'être sur une nouvelle ligne. Je veux dire, ce n'est pas vraiment un facteur décisif. Comme le code fonctionne, et vous pouvez toujours taper une nouvelle commande. Mais cela a l'air un peu stupide. Ce n'était pas l'intention du programme. C'est une bonne pratique de déplacer l'invite à la ligne suivante, et c'est parce que la barre oblique inverse n est ce que nous allons appeler une séquence d'échappement. Il s'avère donc qu'en programmation, vous devez dire exactement à l'ordinateur ce que vous voulez qu'il fasse. Donc, si vous voulez une nouvelle ligne, l'équivalent d'appuyer sur Entrée à l'écran, vous devez dire à l'ordinateur de mettre une nouvelle ligne là-bas. Ce que vous ne faites pas, c'est ceci. Si je dézoome et que je vais dans mon code ici, et que je zoome sur le code - si vous voulez mettre une nouvelle ligne, vous ne faites pas ceci. Pourquoi ? C'est juste déroutant pour l'ordinateur. Comme, attendez une minute, est-ce une faute de frappe ? Vos lignes se sont-elles juste enroulées. Voulez-vous mettre une nouvelle ligne là-bas. Cela a juste l'air stupide. Et cela rend le code lui-même moins basé sur les lignes. Donc, les humains ont décidé il y a des années, si vous voulez un vrai saut de ligne, n'appuyez pas simplement naïvement sur la touche Entrée. Dites littéralement à l'ordinateur, mettez une nouvelle ligne ici. Si vous voulez descendre de deux lignes, faites-en simplement deux. Si vous en voulez trois, faites-en simplement trois. Eh bien, pourquoi la barre oblique inverse ? Encore une fois, ce sont ce que l'on appelle des séquences d'échappement. Et vous ne voulez pas littéralement d'un n, encore moins [? d'un ?] n n. Ce que vous voulez, c'est une nouvelle ligne, qui est représentée dans le code comme simplement une barre oblique inverse n. Maintenant, pour les mathématiciens parmi vous, ce que nous faisons maintenant en écrivant, en utilisant des fonctions comme printf, c'est un peu comme la notation f de x, si vous vous en souvenez du lycée ou d'avant, où f est une fonction, x est un argument ou une entrée, et nous utilisons des parenthèses dans le code, tout comme les mathématiciens le feraient, pour écrire des fonctions comme celles-ci. Et les types de fonctions que nous utilisons actuellement suivent toujours ce modèle. Vous avez une entrée, vous voulez une sortie. Dans ce cas, l'entrée de printf, par exemple, tout comme le bloc dire, est ce que l'on appelle un argument. La sortie, cependant, de la fonction printf est ce que nous appelons un effet secondaire. Et la façon la plus simple d'y penser est qu'un effet secondaire est juste quelque chose qui se produit à l'écran, visuellement, [? auditivement. ?] Cela se produit juste. Et il y a cet effet à l'écran. Et nous contrasterons cela avec d'autres types de sorties de fonctions. Mais pour l'instant, nous nous concentrons sur ceci, qui rappelle, bien sûr, ce que nous avons fait la semaine dernière, c'est-à-dire que si vous tapez Bonjour, le monde dans l'ovale blanc, utilisez la pièce de puzzle dire, vous obtenez l'effet secondaire que le chat semble avoir dit bonjour, le monde. Maintenant, en ce qui concerne ces séquences d'échappement en C, il y en a beaucoup, mais très peu d'entre elles seront réellement utilisées en pratique. La barre oblique inverse n est une nouvelle ligne. La barre oblique inverse r est un peu plus subtile et c'est une sorte de fonctionnalité d'antan. Elle déplace le curseur non pas à la nouvelle ligne, mais au début de la ligne. Un peu comme une machine à écrire ancienne, si vous avez vu comment elles fonctionnent. Parfois, cependant, vous pourriez vouloir imprimer un vrai guillemet double. Mais il y a un problème, bien sûr. Si c'est mon code ici, et que j'utilise déjà des guillemets doubles comme symboles spéciaux pour entourer le texte, je veux que printf dise que ce serait probablement un peu - comme si vous vouliez dire bonjour, le monde, avec des guillemets d'air, pourquoi cela pourrait-il ne pas être une bonne idée ? Si vous y pensez du point de vue de l'ordinateur. Pourquoi ce n'est probablement pas la bonne façon de faire ça ? Oui ? AUDIENCE : [INAUDIBLE]. DAVID J. MALAN : Exactement. L'ordinateur va en effet lire votre code de haut en bas, de gauche à droite. Et quand il voit le premier guillemet ouvrant, OK, c'est bon. Il comprend cela. Mais quand il arrive au deuxième guillemet, il va supposer, oh, attendez une minute. Peut-être que vous voulez juste que je dise bonjour virgule, et ensuite il continuera à lire et dira, attendez une minute, pourquoi le mot monde est-il ici. Et puis attendez une minute, maintenant il y a deux autres guillemets. C'est juste déroutant. C'est ambigu. Et les ordinateurs ont besoin que vous soyez, encore une fois, très précis. Donc, si vous voulez qu'un guillemet soit littéralement affiché à l'écran, vous l'échappez, pour ainsi dire, ce qui semble un peu étrange et demande un peu d'habitude. Mais cela résout juste ce genre de problème. Et de même, pourriez-vous utiliser des guillemets simples dans d'autres contextes ? Nous en parlerons bientôt. Et si vous voulez vraiment vous creuser la tête, comment imprimez-vous réellement une barre oblique inverse littérale, si jamais cela vous intéresse ? Ce n'est pas un caractère très courant à taper, mais si vous en voulez jamais à l'écran, il semble que nous utilisons la barre oblique inverse comme caractère spécial qui dit, hé, donnez-moi une nouvelle ligne ou donnez-moi un retour chariot ou donnez-moi un guillemet double. Bizarrement, en programmation, si vous voulez taper une barre oblique inverse littérale à l'écran, vous faites littéralement une barre oblique inverse barre oblique inverse. Mais c'est tout pour la bizarrerie pour l'instant. Mais cela dit, les humains ont rencontré ces mêmes problèmes il y a des années. Ils ont trouvé des solutions, et maintenant nous avons en effet ces conventions dans le code. Très bien. Décomposons donc d'autres fonctionnalités de ceci dans chaque programme que nous allons écrire, à savoir ce qui se trouve en haut de ce fichier. Donc, tout en haut de ce fichier, il y a ce #include d'apparence cryptique, ou #include standard io.h entre crochets angulaires. C'est donc un peu étrange. Nous en parlerons aussi plus la semaine prochaine. Mais c'est ce qu'on appelle un fichier d'en-tête. Tout fichier se terminant par .h n'est pas une source - eh bien, tout fichier se terminant par .h est ce que nous appellerons un fichier d'en-tête. Et à l'intérieur de ce fichier d'en-tête se trouve une fonctionnalité qui est peut-être venue avec le système, est venue avec le langage de programmation lui-même. Donc, par exemple, je vais faire ceci. Je vais revenir à mon code ici et je vais faire une erreur très courante que vous-mêmes pourriez faire dans les jours à venir, où j'oublie juste cette ligne parce que je ne la comprends même pas en premier lieu, donc je n'ai certainement pas pensé à la taper ici. Maintenant, si je reviens à ma fenêtre de terminal après l'avoir effacée et que j'exécute make hello, parce que je veux la recompiler parce que j'ai modifié le code source, je vais voir une erreur assez cryptique. Je veux dire, il y a plus d'erreurs en vert qu'il n'y a de code ici, mais vous vous y habituerez à lire pour essayer de comprendre ce qui se passe. Et je vois ceci. Hello.c, ligne 3, caractère 5. Donc cela signifie juste ligne 3, deux-points, caractère 5. De gauche à droite, c'est une sorte d'indice visuel quant à l'endroit où se trouve le problème. Appel à la fonction de bibliothèque non déclarée printf avec le type ... Et puis le reste me submerge visuellement à ce stade. Mais c'est un indice. Si vous n'incluez pas ce fichier d'en-tête en haut du code que vous avez écrit, vous n'avez pas accès à ce que l'on appelle généralement une bibliothèque. Une bibliothèque est une collection de code que quelqu'un d'autre a écrit pour vous. Peut-être que c'était MIT, peut-être que c'étaient les auteurs du langage C lui-même il y a des années. Peut-être que c'était CS50 si nous avons écrit du code pour vous. Une bibliothèque est une collection de code que quelqu'un d'autre a écrit pour vous et vous y accédez, encore une fois, en incluant des fichiers d'en-tête que ces mêmes personnes ont écrits pour vous. Donc, si je reviens à mon code maintenant - laissez-moi effacer ma fenêtre de terminal juste pour être moins submergé. Laissez-moi annuler ce que je viens de faire et remettre ce fichier. Pouvez-vous peut-être déduire, juste fonctionnellement, ce qui se trouve dans standard io.h que, encore une fois, quelqu'un d'autre a écrit ? Qu'est-ce qui doit être à l'intérieur ? Printf. Donc, quiconque a inventé printf il y a des décennies a probablement mis ce code dans ce fichier. Et donc en l'incluant, pour ainsi dire, dans mon code, j'ai maintenant accès à la fonctionnalité printf. C'est donc tout. Et encore une fois, C est de plus bas niveau que scratch. Il est évidemment basé sur du texte, ce qui signifie que vous devez être un peu plus pédant vous-même quant à ce que vous voulez que l'ordinateur fasse pour vous. Et si vous voulez utiliser le code de quelqu'un d'autre, vous devez effectivement l'inclure. Scratch ne s'est pas embêté avec ça, mais nous devons effectivement le faire dans le contexte de C. Soit dit en passant, juste pour prévenir certains maux de tête inutiles, ce mot n'est pas studio.h. Chaque année, un nombre non nul de personnes ne comprennent pas pourquoi leur code ne fonctionne pas parce que studio.h est introuvable. C'est standard io, stdio.h. C'est l'une des premières erreurs fréquemment commises sinon. Très bien, alors souvenez-vous de cela. Laissez-moi maintenant annuler les guillemets inutiles que j'ai ajoutés ici. Et laissez-moi proposer de vous montrer où vous pouvez en apprendre davantage. Donc, toutes ces bibliothèques sont généralement documentées. Les gens ont écrit des instructions sur la façon de les utiliser. Vous n'avez donc pas seulement à écouter et à faire attention en classe. Vous n'avez pas à ouvrir un livre. Il y a aussi de la documentation en ligne. Par exemple, pour le fichier d'en-tête standard d'entrée/sortie. Et la documentation dans le monde de la programmation pour C spécifiquement s'appelle des pages de manuel ou des pages man en abrégé. Malheureusement, elles ont été écrites il y a des décennies pour les plus à l'aise d'entre vous, ceux qui ont déjà un œil pour la programmation. Et donc ce que CS50 a fait à cette URL, manual.cs50.io, c'est que nous avons essentiellement des versions plus conviviales de la documentation pour ce fichier d'en-tête et d'autres. Donc, par exemple, si je consulte manual.cs50.io, vous verrez une page Web comme celle-ci. Et si je fais défiler rapidement, vous verrez un tas de fichiers d'en-tête, des fichiers .h, et un tas de fonctions en dessous. Et il n'y en a que quelques dizaines ici. Et en effet, selon cette case à cocher en haut fréquemment utilisée dans CS50, nous avons mis en évidence les fonctions que vous voudrez probablement utiliser au cours du prochain mois et demi. Si je désactive ce mode moins confortable, il y a en fait des centaines de fonctions qui accompagnent C. Et comme aucun programmeur ne connaît toutes ces fonctions. Ce qu'ils font, c'est qu'ils lisent le manuel quand ils veulent trouver une nouvelle fonctionnalité. Je vais donc simplifier cela. Je vais faire défiler vers le bas, cependant, jusqu'à stdio.h, par exemple ici, et vous verrez plus de fonctions que nous aborderons éventuellement. Mais si je clique sur printf, vous verrez, espérons-le, des instructions assez conviviales sur le fonctionnement de cette chose. Par exemple, sous synopsis, vous verrez que nous vous indiquons quel fichier d'en-tête vous devez inclure pour l'utiliser. En dessous se trouve ce que l'on appelle un prototype. Nous en parlerons plus tard. Mais en dessous se trouve une description. Et c'est là que le personnel de CS50 a écrit en termes simples des explications sur le fonctionnement de cette fonction, comment l'utiliser, et ainsi de suite. Mais si vous préférez voir ce que le monde réel utilise, vous pouvez désactiver ce mode et vous verrez de manière beaucoup plus arcanique la langue originale. En bref, ce sont des sortes de roulettes d'entraînement que vous pouvez activer et désactiver à votre guise. Mais en fin de compte, c'est aussi de la documentation du monde réel. Donc, si nous voulons voir autre chose, par exemple, laissez-moi revenir au menu principal. Et comme nous le verrons aujourd'hui, il existe en fait des fonctions dans un fichier d'en-tête appelé cs50.h sur lequel nous nous appuierons fortement pendant quelques semaines. Longue histoire courte, c'est en fait assez difficile. C'est ennuyeux en C d'obtenir une entrée utilisateur, ironiquement, pour faire taper à l'humain un mot ou un nombre. Vous devez franchir quelques obstacles techniques pour que cela se produise. Et nous vous montrerons comment le faire de la vraie manière dans quelques semaines. Mais pour l'instant, parmi les premières roulettes d'entraînement se trouve un code de bibliothèque CS50 que nous avons écrit et qui vous simplifiera la vie. Et en effet, nous vous donnerons accès à des fonctions qui simplifient le processus d'obtention d'une entrée de l'utilisateur. Par exemple, nous vous donnerons accès à des fonctions comme get_string, lorsque vous voulez obtenir une chaîne de texte de l'utilisateur - une chaîne est juste du texte. Donc, si vous voulez obtenir un caractère, un mot, une phrase, un paragraphe, vous pouvez appeler une fonction appelée get_string. Nous vous en donnerons une autre appelée get_int. Lorsque vous voulez obtenir un entier de l'utilisateur, comme 1 ou 0 ou -1 ou tout autre chose, vous pouvez également utiliser cette fonction. Et nous verrons aujourd'hui qu'il existe d'autres fonctions que vous pouvez utiliser de la bibliothèque de CS50. Dans une semaine, nous les retirerons une fois que vous n'en aurez plus besoin. Et vous verrez ce que ces fonctions de bibliothèque ont fait pour vous pendant tout ce temps. Mais pour l'instant, concentrons-nous sur ceci. Peut-être la plus utile d'entre elles, get_string, et résolvons un problème que nous avons déjà résolu assez facilement dans Scratch. Rappelez-vous dans Scratch, c'était un programme qui utilisait deux fonctions. Trois, en fait. Ask, pour poser une question à l'utilisateur. Say, pour afficher réellement quelque chose à l'écran. Et join, pour combiner le défaut de pomme, banane. Ou dans ce cas, Bonjour, et la réponse de l'humain. Cela a donc rendu notre programme Bonjour un peu plus interactif la dernière fois. Comment pouvons-nous traduire cela dans un paradigme similaire maintenant ? Donc, entrée et sortie est l'histoire, comme toujours. Dans ce cas, nous avons des arguments qui entrent dans ces fonctions. Mais maintenant, nous allons introduire non pas des effets secondaires, qui sont des choses qui se produisent visuellement. Nous allons revoir ce cercle bleu appelé answer, ou l'ovale bleu appelé answer, qui représentait la semaine dernière ce que nous appelions une valeur de retour. Et c'est ce que de nombreuses fonctions feront réellement pour nous. Elles ne se contenteront pas d'afficher quelque chose de présomptueux à l'écran ou de jouer un son ou une vidéo ou quelque chose comme ça. Elles vous rendront virtuellement une valeur - du texte, des entiers, des sons, des images avec lesquels vous pourrez ensuite faire ce que vous jugez bon. Le paradigme que nous aurons maintenant sera donc très similaire à Scratch. Si l'entrée est quel est votre nom et que la fonction est ask, et que vous obtenez une valeur de retour de answer, nous voulons réellement faire cela maintenant en C. Donc, côte à côte, le code comme ceci dans Scratch ressemblera aujourd'hui à ceci. Au lieu d'utiliser le bloc Ask, vous utilisez littéralement la fonction de CS50 appelée get_string. Elle prend une entrée. Nous mettons donc les parenthèses à gauche et à droite pour évoquer l'idée de cet ovale blanc. À l'intérieur de cette chaîne, vous pouvez mettre une invite, pour ainsi dire, comme, qu'est-ce que vous voulez demander à l'humain, dans ce cas. Et il me manque encore quelque chose. Selon les espaces réservés ici, qu'est-ce qui manque ? Donc des guillemets, donc littéralement des guillemets à gauche et à droite. Et je vais être un peu maniaque ici. Je vais mettre un espace à la fin. Parce que je ne veux pas - je pourrais, mais je ne veux pas que le curseur passe à la ligne suivante. Donc, pas de barre oblique inverse n. Si je veux que le curseur reste là à clignoter, attendant l'utilisateur après le point d'interrogation, je vais juste mettre un espace. Donc il restera là pour moi. Mais c'est juste un détail esthétique utilisant la même idée qu'auparavant. C'est donc l'analogue de ce bloc. Mais comment puis-je accéder à la soi-disant valeur de retour ? MIT nous l'a simplement affichée à l'écran automatiquement. En C, nous devons écrire un peu plus de code pour accéder à cette valeur de retour. Et la façon dont nous faisons cela est sur le côté gauche de cette ligne de code, nous trouvons un nom pour la valeur de retour. Vous pouvez l'appeler comme vous voulez. Mais answer est un bon équivalent de ce que MIT a fait. Vous pourriez l'appeler plus génériquement x ou y ou z. Mais ce n'est pas vraiment utile. Et donc les informaticiens, contrairement aux mathématiciens, ont tendance à utiliser des variables un peu plus verbeuses, comme le mot "answer". Mais en C, c'est, encore une fois, un peu plus bas niveau. Vous devez dire à l'ordinateur quel type de variable ce sera. Donc, je confonds un peu "variable" et "valeur de retour", mais ils sont utilisés de manière entrelacée. La fonction get_string, tout comme le bloc ask, renvoie une valeur. Si vous voulez en faire quelque chose, vous devez le mettre dans quelque chose appelé une variable, qui est désignée par du texte ici. Mais encore une fois, comme la semaine dernière, l'ordinateur ne sait pas s'il regarde des nombres, des caractères, des images ou des sons. Vous devez lui dire, en tant que programmeur, que les zéros et les uns qui sont en quelque sorte impliqués ici sous le capot de l'ordinateur sont, en fait, à traiter comme du texte, alias string. Maintenant, il manque encore une subtilité stupide à cette ligne de code. Quelqu'un sait-il, surtout si vous avez programmé - OK, vous avez tous programmé auparavant. Oui ? AUDIENCE : Point-virgule. DAVID J. MALAN : Point-virgule. Donc l'un des maux de tête de C et de nombreux langages est que vous devez explicitement terminer votre pensée pour que l'ordinateur sache que cette ligne de code est terminée. Et ce n'est pas un point, comme en anglais. C'est, en fait, un point-virgule. Maintenant, vous ne les utilisez pas partout. Nous verrons où vous les utilisez. Mais c'est aussi une erreur très courante, de négliger quelque chose de simple. Mais encore une fois, dans les semaines à venir, même si cela peut sembler très cryptique, avec la mémoire musculaire et la pratique, vous commencerez à voir ces choses instantanément, même si, pendant quelques jours, vous vous cognez la tête contre l'écran, pour ainsi dire, sans voir ce que les TFs et moi voyons beaucoup plus facilement. Alors allons-y et faisons ceci. Laissez-moi revenir à VS Code ici. Laissez-moi zoomer un peu. Et laissez-moi faire ceci. Je vais me débarrasser de mon utilisation unique de printf. Et je vais dire exactement la même chose - string answer = get string, guillemets, guillemets, "Quel est votre nom ?" point d'interrogation, espace, guillemets fermés, point-virgule. Et maintenant je veux imprimer cette réponse. Eh bien, laissez-moi faire ceci incorrectement, délibérément, pour le moment. Laissez-moi juste dire printf, guillemets, guillemets, "bonjour, answer," si je veux insérer "answer" et que je veux ajouter une nouvelle ligne à la fin, point-virgule. Alors laissez-moi essayer ceci. Mais il y a plusieurs erreurs maintenant dans mon code. Trébuchons délibérément dessus. Laissez-moi descendre dans ma fenêtre de terminal en cliquant en bas de l'écran. Laissez-moi exécuter "make hello" à nouveau. Entrée. Et, oh, mon dieu, il y a encore plus d'erreurs maintenant qu'avant, mais ce n'est pas un problème. Laissez-moi cliquer sur ce petit triangle ici, qui va juste zoomer sur la fenêtre de terminal. Donc, elle prend tout mon écran. Et généralement, tout ce que vous avez à faire est de trouver quelques mots-clés visuellement qui vous donnent un indice sur ce qui se passe. Ou, comme avant, vous pouvez toujours demander au canard CS50. Voici donc la commande que j'ai exécutée, "make hello". D'une manière ou d'une autre, cela a provoqué toutes ces erreurs. Lisez-les toujours de haut en bas, pas de bas en haut. Donc, de haut en bas, il y a un problème à la ligne 5, caractère 5 - utilisation de l'identifiant non déclaré string. Voulais-je dire standard in ? Non, non, non, je ne l'ai pas fait là. Et puis, également, deux erreurs générées. Trop d'erreurs [? sont faites. ?] Qu'ai-je fait de mal ? Eh bien, il s'avère que ce que je dois faire en haut de ce fichier - laissez-moi cliquer sur le triangle pour dézoomer - si je veux utiliser la fonction get_string pour obtenir une chaîne, je dois en fait inclure un autre fichier d'en-tête, qui s'appelle probablement "include cs50.h". Techniquement, n'importe quel ordre convient. J'ai tendance à alphabétiser parce que je sais donc où chercher alphabétiquement un certain fichier d'en-tête. Maintenant que c'est en place, laissez-moi exécuter à nouveau "make hello". Entrée. Et maintenant, nous sommes de retour en affaires. Aucun message d'erreur. Donc, même si vous avez peut-être plus d'erreurs que de code, il y a de fortes chances que l'ordinateur soit confus. Et cela pourrait être quelque chose de simple et une correction facile comme celle-là. Donc, pour être clair, standard io.h, parce que je l'inclus, je peux utiliser printf. cs50.h, je peux utiliser get_string parce que les gens qui ont inventé C et les gens qui ont inventé CS50 ont écrit ces deux fichiers, pour ainsi dire, respectivement. Très bien, malheureusement, même si le programme compile, cela ne signifie pas qu'il est correct. Cela signifie juste qu'il est syntaxiquement valide. C'est du code C valide. Si je vais exécuter "./hello" et appuyer sur Entrée maintenant, on me demandera mon nom. Je vais donc le taper - D-A-V-I-D. Et remarquez qu'il y a un espace à droite du point d'interrogation, comme promis. Entrée. Mais il dit juste "bonjour, answer", ce qui, bien sûr, n'est pas l'intention. Je veux qu'il dise "bonjour, David". Alors comment pouvons-nous faire cela ? Eh bien, dans Scratch, cela a pris quelques pièces de puzzle. Mais c'était assez simple. Si je voulais dire la combinaison de deux phrases, "bonjour" et quelque chose d'autre, je les ai jointes puis j'ai passé cette sortie à l'entrée de say. En C, ce sera un peu différent ici juste parce que c'est un vieux langage et c'est comme ça que ça se fait. Toujours utiliser printf car c'est la même chose que say. J'ai mes parenthèses. J'ai mon point-virgule. C'est bon. Mais à l'intérieur, c'est là que printf est différent. Si vous voulez dire quelque chose suivi de quelque chose d'autre, dans le monde de C, vous avez tendance à utiliser des espaces réservés. Donc vous ne joignez pas simplement les choses comme nous le ferons en Python et dans d'autres langages. Vous dites au compilateur, donnez-moi le mot "bonjour", virgule, et puis quelque chose d'autre. Et le pourcentage s signifie, mettez une autre chaîne ici. C'est un peu comme laisser un espace réservé dans votre code ou un modèle où vous allez réellement insérer des valeurs. Maintenant, si c'est ce que je veux afficher, j'utilise toujours mes guillemets, comme avant. Et je pourrais, en fait, avoir une barre oblique inverse n si je veux déplacer le curseur à la ligne suivante. Mais c'est là que printf est un peu différent. Contrairement à say, qui prenait une entrée, printf est un peu comme join. Il peut prendre deux entrées ou plus si vous le souhaitez. Vous devez simplement les séparer par une virgule. Donc beaucoup
comme le bloc "join" a deux ovales ici qui sont initialement blancs -- pomme et banane -- jusqu'à ce que nous ayons glissé et déposé "answer" dessus, printf -- et vraiment n'importe quelle fonction en C -- si vous voulez passer plusieurs entrées, c'est bien si elles sont prises en charge. Séparez-les simplement par des virgules. Il n'y a pas de parenthèses multiples. Il n'y a pas d'ovales multiples. Séparez-les simplement par des virgules. Et remarquez maintenant un point de confusion potentiel. Qu'est-ce qui est différent entre cette virgule et celle-ci, instinctivement ? Une sorte de détail mineur, mais important. Oui ? AUDIENCE : Intérieur et extérieur. DAVID J. MALAN : Donc, l'un est à l'intérieur, l'autre est à l'extérieur. Donc, celui qui est à l'intérieur des guillemets est littéralement la virgule grammaticale anglaise que vous voulez que l'humain voie. Celui qui est ici à l'extérieur est une chose en C qui sépare la première entrée de cette fonction printf de la seconde. Strictement parlant, vous n'avez pas besoin d'un espace ici. Mais c'est une bonne pratique, stylistiquement, de séparer vos arguments par des espaces simples, comme je l'ai fait ici. Alors, permettez-moi de continuer et de faire quelque chose avec ça maintenant. Laissez-moi revenir à mon code C ici. Je vais effacer ma fenêtre de terminal juste pour me débarrasser de cette distraction. Et maintenant, je vais changer "answer" en "%s". Et puis, en dehors des guillemets doubles sur la ligne 7, je vais faire ", "answer"". Et ensuite, après qu'il se soit sauvegardé automatiquement, je vais retourner à ma fenêtre de terminal. Et juste pour faire une autre erreur délibérée, "./hello". Entrée. "Quel est votre nom ? David." Entrée. Ça ne marche toujours pas. Mais pourquoi ? Je dois toujours le recompiler. Donc encore une fois, prenez l'habitude, lorsque vous modifiez votre code, vous devez le recompiler pour obtenir un nouveau code machine dans le fichier "hello". Alors, faisons-le à nouveau. "make hello." Aucune erreur, c'est bien. "./hello." Entrée. "Quel est votre nom ?" encore. D-A-V-I-D. Et maintenant, "hello, David." Donc encore une fois, beaucoup de choses ici sont encore cryptiques. Mais cela va commencer à suivre des schémas comme celui-ci. Les fonctions, comme en cours de maths, f(x), s'écrivent nom de la fonction, parenthèses, entrée, virgule, entrée, virgule, entrée, autant que vous en ayez. Elles vont suivre ces schémas. Mais remarquez aussi, sur les lignes 6 et 7, j'ai terminé chacune de mes pensées par un point-virgule. Alors, quelles sont les autres commandes que vous pouvez exécuter dans votre fenêtre de terminal, à part quelque chose comme ls ? Eh bien, il s'avère qu'il y en a un tas. ls, bien sûr, était simplement l'abréviation de "list", qui vous montre les fichiers dans votre dossier actuel. Mais il y a aussi cd pour "change directory", qui est l'équivalent en ligne de commande de double-cliquer sur un dossier pour l'ouvrir dans un environnement graphique. Il y a cp, qui est l'abréviation de "copy", qui vous permet de faire une copie d'un fichier ou d'un dossier. Il y a make dir, "mkdir", qui est l'abréviation de "make directory", qui est la façon dont vous pouvez créer un nouveau dossier. Il y a mv, qui est l'abréviation de "move", qui vous permettrait de déplacer un fichier ou un dossier d'un endroit à un autre ou simplement de renommer l'un d'eux avec un nom différent. Il y a rm, qui est l'abréviation de "remove". Et il y a "rmdir", qui est l'abréviation de "remove directory". Alors, en fait, jouons avec quelques-unes de ces commandes. Laissez-moi revenir à VS Code ici. Laissez-moi ouvrir mon explorateur de fichiers. Et rappelez-vous qu'à ce stade, j'ai deux fichiers, hello.c, qui contient mon code source, et ensuite hello, qui contient mon code machine, le programme exécutable que j'ai précédemment généré en exécutant make. Eh bien, laissez-moi proposer que je souhaite préparer à garder tous mes fichiers et dossiers très ordonnés. Donc, pour chaque programme que j'écris ou pour chaque problème d'un jeu de problèmes que j'écris, peut-être que je veux stocker mes fichiers pertinents dans un dossier spécifique pour ce problème. Supposons donc que je veuille mettre hello.c dans un dossier, autrement appelé répertoire, appelé hello. Eh bien, je ne peux pas le faire tout de suite car j'ai déjà un programme appelé hello. Alors, laissez-moi utiliser l'une de ces nouvelles commandes. rm espace hello supprimera ou retirera hello de mon répertoire actuel. Alors, je vais appuyer sur Entrée. On me demandera de confirmer avec y pour oui ou n pour non. "Supprimer le fichier régulier 'hello' ?" Je vais appuyer sur y et entrer. Et lorsque j'appuie sur Entrée, regardez en haut à gauche de mon écran, le fichier hello semblera disparaître. Voilà, il a disparu. Alors maintenant, je vais utiliser une commande différente. Laissez-moi faire mkdir pour "make directory". Je vais appeler le répertoire lui-même hello. Et regardez encore, en haut à gauche, ce qui se passe. Entrée. Maintenant, j'ai non pas un fichier mais un dossier appelé hello. Et dans cette interface graphique, le fait que ce soit un dossier est indiqué, un, par son icône et, deux, par ce petit triangle pointant vers la droite, ce qui signifie que je peux l'étendre pour voir ce qu'il y a dedans. Et en fait, si je le fais, je verrai, bien sûr, qu'il n'y a rien dedans car nous venons de le créer. Très bien, eh bien, que faire si je veux déplacer hello.c dans le nouveau dossier hello ? Eh bien, je pourrais, tout comme sur macOS ou Windows. Je pourrais, en fait, dans mon explorateur de fichiers, cliquer et glisser l'un dans l'autre. Mais faisons cela entièrement dans la fenêtre du terminal. Alors, laissez-moi faire ça. Laissez-moi déplacer, ou mv pour faire court, mon fichier appelé hello.c dans une nouvelle destination, hello. Et je peux, facultativement, mettre une barre oblique à la fin de "hello" juste pour rendre super clair que c'est un répertoire. Mais ce n'est pas strictement nécessaire. Mais si je dis mv hello.c hello, avec des espaces entre les deux, en supposant que hello existe en tant que dossier, regardez ce qui se passe en haut à gauche maintenant. C'est un peu plus subtil, mais hello.c va se déplacer à l'intérieur du dossier hello dès maintenant. Et en effet, il est juste légèrement plus indenté. Mais remarquez si je ferme le dossier hello, remarquez qu'il semble avoir disparu car hello.c est maintenant à l'intérieur de ce dossier. Bien sûr, si je l'ouvre, je le verrai à nouveau. Si je retourne à ma fenêtre de terminal et que je tape ls pour "list", maintenant je ne vois pas hello.c. Et je ne vois plus de programme exécutable. Mais je vois hello. Et la barre oblique ici rend super clair pour moi, l'utilisateur, que c'est bien un dossier. Alors, comment puis-je aller dans ce dossier ? Eh bien, je peux évidemment utiliser l'interface graphique à gauche et cliquer et développer et voir ce qui se passe. Mais il n'y a pas de connexion directe entre l'explorateur de fichiers en haut à gauche et ma fenêtre de terminal en bas à droite. Plutôt, ce sont juste deux façons différentes d'explorer le système sous-jacent. Donc, si je veux changer ma fenêtre de terminal dans ce nouveau répertoire, je peux faire cd pour "change directory", hello, puis Entrée. Et maintenant, remarquez que l'invite de ma fenêtre de terminal change légèrement. Il y a toujours un signe dollar, qui indique, tapez mes commandes ici. Mais avant ce signe dollar, juste pour que j'aie un rappel, des sortes de miettes de pain qui me rappellent visuellement dans quel dossier je suis maintenant, je vois que je suis à l'intérieur de hello. Si je tape maintenant ls, je devrais voir le fichier que je m'attends à trouver là-bas, qui est en effet hello.c. Maintenant, supposons que je veuille essayer certaines de ces autres commandes. Et supposons que je veuille peut-être renommer ce fichier. Je veux vraiment que ce fichier s'appelle quelque chose d'autre. Alors peut-être que je ferais quelque chose comme ça, mv hello.c espace, puis un nouveau nom pour le fichier. Eh bien, peut-être que je veux faire -- disons que c'est une ancienne version de mon code, parce que je veux juste recommencer avec quelque chose de nouveau. Alors je pourrais faire quelque chose comme ça, mv hello.c old.c. Et regardez ce qui se passe en haut à gauche. hello.c, bien sûr, est renommé via la commande move. Donc je peux utiliser move pour déplacer un fichier dans un dossier. Ou je peux l'utiliser pour renommer un fichier ou un dossier, comme je viens de le faire ici. Maintenant, supposons que je veuille annuler cela. Eh bien, je ne peux pas simplement taper annuler. Je ne peux pas simplement appuyer sur Control C. Mais je peux faire l'inverse, en effet. mv old.c hello.c changera maintenant, en haut à gauche, cela redeviendra ce fichier. Si je veux faire une copie de ce fichier, peut-être comme sauvegarde réelle car je suis vraiment content de cette version et j'ai peur de la casser, eh bien, je pourrais faire cp pour faire court. Je peux ensuite faire hello.c. Et ensuite, je peux faire quelque chose comme backup.c, ou n'importe quel autre nom de fichier. Je prends soin d'utiliser la même extension de fichier pour que si j'ouvre ce fichier plus tard, il s'ouvre et soit mis en surbrillance et colorisé de la même manière. Mais regardez ce qui se passe maintenant en haut à gauche. Lorsque j'appuie sur Entrée, j'ai maintenant deux fichiers dans ce dossier hello. Et en effet, si je tape ls maintenant, je peux voir exactement la même chose. Donc, pour faire court, il y a toute cette liste de commandes, et même plus que celles-ci, qui vous permettent de manipuler le système sous-jacent exactement de la même manière que vous et moi avons probablement fait pendant des années en utilisant une souris, en pointant et en cliquant et en double-cliquant. Mais pour l'instant, annulons tout cela car je n'ai pas vraiment écrit autant de programmes aujourd'hui. Et je vais garder les choses simples aujourd'hui et tout garder dans mon même dossier. Alors, annulons tout cela. Laissez-moi maintenant supprimer backup.c car cela ne me concerne pas particulièrement. On me demandera de confirmer. Ensuite, laissez-moi déplacer hello.c hors de ce dossier et dans le dossier d'origine. Et, conceptuellement, le dossier d'origine est ce que nous appellerions le dossier parent, le dossier qui contient ce dossier hello. Et la façon dont vous pouvez spécifier le dossier parent, comme remonter d'où vous venez, est avec deux points. Donc un seul point, comme nous l'avons vu "./hello", "./a.out" signifie exécuter un programme dans ce répertoire, point. Mais deux points fait référence à votre répertoire parent. Alors regardez ce qui se passe en haut à gauche lorsque je déplace ce fichier hello.c hors de ce dossier. Il se décale un peu vers la gauche pour indiquer qu'il n'est plus dans ce dossier. Je vais faire cd deux points, ce qui me ramènera à mon dossier parent. Ou, encore plus utile, surtout si vous vous sentez confus ou perdu quelque part dans vos dossiers, vous pouvez simplement taper cd et rien, et cela vous ramènera à ce dossier d'origine, peu importe où vous êtes. C'est donc un raccourci agréable. Et c'est une bonne façon d'annuler toute confusion que vous auriez pu vous causer. Enfin, supprimons le répertoire hello avec rmdir hello, Entrée. Et cela disparaît maintenant en haut à gauche, également. Maintenant, ce à quoi j'ai fait allusion ici, où j'avais mon fichier hello.c dans un dossier et où je déplaçais des choses, renommais des choses et faisais des sauvegardes, n'est pas strictement nécessaire car il existe en fait d'autres fonctionnalités dans VS Code avec lesquelles vous êtes invité et encouragé à jouer. En fait, si je vais dans ma soi-disant chronologie en bas de mon explorateur de fichiers ici, vous pouvez en fait voir qu'il y a eu des sauvegardes automatiques effectuées au fil du temps de ce fichier. Donc, si vous cliquez, cliquez, cliquez sur ces sauvegardes, vous pouvez en fait voir différentes versions de ce même fichier légèrement dans le passé, ce qui pourrait vous épargner la peine de créer manuellement des fichiers. Et en fait, dans le monde du développement logiciel et de l'industrie, il existe des outils standard, très similaires dans l'esprit à ce que nous avons utilisé GitHub, qui vous permettent manuellement de créer différentes versions de votre code afin que vous puissiez suivre proactivement tous les changements que vous avez apportés sans renommer manuellement les choses comme vous le feriez typiquement sur votre propre Mac ou PC. Très bien, laissez-moi effacer ma fenêtre de terminal et demander s'il y a des questions. Oui, ici. AUDIENCE : Que se passe-t-il si vous aviez un type autre que [INAUDIBLE] ? DAVID J. MALAN : Oui, très bonne question. Si nous avions quelque chose d'autre qu'une chaîne de caractères, si nous avions un entier, utiliseriez-vous toujours %s ? Non, vous utiliseriez autre chose. Et, en effet, %i est ce que nous allons utiliser. Et nous allons en fait faire cela -- parfaite transition -- vers d'autres types que C a réellement. Jusqu'à présent, nous avons appelé une chaîne de caractères littéralement une chaîne. Et c'est courant dans de nombreux langages de programmation, y compris Python et JavaScript. Les "chaînes" dans le monde de la programmation signifient simplement du texte, qu'il s'agisse de zéro ou plusieurs caractères. Mais C a d'autres types de données, dont quelques-uns que nous allons effleurer aujourd'hui mais que vous utiliserez davantage au fil du temps. Nous avons déjà vu string, par exemple, qui est en effet une chaîne de caractères. Mais concentrons-nous aussi sur un entier. Soit dit en passant, il existe d'autres types. Il y a des valeurs booléennes, comme vrai ou faux. Il y a des chars, qui sont des caractères uniques au lieu de phrases ou de phrases complètes. Il y a des doubles et des floats, qui sont des nombres réels, quelque chose avec une virgule, l'équivalent de fractions. Et il y a des longs, qui sont des entiers mais des entiers plus longs, des entiers encore plus grands que vous ne pourriez taper par défaut. Concentrons-nous donc sur un int car tant de programmes informatiques manipulent des nombres d'une manière ou d'une autre. Alors, que pouvons-nous faire avec cela ? Eh bien, si nous voulons pouvoir obtenir un entier, heureusement, la bibliothèque de CS50 ne vient pas seulement avec get_string mais aussi avec get_int. C'est donc une troisième fonction que nous utilisons maintenant en C. Et nous devons connaître ce qu'on appelle généralement les codes de format. Donc, ce placeholder que j'ai appelé auparavant, %s, est en effet pour une chaîne. Si nous voulons placer un entier à l'intérieur de quelque chose que nous imprimons à l'écran, nous allons, en fait, utiliser %i à la place. Alors, utilisons maintenant ces éléments constitutifs, get_int et %i, pour obtenir réellement des nombres d'une manière ou d'une autre pour résoudre un problème. Eh bien, quel problème pourrions-nous résoudre ? Introduisons un autre concept à partir de zéro et de la programmation plus généralement connu sous le nom de conditionnelles, comme ces fameux embranchements. Si quelque chose est vrai, faites ceci. Sinon, faites peut-être cette autre chose. Donc, dans Scratch, nous aurions pu avoir un ensemble de pièces de puzzle qui ressemblaient à ceci. Si x est inférieur à y, alors dites, ou faites dire au chat, x est inférieur à y. Donc, un programme un peu stupide. Mais cela démontre simplement que nous avons deux variables, x et y. Dans le contexte de Scratch, nous les comparons avec une expression booléenne. Nous utilisons une conditionnelle pour ensuite dire conditionnellement ou ne pas dire cette phrase ici, en fonction de si cette question a une réponse vraie ou fausse, oui ou non. En C, cela ne ressemble pas du tout à cela. C'est un peu plus cryptique. Mais vous dites littéralement "if". Vous utilisez des parenthèses, similaires aux fonctions. Mais de manière déroutante, par convention, vous mettez un espace après le mot "if". Donc, vous ne mettez pas d'espaces après les noms de fonctions. Vous mettez des espaces après des mots comme "if". Et vous utilisez les parenthèses pour faire apparaître cette forme étrange ressemblant à un trapèze. Donc, il n'y a pas de touches réelles qui font apparaître cela. Donc C utilise des parenthèses, comme la plupart des langages. Et puis il y a ces accolades étranges, que, du moins en anglais, nous n'utilisons pas si souvent. Mais elles sont là sur votre clavier, en anglais ou autrement. Et elles nous permettent essentiellement de créer cette forme de câlin pour la pièce de puzzle. Tout ce qui se trouve à l'intérieur de ces accolades sera équivalent à tout ce qui se trouve à l'intérieur de ce câlin jaune qui attrape une ou plusieurs pièces à l'intérieur. Alors, que mettons-nous à l'intérieur ? Eh bien, cette partie est simple -- printf, guillemets, guillemets, "x est inférieur à y" \n point-virgule. Donc rien de nouveau ici. La seule partie de nouveau code est cette construction "if" à la place. Et si vous avez un "if-else", donc un embranchement à deux voies ? C'est à quoi cela ressemblait dans Scratch. Même question -- si x est inférieur à y, alors dites x est inférieur à y. Sinon, dites x n'est pas inférieur à y. En C, le code sera configuré initialement comme ceci, donc deux ensembles d'accolades pour représenter cette paire de barres jaunes et cette paire de barres jaunes. Et ce qui est à l'intérieur -- indenté, pas moins, tout comme notre pseudocode la semaine dernière -- ce sont deux printf -- x est inférieur à y, x n'est pas inférieur à y. C'est donc tout. Donc, la seule nouveauté ici est maintenant le mot-clé "else", qui n'a pas besoin de parenthèses car vous dites simplement, sinon, faites cette autre chose. Mais et si c'est un embranchement à trois voies ? Et nous nous arrêterons après cela. Voici un embranchement à trois voies dans Scratch. Si x est inférieur à y, alors dites ceci. Sinon, si x est supérieur à y, dites ceci. Sinon, si x est égal à y, alors dites ceci. C'est donc un peu plus précis car nous gérons maintenant l'égalité, pas seulement le supérieur ou l'inverse. En C, cela ressemblera à ce qui précède. Mais nous ajoutons cet élément ici. Et à première vue, surtout si vous n'avez jamais programmé auparavant, cela ressemble à si je suis idiot et que j'ai fait une faute de frappe. Qu'est-ce qui semble faux ? Il y a deux signes égal -- pas une faute de frappe. Donc, il s'avère, rappelez-vous d'avant, lorsque nous avons utilisé le signe égal la première fois, nous l'avons utilisé dans le contexte d'obtenir une valeur de retour d'une fonction, comme la fonction get_string m'a renvoyé la réponse de l'utilisateur. Donc, malheureusement, parce que les humains il y a des décennies ont décidé, hé, utilisons le signe égal pour assigner une valeur de retour du côté droit d'une ligne de code au côté gauche, nous nous sommes un peu mis dans le coin et nous nous sommes dit, oh, zut, que faisons-nous lorsque nous voulons réellement tester l'égalité de deux valeurs à gauche et à droite ? Donc, ce que la plupart des langages, y compris C, font, c'est utiliser des doubles signes égal. Donc vous dites double égal ou égal égal ou quoi que ce soit. Mais c'est, en fait, syntaxiquement correct. Qu'est-ce qui se trouve à l'intérieur de ces trois ensembles d'accolades ? Même idée -- printf, printf, printf en fonction de la phrase anglaise que vous voulez imprimer. Donc, ce code, à la fois dans Scratch et en C, je prétends qu'il est correct. Il ne fonctionnera pas car nous avons toujours besoin de l'autre chose, l'équivalent de "quand le drapeau vert est cliqué". Mais hors contexte, ce code est correct. Mais il y a une faiblesse subtile dans la conception. Et nous en parlerons beaucoup cette semaine et au-delà. "Correctness" signifie simplement que le code fait ce qu'il est censé faire. La conception est plus subjective. Comment avez-vous bien écrit votre argument dans un article en anglais, comment avez-vous bien écrit votre code, c'est la conception. Ce code n'est pas aussi bien conçu qu'il pourrait l'être car je fais plus de travail que nécessaire. Oui, au fond. AUDIENCE : Vous n'avez pas besoin de [INAUDIBLE]. DAVID J. MALAN : Oui, je n'ai pas besoin de x == y. Mais pourquoi, logiquement ? AUDIENCE : Parce que [INAUDIBLE] [? il n'y a pas besoin. ?] [INAUDIBLE]. DAVID J. MALAN : Exactement, c'est juste une chose mathématique. Soit x est inférieur à y, soit il est supérieur à y. Ou la troisième et dernière option est qu'ils doivent être égaux. C'est donc subtil, mais pourquoi vous donner la peine d'écrire une ligne de code et d'attendre que l'ordinateur exécute une ligne de code qui va simplement répondre à une question que logiquement vous auriez déjà pu conclure ? Parce que si x n'est pas inférieur à y et x n'est pas supérieur à y, alors, mon Dieu, imprimez simplement x est égal à y parce que vous savez, à ce moment-là, logiquement c'est vrai. Vous n'avez pas besoin de perdre votre temps ou celui de l'ordinateur à poser une troisième question inutilement. En réalité, ce n'est pas un gros problème. Personne ne remarquera dans le monde réel sur un Mac ou un PC qu'il y a cette ligne de code supplémentaire. Mais c'est une mauvaise habitude. Gardez les choses simples. N'écrivez pas de code qui n'a pas besoin d'être là si, logiquement, vous pouvez conclure le contraire. Alors, en fait, nettoyons cela à la fois dans Scratch et en C. Je peux resserrer cela, pour ainsi dire, utiliser moins de code ici, moins de code ici. Et honnêtement, même statistiquement, moins j'écris de code, moins je suis susceptible de faire des erreurs. Donc, cela aussi, est probablement un avantage net global. Écrire moins de code est généralement mieux que d'écrire plus de code, pas différent des essais en anglais, peut-être. Très bien, des questions sur cette fonctionnalité de C, les conditionnelles et cette syntaxe ? Oui ? AUDIENCE : [INAUDIBLE] DAVID J. MALAN : Oh, une très bonne question. Et, oui, vous sautez aux conclusions. Il existe d'autres moyens de résoudre des problèmes comme ceux-ci. Et la question était, pour résumer, quand utiliser "if, else, if, else" par rapport à ce qu'on appelle une instruction switch. Plus à ce sujet une autre fois. Mais cela sera vrai, en général, en programmation, pas seulement en C, pas seulement en Scratch, mais dans tous les langages. Il y aura plusieurs, des dizaines, des centaines, une infinité de façons de résoudre des problèmes. Parmi les choses que nous allons vous enseigner, cependant, il y a en effet comment faire les choses bien ou mieux que vous ne le feriez autrement. Et nous vous présenterons éventuellement une autre fonctionnalité du langage qui peut même simplifier ce code. Alors, pour l'instant, utilisons cela. Alors, laissez-moi aller à nouveau à VS Code. Je vais maintenant effacer ma fenêtre de terminal ici. Je vais fermer l'onglet hello.c juste pour que -- nous allons créer un nouveau programme. Et faisons quelque chose d'un peu simple en utilisant un opérateur, pour ainsi dire. Et je n'ai pas utilisé ce mot par son nom. Mais il s'avère qu'il existe de nombreux opérateurs livrés avec C, tout comme de nombreux opérateurs livrés avec Scratch, pour faire l'affectation ou inférieur à ou inférieur ou égal à, supérieur à, supérieur ou égal à, réellement égal à, différent de. Maintenant, certains d'entre eux sont un peu cryptiques. Mais il n'y a pas de touche facilement trouvable sur votre clavier anglais américain, du moins, où vous pouvez faire inférieur ou égal à ou supérieur ou égal à. Donc, ce que la plupart des langages de programmation font, c'est que vous n'utilisez pas un symbole spécial où il y a un crochet angulaire suivi d'une ligne en dessous. Vous utilisez en fait deux caractères. Donc, supérieur ou égal est littéralement ceci, ceci. Inférieur ou égal est littéralement ceci, ceci. Nous avons déjà vu que égal est ceci, ceci. Et différent de, c'est utiliser un point d'exclamation. Donc, ceci aussi, c'est une chose en programmation. Utiliser le point d'exclamation, prononcé "bang", est la façon dont vous inversez, logiquement, certaines choses. Donc, "bang equals" ou "not equals" est la façon dont vous exprimeriez exactement cette idée. C'est juste un symbole sur le clavier que certains humains ont décidé, utilisons celui-ci pour inverser l'idée. Mais nous aurons besoin d'une autre chose pour ce programme, spécifiquement des variables, que nous avons déjà utilisées car, dans Scratch, nous en avons eu une gratuitement. Nous avions cette variable "answer" qui stockait la valeur de retour du bloc "ask". Mais considérons, en général, comment vous pouvez -- et probablement l'avez fait pour le jeu de problèmes 0 -- utiliser une variable de votre propre chef, comme pour suivre un compteur ou un score ou quelque chose de similaire. Dans Scratch, si vous voulez créer une variable appelée "counter", vous pouvez la définir égale à une valeur initiale, comme 0. En C, ce code ressemblera à ceci. Vous écrivez littéralement le nom que vous voulez donner à la variable, puis un signe égal, puis la valeur que vous voulez donner à cette variable. Et parce que le signe égal est l'opérateur d'affectation, il se comportera essentiellement de droite à gauche et copiera le 0 dans "counter". Mais ce n'est pas suffisant pour C. Rappelez-vous que vous, le programmeur, devez dire à l'ordinateur, est-ce bien un nombre ? Est-ce une lettre ? Est-ce une image ? Est-ce un son ? Vous devez dire à l'ordinateur que c'est un entier, sinon écrit "int" pour faire court en C. Mais il y a un autre détail stupide qui manque, c'est maintenant -- point-virgule pour terminer la pensée ici. Mais cela est alors équivalent à ceci dans Scratch. Faisons-en un autre. Dans Scratch, si vous vouliez incrémenter le compteur, c'est-à-dire y ajouter 1, vous pouviez littéralement utiliser cette pièce de puzzle ici et spécifier que vous vouliez ajouter 1. En C, cela ressemblera à ceci -- counter = counter + 1 ;. Maintenant, à première vue, cela semble être un paradoxe. Comment "counter" peut-il être égal à "counter" + 1 ? Je ne peux pas rendre cette expression mathématique vraie. Mais ce n'est pas des mathématiques dans ce cas. Le signe égal unique est une affectation. Donc, cela signifie prendre la valeur actuelle de "counter", quelle qu'elle soit, y ajouter 1, puis copier cette valeur de droite à gauche dans la même variable, la changeant ainsi de 1 à 2, de 2 à 3, et ainsi de suite. Ceci, cependant, est si courant en programmation, de pouvoir incrémenter ou même décrémenter des nombres de un, deux ou plus, que vous pouvez le resserrer comme ceci. C'est exactement la même chose -- un peu plus rapide à taper, vous fait gagner des frappes, peut-être moins de chances d'erreur. Counter += 1 ; est la même idée. Mieux encore, c'est si courant en C et C++ et Java qu'il existe une troisième façon de faire cela, pour mon commentaire précédent sur la résolution de problèmes de différentes manières. La façon la plus canonique, la plus populaire est probablement de dire simplement counter++ ; qui, littéralement, automatiquement, ajoute 1 à cette valeur. Cela ne fonctionne que pour 1. Si vous voulez faire 2 ou 3 ou un autre incrément, vous devez utiliser l'une des autres approches. Mais cela fait simplement la même chose que ceci. Et si vous voulez l'inverser pour -1, vous changez le ++ en -- à la place. Donc encore une fois, juste de petites choses que nous verrons et apprendrons au fil du temps. Invariablement, vous devrez les rechercher ou consulter les notes ou regarder les diapositives de cours. Mais avec le temps, cela deviendra familier si vous ne l'êtes pas déjà. Alors, considérons logiquement comment nous pourrions implémenter cela dans le code. Revenons à VS Code ici. Et laissez-moi proposer que nous créions un programme appelé compare.c dont le but est simplement de comparer quelques valeurs. Je vais proactivement, sur la base de la discussion précédente, inclure la bibliothèque CS50 dès le départ. Je vais inclure standard io.h dès le départ. Je peux donc utiliser get_int et printf respectivement. Je vais juste, par foi, taper int main(void). Et aujourd'hui, nous n'expliquerons pas ce que cela fait. Plus à ce sujet à venir. Pour l'instant, supposez que c'est comme, quand le drapeau vert est cliqué. Mais dans ce programme, faisons quelques choses. Déclarons un entier appelé x et attribuons-lui la valeur de retour de get_int. Et gardons les choses simples. Demandons à l'utilisateur non pas quel est son nom, mais "Quel est x ?", point d'interrogation, point-virgule. Maintenant, pour que nous ayons quelque chose à comparer, faisons-le à nouveau mais avec y. int y = get_int("Quel est y ? ");. Et je laisse encore un espace juste visuellement pour que le curseur se décale un peu, suivi d'un point-virgule. À ce stade de l'histoire, mes utilisateurs seront invités pour x et y respectivement. Faisons quelque chose avec ces valeurs. Que diriez-vous si x est inférieur à y, alors allez-y et imprimez, "x est inférieur à y" \n, fermez les guillemets, point-virgule. Très bien, et laissez-moi cacher ma fenêtre de terminal juste un instant. C'est un programme de 13 lignes pour le moment. Mais vraiment, ce sont cinq ou six lignes intéressantes. Le reste a été copié/collé de programmes précédents. Remarquez quelques détails. Premièrement, j'ai bien utilisé mes accolades ici. Et remarquez, si vous mettez en surbrillance des lignes, vous verrez en fait de petits points qui peuvent vous aider à vous assurer, oh, il y a bien quatre espaces ici. J'ai indenté tout comme nous l'avons fait la semaine dernière avec le pseudocode. Strictement parlant, ce n'est pas nécessaire. Mais il sera beaucoup plus facile de lire votre code si vous faites tout ce travail d'espacement, pour ainsi dire, que si vous écrivez et nous soumettez, comme devoir, un programme qui ressemble à ceci, ce qui rendra beaucoup, beaucoup plus difficile pour l'humain de le lire, pour vous de le lire, vos collègues dans le monde réel de le lire. Mais l'ordinateur ne s'en souciera pas vraiment. En fait, soit dit en passant, l'un des outils que nous avons intégrés à VS Code pour CS50 est ce bouton en haut appelé style50. C'est un programme que nous avons effectivement écrit et qui vous donnera des suggestions sur la façon d'améliorer le style de votre code afin qu'il ressemble à la manière dont les programmeurs l'écriraient généralement. Soit dit en passant, le monde de l'informatique est semé de débats religieux, pour ainsi dire, sur l'apparence du code. Et les gens dans le monde réel auront des disputes vraiment stupides sur le nombre d'espaces à utiliser pour l'indentation et sur quelles lignes le code doit aller, etc. Généralement, dans le monde réel ou dans un cours, il existe un guide de style officiel que quelqu'un déclare autocratiquement, c'est ainsi que tout le monde devrait écrire son code afin que le code de tout le monde dans l'entreprise ou le cours soit le même. Mais vous constaterez, dans le monde réel, que des personnes raisonnables seront en désaccord. Lorsque vous cliquez sur style50, il sera formaté comme nous le recommandons nous-mêmes en CS50. Et en fait, laissez-moi zoomer ici. Et cela ressemble un peu à du cryptique à première vue. Mais à gauche se trouve le code que je viens d'écrire et que j'ai gâché en supprimant tout cet espacement. À droite se trouve la façon dont le code devrait ressembler s'il est bien stylisé. Donc, alors que la correction concerne le fait que le code fonctionne comme il est censé le faire, la conception concerne la qualité de l'écriture de ce code. Est-il efficace ? Avez-vous pris de bonnes décisions ? Le style est purement esthétique. Est-il lisible ? Suit-il une norme ? Un autre humain peut-il facilement le parcourir de haut en bas, de gauche à droite, et comprendre ce qui se passe ? Donc, ces surlignages verts disent, veuillez ajouter de l'espace ici. Et donc je peux en fait changer mon code pour qu'il corresponde. Sur le côté gauche ici, si je réalise, oh, mon code a l'air assez laid, regardez à la ligne 6 à gauche. Lorsque j'appuie sur la barre d'espace deux -- oops, désolé -- à gauche, 1, 2, 3, 4, remarquez que le côté droit commence à être plus satisfait de mon code en supprimant les indicateurs verts. Et je peux faire 1, 2, 3, 4. Cela a réglé ça. Ici, je peux faire 1, 2, 3, 4. Je peux déplacer ceci sur sa propre ligne en appuyant sur Entrée. Et vous savez quoi, si cela prend trop de temps, une fois que vous avez pris l'habitude des choses, vous pouvez simplement appliquer les modifications. Il vous donnera automatiquement les suggestions. Et nous avons terminé et nous sommes en route. Mais pour la pratique, je prendrais l'habitude de faire les choses manuellement jusqu'à ce que cela devienne ennuyeux et fastidieux, auquel cas, vous pourriez aussi bien automatiser le processus en un seul clic. Très bien, alors exécutons ce code. Je vais ouvrir ma fenêtre de terminal à nouveau et l'effacer pour plus de clarté. Je vais exécuter make compare et espérer que je n'ai pas fait d'erreurs. Je ne semble pas encore en avoir -- "./compare." Et maintenant, remarquez que l'on me demande x. Tapez 1. Pour y, tapez 2. Entrée. Et x est inférieur à y. Faisons une petite vérification de bon sens, pour ainsi dire. Relançons-le -- c Quel est x ? Faisons 2 cette fois ; 1 pour y. Et cette fois, il n'a rien dit. C'est donc à prévoir car je n'avais pas d'embranchement à deux ou trois voies. La seule fois où ce code devrait dire quelque chose, c'est si, en effet, x est inférieur à y. Donc, pour ceux d'entre vous qui pourraient être plus visuels en matière d'apprentissage, voici un organigramme qui représente exactement le même programme. Si vous le lisez de haut en bas, vous commencez le programme avec "./compare." On vous demande ensuite x et y. Et on vous pose cette question : x est-il inférieur à y ? Et le fait que ce soit un losange signifie que c'est une expression booléenne, une question que l'ordinateur se pose. Si la réponse à cette question est vraie, alors, "x est inférieur à y" est imprimé. Et le programme s'arrête. Sinon, si x n'est pas inférieur à y, comme dans le deuxième scénario, la réponse est, bien sûr, fausse, et rien d'autre ne se passe. Mais nous pouvons développer cet arbre, pour ainsi dire, en ajoutant un peu plus de code. Alors, faisons-le ressembler au deuxième exemple Scratch. Si je reviens ici, il n'est pas difficile de dire simplement, sinon, si x n'est pas inférieur à y, disons-le. "x n'est pas inférieur à y" \n, fermez les guillemets. Laissez-moi maintenant relancer make compare. Entrée. "./compare," Entrée. Et encore une fois, je ferai le deuxième exemple -- 2, qui est plus grand, et 1, qui est plus petit. Et cette fois, je verrai x n'est pas inférieur à y. Si, alors, nous regardions non pas cet organigramme mais un organigramme légèrement plus grand, vous pouvez le visualiser ainsi. Tout sur le côté gauche de cette image est le même. Mais s'il n'est pas vrai que x est inférieur à y, la réponse est donc fausse. Cette fois, nous disons, "x n'est pas inférieur à y." Et nous pouvons le faire évidemment une dernière fois juste pour bien faire comprendre le point. Si je retourne à mon code et que je compare encore plus méticuleusement ces trois valeurs, laissez-moi faire ceci. Alors, else -- hm, je ne veux pas d'un else en fait. Alors, faisons ceci -- else if x est supérieur à y, disons alors "x est supérieur à y" en anglais. Et ensuite, enfin, avoir un else qui dit printf "x est égal à y", fermez les guillemets, ou plutôt \n, fermez les guillemets, point-virgule. Donc, juste pour montrer tout cela à l'écran en même temps, c'est identique maintenant à cette version Scratch. C'est bien conçu car je ne pose pas la question de l'égalité inutilement. Si je retourne à ma fenêtre de terminal ici, efface l'écran, exécute make compare, Entrée, puis "./compare" à nouveau. Entrée. "Quel est x ?" Faisons 1. Faisons 2. "x est inférieur à y." Relançons-le -- "./compare." "Quel est" -- 2 et 1. "x est supérieur à y." Encore une fois -- "./compare." "Quel est x ?" 1. "Quel est y ?" 1. Et maintenant x est égal à y. Soit dit en passant, si je semble taper assez vite, vous pouvez en fait tricher avec votre clavier. Si vous allez en haut ou en bas, vous pouvez faire défiler toutes les commandes précédentes que vous avez tapées. C'est donc très utile. Si vous appuyez simplement sur haut, cela réécrira la commande précédente pour vous, auquel cas vous pouvez simplement dire Entrée. Ou il existe d'autres fonctionnalités sophistiquées intégrées à cet environnement de programmation. Si vous faites ./C-O-M et que vous vous ennuyez à taper le mot anglais entier, vous pouvez appuyer sur Tab pour la complétion automatique comme dans un navigateur Web. Et cela aussi, complétera automatiquement s'il trouve un fichier qui commence par ces lettres. Donc, de petites efficacités ici. Des questions alors sur le code ici ? Oui ? AUDIENCE : J'ai une question sur les bibliothèques. DAVID J. MALAN : Bien sûr. AUDIENCE : [INAUDIBLE] y a-t-il un inconvénient à inclure toutes les bibliothèques ? DAVID J. MALAN : Bonne question. Y a-t-il un inconvénient à simplement inclure toutes les bibliothèques comme nous l'avons vu dans les pages manuelles tout à l'heure ? La performance. Donc, en général, C est censé être un langage très efficace, tellement efficace que, même s'il a des décennies, il est toujours omniprésent de nos jours car il est si rapide. Il minimise donc le temps. Il minimise la consommation d'énergie. Il est donc toujours largement utilisé. Vous ralentiriez les choses si vous disiez au compilateur, au fait, donnez-moi toutes ces autres fonctions que je n'utiliserai jamais. Donc, en bref, ne faites pas cela car c'est inutile. Mais bonne question. D'autres questions sur ce que nous avons fait ici ? Oui, devant. AUDIENCE : [? Juste pour faire un suivi, ?] [? pourquoi est-ce C ? ?] DAVID J. MALAN : Qu'est-ce que c'est -- oh, pourquoi C est-il plus rapide ? Pourquoi C est-il plus rapide que d'autres langages, je répondrai à cela plus en détail dans la semaine 6, lorsque vous verrez à quel point il est plus facile d'écrire du code dans d'autres langages car quelqu'un d'autre fait une grande partie du travail pour vous. Donc, en tant que cours d'introduction, nous vous enseignons de bas en haut, comment écrivez-vous du code ? Comment l'ordinateur comprend-il le code ? Finalement, ce genre de choses, certainement après cinq, six semaines de cela, cela deviendra fastidieux de faire certaines de ces choses. Nous passerons à un autre langage qui élimine la monotonie et nous permet de nous concentrer vraiment sur les problèmes à résoudre une fois que nous aurons atteint ce stade. Oui ? AUDIENCE : [INAUDIBLE] raccourcis ? DAVID J. MALAN : Bien sûr. Pour répéter les raccourcis clavier, vous pouvez simplement aller en haut, en haut, en haut, en haut, en haut. Et cela parcourra toutes vos commandes précédentes, auquel cas vous pouvez simplement appuyer sur Entrée. Ou vous pouvez utiliser la complétion Tab. Donc, vous pouvez commencer à taper un mot comme "code". Et C-O-D tab complétera la pensée. Ou ./C-O-M Tab complétera cette pensée juste pour vous faire gagner quelques frappes. Et effacer l'écran est Control L, qui n'a pas de but fonctionnel autre que de garder les choses nettes et rangées en classe. Donc, une question de conception. Donc, ce code, j'ose dire, est correct. Laissez-moi zoomer un peu ici. Laissez-moi changer le code pour faire juste ceci, même si nous avons déjà vu dans Scratch que nous ne devrions probablement pas faire cela. Pourquoi ne devrions-nous pas faire cela si, surtout, je suis plus à l'aise à poser trois questions distinctes, comme si x est inférieur à y, si x est supérieur à y, si x est égal à y, faites ceci ? C'est un monde agréable dans lequel vivre. Posez simplement vos questions. Vous n'avez pas à vous soucier de else, else-if, else-if, embranchements. Vous pouvez simplement poser trois questions. Mais mettons le doigt sur, pourquoi est-ce correct, oui, mais pas bien conçu ? Oui, au fond encore ? AUDIENCE : [INAUDIBLE] DAVID J. MALAN : OK, il pourrait y avoir des cas qui sont potentiellement en dehors de ces trois. Parce que c'est des mathématiques relativement simples, comparer des nombres, nous n'avons pas à nous en soucier ici. Mais, oui, en général, vous pourriez manquer un scénario sans utiliser un fourre-tout comme "else". AUDIENCE : Peut-être que plus d'un d'entre eux serait évalué comme vrai. DAVID J. MALAN : Oui, donc peut-être que plus d'un d'entre eux pourrait être évalué comme vrai -- cela n'arrivera pas ici. Mais, oui, vous pourriez accidentellement créer une situation où deux choses s'impriment ou trois choses s'impriment parce que vous n'avez pas vraiment réfléchi aux limites entre ces questions que vous posez. Encore une fois, non applicable ici mais, en général, une bonne préoccupation. AUDIENCE : Vous forcez l'ordinateur à avoir une condition qui n'a pas besoin d'être vérifiée si je le ralentis. DAVID J. MALAN : Très bien. Ce qui est vraiment préoccupant ici dans cet exemple, c'est que vous ralentissez l'ordinateur en lui faisant perdre son temps, en lui faisant faire un travail logiquement inutile, encore plus que Scratch dans le premier exemple C. Pourquoi ? Supposons que je tape 1 pour x et 1 pour y. Parce que j'ai écrit ce code de haut en bas, cette question sera posée quoi qu'il arrive. La réponse sera fausse. Cette question sera posée quoi qu'il arrive. La réponse sera fausse. Cette question sera posée. Et quoi qu'il arrive, la réponse sera vraie. Nous sommes d'accord là-dessus car nous avons dû poser les trois questions. Mais supposons que j'aie fait la première chose, x est 1, y est 2. Alors cette première question sera vraie car x est inférieur à y. 1 est inférieur à 2. Donc cela sera imprimé. Et pourtant, je fais perdre du temps à tout le monde en demandant, hm, x est-il supérieur à y, même si évidemment ce n'est pas le cas. x est-il égal à y ? Hm, évidemment ce n'est pas le cas. Vous faites trois fois plus de travail dans ce cas particulier. Ce n'est tout simplement pas une bonne conception. Et encore une fois, pour ceux d'entre vous qui pensent un peu plus visuellement, nous pouvons en fait faire correspondre cette image. Voici un organigramme final pour un mauvais code, une mauvaise conception. Pourquoi ? Parce que quoi qu'il arrive, lorsque vous démarrez le programme et que vous voulez l'arrêter, vous passez par les trois questions, quoi qu'il arrive, alors que les organigrammes précédents nous ont conduits plus rapidement à la bulle d'arrêt en prenant des flèches alternatives basées sur des réponses vraies ou fausses. Donc, en bref, toujours correct mais mauvaise conception. Et donc encore une fois, même pour le jeu de problèmes 1, lorsque nous commencerons à écrire du code C, considérez non seulement à faire le travail, mais comment vous pourriez faire le travail mieux que vous ne le feriez autrement. Très bien, ajoutons quelques autres fonctionnalités. Ici, nous avons les mêmes types de données pris en charge par C. Concentrons-nous un instant sur quelque chose d'un peu plus simple, juste des chars, des caractères uniques. Malheureusement, pour le meilleur ou pour le pire, en C, le langage fait une distinction entre les chaînes de caractères, qui sont généralement des mots, des phrases. Elles peuvent, de manière déroutante, être des caractères uniques ou même zéro caractère si vous ne tapez rien entre les guillemets. Mais plus à ce sujet une autre fois. Mais lorsque vous savez dès le départ que vous ne voulez obtenir qu'un seul caractère de l'utilisateur, comme "y" pour oui, "n" pour non, par exemple, ce qui est très courant dans les programmes, vous pouvez l'obtenir en utilisant un char et la propre fonction de CS50, get_char. Alors, comment pourrions-nous utiliser cela ? Eh bien, retournons à VS Code ici. Je vais fermer compare.c. Et écrivons un troisième programme entièrement. Appelons-le agree.c. Et cela est censé représenter des conditions générales, où vous devez cocher une case oui ou non ou quelque chose comme ça. Dans ce programme, je vais faire ce qui suit. Je vais, comme avant, inclure cs50.h, donc nous l'avons, inclure standard io.h pour que nous l'ayons, int main(void) parce que nous devons le faire pour l'instant. Plus à ce sujet une autre fois. Et maintenant, demandons à l'utilisateur une question. Est-ce qu'il est d'accord ? Donc, je vais appeler get_char puis passer une invite de, "Êtes-vous d'accord ?", point d'interrogation, avec un espace, point-virgule. Mais comme avant avec get_string et get_int, ces fonctions renvoient une valeur. Donc, je veux attribuer cette valeur de droite à gauche à une variable, que je pourrais appeler "answer again". Mais honnêtement, ce programme est si court, nous allons juste utiliser la lettre c, ce qui est conventionnel. Donc, "c" pour char, "i" pour int, ou "n" pour number sont très courants. Mais une chose de plus. Qu'est-ce qui manque encore pour ma variable ? Le type. Je dois dire, ce sera un char, pas un int, pas une chaîne, un seul char. Très bien, maintenant que veux-je faire ? Je peux poser une question. Si c == 'y' (en minuscules), alors allez-y et imprimez, juste pour que nous voyions quelque chose à l'écran, "Agreed." période, \n, comme s'ils avaient accepté les conditions générales. Sinon, si c == 'n' (en minuscules), allez-y et imprimez, par exemple, "Not agreed" juste pour que nous voyions quelque chose à l'écran. Alors, laissez-moi cacher ma fenêtre de terminal et me concentrer sur le code. Il y a quelques détails ici qui sont un peu intéressants. Donc, un, qu'ai-je fait à la ligne 7 et 11 qui n'est pas cohérent avec ce que j'ai fait auparavant ? Subtil. Donc, j'utilise maintenant des apostrophes ou des guillemets simples au lieu de guillemets doubles. Pourquoi ? C'est une chose en C. Lorsque vous utilisez des chaînes, vous utilisez des guillemets doubles. Lorsque vous utilisez des caractères uniques, vous utilisez des guillemets simples. Donc, l'argument pour get_char, c'est toujours une chaîne. C'est une phrase entière que je passe. Donc, c'est comme get_int, comme get_string. Mais lorsque j'obtiens la réponse, la valeur de retour, et que je la mets dans cette variable et que je veux vérifier, quel est ce caractère unique, je dois entourer le caractère auquel je compare avec des guillemets simples ou des apostrophes, à la fois pour le y et pour le n. Donc, ce programme n'est pas très bien conçu car il ne gérera pas les majuscules. Il ne gérera pas très bien les entrées étranges. Mais laissez-moi ouvrir ma fenêtre de terminal. Make agree, Entrée. Le code compile bien -- "./agree." Êtes-vous d'accord ? Essayons. y pour oui. OK, essayons à nouveau -- "./agree." n pour non. "Not agreed." Essayons encore une fois. Disons très avec enthousiasme "YES" en majuscules, et cela nous ignore simplement. Mais pourquoi ? Eh bien, c'est une fonctionnalité de la fonction get_char de CS50. Si vous nous dites que vous voulez obtenir un char, nous ne tolérerons pas une chaîne de texte entière de l'utilisateur. Nous lui demanderons encore et encore jusqu'à ce qu'il nous donne juste un char. Donc "YES" est trois fois trop long. Alors, faisons juste un seul Y majuscule et voyons ce qui se passe. Retour. Le programme m'ignore complètement. Alors, d'accord, c'est un programme mal conçu. C'est un peu agaçant que nous ignorions simplement les humains même s'ils tapent Y ou N qui se trouve être en majuscules. Alors, améliorons cela. Laissez-moi ajouter quelques conditions supplémentaires. Else if c == 'Y' (en majuscules), alors allez-y et imprimez, "Agreed", comme avant. Et puis, ici, else if C == 'N' (en majuscules), alors imprimons, par exemple, "Not agreed". C'est donc maintenant plus correct. Il ignorera toujours les entrées bidons qui n'ont pas de sens, si c'est juste le mot -- si c'est une lettre différente. Mais cela aussi, le code, bien que correct dans un certain sens, est toujours mal conçu. Même si vous n'avez jamais programmé auparavant, qu'est-ce qui vous dérange dans ce code maintenant ? Soyez critique. Oui ? AUDIENCE : [INAUDIBLE] majuscules et minuscules Y ensemble [INAUDIBLE]. DAVID J. MALAN : Oui, ce serait bien de simplement fusionner les majuscules et les minuscules Y ensemble, la même chose pour les majuscules et les minuscules N. Pourquoi ? Ne serait-ce que parce que littéralement les lignes 9 et 12 sont identiques. Les lignes 17 et 21 sont identiques. Et bien que ce ne soit pas un gros problème, si je vais et que je change cette phrase, il y a de fortes chances que, au cours de ma vie de programmeur, j'oublie de changer celle-ci même si j'ai changé celle-ci. Ou j'oublierai de changer celle-ci et celle-ci. Donc, vous ne voulez pas que le code devienne potentiellement désynchronisé. Et vous ne voulez certainement pas répéter
vous-même. Donc "ne vous répétez pas" est un principe de programmation, aussi. Si vous pouvez l'éviter en factorisant d'une manière ou d'une autre une certaine communauté, vous devriez le faire, dans un esprit similaire aux mathématiques lorsque vous factorisez des variables ou autre. Alors laissez-moi resserrer cela, pour ainsi dire. Laissez-moi me débarrasser de ce que nous venons de faire afin que ce soit un peu plus court qu'avant. Et laissez-moi m'exprimer avec deux conditions en utilisant la syntaxe suivante. Je veux vérifier si c est égal à y en minuscules ou si c est égal à Y en majuscules. Vous pouvez donc utiliser ce qu'on appelle un opérateur logique, deux barres verticales, ce qui signifie "ou". Et nous pouvons faire cela ici, ou c est égal à N majuscule. Donc, même fonctionnalité exacte. Mais pour en revenir à votre point, nous avons maintenant éliminé, quoi, comme une autre-- c'était, comme, 1, 4-- il reste huit lignes de code maintenant, ce qui fait huit lignes de moins que je pourrais gâcher dans ce programme. Moins d'opportunités d'erreurs ou de bugs, probablement une bonne chose. Alors maintenant, si j'exécute cela, laissez-moi ouvrir ma fenêtre de terminal. Laissez-moi exécuter make agree, Entrée. "./agree," Entrée. Êtes-vous d'accord ? Y majuscule. Maintenant, cela semble gérer ces deux situations. Juste un peu plus concis. Soit dit en passant-- nous ne l'utiliserons pas ici-- mais si vous voulez dire "et", ce qui serait absurde, c'est, un peu confusément, deux esperluettes, ce qui signifie un "et" logique, où la chose de gauche doit être vraie et la chose de droite doit être vraie. Ce sont donc deux expressions booléennes à la fois. Celle-ci n'a cependant aucun sens logique, car un caractère ne peut pas être simultanément en minuscules et en majuscules. Il doit être l'un ou l'autre. Donc, deux barres verticales est logiquement correct. Cela représente notre notion ici de "ou". Des questions ? Non ? Oui. AUDIENCE : Ne pourriez-vous pas écrire ou ? Est-ce que cela le reconnaît ? DAVID J. MALAN : Vous ne pourriez pas écrire "ou". Je dis donc "ou" simplement parce que c'est un peu plus normal. Mais c'est incorrect. Cependant-- aperçu-- dans le langage Python, vous direz littéralement "ou", entre autres choses, ce qui est un peu plus convivial. D'autres questions sur ceci ? Recherche. Oui, à l'arrière. AUDIENCE : Y a-t-il un moyen plus simple de-- DAVID J. MALAN : Y a-t-il un moyen plus simple de gérer la sensibilité à la casse ? Oui, et nous vous montrerons cela la semaine prochaine, en fait. Nous pouvons donc combiner ce code pour le rendre encore plus concis. Bien, faisons un dernier ensemble d'exemples avant de faire une pause-café, si nous le pouvions. Mais fermons agree.c ici. Laissez-moi ouvrir ma fenêtre de terminal. Et implémentons un chat virtuel comme nous l'avons fait la semaine dernière. Je vais coder un fichier appelé cat.c. Et je vais implémenter cela de quelques manières différentes, la première étant assez stupide. Alors ici, j'inclurai standard io.h. Pas besoin de CS50 dot encore-- pas encore. int main(void). À l'intérieur de ces accolades, faisons un printf "miaou" pour faire miauler le chat. Et ensuite, pour gagner du temps, je vais copier/coller cela deux fois de plus. Donc ce chat miaulera trois fois au total. Bien, je vais faire le chat, pour ainsi dire. Tout va bien. "./cat," Entrée. Et il miaule trois fois, tout comme notre chat Scratch la dernière fois. Je stipule que c'est correct. C'est un chat vraiment bien implémenté en termes de correction. Mais pourquoi est-ce une mauvaise conception intuitivement, tout comme la semaine dernière ? AUDIENCE : [INAUDIBLE] [? Sortir. ?] DAVID J. MALAN : Pardon ? AUDIENCE : Répéter le code. DAVID J. MALAN : Pardon. AUDIENCE : Vous continuez à répéter le code. DAVID J. MALAN : Je continue à répéter le code. Je veux dire, j'ai littéralement copié et collé, ce qui est votre premier signe évident. Je fais probablement quelque chose de mal si je copie et colle parce que je me répète littéralement. Donc, pour gâcher cela, il y a de fortes chances qu'une boucle soit probablement notre amie ici. Et donc, en fait, en C, nous avons aussi ces fonctionnalités. Donc, dans le monde du C, nous pouvons implémenter certaines des mêmes idées de la semaine dernière de quelques manières différentes. Celles-ci sont un peu plus mécaniques. Mais supposons que nous voulions répéter quelque chose littéralement trois fois. Scratch nous donne une répétition, un bloc avec une entrée-- c'est si facile. C et beaucoup de langages, ce sera un peu plus mécanique. Et cela aura l'air moche au début. Il faudra un certain temps pour s'y habituer. Mais c'est un paradigme que vous utiliserez encore et encore. Cela deviendra une mémoire très routinière bientôt. Eh bien, la traduction la plus directe de ce code Scratch en C est probablement quelque chose qui ressemble un peu à ceci, où j'initialise une variable, ici appelée i, et je la mets égale à 3. C'est l'équivalent de code en C de lever trois doigts. Ensuite, ce que je veux faire, c'est, tant que i est supérieur à 0, c'est-à-dire tant qu'il me reste au moins un doigt levé, allez-y et faites ce qui suit. Et ensuite, une fois que j'ai fait cela, par exemple dire "miaou" à l'écran, je veux décrémenter i, puis refaire tout cela. Maintenant, j'aurais pu appeler cette variable "compteur", par souci de cohérence avec les précédents. Mais il s'avère que c'est conventionnel lorsque vous n'avez qu'une seule variable impliquée dans votre code et que tout ce qu'elle fait est quelque chose de simple comme compter, vous pouvez appeler la variable i pour entier, par exemple. Mais ce ne serait pas faux d'appeler i "compteur" à la place. Mais remarquez aussi que dans cette boucle dite while, comme nous allons commencer à l'appeler, il y a cette parenthèse. Et cette parenthèse est en fait elle-même une expression booléenne. Mais contrairement à une instruction if, où l'expression booléenne est évaluée une seule fois et si la réponse est vraie, ou oui, vous faites cette chose, l'expression booléenne dans une boucle while ici en C est évaluée encore et encore à chaque fois que vous parcourez la boucle pour vérifier si vous devez continuer à parcourir la boucle. Donc, par exemple, si le but est de dire "miaou", eh bien, bien sûr, la fonction C comparable sera printf. Et je veux imprimer à l'écran "miaou", suivi d'une nouvelle ligne. Eh bien, que se passe-t-il ? Eh bien, encore une fois, j'initialise i à 3. Je vérifie ensuite, i est-il supérieur à 0 ? Et bien sûr, il l'est car effectivement, dans la mémoire de l'ordinateur, trois doigts sont levés. Je procède à l'impression de "miaou". Je décrémente i, ce qui signifie baisser un de ces doigts. Et ensuite, je vérifie à nouveau l'expression booléenne. 2 est-il supérieur à 0 ? Bien sûr, il l'est. Donc j'imprime "miaou". Et ensuite, je décrémente i, en baissant un autre doigt. Ensuite, je vérifie à nouveau l'expression. 1 est-il supérieur à 0 ? Bien sûr, il l'est. J'imprime "miaou". Et ensuite, je décrémente i. Et maintenant, je suis à 0. Je vérifie à nouveau. 0 est-il supérieur à 0 ? Eh bien, non. Et donc la boucle se terminera automatiquement, par la définition du fonctionnement de ce code C, et passera à toute autre ligne s'il y a d'autres lignes de code que j'ai écrites. Alors, comment implémentons-nous cela en code et le faisons-nous fonctionner ? Eh bien, ce sera à peu près la même idée. Laissez-moi retourner à VS Code ici. Je vais me débarrasser de tout ce copier-coller. Et à l'intérieur de ma fonction main, je vais faire exactement ce que nous avons vu-- int i égale 3, point-virgule. while i est supérieur à 0, alors allez-y et imprimez avec printf "miaou" backslash n. Et assurez-vous de décrémenter i. Et remarquez que les lignes 8 et 9 ne sont pas seulement indentées, elles sont à l'intérieur de cette boucle while, pour ainsi dire, ce qui signifie qu'elles se produiront encore et encore parce que ce qui se passe dans le code ici, c'est que ces accolades sont un peu comme les pièces jaunes qui serrent les autres pièces de puzzle dans Scratch. Cela continuera à faire ceci, ceci, ceci. Mais à chaque fois, à travers cette boucle ou ce cycle, cette expression booléenne sera vérifiée encore et encore jusqu'à ce que la réponse soit fausse, auquel cas l'ordinateur sautera à la dernière ligne. Et s'il ne reste rien, c'est fini pour le programme, plus rien à faire. Donc, même idée exacte dans Scratch, même si c'est un peu plus mécanique. C'est donc ainsi que nous pourrions implémenter cela. Et vous pouvez y penser, ces variables-- c'est peut-être un peu gratuit, mais faisons-le. Donc, si vous avez une variable dans la mémoire d'un ordinateur-- et c'est un détail que nous aborderons plus en détail bientôt-- vous pouvez vraiment y penser comme un conteneur qui stocke une valeur. Donc, par exemple, ce bol en plastique transparent, il peut être considéré comme une variable. Il stocke simplement des valeurs. Et en ce moment, il y a évidemment trois balles anti-stress dedans. Il représente donc le nombre 3. Donc, ce qui se passe réellement dans un code comme celui-ci, c'est que nous avons initialisé i à 3, qui est ce bol. Nous vérifions ensuite la question à la ligne 6. i est-il supérieur à 0 ? Évidemment. Nous procédons donc à l'intérieur des accolades. Et nous imprimons "miaou". Nous décrémentons ensuite i. Donc, pour des raisons de drame inutile, c'est décrémenter la variable. Donc, ce qui est stocké dans ce conteneur maintenant, c'est une unité de moins. Nous le faisons à nouveau, vérifions le compte. Non, 2 est supérieur à 0. Nous continuons donc-- "miaou". Décrémenter i. Vérifier la variable. 1 est supérieur à 0, donc nous imprimons "miaou". Décrémenter i. Nous vérifions à nouveau la condition. i n'est pas supérieur à 0 car 0 n'est pas supérieur à 0. Et donc le reste du code cesse de s'exécuter. Je ne suis pas sûr que ce soit plus efficace que les doigts sur ma main. Mais nous avions le bol. Nous avions les balles. Donc, même idée exacte. Les variables stockent simplement une valeur. Et incrémenter et décrémenter serait simplement ajouter ou soustraire des balles anti-stress dans ce cas. Mais il y a d'autres façons de faire cela. En fait, laissez-moi zoomer sur mon code ici. Et ce n'est pas vraiment conventionnel en programmation de compter à rebours-- rien de mal à cela, ce n'est juste pas vraiment une chose. Nous compterions généralement à rebours. Nous pourrions donc faire ceci alternativement-- mettre i égal à 1 initialement. Donc nous comptons 1, 2, 3, comme une personne normale. Et nous pouvons changer notre condition. Si je vais compter de 1 à 3, quelle devrait être ma comparaison dans mon expression booléenne ici ? i est inférieur à 3 ? Inférieur ou égal à 3, je pense. Donc, si i est initialisé à 1, nous allons passer par cela une fois, deux fois, trois fois. i sera finalement incrémenté à 4. Mais à ce moment-là, 4 n'est pas inférieur ou égal à 3. Donc, cela ne s'exécutera que trois fois au total. Mais il y a toujours un bug dans ce code. Quelle autre ligne doit changer ? AUDIENCE : Plus plus. DAVID J. MALAN : Oui, donc la ligne 9 doit devenir plus plus. Donc ce code est tout aussi correct. Et honnêtement, vous pourriez-- des gens raisonnables seront en désaccord. Votre TF pourrait dire de faire cela de cette façon et pas de cette façon. Mais c'est toujours correct. Mais ce n'est pas la façon la plus conventionnelle. Comme la semaine dernière, les informaticiens et les programmeurs en général, en fait, commencent à compter à partir de 0 par convention pour des raisons que nous verrons bientôt. Donc, la meilleure façon, la façon la plus conventionnelle sans doute, serait de toujours commencer à compter à partir de 0. Comptez jusqu'au nombre que vous voulez, mais sans l'inclure. Et donc cette forme de code est probablement la façon la plus populaire de le faire. Commencez à 0, comptez jusqu'à 3 mais sans inclure 3, comme avec inférieur ou égal à. Les trois sont corrects. On ne peut pas vraiment compter à rebours aussi facilement avec le bol sans ramasser les balles. Mais la logique exacte s'applique. Et en fait, cette version du code est si couramment faite qu'il existe une autre façon de l'implémenter-- il existe une façon similaire de l'implémenter entièrement. En fait, ce code ici-- même chose exacte, répété trois fois-- parce que c'est si couramment fait que vous voulez initialiser quelque chose à 0 et continuer à faire quelque chose jusqu'à la valeur 3, vous pouvez en fait utiliser une préposition différente, for, qui est un autre mot-clé en C. Et cela a l'air un peu plus cryptique. Mais cela resserre simplement les choses. C'est ce qu'on appelle une boucle for. Précédemment, c'est ce qu'on appelle une boucle while. Et honnêtement, même si, probablement pour le débutant, cela a toujours l'air tout aussi cryptique, c'est juste un peu plus concis car vous exprimez toutes ces idées sur une seule ligne. Vous spécifiez la variable que vous voulez créer et initialiser. Vous spécifiez l'expression booléenne que vous voulez vérifier encore et encore. Vous spécifiez quel incrément ou décrément vous voulez qu'il se produise. Et confusément, vous utilisez des points-virgules ici, pas des virgules. Vous ne mettez pas de point-virgule ici. Vous n'en mettez bien sûr pas après ces choses. Vous ne les mettez généralement qu'après les fonctions jusqu'à présent. Nous avons donc un point-virgule ici. Mais en bref, vous vous y habituerez. C'est ainsi que j'écris presque toujours une boucle, par exemple. Mais cela fait exactement la même chose mécaniquement que ceci, la même chose que compter sur vos doigts, la même chose que compter les balles anti-stress. Il existe simplement différentes façons d'exprimer la même idée exacte. Mais il y a des façons de gâcher. Donc, en fait, laissez-moi faire ceci. Supposons que le chat-- nous aimerions que le chat vive le plus longtemps possible. Et nous ne voulons pas qu'il arrête de miauler après seulement trois fois ou un nombre fini de fois. Comment faire quelque chose pour toujours, encore et encore ? Eh bien, laissez-moi retourner dans VS Code ici. Laissez-moi supprimer tout le code précédent. Et laissez-moi dire, tant que quelque chose est vrai-- j'y reviendrai-- faisons simplement un printf "miaou" backslash n idéalement pour toujours. Mais que dois-je mettre ici ? Eh bien, si je veux faire quelque chose pour toujours, je pourrais faire quelque chose d'un peu stupide, comme tant que 1 est inférieur à 2, ce qui sera toujours le cas, ou tant que 50 est inférieur à 51, ce qui sera toujours le cas-- je pourrais simplement poser une question arbitraire. Mais arbitraire-- pas bon en général. Vous devriez avoir un sens derrière votre code. Donc, si vous voulez que l'expression soit toujours vraie, dites simplement "while true", car true ne changera pas de sitôt. Si c'est littéralement vrai, ce sera toujours vrai. La seule mise en garde est d'utiliser cette astuce. Pour l'instant, vous devrez inclure la bibliothèque CS50, ce qui, pour les besoins d'aujourd'hui, rend cela possible. Mais il y a un problème, bien sûr. Si le chat va vivre pour toujours, si je fais make cat, "./cat," Entrée, vous pouvez très rapidement perdre le contrôle de votre fenêtre de terminal. Et vous pouvez voir les miaulements voler à travers l'écran, du moins d'après le bas de ce que nous voyons. Ce chat ne s'arrêtera jamais de miauler. Et c'est soit une fonctionnalité, soit un bug, pour ainsi dire, selon la durée de vie virtuelle du chat. Mais comment terminer un programme qui est hors de contrôle comme celui-ci, infiniment ? L'une des leçons à retenir pour aujourd'hui est que Control-C est votre ami pour annuler ou interrompre le programme. Si vous perdez jamais le contrôle d'un programme parce que vous avez intentionnellement ou involontairement une boucle infinie, vous pouvez aller dans votre fenêtre de terminal, appuyer sur Control-C, parfois plusieurs fois s'il vous ignore. Et cela sortira du programme et le forcera simplement à quitter, comme sur Mac ou PC. Mais faisons encore une amélioration ici. La dernière chose que nous avons faite avec notre chat dans Scratch avant maintenant-- nous ferons une pause dans un moment-- c'est que nous avons défini nos propres fonctions. Et rappelez-vous que nous l'avons fait pour abstraire l'idée de miauler parce que Scratch ne venait pas avec une pièce de puzzle miaou. C ne vient certainement pas avec une fonction miaou. Nous devons l'implémenter nous-mêmes. Donc, rapidement, vers la fin de la semaine 0, nous avons fait ceci-- définir une fonction appelée meow qui joue simplement le son miaou. Et maintenant, nous avons une pièce de puzzle miaou que nous pouvons utiliser et réutiliser. En C, nous sommes sur le point de faire cela. Et cela aura l'air un peu cryptique. Mais cela jettera les bases pour les semaines à venir lorsque nous ferons cela encore plus. J'ai une fonction miaou, des mentions étranges de void. Cela signifie simplement qu'il n'y a pas d'entrée et pas de sortie pour cette fonction. Elle fait juste une chose simplement. Et cette seule chose est printf, "miaou". Alors, comment l'utiliser ici dans le code ? Ici, dans Scratch, c'est ainsi que nous l'avons utilisé la semaine dernière. Lorsque le drapeau vert est cliqué, répétez trois fois la fonction miaou. En C, cela ressemblera à ceci-- int main(void) et tout cela. Et je peux utiliser une boucle for, une boucle while. Je copie la version boucle for du code. Mettez i égal à 0. Assurez-vous qu'il reste inférieur à 3. Incrémentez-le à chaque itération, ou cycle. Et appelez simplement meow. Ce qui est bien ici, c'est que nous avons, assez simplement, un moyen en C de créer nos propres fonctions appelées meow ou quoi que ce soit d'autre qui s'aligne parfaitement avec ce que nous avons fait dans Scratch. Nous prendrons du temps pour nous familiariser avec la syntaxe et nous en souvenir, devoir la rechercher fréquemment pour référence. Mais faisons-le réellement. Si je retourne à VS Code, efface mon écran-- laissez-moi cacher ma fenêtre de terminal temporairement. Laissez-moi inventer cette fonction miaou. Selon le code précédent, je vais faire ceci-- void meow(void). Et encore une fois, les deux voids signifient pas d'entrée, pas de sortie. Elle fait juste une chose bien. printf, guillemet, guillemet, "miaou" backslash n. Et maintenant, ici, je peux utiliser une boucle for. Donc pour-- et je le sais par cœur-- int i égale 0; i inférieur à 3; i plus plus. Et ensuite, à l'intérieur des accolades, je vais appeler la fonction meow. Remarquez, lorsque je crée la fonction ici, je dis explicitement, pédantiquement, void void, pas d'entrée, pas de sortie. Lorsque j'utilise la fonction à la ligne 13, vous dites simplement parenthèse ouverte, parenthèse fermée. C'est l'équivalent d'une pièce de puzzle Scratch sans ovale blanc. Vous ne mettez rien là. Vous ne mettez pas le mot "void". C'est donc tout. Laissez-moi ouvrir ma fenêtre de terminal. Laissez-moi exécuter make cat pour recompiler-- "./cat." Et je pense que j'ai un chat qui fonctionne. Maintenant, c'est correct. La seule chose que je n'aime pas dans cette version, si je cache ma fenêtre de terminal, c'est que lorsque je commence à écrire des programmes de plus en plus grands, ce serait bien si ma fonction main, que je vous ai dit de prendre pour argent comptant pour aujourd'hui, était en haut du fichier, ne serait-ce que parce que littéralement le nom "main" signifie que c'est la partie principale de mon programme. Ce serait bien si c'était la première chose que je voyais, c'est-à-dire, pour être pédant, il est très courant de mettre toutes les fonctions que vous écrivez en bas de votre fichier, peut-être par ordre alphabétique, peut-être organisé d'une autre manière. Mais vous mettez main en premier par convention, tout comme "quand le drapeau vert est cliqué". C'était la première chose avec laquelle vous commenciez toujours la semaine dernière. Mais regardez ce qui se passe maintenant. Si je vais dans ma fenêtre de terminal-- et Commande-- ou Control-J cache et affiche, si vous êtes curieux. Mais probablement, vous la laisserez ouverte tout le temps. Laissez-moi faire make cat à nouveau. Et, huh, j'ai gâché quelque chose. Tout ce que j'ai fait, c'est déplacer la fonction meow du haut vers le bas. Et j'obtiens "appel à la fonction non déclarée 'meow'", quelque chose, quelque chose, quelque chose. Eh bien, que se passe-t-il ? Eh bien, C est assez naïf et simpliste. Il ne fera que ce que vous lui dites de faire. Et il ne fera les choses que de haut en bas, de gauche à droite. Et malheureusement, à la ligne 8, vous dites à C, appelez une fonction appelée meow. Mais elle n'existe pas dans le fichier d'en-tête de CS50. Elle n'existe pas dans le fichier d'en-tête de standard io. Elle existe au bas de mon fichier, à ce moment-là, il est trop tard car j'essaie de l'utiliser avant qu'elle n'existe. Je pourrais donc annuler cela et mettre cette fonction meow en haut du fichier. Mais vous finirez par vous retrouver dans un scénario pervers où vous ne pourrez pas mettre toutes vos fonctions au-dessus de toutes vos fonctions. Vous devrez choisir une voie à un moment donné. Donc, la solution à cela, bien qu'un peu étrange-- et la seule fois en CS50, en programmation, où il est encouragé et nécessaire de copier/coller-- c'est ce que vous pouvez faire en haut de votre code, au-dessus de main, c'est simplement copier/coller la première ligne de votre propre fonction. C'est le soi-disant prototype de la fonction. Et il décrit simplement comment utiliser la fonction. Et drôle de coïncidence, nous l'avons vu plus tôt. Mais je l'ai un peu balayé sous le tapis. Il y a un moment, ou il y a un peu, quand nous avons regardé standard io.h et que nous avons regardé la fonction printf dans les pages du manuel, j'ai mis en évidence le fichier d'en-tête. Mais j'ai aussi survolé le soi-disant prototype, qui est-- désolé-- la première ligne de la fonction printf, tout comme c'est la première ligne de ma fonction meow. C'est comme un petit indice. C'est comme dire à C, hé, il y aura une fonction appelée meow qui ne prend aucune entrée, n'a pas d'entrée-- ne prend aucune entrée, n'a pas de sortie. Sachez juste qu'elle existera éventuellement. Et cela satisfera le compilateur car si je retourne à mon terminal, réexécute make cat, il sait maintenant par foi, selon la ligne 4, que cette fonction existera éventuellement. Et en effet, une fois qu'il atteint le bas de mon code, à partir de la ligne 14, elle est, en fait, là. Vous copiez donc simplement la seule et unique première ligne du code de votre fonction en haut, appelée prototype. Et maintenant, si je fais "./cat," j'obtiens, finalement, "miaou", "miaou", "miaou" encore une fois dans ce cas. Des questions sur ces chats ici ? Non ? Bien, alors la dernière touche avant-- je continue de promettre des cookies. Et je promets qu'ils existent. Donc, dernière touche-- tout comme nous l'avons fait dans Scratch-- donc dans Scratch, rappelez-vous que nous avons paramétré notre fonction miaou en nous permettant de dire à miaou combien de fois miauler afin que nous n'ayons pas besoin d'utiliser notre boucle dans notre bloc "quand le drapeau vert est cliqué". En d'autres termes, si je veux réellement que le chat miaule un nombre spécifique de fois, je peux en fait le faire proactivement avec une partie de mon propre code comme ceci dans Scratch. Lorsque j'ai modifié ma fonction miaou la semaine dernière dans Scratch, j'ai spécifié que je veux maintenant qu'elle prenne une entrée appelée n, qui représente un certain nombre de fois. Et j'ai changé mon bloc de répétition pour qu'il ne soit pas 3 perpétuellement, mais qu'il intègre en fait n à la place. Ou en fait, au lieu de simplement dire jouer le son "miaou", j'avais un bloc de répétition utilisant n comme espace réservé au lieu d'un 3 codé en dur. Alors, comment puis-je maintenant l'utiliser en C ? En C, c'est presque la même chose. C'est toujours void au début du nom de ma fonction, ce qui signifie toujours pas de sortie. Elle n'a que des effets secondaires. Mais qu'est-ce qui a changé par rapport à la version précédente de meow ? Qu'est-ce qui a changé ? AUDIENCE : [INAUDIBLE] DAVID J. MALAN : Exactement. Au lieu de dire "void" une deuxième fois entre parenthèses, il est littéralement écrit "int n" entre ces parenthèses, ce qui signifie, en C, que cette fonction appelée meow prend une entrée. Cela signifie la même chose que le rose à gauche. Et encore une fois, c'est pourquoi nous continuons à insister sur les blocs Scratch. Comme, pas de nouvelles idées avec beaucoup de ces fonctionnalités. C'est juste une syntaxe différente à laquelle vous vous habituerez avec le temps. Donc, si je retourne dans VS Code ici et que je change cette fonction, faisons-le. Changeons mon prototype pour qu'il soit int n, où n représente un certain nombre de fois. Changeons la fonction réelle à la ligne 14 pour qu'elle ait aussi int n ici. Et déplaçons la boucle for de main dans la fonction meow de telle sorte que j'aie maintenant mes accolades ici. J'ai mon instruction d'impression à l'intérieur de ces accolades. Et maintenant, dans main, je peux me débarrasser de tout ce code. Dites simplement "meow" autant de fois que vous le souhaitez, comme trois. Et tout comme je l'ai fait avec Scratch, laissez-moi appuyer sur Entrée un nombre arbitraire de fois. Un peu hors de vue, hors de l'esprit. Maintenant, l'essence de mon programme est une seule ligne de code-- "meow" trois fois-- parce que j'ai abstrait l'idée de miauler et que j'ai dit au chat, au lieu de cela, exactement combien de fois miauler par le biais de cette fonction. OK, je ne peux pas continuer à promettre des cookies si longtemps. Faisons une pause de 10 minutes ici. Et quand nous reviendrons, plus de chats, plus de code. Bien. Nous sommes donc de retour. Et je veux ajouter une dernière touche à ce programme car maintenant, plus que beaucoup d'exemples, les programmes commencent à s'allonger. Et en effet, bientôt il y aura quelques dizaines de lignes de code, ce qui n'est pas rare. Mais supposons que nous voulions arrêter de coder en dur 3 partout et demander réellement à l'utilisateur un certain nombre de miaulements ici. Eh bien, faisons ceci. Dans VS Code, je vais supprimer cette ligne pour l'instant. Et faisons quelque chose comme ceci. Demandons à l'utilisateur un entier. Donc int, peut-être n pour nombre, égale get_int. Et nous dirons quelque chose comme juste "Nombre" pour donner un nombre de miaulements. Et ensuite, nous appellerons réellement meow, en passant non pas 3 cette fois, mais en passant n. Nous utilisons donc la valeur de retour de get_int pour la stocker dans une variable appelée n à la ligne 8. Et ensuite, nous passons n comme entrée, ou argument, à la fonction appelée meow à la ligne 9. Et encore une fois, l'implémentation réelle de meow à partir de la ligne 22, peu importe. Hors de vue, hors de l'esprit. Une fois qu'elle existe, nous pouvons l'abstraire mentalement. Mais je la garderai ici de toute façon. Bien, laissez-moi ouvrir ma fenêtre de terminal-- make cat, "./cat," "Nombre"-- je peux toujours taper 3, et ça marche. Ou je peux taper 5. "Miaou", "miaou", "miaou". Mais, hm, il ne miaule pas vraiment cinq fois. Pourquoi ? [CHUCHOTEMENT] Je ne m'en suis pas rendu compte non plus, mais il y a un bug. AUDIENCE : [INAUDIBLE] DAVID J. MALAN : Oui, exactement. Donc la boucle for, quand je l'ai copiée-collée avant, avant la pause, j'ai été paresseux et j'ai oublié de changer le 3 en n afin qu'il corresponde au nom de l'argument qui est passé à meow. C'était donc un bug-- involontaire de ma part. Mais nous l'avons maintenant corrigé ici. Et maintenant, nous le passons de main à meow. Donc, si je fais make cat, "./cat", et que je tape 5 cette fois, j'obtiens effectivement cinq miaulements. Mais il convient de noter qu'il y a des subtilités ici dans mon code dans le sens où j'ai utilisé n plusieurs fois. C'est donc délibéré, que j'ai utilisé n deux fois de cette manière, pour induire un peu de confusion. Mais il s'avère que ce n n'est en fait pas le même que ce n, ni celui-ci. Alors, que se passe-t-il ici ? Eh bien, il s'avère qu'en programmation, il y a souvent cette idée de portée. Et pour faire court, en général, les variables n'existent que dans la portée dans laquelle vous les créez. Plus concrètement, les variables n'existent qu'à l'intérieur des accolades dans lesquelles vous les définissez. Donc, par exemple, supposons que j'ai été un peu négligent et supposons que je n'ai pas pris la peine de donner une entrée à meow et que je n'ai pas pris la peine de donner une entrée à son prototype et que j'ai juste utilisé n à la ligne 14 parce que, pourquoi ? Eh bien, j'ai déjà défini n à la ligne 8. C'est donc juste un univers alternatif dans lequel je ne change pas meow pour prendre une entrée. J'utilise simplement n dans deux fonctions différentes, dans main à la ligne 8 et 9-- en fait, je n'en ai même pas besoin-- aux lignes 8 et 9 et aussi à nouveau à la ligne 14. Ce code ne fonctionnera pas. Le compilateur n'aimera pas cela. Pourquoi ? Parce que n n'existe pas à l'intérieur de meow. Pourquoi ? Selon l'heuristique que j'ai proposée, n n'existe que dans les accolades dans lesquelles il a été défini, à savoir ces accolades ici. Donc n est en portée dans main, pour ainsi dire. Mais il n'est pas en portée dans meow. Et c'est pourquoi nous devons passer par ces étapes et utiliser des entrées et des sorties et des entrées et des sorties et passer des choses entre les fonctions sans partager des choses entre les fonctions à la place. Maintenant, je pourrais clarifier cela et peut-être changer mon argument ici de n à times. Si je veux préciser que, oh, c'est le nombre de fois que je veux que meow soit dit, je n'ai pas à utiliser n pour les deux. Mais réalisez simplement que, si vous le faites, c'est juste une coïncidence. Ils ne sont pas utilisables dans deux portées différentes. Bien, faisons une autre chose, cependant. Ne demandons pas seulement à l'utilisateur le nombre ici, assurons-nous que le nombre qu'il nous donne a du sens. Donc, si je fais make cat-- juste pour nettoyer-- "./cat," supposons que je tape 0, OK, je suppose que c'est correct. Si je dis miaou 0 fois et qu'il ne miaule pas du tout, c'est sans doute correct. Mais si je tape quelque chose comme moins 5, il m'ignore, ce qui est peut-être mieux que de planter ou de geler ou quelque chose comme ça. Mais idéalement, ce serait bien de gérer cette situation. Et s'il me donne un nombre négatif, demandez-lui à nouveau un nombre positif. Demandez-lui à nouveau un nombre positif. Rendez le programme logique. Alors, comment pourrions-nous faire cela ? Eh bien, il y a plusieurs façons. Si je retourne à mon code ici, je pourrais faire ceci. Je pourrais peut-être faire quelque chose comme une boucle ou-- voyons. Donc, si j'obtiens n, donc si n est inférieur à 1, alors cela n'a pas de sens. Alors, que veux-je faire si n est inférieur à 1 ? Eh bien, je pourrais simplement demander à nouveau à l'utilisateur. Et je dis, OK, prenons n à nouveau. Et ensuite, je peux dire, si n est inférieur à 1, que veux-je faire ? Je suppose que nous pourrions demander à nouveau à l'utilisateur. Et ensuite, si n est inférieur à 1, je pourrais simplement, encore-- je peux lui donner trois essais, quatre essais pour bien faire. C'est évidemment stupide. Je copie et colle. Je me répète. Il n'y a pas de fin en vue. Je ne peux pas faire ça pour toujours, sûrement. Donc, cela semble être la mauvaise solution. Il existe donc différentes façons de résoudre ce problème. Et drôle de coïncidence, une boucle while n'est pas vraiment la meilleure façon. Une boucle do while est-- agh-- une boucle while n'est pas la meilleure façon. Une boucle for n'est pas la meilleure façon. Il s'avère qu'il existe un autre type de boucle que nous voulons introduire qui est super utile pour obtenir l'entrée de l'utilisateur, potentiellement, encore et encore et encore afin que l'utilisateur coopère. Spécifiquement, ce que je vais faire, c'est ceci. Je vais littéralement dire, faites ce qui suit tant que quelque chose est vrai. C'est donc plus une bouche à oreille. Je l'étale sur plusieurs lignes. Mais que vais-je mettre dans le bloc do ici ? Je vais dire int n égale get_int et demander ce nombre comme avant, guillemet fermé, point-virgule. Et je vais continuer à demander tant que-- désolé, Entrée accidentelle-- tant que n est inférieur à 1, point-virgule. Donc, remarquez la sémantique de cela. Même si cela a l'air un peu bizarre, cela se lit, en anglais, faites ce qui suit. Obtenez un entier stocké dans n. Et continuez à faire cela tant que n est inférieur à 1. Mais ce code tel qu'il est écrit ne fonctionnera pas tout à fait encore. Laissez-moi essayer d'ouvrir ma fenêtre de terminal. Make cat, Entrée. Ugh, zut-- "Utilisation d'un identifiant non déclaré 'n'." Eh bien, c'est là que le numéro de ligne est utile. Le numéro de ligne est indiqué ici, 12. Et il est répété ici, 12. J'ai donc clairement gâché à la ligne 12. Mais il n'y a pas grand-chose qui se passe à la ligne 12. Pourquoi n est-il "non déclaré" à la ligne 12 alors que je viens littéralement de le déclarer à la ligne 10 ? AUDIENCE : Parce que c'est [INAUDIBLE] à l'intérieur de [INAUDIBLE] ligne 10, pas à l'extérieur. DAVID J. MALAN : Exactement, parce que j'ai déclaré n à l'intérieur de la portée du bloc do, pour ainsi dire, à l'intérieur des accolades des lignes 9 et 11. Cette variable n n'existe plus lorsque nous arrivons à la ligne 12. Ce serait formidable si c'était le cas, mais ce n'est pas le cas parce que cela viole l'heuristique que j'ai proposée, à savoir que les variables n'existent que dans la portée des accolades dans lesquelles elles ont été définies. Alors, comment puis-je corriger cela ? Eh bien, il s'avère que vous pouvez déclarer une variable à l'avance en dehors d'une portée, mais ensuite la définir, c'est-à-dire l'initialiser, ailleurs. Donc, la solution ici est en fait ceci. À l'intérieur de la boucle, définissez simplement n égal à la valeur de retour de get_int. Mais selon l'heuristique, vous devez déclarer n, la faire exister dans la portée la plus externe de cette fonction. C'est donc un peu bizarre. Et nous décomposons cela en deux étapes. Mais c'est du code C valide, recommandé, correct. Vous déclarez une variable sans lui donner de valeur initiale. Et ensuite, à la ligne 11, vous procédez à lui donner une valeur, potentiellement encore et encore. Maintenant, qu'est-ce qui est utile dans une boucle do while ? Donc, une boucle do while, comme son nom l'indique, fera quelque chose quoi qu'il arrive. Mais elle le fera potentiellement encore et encore tant qu'une certaine question est vraie, comme n étant inférieur à 1 dans ce cas. Soit dit en passant, pourquoi n'avons-nous pas fait une boucle while ? Eh bien, pensons-y. Tant que n est inférieur à 1-- mais attendez une minute. n n'a pas de valeur. OK, donc je suppose que nous devons revenir à faire get_int, nombre, deux-points, point-virgule. OK. Mais tant que n est inférieur à 1, nous revenons au même problème où nous devons nous répéter à nouveau. C'est donc pourquoi les boucles for, les boucles while, ne sont pas la bonne solution lorsque vous voulez faire quelque chose au moins une fois, mais potentiellement encore et encore. Donc, la bonne solution ici, encore une fois, est cette nouvelle et dernière construction de boucle-- je n'arrête pas d'appuyer sur Control-Z-- où nous l'avons fait comme suit. Bien, essayons ceci. Effacez l'écran. make cat, Entrée. "./cat." Tapez 5. Ça marche toujours. Tapez moins 5. Et remarquez qu'il ne m'ignore pas simplement. Il me demande encore et encore. Même si je tape 0, je dois au moins lui donner un entier positif. Eh bien, cela semble en fait être un paradigme courant. Et si nous voulons demander à l'utilisateur un nombre positif dans d'autres programmes aussi ? Nous approchons déjà, même après seulement la semaine 1, du point où il serait bien d'écrire nos propres fonctions réutilisables qui résolvent des problèmes courants. Et éventuellement, nous pourrons même les mettre dans des fichiers d'en-tête. Mais pour l'instant, faisons ceci. Je vais en fait copier tout ce code. Et je vais créer une autre fonction dans ce fichier sous main appelée get_positive_int, pour entier. Et je vais spécifier qu'elle n'a pas besoin d'entrée car la seule chose que cette fonction fera, c'est exactement la même chose. Donc, remarquez que j'ai déplacé mon code de main dans une fonction dont le nom décrit ce qu'elle fait, "get_positive_int". Je déclare n ici. Je fais cela encore et encore. Et je le fais tant que n est inférieur à 1. Et que vais-je faire ici ? Je peux faire quelque chose comme ceci. Donnez-moi une variable appelée times pour, combien de fois voulez-vous miauler ? Et appelez simplement get_positive_int point-virgule. Donc maintenant, encore une fois, nous avons abstrait les choses. Et tout comme dans Scratch, notre dernier exemple-- qui, rappelez-vous, ressemblait un peu à ceci, où nous appelions simplement une fonction pour miauler trois fois-- maintenant nous appelons une fonction pour obtenir du texte. Si j'appuie sur Entrée un nombre arbitraire de fois, hors de vue, hors de l'esprit, j'ai maintenant deux fonctions dans ce monde, get_positive_int et meow qui implémentent collectivement ce programme entier. Mais ce n'est pas tout à fait correct. Il y a encore une erreur ici. Remarquez que get_positive_int est écrit légèrement différemment de la fonction meow. Et pour être clair aussi, laissez-moi copier son prototype en haut du fichier juste pour que nous ne fassions pas la même erreur que j'ai faite plus tôt où je n'ai pas mis le prototype en haut, donc C ne savait pas ce que c'était. Qu'est-ce qui est différent entre ces deux prototypes à première vue ? Oui. AUDIENCE : get_positive_int devrait retourner int. DAVID J. MALAN : OK, donc get_positive_int apparemment-- et nous n'en avons pas beaucoup parlé-- apparemment a une sortie de type entier. Elle est censée retourner un int, me rendre un int. Elle n'a pas d'entrée. C'est ce que signifiait le "void" entre parenthèses. Pas d'entrée, mais oui de sortie. Et meow, drôle de coïncidence, est le contraire-- oui entrée, pas de sortie. Pourquoi ? Parce qu'elle a un effet secondaire, la chose visuelle, où elle imprime quelque chose à l'écran mais ne me renvoie aucune valeur utile comme la fonction ask ou la pièce de puzzle ask l'ont fait. Donc, elles sont opposées en fonctionnalité, ce qui signifie que je dois en fait retourner un entier de cette fonction à toute fonction qui veut l'utiliser. Donc, si je veux que l'opérateur d'affectation fonctionne ici à la ligne 9, je dois faire quoi, tout ce temps, get_int, get_string, et d'autres fonctions CS50 ont fait. Je dois, dans ma propre fonction, retourner cette valeur littéralement avec un nouveau mot-clé appelé return. Et c'est pourquoi je continue à tendre la main. Quand vous voulez qu'une fonction vous renvoie une valeur, vous utilisez littéralement "return" puis cette valeur. C'est pourquoi nous avons "valeur de retour" comme terme technique, littéralement le mot-clé "return". Donc, si j'ouvre ma fenêtre de terminal maintenant, make cat, Entrée-- huh, j'ai gâché accidentellement. Comment ? Oui. AUDIENCE : [INAUDIBLE] DAVID J. MALAN : Oui, donc aux lignes 9 et 10, j'ai fait un changement rapide. J'ai changé ma variable en times. Mais j'ai bêtement pas changé ceci. Donc, c'est bon. C'est pourquoi n n'était pas déclaré dans ce contexte. Laissez-moi effacer mon terminal, make cat une fois de plus. OK, ça a marché. "./cat." Tapez 5. Et ça marche toujours. Donc, encore une fois, même si le code donne l'impression qu'il-- désolé-- même si le code grandit et grandit, c'est exactement le même programme que nous avons écrit très simplement avant la pause. Mais maintenant, nous le modularisons. Nous créons des fonctions réutilisables. Et c'est pourquoi des fonctions comme get_string existent, get_int existe. Comme, CS50 les a écrites il y a des années. Et nous avons réalisé, pourquoi copions-nous et collons-nous ces fonctions dans tous ces différents programmes CS50 ? Factorisons cette fonctionnalité dans une fonction de notre propre-- get_int, get_string. Tout comme ici, je propose de factoriser cette fonctionnalité, d'obtenir un entier positif qui vous donne une fonctionnalité encore plus précise, donc théoriquement vous pourriez l'utiliser et la réutiliser dans d'autres programmes aussi. En ne la mettant pas seulement ici, nous pourrions la mettre dans un fichier de votre propre nom et l'inclure dans les programmes futurs également. C'est tout ce qu'est une bibliothèque. Quelqu'un a réalisé, bon sang, d'autres personnes, y compris moi-même, pourraient trouver cette fonction utile encore et encore. Emballons-la dans nos propres fonctions personnalisées, tout comme notre pièce de puzzle miaou personnalisée la semaine dernière, afin que nous puissions effectivement l'utiliser encore et encore. Et les leçons à retenir pour l'instant sont que contrairement à Scratch, qui était un peu plus convivial, en C, vous devez spécifier si vous voulez que vos fonctions aient des entrées. Et vous devez spécifier si vous voulez qu'elles aient des sorties également. Mais plus sur cette syntaxe à venir. Alors, où cela nous mène-t-il ? Donc, après toute cette discussion sur le code, à la fin de la journée, c'est ce qui est important dans le monde de la programmation. Sans surprise, c'est comme, ce qui est important en matière de notation et d'évaluation de la qualité du code. Un, et avant tout, c'est la correction. Si le code ne fait pas ce qu'il est censé faire, à quoi servait d'écrire le code ? Donc, la correction va de soi. La conception, encore une fois, est beaucoup plus qualitative. C'est comme obtenir des commentaires, encore une fois, sur une dissertation en anglais, où des gens raisonnables peuvent être en désaccord. Vous pouvez améliorer votre argument. Vous pouvez mieux structurer le papier. Vous pouvez mieux structurer le code dans le cas de la programmation. Et le style est purement esthétique. Est-ce que ça a l'air bien ? Est-ce joliment imprimé, pour ainsi dire ? D'autres personnes, collègues futurs et camarades de classe présents, peuvent-ils réellement le lire et le comprendre ? C'est ce que nous entendons par style. Heureusement, au sein de l'environnement de programmation de CS50, vous aurez des outils pour évaluer la qualité de ces trois axes, pour ainsi dire. Donc, à partir du problème 1, vous serez introduit à un outil en ligne de commande dont vous tapez le nom à l'invite, appelé check50, qui vérifiera pour vous la correction de votre code-- pas nécessairement de manière exhaustive. Il peut y avoir des erreurs que vous avez commises que nous ne détectons pas, ce qui ne rend pas votre code correct. Mais c'est un outil pour trouver bon nombre des erreurs dans votre code. Dans le monde réel, vous auriez des collègues ou vous-même, écririez des tests pour le code que vous avez écrit ou que quelqu'un d'autre a écrit. Donc, tester le code n'est pas seulement une question de notation. C'est une chose du monde réel pour s'assurer que les systèmes sont conçus correctement. Nous avons déjà vu l'outil style50 dans VS Code. Vous cliquez sur le bouton "style50". Il y a maintenant, grâce au canard, un bouton "design50" aussi, également dans le coin supérieur droit, où une fois que votre code est correct et fonctionne, comme plusieurs de mes programmes l'ont été, vous pouvez cliquer sur "design50", et le canard ne fera pas que coasser mais vous donnera des conseils qualitatifs, si possible, sur la façon de rendre ce code encore meilleur avant même de le soumettre. Et bien sûr, il y a tous nous, humains, dans la pièce et en ligne, à qui vous pouvez poser ces mêmes questions. Alors, résolvons maintenant des problèmes réels mais toujours simples par opposition à l'accent mis sur de petites bouchées comme nous l'avons fait jusqu'à présent. Donc, le premier de ces programmes entre dans cette catégorie d'avoir des effets secondaires. Implémentons donc une ou plusieurs fonctions qui prennent des arguments en entrée et, en sortie, produisent ces effets secondaires visuels. Nous nous inspirerons de Super Mario Brothers-- sans surprise, peut-être, ici-- l'original, qui était très bidimensionnel, défilement latéral, de gauche à droite. Mario ou Luigi se déplacent de gauche à droite et doivent généralement sauter par-dessus des choses comme des pyramides ou d'autres formes à l'écran. Alors, comment pourrions-nous implémenter certains des écrans de Super Mario Brothers, bien que textuellement ? Eh bien, nous allons le rendre un peu noir et blanc et en art ASCII, pour ainsi dire, ici en utilisant simplement notre clavier. Mais supposons que nous voulions écrire un programme appelé mario.c qui imprime simplement quatre points d'interrogation. Ce ne sera pas aussi joli que ce qui est à l'écran ici. Mais la logique sera exactement la même que ce que Nintendo a probablement fait il y a des années. Alors, laissez-moi ouvrir VS Code, ma fenêtre de terminal. Codons un programme appelé mario.c. Dans mario.c, je vais commencer par un peu de code boilerplate-- je sais que je veux imprimer. Donc, même si je ne sais pas encore comment faire cela, j'inclurai standard io.h. Pour les besoins d'aujourd'hui, je vais copier-coller ou taper la même ligne encore et encore-- int meow(void). Et à l'intérieur de ma fonction main, à l'instar du clic sur le drapeau vert, je veux imprimer quatre points d'interrogation. Eh bien, honnêtement, la façon la plus simple à laquelle je puisse penser est d'utiliser printf point d'interrogation, point d'interrogation, point d'interrogation, point d'interrogation. Peut-être un backslash n pour déplacer le curseur, et c'est tout. C'est donc sans doute correct. Alors, faisons make mario dans le terminal, "./mario." Et ce n'est pas aussi joli que la version du jeu. Mais c'est, en fait, la même idée. Mais ici, c'est une opportunité, un tremplin pour faire mieux. Ce jeu évolue. Et tous les écrans n'ont pas seulement quatre points d'interrogation. Il peut y en avoir cinq, six, voire plus. Alors, quelle est la bonne construction de programmation avec laquelle nous pourrions généraliser le nombre de points d'interrogation imprimés ici ? Quelle fonctionnalité de C voulons-nous ? Une boucle, comme une boucle for, une boucle while, ou quelque chose comme ça. Et il existe différentes façons de le faire. Mais honnêtement, j'ai proposé plus tôt que nous prenions l'habitude de recourir aux boucles for comme étant très conventionnelles. Faisons donc cela. for int i égale 0; i inférieur à 4-- parce que c'est combien je veux pour le moment-- i++. Et ensuite, à l'intérieur de mes accolades, allons-y et imprimons, guillemet, guillemet, un seul point d'interrogation, mais pas de nouvelle ligne. Laissez-moi maintenant faire make mario. Et pouvez-vous anticiper un bug sans doute esthétique lorsque j'appuierai sur Entrée ? Il ne déplacera pas le curseur à la ligne suivante. Mais la solution ici est un peu non évidente. Cela ne m'aide pas. Si je mets le backslash n là et que je refais make mario et "./mario," à quoi ressemblera cette sortie à la place ? AUDIENCE : [INAUDIBLE] DAVID J. MALAN : Oui, comme une colonne verticale de points d'interrogation, ce qui, bien que joli, n'est pas le but recherché. Le but est ces points d'interrogation horizontaux. Alors, quelqu'un d'autre, quelle est la solution ici, si clairement mettre le backslash n à l'intérieur de la ligne 7 est faux ? AUDIENCE : [INAUDIBLE] DAVID J. MALAN : Oui, donc mettez-le après la boucle, et pas après la ligne printf, spécifiquement après et donc à l'extérieur de la boucle afin qu'après que cette boucle ait fini de s'exécuter trois fois au total, il est tout à fait acceptable de ne rien imprimer d'autre qu'un backslash n tant que nous recompilons maintenant le code, make mario, "./mario." Et, voilà, maintenant nous avons quatre d'affilée. C'est un peu généralisé. OK, nous avons donc résolu un problème assez facile. Eh bien, retournons dans le monde de Mario et essayons quelque chose qui est, en fait, vertical, comme ceci. C'est donc une autre scène avec trois briques ici. Au lieu d'utiliser des points d'interrogation, nous utiliserons des symboles dièse pour représenter les briques. C'est en fait l'incarnation de mon erreur il y a un instant. Alors, annulons cela en supprimant ce printf. Changeons l'intérieur d'un point d'interrogation en un symbole dièse, qui ressemble le plus à
ASCII à une brique. Et allons-y et mettons un antislash n après cela. Si je fais make mario, "./mario", ce n'est pas très intéressant. Mais -- et ce n'est en fait pas très correct car je voulais trois. Donc, pas de problème. Je peux, bien sûr, retourner à mon code et changer le 4 en 3. Ou mieux encore, je pourrais utiliser get_int ou ma nouvelle fonction get_positive_int et simplement généraliser cela davantage afin de pouvoir imprimer n'importe quel nombre d'entre eux. Mais pour l'instant, "./mario" me donne trois. Très bien, nous avons donc résolu le deuxième de deux problèmes. Laissons maintenant les choses s'intensifier un peu. Il s'avère qu'une fois que vous atteignez le Monde 2 et au-delà, il y a des parties souterraines de Mario où vous avez en fait des briques plus grosses et plus solides comme celles-ci. Et à vue de nez, c'est une grille de briques de 3 par 3, comme neuf au total, nous conjecturons. Alors, comment puis-je m'y prendre pour implémenter cela ? Eh bien, c'est là que le programme devient un peu plus intéressant. Et la façon non -- eh bien, la façon mal conçue de faire cela serait comme printf dièse, dièse, dièse, antislash n, point-virgule, et puis peut-être printf, printf. C'est correct mais mal conçu. Donc make mario, "./mario." Cela ne ressemble pas à un carré, juste parce que ces dièses sont plus verticaux qu'horizontaux. Mais c'est correct, cet exemple. Mais ce n'est pas très généralisable. Et c'est littéralement du codage en dur. J'ai copié/collé. Je fais juste beaucoup de mauvaises pratiques ici. Alors, que pourrais-je faire à la place ? Eh bien, il s'avère que nous pouvons combiner les idées d'aujourd'hui, y compris les boucles, pour faire les choses encore et encore. Alors, qu'est-ce que cette grille de briques ? C'est un 3 par 3. C'est donc comme une rangée et une rangée et une rangée. Et puis, dans chaque rangée, il y a une colonne, une colonne, une colonne. C'est donc aussi comme une vieille machine à écrire qui imprime une ligne, puis la ligne suivante, puis la ligne suivante, et ainsi de suite. Alors, comment pouvons-nous conjurer cela dans le code ? Eh bien, laissez-moi faire cela. Je pense qu'une approche d'impression fonctionnerait comme ceci. Pour int i égal 0, i inférieur à 3, i plus plus, parce que je sais que je veux faire quelque chose trois fois -- mais qu'est-ce que je veux faire trois fois ? Cette boucle représente, dans mon esprit, rangée, rangée, rangée. Donc, en fait, je pourrais être plus pédant. Si je veux que mon i signifie quelque chose au-delà de int, je pourrais dire rangée égale 0, rangée inférieure à 3, rangée plus plus, juste pour m'aider à y penser. Et alors, que veux-je faire sur chaque rangée ? Que veux-je imprimer ? Colonne, colonne, colonne, donc brique, brique, brique. Alors, comment imprimer trois briques ou n'importe quel nombre de briques ? Eh bien, je pourrais tricher et juste faire printf dièse, dièse, dièse, antislash n. Mais encore une fois, je ne peux pas généraliser. Je ne peux pas prendre une entrée de l'utilisateur et imprimer quatre ou cinq ou six briques. Cela va donc me causer des problèmes à terme. Alors peut-être que je pourrais utiliser une boucle. Je pourrais donc faire pour int i égal 0, i inférieur à 3, i plus plus à l'intérieur de ma boucle. Et puis ici, je pourrais imprimer un dièse. Et c'est un peu dans la bonne direction, le bon chemin, car maintenant j'utilise juste le bloc de construction simple, ou brique, mais je le réutilise encore et encore. Et il est tout à fait acceptable d'avoir imbriqué ces colonnes de cette manière. J'ai utilisé i par habitude. Mais quel serait un meilleur nom ? Eh bien, peut-être "colonne", ou peut-être juste C-O-L, "col" en abrégé, de sorte que mon code dise ce qu'il fait pour moi. Et je n'ai pas besoin d'utiliser "rangée" ou "colonne" explicitement. Je n'ai pas besoin de les imprimer. Mais je les utilise comme compteurs l'un après l'autre. Alors laissez-moi faire make Mario, "./mario." Et je me sens bien à ce sujet, mais -- ugh. Zut, il y a neuf briques. Mais elles ne sont pas vraiment disposées. Pourquoi ? Quel est le correctif ? Oui. AUDIENCE : Vous n'êtes jamais passé à une nouvelle ligne. DAVID J. MALAN : Oui, je ne suis jamais passé à une nouvelle ligne. Et laissez-moi faire ce que je pense que vous ne me suggérerez pas de faire. Laissez-moi aller à l'endroit évident. Très bien, eh bien, mettons-en une juste après la brique. Mais, bien sûr, si je fais make mario, "./mario", je fais la même erreur qu'avant. J'imprime trop de nouvelles lignes. Alors, entre quelles lignes dois-je réellement imprimer une nouvelle ligne ? Entre, oui ? AUDIENCE : 10 et 11. DAVID J. MALAN : Oui, donc 10 et 11. Donc, en dehors de la boucle interne mais à l'intérieur de la boucle externe, donc cela se produit encore et encore. Alors, imprimons, comme avant, un simple antislash n, point-virgule. Maintenant, faisons make mario, "./mario," Entrée. Ah, maintenant c'est généralisé comme je le souhaite. Et si je voulais vraiment m'attarder sur cela, je pourrais aller et inviter l'utilisateur avec get_int ou avec get_positive_int, déterminer quelle rangée et/ou colonne devrait être. Nous pouvons faire n'importe quelle taille de brique que nous voulons. Mais maintenant, nous avons un bon point de départ. Mais il y a une autre façon de penser à cela car j'ose dire, surtout pour votre premier devoir CS50, si vous essayez d'imprimer des briques et le monde de Mario de cette façon, ce ne sera probablement pas évident de trouver des boucles comme celles-ci et de les faire fonctionner comme par magie en 45 secondes au total. Ce sera une lutte au début. Mais il y a des modèles à suivre. Donc, un, il est assez conventionnel néanmoins d'utiliser juste i, puis j, puis k, puis l. Et si vous avez des boucles imbriquées, imbriquées, imbriquées, imbriquées, à un moment donné de l'imbrication, vous écrivez probablement du mauvais code. Ce n'est pas bien conçu. Mais une ou deux ou peut-être trois imbrications pourraient être une bonne chose. Mais vous ne pouvez pas utiliser et réutiliser i encore et encore. Pourquoi ? Parce que si vous comptez i ici, mais que vous changez ensuite i ici pour faire vos colonnes de gauche à droite, vous allez désynchroniser tous vos calculs. Vous avez donc besoin de deux variables séparées. i et j sont conventionnels. Ou rangée et colonne fonctionneraient aussi. Mais si nous revenons à cette idée de rangées et de colonnes, eh bien, laissez-moi en fait factoriser quelque chose ici. Et cela pourrait vous aider à la place. Supposons que vous vous attaquiez à ce problème. Vous savez que vous voulez faire quelque chose trois fois. Mais vous ne comprenez pas tout à fait comment imprimer ces rangées. Eh bien, faites un pas de bébé, une bouchée du problème, et faites peut-être ceci. Créez une fonction sans sortie, juste un effet secondaire dont le but dans la vie est d'imprimer une rangée. Et combien de rangées ? Eh bien, peut-être n pour un certain nombre de rangées -- pour un certain nombre de briques, plutôt. Comment imprimer une rangée de briques ? Eh bien, laissez-moi juste y penser isolément. Comment imprimer une seule rangée de briques ? C'est facile -- pour int i égal 0, i est inférieur à n -- si je généralise -- i++, et puis -- oups, i++. Et puis, à l'intérieur de nos accolades, allez-y et imprimez simplement un seul dièse. Et à la fin, comme vous l'avez suggéré, imprimez une seule nouvelle ligne. En d'autres termes, abstrayez l'idée d'imprimer une seule rangée. Et en fait, à ce stade de l'histoire, surtout si vous avez du mal à commencer, vous n'avez même pas besoin de commencer par main. Prenez une bouchée du problème qui a du sens pour vous et qui est plus petite que le problème entier, imprimer une seule rangée, car vous pourrez alors venir et itérer. Ensuite, vous pourrez aller et dire, OK, écrivons maintenant ma fonction main réelle. Donc int meow(void), comme toujours. Et maintenant, que veux-je faire ? Je veux imprimer un tas de rangées. Comment imprimer un tas de rangées ? Oh, mon Dieu, c'est comme la même idée -- pour int i égal 0, i est inférieur à, appelons cela 3 pour l'instant -- mais nous pouvons généraliser cela -- i++. Et que veux-je faire à chaque itération de cette boucle ? Mon Dieu, imprimez juste une rangée avec trois briques. Et puis nous avons fini. Encore une fois, loin des yeux, loin du cœur, cette fonction peut disparaître et ne jamais être vue auparavant car une fois que print_row existe, c'est ce qu'elle fait en fait pour moi. Maintenant, ce n'est pas 100% correct. J'ai toujours besoin de mon prototype car si j'ai créé ma propre fonction, je dois dire à C à l'avance qu'elle existera. J'ai donc besoin de copier et coller cette ligne de code. Si j'étais vraiment pédant, c'est une mauvaise conception. En général, lorsque vous avez le même nombre à plusieurs endroits dans un programme, un programmeur appellerait cela un "nombre magique". Comme, comment cela fonctionne-t-il ? Juste sur parole, que vous utilisez le même nombre encore et encore. Donc une meilleure solution ici, même si vous n'allez pas prendre l'entrée de l'utilisateur, serait de faire ceci -- int n égal 3. Et puis utilisez n ici. Et puis utilisez n ici. Ou vous pouvez l'appeler comme vous voulez. Mais maintenant, vous avez spécifié 3 en un seul endroit. Et nous pouvons aller un peu plus loin. Il s'avère que, en C et dans d'autres langages, vous pouvez vous protéger contre vous-même. Si vous savez qu'une variable ne doit jamais changer sa valeur, elle doit toujours rester 3 dans ce cas, vous pouvez utiliser ce qu'on appelle une constante, où vous pouvez spécifiquement dire, je ne veux pas juste que n soit un int. Je veux que ce soit un const int, "const" en abrégé pour "constant". Et cela signifie que même si j'essaie de changer n dans mon code, le compilateur ne me le permettra pas. Je peux donc me protéger de moi-même, ou dans le monde réel, vous pouvez utiliser une variable que aucun de vos collègues ne peut changer bêtement sans que vous vous rendiez compte que cela s'est produit. Donc, beaucoup de programmation, honnêtement, c'est juste ne pas se faire confiance le lendemain matin quand on a oublié ce qu'on a écrit, sans parler du mois prochain, de l'année prochaine quand on écrit du code dans le monde réel. Les constantes nous donnent donc une fonctionnalité pour nous défendre contre nous-mêmes. Il existe une autre fonctionnalité utile, surtout lorsque vous vous réveillez le lendemain et que vous vous dites, oh, mon Dieu, comment ce code fonctionne-t-il ? Que fait-il ? Eh bien, il y a des commentaires dans le code. Et certains d'entre vous l'ont peut-être utilisé dans Scratch. Vous pourriez ajouter de petites notes autocollantes jaunes dans Scratch pour les "commentaires". Dans le code, vous pouvez faire quelque chose comme ceci. Vous pouvez, si vous voulez mettre un rappel en anglais pour vous-même, ou si vous parlez une autre langue humaine -- un commentaire en espagnol ou dans toute autre langue humaine -- vous pouvez l'écrire avec un antislash antislash au début de la ligne. Et puis vous pouvez dire quelque chose comme, imprimer n rangées. Et cela vous dit, dans un commentaire, ce que font les lignes de code suivantes. C'est une sorte de note pour soi-même. Cela n'a aucune fonctionnalité pour l'ordinateur. C'est juste une note pour vous-même. Ou vous pouvez dire quelque chose comme ceci, comme ne jamais changer n, parce que vous précisez qu'il est bien constant. Mais cela aussi est un peu pédant puisque const dit la même chose. Mais les commentaires sont des notes pour soi-même pour vous aider à vous souvenir de ce que quelque chose fait ou pourquoi vous l'avez fait de cette façon. Des questions maintenant sur l'un de ces problèmes de Mario que nous avons résolus ? Non ? Très bien, donc un dernier ensemble d'exemples qui poussent les limites de ce que les ordinateurs peuvent réellement faire. Jusqu'à présent, nous avons résolu tous les problèmes que j'ai proposés. Mais c'est parce que j'ai un peu contourné certains des défis sous-jacents. Il s'avère que nous avons non seulement des fonctions qui nous donnent des effets secondaires visuellement à l'écran. Nous avons à nouveau des fonctions qui ont des valeurs de retour. Concentrons-nous donc sur celles-ci et sur les endroits où les choses peuvent mal tourner. Et utilisons également un tas d'autres opérateurs. Il suffit de dire que les ordinateurs ont commencé par être de très bons calculateurs. Les ordinateurs prennent donc en charge l'addition, la soustraction, la multiplication, la division, les opérateurs de reste, représentés par le signe de pourcentage ici, qui indique de prendre le reste de quelque chose sur autre chose. Et il y a encore plus d'opérateurs que cela. Alors allons-y et implémentons notre propre calculatrice en quelque sorte qui a en fait quelques bugs en cours de route. Laissez-moi retourner à VS Code ici. Je vais fermer mario.c, ouvrir mon terminal, et coder un dernier fichier appelé calculator.c. Et dans ce fichier de calculatrice, faisons quelque chose de super simple initialement. Incluons CS50.h. Incluons standard io.h. Faisons int meow(void), comme toujours -- tout est boilerplate jusqu'à présent. Et maintenant, faisons quelque chose de plus intéressant -- int x égal get_int. Et nous demanderons à l'utilisateur une valeur x. int y -- demandons à l'utilisateur une valeur y, comme nous l'avons fait précédemment pour comparer des nombres. Et faisons quelque chose de super simple. Donnons-nous une autre variable, int z égal x plus y. Et puis imprimons la somme. Donc printf, guillemet, guillemet -- et je ne fais pas de percent s ici. Si je veux imprimer un nombre -- quelqu'un l'a dit plus tôt -- nous voulons percent s pour une chaîne mais percent i pour un entier. Antislash n, et imprimons la valeur de z. C'est donc une calculatrice un peu stupide. Elle additionne juste deux nombres. Mais cela va démontrer certains points. Donc make calculator, Entrée. Jusqu'à présent, tout va bien -- "./calculator." Disons juste que x est 1, y est 2, z sera 3. Ce code est correct, bien que simple. Y a-t-il une opportunité pour une conception marginalement meilleure ? Pourrions-nous le resserrer, le raccourcir ? Moins de lignes signifie une probabilité plus faible de bugs, probablement. Oui. AUDIENCE : Vous n'avez pas besoin de fournir une variable z séparée. DAVID J. MALAN : Oui, nous n'avons pas vraiment besoin d'une variable z séparée. Je veux dire, c'est bien si c'est plus clair pour vous, si c'est plus clair pour votre TF, si c'est plus clair pour vos collègues. Mais honnêtement, c'est tellement relativement simple, je pense que nous allons juste nous débarrasser de z et dire quelque chose comme x plus y ici, ce qui est tout à fait raisonnable aussi. Mais vous ne voulez pas pousser cela à l'extrême. Diable, si nous n'avons pas besoin de z, avons-nous vraiment besoin de x et y ? Eh bien, nous pourrions faire quelque chose comme ceci. Laissez-moi en fait -- oups -- laissez-moi en fait supprimer ces lignes de code et prétendre -- nous pouvons faire tout cela en une seule ligne très jolie. Nous pourrions faire, disons, get_int x plus get_int y. Et remarquez maintenant, comme l'exemple de jointure la dernière fois, j'appelle get_int une fois, get_int deux fois. Les deux retournent une valeur, qui sera 1 et 2 respectivement en fonction de ce que j'ai tapé plus tôt. Ensuite, je fais 1 plus 2. Cela va dans printf comme deuxième argument. C'est en fait correct et fonctionnera. C'est juste stupide. Ne faites pas ça. Nous avons franchi une ligne mal définie où c'est juste plus difficile à lire maintenant. Et donc, même si les variables ne sont pas strictement nécessaires, je dirais, et la plupart des programmeurs diraient, c'est juste beaucoup plus lisible. Chaque ligne fait un peu moins de travail. Il y a moins de chances d'erreur. Cela a juste un peu plus de sens. Mais les gens raisonnables seront en désaccord. Par conséquent, cela signifie que, au fil du temps, vous et votre TF pourriez être en désaccord. Vous et vos collègues pourriez être en désaccord. Et à ce moment-là, les débats religieux commenceront quant à la bonne façon de faire. Très bien, c'est une calculatrice. Faisons autre chose qui double juste un nombre ici. Laissez-moi changer cela pour obtenir un seul entier de l'utilisateur. Appelons-le x. Et doublons-le tout simplement. Donc printf, percent i, antislash n, x fois 2. Nous allons simplement doubler cela. L'opérateur étoile est bien la multiplication dans ce cas. Cela va donc doubler mon nombre. Donc make calculator à nouveau, "./calculator." Entrée. Et tapons 1. Et j'obtiens 2. Relançons-le. Tapons 2, j'obtiens 4. Tapons encore. Tapons 3. J'obtiens 6, et ainsi de suite. Très bien, ce n'est pas mal dans ce cas ici. Mais si nous voulons écrire un programme correct ? En fait, oui, voyons. C'est un peu un mème qui va et vient. Laissez-moi voir si vous reconnaissez cela. Je vais dire une autre variable -- pas x. Soyons plus précis, comme int dollars égal 1. Et puis laissez-moi induire délibérément une boucle infinie. Parfois, il est utile d'induire une boucle infinie tant que vous en sortez éventuellement d'une manière ou d'une autre si vous ne voulez pas que le programme s'exécute indéfiniment. Je vais poser à l'utilisateur une question lui demandant un char c en utilisant get_char. Et je vais lui demander, guillemet, guillemet, "Voici percent i." Point. "Doublez-le et donnez-le à la personne suivante ?" Point d'interrogation. Cela me dit quelque chose. Et puis nous pouvons passer à get_char la valeur dollars ici. Donc, en fait, cela semble déjà un peu cryptique. Je vais mettre un signe dollar devant, comme si nous traitions de la monnaie américaine. Et que voulons-nous faire ? Et si l'utilisateur dit y pour oui -- doublez-le et donnez-le à la personne suivante -- alors faisons dollars. Et doublons "dollar". Je peux faire dollars égal dollars fois 2. Ou rappelez-vous l'astuce pour plus et moins. Je peux aussi faire fois égal 2, ce qui le double en une seule ligne également. Juste un peu de sucre syntaxique, comme les programmeurs l'appellent, qui resserre simplement votre code même si c'est exactement la même chose. Mais que se passe-t-il si l'utilisateur ne tape pas y et veut garder l'argent ? Eh bien, nous avons une condition else. À ce moment-là, vous ne voulez pas continuer à demander, demander, demander avec get_char. Sortons plutôt de cette boucle. Donc break est un autre mot-clé qui, si vous êtes à l'intérieur d'une boucle for, d'une boucle while, d'une boucle do-while, vous pouvez sortir de la boucle prématurément si et quand vous le souhaitez. Et donc cela satisfait l'objectif de s'assurer que cela ne s'exécute pas indéfiniment, mais cela va s'exécuter encore et encore et encore pendant que nous continuons à interroger l'utilisateur avec cette question. Voyons maintenant ce qui se passe, sauf qu'à la fin, assurons-nous que l'utilisateur sache combien d'argent il emporte. Voici signe dollar, percent i, antislash n, dollars. Nous verrons donc, à la fin, quel montant en dollars la personne finit par avoir. Make calculator, Entrée. "./calculator." Et laissez-moi augmenter la taille de ma fenêtre de terminal. Alors voilà. "Voici 1 $. Doublez-le et donnez-le à la personne suivante ?" Oui. "Voici 2 $. Doublez-le et donnez-le à la personne suivante ?" Oui, oui, oui, oui, oui. Les Reels Instagram ne sont pas si longs. Mais si vous continuez à doubler encore et encore, c'est ce qu'on appelle l'exponentiation, ce qui vous rendra très riche très rapidement car, remarquez, nous sommes déjà dans les milliers de dollars en disant simplement oui et oui et oui. C'est une question sociétale intéressante quant au montant en dollars pour lequel vous garderiez l'argent et ne le doubleriez plus et ne le passeriez pas. Mais pour l'instant, nous allons continuer à le doubler car cela devient de plus en plus grand, apparemment infiniment grand. Et le programme C -- mais, oh, mon Dieu, apparemment les Reels Instagram ont coupé le mème trop court car finalement il devient négatif puis 0. Que se passe-t-il réellement ? Le code est en fait correct. Mais nous nous heurtons à un problème différent. Une intuition sur ce qui ne va pas réellement ici ? Ce n'est pas un doublement infini. Oui. AUDIENCE : Il n'y a pas assez de bits pour stocker. DAVID J. MALAN : Oui, il n'y a pas assez de bits pour stocker des nombres de plus en plus grands. Rappelez-vous, avec 32 bits, ce qui se trouve être la taille de la plupart des int, vous pouvez compter jusqu'à 4 milliards si vous commencez à 0 ou environ 2 milliards si vous voulez gérer aussi les nombres négatifs, de moins 2 milliards à plus 2 milliards. Donc, éventuellement, une fois que j'atteins 2 milliards de dollars, ou 1 milliard de dollars, cela devient négatif. Et puis cela devient 0. C'est à cause de quelque chose appelé dépassement d'entier, où si vous n'avez qu'un nombre fini de bits et que vous continuez à les incrémenter, à les incrémenter, à les incrémenter, vous ne pouvez finalement pas simplement reporter le 1 car il n'y a pas de 33ème bit. Donc, tous les autres bits reviennent de uns à zéros. Et il semble que vos 32 bits soient tous 0 car le 33ème bit était censé être le 1, mais il n'est pas là. Ils n'ont pas assez de mémoire. C'est donc un problème fondamental avec les ordinateurs où si vous comptez suffisamment haut, les choses commenceront à casser, du moins si vous utilisez C ou C++ ou certains autres langages qui ne l'anticipent pas. Et il y a une implication très réelle de cela. Voici donc une photographie de quelque chose que nous examinerons plus en détail à l'avenir : la mémoire à l'intérieur de votre ordinateur ou de votre téléphone ou de tout appareil électronique. Il suffit de dire qu'il n'y a qu'une quantité finie de mémoire. Et si vous n'utilisez que 32 bits alors, ou même trois bits, vous déborderez éventuellement. Nous avons utilisé trois bits la semaine dernière. Voici donc un exemple. En binaire, si vous n'utilisez que trois bits, selon les chiffres blancs ici -- j'ai mis en gris le quatrième juste pour vous montrer quel report nous pourrions vouloir avoir -- voici 0, 1, 2, 3, 4, 5, 4, 7, comme la semaine dernière. Et comme la semaine dernière, quelqu'un a dit, comment arrivons-nous à 8 ? Nous avons besoin d'un autre bit. Mais si ce bit est grisé parce qu'il n'existe pas, nous avons juste dépassé cet entier minuscule et sommes revenus à 0, tout comme mon argent est revenu à 0. Alors, comment éviter cela ? Une façon de faire cela est ceci. Laissez-moi appuyer sur Control-C pour sortir du programme. Ou je pourrais simplement taper "non". Laissez-moi réduire ma fenêtre de terminal et la nettoyer ici. Je pourrais en fait faire ceci. Il s'avère que les int utilisent généralement 32 bits. Mais il existe un autre type de données qui était sur la diapositive précédente appelé long, qui est une version plus longue d'un int, qui est de 64 bits, ce qui est incroyablement grand. Il n'y a pas autant de dollars dans le monde. Mais c'est toujours fini, même si je ne peux pas prononcer un nombre aussi grand. Mais si nous changeons tous nos int en longs et que nous changeons notre espace réservé de percent i à percent li, pour long int, je peux en fait compter de plus en plus haut. Donc, à titre d'exemple, laissez-moi en fait retourner à mon terminal -- make calculator, Entrée. Rendez-le à nouveau plus grand -- "./calculator." Et je vais juste continuer à dire oui mais plus vite cette fois. La séquence est exactement la même. Mais rappelez-vous qu'une fois que nous sommes arrivés dans les milliards, cela a commencé à revenir en arrière vers le négatif puis vers 0. C'est beaucoup d'argent maintenant. Les longs sont en effet plus longs. Et je pourrais faire cela probablement toute la journée. Oh, intéressant. Je n'aurais pas dû dire ça. Je ne peux pas faire ça toute la journée car éventuellement un long, aussi, débordera. [CHUCHOTEMENTS] Je ne pensais juste pas que cela arriverait si vite. Donc, un long, aussi, débordera car nous aurons besoin d'un 65ème bit, mais l'ordinateur ne l'a pas alloué. Donc, cela devient aussi un problème de dépassement. Pour lire un extrait, ce sont des problèmes très réels. Et en fait, voici une photographie de quelque chose que nous regarderons plus tard : la mémoire à l'intérieur de votre ordinateur ou de votre téléphone ou de tout appareil électronique. Il suffit de dire qu'il n'y a qu'une quantité finie de mémoire. Et si vous n'utilisez que 32 bits alors, ou même trois bits, vous déborderez éventuellement. Nous avons utilisé trois bits la semaine dernière. Voici donc un exemple. En binaire, si vous n'utilisez que trois bits, selon les chiffres blancs ici -- j'ai mis en gris le quatrième juste pour vous montrer quel report nous pourrions vouloir avoir -- voici 0, 1, 2, 3, 4, 5, 4, 7, comme la semaine dernière. Et comme la semaine dernière, quelqu'un a dit, comment arrivons-nous à 8 ? Nous avons besoin d'un autre bit. Mais si ce bit est grisé parce qu'il n'existe pas, nous avons juste dépassé cet entier minuscule et sommes revenus à 0, tout comme mon argent est revenu à 0. Alors, comment éviter cela ? Une façon de faire cela est ceci. Laissez-moi appuyer sur Control-C pour sortir du programme. Ou je pourrais simplement taper "non". Laissez-moi réduire ma fenêtre de terminal et la nettoyer ici. Je pourrais en fait faire ceci. Il s'avère que les int utilisent généralement 32 bits. Mais il existe un autre type de données qui était sur la diapositive précédente appelé long, qui est une version plus longue d'un int, qui est de 64 bits, ce qui est incroyablement grand. Il n'y a pas autant de dollars dans le monde. Mais c'est toujours fini, même si je ne peux pas prononcer un nombre aussi grand. Mais si nous changeons tous nos int en longs et que nous changeons notre espace réservé de percent i à percent li, pour long int, je peux en fait compter de plus en plus haut. Donc, à titre d'exemple, laissez-moi en fait retourner à mon terminal -- make calculator, Entrée. Rendez-le à nouveau plus grand -- "./calculator." Et je vais juste continuer à dire oui mais plus vite cette fois. La séquence est exactement la même. Mais rappelez-vous qu'une fois que nous sommes arrivés dans les milliards, cela a commencé à revenir en arrière vers le négatif puis vers 0. C'est beaucoup d'argent maintenant. Les longs sont en effet plus longs. Et je pourrais faire cela probablement toute la journée. Oh, intéressant. Je n'aurais pas dû dire ça. Je ne peux pas faire ça toute la journée car éventuellement un long, aussi, débordera. [CHUCHOTEMENTS] Je ne pensais juste pas que cela arriverait si vite. Donc, un long, aussi, débordera car nous aurons besoin d'un 65ème bit, mais l'ordinateur ne l'a pas alloué. Donc, cela devient aussi un problème de dépassement. Pour lire un extrait, ce sont des problèmes très réels. Et en fait, voici une photographie de quelque chose que nous examinerons plus en détail à l'avenir : la mémoire à l'intérieur de votre ordinateur ou de votre téléphone ou de tout appareil électronique. Il suffit de dire qu'il n'y a qu'une quantité finie de mémoire. Et si vous n'utilisez que 32 bits alors, ou même trois bits, vous déborderez éventuellement. Nous avons utilisé trois bits la semaine dernière. Voici donc un exemple. En binaire, si vous n'utilisez que trois bits, selon les chiffres blancs ici -- j'ai mis en gris le quatrième juste pour vous montrer quel report nous pourrions vouloir avoir -- voici 0, 1, 2, 3, 4, 5, 4, 7, comme la semaine dernière. Et comme la semaine dernière, quelqu'un a dit, comment arrivons-nous à 8 ? Nous avons besoin d'un autre bit. Mais si ce bit est grisé parce qu'il n'existe pas, nous avons juste dépassé cet entier minuscule et sommes revenus à 0, tout comme mon argent est revenu à 0. Alors, comment éviter cela ? Une façon de faire cela est ceci. Laissez-moi appuyer sur Control-C pour sortir du programme. Ou je pourrais simplement taper "non". Laissez-moi réduire ma fenêtre de terminal et la nettoyer ici. Je pourrais en fait faire ceci. Il s'avère que les int utilisent généralement 32 bits. Mais il existe un autre type de données qui était sur la diapositive précédente appelé long, qui est une version plus longue d'un int, qui est de 64 bits, ce qui est incroyablement grand. Il n'y a pas autant de dollars dans le monde. Mais c'est toujours fini, même si je ne peux pas prononcer un nombre aussi grand. Mais si nous changeons tous nos int en longs et que nous changeons notre espace réservé de percent i à percent li, pour long int, je peux en fait compter de plus en plus haut. Donc, à titre d'exemple, laissez-moi en fait retourner à mon terminal -- make calculator, Entrée. Rendez-le à nouveau plus grand -- "./calculator." Et je vais juste continuer à dire oui mais plus vite cette fois. La séquence est exactement la même. Mais rappelez-vous qu'une fois que nous sommes arrivés dans les milliards, cela a commencé à revenir en arrière vers le négatif puis vers 0. C'est beaucoup d'argent maintenant. Les longs sont en effet plus longs. Et je pourrais faire cela probablement toute la journée. Oh, intéressant. Je n'aurais pas dû dire ça. Je ne peux pas faire ça toute la journée car éventuellement un long, aussi, débordera. [CHUCHOTEMENTS] Je ne pensais juste pas que cela arriverait si vite. Donc, un long, aussi, débordera car nous aurons besoin d'un 65ème bit, mais l'ordinateur ne l'a pas alloué. Donc, cela devient aussi un problème de dépassement. Pour lire un extrait, ce sont des problèmes très réels. Et en fait, voici une photographie d'un Boeing 787 il y a des années qui a en fait eu des problèmes au-delà des problèmes les plus récents avec les avions Boeing, où après 248 jours, le Boeing 787, il y a des années, peut perdre toute son alimentation électrique en raison des unités de contrôle du générateur entrant simultanément en mode de sécurité, quoi que cela signifie. Mais si vous creusez cela, il s'avère qu'il y avait un compteur logiciel dans ces avions il y a des années qui débordait après 248 jours d'alimentation continue. 248 jours, pourquoi ? Eh bien, Boeing utilisait un entier de 32 bits. Et ils l'utilisaient pour compter les dixièmes de seconde. Et il s'avère que, si vous faites le calcul, après 248 jours, vous avez utilisé trop de dixièmes pour dépasser la taille d'un entier de 32 bits. L'avion aurait essentiellement cet entier, cette petite variable stupide, qui débordait. Mais en général, lorsque vos nombres deviennent soudainement négatifs ou 0, de mauvaises choses se produisent. L'avion pourrait littéralement perdre son alimentation en plein vol ou au sol. Et si vous pouvez le croire, qui veut deviner quelle était la solution de contournement de Boeing jusqu'à ce qu'ils corrigent le logiciel réel ? AUDIENCE : [INAUDIBLE] Qu'est-ce que c'est ? AUDIENCE : [? C'est pour ?] [INAUDIBLE]. DAVID J. MALAN : Même pas -- redémarrez l'avion. On leur a dit, tous les quelques jours, certainement tous les 248 jours, d'éteindre l'alimentation, de la rallumer, ce qui, stupidement, est ce qu'on nous a dit pendant des années avec nos Mac et nos PC et nos téléphones. Pourquoi ? Parce que parfois, à cause de bugs logiciels, les ordinateurs entrent dans des états étranges, ce qui est une façon familière de dire qu'un programmeur a fait une erreur et qu'un compteur a débordé ou qu'une condition n'a pas été gérée et que des choses étranges et inattendues se produisent. Donc, redémarrer réinitialise toutes vos variables à leurs valeurs d'origine et vous donne plus de temps, plus de marge de manœuvre dans ce cas, sans jeu de mots. Il y en a d'autres. En fait, l'un des plus célèbres des années 1980 était le jeu original Pac-Man -- il ne prenait en charge que 255 niveaux. Pourquoi ? Ils utilisaient 8 bits. Rappelez-vous que 8 bits vous donnent 256. Mais si vous commencez à compter à partir de 0, vous ne pouvez aller qu'à 255. Donc, les enfants fous qui étaient si bons à Pac-Man qu'ils ont atteint le niveau 256, les créateurs de Pac-Man n'avaient pas anticipé que quelqu'un gagnerait autant de niveaux. Et des choses étranges se sont produites à l'écran. Tous les fruits ont commencé à écraser tout le reste car ils n'avaient pas assez de mémoire allouée au niveau, ni de condition qui disait, si niveau égal égal 255, "vous gagnez." Il n'y avait rien pour gérer ce cas d'angle, pour ainsi dire. Donc, ces choses abondent même de nos jours. Heureusement, dans certains langages, il existe de meilleures solutions où vous pouvez utiliser de grands entiers. Et vous utiliserez 64, peut-être 128, peut-être 256 bits. Mais vous devez utiliser un langage ou une bibliothèque qui vous permet de faire croître et rétrécir la quantité de mémoire utilisée. Et beaucoup, sinon la plupart des langages, ne font pas cela pour nous. Il y a donc quelques problèmes finaux à voir que nous avons pris pour acquis jusqu'à présent. Et ils impliquent également des nombres et de la mémoire. Revenons donc à notre calculatrice. Jetons tout ce code mème ici. Et au lieu de cela, faisons quelque chose de simple à nouveau. int x égal get_int. Et demandons à l'utilisateur une variable x. int y égal get_int, demandons à l'utilisateur une variable y. Et cette fois, au lieu de l'addition, au lieu du doublement, faisons la division. Donc printf, guillemet, guillemet, percent i antislash n. Et puis insérez x divisé par y. Vous utilisez donc une seule barre oblique pour la division. Laissez-moi faire, make calculator ici, "./calculator." Et faisons 1 divisé par 3, ce qui devrait, en fait, être -- ce n'est pas vraiment 0. C'est comme 0,333. Essayons encore. Que diriez-vous de "./calculator" 3 divisé par 2 ? Devrait être 1,5. Non, l'ordinateur pense que c'est 1. Eh bien, que se passe-t-il ici ? Eh bien, il s'avère que, lorsque vous utilisez des entiers dans un programme, vous êtes vulnérable à ce qu'on appelle la troncature. Un entier plus un entier vous donne un entier. Un entier divisé par un entier, curieusement, vous donne un entier. Donc, même si la réponse est censée être 0,333 ou 1,5, tout dans le monde des entiers jette le point décimal et au-delà. Et vous n'obtenez que la partie entière de la valeur. Ce n'est donc même pas un arrondi. C'est la troncature de tout ce qui suit la virgule. Ce programme n'est donc tout simplement pas correct. Mais il existe des solutions potentielles. Par exemple, si je retourne dans mon code ici et que j'utilise un code de format différent que nous n'avons pas encore utilisé -- nous avions s pour string, i pour int. Il y a aussi f pour float. Et un float était comme un nombre réel, quelque chose avec un point décimal par définition. Nous ne l'avons pas encore utilisé. Je pourrais dire à l'ordinateur d'imprimer cela comme un float. Laissez-moi donc faire make calculator à nouveau. Et maintenant, hm, il spécifie le type double. Il y a une erreur ici. Le problème est que je ne peux pas simplement dire à l'ordinateur de formater ce nombre comme un float. Je dois convertir le nombre, x divisé par y, en un float. Et je peux le faire de plusieurs façons. Premièrement, je pourrais littéralement tout convertir en floats et simplement éviter le problème. Utiliser float, utiliser get_float, utiliser percent f, et j'ai terminé. Mais si je veux utiliser des int pour une raison quelconque -- parce que je veux que l'utilisateur tape des entiers, mais je veux leur montrer des nombres réels avec des points décimaux pour des calculs corrects -- je peux faire ce qu'on appelle un transtypage de valeur. Je peux, entre parenthèses -- ce qui est une nouvelle utilisation étrange des parenthèses -- je peux dire, hé, ordinateur, traite s'il te plaît l'entier suivant comme un float à la place, évitant ainsi la troncature. Ne tronque pas pour moi. Donc, si j'exécute maintenant make calculator à nouveau, "./calculator," et que je tape, par exemple, 1 pour x, 3 pour y, maintenant j'obtiens une valeur à virgule flottante réelle. Je la formate comme telle. Et je dis à l'ordinateur de la calculer arithmétiquement comme telle aussi. Mais ici aussi, je vous vole un peu la réalité. Il s'avère -- laissez-moi effacer cet écran ici. Et il s'avère qu'il existe des moyens sophistiqués dans printf pour lui dire combien de chiffres afficher, combien de chiffres significatifs. Et la syntaxe est très étrange. Je dois la rechercher constamment. Mais au lieu de dire simplement percent f, vous y insérez littéralement des nombres. Et vous dites point 5. Et cela dira -- c'est une syntaxe étrange -- hé, printf, formate cela à cinq chiffres à la place. Laissez-moi donc faire make calculator à nouveau, "./calculator." Et faisons 1 divisé par 3. Et en effet, j'obtiens cinq chiffres significatifs ici. Mais supposez que je devienne un peu fou et que je veuille 50 chiffres significatifs. Eh bien, selon l'école primaire, je devrais juste voir plus de 3. Mais regardez ça. Make calculator, "./calculator." Et il s'avère que celui qui vous a enseigné les mathématiques de l'école primaire vous a un peu menti, car si vous le faites vraiment avec un Mac, un PC ou un téléphone puissant, un tiers est en fait 0,3333333334326744079 -- [SOUPIRS] qui a raison ? Monsieur et Madame Untel de l'école primaire ou d'Internet ? Que se passe-t-il ? Qu'est-ce qui explique cela ? Tout cela se résume d'une manière ou d'une autre à [? faibles ?] zéros et uns. Pourquoi ce nombre à virgule flottante est-il imprécis, pour ainsi dire ? Quelle est l'intuition ? Oui. AUDIENCE : Est-ce similaire à ce qui s'est passé plus tôt où il y a eu un dépassement ? DAVID J. MALAN : Oui, similaire dans l'esprit. Tout comme les int n'utilisent que 32 bits, les floats n'utilisent également que 32 bits. Si vous en voulez plus, tout comme int a long, les floats ont quelque chose appelé "double". Je pourrais donc éviter une partie du problème en passant à double. Mais ce sera toujours fini. Et si vous y pensez intuitivement, si vous utilisez un nombre fini de bits, que ce soit 32 ou 64, vous ne pouvez représenter littéralement qu'un certain nombre de motifs et donc un certain nombre de valeurs à virgule flottante, un certain nombre de nombres réels. Mais combien de nombres réels y a-t-il dans le monde ? Littéralement une infinité, c'est le défi des nombres réels. Vous pouvez continuer à ajouter des nombres après le chiffre. Alors, comment un ordinateur, Mac, PC ou autre, pourrait-il représenter chaque valeur à virgule flottante avec une super précision s'il n'y a pas assez de motifs pour représenter chaque nombre dans le monde ? De plus, la façon dont les ordinateurs utilisent pour représenter les nombres ne leur permet parfois pas de représenter les nombres avec autant de précision. Nous pouvons obtenir plus de chiffres significatifs peut-être, mais pas une perfection ou une précision à 100 %. La précision des nombres à virgule flottante est donc également un problème fondamental avec les ordinateurs aujourd'hui. Et à moins, encore une fois, que vous n'utilisiez un langage ou une bibliothèque spécialisée qui comprend, pour le calcul scientifique, les implications du dépassement ou de l'imprécision, votre code aura des erreurs, tout comme Boeing l'a découvert, tout comme Pac-Man l'a découvert aussi. Et en fait, juste pour finir sur une note sombre, il s'avère qu'il y a un autre problème similaire à l'horizon déjà. Donc, à mon époque, tout le monde s'inquiétait beaucoup du problème Y2K, le problème de l'an 2000. Pourquoi ? Parce que pendant des décennies, lorsque les ordinateurs ont été inventés, la plupart des systèmes utilisaient seulement deux chiffres -- indépendamment des bits -- deux chiffres pour représenter les années. Pourquoi ? Les ordinateurs sont sortis il y a quelques décennies. Qui aurait pensé qu'un ordinateur fonctionnerait encore des décennies plus tard ? Il s'avère qu'ils le faisaient, surtout dans le gouvernement et les entreprises et autres. Mais si vous n'utilisez que deux chiffres pour représenter les années et que le millénaire arrive et que c'est 1999 sur le point de basculer, sur le point de basculer, que vient-il après 1999 ? Eh bien, si vous n'utilisez que deux chiffres, idéalement 2000. Mais si vous n'utilisez que deux chiffres, l'année 0 vient après l'année 1999. Et le monde entier, vraiment -- vous pouvez le vérifier aujourd'hui sur Wikipédia -- paniquait parce qu'il y avait tellement de vieux logiciels dans le monde qui auraient pu avoir cette erreur. Et qui sait ? Des avions tombant du ciel, des ordinateurs redémarrant, se bloquant. Personne ne savait vraiment parce que c'était une situation non gérée dans le code. Donc, heureusement, le monde s'est vraiment organisé. Le monde ne s'est pas terminé en l'an 2000. Et la plupart des systèmes ont été mis à jour à temps sans histoires d'horreur folles. Mais cela va se reproduire parce qu'il s'avère que dans quelques années, à ce stade, les ordinateurs utilisent depuis des années des entiers de 32 bits pour suivre le temps, dans le sens de l'heure de la journée. Et le point dans le temps qu'ils ont décidé il y a des années était, comme, hé tout le monde, suivons simplement le nombre de secondes écoulées depuis le 1er janvier 1970. Et nous pouvons calculer le temps relativement par la suite. C'est donc formidable. Cela nous donne des décennies. Mais 32 bits finissent par atteindre leur maximum à environ 4 milliards positifs, ou 2 milliards si vous voulez des nombres négatifs et positifs. Et il s'avère que, si vous comptez le nombre de secondes entre 1970 et le jour du 19 janvier 2038, le monde pourrait à nouveau se terminer car toutes ces horloges vont déborder. Et nous nous retrouverons à l'an 0 ou à un nombre négatif. Maintenant, quelle est la solution ? Je veux dire, mon Dieu, c'est exactement la même chose. Arrêtez d'utiliser si peu de bits. Utilisez plus de bits. Mais les bits et la mémoire et les ordinateurs étaient autrefois chers. De nos jours, le stockage est beaucoup plus disponible. Mais parmi les choses que nous discuterons alors, il y a la façon dont vous pouvez utiliser à la fois le matériel et le logiciel pour résoudre ce problème. Mais pour l'instant, peut-être définissez un rappel sur Google Agenda pour le 19 janvier 2038. Et nous espérons vous voir la semaine prochaine. [APPLAUDISSEMENTS] [MUSIQUE CLASSIQUE]