1 00:00:00,000 --> 00:00:02,500 [Powered by Google Translate] [Section 5 - Plus confortable] 2 00:00:02,500 --> 00:00:04,690 [Rob Bowden - Université de Harvard] 3 00:00:04,690 --> 00:00:07,250 [C'est CS50. - CS50.TV] 4 00:00:08,990 --> 00:00:14,250 >> Comme je l'ai dit dans mon e-mail, il ya beaucoup de choses que vous pouvez utiliser 5 00:00:14,250 --> 00:00:17,060 autre que l'appareil de réellement faire les séries de problèmes. 6 00:00:17,060 --> 00:00:19,910 Nous vous recommandons de le faire dans l'appareil juste parce que nous pouvons plus facilement vous aider 7 00:00:19,910 --> 00:00:22,070 et nous savons comment tout va fonctionner. 8 00:00:22,070 --> 00:00:26,950 Mais comme un exemple de situation où vous pouvez faire des choses si, par exemple, vous n'avez pas accès 9 00:00:26,950 --> 00:00:31,570 à un appareil ou si vous voulez travailler dans le sous-sol Science Center - 10 00:00:31,570 --> 00:00:33,090 ce qui fait qu'ils ont l'appareil trop - 11 00:00:33,090 --> 00:00:35,150 si vous voulez travailler n'importe où. 12 00:00:35,150 --> 00:00:42,370 Un exemple est que vous avez vu / entendu parler de SSH? 13 00:00:44,380 --> 00:00:47,780 SSH est fondamentalement juste comme se connecter à quelque chose. 14 00:00:47,780 --> 00:00:51,340 En fait, en ce moment je suis SSHed dans l'appareil. 15 00:00:51,340 --> 00:00:54,290 Je ne travaille jamais directement dans l'appareil. 16 00:00:55,930 --> 00:01:01,060 Voici l'appareil, et si vous regardez en bas ici, vous voyez cette adresse IP. 17 00:01:01,060 --> 00:01:03,650 Je ne travaille jamais dans l'appareil lui-même; 18 00:01:03,650 --> 00:01:08,840 J'ai toujours venir à une iTerm2 fenêtre / fenêtre de terminal. 19 00:01:08,840 --> 00:01:15,910 Vous pouvez SSH à cette adresse IP, ssh jharvard@192.168.129.128. 20 00:01:15,910 --> 00:01:20,390 Je me souviens que nombre très facilement parce que c'est un joli motif. 21 00:01:20,390 --> 00:01:24,920 Mais qui va me demander mon mot de passe, et maintenant je suis dans l'appareil. 22 00:01:24,920 --> 00:01:33,060 Fondamentalement, à ce stade, si vous avez ouvert un terminal intérieur de l'appareil lui-même, 23 00:01:33,060 --> 00:01:36,350 cette interface, mais vous devez l'utiliser, est exactement le même 24 00:01:36,350 --> 00:01:40,010 que l'interface que j'utilise ici, mais maintenant vous êtes SSHed. 25 00:01:42,240 --> 00:01:44,920 Vous n'avez pas besoin de SSH à l'appareil. 26 00:01:44,920 --> 00:01:52,360 Un exemple d'un autre endroit que vous pourriez SSH, c'est que je suis sûr que vous avez par défaut - 27 00:01:52,360 --> 00:01:55,020 Oh. Bigger. 28 00:01:55,020 --> 00:02:01,130 Chacun d'entre vous doit avoir de comptes SAF par défaut sur les serveurs du SAF. 29 00:02:01,130 --> 00:02:06,840 Pour moi, je le ferais SSH pour rbowden@nice.fas.harvard.edu. 30 00:02:06,840 --> 00:02:11,610 Il va vous demander que la première fois, et vous dites oui. 31 00:02:11,610 --> 00:02:15,840 Mon mot de passe est juste va être mon mot de passe SAF. 32 00:02:15,840 --> 00:02:22,650 Et maintenant, je suis SSHed les serveurs sympas, et je peux faire ce que je veux ici. 33 00:02:22,650 --> 00:02:28,560 Un grand nombre de classes que vous pourriez prendre, comme 124, vont avoir des choses à vous téléchargez ici 34 00:02:28,560 --> 00:02:30,950 à soumettre effectivement vos ensembles de problèmes. 35 00:02:30,950 --> 00:02:34,100 Mais dire que vous n'avez pas accès à votre appareil. 36 00:02:34,100 --> 00:02:37,910 Ensuite, vous pouvez faire des choses, comme sur ici il va dire: - 37 00:02:37,910 --> 00:02:42,160 C'est juste notre section de questions. 38 00:02:42,160 --> 00:02:45,070 Il vous sera demandé de le faire dans l'appareil. 39 00:02:45,070 --> 00:02:47,790 Au lieu de cela, je vais le faire sur le serveur. 40 00:02:47,790 --> 00:02:50,560 Je vais décompresser ce. 41 00:02:50,560 --> 00:02:55,670 Le problème va être que vous êtes habitué à utiliser quelque chose comme gedit 42 00:02:55,670 --> 00:02:58,160 ou autre à l'intérieur de l'appareil. 43 00:02:58,160 --> 00:03:01,830 Vous n'allez pas avoir ce sur le serveur SAF. 44 00:03:01,830 --> 00:03:04,110 Il est tout simplement va être cette interface textuelle. 45 00:03:04,110 --> 00:03:09,180 Ainsi, vous pouvez une ou l'autre, essayer d'apprendre un éditeur de texte qu'ils ont. 46 00:03:09,180 --> 00:03:12,130 Ils ont Nano. 47 00:03:12,130 --> 00:03:14,990 Nano est généralement assez facile à utiliser. 48 00:03:14,990 --> 00:03:19,470 Vous pouvez utiliser vos flèches et taper normalement. 49 00:03:19,470 --> 00:03:21,250 Donc, ce n'est pas difficile. 50 00:03:21,250 --> 00:03:24,720 Si vous voulez vraiment fantaisie, vous pouvez utiliser Emacs, 51 00:03:24,720 --> 00:03:29,850 que je n'aurais probablement pas ouvert parce que je ne sais même pas comment fermer Emacs. 52 00:03:29,850 --> 00:03:32,760 X Control, Contrôle C? Ouais. 53 00:03:32,760 --> 00:03:35,310 Ou vous pouvez utiliser Vim, qui est ce que j'utilise. 54 00:03:35,310 --> 00:03:37,800 Et si ce sont vos options. 55 00:03:37,800 --> 00:03:43,830 Si vous ne voulez pas le faire, vous le pouvez aussi, si vous regardez manual.cs50.net-- 56 00:03:43,830 --> 00:03:45,410 Oh. 57 00:03:45,410 --> 00:03:49,920 Sur un PC, vous pouvez utiliser SSH PuTTY, 58 00:03:49,920 --> 00:03:51,940 que vous allez avoir à télécharger séparément. 59 00:03:51,940 --> 00:03:55,460 Sur un Mac, vous pouvez tout simplement par l'utilisation du terminal par défaut ou vous pouvez télécharger iTerm2, 60 00:03:55,460 --> 00:03:58,490 qui est comme une belle Terminal fantaisie. 61 00:03:58,490 --> 00:04:03,780 Si vous allez à manual.cs50.net vous verrez un lien vers Notepad + +, 62 00:04:03,780 --> 00:04:07,120 qui est ce que vous pouvez utiliser sur un PC. 63 00:04:07,120 --> 00:04:13,340 Il vous permet de SFTP à partir de Notepad + +, qui est essentiellement SSH. 64 00:04:13,340 --> 00:04:17,750 Que cela vous permettra de faire est d'éditer vos fichiers en local, 65 00:04:17,750 --> 00:04:20,670 et puis quand vous voulez les sauver, il vous fera économiser de nice.fas, 66 00:04:20,670 --> 00:04:23,670 où vous pouvez ensuite les faire fonctionner. 67 00:04:23,670 --> 00:04:26,880 Et l'équivalent sur Mac va être TextWrangler. 68 00:04:26,880 --> 00:04:28,760 Donc, il vous permet de faire la même chose. 69 00:04:28,760 --> 00:04:32,800 Il vous permet d'éditer des fichiers en local et de les enregistrer sur nice.fas, 70 00:04:32,800 --> 00:04:35,730 où vous pouvez ensuite les faire fonctionner. 71 00:04:35,730 --> 00:04:40,400 Donc, si jamais vous êtes coincé sans un appareil, vous disposez des options 72 00:04:40,400 --> 00:04:44,230 à toujours faire vos ensembles de problèmes. 73 00:04:44,230 --> 00:04:48,250 Le seul problème va être que vous n'allez pas avoir la bibliothèque CS50 74 00:04:48,250 --> 00:04:51,580 parce nice.fas ne pas par défaut l'avoir. 75 00:04:51,580 --> 00:04:55,970 Vous pouvez soit télécharger la bibliothèque CS50 - 76 00:04:55,970 --> 00:04:58,470 Je ne pense pas que j'ai besoin en ce moment. 77 00:04:58,470 --> 00:05:03,270 Vous pouvez soit télécharger la bibliothèque CS50 et de le copier vers nice.fas, 78 00:05:03,270 --> 00:05:07,450 ou je pense qu'à ce stade, nous ne l'utilisons pas plus de toute façon. 79 00:05:07,450 --> 00:05:12,720 Ou si nous le faisons, vous pouvez pour le moment de le remplacer par 80 00:05:12,720 --> 00:05:18,480 les implémentations des fonctions de la bibliothèque CS50 toute façon. 81 00:05:18,480 --> 00:05:21,370 Donc, cela ne devrait pas être que beaucoup de restrictions. 82 00:05:21,370 --> 00:05:23,710 Et c'est tout. 83 00:05:26,460 --> 00:05:29,820 >> Je vais revenir à l'appareil maintenant, nous allons tout faire dans l'appareil. 84 00:05:29,820 --> 00:05:37,510 En regardant notre section de questions, au début, comme je l'ai dit dans mon email, 85 00:05:37,510 --> 00:05:43,620 nous devons parler de la courte que vous étiez censé regarder. 86 00:05:43,620 --> 00:05:51,980 Nous avons la Redirection & Tubes et ces trois questions. 87 00:05:51,980 --> 00:05:56,070 >> Pour ce courant ne fonctionne comme printf écrire par défaut? 88 00:05:56,070 --> 00:05:59,130 Alors flux. Qu'est-ce qu'un flux? 89 00:06:06,520 --> 00:06:15,100 Un flux est fondamentalement comme c'est juste une - 90 00:06:15,100 --> 00:06:21,450 Ce n'est même pas une source de 1 et de 0. 91 00:06:21,450 --> 00:06:24,920 Le flux c'est demander ici, c'est la sortie standard. 92 00:06:24,920 --> 00:06:27,250 Et de manière standard est un cours d'eau que lorsque vous écrivez à elle, 93 00:06:27,250 --> 00:06:30,940 il apparaît à l'écran. 94 00:06:30,940 --> 00:06:36,860 La sortie standard, par stream, et cela signifie que vous venez d'écrire 1 et de 0 à elle, 95 00:06:36,860 --> 00:06:40,220 et l'autre extrémité du lit sur tout type de ce flux. 96 00:06:40,220 --> 00:06:43,540 C'est juste une chaîne de 1 et de 0. 97 00:06:43,540 --> 00:06:45,570 Vous pouvez écrire dans les flux ou vous pouvez lire à partir de flux 98 00:06:45,570 --> 00:06:47,950 selon ce que le flux est en réalité. 99 00:06:47,950 --> 00:06:52,800 Les deux autres volets par défaut sont standard dans et erreur standard. 100 00:06:52,800 --> 00:06:57,540 Standard en est lorsque vous ne GetString, il vous attend pour des trucs d'entrée. 101 00:06:57,540 --> 00:07:01,570 Donc, il vous attend, il est effectivement en attente sur la norme en, 102 00:07:01,570 --> 00:07:04,880 ce qui est vraiment ce que vous obtenez lorsque vous tapez au clavier. 103 00:07:04,880 --> 00:07:07,530 Vous tapez dans pouces standard 104 00:07:07,530 --> 00:07:10,050 Erreur type est pratiquement équivalent à la sortie standard, 105 00:07:10,050 --> 00:07:13,280 mais il est spécialisé en ce que lorsque vous imprimez à l'erreur standard, 106 00:07:13,280 --> 00:07:16,770 vous êtes censé imprimer uniquement les messages d'erreur à ce 107 00:07:16,770 --> 00:07:20,200 afin que vous puissiez différencier les messages réguliers affichées à l'écran 108 00:07:20,200 --> 00:07:24,560 par rapport à des messages d'erreur suivant qu'ils allé à la sortie standard ou d'erreur standard. 109 00:07:24,560 --> 00:07:28,660 Trop de fichiers. 110 00:07:28,660 --> 00:07:32,440 La sortie standard, standard et l'erreur standard sont juste flux spéciaux, 111 00:07:32,440 --> 00:07:36,810 mais vraiment n'importe quel fichier, lorsque vous ouvrez un fichier, il devient un flux d'octets 112 00:07:36,810 --> 00:07:40,740 où vous pouvez juste lire à partir de ce flux. 113 00:07:40,740 --> 00:07:47,770 Vous, pour la plupart, peut il suffit de penser un fichier comme un flux d'octets. 114 00:07:47,770 --> 00:07:51,190 Donc, ce flux ne leur écrire par défaut? La sortie standard. 115 00:07:51,190 --> 00:07:56,980 >> Quelle est la différence entre> et >>? 116 00:07:58,140 --> 00:08:03,710 Quelqu'un at-il regarder la vidéo avant? D'accord. 117 00:08:03,710 --> 00:08:10,960 > Va être la façon dont vous rediriger vers des fichiers, 118 00:08:10,960 --> 00:08:15,240 et >> va également rediriger la sortie dans des fichiers, 119 00:08:15,240 --> 00:08:17,820 mais il est plutôt va ajouter dans le fichier. 120 00:08:17,820 --> 00:08:23,430 Par exemple, disons que j'ai la chance d'avoir dict ici, 121 00:08:23,430 --> 00:08:27,020 et la seule chose que l'intérieur du dict est chat, chat, chien, poisson, chien. 122 00:08:27,020 --> 00:08:31,530 Une commande que vous avez à la ligne de commande est le chat, 123 00:08:31,530 --> 00:08:34,539 qui va juste pour imprimer ce qu'il ya dans un fichier. 124 00:08:34,539 --> 00:08:40,679 Donc, quand je dis dict chat, il va imprimer chat, chat, chien, poisson, chien. C'est tout ce chat fait. 125 00:08:40,679 --> 00:08:46,280 Cela signifie qu'il imprimée sur la sortie standard chat, chat, chien, poisson, chien. 126 00:08:46,280 --> 00:08:53,240 Si je veux rediriger la place que pour un fichier, je peux utiliser> et le rediriger vers quel que soit le fichier est. 127 00:08:53,240 --> 00:08:56,460 Je vais appeler le fichier fichier. 128 00:08:56,460 --> 00:09:00,320 Alors maintenant, si I ls, je vois que j'ai un nouveau fichier appelé fichier. 129 00:09:00,320 --> 00:09:05,700 Et si je l'ouvre, il va avoir exactement ce chat mis à la ligne de commande. 130 00:09:05,700 --> 00:09:11,040 Alors maintenant, si je fais ça encore une fois, il va rediriger la sortie dans un fichier, 131 00:09:11,040 --> 00:09:13,930 et je vais avoir exactement la même chose. 132 00:09:13,930 --> 00:09:17,910 Donc, techniquement, il a complètement passé outre ce que nous avions. 133 00:09:17,910 --> 00:09:22,970 Et nous verrons si je change dict, j'ai sorti chien. 134 00:09:22,970 --> 00:09:29,980 Maintenant, si nous dict chat dans un fichier de plus, nous allons avoir la nouvelle version avec un chien enlevé. 135 00:09:29,980 --> 00:09:32,400 Donc, il remplace complètement. 136 00:09:32,400 --> 00:09:36,640 Au lieu de cela, si nous utilisons >>, il va ajouter le fichier. 137 00:09:36,640 --> 00:09:40,860 Maintenant, l'ouverture du fichier, nous voyons que nous avons exactement la même chose imprimée deux fois 138 00:09:40,860 --> 00:09:44,920 parce que c'était là une fois, nous annexés à l'original. 139 00:09:44,920 --> 00:09:48,130 C'est donc ce que> et >> faire. 140 00:09:48,130 --> 00:09:50,580 Est-ce que la prochaine demande - Il ne demande pas à ce sujet. 141 00:09:50,580 --> 00:09:59,050 >> L'autre est que nous avons <, qui, si> redirige la sortie standard, 142 00:09:59,050 --> 00:10:01,970 00:10:12,050 Voyons voir si nous avons un exemple. 144 00:10:14,750 --> 00:10:16,930 Je peux écrire un vrai rapide. 145 00:10:17,870 --> 00:10:25,700 Prenons n'importe quel fichier, hello.c. 146 00:10:56,060 --> 00:10:59,070 Fichier relativement simple. 147 00:10:59,070 --> 00:11:03,570 Je viens juste de une chaîne, puis imprimer "Bonjour" quelle que soit la chaîne que je viens d'entrer était. 148 00:11:03,570 --> 00:11:07,990 Donc, assurez-bonjour et puis. / Bonjour. 149 00:11:07,990 --> 00:11:10,720 Maintenant, il m'invite à entrer dans quelque chose, 150 00:11:10,720 --> 00:11:15,070 ce qui signifie qu'il est en attente sur les choses à être entré en pouces standard 151 00:11:15,070 --> 00:11:20,450 Donc, ce que je veux entrer en pouces standard Nous allons juste dire Bonjour, Rob! 152 00:11:20,450 --> 00:11:23,310 Ensuite, il a l'impression vers la sortie standard Bonjour, Rob! 153 00:11:23,310 --> 00:11:28,860 Si je fais. / Bonjour et puis rediriger, 154 00:11:30,740 --> 00:11:34,310 pour l'instant, vous ne pouvez rediriger dans un fichier. 155 00:11:34,310 --> 00:11:41,720 Donc, si je mets dans un fichier, txt, et j'ai mis Rob, 156 00:11:41,720 --> 00:11:52,300 si je n'ai bonjour et puis rediriger le fichier txt en. / bonjour, il va dire Bonjour, Rob! immédiatement. 157 00:11:52,300 --> 00:11:57,160 Quand il devient premier à GetString et qu'il est en attente sur le standard dans, 158 00:11:57,160 --> 00:12:01,730 standard n'est plus en attente sur le clavier pour que les données se saisies. 159 00:12:01,730 --> 00:12:05,980 Au lieu de cela, nous avons redirigé norme pour lire à partir du fichier txt. 160 00:12:05,980 --> 00:12:10,290 Et il en va de lire le fichier txt, qui est juste la ligne de Rob, 161 00:12:10,290 --> 00:12:13,380 et puis ça va imprimer Bonjour, Rob! 162 00:12:13,380 --> 00:12:18,180 Et si je voulais, je pourrais aussi le faire. / Bonjour 00:12:21,500 et ensuite le niveau que cette impression, qui est Bonjour, Rob!, 164 00:12:21,500 --> 00:12:24,700 Je ne peux rediriger que dans son propre fichier. 165 00:12:24,700 --> 00:12:29,790 Je vais appeler le fichier bonjour - non, je ne veux pas, parce que c'est l'exécutable - txt2. 166 00:12:29,790 --> 00:12:40,150 Maintenant, txt2 va avoir la sortie de. / Bonjour 00:12:43,520 >> Des questions? 168 00:12:45,900 --> 00:12:49,090 >> D'accord. Alors ici nous avons pipeline. 169 00:12:49,090 --> 00:12:53,510 Les tubes sont la dernière unité de redirection. 170 00:12:53,510 --> 00:12:58,750 >> Oh. Je suppose que d'une unité supplémentaire de redirection est si au lieu de> vous faites 2>, 171 00:12:58,750 --> 00:13:01,070 qui est rediriger l'erreur standard. 172 00:13:01,070 --> 00:13:06,280 Donc, si quelque chose se passait à l'erreur standard, il ne serait pas se mettre en txt2. 173 00:13:06,280 --> 00:13:12,480 Mais remarquez si je fais 2>, puis il est toujours l'impression Bonjour, Rob! à la ligne de commande 174 00:13:12,480 --> 00:13:18,600 parce que je ne fais que rediriger l'erreur-type, je ne suis pas rediriger la sortie standard. 175 00:13:18,600 --> 00:13:22,210 Erreur type et la sortie standard sont différentes. 176 00:13:24,210 --> 00:13:27,080 Si vous vouliez réellement écrire sur la sortie standard, 177 00:13:27,080 --> 00:13:35,080 alors je pourrais changer cela soit fprintf sur stderr. 178 00:13:35,080 --> 00:13:37,850 Donc, printf, par défaut, imprime sur la sortie standard. 179 00:13:37,850 --> 00:13:41,720 Si je veux imprimer sur la sortie standard manuellement, puis-je utiliser fprintf 180 00:13:41,720 --> 00:13:45,010 et de préciser ce que je veux imprimer. 181 00:13:45,010 --> 00:13:49,720 Si, au contraire je l'ai fait stdout fprintf, alors que c'est à peu près équivalent à printf. 182 00:13:49,720 --> 00:13:55,530 Mais fprintf d'erreur standard. 183 00:13:57,790 --> 00:14:03,650 Alors maintenant, si je rediriger ce dans txt2, Bonjour, Rob! est encore en train imprimée à la ligne de commande 184 00:14:03,650 --> 00:14:08,270 car il est imprimé à se faire d'erreur standard et je ne fais que rediriger la sortie standard. 185 00:14:08,270 --> 00:14:16,420 Si maintenant je rediriger l'erreur-type, maintenant cela n'a pas été imprimée, et txt2 va être Bonjour, Rob! 186 00:14:16,420 --> 00:14:21,910 Alors maintenant, vous pouvez imprimer vos erreurs réelles d'erreur standard 187 00:14:21,910 --> 00:14:24,720 et imprimer vos messages réguliers à la sortie standard. 188 00:14:24,720 --> 00:14:31,420 Et donc quand vous exécutez votre programme, vous pouvez l'exécuter en tant que. / Bonjour ce type avec le 2> 189 00:14:31,420 --> 00:14:33,800 de sorte que votre programme va fonctionner normalement, 190 00:14:33,800 --> 00:14:38,400 mais les messages d'erreur que vous pouvez vérifier que vous obtenez plus tard dans le journal des erreurs, 191 00:14:38,400 --> 00:14:44,500 tant d'erreurs, et ensuite chercher plus tard et que votre fichier aura des erreurs éventuelles erreurs qui se sont produites. 192 00:14:45,200 --> 00:14:47,540 >> Des questions? 193 00:14:47,540 --> 00:14:58,070 >> Le dernier est un tuyau, que vous pouvez considérer comme prenant la sortie standard d'une commande 194 00:14:58,070 --> 00:15:01,210 et ce qui en fait la norme de la prochaine commande. 195 00:15:01,210 --> 00:15:05,570 Un exemple est ici l'écho est une chose ligne de commande 196 00:15:05,570 --> 00:15:11,840 qui va tout simplement faire écho à ce que j'ai mis comme argument. Je ne vais pas mettre des guillemets. 197 00:15:11,840 --> 00:15:16,150 Echo blah, blah, blah va juste pour imprimer blah, blah, blah. 198 00:15:16,150 --> 00:15:20,600 Avant, quand j'ai dit que je devais mettre Rob dans un fichier txt 199 00:15:20,600 --> 00:15:28,830 car je ne peux rediriger les fichiers txt, au contraire, / si je fais écho à Rob 200 00:15:28,830 --> 00:15:35,520 puis redirigez vers. / bonjour, cela va aussi faire le même genre de chose. 201 00:15:35,520 --> 00:15:39,160 Cela prend la sortie de cette commande, Rob écho, 202 00:15:39,160 --> 00:15:43,610 et de l'utiliser comme entrée pour. / bonjour. 203 00:15:44,790 --> 00:15:49,560 Vous pouvez penser que c'est en tant que premier rediriger écho Rob dans un fichier 204 00:15:49,560 --> 00:15:54,160 et ensuite entrée dans. / bonjour ce fichier qui vient d'être émis. 205 00:15:54,160 --> 00:15:57,850 Mais il faut le fichier temporaire hors de l'image. 206 00:16:01,890 --> 00:16:04,460 >> Questions à ce sujet? 207 00:16:04,460 --> 00:16:07,150 >> La question suivante va impliquer ce sujet. 208 00:16:07,150 --> 00:16:15,310 Qu'est-ce pipeline pourrait que vous utilisez pour trouver le nombre de noms uniques dans un fichier appelé names.txt? 209 00:16:15,310 --> 00:16:24,160 Les commandes que nous allons avoir à utiliser ici sont uniques, uniq, puis wc. 210 00:16:24,160 --> 00:16:28,840 Vous pouvez le faire uniq homme fait regarder ce que fait, 211 00:16:28,840 --> 00:16:34,840 et il va tout simplement de filtrer les lignes adjacentes correspondant de l'entrée. 212 00:16:34,840 --> 00:16:40,690 Et l'homme wc va imprimer le saut de ligne, un mot, et le nombre d'octets pour chaque fichier. 213 00:16:40,690 --> 00:16:43,760 Et le dernier que nous allons avoir à utiliser est en quelque sorte, 214 00:16:43,760 --> 00:16:47,410 qui va simplement trier les lignes du fichier txt. 215 00:16:47,410 --> 00:16:58,080 Si je fais un fichier txt, names.txt, et c'est Rob, Tommy, Joseph, Tommy, Joseph, RJ, Rob, 216 00:16:58,080 --> 00:17:03,910 ce que je veux faire ici est de trouver le nombre de noms uniques dans ce fichier. 217 00:17:03,910 --> 00:17:08,750 Donc, quelle devrait être la réponse? >> [L'élève] 4. Ouais >>. 218 00:17:08,750 --> 00:17:13,780 Il doit être de 4 depuis Rob, Tommy, Joseph, RJ sont les seuls noms uniques dans ce fichier. 219 00:17:13,780 --> 00:17:20,180 La première étape, si je fais juste le nombre de mots sur names.txt, 220 00:17:20,180 --> 00:17:24,290 cela est fait de me dire tout. 221 00:17:24,290 --> 00:17:32,560 Il s'agit en fait d'impression - Voyons, l'homme wc - nouvelles lignes, de mots et de comptage d'octets. 222 00:17:32,560 --> 00:17:38,270 Si je ne se soucient que des lignes, alors je peux juste faire wc-l names.txt. 223 00:17:41,730 --> 00:17:44,300 Donc, c'est l'étape 1. 224 00:17:44,300 --> 00:17:50,510 Mais je ne veux pas wc-l names.txt parce names.txt ne contient que tous les noms, 225 00:17:50,510 --> 00:17:54,170 et je tiens à les filtrer tous les non-uniques. 226 00:17:54,170 --> 00:18:01,200 Donc, si je fais names.txt uniq, qui n'est pas tout à me donner ce que je veux 227 00:18:01,200 --> 00:18:03,760 parce que les noms dupliqués sont toujours là. 228 00:18:03,760 --> 00:18:07,690 Pourquoi est-ce? Pourquoi ne pas faire uniq ce que je veux? 229 00:18:07,690 --> 00:18:10,500 [L'élève] Les doublons ne sont pas [inaudible] >> Oui. 230 00:18:10,500 --> 00:18:16,370 Rappelez-vous la page de manuel pour uniq dit filtre lignes sans concordances adjacentes. 231 00:18:16,370 --> 00:18:19,680 Ils ne sont pas adjacents, afin de ne pas les filtrer. 232 00:18:19,680 --> 00:18:31,100 Si je les trier d'abord, names.txt genre va mettre toutes les lignes en double ensemble. 233 00:18:31,100 --> 00:18:34,450 Alors maintenant, names.txt sorte que. 234 00:18:34,450 --> 00:18:40,550 Je vais vouloir l'utiliser comme entrée uniq, qui est | uniq. 235 00:18:40,550 --> 00:18:43,390 Cela me donne Joseph, RJ, Rob, Tommy, 236 00:18:43,390 --> 00:18:49,260 et je veux l'utiliser comme entrée pour wc-l, 237 00:18:49,260 --> 00:18:52,740 qui va me donner 4. 238 00:18:52,740 --> 00:18:56,930 Comme il est dit ici, ce pipeline pourriez-vous utiliser? 239 00:18:56,930 --> 00:19:01,390 Vous pouvez faire beaucoup de choses comme l'utilisation d'une série de commandes 240 00:19:01,390 --> 00:19:05,130 où vous utilisez la sortie d'une commande comme entrée de la commande suivante. 241 00:19:05,130 --> 00:19:08,780 Vous pouvez faire beaucoup de choses, beaucoup de choses intelligentes. 242 00:19:08,780 --> 00:19:11,440 >> Des questions? 243 00:19:12,910 --> 00:19:14,600 D'accord. 244 00:19:14,600 --> 00:19:17,880 C'est tout pour les tubes et redirection. 245 00:19:18,370 --> 00:19:24,090 >> Maintenant, nous passons à la matière même, les trucs de codage. 246 00:19:24,090 --> 00:19:29,100 A l'intérieur de ce fichier PDF, vous verrez cette commande, 247 00:19:29,100 --> 00:19:32,950 et vous voulez exécuter cette commande dans votre appareil. 248 00:19:36,240 --> 00:19:42,250 wget est la commande pour simplement obtenir quelque chose de l'Internet, essentiellement, 249 00:19:42,250 --> 00:19:45,180 si wget et cette URL. 250 00:19:45,180 --> 00:19:49,110 Si vous êtes allé à cette URL dans votre navigateur, il serait de télécharger ce fichier. 251 00:19:49,110 --> 00:19:52,510 J'ai simplement cliqué sur elle, alors qu'elle le fichier téléchargé pour moi. 252 00:19:52,510 --> 00:19:55,650 Mais écrire wget de cette chose à l'intérieur de la borne 253 00:19:55,650 --> 00:19:58,620 va tout simplement de le télécharger sur votre terminal. 254 00:19:58,620 --> 00:20:02,750 J'ai section5.zip, et vous aurez envie de décompresser section5.zip, 255 00:20:02,750 --> 00:20:06,520 qui va vous donner un dossier appelé section5, 256 00:20:06,520 --> 00:20:11,550 qui va avoir tous les fichiers que nous allons utiliser aujourd'hui à l'intérieur de celui-ci. 257 00:20:33,380 --> 00:20:37,710 Comme les noms de fichiers de ces programmes suggèrent, ils sont un peu buggé, 258 00:20:37,710 --> 00:20:40,990 de sorte que votre mission est de comprendre pourquoi l'utilisation de gdb. 259 00:20:40,990 --> 00:20:44,560 Est-ce que tout le monde les ont téléchargés et / ou savoir comment obtenir les télécharger 260 00:20:44,560 --> 00:20:47,480 dans leur appareil? D'accord. 261 00:20:47,480 --> 00:20:56,400 >> Exécution ./buggy1, il va dire: Segmentation fault (core dumped), 262 00:20:56,400 --> 00:21:00,500 qui chaque fois que vous obtenez une erreur de segmentation, c'est une mauvaise chose. 263 00:21:00,500 --> 00:21:03,810 Dans quelles circonstances avez-vous obtenir une erreur de segmentation? 264 00:21:03,810 --> 00:21:08,210 [L'élève] déréférencement d'un pointeur nul. Ouais >>. Voilà donc un exemple. 265 00:21:08,210 --> 00:21:11,580 Déréférencer un pointeur NULL, vous allez obtenir une erreur de segmentation. 266 00:21:11,580 --> 00:21:16,720 Qu'est-ce une erreur de segmentation signifie que vous touchez mémoire que vous ne doit pas toucher. 267 00:21:16,720 --> 00:21:21,350 Donc déréférencement d'un pointeur null est en contact avec l'adresse 0, 268 00:21:21,350 --> 00:21:28,060 et, fondamentalement, tous les ordinateurs de nos jours dire que l'adresse 0 est la mémoire vous ne devriez pas être en contact. 269 00:21:28,060 --> 00:21:31,920 C'est pour cela que le déréférencement d'un pointeur NULL dans les résultats une erreur de segmentation. 270 00:21:31,920 --> 00:21:37,210 S'il vous arrive de ne pas initialiser un pointeur, alors qu'elle a une valeur ordures, 271 00:21:37,210 --> 00:21:41,520 et donc quand vous essayez de déréférencer, selon toute vraisemblance, vous touchez la mémoire 272 00:21:41,520 --> 00:21:43,540 c'est au milieu de nulle part. 273 00:21:43,540 --> 00:21:45,650 S'il vous arrive d'avoir de la chance et de la valeur des ordures 274 00:21:45,650 --> 00:21:48,440 qui est arrivé à pointer vers quelque part sur la pile ou quelque chose, 275 00:21:48,440 --> 00:21:50,820 puis quand vous déréférencer ce pointeur que vous n'avez pas initialisé, 276 00:21:50,820 --> 00:21:52,730 rien ne va mal tourner. 277 00:21:52,730 --> 00:21:55,480 Mais si elle pointe vers, disons, quelque part entre la pile et le tas, 278 00:21:55,480 --> 00:21:59,850 ou il est juste de pointer quelque part qui n'a pas été utilisée par votre programme encore, 279 00:21:59,850 --> 00:22:02,240 alors que vous touchez la mémoire vous ne devriez pas être en contact avec vous et erreur de segmentation. 280 00:22:02,240 --> 00:22:06,370 Lorsque vous écrivez une fonction récursive et récursivement trop de fois 281 00:22:06,370 --> 00:22:08,720 et votre pile devient trop importante et la collision de pile dans les choses 282 00:22:08,720 --> 00:22:12,270 qu'il ne devrait pas être entré en collision avec, vous touchez la mémoire vous ne devriez pas être en contact, 283 00:22:12,270 --> 00:22:14,810 de sorte que vous segfault. 284 00:22:14,810 --> 00:22:17,010 C'est ce qui est une erreur de segmentation. 285 00:22:17,010 --> 00:22:21,810 >> C'est aussi la même raison que si vous avez une chaîne comme - 286 00:22:21,810 --> 00:22:23,930 Revenons au programme précédent. 287 00:22:23,930 --> 00:22:28,530 En hello.c--Je suis juste faire quelque chose d'autre. 288 00:22:28,530 --> 00:22:33,770 char * s = "Bonjour tout le monde!"; 289 00:22:33,770 --> 00:22:42,310 Si j'utilise * s = quelque chose ou s [0] = 'X'; 290 00:22:42,310 --> 00:22:47,290 alors assurez-bonjour,. / bonjour, pourquoi est-ce une erreur de segmentation? 291 00:22:48,410 --> 00:22:51,250 Pourquoi est-ce une erreur de segmentation? 292 00:22:55,660 --> 00:22:57,890 Que feriez-vous m'attendre? 293 00:22:57,890 --> 00:23:06,640 Si je le faisais printf ("% s \ n", s); que voulez-vous faire imprimer? 294 00:23:06,640 --> 00:23:09,930 [L'élève] X bonjour. Ouais >>. 295 00:23:09,930 --> 00:23:15,140 Le problème est que lorsque vous déclarez une chaîne comme ceci, 296 00:23:15,140 --> 00:23:18,190 s est un pointeur qui va aller sur la pile, 297 00:23:18,190 --> 00:23:25,880 et ce que s est orientée vers cette chaîne est contenu dans la mémoire morte. 298 00:23:25,880 --> 00:23:30,560 Il suffit donc de par le nom, la mémoire morte, vous devriez avoir l'idée 299 00:23:30,560 --> 00:23:33,010 que si vous essayez de changer ce qu'il ya dans la mémoire morte, 300 00:23:33,010 --> 00:23:36,670 vous faites quelque chose que vous ne devriez pas faire avec de la mémoire et vous segfault. 301 00:23:36,670 --> 00:23:45,360 C'est en fait une grande différence entre char * s et char s []. 302 00:23:45,360 --> 00:23:48,790 Donc char s [], maintenant cette chaîne va être mis sur la pile, 303 00:23:48,790 --> 00:23:53,960 et la pile n'est pas en lecture seule, ce qui signifie que cela devrait fonctionner parfaitement bien. 304 00:23:55,500 --> 00:23:57,370 Et il le fait. 305 00:23:57,370 --> 00:24:06,250 Rappelez-vous que quand je fais char * s = "Bonjour tout le monde!", S elle-même est sur la pile 306 00:24:06,250 --> 00:24:10,390 mais s pointe vers un autre endroit, et que quelque part se trouve être en lecture seule. 307 00:24:10,390 --> 00:24:15,640 Mais char s [] est juste quelque chose sur la pile. 308 00:24:17,560 --> 00:24:21,760 C'est donc un autre exemple d'une erreur de segmentation se produit. 309 00:24:21,760 --> 00:24:27,820 >> Nous avons vu que ./buggy1 donné lieu à une erreur de segmentation. 310 00:24:27,820 --> 00:24:31,810 En théorie, vous ne devriez pas regarder buggy1.c immédiatement. 311 00:24:31,810 --> 00:24:35,170 Au lieu de cela, nous allons regarder à travers gdb. 312 00:24:35,170 --> 00:24:37,750 Notez que lorsque vous obtenez Segmentation fault (core dumped), 313 00:24:37,750 --> 00:24:40,850 vous obtenez ce dossier au cours de base appelé ici. 314 00:24:40,850 --> 00:24:45,200 Si nous ls-l, nous allons voir que le noyau est généralement un fichier assez gros. 315 00:24:45,200 --> 00:24:51,580 C'est le nombre d'octets du fichier, donc il semble que c'est quelque chose de 250 kilo-octets. 316 00:24:51,580 --> 00:24:56,120 La raison en est que ce que le core dump est en fait 317 00:24:56,120 --> 00:25:01,410 c'est quand votre programme plante, l'état de la mémoire de votre programme 318 00:25:01,410 --> 00:25:05,230 obtient juste copié et collé dans ce fichier. 319 00:25:05,230 --> 00:25:07,270 Il est rejeté dans ce fichier. 320 00:25:07,270 --> 00:25:13,060 Ce programme, alors qu'il était en cours d'exécution, qui est arrivé à une utilisation de la mémoire d'environ 250 kilo-octets, 321 00:25:13,060 --> 00:25:17,040 et c'est ce que me suis jeté dans ce fichier. 322 00:25:17,040 --> 00:25:23,630 Maintenant vous pouvez regarder ce fichier si nous faisons gdb buggy1 de base. 323 00:25:23,630 --> 00:25:30,130 Nous pouvons juste faire gdb buggy1, et ce sera tout simplement de démarrer gdb régulièrement, 324 00:25:30,130 --> 00:25:33,800 en utilisant buggy1 que le fichier d'entrée. 325 00:25:33,800 --> 00:25:38,260 Mais si vous faites gdb buggy1 de base, il est spécifiquement va démarrer gdb 326 00:25:38,260 --> 00:25:40,330 en consultant à ce fichier core. 327 00:25:40,330 --> 00:25:45,560 Et dites-vous buggy1 gdb moyen sait que le fichier core provient du programme buggy1. 328 00:25:45,560 --> 00:25:49,580 Donc gdb buggy1 coeur va nous apporter immédiatement 329 00:25:49,580 --> 00:25:52,060 à l'endroit où le programme est arrivé à terminer. 330 00:25:57,720 --> 00:26:02,340 Nous voyons ici Programme terminé avec le signal 11, Segmentation fault. 331 00:26:02,340 --> 00:26:10,110 Il nous arrive de voir une ligne d'assemblage, ce qui n'est probablement pas très utile. 332 00:26:10,110 --> 00:26:15,360 Mais si vous tapez bt ou trace, ça va être la fonction 333 00:26:15,360 --> 00:26:19,430 qui nous donne la liste de nos cadres de pile en cours. 334 00:26:19,430 --> 00:26:23,150 Donc trace. On dirait que nous n'avons que deux cadres de pile. 335 00:26:23,150 --> 00:26:26,310 Le premier est notre cadre de pile principale, 336 00:26:26,310 --> 00:26:29,810 et le second est le cadre de pile pour cette fonction que nous arrive d'être dans, 337 00:26:29,810 --> 00:26:34,440 qui ressemble nous n'avons que le code assembleur pour. 338 00:26:34,440 --> 00:26:38,050 Donc, revenons à notre fonction principale, 339 00:26:38,050 --> 00:26:42,300 et pour ce faire nous pouvons faire l'image 1, et je pense que nous pouvons aussi le faire vers le bas, 340 00:26:42,300 --> 00:26:45,160 mais je n'ai presque jamais le faire vers le bas - ou le haut. Ouais. 341 00:26:45,160 --> 00:26:50,710 De haut en bas. Vous amène jusqu'à une trame de pile, vers le bas vous ramène un cadre de pile. 342 00:26:50,710 --> 00:26:53,240 J'ai tendance à ne jamais l'utiliser. 343 00:26:53,240 --> 00:26:59,120 Je viens de dire précisément cadre 1, qui est d'aller vers l'image 1. 344 00:26:59,120 --> 00:27:01,750 Image 1 va nous mettre en stack frame principale, 345 00:27:01,750 --> 00:27:05,570 et il est dit ici de la ligne de code que nous arrive d'être à. 346 00:27:05,570 --> 00:27:07,950 Si nous voulions quelques lignes de plus de code, on peut dire la liste, 347 00:27:07,950 --> 00:27:11,280 et qui va nous donner toutes les lignes de code qui l'entourent. 348 00:27:11,280 --> 00:27:13,360 La ligne que nous crashait à été de 6: 349 00:27:13,360 --> 00:27:17,360 if (strcmp ("CS50 pierre", argv [1]) == 0). 350 00:27:17,360 --> 00:27:24,130 Si ce n'est pas évident, mais, vous pouvez l'obtenir directement d'ici simplement en pensant pourquoi il crashait. 351 00:27:24,130 --> 00:27:28,800 Mais nous pouvons aller encore plus loin et dire: «Pourquoi argv [1] erreur de segmentation?" 352 00:27:28,800 --> 00:27:38,830 Impression Faisons argv [1], et on dirait qu'il a 0x0, qui est le pointeur NULL. 353 00:27:38,830 --> 00:27:44,750 Nous strcmping CS50 roches et nulles, et donc ce qui se passe une erreur de segmentation. 354 00:27:44,750 --> 00:27:48,280 Et pourquoi est-argv [1] null? 355 00:27:48,640 --> 00:27:51,280 [L'élève] Parce que nous ne lui donne pas tous les arguments de ligne de commande. 356 00:27:51,280 --> 00:27:53,390 Ouais. Nous ne lui donne pas tous les arguments de ligne de commande. 357 00:27:53,390 --> 00:27:58,460 Donc ./buggy1 va seulement avoir argv [0] est ./buggy1. 358 00:27:58,460 --> 00:28:02,100 Il ne va pas avoir un argv [1], de sorte que se passe une erreur de segmentation. 359 00:28:02,100 --> 00:28:07,450 Mais si, au contraire, je fais juste CS50, il va dire Vous obtenez un D 360 00:28:07,450 --> 00:28:09,950 parce que c'est ce qu'il est censé faire. 361 00:28:09,950 --> 00:28:15,240 En regardant buggy1.c, il est censé print "Vous obtenez un D» - 362 00:28:15,240 --> 00:28:20,820 Si argv [1] n'est pas "CS50 rochers", "Vous obtenez un D", sinon "Vous obtenez un A!" 363 00:28:20,820 --> 00:28:25,660 Donc, si nous voulons un A, nous avons besoin de comparer ce aussi vrai, 364 00:28:25,660 --> 00:28:28,710 ce qui signifie que le compare à 0. 365 00:28:28,710 --> 00:28:31,100 Donc, argv [1] doit être "CS50" rochers. 366 00:28:31,100 --> 00:28:35,660 Si vous voulez faire cela en ligne de commande, vous devez utiliser \ pour échapper à l'espace. 367 00:28:35,660 --> 00:28:41,690 Donc CS50 \ roches et vous obtenez un A! 368 00:28:41,690 --> 00:28:44,060 Si vous ne faites pas la barre oblique inverse, pourquoi ça ne marche pas? 369 00:28:44,060 --> 00:28:47,190 [L'élève] Il s'agit de deux arguments différents. Ouais >>. 370 00:28:47,190 --> 00:28:52,540 Argv [1] va être CS50, et argv [2] va être rochers. D'accord. 371 00:28:52,540 --> 00:28:56,470 >> Maintenant ./buggy2 va segfault nouveau. 372 00:28:56,470 --> 00:29:01,880 Au lieu de l'ouvrir avec le fichier de base, nous allons simplement ouvrir buggy2 directement, 373 00:29:01,880 --> 00:29:05,000 si gdb buggy2. 374 00:29:05,000 --> 00:29:09,590 Maintenant, si nous venons de lancer notre programme, alors il va dire Program received signal SIGSEGV, 375 00:29:09,590 --> 00:29:15,530 qui est l'erreur de segmentation du signal, et c'est là que c'est arrivé à arriver. 376 00:29:15,530 --> 00:29:21,250 En regardant notre trace, nous voyons que nous étions dans la oh_no fonction, 377 00:29:21,250 --> 00:29:23,900 qui a été appelé par le dinky fonction, ce qui a été appelé par la fonction binky, 378 00:29:23,900 --> 00:29:26,460 qui a été appelé par le principal. 379 00:29:26,460 --> 00:29:31,680 Nous pouvons aussi voir les arguments de ces fonctions. 380 00:29:31,680 --> 00:29:34,680 L'argument de dinky et binky était de 1. 381 00:29:34,680 --> 00:29:44,390 Si nous listons les oh_no fonction, nous voyons que oh_no fait juste char ** s = NULL; 382 00:29:44,390 --> 00:29:47,410 * S = "BOOM"; 383 00:29:47,410 --> 00:29:50,330 Pourquoi en serait-il échoué? 384 00:29:54,330 --> 00:29:58,380 [L'élève] Vous ne pouvez pas déréférencer le pointeur NULL? Ouais >>. 385 00:29:58,380 --> 00:30:06,090 Ceci est juste que s est NULL, peu importe si ce qui arrive à être de type char **, 386 00:30:06,090 --> 00:30:12,070 qui, selon la façon dont vous l'interprétez, il pourrait être un pointeur vers un pointeur vers une chaîne 387 00:30:12,070 --> 00:30:15,550 ou un tableau de chaînes. 388 00:30:15,550 --> 00:30:21,430 C'est s est NULL, alors s * est déréférencer un pointeur NULL, 389 00:30:21,430 --> 00:30:24,800 et si cela va s'écraser. 390 00:30:24,800 --> 00:30:27,540 C'est l'une des façons les plus rapides, vous pouvez peut-être une erreur de segmentation. 391 00:30:27,540 --> 00:30:31,300 Il est juste de déclarer un pointeur nul et immédiatement des erreurs de segmentation. 392 00:30:31,300 --> 00:30:34,570 C'est ce que oh_no fait. 393 00:30:34,570 --> 00:30:43,400 Si nous remontons un cadre, puis nous allons entrer dans la fonction qui a appelé oh_no. 394 00:30:43,400 --> 00:30:44,830 J'ai besoin de le faire vers le bas. 395 00:30:44,830 --> 00:30:48,610 Si vous n'entrez pas de commande et que vous appuyez simplement de nouveau sur Entrée, 396 00:30:48,610 --> 00:30:52,350 il suffit de répéter la commande précédente que vous avez exécuté. 397 00:30:52,350 --> 00:30:56,610 Nous sommes dans le cadre 1. 398 00:30:56,610 --> 00:31:04,650 Énumérant ce cadre, nous voyons ici, c'est notre fonction. 399 00:31:04,650 --> 00:31:08,520 Vous pouvez frapper à nouveau la liste, ou vous pouvez faire la liste 20 et il donnera la liste plus. 400 00:31:08,520 --> 00:31:13,640 La fonction dinky dit que si i est 1, puis passez à la fonction oh_no, 401 00:31:13,640 --> 00:31:15,960 sinon, passez à la fonction slinky. 402 00:31:15,960 --> 00:31:18,700 Et nous savons que i est 1 car il nous arrive de voir ici 403 00:31:18,700 --> 00:31:22,560 que dinky a été appelé avec l'argument 1. 404 00:31:22,560 --> 00:31:27,560 Ou vous pouvez simplement imprimer puis-je et il va dire i est 1. 405 00:31:27,560 --> 00:31:33,770 Nous sommes actuellement en dinky, et si nous montons un autre cadre, nous savons que nous allons retrouver dans binky. 406 00:31:33,770 --> 00:31:36,600 Vers le haut. Maintenant, nous sommes dans binky. 407 00:31:36,600 --> 00:31:41,340 Inscription de cette fonction - la liste des avant la mi me couper - 408 00:31:41,340 --> 00:31:52,670 il a commencé comme si i vaut 0, alors nous allons l'appeler oh_no, sinon appelez dinky. 409 00:31:52,670 --> 00:31:57,000 Nous savons que i était de 1, donc il a appelé dinky. 410 00:31:57,000 --> 00:32:05,030 Et maintenant nous sommes de retour en principal et principal va juste être int i = rand ()% 3; 411 00:32:05,030 --> 00:32:08,790 Cela va juste pour vous donner un nombre aléatoire qui est soit 0, 1, ou 2. 412 00:32:08,790 --> 00:32:12,780 Il va appeler binky avec ce numéro, et il retournera 0. 413 00:32:12,780 --> 00:32:16,700 En regardant cela, 414 00:32:16,700 --> 00:32:19,880 tout marche à travers le programme manuellement sans l'exécuter immédiatement, 415 00:32:19,880 --> 00:32:25,400 vous devez définir un point d'arrêt au principal, ce qui signifie que lorsque nous lançons le programme 416 00:32:25,400 --> 00:32:31,020 votre programme s'exécute jusqu'à ce qu'il frappe une balle de break. 417 00:32:31,020 --> 00:32:35,450 Il faut donc lancer le programme, elle se déroulera, puis il va frapper la fonction principale et arrêter de courir. 418 00:32:35,450 --> 00:32:44,700 Maintenant, nous sommes à l'intérieur de la principale, et l'étape suivante ou va nous amener à la ligne de code suivante. 419 00:32:44,700 --> 00:32:47,050 Vous pouvez faire étape ou suivante. 420 00:32:47,050 --> 00:32:51,800 Frapper prochaine, maintenant je a été mis au rand ()% 3, afin que nous puissions afficher la valeur de i, 421 00:32:51,800 --> 00:32:55,280 et il va dire i est 1. 422 00:32:55,280 --> 00:32:58,110 Maintenant, c'est important que nous utilisions suivant ou pas. 423 00:32:58,110 --> 00:33:01,000 Je suppose que c'était important dans le précédent, mais nous voulons utiliser ensuite. 424 00:33:01,000 --> 00:33:06,000 Si nous utilisons étape, nous entrons dans la fonction, ce qui signifie oeil à la chose réelle 425 00:33:06,000 --> 00:33:07,940 ce qui se passe à l'intérieur de binky. 426 00:33:07,940 --> 00:33:10,510 Si nous utilisons prochaine, alors cela signifie aller sur la fonction 427 00:33:10,510 --> 00:33:14,070 et passez à la ligne suivante de code dans notre fonction principale. 428 00:33:14,070 --> 00:33:17,900 Ici, sur cette ligne, j'étais à où il est dit rand ()% 3; 429 00:33:17,900 --> 00:33:21,320 si je le faisais pas, il irait dans l'implémentation de rand 430 00:33:21,320 --> 00:33:25,110 et regardez ce qui se passe là-bas, et je ne pouvais parcourir la fonction rand. 431 00:33:25,110 --> 00:33:26,920 Mais je ne se soucient pas de la fonction rand. 432 00:33:26,920 --> 00:33:30,190 Je veux juste aller à la ligne suivante de code dans main, donc j'utilise prochaine. 433 00:33:30,190 --> 00:33:35,800 Mais maintenant, je me préoccupe de la fonction binky, donc je veux faire un pas dans cela. 434 00:33:35,800 --> 00:33:37,730 Maintenant, je suis dans binky. 435 00:33:37,730 --> 00:33:42,040 La première ligne de code va dire if (i == 0), je fais un pas, 436 00:33:42,040 --> 00:33:44,930 nous voyons nous nous retrouvons à dinky. 437 00:33:44,930 --> 00:33:51,620 Si nous listons les choses, nous voyons qu'il est vérifié i = 0. 438 00:33:51,620 --> 00:33:55,470 i n'est pas égal à 0, donc il est allé à la condition else, 439 00:33:55,470 --> 00:33:59,540 qui va appeler dinky (i). 440 00:33:59,540 --> 00:34:04,030 Vous pourriez devenir confus. 441 00:34:04,030 --> 00:34:07,380 Si vous regardez ces lignes directement, vous pourriez penser if (i == 0), 442 00:34:07,380 --> 00:34:10,800 OK, alors j'ai fait un pas et maintenant je suis à dinky (i), 443 00:34:10,800 --> 00:34:14,120 vous pourriez penser que cela doit vouloir dire i = 0 ou quelque chose. 444 00:34:14,120 --> 00:34:18,980 Non, cela signifie juste qu'il sait qu'il peut coller directement sur la ligne de dinky (i). 445 00:34:18,980 --> 00:34:23,300 Parce que je n'est pas 0, l'étape suivante ne va pas mettre fin à l'autre. 446 00:34:23,300 --> 00:34:26,239 Le reste est pas une ligne que ça va s'arrêter. 447 00:34:26,239 --> 00:34:31,570 Il va juste pour aller à la ligne suivante il peut effectivement exécuter, ce qui est très bien entretenue (i). 448 00:34:31,570 --> 00:34:36,090 En entrant dans dinky (i), nous voyons if (i == 1). 449 00:34:36,090 --> 00:34:42,670 Nous savons i = 1, alors quand nous entrons, nous savons que nous allons retrouver dans oh_no 450 00:34:42,670 --> 00:34:46,489 parce que i = 1 appelle la fonction oh_no, que vous pouvez entrer dans, 451 00:34:46,489 --> 00:34:52,969 qui va mettre en char ** s = NULL et immédiatement "BOOM". 452 00:34:54,270 --> 00:34:59,690 Et puis en fait en regardant la mise en œuvre de buggy2, 453 00:34:59,690 --> 00:35:04,590 cela, je ne fait que commencer un nombre aléatoire - 0, 1, ou 2 - appel binky, 454 00:35:04,590 --> 00:35:10,610 qui, si i est 0, il appelle oh_no, sinon il appelle dinky, qui vient ici. 455 00:35:10,610 --> 00:35:18,100 Si i est 1, oh_no appel, sinon appelez slinky, qui viennent ici, 456 00:35:18,100 --> 00:35:20,460 si i est 2, contactez oh_no. 457 00:35:20,460 --> 00:35:24,720 Je ne pense même pas il ya un moyen - 458 00:35:24,720 --> 00:35:30,030 Quelqu'un voit-il un moyen de rendre ce un programme qui ne sera pas une erreur de segmentation? 459 00:35:30,030 --> 00:35:37,530 Parce que si je ne me manque quelque chose, si i est 0, vous obtiendrez immédiatement une erreur de segmentation, 460 00:35:37,530 --> 00:35:41,250 sinon vous allez à une fonction qui, si i est 1, vous segfault, 461 00:35:41,250 --> 00:35:44,540 sinon vous allez à une fonction où si i est 2, vous segfault. 462 00:35:44,540 --> 00:35:46,810 Donc, peu importe ce que vous faites, vous segfault. 463 00:35:46,810 --> 00:35:52,380 >> Je suppose qu'une façon de fixer ce serait au lieu de faire char ** s = NULL, 464 00:35:52,380 --> 00:35:55,610 vous pourriez malloc espace pour cette chaîne. 465 00:35:55,610 --> 00:36:04,230 Nous pourrions faire malloc (sizeof) - sizeof quoi? 466 00:36:09,910 --> 00:36:15,190 [L'élève] (char) * 5? >> Cela vous semble juste? 467 00:36:15,190 --> 00:36:21,060 Je suppose que cela va fonctionner si j'ai effectivement couru, mais ce n'est pas ce que je recherche. 468 00:36:24,400 --> 00:36:32,940 Regardez le type de l'art. Ajoutons int *, int * x sorte. 469 00:36:32,940 --> 00:36:35,600 Je ferais malloc (sizeof (int)). 470 00:36:35,600 --> 00:36:40,490 Ou si je voulais un rayon de 5, je ferais (sizeof (int) * 5); 471 00:36:40,490 --> 00:36:44,210 Que faire si j'ai un int **? 472 00:36:46,260 --> 00:36:49,140 Que ferais-je malloc? 473 00:36:49,140 --> 00:36:53,510 [L'élève] Taille de l'aiguille. Ouais >>. (Sizeof (int *)); 474 00:36:53,510 --> 00:36:56,960 C'est la même chose ici-bas. 475 00:36:56,960 --> 00:37:01,280 Je veux (sizeof (char *)); 476 00:37:06,170 --> 00:37:12,840 Cela va allouer de l'espace pour le pointeur qui pointe vers "BOOM". 477 00:37:12,840 --> 00:37:15,330 Je n'ai pas besoin d'allouer de l'espace pour "BOOM" lui-même 478 00:37:15,330 --> 00:37:17,210 parce que c'est à peu près équivalent à ce que j'ai dit avant 479 00:37:17,210 --> 00:37:20,870 de char * x = "BOOM". 480 00:37:20,870 --> 00:37:27,950 "BOOM" existe déjà. Il arrive à exister dans la région en lecture seule de la mémoire. 481 00:37:27,950 --> 00:37:35,200 Mais il existe déjà, ce qui signifie que cette ligne de code, si s est de type char **, 482 00:37:35,200 --> 00:37:43,900 alors s * est un char * et vous l'avez installé char * pour pointer vers "BOOM". 483 00:37:43,900 --> 00:37:50,040 Si je voulais copier "BOOM" dans s, alors j'aurais besoin d'allouer de l'espace pour l'art. 484 00:37:55,170 --> 00:38:03,900 Je ferai * s = malloc (sizeof (char) * 5); 485 00:38:03,900 --> 00:38:06,210 Pourquoi 5? 486 00:38:06,210 --> 00:38:10,860 Pourquoi pas 4? Il ressemble à «BOOM» est de 4 caractères. >> [L'élève] Le caractère nul. 487 00:38:10,860 --> 00:38:14,580 Ouais. Toutes vos chaînes vont avoir besoin le caractère nul. 488 00:38:14,580 --> 00:38:23,590 Maintenant, je peux faire quelque chose comme strcat - Quelle est la fonction pour copier une chaîne de caractères? 489 00:38:23,590 --> 00:38:28,520 [L'élève] cpy? Strcpy >>. 490 00:38:28,520 --> 00:38:32,700 strcpy homme. 491 00:38:36,120 --> 00:38:39,590 Donc strcpy strncpy ou. 492 00:38:39,590 --> 00:38:43,410 strncpy est un peu plus sûr puisque vous pouvez spécifier exactement combien de caractères, 493 00:38:43,410 --> 00:38:46,190 mais ici ce n'est pas grave parce que nous savons. 494 00:38:46,190 --> 00:38:50,340 Donc strcpy et de regarder dans les arguments. 495 00:38:50,340 --> 00:38:53,100 Le premier argument est notre destination. 496 00:38:53,100 --> 00:38:56,770 Le second argument est notre source. 497 00:38:56,770 --> 00:39:10,310 Nous allons copier dans notre destination * s le pointeur "BOOM". 498 00:39:10,310 --> 00:39:19,820 Pourquoi auriez-vous envie de faire cela avec un strcpy au lieu de simplement ce que nous avions avant 499 00:39:19,820 --> 00:39:22,800 d'* s = "BOOM"? 500 00:39:22,800 --> 00:39:28,630 Il ya une raison pour laquelle vous voudrez peut-être le faire, mais quelle est cette raison? 501 00:39:28,630 --> 00:39:31,940 [L'élève] Si vous voulez changer quelque chose dans "BOOM". Ouais >>. 502 00:39:31,940 --> 00:39:37,950 Maintenant, je peux faire quelque chose comme s [0] = 'X'; 503 00:39:37,950 --> 00:39:48,190 parce que les points s sur le tas et que l'espace sur le tas qui s est orientée vers 504 00:39:48,190 --> 00:39:52,320 est un pointeur vers plus d'espace sur le tas, ce qui est le stockage "BOOM". 505 00:39:52,320 --> 00:39:55,150 Donc, cette copie de "BOOM" est stocké dans le tas. 506 00:39:55,150 --> 00:39:58,780 Il ya techniquement deux exemplaires de "BOOM" dans notre programme. 507 00:39:58,780 --> 00:40:03,500 Il est le premier qui vient donnée par cette constante "BOOM" chaîne de caractères, 508 00:40:03,500 --> 00:40:09,250 et la deuxième copie de "BOOM", strcpy crée la copie de "BOOM". 509 00:40:09,250 --> 00:40:13,100 Mais la copie de "BOOM" est stocké sur le tas, et le tas vous êtes libre de changer. 510 00:40:13,100 --> 00:40:17,250 Le tas est pas en lecture seule, ce qui signifie que s [0] 511 00:40:17,250 --> 00:40:20,500 va vous permettre de modifier la valeur de "BOOM". 512 00:40:20,500 --> 00:40:23,130 Il va vous permettre de modifier ces caractères. 513 00:40:23,130 --> 00:40:26,640 >> Des questions? 514 00:40:27,740 --> 00:40:29,290 D'accord. 515 00:40:29,290 --> 00:40:35,500 >> Passant à buggy3, nous allons de gdb buggy3. 516 00:40:35,500 --> 00:40:39,840 Nous venons de le faire fonctionner et nous voyons nous obtenons une erreur de segmentation. 517 00:40:39,840 --> 00:40:46,550 Si l'on trace, il ya seulement deux fonctions. 518 00:40:46,550 --> 00:40:52,970 Si nous remontons dans notre fonction principale, nous voyons que nous crashait sur cette ligne. 519 00:40:52,970 --> 00:41:00,180 Il suffit donc de regarder cette ligne, for (int ligne = 0; fgets ce genre de choses ne NULL n'est pas égale; 520 00:41:00,180 --> 00:41:03,770 ligne + +). 521 00:41:03,770 --> 00:41:08,010 Notre image précédente a été appelé _IO_fgets. 522 00:41:08,010 --> 00:41:10,720 Vous verrez que beaucoup de fonctions C intégrés, 523 00:41:10,720 --> 00:41:15,350 que lorsque vous obtenez l'erreur de segmentation, il y aura vraiment des noms de fonctions cryptiques 524 00:41:15,350 --> 00:41:18,090 comme ceci _IO_fgets. 525 00:41:18,090 --> 00:41:21,770 Mais cela va se rapporter à cet appel fgets. 526 00:41:21,770 --> 00:41:25,850 Quelque part à l'intérieur ici, nous sommes des erreurs de segmentation. 527 00:41:25,850 --> 00:41:30,340 Si nous regardons les arguments à fgets, nous pouvons imprimer tampon. 528 00:41:30,340 --> 00:41:41,180 Nous allons imprimer en tant que - Oh, non. 529 00:41:48,980 --> 00:41:51,900 D'impression n'est pas d'aller travailler exactement comme je veux. 530 00:41:55,460 --> 00:41:58,000 Regardons le programme proprement dit. 531 00:42:02,200 --> 00:42:09,640 Le tampon est un tableau de caractères. C'est un tableau de caractères de 128 caractères. 532 00:42:09,640 --> 00:42:14,980 Donc, quand je dis tampon d'impression, il va imprimer ces 128 caractères, 533 00:42:14,980 --> 00:42:18,300 qui je pense est ce qui est attendu. 534 00:42:18,300 --> 00:42:21,390 Qu'est-ce que je cherchais est d'imprimer l'adresse de tampon, 535 00:42:21,390 --> 00:42:23,680 mais cela ne me dit pas vraiment grand-chose. 536 00:42:23,680 --> 00:42:30,770 Donc, quand il m'arrive de dire ici x tampon, il me montre 0xbffff090, 537 00:42:30,770 --> 00:42:38,690 qui, si vous vous souvenez de plus tôt ou un certain point, Oxbffff tend à être une région pile-ish. 538 00:42:38,690 --> 00:42:46,020 La pile a tendance à commencer quelque part un peu moins de 0xC000. 539 00:42:46,020 --> 00:42:51,890 Juste en voyant cette adresse, je sais que le tampon qui se passe sur la pile. 540 00:42:51,890 --> 00:43:04,500 Le redémarrage de mon programme, courir, jusqu'à, tamponner nous avons vu était cette séquence de caractères 541 00:43:04,500 --> 00:43:06,530 qui sont à peu près vide de sens. 542 00:43:06,530 --> 00:43:12,270 Puis en imprimant le fichier, ce fichier ne ressemblerait-il? 543 00:43:15,120 --> 00:43:17,310 [L'élève] Null. Ouais >>. 544 00:43:17,310 --> 00:43:22,610 Le fichier est un des type FILE *, il est donc un pointeur, 545 00:43:22,610 --> 00:43:26,610 et la valeur de ce pointeur est nul. 546 00:43:26,610 --> 00:43:33,240 Donc fgets va essayer de lire à partir de ce pointeur d'une manière indirecte, 547 00:43:33,240 --> 00:43:37,320 mais dans le but d'accéder à ce pointeur, il doit le déréférencement. 548 00:43:37,320 --> 00:43:40,550 Ou, dans le but d'accéder à ce qu'il devrait être dirigée vers, il le déréférence. 549 00:43:40,550 --> 00:43:43,810 Donc, c'est le déréférencement d'un pointeur null et il segfault. 550 00:43:46,600 --> 00:43:48,730 J'aurais pu le redémarrage de là. 551 00:43:48,730 --> 00:43:52,170 Si nous rompons notre principal point de fuite, 552 00:43:52,170 --> 00:43:57,320 la première ligne de code est char * filename = "nonexistent.txt"; 553 00:43:57,320 --> 00:44:00,870 Cela devrait vous donner un indice assez grand pour expliquer pourquoi ce programme échoue. 554 00:44:00,870 --> 00:44:06,080 Taper prochaine m'amène à la ligne suivante, où je ouvrir ce fichier, 555 00:44:06,080 --> 00:44:11,140 et puis j'ai tout de suite entrer dans notre ligne, où une fois que j'ai touché prochaine, il va erreur de segmentation. 556 00:44:11,140 --> 00:44:16,880 Quelqu'un veut-il jeter une raison pour laquelle nous pourrions être des erreurs de segmentation? 557 00:44:16,880 --> 00:44:19,130 [L'élève] Le fichier n'existe pas. Ouais >>. 558 00:44:19,130 --> 00:44:22,250 Ceci est censé être un indice 559 00:44:22,250 --> 00:44:29,570 que chaque fois que vous ouvrez un fichier, vous devez vérifier que le fichier existe réellement. 560 00:44:29,570 --> 00:44:31,510 Donc, ici, "nonexistent.txt"; 561 00:44:31,510 --> 00:44:34,700 Lorsque nous avons fichier fopen pour la lecture, nous avons alors besoin de dire 562 00:44:34,700 --> 00:44:45,870 if (fichier == NULL) et dire printf ("Le fichier n'existe pas!" 563 00:44:45,870 --> 00:44:56,340 ou - mieux encore - filename); return 1; 564 00:44:56,340 --> 00:45:00,300 Alors maintenant, nous vérifions pour voir si elle est NULL 565 00:45:00,300 --> 00:45:03,930 avant même de poursuivre et d'essayer de lire ce fichier. 566 00:45:03,930 --> 00:45:08,800 Nous pouvons le refaire juste pour voir que cela fonctionne. 567 00:45:11,020 --> 00:45:14,970 J'ai l'intention d'inclure une nouvelle ligne. 568 00:45:21,090 --> 00:45:25,290 Alors maintenant, nonexistent.txt n'existe pas. 569 00:45:26,890 --> 00:45:30,040 Vous devriez toujours vérifier ce genre de chose. 570 00:45:30,040 --> 00:45:33,870 Vous devriez toujours vérifier pour voir si fopen retourne NULL. 571 00:45:33,870 --> 00:45:38,170 Vous devriez toujours vérifier pour s'assurer que malloc ne retourne pas NULL, 572 00:45:38,170 --> 00:45:41,410 ou bien vous segfault. 573 00:45:42,200 --> 00:45:45,930 >> Maintenant buggy4.c. 574 00:45:49,190 --> 00:45:58,440 Running. Je devine que cela est en attente d'entrée ou de boucle infinie peut-être. 575 00:45:58,440 --> 00:46:01,870 Oui, c'est une boucle infinie. 576 00:46:01,870 --> 00:46:05,560 Donc buggy4. Il semble que nous sommes en boucle infinie. 577 00:46:05,560 --> 00:46:12,590 Nous pouvons briser au principal, exécuter notre programme. 578 00:46:12,590 --> 00:46:20,180 Avec gdb, aussi longtemps que l'abréviation que vous utilisez est sans ambiguïté 579 00:46:20,180 --> 00:46:23,420 ou abréviations spéciales qu'elles offrent pour vous, 580 00:46:23,420 --> 00:46:29,020 alors vous pouvez utiliser n utiliser ensuite au lieu d'avoir à taper suivant tout le chemin. 581 00:46:29,020 --> 00:46:33,730 Et maintenant que j'ai frappé une fois n, je peux juste appuyer sur Entrée pour continuer prochaine 582 00:46:33,730 --> 00:46:36,640 au lieu d'avoir à frapper n Entrez, Entrez n, n Entrée. 583 00:46:36,640 --> 00:46:44,630 On dirait que je suis dans une sorte de boucle for qui est mise en tableau [i] à 0. 584 00:46:44,630 --> 00:46:50,510 On dirait que je ne suis jamais sortir de cette boucle for. 585 00:46:50,510 --> 00:46:54,780 Si je i imprimer, donc i vaut 2, alors je vais aller. 586 00:46:54,780 --> 00:46:59,250 Je vais imprimer i, i vaut 3, alors je vais aller. 587 00:46:59,250 --> 00:47:05,360 Je vais imprimer i et i est 3. Ensuite, j'ai l'impression, i est 4. 588 00:47:05,360 --> 00:47:14,520 En fait, l'impression sizeof (array), donc la taille de la matrice est de 20. 589 00:47:16,310 --> 00:47:32,870 Mais il semble qu'il y ait une certaine commande gdb spécial pour aller jusqu'à ce que quelque chose arrive. 590 00:47:32,870 --> 00:47:37,620 C'est comme mettre une condition sur la valeur de la variable. Mais je ne me souviens pas ce que c'est. 591 00:47:37,620 --> 00:47:44,100 Donc, si nous continuons - 592 00:47:44,100 --> 00:47:47,120 Que disiez-vous? Qu'avez-vous monter? 593 00:47:47,120 --> 00:47:50,500 [L'élève] Est-ce que je ajouter afficher - >> Oui. Donc afficher je peux aider. 594 00:47:50,500 --> 00:47:54,530 Si nous nous contentons i afficher, il sera mis en place voici ce que la valeur de i est 595 00:47:54,530 --> 00:47:56,470 donc je n'ai pas l'imprimer à chaque fois. 596 00:47:56,470 --> 00:48:02,930 Si nous just keep going suivant, nous voyons 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5. 597 00:48:02,930 --> 00:48:08,530 Quelque chose va terriblement mal, et i étant remis à 0. 598 00:48:13,330 --> 00:48:22,220 En regardant buggy4.c, nous voyons tout ce qui arrive est un tableau int [5]; 599 00:48:22,220 --> 00:48:26,200 for (i = 0; i <= sizeof (array); i + +) 600 00:48:26,200 --> 00:48:28,550 tableau [i] = 0; 601 00:48:28,550 --> 00:48:31,390 Que voyons-nous que c'est mal ici? 602 00:48:31,390 --> 00:48:39,480 Comme un soupçon, quand je faisais le gdb buggy4 - brisons principal, course - 603 00:48:39,480 --> 00:48:45,980 Je n'ai impression sizeof (array), juste pour voir ce que la condition est l'endroit où je devrais enfin éclater. 604 00:48:47,690 --> 00:48:51,100 Où suis-je? Ai-je courir? 605 00:48:51,100 --> 00:48:54,280 Je n'ai pas encore déclarer. 606 00:48:54,280 --> 00:48:58,680 Donc imprimer sizeof (array) et c'est 20, 607 00:48:58,680 --> 00:49:06,690 qui est attendue depuis mon tableau est de taille 5 et il est de 5 entiers, 608 00:49:06,690 --> 00:49:12,410 si la chose entière doit être de 5 * sizeof (int) octets, sizeof (int) tend à être 4. 609 00:49:12,410 --> 00:49:14,780 Donc, sizeof (array) est de 20. 610 00:49:14,780 --> 00:49:17,420 Que doit-il être? 611 00:49:17,420 --> 00:49:21,720 [L'élève] Divisé par sizeof (int). >> Ouais, / sizeof (int). 612 00:49:21,720 --> 00:49:30,630 Il semble qu'il y ait toujours un problème ici. Je pense que ce devrait juste être < 613 00:49:30,630 --> 00:49:36,960 car il est à peu près toujours 00:49:44,860 Maintenant, nous allons réfléchir à pourquoi cela a été fait rompu. 615 00:49:44,860 --> 00:49:53,370 Quelqu'un at-il devine pourquoi ai-je été remis à 0 dans chaque itération de la boucle? 616 00:50:01,300 --> 00:50:09,350 La seule chose à l'intérieur de ce qui se passe ici, c'est que tab [i] est réglé sur 0. 617 00:50:09,350 --> 00:50:15,350 Donc, en quelque sorte, cette ligne de code est à l'origine de notre int i pour être mis à 0. 618 00:50:16,730 --> 00:50:23,130 [L'élève] Serait-ce parce que c'est la substitution de la mémoire de cette partie de i 619 00:50:23,130 --> 00:50:27,970 quand il pense que c'est l'élément suivant du tableau? >> [Bowden] Oui. 620 00:50:27,970 --> 00:50:33,880 Lorsque nous allons au-delà de la fin de notre tableau, 621 00:50:33,880 --> 00:50:39,870 en quelque sorte que l'espace que nous la surcharge est la substitution de la valeur de i. 622 00:50:39,870 --> 00:50:48,030 Et si nous regardons dans buggy4, briser principal, courir, 623 00:50:48,030 --> 00:50:53,120 nous allons imprimer l'adresse de i. 624 00:50:53,120 --> 00:50:57,280 On dirait que c'est bffff124. 625 00:50:57,280 --> 00:51:03,930 Maintenant, nous allons imprimer l'adresse de tableau [0]. 110. 626 00:51:03,930 --> 00:51:06,290 Qu'en est-il [1]? 114. 627 00:51:06,290 --> 00:51:07,920 [2], 118. 628 00:51:07,920 --> 00:51:14,530 11c, 120. array [5] est bfff124. 629 00:51:14,530 --> 00:51:26,990 Donc array [5] a la même adresse que i, ce qui signifie que array [5] i. 630 00:51:26,990 --> 00:51:30,720 S'ils ont la même adresse, ils sont la même chose. 631 00:51:30,720 --> 00:51:38,410 Donc, lorsque nous avons créé array [5] à 0, nous sommes i la mise à 0. 632 00:51:38,410 --> 00:51:46,070 Et si vous pensez à ce sujet dans termes de la pile, 633 00:51:46,070 --> 00:51:55,590 int i est déclarée en premier, ce qui signifie que i ait un peu d'espace sur la pile. 634 00:51:55,590 --> 00:52:04,730 Puis array [5] est affecté, de sorte alors 20 octets sont alloués sur la pile. 635 00:52:04,730 --> 00:52:08,400 Donc j'ai est alloué en premier, ces 20 octets se alloué. 636 00:52:08,400 --> 00:52:11,400 Donc, je passe juste avant le tableau, 637 00:52:11,400 --> 00:52:19,230 et à cause de la façon dont, comme je l'ai dit la semaine dernière, lorsque cela est techniquement la pile grandit vers le bas, 638 00:52:19,230 --> 00:52:28,520 lorsque vous indice dans un tableau, nous avons la garantie que la position 0e dans le tableau 639 00:52:28,520 --> 00:52:31,970 il arrive toujours avant la première position dans la matrice. 640 00:52:31,970 --> 00:52:35,900 C'est un peu de la façon dont je l'ai dessiné la semaine dernière. 641 00:52:35,900 --> 00:52:42,210 Remarquez qu'au fond nous avons l'adresse 0 et au sommet, nous avons Max adresse. 642 00:52:42,210 --> 00:52:44,880 La pile est toujours de plus en plus vers le bas. 643 00:52:48,100 --> 00:52:53,500 Disons que nous i allouer. 644 00:52:53,500 --> 00:52:59,680 Nous attribuons entier i, ce qui signifie Disons simplement ici entier i est alloué. 645 00:52:59,680 --> 00:53:06,420 Ensuite, nous attribuons notre tableau de 5 entiers, ce qui signifie qu'en dessous de ce que, 646 00:53:06,420 --> 00:53:11,230 depuis la pile est de plus en plus vers le bas, les 5 entiers se alloué. 647 00:53:11,230 --> 00:53:15,900 Mais à cause de la façon dont les tableaux travailler, nous garanti que la première position dans le tableau 648 00:53:15,900 --> 00:53:22,260 a toujours une adresse inférieure à la seconde chose dans le tableau. 649 00:53:22,260 --> 00:53:28,270 Ainsi, la position 0 tableau est toujours à cela arrive d'abord dans la mémoire, 650 00:53:28,270 --> 00:53:30,700 tandis que 1 position du tableau qui doit arriver après cela 651 00:53:30,700 --> 00:53:33,310 et 2 position du tableau qui doit arriver après cela, 652 00:53:33,310 --> 00:53:37,900 ce qui signifie que la position 0 éventail allait arriver quelque part ici-bas, 653 00:53:37,900 --> 00:53:40,690 1 position large qui se passerait au-dessus de ce que 654 00:53:40,690 --> 00:53:45,530 car le déplacement en place des moyens plus élevés d'adresse depuis l'adresse maximale est ici. 655 00:53:45,530 --> 00:53:50,490 Donc array [0] ici-bas, array [1] ici, array [2] ici, array [3] ici. 656 00:53:50,490 --> 00:53:55,620 Remarquez comment nous avons attribué, avant entier i tout le chemin jusqu'à ici, 657 00:53:55,620 --> 00:54:01,040 que nous nous dirigeons de plus en plus dans notre tableau, nous nous rapprochons et plus proche de notre entier i. 658 00:54:01,040 --> 00:54:07,640 Il se trouve que array [5], qui est une position au-delà de notre gamme, 659 00:54:07,640 --> 00:54:13,010 C'est exactement là où je me trouvais entier à allouer. 660 00:54:13,010 --> 00:54:16,920 Donc, c'est le point où nous nous trouvons à frapper l'espace sur la pile 661 00:54:16,920 --> 00:54:21,680 qui a été alloué pour l'entier i, et que nous mettons en place à 0. 662 00:54:21,680 --> 00:54:26,160 >> C'est comme ça que fonctionne. Des questions? Ouais. 663 00:54:26,160 --> 00:54:30,710 [L'élève] Peu importe. D'accord. 664 00:54:30,710 --> 00:54:33,090 [L'élève] Comment pouvez-vous éviter ce genre de fautes? 665 00:54:33,090 --> 00:54:41,190 Ce genre d'erreurs? Ne pas utiliser C comme langage de programmation. 666 00:54:41,190 --> 00:54:45,840 Utilisez un langage qui doit limites du tableau de contrôle. 667 00:54:45,840 --> 00:54:55,900 Tant que vous êtes prudent, vous avez juste besoin d'éviter d'aller au-delà des limites de votre tableau. 668 00:54:55,900 --> 00:54:58,300 [L'élève] Donc ici quand nous sommes allés au-delà des limites de votre réseau - 669 00:54:58,300 --> 00:55:01,840 [Bowden] C'est là que les choses commencent à aller mal. >> [L'élève] Oh, d'accord. 670 00:55:01,840 --> 00:55:05,730 Tant que vous restez dans la mémoire allouée à votre tableau, vous êtes très bien. 671 00:55:05,730 --> 00:55:12,400 Mais C ne fait pas de vérification d'erreur. Si je fais tableau [1000], il se fera un plaisir il suffit de modifier quoi qu'il arrive - 672 00:55:12,400 --> 00:55:16,500 Il va au début du tableau, puis il va après 1000 positions et le met à 0. 673 00:55:16,500 --> 00:55:20,000 Il ne fait pas de vérification que oh, ce n'est pas vraiment 1000 choses en elle. 674 00:55:20,000 --> 00:55:22,750 1000 est bien au-delà ce que je devrais changer, 675 00:55:22,750 --> 00:55:26,940 tandis que Java ou quelque chose que vous aurez baie hors de l'indice de limites 676 00:55:26,940 --> 00:55:29,820 ou indice sur des bornes exception. 677 00:55:29,820 --> 00:55:33,950 C'est pourquoi un grand nombre de langues de niveau supérieur ont ces choses 678 00:55:33,950 --> 00:55:37,340 où si vous allez au-delà des limites du tableau, vous ne 679 00:55:37,340 --> 00:55:40,070 de sorte que vous ne pouvez pas changer les choses par-dessous vous 680 00:55:40,070 --> 00:55:42,590 et puis les choses se passent bien pire que le simple fait d'exception 681 00:55:42,590 --> 00:55:44,940 dire que vous êtes allé au-delà de la fin du tableau. 682 00:55:44,940 --> 00:55:50,970 [L'élève] Et ne devrait donc nous avons juste changé le <= juste > [Bowden] Ouais. 683 00:55:50,970 --> 00:55:54,800 Il devrait être 00:55:59,560 depuis sizeof (array) est de 20, mais nous ne voulons 5. >> [L'élève] Droit. 685 00:55:59,560 --> 00:56:04,060 Plus de questions? D'accord. 686 00:56:04,060 --> 00:56:07,380 >> [L'élève] J'ai une question. Ouais >>. 687 00:56:07,380 --> 00:56:16,440 [L'élève] Quelle est la variable tableau réel? 688 00:56:16,440 --> 00:56:20,000 [Bowden] Comme quoi est un tableau? 689 00:56:20,000 --> 00:56:24,930 Tableau lui-même est un symbole. 690 00:56:24,930 --> 00:56:31,490 Il est simplement l'adresse du début des 20 octets qui nous référencent. 691 00:56:31,490 --> 00:56:38,070 Vous pouvez penser que c'est un pointeur, mais il est un pointeur constant. 692 00:56:38,070 --> 00:56:44,140 Dès que les choses se compilée, la variable tableau n'existe plus. 693 00:56:44,140 --> 00:56:48,210 [L'élève] Alors, comment trouver la taille de tableau? 694 00:56:48,210 --> 00:56:54,130 Taille du tableau correspond à la taille de ce bloc qui se rapporte à ce symbole. 695 00:56:54,130 --> 00:57:01,240 Quand je fais quelque chose comme printf ("% p \ n", array); 696 00:57:01,240 --> 00:57:05,140 nous allons l'exécuter. 697 00:57:12,960 --> 00:57:15,530 Qu'est-ce que je viens de faire le mal? 698 00:57:15,530 --> 00:57:19,220 'Array' tableau déclaré ici. 699 00:57:20,820 --> 00:57:23,200 Oh, là-haut. 700 00:57:23,200 --> 00:57:31,250 Clang est intelligent, et il arrive de constater que j'ai déclaré que le tableau 5 éléments 701 00:57:31,250 --> 00:57:34,540 mais je suis d'indexation en position 1000. 702 00:57:34,540 --> 00:57:38,450 Il peut le faire parce que ce ne sont que des constantes. 703 00:57:38,450 --> 00:57:43,370 Elle ne peut aller aussi loin en remarquant que je vais au-delà des limites du tableau. 704 00:57:43,370 --> 00:57:46,880 Mais remarquez avant lorsque nous avons eu i est incorrecte, 705 00:57:46,880 --> 00:57:51,040 cela ne peut pas déterminer le nombre de valeurs que je pourrais prendre, 706 00:57:51,040 --> 00:57:55,540 de sorte qu'il ne peut pas déterminer ce que j'allais au-delà de la fin du tableau. 707 00:57:55,540 --> 00:57:59,430 C'est juste Clang être intelligent. 708 00:57:59,430 --> 00:58:03,340 >> Mais maintenant faire buggy4. Alors quoi d'autre je fais de mal? 709 00:58:03,340 --> 00:58:05,970 Déclarer implicitement une fonction de bibliothèque 'printf'. 710 00:58:05,970 --> 00:58:14,960 Je vais vouloir # include. 711 00:58:14,960 --> 00:58:18,710 D'accord. Fonctionne maintenant buggy4. 712 00:58:18,710 --> 00:58:24,840 Impression de la valeur du tableau, comme je l'ai fait ici, l'imprimer comme un pointeur 713 00:58:24,840 --> 00:58:30,060 quelque chose de gravures qui ressemble à ceci - bfb8805c - ce qui est une adresse 714 00:58:30,060 --> 00:58:33,450 qui se trouve dans la zone de pile-ish. 715 00:58:33,450 --> 00:58:41,820 Tableau lui-même est comme un pointeur, mais ce n'est pas un pointeur réel, 716 00:58:41,820 --> 00:58:45,410 depuis un pointeur régulière, nous pouvons changer. 717 00:58:45,410 --> 00:58:54,700 Tableau est juste une constante. Les 20 blocs de mémoire commencent à 0xbfb8805c adresse. 718 00:58:54,700 --> 00:59:09,020 Donc bfb8805c via cette adresse +20- ou je suppose -20 - 719 00:59:09,020 --> 00:59:17,400 est toute la mémoire allouée pour ce tableau. 720 00:59:17,400 --> 00:59:20,350 Tableau, la variable elle-même n'est stocké nulle part. 721 00:59:20,350 --> 00:59:27,660 Lorsque vous compilez, le compilateur - vague main à elle - 722 00:59:27,660 --> 00:59:33,060 mais le compilateur ne se serviront où il sait être ensemble. 723 00:59:33,060 --> 00:59:36,090 Il sait où ce tableau commence, 724 00:59:36,090 --> 00:59:40,910 et donc il peut toujours juste faire les choses en termes de compensations de ce début. 725 00:59:40,910 --> 00:59:43,960 Il n'a pas besoin d'une variable pour représenter elle-même matrice. 726 00:59:43,960 --> 00:59:53,730 Mais quand je fais quelque chose comme int * p = array; maintenant p est un pointeur qui pointe vers ce tableau, 727 00:59:53,730 --> 00:59:57,830 et maintenant p existe bel et bien sur la pile. 728 00:59:57,830 --> 01:00:01,950 Je suis libre de changer p. Je peux faire p = malloc. 729 01:00:01,950 --> 01:00:06,500 Donc, il pointait initialement à la matrice, et maintenant il pointe un peu d'espace sur le tas. 730 01:00:06,500 --> 01:00:09,620 Je ne peux pas le faire = array malloc. 731 01:00:09,620 --> 01:00:13,710 Si Clang est intelligent, il va me crier dessus dès le départ. 732 01:00:17,000 --> 01:00:21,430 En fait, je suis sûr que gcc ne le font aussi. 733 01:00:21,430 --> 01:00:25,010 Ainsi type de tableau 'int [5] «n'est pas cessible. 734 01:00:25,010 --> 01:00:28,040 Vous ne pouvez pas assigner quelque chose à un type tableau 735 01:00:28,040 --> 01:00:30,500 parce tableau est juste une constante. 736 01:00:30,500 --> 01:00:34,760 C'est un symbole qui fait référence à ces 20 octets. Je ne peux pas le changer. 737 01:00:34,760 --> 01:00:37,690 >> [L'élève] Et où est la taille du tableau stocké? 738 01:00:37,690 --> 01:00:40,670 [Bowden] Ce n'est pas stocké n'importe où. C'est quand il a la compilation. 739 01:00:40,670 --> 01:00:46,310 Alors, où est la taille du tableau stocké? 740 01:00:46,310 --> 01:00:51,870 Vous ne pouvez utiliser sizeof (array) à l'intérieur de la fonction que le tableau est lui-même déclaré. 741 01:00:51,870 --> 01:01:03,150 Donc, si je fais une fonction, foo, et je le fais (int tableau []) 742 01:01:03,150 --> 01:01:10,450 printf ("% d \ n", sizeof (array)); 743 01:01:10,450 --> 01:01:21,330 et puis ici je appeler foo (array); 744 01:01:21,330 --> 01:01:24,840 l'intérieur de cette fonction - il faut bien l'exécuter. 745 01:01:34,200 --> 01:01:36,840 C'est Clang être intelligent à nouveau. 746 01:01:36,840 --> 01:01:43,890 Il me dit que sizeof le paramètre de la fonction réseau 747 01:01:43,890 --> 01:01:46,690 retourne la taille de la «int *». 748 01:01:46,690 --> 01:01:55,150 Ce serait une erreur si ce n'est pas ce que je voulais arriver. 749 01:01:55,150 --> 01:01:58,960 Nous allons effectivement éteindre Werror. 750 01:02:14,950 --> 01:02:17,590 Avertissement. Les avertissements sont très bien. 751 01:02:17,590 --> 01:02:19,960 Il faudra encore rassembler autant qu'il dispose d'une alarme. 752 01:02:19,960 --> 01:02:22,910 . / A.out va imprimer 4. 753 01:02:22,910 --> 01:02:28,650 L'avertissement qui a été généré est un indicateur clair de ce qui s'est passé. 754 01:02:28,650 --> 01:02:34,120 Ce tableau int va juste pour imprimer sizeof (int *). 755 01:02:34,120 --> 01:02:39,790 Même si je mets array [5] ici, c'est toujours aller juste pour imprimer sizeof (int *). 756 01:02:39,790 --> 01:02:47,440 Donc dès que vous passez dans une fonction, la distinction entre les tableaux et les pointeurs 757 01:02:47,440 --> 01:02:49,670 est inexistant. 758 01:02:49,670 --> 01:02:52,640 Cela arrive à être un tableau qui a été déclaré sur la pile, 759 01:02:52,640 --> 01:02:58,300 mais dès que nous passons de cette valeur, que 0xbf blah, blah, blah dans cette fonction, 760 01:02:58,300 --> 01:03:03,350 puis ce pointeur pointe sur cette matrice dans la pile. 761 01:03:03,350 --> 01:03:08,310 Cela signifie donc que sizeof ne s'applique que dans la fonction que le tableau a été déclaré, 762 01:03:08,310 --> 01:03:11,230 ce qui signifie que si vous compilez cette fonction, 763 01:03:11,230 --> 01:03:17,330 quand Clang passe par cette fonction, il voit tableau est un tableau de taille 5 int. 764 01:03:17,330 --> 01:03:20,640 Alors il voit sizeof (tableau). Eh bien, c'est 20. 765 01:03:20,640 --> 01:03:26,440 En fait, c'est la façon dont fonctionne essentiellement sizeof pour presque tous les cas. 766 01:03:26,440 --> 01:03:31,150 Sizeof n'est pas une fonction, c'est un opérateur. 767 01:03:31,150 --> 01:03:33,570 Vous n'appelez pas la fonction sizeof. 768 01:03:33,570 --> 01:03:38,280 Sizeof (int), le compilateur juste traduire à 4. 769 01:03:41,480 --> 01:03:43,700 Got it? D'accord. 770 01:03:43,700 --> 01:03:47,520 >> [L'élève] Alors, quelle est la différence entre sizeof (array) dans main et dans foo? 771 01:03:47,520 --> 01:03:52,840 C'est parce que nous disons, sizeof (array), qui est de type int *, 772 01:03:52,840 --> 01:03:57,120 tandis que le tableau vers le bas ici n'est pas de type int *, c'est un tableau int. 773 01:03:57,120 --> 01:04:04,540 >> [L'élève] Donc, si vous aviez le paramètre array [] au lieu d'un tableau int *, 774 01:04:04,540 --> 01:04:09,230 serait-ce à dire que vous pouvez toujours modifier tableau, car il est maintenant un pointeur? 775 01:04:09,230 --> 01:04:14,250 [Bowden] Vous aimez? >> [L'élève] Ouais. Pouvez-vous changer tableau dans la fonction maintenant? 776 01:04:14,250 --> 01:04:18,420 [Bowden] Vous pouvez changer de tableau dans les deux cas. 777 01:04:18,420 --> 01:04:23,130 Dans ces deux cas, vous êtes libre de dire array [4] = 0. 778 01:04:23,130 --> 01:04:26,590 [L'élève] Mais pouvez-vous faire le point ensemble à quelque chose d'autre? 779 01:04:26,590 --> 01:04:30,230 [Bowden] Oh. Ouais. Dans les deux cas - >> [l'élève] Ouais. 780 01:04:30,230 --> 01:04:38,410 [Bowden] La distinction entre array [] et un tableau de type int *, il n'en est pas. 781 01:04:38,410 --> 01:04:42,570 Vous pouvez également obtenir des tableaux multidimensionnels ici 782 01:04:42,570 --> 01:04:47,050 pour une syntaxe pratique, mais elle est encore juste un pointeur. 783 01:04:47,050 --> 01:04:56,400 Cela signifie que je suis libre de faire array = malloc (sizeof (int)), et maintenant pointer ailleurs. 784 01:04:56,400 --> 01:04:59,610 Mais tout comme la façon dont cela fonctionne toujours et à jamais, 785 01:04:59,610 --> 01:05:03,210 modifier ce tableau en le faisant pointer vers quelque chose d'autre 786 01:05:03,210 --> 01:05:07,570 ne change pas ce tableau ici-bas parce que c'est une copie de l'argument, 787 01:05:07,570 --> 01:05:10,780 ce n'est pas un pointeur sur cet argument. 788 01:05:10,780 --> 01:05:16,070 Et en fait, tout comme indication de plus que c'est exactement la même chose - 789 01:05:16,070 --> 01:05:21,100 nous avons déjà vu ce tableau impressions impression - 790 01:05:21,100 --> 01:05:31,410 si on imprimer l'adresse du réseau ou l'adresse de l'adresse du tableau 791 01:05:31,410 --> 01:05:36,290 soit à des personnes? 792 01:05:41,770 --> 01:05:45,220 Ignorons celui-ci. 793 01:05:48,140 --> 01:05:51,660 D'accord. C'est très bien. Il tourne maintenant. / A.out. 794 01:05:51,660 --> 01:06:00,220 Ensemble d'impression, puis imprimer l'adresse du tableau, c'est la même chose. 795 01:06:00,220 --> 01:06:02,870 Tableau n'existe tout simplement pas. 796 01:06:02,870 --> 01:06:08,190 Il sait quand vous imprimez tableau, vous imprimez le symbole qui fait référence à ces 20 octets. 797 01:06:08,190 --> 01:06:11,940 Imprimer l'adresse du tableau, ainsi, tableau n'existe pas. 798 01:06:11,940 --> 01:06:17,200 Il ne possède pas d'adresse, il affiche juste l'adresse de ces 20 octets. 799 01:06:20,820 --> 01:06:28,150 Dès que vous compilez le bas, comme dans votre buggy4 compilé. / A.out, 800 01:06:28,150 --> 01:06:30,340 tableau est inexistante. 801 01:06:30,340 --> 01:06:33,640 Pointeurs existent. Les tableaux ne sont pas. 802 01:06:34,300 --> 01:06:38,060 Les blocs de mémoire représentant l'ensemble existent encore, 803 01:06:38,060 --> 01:06:43,270 mais le tableau de variables et les variables de ce type n'existent pas. 804 01:06:46,260 --> 01:06:50,270 Ce sont comme les principales différences entre les tableaux et les pointeurs 805 01:06:50,270 --> 01:06:55,590 sont dès que vous effectuer des appels de fonction, il n'ya aucune différence. 806 01:06:55,590 --> 01:07:00,460 Mais à l'intérieur de la fonction que le tableau lui-même est déclarée, sizeof fonctionne différemment 807 01:07:00,460 --> 01:07:05,190 puisque vous l'impression de la taille des blocs au lieu de la taille du type, 808 01:07:05,190 --> 01:07:08,950 et vous ne pouvez pas le changer parce que c'est un symbole. 809 01:07:08,950 --> 01:07:14,370 Impression de la chose et l'adresse de la chose imprime la même chose. 810 01:07:14,370 --> 01:07:18,480 Et c'est à peu près tout. 811 01:07:18,480 --> 01:07:20,820 [L'élève] Pourriez-vous dire que une fois de plus? 812 01:07:21,170 --> 01:07:24,170 J'ai peut-être raté quelque chose. 813 01:07:24,170 --> 01:07:29,260 Ensemble d'impression et l'adresse du tableau affiche la même chose, 814 01:07:29,260 --> 01:07:33,180 tandis que si vous imprimez un pointeur par rapport à l'adresse du pointeur, 815 01:07:33,180 --> 01:07:36,010 la seule chose imprime l'adresse de ce que vous pointez, 816 01:07:36,010 --> 01:07:40,360 l'autre imprime l'adresse du pointeur sur la pile. 817 01:07:40,360 --> 01:07:47,040 Vous pouvez modifier un pointeur, vous ne pouvez pas changer un symbole de tableau. 818 01:07:47,740 --> 01:07:53,270 Et pointeur sizeof va imprimer la taille de ce type de pointeur. 819 01:07:53,270 --> 01:07:57,470 Donc, int * p sizeof (p) va imprimer 4, 820 01:07:57,470 --> 01:08:04,110 mais int array [5] impression sizeof (array) va imprimer 20. 821 01:08:04,110 --> 01:08:07,480 [L'élève] Donc int array [5] permet d'imprimer 20? Oui >>. 822 01:08:07,480 --> 01:08:13,300 C'est pourquoi l'intérieur de buggy4 quand il l'habitude d'être sizeof (array) 823 01:08:13,300 --> 01:08:16,660 cela a été fait i <20, ce qui n'est pas ce que nous voulions. 824 01:08:16,660 --> 01:08:20,880 Nous voulons que i <5. >> [L'élève] D'accord. 825 01:08:20,880 --> 01:08:25,569 [Bowden] Et puis, dès que vous commencez à passer dans les fonctions, 826 01:08:25,569 --> 01:08:34,340 si nous le faisions int * p = array; 827 01:08:34,340 --> 01:08:39,779 l'intérieur de cette fonction, on peut utiliser fondamentalement p et rangée dans exactement de la même manière, 828 01:08:39,779 --> 01:08:43,710 à l'exception du problème sizeof et le problème de changer. 829 01:08:43,710 --> 01:08:49,810 Mais p [0] = 1; est la même chose que dire array [0] = 1; 830 01:08:49,810 --> 01:08:55,600 Et dès que nous disons foo (array); ou foo (p); 831 01:08:55,600 --> 01:08:59,760 à l'intérieur de la fonction foo, c'est le même appel deux fois. 832 01:08:59,760 --> 01:09:03,350 Il n'y a pas de différence entre ces deux appels. 833 01:09:07,029 --> 01:09:11,080 >> Tout le monde bien sur cela? D'accord. 834 01:09:14,620 --> 01:09:17,950 Nous avons 10 minutes. 835 01:09:17,950 --> 01:09:28,319 >> Nous allons essayer de passer à travers ce programme Typer Hacker, 836 01:09:28,319 --> 01:09:32,350 ce site, qui est sorti l'année dernière ou quelque chose. 837 01:09:34,149 --> 01:09:41,100 C'est juste censé être comme vous tapez au hasard et l'imprime - 838 01:09:41,100 --> 01:09:46,729 Quel que soit le fichier, il arrive à avoir chargé est ce qu'il semble que vous tapez. 839 01:09:46,729 --> 01:09:52,069 Il ressemble à une sorte de code du système d'exploitation. 840 01:09:53,760 --> 01:09:56,890 C'est ce que nous voulons mettre en œuvre. 841 01:10:08,560 --> 01:10:11,690 Vous devriez avoir un fichier binaire exécutable nommé hacker_typer 842 01:10:11,690 --> 01:10:14,350 qui prend en un seul argument, le fichier «type hacker». 843 01:10:14,350 --> 01:10:16,480 Exécution de l'exécutable doit effacer l'écran 844 01:10:16,480 --> 01:10:20,850 et ensuite imprimer un caractère à partir du fichier passé en entrée à chaque fois que l'utilisateur appuie sur une touche. 845 01:10:20,850 --> 01:10:24,990 Donc, quoi que vous appuyez sur la touche, il faut jeter et au lieu d'imprimer un caractère à partir du fichier 846 01:10:24,990 --> 01:10:27,810 c'est l'argument. 847 01:10:29,880 --> 01:10:34,350 Je vais assez bien vous dire ce que les choses que nous allons avoir besoin de connaître sont. 848 01:10:34,350 --> 01:10:36,440 Mais nous voulons aller à votre bibliothèque termios. 849 01:10:36,440 --> 01:10:44,840 Je n'ai jamais utilisé cette bibliothèque dans toute ma vie, donc il a des objectifs très minimes. 850 01:10:44,840 --> 01:10:48,610 Mais cela va être la bibliothèque nous pouvons utiliser pour jeter le personnage que vous a frappé 851 01:10:48,610 --> 01:10:52,390 lorsque vous tapez dans pouces standard 852 01:10:56,970 --> 01:11:05,840 Donc hacker_typer.c, et nous allons vouloir # include. 853 01:11:05,840 --> 01:11:12,870 En regardant la page de manuel de termios - je devine que le terminal OS ou quelque chose - 854 01:11:12,870 --> 01:11:16,240 Je ne sais pas comment le lire. 855 01:11:16,240 --> 01:11:21,040 En regardant cela, il dit d'inclure ces 2 fichiers, de sorte que nous allons faire. 856 01:11:37,620 --> 01:11:46,820 >> La première chose d'abord, nous voulons prendre en un seul argument, qui est le fichier qu'il faut ouvrir. 857 01:11:46,820 --> 01:11:52,420 Alors qu'est-ce que je veux faire? Comment puis-je vérifier pour voir que j'ai un seul argument? 858 01:11:52,420 --> 01:11:56,480 [L'élève] Si elle est égale à argc. >> [Bowden] Ouais. 859 01:11:56,480 --> 01:12:21,250 Donc if (argc = 2!) Printf ("usage:% s [fichier à ouvrir]»). 860 01:12:21,250 --> 01:12:32,750 Alors maintenant, si je lance ce sans fournir un second argument - oh, j'ai besoin de la nouvelle ligne - 861 01:12:32,750 --> 01:12:36,240 vous verrez qu'il dit utilisation:. / hacker_typer, 862 01:12:36,240 --> 01:12:39,770 puis le second argument doit être le fichier que je veux ouvrir. 863 01:12:58,430 --> 01:13:01,260 Maintenant que dois-je faire? 864 01:13:01,260 --> 01:13:08,490 Je veux lire ce fichier. Comment puis-je lire un fichier? 865 01:13:08,490 --> 01:13:11,920 [L'élève] Vous d'abord l'ouvrir. Ouais >>. 866 01:13:11,920 --> 01:13:15,010 Ainsi, la fonction fopen. Qu'est-ce que la fonction fopen ressembler? 867 01:13:15,010 --> 01:13:22,980 [L'élève] Nom de fichier. >> [Bowden] Nom du fichier va être argv [1]. 868 01:13:22,980 --> 01:13:26,110 [L'élève] Et puis ce que vous voulez faire avec elle, de sorte que le - >> [Bowden] Ouais. 869 01:13:26,110 --> 01:13:28,740 Donc, si vous ne me souviens pas, vous pouvez simplement faire fopen homme, 870 01:13:28,740 --> 01:13:32,960 où il va y avoir un chemin const char * nom du fichier où chemin est, 871 01:13:32,960 --> 01:13:34,970 const char * mode d'. 872 01:13:34,970 --> 01:13:38,660 S'il vous arrive de ne pas se souvenir de ce mode est, alors vous pouvez chercher pour le mode. 873 01:13:38,660 --> 01:13:44,660 A l'intérieur des pages de manuel, la barre oblique est ce que vous pouvez utiliser pour rechercher des choses. 874 01:13:44,660 --> 01:13:49,790 Donc je tape / mode à la recherche de mode. 875 01:13:49,790 --> 01:13:57,130 n et N sont ce que vous pouvez utiliser pour faire défiler les matchs de recherche. 876 01:13:57,130 --> 01:13:59,800 Ici, il dit que les argument mode pointe vers une chaîne 877 01:13:59,800 --> 01:14:01,930 en commençant par l'une des séquences suivantes. 878 01:14:01,930 --> 01:14:06,480 Donc r, fichier texte ouvert pour la lecture. C'est ce que nous voulons faire. 879 01:14:08,930 --> 01:14:13,210 Pour la lecture, et je veux qu'elle soit stockée. 880 01:14:13,210 --> 01:14:18,720 La chose va être un FILE *. Maintenant, qu'est-ce que je veux faire? 881 01:14:18,720 --> 01:14:21,200 Donnez-moi une seconde. 882 01:14:28,140 --> 01:14:30,430 D'accord. Maintenant, qu'est-ce que je veux faire? 883 01:14:30,430 --> 01:14:32,940 [L'élève] Vérifiez si c'est NULL. >> [Bowden] Ouais. 884 01:14:32,940 --> 01:14:38,690 Chaque fois que vous ouvrez un fichier, assurez-vous que vous êtes en mesure de réussir l'ouvrir. 885 01:14:58,930 --> 01:15:10,460 >> Maintenant, je veux faire ce genre de choses termios où je veux d'abord lire mes paramètres actuels 886 01:15:10,460 --> 01:15:14,050 et sauver ceux en quelque chose, alors je veux modifier mes réglages 887 01:15:14,050 --> 01:15:19,420 de jeter n'importe quel caractère de type I, 888 01:15:19,420 --> 01:15:22,520 et puis je veux mettre à jour ces paramètres. 889 01:15:22,520 --> 01:15:27,250 Et puis à la fin du programme, je veux revenir à mes paramètres d'origine. 890 01:15:27,250 --> 01:15:32,080 Ainsi, la structure va être de type termios, et je vais vouloir deux d'entre eux. 891 01:15:32,080 --> 01:15:35,600 Le premier va être mes current_settings, 892 01:15:35,600 --> 01:15:42,010 et puis ils vont être mes hacker_settings. 893 01:15:42,010 --> 01:15:48,070 Tout d'abord, je vais souhaitez enregistrer mes paramètres actuels, 894 01:15:48,070 --> 01:15:53,790 alors je vais mettre à jour hacker_settings, 895 01:15:53,790 --> 01:16:01,570 puis cours à la fin de mon programme, je veux revenir aux paramètres actuels. 896 01:16:01,570 --> 01:16:08,660 Ainsi, l'enregistrement des paramètres actuels, la façon dont cela fonctionne, nous termios homme. 897 01:16:08,660 --> 01:16:15,810 Nous voyons que nous avons cette tcsetattr int, int tcgetattr. 898 01:16:15,810 --> 01:16:22,960 Je passe dans une structure termios par son pointeur. 899 01:16:22,960 --> 01:16:30,640 La façon dont cela va regarder est - je l'ai déjà oublié ce que la fonction a été appelée. 900 01:16:30,640 --> 01:16:34,930 Copiez et collez. 901 01:16:39,150 --> 01:16:45,500 Donc tcgetattr, alors je veux faire passer dans la structure que je suis d'enregistrer les informations dans, 902 01:16:45,500 --> 01:16:49,650 qui va être current_settings, 903 01:16:49,650 --> 01:16:59,120 et le premier argument est le descripteur de fichier pour la chose que je veux enregistrer les attributs de. 904 01:16:59,120 --> 01:17:04,360 Ce que le descripteur de fichier est est comme chaque fois que vous ouvrez un fichier, il reçoit un descripteur de fichier. 905 01:17:04,360 --> 01:17:14,560 Quand je fopen argv [1], il reçoit un descripteur de fichier qui vous référencez 906 01:17:14,560 --> 01:17:16,730 chaque fois que vous voulez lire ou écrire. 907 01:17:16,730 --> 01:17:19,220 Ce n'est pas un descripteur de fichier que je veux utiliser ici. 908 01:17:19,220 --> 01:17:21,940 Il ya trois descripteurs de fichiers que vous avez par défaut, 909 01:17:21,940 --> 01:17:24,310 qui sont la norme dans, la sortie standard et l'erreur standard. 910 01:17:24,310 --> 01:17:29,960 Par défaut, je pense que c'est la norme en est 0, la sortie standard est de 1, et de l'erreur-type vaut 2. 911 01:17:29,960 --> 01:17:33,980 Alors qu'est-ce que je veux changer les paramètres de? 912 01:17:33,980 --> 01:17:37,370 Je veux changer les paramètres de chaque fois que je touché un caractère, 913 01:17:37,370 --> 01:17:41,590 Je veux lancer ce caractère de suite au lieu de l'imprimer à l'écran. 914 01:17:41,590 --> 01:17:45,960 Que flux - standard, la sortie standard ou d'erreur standard - 915 01:17:45,960 --> 01:17:52,050 répond à des choses quand je tape au clavier? >> [L'élève] Standard po >> Oui. 916 01:17:52,050 --> 01:17:56,450 Donc, je peux soit faire 0 ou je peux faire stdin. 917 01:17:56,450 --> 01:17:59,380 Je reçois le current_settings des pouces standard 918 01:17:59,380 --> 01:18:01,720 >> Maintenant, je veux mettre à jour ces paramètres, 919 01:18:01,720 --> 01:18:07,200 si d'abord je vais copier dans hacker_settings ce que mes current_settings sont. 920 01:18:07,200 --> 01:18:10,430 Et comment le travail est structs il suffit de copier. 921 01:18:10,430 --> 01:18:14,510 Cela permet de copier tous les champs, comme vous le souhaitiez. 922 01:18:14,510 --> 01:18:17,410 >> Maintenant, je veux mettre à jour certains champs. 923 01:18:17,410 --> 01:18:21,670 En regardant termios, vous devez lire beaucoup de ce 924 01:18:21,670 --> 01:18:24,110 juste pour voir ce que vous voulez chercher, 925 01:18:24,110 --> 01:18:28,210 mais les drapeaux que vous allez avoir à rechercher sont l'écho, 926 01:18:28,210 --> 01:18:33,110 si ECHO saisir les caractères Echo. 927 01:18:33,110 --> 01:18:37,710 Je veux d'abord régler - je l'ai déjà oublié ce que les champs sont. 928 01:18:45,040 --> 01:18:47,900 C'est ce que la structure ressemble. 929 01:18:47,900 --> 01:18:51,060 Ainsi, les modes d'entrée, je pense que nous voulons changer. 930 01:18:51,060 --> 01:18:54,210 Nous allons examiner la solution pour vous assurer que c'est ce que nous voulons changer. 931 01:19:04,060 --> 01:19:12,610 Nous voulons changer lflag afin de prévenir besoin de regarder à travers tout cela. 932 01:19:12,610 --> 01:19:14,670 Nous voulons changer les modes locaux. 933 01:19:14,670 --> 01:19:17,710 Vous n'avez pas à lire toute cette chose à comprendre où tout appartient 934 01:19:17,710 --> 01:19:19,320 que nous voulons changer. 935 01:19:19,320 --> 01:19:24,120 Mais c'est à l'intérieur des modes locaux où nous allons voulons changer cela. 936 01:19:27,080 --> 01:19:33,110 Donc hacker_settings.cc_lmode est ce que ça s'appelle. 937 01:19:39,630 --> 01:19:43,020 c_lflag. 938 01:19:49,060 --> 01:19:52,280 C'est là que nous entrons dans des opérateurs de bits. 939 01:19:52,280 --> 01:19:54,860 Nous sommes un peu hors du temps, mais nous allons passer par là très vite. 940 01:19:54,860 --> 01:19:56,600 C'est là que nous entrons dans des opérateurs de bits, 941 01:19:56,600 --> 01:19:59,950 où je crois que j'ai dit une fois il ya longtemps que chaque fois que vous commencer à traiter avec des drapeaux, 942 01:19:59,950 --> 01:20:03,370 vous allez être en utilisant l'opérateur bit à bit beaucoup. 943 01:20:03,370 --> 01:20:08,240 Chaque bit dans le drapeau correspond à une sorte de comportement. 944 01:20:08,240 --> 01:20:14,090 Donc, ici, ce drapeau a un tas de choses différentes, où chacun d'eux signifie quelque chose de différent. 945 01:20:14,090 --> 01:20:18,690 Mais ce que je veux faire est de simplement désactiver le bit qui correspond à ECHO. 946 01:20:18,690 --> 01:20:25,440 Donc, pour éteindre ça que je fais et = ¬ ECHO. 947 01:20:25,440 --> 01:20:30,110 En fait, je pense que c'est comme Techo ou quelque chose. Je vais vérifier de nouveau. 948 01:20:30,110 --> 01:20:34,050 Je peux le termios. C'est juste ECHO. 949 01:20:34,050 --> 01:20:38,440 ECHO va être un peu seul. 950 01:20:38,440 --> 01:20:44,230 ¬ ECHO va dire tous les bits sont mis à 1, ce qui signifie que tous les drapeaux sont définies sur true 951 01:20:44,230 --> 01:20:47,140 à l'exception du bit ECHO. 952 01:20:47,140 --> 01:20:53,830 En mettant fin à mes drapeaux locales avec cela, cela signifie que tous les drapeaux qui sont actuellement définies sur true 953 01:20:53,830 --> 01:20:56,520 sera toujours la valeur true. 954 01:20:56,520 --> 01:21:03,240 Si mon drapeau ECHO est définie sur true, cela est nécessairement définie sur false sur le drapeau ECHO. 955 01:21:03,240 --> 01:21:07,170 Donc cette ligne de code tourne juste à côté du drapeau ECHO. 956 01:21:07,170 --> 01:21:16,270 Les autres lignes de code, je vais les copier dans l'intérêt de temps et puis les expliquer. 957 01:21:27,810 --> 01:21:30,180 Dans la solution, at-il dit 0. 958 01:21:30,180 --> 01:21:33,880 Il est probablement mieux de dire explicitement stdin. 959 01:21:33,880 --> 01:21:42,100 >> Remarquez que je fais aussi ECHO | ICANON ici. 960 01:21:42,100 --> 01:21:46,650 ICANON se réfère à quelque chose de séparé, ce qui signifie que le mode canonique. 961 01:21:46,650 --> 01:21:50,280 Quels sont les moyens mode canonique est habituellement quand vous tapez sur la ligne de commande, 962 01:21:50,280 --> 01:21:54,670 norme ne traite pas de rien jusqu'à ce que vous appuyez sur une nouvelle ligne. 963 01:21:54,670 --> 01:21:58,230 Ainsi, lorsque vous ne GetString, vous tapez un tas de choses, alors vous frappez saut de ligne. 964 01:21:58,230 --> 01:22:00,590 C'est quand il est envoyé à la norme po 965 01:22:00,590 --> 01:22:02,680 C'est la valeur par défaut. 966 01:22:02,680 --> 01:22:05,830 Lorsque je désactive le mode canonique, maintenant chaque personnage que vous appuyez sur 967 01:22:05,830 --> 01:22:10,910 est ce qui doit être traitée, ce qui est généralement un peu mal parce que c'est lent à traiter ces choses, 968 01:22:10,910 --> 01:22:14,330 C'est pourquoi il est bon de mettre en mémoire tampon dans les lignes entières. 969 01:22:14,330 --> 01:22:16,810 Mais je veux que chaque personnage à traiter 970 01:22:16,810 --> 01:22:18,810 car je ne voulez pas attendre pour moi de frapper saut de ligne 971 01:22:18,810 --> 01:22:21,280 avant de traiter tous les personnages que j'ai tapé. 972 01:22:21,280 --> 01:22:24,760 Cela désactive le mode canonique. 973 01:22:24,760 --> 01:22:31,320 Ce truc signifie simplement que quand il traite en fait des personnages. 974 01:22:31,320 --> 01:22:35,830 Cela signifie les traiter immédiatement, dès que je les taper, de les traiter. 975 01:22:35,830 --> 01:22:42,510 Et c'est la fonction qui est mise à jour mes paramètres pour standard, 976 01:22:42,510 --> 01:22:45,480 et des moyens TCSA le faire dès maintenant. 977 01:22:45,480 --> 01:22:50,310 Les autres options sont attendre que tout ce qui est actuellement sur le flux est traité. 978 01:22:50,310 --> 01:22:52,030 Cela n'a pas vraiment d'importance. 979 01:22:52,030 --> 01:22:56,920 Juste ce qu'il faut maintenant modifier les paramètres de mon être tout ce qui est actuellement en hacker_typer_settings. 980 01:22:56,920 --> 01:23:02,210 Je suppose que je l'ai appelé hacker_settings, nous allons donc changer cela. 981 01:23:09,610 --> 01:23:13,500 Changer tout pour hacker_settings. 982 01:23:13,500 --> 01:23:16,870 >> Maintenant, à la fin de notre programme, nous allons souhaitez revenir 983 01:23:16,870 --> 01:23:20,210 à ce qui est actuellement à l'intérieur de normal_settings, 984 01:23:20,210 --> 01:23:26,560 qui va juste ressembler et normal_settings. 985 01:23:26,560 --> 01:23:30,650 Remarquez que je n'ai pas changé aucun de mes normal_settings depuis l'origine de l'obtenir. 986 01:23:30,650 --> 01:23:34,520 Ensuite, il suffit de les changer à dos, je les passe en arrière à la fin. 987 01:23:34,520 --> 01:23:38,390 Il s'agissait de la mise à jour. D'accord. 988 01:23:38,390 --> 01:23:43,900 >> Maintenant, à l'intérieur d'ici, je vais vous expliquer le code dans l'intérêt du temps. 989 01:23:43,900 --> 01:23:46,350 Ce n'est pas que beaucoup de code. 990 01:23:50,770 --> 01:24:03,750 Nous voyons que nous lisons un caractère à partir du fichier. Nous l'avons appelé f. 991 01:24:03,750 --> 01:24:07,850 Maintenant, vous pouvez homme fgetc, mais comment fgetc est d'aller travailler 992 01:24:07,850 --> 01:24:11,910 est juste que ça va revenir le personnage que vous venez de lire, ou EOF, 993 01:24:11,910 --> 01:24:15,680 ce qui correspond à la fin du fichier ou d'un événement d'erreur. 994 01:24:15,680 --> 01:24:19,900 Nous sommes en boucle, en continuant à lire un seul caractère dans le fichier, 995 01:24:19,900 --> 01:24:22,420 jusqu'à ce que nous n'avons plus de caractères à lire. 996 01:24:22,420 --> 01:24:26,650 Et tandis que nous le faisons, nous nous attendons à un seul caractère pouces standard 997 01:24:26,650 --> 01:24:29,090 Chaque fois que vous tapez quelque chose dans la ligne de commande, 998 01:24:29,090 --> 01:24:32,820 qui est lu dans un personnage de pouces standard 999 01:24:32,820 --> 01:24:38,330 Puis putchar va juste mettre le char nous lisons ici à partir du fichier de sortie standard. 1000 01:24:38,330 --> 01:24:42,890 Vous pouvez homme putchar, mais il est juste de mettre sur la sortie standard, c'est l'impression de ce caractère. 1001 01:24:42,890 --> 01:24:51,600 Vous pouvez aussi simplement faire printf ("% c", c); même idée. 1002 01:24:53,330 --> 01:24:56,670 Cela va faire le gros de notre travail. 1003 01:24:56,670 --> 01:25:00,300 >> La dernière chose que nous allons avoir à faire est juste fclose notre fichier. 1004 01:25:00,300 --> 01:25:03,310 Si vous n'avez pas fclose, c'est une fuite de mémoire. 1005 01:25:03,310 --> 01:25:06,680 Nous voulons le fichier fclose nous avait ouvert ses portes, et je pense que c'est ça. 1006 01:25:06,680 --> 01:25:13,810 Si nous faisons cela, j'ai déjà eu des problèmes. 1007 01:25:13,810 --> 01:25:17,260 Voyons voir. 1008 01:25:17,260 --> 01:25:19,960 Que s'est-il se plaindre? 1009 01:25:19,960 --> 01:25:30,220 Prévue 'int', mais l'argument est de type 'struct _IO_FILE *'. 1010 01:25:36,850 --> 01:25:39,370 Nous allons voir si cela fonctionne. 1011 01:25:45,210 --> 01:25:53,540 Uniquement autorisé dans C99. Augh. Bon, faire hacker_typer. 1012 01:25:53,540 --> 01:25:57,760 Maintenant nous avons des descriptions plus utiles. 1013 01:25:57,760 --> 01:25:59,900 Il faut donc utiliser l'identificateur non déclaré »normal_settings». 1014 01:25:59,900 --> 01:26:04,170 Je n'ai pas l'appeler normal_settings. Je l'ai appelé current_settings. 1015 01:26:04,170 --> 01:26:12,090 Donc, nous allons changer tout cela. 1016 01:26:17,920 --> 01:26:21,710 Maintenant, passer argument. 1017 01:26:26,290 --> 01:26:29,500 Je vais faire ce 0 pour le moment. 1018 01:26:29,500 --> 01:26:36,720 D'accord. . / Hacker_typer cp.c. 1019 01:26:36,720 --> 01:26:39,590 Mais je n'ai pas l'écran au début. 1020 01:26:39,590 --> 01:26:42,960 Mais vous pouvez regarder en arrière au problème posé dernière pour voir comment vous effacer l'écran. 1021 01:26:42,960 --> 01:26:45,160 C'est juste l'impression de certains caractères 1022 01:26:45,160 --> 01:26:47,210 tout cela est de faire ce que je veux faire. 1023 01:26:47,210 --> 01:26:48,900 D'accord. 1024 01:26:48,900 --> 01:26:55,280 Et penser à pourquoi cela devait être 0 au lieu de stdin, 1025 01:26:55,280 --> 01:27:00,560 qui devrait être # define 0, 1026 01:27:00,560 --> 01:27:03,890 ce qui se plaint - 1027 01:27:13,150 --> 01:27:19,360 Avant, quand je dis qu'il ya descripteurs de fichiers, mais vous avez aussi votre FILE *, 1028 01:27:19,360 --> 01:27:23,210 un descripteur de fichier est juste un seul entier, 1029 01:27:23,210 --> 01:27:26,970 tandis qu'un FILE * a tout un tas de trucs qui lui est associé. 1030 01:27:26,970 --> 01:27:30,380 La raison pour laquelle nous avons besoin de dire 0 au lieu de stdin 1031 01:27:30,380 --> 01:27:37,480 est que stdin est un FILE * qui pointe vers la chose qui fait référence descripteur de fichier 0. 1032 01:27:37,480 --> 01:27:45,070 Ainsi, même ici quand je fais fopen (argv [1], je me fais un FILE * en arrière. 1033 01:27:45,070 --> 01:27:51,180 Mais quelque part dans ce FILE * est une chose qui correspond à un descripteur de fichier pour ce fichier. 1034 01:27:51,180 --> 01:27:57,430 Si vous regardez la page de manuel ouvert, donc je pense que vous aurez à faire l'homme ouvert 3 - nope - 1035 01:27:57,430 --> 01:27:59,380 man 2 ouvert - oui. 1036 01:27:59,380 --> 01:28:06,250 Si vous regardez la page pour ouvrir, ouverte, c'est comme un fopen niveau inférieur, 1037 01:28:06,250 --> 01:28:09,350 et il est de retour le descripteur de fichier réel. 1038 01:28:09,350 --> 01:28:12,050 fopen fait un tas de trucs sur le dessus de normes ouvertes, 1039 01:28:12,050 --> 01:28:17,640 qui, au lieu de retourner tout ce descripteur de fichier renvoie un pointeur sur l'image entière * 1040 01:28:17,640 --> 01:28:20,590 à l'intérieur de laquelle est notre petit descripteur de fichier. 1041 01:28:20,590 --> 01:28:25,020 Donc standard se réfère à la chose FILE *, 1042 01:28:25,020 --> 01:28:29,120 alors que 0 désigne simplement la norme descripteur de fichier en lui-même. 1043 01:28:29,120 --> 01:28:32,160 >> Des questions? 1044 01:28:32,160 --> 01:28:35,930 [Rires] Blew par là. 1045 01:28:35,930 --> 01:28:39,140 Très bien. Nous en avons terminé. [Rires] 1046 01:28:39,140 --> 01:28:42,000 >> [CS50.TV]