1 00:00:00,000 --> 00:00:02,500 [Powered by Google Translate] [Oddíl 5 - Více Comfortable] 2 00:00:02,500 --> 00:00:04,690 [Rob Bowden - Harvard University] 3 00:00:04,690 --> 00:00:07,250 [To je CS50. - CS50.TV] 4 00:00:08,990 --> 00:00:14,250 >> Jak jsem řekl ve svém e-mailu, existuje mnoho věcí, které můžete použít 5 00:00:14,250 --> 00:00:17,060 jiné než zařízení skutečně dělat problémové soubory. 6 00:00:17,060 --> 00:00:19,910 Doporučujeme vám to v přístroji jen proto, že pak můžeme snáze pomůže 7 00:00:19,910 --> 00:00:22,070 a víme, jak to všechno bude fungovat. 8 00:00:22,070 --> 00:00:26,950 Ale jako jeden příklad, kde si můžete dělat věci, pokud, řekněme, nemáte přístup 9 00:00:26,950 --> 00:00:31,570 ke spotřebiči, nebo chcete pracovat v suterénu Science Center - 10 00:00:31,570 --> 00:00:33,090 které vlastně mají přístrojem příliš - 11 00:00:33,090 --> 00:00:35,150 Pokud chcete pracovat kdekoliv. 12 00:00:35,150 --> 00:00:42,370 Jedním z příkladů je viděli jste / slyšel SSH? 13 00:00:44,380 --> 00:00:47,780 SSH je v podstatě stejně jako připojení k něčemu. 14 00:00:47,780 --> 00:00:51,340 Vlastně, teď jsem SSHed do přístroje. 15 00:00:51,340 --> 00:00:54,290 Nikdy jsem pracovat přímo v přístroji. 16 00:00:55,930 --> 00:01:01,060 Zde je spotřebič, a když se podíváte dolů tady vidíte tuto IP adresu. 17 00:01:01,060 --> 00:01:03,650 Nikdy jsem pracovat v zařízení samotném; 18 00:01:03,650 --> 00:01:08,840 Vždycky jsem přijít na iTerm2 okna / terminálovém okně. 19 00:01:08,840 --> 00:01:15,910 Můžete SSH na tuto IP adresu, ssh jharvard@192.168.129.128. 20 00:01:15,910 --> 00:01:20,390 Pamatuji si, že počet velmi snadno, protože je to takový milý vzor. 21 00:01:20,390 --> 00:01:24,920 Ale to bude zeptejte se mě na mé heslo, a teď jsem ve spotřebiči. 22 00:01:24,920 --> 00:01:33,060 V podstatě, v tomto bodě, pokud otevřel terminál uvnitř spotřebiče samotného, 23 00:01:33,060 --> 00:01:36,350 toto rozhraní, ale měli byste použít ji, je přesně stejná 24 00:01:36,350 --> 00:01:40,010 jako rozhraní já používám tady, ale teď jsi SSHed. 25 00:01:42,240 --> 00:01:44,920 Nemusíte se připojit přes SSH na spotřebiče. 26 00:01:44,920 --> 00:01:52,360 Jeden příklad na jiném místě byste mohli SSH na je, že jsem si jistá, že máte ve výchozím nastavení - 27 00:01:52,360 --> 00:01:55,020 Oh. Větší. 28 00:01:55,020 --> 00:02:01,130 Všichni z vás by měl mít podle účtů výchozí FAS na serverech FAS. 29 00:02:01,130 --> 00:02:06,840 Pro mě, já bych SSH rbowden@nice.fas.harvard.edu. 30 00:02:06,840 --> 00:02:11,610 Je tě zeptat, že poprvé, a řeknete ano. 31 00:02:11,610 --> 00:02:15,840 Moje heslo je jen bude můj FAS heslo. 32 00:02:15,840 --> 00:02:22,650 A tak teď, jsem SSHed na pěkné servery, a můžu si dělat, co chci tady. 33 00:02:22,650 --> 00:02:28,560 Mnoho tříd můžete vzít, stejně jako 124, budou mít nahrajete věci sem 34 00:02:28,560 --> 00:02:30,950 skutečně předložit své problémové sady. 35 00:02:30,950 --> 00:02:34,100 Ale říct, že nemáte přístup k vašemu přístroji. 36 00:02:34,100 --> 00:02:37,910 Pak můžete dělat věci, jako je tady to bude říkat - 37 00:02:37,910 --> 00:02:42,160 To je jen naše část otázek. 38 00:02:42,160 --> 00:02:45,070 To se vás zeptá, jak to udělat ve spotřebiči. 39 00:02:45,070 --> 00:02:47,790 Místo toho jsem si jen to na serveru. 40 00:02:47,790 --> 00:02:50,560 Jdu k rozbalení, že. 41 00:02:50,560 --> 00:02:55,670 Problém bude, že jste zvyklí používat něco jako gedit 42 00:02:55,670 --> 00:02:58,160 nebo co uvnitř zařízení. 43 00:02:58,160 --> 00:03:01,830 Nebudete mít, že na FAS serveru. 44 00:03:01,830 --> 00:03:04,110 Je to všechno jenom bude to textové rozhraní. 45 00:03:04,110 --> 00:03:09,180 Takže byste mohli buď jeden, zkuste se naučit textového editoru, který oni mají. 46 00:03:09,180 --> 00:03:12,130 Mají Nano. 47 00:03:12,130 --> 00:03:14,990 Nano je obvykle velmi snadno ovladatelný. 48 00:03:14,990 --> 00:03:19,470 Můžete použít šipky a zadejte normálně. 49 00:03:19,470 --> 00:03:21,250 Takže to není těžké. 50 00:03:21,250 --> 00:03:24,720 Pokud chcete získat opravdu fantazie můžete použít Emacs, 51 00:03:24,720 --> 00:03:29,850 které jsem asi neměl otevřít, protože já ani nevím, jak ukončit Emacs. 52 00:03:29,850 --> 00:03:32,760 Control X, Control C? Jo. 53 00:03:32,760 --> 00:03:35,310 Nebo můžete použít Vim, což je to, co mám použít. 54 00:03:35,310 --> 00:03:37,800 A tak to jsou vaše možnosti. 55 00:03:37,800 --> 00:03:43,830 Pokud nechcete dělat, že můžete také, když se podíváte na manual.cs50.net-- 56 00:03:43,830 --> 00:03:45,410 Oh. 57 00:03:45,410 --> 00:03:49,920 Na počítači, můžete pomocí SSH PuTTY, 58 00:03:49,920 --> 00:03:51,940 které budete muset stáhnout zvlášť. 59 00:03:51,940 --> 00:03:55,460 Na Macu, stačí Terminal výchozí použití, nebo si můžete stáhnout iTerm2, 60 00:03:55,460 --> 00:03:58,490 který je jako pěkné, efektní terminálu. 61 00:03:58,490 --> 00:04:03,780 Pokud půjdete do manual.cs50.net uvidíte odkaz na Notepad + +, 62 00:04:03,780 --> 00:04:07,120 což je to, co můžete použít na počítači. 63 00:04:07,120 --> 00:04:13,340 To vám umožní SFTP z Notepad + +, který je v podstatě SSH. 64 00:04:13,340 --> 00:04:17,750 Co to vám umožní udělat, je upravovat své soubory lokálně, 65 00:04:17,750 --> 00:04:20,670 a pak pokaždé, když chcete uložit, bude to ušetří až nice.fas, 66 00:04:20,670 --> 00:04:23,670 kde pak můžete spustit. 67 00:04:23,670 --> 00:04:26,880 A odpovídá na Mac bude TextWrangler. 68 00:04:26,880 --> 00:04:28,760 Tak to vám umožní udělat to samé. 69 00:04:28,760 --> 00:04:32,800 To vám umožní upravovat soubory lokálně a uložit je do nice.fas, 70 00:04:32,800 --> 00:04:35,730 kde pak můžete spustit. 71 00:04:35,730 --> 00:04:40,400 Takže pokud jste někdy uvízl bez zařízení, máte tyto možnosti 72 00:04:40,400 --> 00:04:44,230 na stále dělat své problémové sady. 73 00:04:44,230 --> 00:04:48,250 Jeden problém bude, že nebudete mít CS50 knihovnu 74 00:04:48,250 --> 00:04:51,580 protože nice.fas nemá ve výchozím nastavení mají, že. 75 00:04:51,580 --> 00:04:55,970 Můžete buď stáhnout CS50 knihovny - 76 00:04:55,970 --> 00:04:58,470 Já si nemyslím, že je třeba, aby v tomto bodě. 77 00:04:58,470 --> 00:05:03,270 Můžete buď stáhnout CS50 knihovnu a zkopírujte jej do nice.fas, 78 00:05:03,270 --> 00:05:07,450 nebo jsem si, že v tomto bodě nemáme používat už tak jako tak. 79 00:05:07,450 --> 00:05:12,720 Nebo pokud ano, můžete v současné době jej nahradit 80 00:05:12,720 --> 00:05:18,480 Implementace těchto funkcí v CS50 knihovně tak jako tak. 81 00:05:18,480 --> 00:05:21,370 Takže by neměl být tak velký omezení. 82 00:05:21,370 --> 00:05:23,710 A to je, že. 83 00:05:26,460 --> 00:05:29,820 >> Vrátím se do spotřebiče nyní, budeme dělat vše, co ve spotřebiči. 84 00:05:29,820 --> 00:05:37,510 Při pohledu na naši sekci otázek, na začátku, jak jsem řekl ve svém e-mailu, 85 00:05:37,510 --> 00:05:43,620 musíme si promluvit o jedné zkratce jste se měli dívat. 86 00:05:43,620 --> 00:05:51,980 Máme přesměrování a trubky a tyto tři otázky. 87 00:05:51,980 --> 00:05:56,070 >> Chcete-li, které proud se funkce jako printf psát ve výchozím nastavení? 88 00:05:56,070 --> 00:05:59,130 Tak stream. Co je proud? 89 00:06:06,520 --> 00:06:15,100 Proud je v podstatě taková, že je to jen nějaký - 90 00:06:15,100 --> 00:06:21,450 Není to ani zdrojem 1s a 0s. 91 00:06:21,450 --> 00:06:24,920 Proud, který se ptá na tu je standardní výstup. 92 00:06:24,920 --> 00:06:27,250 A tak standardní výstup je proud, který při psaní na to, 93 00:06:27,250 --> 00:06:30,940 se objeví na obrazovce. 94 00:06:30,940 --> 00:06:36,860 Standardní, tím, že proud, znamená to, že stačí napsat 1s a 0s k němu, 95 00:06:36,860 --> 00:06:40,220 a druhý konec standardní výstup jen čte z tohoto proudu. 96 00:06:40,220 --> 00:06:43,540 Je to jen řetězec 1s a 0s. 97 00:06:43,540 --> 00:06:45,570 Můžete psát do vodních toků, nebo si můžete přečíst z potoků 98 00:06:45,570 --> 00:06:47,950 v závislosti na tom, co proud vlastně je. 99 00:06:47,950 --> 00:06:52,800 Zbylé dva Výchozí toky jsou standardně a standardní chyby. 100 00:06:52,800 --> 00:06:57,540 Standardní in je vždy, když to GetString, je to na vás čeká na vstup věci. 101 00:06:57,540 --> 00:07:01,570 Tak to vás čeká, je to vlastně čeká na standardu, 102 00:07:01,570 --> 00:07:04,880 což je opravdu to, co dostanete, když zadáte na klávesnici. 103 00:07:04,880 --> 00:07:07,530 Píšete do standardu palců 104 00:07:07,530 --> 00:07:10,050 Standardní chyba je v podstatě ekvivalentní standardní výstup, 105 00:07:10,050 --> 00:07:13,280 ale je to specializované v tom, že při tisku na standardní chybový výstup, 106 00:07:13,280 --> 00:07:16,770 jste měl tisknout pouze chybové zprávy, které 107 00:07:16,770 --> 00:07:20,200 takže můžete rozlišit mezi pravidelnými zprávami tištěných na obrazovku 108 00:07:20,200 --> 00:07:24,560 proti chybových zpráv v závislosti na tom, zda šli do standardní výstup nebo standardní chybou. 109 00:07:24,560 --> 00:07:28,660 Soubory taky. 110 00:07:28,660 --> 00:07:32,440 Standardní výstup, standardní v, a standardní chyba je jen zvláštní proudy, 111 00:07:32,440 --> 00:07:36,810 ale opravdu jakýkoli soubor, při otevření souboru, to se stává proud bajtů 112 00:07:36,810 --> 00:07:40,740 , kde můžete jen číst z tohoto proudu. 113 00:07:40,740 --> 00:07:47,770 Ty, pro nejvíce se rozdělit, může jen myslet souboru jako proud bajtů. 114 00:07:47,770 --> 00:07:51,190 Takže to, co toky se píší ve výchozím nastavení? Standardní výstup. 115 00:07:51,190 --> 00:07:56,980 >> Jaký je rozdíl mezi> a >>? 116 00:07:58,140 --> 00:08:03,710 Copak někdo sledovat video předem? Dobře. 117 00:08:03,710 --> 00:08:10,960 > Se bude, jak přesměrovat do souborů, 118 00:08:10,960 --> 00:08:15,240 a >> bude také přesměrovat výstup do souboru, 119 00:08:15,240 --> 00:08:17,820 ale je to místo bude připojit k souboru. 120 00:08:17,820 --> 00:08:23,430 Například, řekněme, že jsem náhodou dict tady, 121 00:08:23,430 --> 00:08:27,020 a jediný věci uvnitř dict je kočka, kočka, pes, ryba, pes. 122 00:08:27,020 --> 00:08:31,530 Jeden příkaz, který jste v příkazovém řádku je kočka, 123 00:08:31,530 --> 00:08:34,539 který je jen tak vytisknout to, co je v souboru. 124 00:08:34,539 --> 00:08:40,679 Takže když říkám kočka dict, že to bude tisknout kočka, kočka, pes, ryba, pes. To je vše, kočka dělá. 125 00:08:40,679 --> 00:08:46,280 To znamená, že pro tisk na standardní výstup kočka, kočka, pes, ryba, pes. 126 00:08:46,280 --> 00:08:53,240 Kdybych místo toho chcete přesměrovat, že do souboru, mohu použít> a přesměrovat ji na co je soubor. 127 00:08:53,240 --> 00:08:56,460 Zavolám soubor soubor. 128 00:08:56,460 --> 00:09:00,320 Takže teď, když já ls, uvidím Mám nový soubor s názvem souboru. 129 00:09:00,320 --> 00:09:05,700 A když jsem ho otevřete, bude to mít přesně to, co kočky dal na příkazovém řádku. 130 00:09:05,700 --> 00:09:11,040 Takže teď když to udělám znovu, pak to bude přesměrovat výstup do souboru, 131 00:09:11,040 --> 00:09:13,930 a budu mít stejný přesně to. 132 00:09:13,930 --> 00:09:17,910 Takže technicky to zcela nedbala toho, co jsme měli. 133 00:09:17,910 --> 00:09:22,970 A uvidíme, jestli změním dict, jsem vytáhl psa. 134 00:09:22,970 --> 00:09:29,980 Nyní, když jsme se kočka dict do souboru znovu, budeme mít novou verzi s pes odstraněny. 135 00:09:29,980 --> 00:09:32,400 Tak to úplně potlačí jej. 136 00:09:32,400 --> 00:09:36,640 Místo toho, pokud budeme používat >>, bude to připojit soubor. 137 00:09:36,640 --> 00:09:40,860 Nyní, otevírání souboru, vidíme, máme jen samé tištěné dvakrát 138 00:09:40,860 --> 00:09:44,920 protože tam byl jednou, pak jsme připojena k originálu. 139 00:09:44,920 --> 00:09:48,130 Tak to je to, co> a >> dělat. 140 00:09:48,130 --> 00:09:50,580 Má další se zeptat - to není to zeptat. 141 00:09:50,580 --> 00:09:59,050 >> Druhý, který máme, je <, která, pokud> přesměruje standardní výstup, 142 00:09:59,050 --> 00:10:01,970 00:10:12,050 Uvidíme, jestli se máme příklad. 144 00:10:14,750 --> 00:10:16,930 Umím psát jednoho opravdu rychle. 145 00:10:17,870 --> 00:10:25,700 Pojďme se libovolný soubor, hello.c. 146 00:10:56,060 --> 00:10:59,070 Relativně jednoduché souboru. 147 00:10:59,070 --> 00:11:03,570 Já jsem jen na to, řetězec a pak tisk "Hello", co řetězec jsem vstoupil byl. 148 00:11:03,570 --> 00:11:07,990 Takže si ahoj a pak. / Hello. 149 00:11:07,990 --> 00:11:10,720 Teď to výzva, abych zadat něco, 150 00:11:10,720 --> 00:11:15,070 což znamená, že čeká na věci, které mají být zapsány do standardu palců 151 00:11:15,070 --> 00:11:20,450 Takže zadat co chci do standardu dovnitř jsme jen říct Ahoj, Rob! 152 00:11:20,450 --> 00:11:23,310 Pak se tiskne na standardní výstup Hello, Robe! 153 00:11:23,310 --> 00:11:28,860 Pokud to udělám. / Hello a pak přesměrovat, 154 00:11:30,740 --> 00:11:34,310 zatím můžete pouze přesměrovat ze souboru. 155 00:11:34,310 --> 00:11:41,720 Takže když jsem dal v nějakém souboru, txt, a dal jsem Roba, 156 00:11:41,720 --> 00:11:52,300 když spustím ahoj a pak přesměrovat soubor txt do. / hello, to bude říkat Hello, Rob! okamžitě. 157 00:11:52,300 --> 00:11:57,160 Když se poprvé dostane do GetString a to čekání na standardu v, 158 00:11:57,160 --> 00:12:01,730 standard v již čeká na klávesnici dat dostat zadaných. 159 00:12:01,730 --> 00:12:05,980 Místo toho, jsme přesměrováni standardem pro čtení ze souboru txt. 160 00:12:05,980 --> 00:12:10,290 A tak to bude číst ze souboru txt, který je jen čára Rob, 161 00:12:10,290 --> 00:12:13,380 a pak to bude tisknout Hello, Rob! 162 00:12:13,380 --> 00:12:18,180 A kdybych chtěl, mohl bych také udělat. / Hello 00:12:21,500 a pak standardní na to, že je to tisk, který je Ahoj, Robe!, 164 00:12:21,500 --> 00:12:24,700 Mohu přesměrovat, že do vlastního souboru. 165 00:12:24,700 --> 00:12:29,790 Já si jen zavolat na soubor hello - ne, nebudu, protože to je spustitelný - txt2. 166 00:12:29,790 --> 00:12:40,150 Nyní, txt2 bude mít výstup. / Dobrý den, 00:12:43,520 >> Otázky? 168 00:12:45,900 --> 00:12:49,090 >> Dobře. Takže tady máme potrubí. 169 00:12:49,090 --> 00:12:53,510 Trubky jsou poslední jednotka přesměrování. 170 00:12:53,510 --> 00:12:58,750 >> Oh. Myslím, že jeden jednotka přesměrování, je-li místo> ty 2>, 171 00:12:58,750 --> 00:13:01,070 že je přesměrování standardní chyba. 172 00:13:01,070 --> 00:13:06,280 Takže pokud se něco na standardní chybový výstup, dopadlo by to dát do txt2. 173 00:13:06,280 --> 00:13:12,480 Povšimněme si ale, jestli jsem to 2>, pak je to stále tisku Ahoj, Rob! do příkazového řádku 174 00:13:12,480 --> 00:13:18,600 protože jsem jen přesměrování standardní chybu, já nejsem přesměrování normu ven. 175 00:13:18,600 --> 00:13:22,210 Standardní chyba a standardní výstup se liší. 176 00:13:24,210 --> 00:13:27,080 Pokud byste chtěli, aby skutečně psát na standardní chybový výstup, 177 00:13:27,080 --> 00:13:35,080 pak bych mohl změnit to být fprintf na stderr. 178 00:13:35,080 --> 00:13:37,850 Takže printf, ve výchozím nastavení, vytiskne na standardní výstup. 179 00:13:37,850 --> 00:13:41,720 Pokud chci tisknout na standardní chybový výstup ručně, pak musím použít fprintf 180 00:13:41,720 --> 00:13:45,010 a určit, co chci tisknout. 181 00:13:45,010 --> 00:13:49,720 Pokud místo toho jsem fprintf stdout, pak je to v podstatě rovnocenné printf. 182 00:13:49,720 --> 00:13:55,530 Ale fprintf na standardní chybový výstup. 183 00:13:57,790 --> 00:14:03,650 Takže teď, když jsem přesměrovat to na txt2, Hello, Rob! stále dostává vytištěn v příkazovém řádku 184 00:14:03,650 --> 00:14:08,270 protože je dostat vytištěny na standardní chybový výstup, a já jsem jen přesměrování standardní výstup. 185 00:14:08,270 --> 00:14:16,420 Kdybych teď přesměrovat standardní chyba, teď to nedostal tištěný, a txt2 bude Hello, Rob! 186 00:14:16,420 --> 00:14:21,910 Takže teď, můžete tisknout skutečné chyby na standardní chybový výstup 187 00:14:21,910 --> 00:14:24,720 a tisknout pravidelné zprávy na standardní výstup. 188 00:14:24,720 --> 00:14:31,420 A tak při spuštění programu, můžete jej spustit jako. / Hello tento typ s 2> 189 00:14:31,420 --> 00:14:33,800 tak, aby váš program bude běžet normálně, 190 00:14:33,800 --> 00:14:38,400 ale nějaké chybové zprávy, které dostanete, můžete zjistit později v protokolu chyb, 191 00:14:38,400 --> 00:14:44,500 tak chyby, a pak se podívejte později a vaše chyby soubor bude mít nějaké chyby, které se staly. 192 00:14:45,200 --> 00:14:47,540 >> Otázky? 193 00:14:47,540 --> 00:14:58,070 >> Poslední z nich je trubka, která si můžete myslet, jako že se normu z jednoho příkazu 194 00:14:58,070 --> 00:15:01,210 , která je tak standard dalšího příkazu. 195 00:15:01,210 --> 00:15:05,570 Příkladem je echo je příkazový řádek věc 196 00:15:05,570 --> 00:15:11,840 , který je jen tak echo, co jsem dal jako svůj argument. Nebudu dát uvozovky. 197 00:15:11,840 --> 00:15:16,150 Echo bla, bla, bla je jen tak tisknout bla, bla, bla. 198 00:15:16,150 --> 00:15:20,600 Předtím, když jsem řekl, že jsem musel dát Roba do txt souboru 199 00:15:20,600 --> 00:15:28,830 protože mohu jen přesměrovat soubory s příponou TXT, místo, / když jsem echo Rob 200 00:15:28,830 --> 00:15:35,520 a pak potrubí je do. / hello, bude to také udělat stejný typ věci. 201 00:15:35,520 --> 00:15:39,160 To je v současné době výstup tohoto příkazu, echo Rob, 202 00:15:39,160 --> 00:15:43,610 a používat to jako vstup pro. / hello. 203 00:15:44,790 --> 00:15:49,560 Můžete si ji představit jako první přesměrování echo Roba do souboru 204 00:15:49,560 --> 00:15:54,160 a poté zadejte do. / hello tohoto souboru, který byl právě na výstupu. 205 00:15:54,160 --> 00:15:57,850 Ale to má dočasný soubor z obrázku. 206 00:16:01,890 --> 00:16:04,460 >> Otázky týkající se, že? 207 00:16:04,460 --> 00:16:07,150 >> Další otázka se bude týkat tohoto. 208 00:16:07,150 --> 00:16:15,310 Co potrubí můžete použít k vyhledání počet unikátních jmen v souboru s názvem names.txt? 209 00:16:15,310 --> 00:16:24,160 Příkazy budeme chtít použít tady jsou jedinečné, tak uniq, a pak wc. 210 00:16:24,160 --> 00:16:28,840 Můžete to udělat man uniq skutečně podívat na to, co dělá, že, 211 00:16:28,840 --> 00:16:34,840 a to jen tak filtruje sousedící shodné řádky od vstupu. 212 00:16:34,840 --> 00:16:40,690 A člověk wc bude tisknout znak nového řádku, slovo, a počet bajtů pro každý soubor. 213 00:16:40,690 --> 00:16:43,760 A poslední budeme chtít použít je něco, 214 00:16:43,760 --> 00:16:47,410 který se bude jen trochu řádky souboru txt. 215 00:16:47,410 --> 00:16:58,080 Pokud udělám nějaký soubor txt, names.txt, a to Rob, Tommy, Joseph, Tommy, Joseph, RJ, Rob, 216 00:16:58,080 --> 00:17:03,910 to, co chci udělat je zjistit počet unikátních jmen v tomto souboru. 217 00:17:03,910 --> 00:17:08,750 Takže to, co by měla být odpověď? >> [Student] 4. Jo >>. 218 00:17:08,750 --> 00:17:13,780 Mělo by být 4 od Roba, Tommy, Josef, RJ jsou pouze jedinečné názvy v tomto souboru. 219 00:17:13,780 --> 00:17:20,180 Prvním krokem, když jsem prostě počet slov na names.txt, 220 00:17:20,180 --> 00:17:24,290 je to vlastně říká mi všechno. 221 00:17:24,290 --> 00:17:32,560 To je vlastně tisk - Pojďme se podívat, man wc - nové řádky, slova, a byte počet. 222 00:17:32,560 --> 00:17:38,270 Kdybych jen o vedení, pak jsem si jen udělat wc-l names.txt. 223 00:17:41,730 --> 00:17:44,300 Tak to je krok 1. 224 00:17:44,300 --> 00:17:50,510 Ale já nechci, aby wc-l names.txt protože names.txt jen obsahuje všechny názvy, 225 00:17:50,510 --> 00:17:54,170 a chci odfiltrovat žádné non-jedinečné ty. 226 00:17:54,170 --> 00:18:01,200 Takže pokud jsem to Uniq names.txt, že není úplně dej mi to, co chci 227 00:18:01,200 --> 00:18:03,760 protože duplikované názvy jsou stále tam. 228 00:18:03,760 --> 00:18:07,690 Jak to? Proč se uniq není dělat to, co chci? 229 00:18:07,690 --> 00:18:10,500 [Student] duplicity nejsou [neslyšitelné] >> Jo. 230 00:18:10,500 --> 00:18:16,370 Nezapomeňte si man stránku pro Uniq říká filtruje sousedící shodné řádky. 231 00:18:16,370 --> 00:18:19,680 Jsou spolu nesousedí, takže to nebude filtrovat. 232 00:18:19,680 --> 00:18:31,100 Kdybych třídit je první, sort names.txt bude dát všechny duplicitní řádky dohromady. 233 00:18:31,100 --> 00:18:34,450 Takže teď trochu names.txt je. 234 00:18:34,450 --> 00:18:40,550 Budu chtít použít, že jako vstup do uniq, který je | uniq. 235 00:18:40,550 --> 00:18:43,390 To mi dává Josefa, RJ, Rob, Tommy, 236 00:18:43,390 --> 00:18:49,260 a chci jej použít jako vstup do wc-l, 237 00:18:49,260 --> 00:18:52,740 které se bude dát mi 4. 238 00:18:52,740 --> 00:18:56,930 Stejně jako tady se píše, co by mohlo potrubí použít? 239 00:18:56,930 --> 00:19:01,390 Můžete si udělat hodně věcí, jako pomocí série příkazů 240 00:19:01,390 --> 00:19:05,130 kde použít výstup z jednoho příkazu jako vstup do dalšího příkazu. 241 00:19:05,130 --> 00:19:08,780 Můžete si udělat hodně věcí, hodně chytrých věcí. 242 00:19:08,780 --> 00:19:11,440 >> Otázky? 243 00:19:12,910 --> 00:19:14,600 Dobře. 244 00:19:14,600 --> 00:19:17,880 To je to pro potrubí a přesměrování. 245 00:19:18,370 --> 00:19:24,090 >> Teď půjdeme na skutečné věci, kódování stuff. 246 00:19:24,090 --> 00:19:29,100 Uvnitř tohoto PDF, uvidíte tento příkaz, 247 00:19:29,100 --> 00:19:32,950 a budete chtít spustit tento příkaz ve vašem přístroji. 248 00:19:36,240 --> 00:19:42,250 wget je příkaz pro jen dostat něco z internetu, v podstatě, 249 00:19:42,250 --> 00:19:45,180 tak wget a to URL. 250 00:19:45,180 --> 00:19:49,110 Pokud jste šel na tuto adresu URL v prohlížeči, bylo by to stáhnout tento soubor. 251 00:19:49,110 --> 00:19:52,510 Jen jsem kliknul na to, tak to stáhli soubor pro mě. 252 00:19:52,510 --> 00:19:55,650 Ale psaní wget této věci uvnitř terminálu 253 00:19:55,650 --> 00:19:58,620 se právě chystá stáhnout do svého terminálu. 254 00:19:58,620 --> 00:20:02,750 Mám section5.zip, a budete chtít rozbalit section5.zip, 255 00:20:02,750 --> 00:20:06,520 které se bude dát vám složku s názvem section5, 256 00:20:06,520 --> 00:20:11,550 která bude mít všechny soubory se budeme používat dnes uvnitř ní. 257 00:20:33,380 --> 00:20:37,710 Jak souborů tyto programy "názvy napovídají, že jsou trochu buggy, 258 00:20:37,710 --> 00:20:40,990 Takže vaším úkolem je přijít na to, proč používat gdb. 259 00:20:40,990 --> 00:20:44,560 Má všechny nechat stáhnout / vědět, jak se dostat je ke stažení 260 00:20:44,560 --> 00:20:47,480 do jejich zařízení? Dobře. 261 00:20:47,480 --> 00:20:56,400 >> Běh ./buggy1, bude říkat Segmentation fault (core dumpingové), 262 00:20:56,400 --> 00:21:00,500 který pokaždé, když se segfault, je to špatná věc. 263 00:21:00,500 --> 00:21:03,810 Za jakých okolností byste si segfault? 264 00:21:03,810 --> 00:21:08,210 [Student] Nepřímý odkaz nulový ukazatel. Jo >>. Takže to je jeden příklad. 265 00:21:08,210 --> 00:21:11,580 Nepřímý odkaz nulový ukazatel Budeš se dostat segfault. 266 00:21:11,580 --> 00:21:16,720 Co segfault znamená je, že se dotknete paměti byste neměli dotýkat. 267 00:21:16,720 --> 00:21:21,350 Takže dereferencing nulový ukazatel se dotýká adresu 0, 268 00:21:21,350 --> 00:21:28,060 av podstatě všechny počítače v současné době říci, že adresa 0 je paměť, kterou jste neměli dotýkat. 269 00:21:28,060 --> 00:21:31,920 Takže to je důvod, proč dereferencing nulový ukazatel výsledků v segfault. 270 00:21:31,920 --> 00:21:37,210 Pokud se vám stalo, není inicializovat ukazatel, pak to má na odpadky hodnotu, 271 00:21:37,210 --> 00:21:41,520 a tak při pokusu o dereference to, se vší pravděpodobností jste se dotknete paměti 272 00:21:41,520 --> 00:21:43,540 že je uprostřed ničeho. 273 00:21:43,540 --> 00:21:45,650 Pokud se vám stalo, štěstí a odpadky hodnota 274 00:21:45,650 --> 00:21:48,440 stalo poukázat na někde na frontě, nebo tak něco, 275 00:21:48,440 --> 00:21:50,820 pak, když dereference, že ukazatel, který jste nebyl inicializován, 276 00:21:50,820 --> 00:21:52,730 nic pokazit. 277 00:21:52,730 --> 00:21:55,480 Ale pokud je to ukázal na, řekněme, někde mezi zásobníku a haldy, 278 00:21:55,480 --> 00:21:59,850 nebo je to ukazuje jen někde, že nebyl použit ani programu ještě, 279 00:21:59,850 --> 00:22:02,240 pak jste se dotknete paměť, neměli byste se dotýkat a segfault. 280 00:22:02,240 --> 00:22:06,370 Pokud napsat rekurzivní funkci, a to recurses příliš mnohokrát 281 00:22:06,370 --> 00:22:08,720 a váš stack roste příliš velký a zásobník srazí do věcí 282 00:22:08,720 --> 00:22:12,270 že by neměl být kolize s, jste dotýká paměti byste neměli dotýkat, 283 00:22:12,270 --> 00:22:14,810 takže segfault. 284 00:22:14,810 --> 00:22:17,010 To je to, co segfault je. 285 00:22:17,010 --> 00:22:21,810 >> Je to také ze stejného důvodu, že pokud máte řetězec ve tvaru - 286 00:22:21,810 --> 00:22:23,930 Pojďme se vrátit k předchozímu programu. 287 00:22:23,930 --> 00:22:28,530 Ve hello.c--já jen tak, aby se něco jiného. 288 00:22:28,530 --> 00:22:33,770 char * s = "hello world!"; 289 00:22:33,770 --> 00:22:42,310 Mám-li použít * s = něco nebo s [0] = 'X'; 290 00:22:42,310 --> 00:22:47,290 tak, aby ahoj,. / hello, proč se to segfault? 291 00:22:48,410 --> 00:22:51,250 Proč se to segfault? 292 00:22:55,660 --> 00:22:57,890 Co byste očekávat, že se stane? 293 00:22:57,890 --> 00:23:06,640 Pokud jsem printf ("% s \ n", s); co byste očekávat, že bude tisknout? 294 00:23:06,640 --> 00:23:09,930 [Student] X ahoj. Jo >>. 295 00:23:09,930 --> 00:23:15,140 Problém je, že při deklarování řetězec, jako je tento, 296 00:23:15,140 --> 00:23:18,190 s je ukazatel, který půjde na stack, 297 00:23:18,190 --> 00:23:25,880 a co s ukazuje na to je řetězec, který je obsažen v nepřepisovatelné paměti. 298 00:23:25,880 --> 00:23:30,560 Takže jen podle jména, jen pro čtení paměti, měli byste mít představu 299 00:23:30,560 --> 00:23:33,010 , že pokud se pokusíte změnit to, co je v read-only paměti, 300 00:23:33,010 --> 00:23:36,670 děláte něco, co by neměl dělat s pamětí a segfault. 301 00:23:36,670 --> 00:23:45,360 To je vlastně velký rozdíl mezi char * s a char s []. 302 00:23:45,360 --> 00:23:48,790 Takže char s [], nyní tento řetězec se bude kladen na zásobníku, 303 00:23:48,790 --> 00:23:53,960 a zásobník je jen pro čtení, což znamená, že by to mělo fungovat naprosto v pořádku. 304 00:23:55,500 --> 00:23:57,370 A to dělá. 305 00:23:57,370 --> 00:24:06,250 Pamatujte si, že když jsem si char * s = "hello world!", S sám je na zásobníku 306 00:24:06,250 --> 00:24:10,390 ale s body někam jinam, a že někde jinde se stane, že jen pro čtení. 307 00:24:10,390 --> 00:24:15,640 Ale char s [] je prostě něco, na zásobníku. 308 00:24:17,560 --> 00:24:21,760 Takže to je další příklad segfault děje. 309 00:24:21,760 --> 00:24:27,820 >> Viděli jsme, že ./buggy1 vyústila v segfault. 310 00:24:27,820 --> 00:24:31,810 Teoreticky, neměli byste se podívat na buggy1.c okamžitě. 311 00:24:31,810 --> 00:24:35,170 Místo toho se podíváme na to přes gdb. 312 00:24:35,170 --> 00:24:37,750 Všimněte si, že když se dostanete Segmentation fault (core dumpingové), 313 00:24:37,750 --> 00:24:40,850 si stáhni soubor sem volal jádro. 314 00:24:40,850 --> 00:24:45,200 Pokud bychom ls-l, uvidíme, že jádro je obvykle docela velký soubor. 315 00:24:45,200 --> 00:24:51,580 To je počet bajtů v souboru, takže to vypadá, že je to 250-něco kilobajtů. 316 00:24:51,580 --> 00:24:56,120 Důvodem je, že to, co core dump je ve skutečnosti 317 00:24:56,120 --> 00:25:01,410 je, když váš program havaruje, stav paměti programu 318 00:25:01,410 --> 00:25:05,230 jen dostane zkopírovat a vložit do tohoto souboru. 319 00:25:05,230 --> 00:25:07,270 To dostane vyhozen do tohoto souboru. 320 00:25:07,270 --> 00:25:13,060 Tento program, zatímco byl spuštěn, se stalo mít využití paměti asi 250 kb, 321 00:25:13,060 --> 00:25:17,040 a tak to je to, co dostal kopačky do tohoto souboru. 322 00:25:17,040 --> 00:25:23,630 Nyní se můžete podívat na tomto souboru, pokud budeme dělat gdb buggy1 jádro. 323 00:25:23,630 --> 00:25:30,130 Můžeme prostě gdb buggy1, a že bude jen spuštění gdb pravidelně, 324 00:25:30,130 --> 00:25:33,800 pomocí buggy1 jako jeho vstupní soubor. 325 00:25:33,800 --> 00:25:38,260 Ale pokud si gdb buggy1 jádro, pak je to konkrétně jde nastartovat gdb 326 00:25:38,260 --> 00:25:40,330 při pohledu na tento základní soubor. 327 00:25:40,330 --> 00:25:45,560 A říkáte buggy1 znamená gdb ví, že jádro souboru pochází z buggy1 programu. 328 00:25:45,560 --> 00:25:49,580 Takže gdb buggy1 jádro bude okamžitě přinést nám 329 00:25:49,580 --> 00:25:52,060 kde program stalo ukončit. 330 00:25:57,720 --> 00:26:02,340 Vidíme zde Program ukončen signálem 11, Segmentation fault. 331 00:26:02,340 --> 00:26:10,110 Jsme se ocitli na řadu shromáždění, které pravděpodobně není příliš užitečné. 332 00:26:10,110 --> 00:26:15,360 Ale pokud zadáte BT nebo backtrace, že to bude funkce 333 00:26:15,360 --> 00:26:19,430 který nám dává seznam našich aktuálních zásobníku snímků. 334 00:26:19,430 --> 00:26:23,150 Tak backtrace. Vypadá to, že máme jen dvě stack rámy. 335 00:26:23,150 --> 00:26:26,310 První z nich je naše hlavní rámec fronty, 336 00:26:26,310 --> 00:26:29,810 a druhý je zásobník rám pro tuto funkci, která se stane, že je v, 337 00:26:29,810 --> 00:26:34,440 který vypadá jako máme pouze montážní kód. 338 00:26:34,440 --> 00:26:38,050 Tak pojďme zpět do naší hlavní funkce, 339 00:26:38,050 --> 00:26:42,300 a to, že můžeme udělat rámeček 1, a myslím, že můžeme také udělat dolů, 340 00:26:42,300 --> 00:26:45,160 ale skoro nikdy to dolů - nebo nahoru. Jo. 341 00:26:45,160 --> 00:26:50,710 Nahoru a dolů. Až vám přináší jednu zásobníku snímek, dolů se dostanete dolů zásobníku rám. 342 00:26:50,710 --> 00:26:53,240 Mám ve zvyku nikdy použít. 343 00:26:53,240 --> 00:26:59,120 Jen jsem konkrétně říct, rám 1, která je jít do rámu s označením 1. 344 00:26:59,120 --> 00:27:01,750 Rám 1 bude nás zavede do hlavního zásobníku rámu, 345 00:27:01,750 --> 00:27:05,570 a říká, že tady na řádek kódu jsme náhodou být. 346 00:27:05,570 --> 00:27:07,950 Pokud bychom chtěli ještě pár řádků kódu, můžeme říci seznamu, 347 00:27:07,950 --> 00:27:11,280 a že se to nám všem řádky kódu kolem něj. 348 00:27:11,280 --> 00:27:13,360 Linka jsme segfaulted na to 6: 349 00:27:13,360 --> 00:27:17,360 if (strcmp ("CS50 skály", argv [1]) == 0). 350 00:27:17,360 --> 00:27:24,130 Pokud to není zřejmé ještě, můžete si jej rovnou odtud jen tím, že myslí, proč je segfaulted. 351 00:27:24,130 --> 00:27:28,800 Ale můžeme si to ještě o krok dále a říci, "Proč by argv [1] segfault?" 352 00:27:28,800 --> 00:27:38,830 Pojďme tisk argv [1], a vypadá to, že je to 0x0, který je nulový ukazatel. 353 00:27:38,830 --> 00:27:44,750 Jsme strcmping CS50 skály a NULL, a tak že to bude segfault. 354 00:27:44,750 --> 00:27:48,280 A proč je argv [1] null? 355 00:27:48,640 --> 00:27:51,280 [Student] Protože jsme neměli dát žádné argumenty příkazového řádku. 356 00:27:51,280 --> 00:27:53,390 Jo. Nechtěli jsme dát žádné argumenty příkazového řádku. 357 00:27:53,390 --> 00:27:58,460 Takže ./buggy1 pouze bude mít argv [0] bude ./buggy1. 358 00:27:58,460 --> 00:28:02,100 Nebude to mít argv [1], tak, že to bude segfault. 359 00:28:02,100 --> 00:28:07,450 Ale pokud, místo toho jsem dělat jen CS50, že to bude říkat Získáte D 360 00:28:07,450 --> 00:28:09,950 protože to je to, co má udělat. 361 00:28:09,950 --> 00:28:15,240 Při pohledu na buggy1.c, to má tisknout "Dostanete D" - 362 00:28:15,240 --> 00:28:20,820 Pokud argv [1] není "CS50 skály", "Dostanete D", jinak "Zde získáte!" 363 00:28:20,820 --> 00:28:25,660 Takže pokud chceme, musíme to porovnat jako pravdivé, 364 00:28:25,660 --> 00:28:28,710 , což znamená, že je v porovnání s 0. 365 00:28:28,710 --> 00:28:31,100 Takže argv [1] musí být "CS50 skály". 366 00:28:31,100 --> 00:28:35,660 Pokud chcete udělat, že na příkazovém řádku, budete muset použít \ uniknout prostor. 367 00:28:35,660 --> 00:28:41,690 Takže CS50 \ skály a dostanete A! 368 00:28:41,690 --> 00:28:44,060 Pokud nechcete dělat zpětné lomítko, proč to nefunguje? 369 00:28:44,060 --> 00:28:47,190 [Student] Je to dva různé argumenty. Jo >>. 370 00:28:47,190 --> 00:28:52,540 Argv [1] bude CS50, a argv [2] bude skály. Dobře. 371 00:28:52,540 --> 00:28:56,470 >> Nyní ./buggy2 bude segfault znovu. 372 00:28:56,470 --> 00:29:01,880 Místo otevření se své hlavní souboru, budeme jen otevřít buggy2 přímo, 373 00:29:01,880 --> 00:29:05,000 tak gdb buggy2. 374 00:29:05,000 --> 00:29:09,590 Nyní, když jsme jen spustit náš program, pak to bude říkat Program přijímaného signálu SIGSEGV, 375 00:29:09,590 --> 00:29:15,530 který je segfault signál, a to je místo, kde se stalo stalo. 376 00:29:15,530 --> 00:29:21,250 Při pohledu na naše backtrace, vidíme, že jsme byli ve funkci oh_no, 377 00:29:21,250 --> 00:29:23,900 který byl povolán funkce Dinky, který byl nazýván pomocí funkce Binkym, 378 00:29:23,900 --> 00:29:26,460 který byl povolán hlavní. 379 00:29:26,460 --> 00:29:31,680 Můžeme také vidět argumenty těchto funkcí. 380 00:29:31,680 --> 00:29:34,680 Argument bezvýznamné a Binky byla 1. 381 00:29:34,680 --> 00:29:44,390 Pokud bychom seznamu funkci oh_no, vidíme, že oh_no je jen to, char ** S = NULL; 382 00:29:44,390 --> 00:29:47,410 * S = "BOOM"; 383 00:29:47,410 --> 00:29:50,330 Proč by to selhání? 384 00:29:54,330 --> 00:29:58,380 [Student] Nemůžete dereference null ukazatel? Jo >>. 385 00:29:58,380 --> 00:30:06,090 To je jen říká s je NULL, bez ohledu na to, pokud se to stane, že je char **, 386 00:30:06,090 --> 00:30:12,070 které, v závislosti na tom, jak interpretovat to, mohlo by to být ukazatel na ukazatel na řetězec 387 00:30:12,070 --> 00:30:15,550 nebo pole řetězců. 388 00:30:15,550 --> 00:30:21,430 Je to s je NULL, takže * s je dereferencing nulový ukazatel, 389 00:30:21,430 --> 00:30:24,800 a tak to bude pád. 390 00:30:24,800 --> 00:30:27,540 To je jeden z nejrychlejších způsobů, jak můžete případně segfault. 391 00:30:27,540 --> 00:30:31,300 Je to prostě prohlašuje, že nulový ukazatel a okamžitě segfaulting. 392 00:30:31,300 --> 00:30:34,570 To je to, co oh_no dělá. 393 00:30:34,570 --> 00:30:43,400 Pokud půjdeme do jednoho snímku, pak budeme dostat do funkce, která je volána oh_no. 394 00:30:43,400 --> 00:30:44,830 Musím to udělat, aby se. 395 00:30:44,830 --> 00:30:48,610 Pokud nezadáte příkaz a vy jednoduše stisknout Enter znovu, 396 00:30:48,610 --> 00:30:52,350 to bude jen opakovat předchozí příkaz, který jste spustili. 397 00:30:52,350 --> 00:30:56,610 Jsme v rámu 1. 398 00:30:56,610 --> 00:31:04,650 Výpis tohoto rámu, zde vidíme, je naše funkce. 399 00:31:04,650 --> 00:31:08,520 Můžete hit seznam znovu, nebo si můžete udělat seznam 20 a bude obsahovat více. 400 00:31:08,520 --> 00:31:13,640 Funkce dinky říká, že pokud je i 1, pak přejděte na funkci oh_no, 401 00:31:13,640 --> 00:31:15,960 jiný jít do slinky funkci. 402 00:31:15,960 --> 00:31:18,700 A my víme, i je 1, protože jsme se ocitli na tady 403 00:31:18,700 --> 00:31:22,560 že dinky byla volána s argumentem 1. 404 00:31:22,560 --> 00:31:27,560 Nebo můžete prostě vytisknout i, a to bude říkat i je 1. 405 00:31:27,560 --> 00:31:33,770 Jsme v současné době v Dinky, a jdeme-li do dalšího snímku, víme, že skončíš v Binkym. 406 00:31:33,770 --> 00:31:36,600 Up. Nyní jsme v Binkym. 407 00:31:36,600 --> 00:31:41,340 Výpis tuto funkci - seznam z před půl mě přerušil - 408 00:31:41,340 --> 00:31:52,670 Začalo to jako když jsem je 0, pak budeme říkat, že oh_no, jinak volejte hezoučký. 409 00:31:52,670 --> 00:31:57,000 Víme, že jsem byl 1, tak to je voláno hezoučký. 410 00:31:57,000 --> 00:32:05,030 A teď jsme zpátky v hlavním, a hlavní je jen bude int i = rand ()% 3; 411 00:32:05,030 --> 00:32:08,790 To je jen tak, aby vám náhodné číslo, které je buď 0, 1, nebo 2. 412 00:32:08,790 --> 00:32:12,780 Bude to říkat Binky s tímto číslem, a to vrátí 0. 413 00:32:12,780 --> 00:32:16,700 Při pohledu na to, 414 00:32:16,700 --> 00:32:19,880 jen procházky programu ručně bez spuštění okamžitě, 415 00:32:19,880 --> 00:32:25,400 byste nastavit bod zlomu na hlavní, což znamená, že když jsme se spustit program 416 00:32:25,400 --> 00:32:31,020 váš program běží až dokud nenarazí na bod přerušení. 417 00:32:31,020 --> 00:32:35,450 Takže spuštění programu, bude to běžet a pak to bude hit hlavní funkce a zastavit běh. 418 00:32:35,450 --> 00:32:44,700 Teď jsme uvnitř hlavní, a krok, nebo vedle se chystá přivést nás na další řádek kódu. 419 00:32:44,700 --> 00:32:47,050 Můžete to udělat krok nebo další. 420 00:32:47,050 --> 00:32:51,800 Bít další, teď jsem byl nastaven na rand ()% 3, a tak můžeme vytisknout hodnotu i, 421 00:32:51,800 --> 00:32:55,280 a to bude říkat i je 1. 422 00:32:55,280 --> 00:32:58,110 Teď to záleží, zda budeme používat následující nebo krok. 423 00:32:58,110 --> 00:33:01,000 Myslím, že by na tom záleželo v předchozím, ale budeme chtít použít další. 424 00:33:01,000 --> 00:33:06,000 Pokud budeme používat krok, jsme krok do funkce, což znamená, že podívat se na skutečné věci 425 00:33:06,000 --> 00:33:07,940 , co se děje uvnitř Binkym. 426 00:33:07,940 --> 00:33:10,510 Pokud budeme používat dál, pak to znamená jít přes funkci 427 00:33:10,510 --> 00:33:14,070 a prostě jít na další řádek kódu v naší hlavní funkce. 428 00:33:14,070 --> 00:33:17,900 Právě zde na této trati, byl jsem na místo, kde se říká rand ()% 3; 429 00:33:17,900 --> 00:33:21,320 kdybych to udělal krok, bylo by to jít do provádění rand 430 00:33:21,320 --> 00:33:25,110 a podívat se na to, co se tam děje, a já jsem mohl šlápnout pomocí funkce rand. 431 00:33:25,110 --> 00:33:26,920 Ale já se nestarám o funkci rand. 432 00:33:26,920 --> 00:33:30,190 Já jen chci jít na další řádek kódu v hlavní, tak jsem použít další. 433 00:33:30,190 --> 00:33:35,800 Ale teď jsem to stará o Binky funkci, takže chci, aby krok do toho. 434 00:33:35,800 --> 00:33:37,730 Teď jsem v Binkym. 435 00:33:37,730 --> 00:33:42,040 První řádek kódu je říct if (i == 0), jsem o krok, 436 00:33:42,040 --> 00:33:44,930 vidíme, skončí na Dinky. 437 00:33:44,930 --> 00:33:51,620 Pokud jsme seznam věcí, vidíme, že četl je i = 0. 438 00:33:51,620 --> 00:33:55,470 i není rovno 0, tak to šlo do jiného stavu, 439 00:33:55,470 --> 00:33:59,540 která se bude volat Dinky (i). 440 00:33:59,540 --> 00:34:04,030 Můžete se zmást. 441 00:34:04,030 --> 00:34:07,380 Pokud stačí se podívat na těchto tratích přímo, možná si myslíte, že if (i == 0), 442 00:34:07,380 --> 00:34:10,800 v pořádku, pak jsem udělal krok, a teď jsem na Dinky (i), 443 00:34:10,800 --> 00:34:14,120 si může myslet, že musí znamenat i = 0, nebo tak něco. 444 00:34:14,120 --> 00:34:18,980 Ne Jde o to, že ví, že může přilepit přímo na řádek Dinky (i). 445 00:34:18,980 --> 00:34:23,300 Vzhledem k tomu, i není 0, je dalším krokem nebude končit na ostatnímu. 446 00:34:23,300 --> 00:34:26,239 Else není položka, že to bude zastavit na. 447 00:34:26,239 --> 00:34:31,570 Je to prostě jít na další řádek může skutečně spustit, což je hezoučký (i). 448 00:34:31,570 --> 00:34:36,090 Vstup do Dinky (i), uvidíme, jestli (i == 1). 449 00:34:36,090 --> 00:34:42,670 Víme, i = 1, takže když jsme krok, víme, že skončíme v oh_no 450 00:34:42,670 --> 00:34:46,489 protože i = 1 volá funkci oh_no, které můžete vstoupit do, 451 00:34:46,489 --> 00:34:52,969 který se bude nastavení char ** s = NULL a okamžitě "BOOM". 452 00:34:54,270 --> 00:34:59,690 A pak vlastně se dívat na provádění buggy2, 453 00:34:59,690 --> 00:35:04,590 to, i se jen na to, náhodné číslo - 0, 1, nebo 2 - volání Binky, 454 00:35:04,590 --> 00:35:10,610 která pokud je i 0 volá oh_no, jinde to volá hezoučký, který přijde sem. 455 00:35:10,610 --> 00:35:18,100 Pokud i je 1, výzva oh_no, jinak volejte Slinky, který přijde sem, 456 00:35:18,100 --> 00:35:20,460 pokud je i 2, volejte oh_no. 457 00:35:20,460 --> 00:35:24,720 Nevím ani, že existuje způsob, jak - 458 00:35:24,720 --> 00:35:30,030 Má někdo vidí způsob, jak dělat to program, který nebude segfault? 459 00:35:30,030 --> 00:35:37,530 Protože pokud jsem něco chybí, pokud je i 0, budete okamžitě segfault, 460 00:35:37,530 --> 00:35:41,250 jinak jdete do funkce, která, pokud i je 1 jste segfault, 461 00:35:41,250 --> 00:35:44,540 jinak jdete do funkce, pokud je i 2 si segfault. 462 00:35:44,540 --> 00:35:46,810 Takže bez ohledu na to, co děláte, budete segfault. 463 00:35:46,810 --> 00:35:52,380 >> Myslím, že jeden způsob, jak se stanoví, že by místo toho dělal char ** S = NULL, 464 00:35:52,380 --> 00:35:55,610 můžete malloc prostor pro tento řetězec. 465 00:35:55,610 --> 00:36:04,230 Mohli bychom udělat malloc (sizeof) - sizeof co? 466 00:36:09,910 --> 00:36:15,190 [Student] (char) * 5? >> Znamená to nezdá správné? 467 00:36:15,190 --> 00:36:21,060 Já jsem za předpokladu, že to bude fungovat, pokud jsem vlastně běžel, ale to není to, co jsem hledal. 468 00:36:24,400 --> 00:36:32,940 Podívejte se na typ s. Dodejme, int *, takže int * x. 469 00:36:32,940 --> 00:36:35,600 Já bych to malloc (sizeof (int)). 470 00:36:35,600 --> 00:36:40,490 Nebo když jsem chtěl pole 5, by se mi nelíbí (sizeof (int) * 5); 471 00:36:40,490 --> 00:36:44,210 Co když mám int **? 472 00:36:46,260 --> 00:36:49,140 Co bych malloc? 473 00:36:49,140 --> 00:36:53,510 [Student] Velikost ukazatele. Jo >>. (Sizeof (int *)); 474 00:36:53,510 --> 00:36:56,960 Stejná věc se tady. 475 00:36:56,960 --> 00:37:01,280 Chci (sizeof (char *)); 476 00:37:06,170 --> 00:37:12,840 To bude přidělit prostor pro ukazatel, který ukazuje na "boom". 477 00:37:12,840 --> 00:37:15,330 Nepotřebuji přidělit místo pro "BOOM" sám 478 00:37:15,330 --> 00:37:17,210 protože to je v podstatě ekvivalentní tomu, co jsem řekl předtím 479 00:37:17,210 --> 00:37:20,870 char * x = "BOOM". 480 00:37:20,870 --> 00:37:27,950 "BOOM" již existuje. Stává se, že existují v read-only oblasti paměti. 481 00:37:27,950 --> 00:37:35,200 Ale to již existuje, což znamená, že tento řádek kódu, jestliže S je char **, 482 00:37:35,200 --> 00:37:43,900 pak * s je char * a vy nastavení tohoto char * poukázat na "BOOM". 483 00:37:43,900 --> 00:37:50,040 Pokud bych chtěl kopírovat "boom" do s, pak budu muset přidělit prostor pro s. 484 00:37:55,170 --> 00:38:03,900 Udělám * s = malloc (sizeof (char) * 5); 485 00:38:03,900 --> 00:38:06,210 Proč 5? 486 00:38:06,210 --> 00:38:10,860 Proč ne 4? Vypadá to, že "boom" je 4 znaky. >> [Student] null znak. 487 00:38:10,860 --> 00:38:14,580 Jo. Všechny vaše řetězců budou potřebovat null charakter. 488 00:38:14,580 --> 00:38:23,590 Teď můžu udělat něco jako strcat - Jaká je funkce pro kopírování řetězce? 489 00:38:23,590 --> 00:38:28,520 [Student] cpy? >> Strcpy. 490 00:38:28,520 --> 00:38:32,700 muž strcpy. 491 00:38:36,120 --> 00:38:39,590 Takže strcpy nebo strncpy. 492 00:38:39,590 --> 00:38:43,410 strncpy je trochu bezpečnější, protože můžete přesně specifikovat, kolik znaků, 493 00:38:43,410 --> 00:38:46,190 ale tady to nevadí, protože víme. 494 00:38:46,190 --> 00:38:50,340 Takže strcpy a podívat se do argumentů. 495 00:38:50,340 --> 00:38:53,100 První argument je náš cíl. 496 00:38:53,100 --> 00:38:56,770 Druhý argument je naším zdrojem. 497 00:38:56,770 --> 00:39:10,310 Budeme kopírovat do našeho cílového * S ukazatel "BOOM". 498 00:39:10,310 --> 00:39:19,820 Proč by si to chcete udělat s strcpy místo právě to, co jsme měli předtím 499 00:39:19,820 --> 00:39:22,800 z * s = "BOOM"? 500 00:39:22,800 --> 00:39:28,630 K dispozici je důvod, proč budete chtít udělat, ale co je to důvod? 501 00:39:28,630 --> 00:39:31,940 [Student] Chcete-li něco změnit v "BOOM". Jo >>. 502 00:39:31,940 --> 00:39:37,950 Teď můžu udělat něco jako s [0] = 'X'; 503 00:39:37,950 --> 00:39:48,190 protože s body do haldy a že prostor na haldě, která je ukazuje na 504 00:39:48,190 --> 00:39:52,320 je ukazatel na další místa na haldě, která je ukládání "boom". 505 00:39:52,320 --> 00:39:55,150 Takže to kopie "boom" je uložen v haldě. 506 00:39:55,150 --> 00:39:58,780 Tam jsou technicky dvě kopie "boom" v našem programu. 507 00:39:58,780 --> 00:40:03,500 Tam je první, který se právě dán touto "boom" řetězcová konstanta, 508 00:40:03,500 --> 00:40:09,250 a druhou kopii "boom", strcpy vytvořil kopii "boom". 509 00:40:09,250 --> 00:40:13,100 Ale kopie "boom" je uložen na haldě, a haldy máte možnost změnit. 510 00:40:13,100 --> 00:40:17,250 Halda je jen pro čtení, tak to znamená, že s [0] 511 00:40:17,250 --> 00:40:20,500 se chystá nechat změnit hodnotu "boom". 512 00:40:20,500 --> 00:40:23,130 Bude to vám umožní změnit tyto znaky. 513 00:40:23,130 --> 00:40:26,640 >> Otázky? 514 00:40:27,740 --> 00:40:29,290 Dobře. 515 00:40:29,290 --> 00:40:35,500 >> Přesun na buggy3, pojďme gdb buggy3. 516 00:40:35,500 --> 00:40:39,840 Jsme jen spustit a vidíme, se segfault. 517 00:40:39,840 --> 00:40:46,550 Pokud bychom backtrace, tam jsou jen dvě funkce. 518 00:40:46,550 --> 00:40:52,970 Pokud bychom šli do naší hlavní funkce, vidíme, že segfaulted na tomto řádku. 519 00:40:52,970 --> 00:41:00,180 Takže jen při pohledu na tento řádek, for (int řádek = 0; fgets tohle není rovný NULL; 520 00:41:00,180 --> 00:41:03,770 linka + +). 521 00:41:03,770 --> 00:41:08,010 Naše předchozí snímek byl nazýván _IO_fgets. 522 00:41:08,010 --> 00:41:10,720 Uvidíte, že šarže vestavěných funkcí C, 523 00:41:10,720 --> 00:41:15,350 že když se dostanete segfault, bude opravdu záhadné názvy funkcí 524 00:41:15,350 --> 00:41:18,090 podobné _IO_fgets. 525 00:41:18,090 --> 00:41:21,770 Ale že se to souvisí s tímto fgets výzvy. 526 00:41:21,770 --> 00:41:25,850 Někde sem dovnitř, jsme segfaulting. 527 00:41:25,850 --> 00:41:30,340 Podíváme-li se na argumenty fgets, můžeme tisknout vyrovnávací paměti. 528 00:41:30,340 --> 00:41:41,180 Pojďme vytisknout jako - Oh, ne. 529 00:41:48,980 --> 00:41:51,900 Tisk nebude fungovat přesně tak, jak chci, aby to. 530 00:41:55,460 --> 00:41:58,000 Pojďme se podívat na aktuální program. 531 00:42:02,200 --> 00:42:09,640 Buffer je pole znaků. Je to postava pole 128 znaků. 532 00:42:09,640 --> 00:42:14,980 Takže když říkám tisk buffer, že to bude tisknout ty 128 znaků, 533 00:42:14,980 --> 00:42:18,300 která Myslím, že je to, co se očekává. 534 00:42:18,300 --> 00:42:21,390 Co jsem hledal, je vytisknout adresu vyrovnávací paměti, 535 00:42:21,390 --> 00:42:23,680 ale to není opravdu mi hodně. 536 00:42:23,680 --> 00:42:30,770 Takže když jsem se náhodou říct, tady x buffer, ukazuje mi 0xbffff090, 537 00:42:30,770 --> 00:42:38,690 které, pokud si pamatujete z dříve nebo nějakého bodu, Oxbffff inklinuje být stack-ish region. 538 00:42:38,690 --> 00:42:46,020 Zásobník má tendenci začít někde těsně pod 0xc000. 539 00:42:46,020 --> 00:42:51,890 Jen tím, že vidí tuto adresu, já vím, že vyrovnávací paměti se děje na zásobníku. 540 00:42:51,890 --> 00:43:04,500 Restartování můj program, spusťte, up, mírnění jsme viděli, bylo tuto posloupnost znaků 541 00:43:04,500 --> 00:43:06,530 které jsou do značné míry smysl. 542 00:43:06,530 --> 00:43:12,270 Pak tisk souboru, co to soubor vypadá? 543 00:43:15,120 --> 00:43:17,310 [Student] Null. Jo >>. 544 00:43:17,310 --> 00:43:22,610 Soubor je z * typ souboru, takže je to ukazatel, 545 00:43:22,610 --> 00:43:26,610 a hodnota tohoto ukazatele je nulový. 546 00:43:26,610 --> 00:43:33,240 Takže fgets se pokusí číst z tohoto ukazatele v nepřímým způsobem, 547 00:43:33,240 --> 00:43:37,320 ale aby se přístup k tomuto ukazatel, že má k dereference to. 548 00:43:37,320 --> 00:43:40,550 Nebo, aby se přístup, co by mělo být směřující, to dereferences IT. 549 00:43:40,550 --> 00:43:43,810 Takže to dereferencing nulový ukazatel, a to segfault chyb. 550 00:43:46,600 --> 00:43:48,730 Mohl jsem znovu ho tam. 551 00:43:48,730 --> 00:43:52,170 Jestliže zrušíme v našem hlavním bodě a spustit, 552 00:43:52,170 --> 00:43:57,320 první řádek kódu je char * filename = "nonexistent.txt"; 553 00:43:57,320 --> 00:44:00,870 To by mělo docela velký náznak toho, proč tento program selže. 554 00:44:00,870 --> 00:44:06,080 Psaní vedle mě přivádí na další řádek, kde jsem otevřít tento soubor, 555 00:44:06,080 --> 00:44:11,140 a pak jsem okamžitě dostat do naší linie, kde kdysi jsem zasáhla další, bude to segfault. 556 00:44:11,140 --> 00:44:16,880 Má někdo chtěl vyhodit důvod, proč bychom mohli být segfaulting? 557 00:44:16,880 --> 00:44:19,130 [Student] Soubor neexistuje. Jo >>. 558 00:44:19,130 --> 00:44:22,250 To má být náznak 559 00:44:22,250 --> 00:44:29,570 že pokud jste otevření souboru je nutné zkontrolovat, zda soubor skutečně existuje. 560 00:44:29,570 --> 00:44:31,510 Tak tady, "nonexistent.txt"; 561 00:44:31,510 --> 00:44:34,700 Když jsme fopen souboru pro čtení, pak jsme třeba říkat 562 00:44:34,700 --> 00:44:45,870 if (soubor == NULL) a říkat printf ("Soubor neexistuje!" 563 00:44:45,870 --> 00:44:56,340 nebo - ještě lépe - filename); return 1; 564 00:44:56,340 --> 00:45:00,300 Takže teď jsme zkontrolovat, jestli je to NULL 565 00:45:00,300 --> 00:45:03,930 než ve skutečnosti pokračování a snaží se číst z tohoto souboru. 566 00:45:03,930 --> 00:45:08,800 Můžeme předělat to prostě vidět, že to funguje. 567 00:45:11,020 --> 00:45:14,970 Měl jsem v úmyslu zahrnout nový řádek. 568 00:45:21,090 --> 00:45:25,290 Takže teď nonexistent.txt neexistuje. 569 00:45:26,890 --> 00:45:30,040 Vždy byste měli zkontrolovat pro tento druh věci. 570 00:45:30,040 --> 00:45:33,870 Vždy byste měli zkontrolovat, zda fopen vrátí NULL. 571 00:45:33,870 --> 00:45:38,170 Vždy byste měli zkontrolovat, aby se ujistil, že malloc nevrátí NULL, 572 00:45:38,170 --> 00:45:41,410 jinak byste segfault. 573 00:45:42,200 --> 00:45:45,930 >> Teď buggy4.c. 574 00:45:49,190 --> 00:45:58,440 Běh. Hádám, že je to čeká na vstup nebo případně nekonečné smyčky. 575 00:45:58,440 --> 00:46:01,870 Ano, je to nekonečné smyčky. 576 00:46:01,870 --> 00:46:05,560 Tak buggy4. Vypadá to, že jsme nekonečné smyčky. 577 00:46:05,560 --> 00:46:12,590 Můžeme rozdělit na hlavní, spusťte náš program. 578 00:46:12,590 --> 00:46:20,180 V gdb, tak dlouho, jak zkratka použít je jednoznačná 579 00:46:20,180 --> 00:46:23,420 nebo speciální zkratky, které poskytují pro vás, 580 00:46:23,420 --> 00:46:29,020 pak můžete použít n k použití příště místo toho, aby musel psát v příštím celou cestu. 581 00:46:29,020 --> 00:46:33,730 A teď, když jsem udeřil n jednou, mohu jen stiskněte Enter dál další 582 00:46:33,730 --> 00:46:36,640 místo toho, aby museli zasáhnout n Enter, n Enter, n Enter. 583 00:46:36,640 --> 00:46:44,630 Vypadá to, že jsem v nějaké smyčce for, že je nastavení pole [i] na 0. 584 00:46:44,630 --> 00:46:50,510 Vypadá to, že jsem nikdy vypadla z toho pro smyčky. 585 00:46:50,510 --> 00:46:54,780 Kdybych tisku i, tak jsem je 2, pak půjdu dál. 586 00:46:54,780 --> 00:46:59,250 Budu tisknout i, i je 3, pak půjdu dál. 587 00:46:59,250 --> 00:47:05,360 Budu tisknout i a i je 3. Další, tisk i, i je 4. 588 00:47:05,360 --> 00:47:14,520 Vlastně, tisk sizeof (pole), takže velikost pole je 20. 589 00:47:16,310 --> 00:47:32,870 Ale vypadá to, že tam je nějaký zvláštní gdb příkaz pro přechod až se něco stane. 590 00:47:32,870 --> 00:47:37,620 Je to jako nastavení podmínku na hodnotě proměnné. Ale já nevím, co to je. 591 00:47:37,620 --> 00:47:44,100 Takže pokud budeme pokračovat - 592 00:47:44,100 --> 00:47:47,120 Co jsi říkal? Co jste vychovávat? 593 00:47:47,120 --> 00:47:50,500 [Student] Má zobrazí i přidat - >> Jo. Takže zobrazí i vám může pomoci. 594 00:47:50,500 --> 00:47:54,530 Pokud bychom jen zobrazit i, bude to dát sem, co hodnota i je 595 00:47:54,530 --> 00:47:56,470 takže nemám ji vytisknout pokaždé. 596 00:47:56,470 --> 00:48:02,930 Pokud budeme jen dál vedle, vidíme 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 Něco se děje strašně špatně, a já se nastaví na 0. 598 00:48:13,330 --> 00:48:22,220 Při pohledu na buggy4.c, vidíme všechno, co se stane, je int pole [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 array [i] = 0; 601 00:48:28,550 --> 00:48:31,390 Co vidíme, že je to špatně? 602 00:48:31,390 --> 00:48:39,480 Jako náznak, když jsem dělal gdb buggy4 - pojďme rozbít hlavní, run - 603 00:48:39,480 --> 00:48:45,980 Já jsem print sizeof (pole) jen proto, aby viděli, co je stav, kdy bych si měl konečně vypuknout. 604 00:48:47,690 --> 00:48:51,100 Kde to jsem? Jsem utíkal? 605 00:48:51,100 --> 00:48:54,280 Jsem nepřiznal ještě. 606 00:48:54,280 --> 00:48:58,680 Takže tisk sizeof (pole), a to 20, 607 00:48:58,680 --> 00:49:06,690 kterého se očekává, protože moje pole je velikosti 5 a je to z 5 celých čísel, 608 00:49:06,690 --> 00:49:12,410 takže celá věc by měla být 5 * sizeof (int) bytů, pokud sizeof (int) tendence k 4. 609 00:49:12,410 --> 00:49:14,780 Takže sizeof (pole) je 20. 610 00:49:14,780 --> 00:49:17,420 Co by to mohlo být? 611 00:49:17,420 --> 00:49:21,720 [Student] děleno sizeof (int). >> Jo, / sizeof (int). 612 00:49:21,720 --> 00:49:30,630 Vypadá to, že je tu ještě jeden problém. Myslím, že by to mělo být jen < 613 00:49:30,630 --> 00:49:36,960 protože je to docela hodně vždy 00:49:44,860 Nyní se pojďme zamyslet, proč byl tento skutečně zlomené. 615 00:49:44,860 --> 00:49:53,370 Má někdo uhodne, proč byl i obnovit 0 až každé iteraci smyčky? 616 00:50:01,300 --> 00:50:09,350 Jediné uvnitř zde, že se děje, je, že pole [i] je nastaven na hodnotu 0. 617 00:50:09,350 --> 00:50:15,350 Takže nějak, tento řádek kódu je příčinou našeho int i být nastavena na 0. 618 00:50:16,730 --> 00:50:23,130 [Student] Mohlo by to být proto, že je to naléhavé paměť této části i 619 00:50:23,130 --> 00:50:27,970 když si myslí, že je to další prvek pole? >> [Bowden] Ano. 620 00:50:27,970 --> 00:50:33,880 Když jdeme po skončení našeho pole, 621 00:50:33,880 --> 00:50:39,870 nějak, že prostor, který jsme přepsání je přepsání hodnoty i. 622 00:50:39,870 --> 00:50:48,030 A tak když se podíváme do buggy4, rozbít hlavní, běh, 623 00:50:48,030 --> 00:50:53,120 Pojďme vytisknout adresu i. 624 00:50:53,120 --> 00:50:57,280 Vypadá to, že to bffff124. 625 00:50:57,280 --> 00:51:03,930 Nyní pojďme vytisknout adresu pole [0]. 110. 626 00:51:03,930 --> 00:51:06,290 Co [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] je bfff124. 629 00:51:14,530 --> 00:51:26,990 Takže pole [5] má stejnou adresu jako já, což znamená, že pole [5], je i. 630 00:51:26,990 --> 00:51:30,720 Pokud mají stejnou adresu, jsou jedno a totéž. 631 00:51:30,720 --> 00:51:38,410 Takže když jsme se pole [5] na 0, kterou vytváříme i na 0. 632 00:51:38,410 --> 00:51:46,070 A pokud si myslíte, že o tom, pokud jde o zásobníku, 633 00:51:46,070 --> 00:51:55,590 int i je deklarován jako první, což znamená, že jsem se dostane určitý prostor na zásobníku. 634 00:51:55,590 --> 00:52:04,730 Pak array [5] je přiděleno, tak pak 20 bytů jsou přidělovány na zásobníku. 635 00:52:04,730 --> 00:52:08,400 Takže i dostane přiděleno první, pak těchto 20 bytů si přiděleny. 636 00:52:08,400 --> 00:52:11,400 Tak jsem se děje přímo před pole, 637 00:52:11,400 --> 00:52:19,230 a kvůli tomu, jak, jak jsem řekl minulý týden, pokud je to technicky stack roste dolů, 638 00:52:19,230 --> 00:52:28,520 když index do pole, jsou zaručeny jsme, že 0. pozice v poli 639 00:52:28,520 --> 00:52:31,970 vždy se stane před prvním místě v poli. 640 00:52:31,970 --> 00:52:35,900 To je druh, jak jsem nakreslil minulý týden. 641 00:52:35,900 --> 00:52:42,210 Všimněte si, že ve spodní části máme adresu 0 a na vrcholu jsme adresu Max. 642 00:52:42,210 --> 00:52:44,880 Zásobník je vždy roste dolů. 643 00:52:48,100 --> 00:52:53,500 Řekněme, že jsme se rozdělit i. 644 00:52:53,500 --> 00:52:59,680 Jsme alokovat integer i, což znamená, řekněme, že se tu celé číslo i dostane přiděleno. 645 00:52:59,680 --> 00:53:06,420 Pak jsme přidělit naší nabídku 5 celých čísel, což znamená, že pod tím, 646 00:53:06,420 --> 00:53:11,230 protože zásobník roste dolů, dostat přiděleno těch 5 celá čísla. 647 00:53:11,230 --> 00:53:15,900 Ale protože, jak pole pracovat, to zaručuje, že jsme první pozice v poli 648 00:53:15,900 --> 00:53:22,260 má vždy adresu menší než druhý věc v poli. 649 00:53:22,260 --> 00:53:28,270 Takže array poloha 0 musí vždy stát první v paměti, 650 00:53:28,270 --> 00:53:30,700 vzhledem k tomu, pole pozici 1 má stát poté, co 651 00:53:30,700 --> 00:53:33,310 a pole pozice 2 se stane po tom, 652 00:53:33,310 --> 00:53:37,900 což znamená, že pole v poloze 0 by se stalo, někde tady dole, 653 00:53:37,900 --> 00:53:40,690 Pole pozice 1 by se stalo, že výše 654 00:53:40,690 --> 00:53:45,530 protože pohybující se rozumí vyšší adresy, protože maximální adresa je tady. 655 00:53:45,530 --> 00:53:50,490 Takže pole [0] se zde, array [1] tady, array [2] tady, array [3] tady. 656 00:53:50,490 --> 00:53:55,620 Všimněte si, jak před tím, než přidělí celé číslo i po celou cestu až sem, 657 00:53:55,620 --> 00:54:01,040 jak jsme se přesunout dále a dále do našeho pole, jsme stále blíž a blíž k našemu celé číslo i. 658 00:54:01,040 --> 00:54:07,640 To jen tak se stane, že pole [5], což je o jednu pozici nad naše pole, 659 00:54:07,640 --> 00:54:13,010 je přesně tam, kde celé číslo i stalo které mají být přiděleny. 660 00:54:13,010 --> 00:54:16,920 Tak to je místo, kde jsme se náhodou bít prostor na zásobníku 661 00:54:16,920 --> 00:54:21,680 , která byla přidělena pro celočíselné i, a my jsme nastavení, které se 0. 662 00:54:21,680 --> 00:54:26,160 >> To je, jak to funguje. Otázky? Jo. 663 00:54:26,160 --> 00:54:30,710 [Student] To nevadí. Dobře. 664 00:54:30,710 --> 00:54:33,090 [Student] Jak se vyhnout těmto druh chyby? 665 00:54:33,090 --> 00:54:41,190 Tyto druh chyby? Nepoužívejte C jako programovací jazyk. 666 00:54:41,190 --> 00:54:45,840 Používejte jazyk, který má pole meze kontroly. 667 00:54:45,840 --> 00:54:55,900 Tak dlouho, jak jste opatrní, stačí, aby se zabránilo jít za hranice svého pole. 668 00:54:55,900 --> 00:54:58,300 [Student] Tak tady, když jsme šli kolem hranice svého pole - 669 00:54:58,300 --> 00:55:01,840 [Bowden] To je místo, kde se věci začnou špatně. >> [Student] Oh, dobře. 670 00:55:01,840 --> 00:55:05,730 Tak dlouho, jak si pobyt v paměti přidělené pro pole, že jsi v pořádku. 671 00:55:05,730 --> 00:55:12,400 Ale C dělá žádnou kontrolu chyb. Pokud to udělám pole [1000], bude to s radostí jen změnit ať se stane cokoli - 672 00:55:12,400 --> 00:55:16,500 To vede k začátku pole, pak jde 1000 postavení po a nastaví na hodnotu 0. 673 00:55:16,500 --> 00:55:20,000 To nedělá žádnou kontrolu, že oh, to není ve skutečnosti mít 1000 věcí v něm. 674 00:55:20,000 --> 00:55:22,750 1000 je daleko za to, co jsem měla být změna, 675 00:55:22,750 --> 00:55:26,940 vzhledem k tomu, Java nebo něco dostanete nabídku z indexu bounds 676 00:55:26,940 --> 00:55:29,820 nebo index out of bounds výjimky. 677 00:55:29,820 --> 00:55:33,950 To je důvod, proč mnoho jazycích vyšší úrovně mají tyto věci 678 00:55:33,950 --> 00:55:37,340 kde když jdete za hranice pole, se vám to nepodaří 679 00:55:37,340 --> 00:55:40,070 takže není možné měnit věci z pod vámi 680 00:55:40,070 --> 00:55:42,590 a pak se věci jít mnohem horší, než jen dostat výjimku 681 00:55:42,590 --> 00:55:44,940 říká, že jste šel za konec pole. 682 00:55:44,940 --> 00:55:50,970 [Student] A tak jsme měli pouze změnil <= jen > [Bowden] Jo. 683 00:55:50,970 --> 00:55:54,800 To by mělo být 00:55:59,560 protože sizeof (pole) je 20, ale chceme jen 5. >> [Student] Právo. 685 00:55:59,560 --> 00:56:04,060 Další otázky? Dobře. 686 00:56:04,060 --> 00:56:07,380 >> [Student] Mám dotaz. Jo >>. 687 00:56:07,380 --> 00:56:16,440 [Student] Jaký je skutečný pole proměnná? 688 00:56:16,440 --> 00:56:20,000 [Bowden] Jako co je pole? 689 00:56:20,000 --> 00:56:24,930 Array sám je symbolem. 690 00:56:24,930 --> 00:56:31,490 Je to právě adresa začátku 20 bajtů, které jsme odkazujících. 691 00:56:31,490 --> 00:56:38,070 Můžete si ji představit jako ukazatel, ale je to konstanta ukazatel. 692 00:56:38,070 --> 00:56:44,140 Jakmile se věci shromážděny, proměnná pole již neexistuje. 693 00:56:44,140 --> 00:56:48,210 [Student] Tak jak to zjistit velikost pole? 694 00:56:48,210 --> 00:56:54,130 Velikost pole se odkazuje na velikost tohoto bloku, který tento symbol odkazuje. 695 00:56:54,130 --> 00:57:01,240 Když jsem udělat něco jako printf ("% p \ n", pole); 696 00:57:01,240 --> 00:57:05,140 pojďme spustit. 697 00:57:12,960 --> 00:57:15,530 Co jsem právě udělal špatně? 698 00:57:15,530 --> 00:57:19,220 Array "array" prohlásil zde. 699 00:57:20,820 --> 00:57:23,200 Oh, tady. 700 00:57:23,200 --> 00:57:31,250 Řinčet je chytrý, a to se stane si, že jsem prohlásil pole jako 5 elementů 701 00:57:31,250 --> 00:57:34,540 ale já jsem indexování do polohy 1000. 702 00:57:34,540 --> 00:57:38,450 To může udělat, protože to jsou jen konstanty. 703 00:57:38,450 --> 00:57:43,370 To může jít jen tak daleko, všiml si, že budu mimo hranice pole. 704 00:57:43,370 --> 00:57:46,880 Povšimněme si ale předtím, když jsme měli i být nesprávné, 705 00:57:46,880 --> 00:57:51,040 nelze přesně určit, kolik hodnot bych si mohl vzít na, 706 00:57:51,040 --> 00:57:55,540 tak to nemůže stanovit, že jsem šel za konec pole. 707 00:57:55,540 --> 00:57:59,430 To je jen zvonění je chytrý. 708 00:57:59,430 --> 00:58:03,340 >> Ale teď dělat buggy4. Takže co jiného dělám špatně? 709 00:58:03,340 --> 00:58:05,970 Implicitně prohlašuje knihovní funkce "printf". 710 00:58:05,970 --> 00:58:14,960 Budu chtít, aby # include . 711 00:58:14,960 --> 00:58:18,710 Dobře. Nyní běží buggy4. 712 00:58:18,710 --> 00:58:24,840 Tisk hodnotu pole jako já zde, potisk jako ukazatel 713 00:58:24,840 --> 00:58:30,060 postery něco, co vypadá takhle - bfb8805c - což je asi adresa 714 00:58:30,060 --> 00:58:33,450 že je v zásobníku-ish regionu. 715 00:58:33,450 --> 00:58:41,820 Pole sám je jako ukazatel, ale není to skutečný ukazatel, 716 00:58:41,820 --> 00:58:45,410 protože běžný ukazatel můžeme změnit. 717 00:58:45,410 --> 00:58:54,700 Pole je jen nějaká konstanta. V 20 bloků paměti kdo na adrese 0xbfb8805c. 718 00:58:54,700 --> 00:59:09,020 Takže bfb8805c prostřednictvím této adrese +20- nebo myslím -20 - 719 00:59:09,020 --> 00:59:17,400 je všechny paměti přidělené pro toto pole. 720 00:59:17,400 --> 00:59:20,350 Array, je proměnná sama není uloženo kdekoliv. 721 00:59:20,350 --> 00:59:27,660 Když jste sestavování, kompilátor - Hand Wave na to - 722 00:59:27,660 --> 00:59:33,060 ale kompilátor bude jen používat, pokud ví, pole se. 723 00:59:33,060 --> 00:59:36,090 Ví, kde toto pole začíná, 724 00:59:36,090 --> 00:59:40,910 a tak to může vždy jen dělat věci, pokud jde o kompenzace od tohoto počátku. 725 00:59:40,910 --> 00:59:43,960 To nepotřebuje proměnnou sám reprezentovat pole. 726 00:59:43,960 --> 00:59:53,730 Ale když jsem něco takového int * p = pole; nyní p je ukazatel, který ukazuje na tomto poli, 727 00:59:53,730 --> 00:59:57,830 a nyní p vlastně neexistuje v zásobníku. 728 00:59:57,830 --> 01:00:01,950 Jsem volná změnit ks. Mohu p = malloc. 729 01:00:01,950 --> 01:00:06,500 Tak to původně zaměřila na pole, teď to ukazuje na nějaký prostor na haldě. 730 01:00:06,500 --> 01:00:09,620 Nemůžu pole = malloc. 731 01:00:09,620 --> 01:00:13,710 Pokud zvonění je chytrý, bude to na mě křičet hned bat. 732 01:00:17,000 --> 01:00:21,430 Vlastně, jsem si docela jistý, gcc by to taky. 733 01:00:21,430 --> 01:00:25,010 Takže typ pole "int [5]" není převoditelná. 734 01:00:25,010 --> 01:00:28,040 Nemůžete přiřadit něco typu pole 735 01:00:28,040 --> 01:00:30,500 protože pole je jen konstantní. 736 01:00:30,500 --> 01:00:34,760 Je to symbol, který odkazuje tato 20 bytů. Nemůžu to změnit. 737 01:00:34,760 --> 01:00:37,690 >> [Student] A, kde je velikost pole uložena? 738 01:00:37,690 --> 01:00:40,670 [Bowden] To není uloženo kdekoliv. Je to, když je to kompilaci. 739 01:00:40,670 --> 01:00:46,310 Takže, kde je velikost pole uloženy? 740 01:00:46,310 --> 01:00:51,870 Můžete použít pouze sizeof (pole) uvnitř funkce, která pole je deklarována sám. 741 01:00:51,870 --> 01:01:03,150 Takže když udělám nějakou funkci, foo, a já (int array []) 742 01:01:03,150 --> 01:01:10,450 printf ("% d \ n", sizeof (pole)); 743 01:01:10,450 --> 01:01:21,330 a pak sem zavolám foo (array); 744 01:01:21,330 --> 01:01:24,840 uvnitř této funkce - pojďme jej spustit. 745 01:01:34,200 --> 01:01:36,840 To je zvonění je chytrý znovu. 746 01:01:36,840 --> 01:01:43,890 To mi říká, že sizeof na pole parametru funkce 747 01:01:43,890 --> 01:01:46,690 vrátí velikost "int * '. 748 01:01:46,690 --> 01:01:55,150 To by bylo chybou, pokud to není to, co jsem chtěl aby se to stalo. 749 01:01:55,150 --> 01:01:58,960 Pojďme skutečně vypnout Werror. 750 01:02:14,950 --> 01:02:17,590 Varování. Varování jsou v pořádku. 751 01:02:17,590 --> 01:02:19,960 To bude ještě sestavit tak dlouho, jak to má varování. 752 01:02:19,960 --> 01:02:22,910 . / A.out bude tisknout 4. 753 01:02:22,910 --> 01:02:28,650 Varování, která byla generována je jasným ukazatelem toho, co se stalo. 754 01:02:28,650 --> 01:02:34,120 Tento int pole je jen tak tisknout sizeof (int *). 755 01:02:34,120 --> 01:02:39,790 I když jsem dal nabídku [5] tady, je to stále jen tak tisknout sizeof (int *). 756 01:02:39,790 --> 01:02:47,440 Takže jakmile předáte jej do funkce, rozdíl mezi poli a ukazatele 757 01:02:47,440 --> 01:02:49,670 neexistuje. 758 01:02:49,670 --> 01:02:52,640 To se stane, že pole, které bylo deklarováno na zásobníku, 759 01:02:52,640 --> 01:02:58,300 ale jakmile jsme se projít tuto hodnotu, že 0xbf bla, bla, bla do této funkce, 760 01:02:58,300 --> 01:03:03,350 pak tento ukazatel ukazuje na daném poli v zásobníku. 761 01:03:03,350 --> 01:03:08,310 Takže to znamená, že sizeof platí pouze ve funkci, která pole byla prohlášena, 762 01:03:08,310 --> 01:03:11,230 což znamená, že když se sestavování tuto funkci, 763 01:03:11,230 --> 01:03:17,330 Při zvonění prochází této funkce, to vidí pole je int pole o velikosti 5. 764 01:03:17,330 --> 01:03:20,640 Takže pak to vidí sizeof (pole). No, to je 20. 765 01:03:20,640 --> 01:03:26,440 To je vlastně, jak sizeof funguje v podstatě téměř ve všech případech. 766 01:03:26,440 --> 01:03:31,150 Sizeof není funkce, je to operátor. 767 01:03:31,150 --> 01:03:33,570 Nemusíte volat sizeof funkci. 768 01:03:33,570 --> 01:03:38,280 Sizeof (int), bude kompilátor jen překládat které až 4. 769 01:03:41,480 --> 01:03:43,700 Máš to? Dobře. 770 01:03:43,700 --> 01:03:47,520 >> [Student] Tak v čem je rozdíl mezi sizeof (pole) v hlavní a v foo? 771 01:03:47,520 --> 01:03:52,840 To je proto, že říkáte, že sizeof (pole), což je z * typ int, 772 01:03:52,840 --> 01:03:57,120 vzhledem k tomu, pole tady dole nemá * typu int, je to int pole. 773 01:03:57,120 --> 01:04:04,540 >> [Student] Takže pokud jste měli parametr v poli [] namísto int * pole, 774 01:04:04,540 --> 01:04:09,230 by znamenalo, že byste mohli ještě změnit pole, protože teď je to ukazatel? 775 01:04:09,230 --> 01:04:14,250 [Bowden] Like this? >> [Student] Jo. Můžete změnit pole ve funkci teď? 776 01:04:14,250 --> 01:04:18,420 [Bowden] Dalo by se změnit pole v obou případech. 777 01:04:18,420 --> 01:04:23,130 V obou těchto případech si budete moci říct, array [4] = 0. 778 01:04:23,130 --> 01:04:26,590 [Student] Ale můžete si pole přejděte na něco jiného? 779 01:04:26,590 --> 01:04:30,230 [Bowden] Oh. Jo. V obou případech - >> [studentka] Jo. 780 01:04:30,230 --> 01:04:38,410 [Bowden] Rozdíl mezi pole [] a int * pole, tam není nikdo. 781 01:04:38,410 --> 01:04:42,570 Můžete také získat nějaké vícerozměrné pole zde 782 01:04:42,570 --> 01:04:47,050 pro některé pohodlné syntaxe, ale je to stále jen ukazatel. 783 01:04:47,050 --> 01:04:56,400 To znamená, že jsem si může dělat, pole = malloc (sizeof (int)), a nyní ukazují někam jinam. 784 01:04:56,400 --> 01:04:59,610 Ale stejně jako, jak to funguje navždy a vždy, 785 01:04:59,610 --> 01:05:03,210 Změnou tohoto pole tím, že ho upozornit na něco jiného 786 01:05:03,210 --> 01:05:07,570 nemění toto pole tady dole, protože je to kopie argumentu, 787 01:05:07,570 --> 01:05:10,780 to není ukazatel na tento argument. 788 01:05:10,780 --> 01:05:16,070 A skutečně, stejně jako další znamení, že je to přesně to samé - 789 01:05:16,070 --> 01:05:21,100 jsme již viděli, co tiskařský pole - 790 01:05:21,100 --> 01:05:31,410 co když tiskneme adresu pole nebo adresu adresu pole 791 01:05:31,410 --> 01:05:36,290 buď z nich? 792 01:05:41,770 --> 01:05:45,220 Pojďme ignorovat tento jeden. 793 01:05:48,140 --> 01:05:51,660 Dobře. To je v pořádku. Je to nyní běží. / A.out. 794 01:05:51,660 --> 01:06:00,220 Potisk pole, pak tisk adresu pole, jsou jedno a totéž. 795 01:06:00,220 --> 01:06:02,870 Array prostě neexistuje. 796 01:06:02,870 --> 01:06:08,190 To ví, kdy tisknete pole, tisknete na symbol, který odkazuje na těch 20 bajtů. 797 01:06:08,190 --> 01:06:11,940 Tisk adresu pole, dobře, pole neexistuje. 798 01:06:11,940 --> 01:06:17,200 To nemá adresu, tak to prostě vytiskne adresu těchto 20 bajtů. 799 01:06:20,820 --> 01:06:28,150 Jakmile budete kompilovat dolů, jako v kompilované buggy4. / A.out, 800 01:06:28,150 --> 01:06:30,340 pole je neexistující. 801 01:06:30,340 --> 01:06:33,640 Ukazatele existují. Pole ne. 802 01:06:34,300 --> 01:06:38,060 Bloky paměti představující pole stále existují, 803 01:06:38,060 --> 01:06:43,270 ale proměnná pole a proměnné tohoto typu neexistují. 804 01:06:46,260 --> 01:06:50,270 Ti jsou jako z hlavních rozdílů mezi poli a ukazatele 805 01:06:50,270 --> 01:06:55,590 jsou, jakmile uděláte volání funkce, není tam žádný rozdíl. 806 01:06:55,590 --> 01:07:00,460 Ale uvnitř funkce, které pole má prohlášení, sizeof pracuje odlišně 807 01:07:00,460 --> 01:07:05,190 protože tisknete velikost bloků namísto velikosti typu, 808 01:07:05,190 --> 01:07:08,950 a můžete jej změnit, protože je to symbol. 809 01:07:08,950 --> 01:07:14,370 Tisk věc a adresu věci vytiskne stejnou věc. 810 01:07:14,370 --> 01:07:18,480 A to je docela hodně to. 811 01:07:18,480 --> 01:07:20,820 [Student] Mohl byste říci, že ještě jednou? 812 01:07:21,170 --> 01:07:24,170 Možná jsem něco uniklo. 813 01:07:24,170 --> 01:07:29,260 Tisk pole a adresa pole vypíše to samé, 814 01:07:29,260 --> 01:07:33,180 vzhledem k tomu, pokud tisknete ukazatel oproti adresu ukazatele, 815 01:07:33,180 --> 01:07:36,010 jedna věc vytiskne adresu toho, co jste ukázal, 816 01:07:36,010 --> 01:07:40,360 jiný vytiskne adresu ukazatelem na zásobníku. 817 01:07:40,360 --> 01:07:47,040 Můžete změnit ukazatel, nemůžete změnit pole symbol. 818 01:07:47,740 --> 01:07:53,270 A sizeof ukazatel bude tisknout velikost tohoto ukazatele typu. 819 01:07:53,270 --> 01:07:57,470 Takže int * p sizeof (p) se bude tisknout 4, 820 01:07:57,470 --> 01:08:04,110 ale int array [5] print sizeof (pole), bude k tisku 20. 821 01:08:04,110 --> 01:08:07,480 [Student] Tak int array [5] se vytiskne 20? Ano >>. 822 01:08:07,480 --> 01:08:13,300 Proto uvnitř buggy4 když to bylo sizeof (pole) 823 01:08:13,300 --> 01:08:16,660 to bylo dělal i <20, což není to, co jsme chtěli. 824 01:08:16,660 --> 01:08:20,880 Chceme i <5. >> [Student] Dobře. 825 01:08:20,880 --> 01:08:25,569 [Bowden] A pak, jakmile začnete procházet v funkcemi, 826 01:08:25,569 --> 01:08:34,340 kdybychom int * p = array; 827 01:08:34,340 --> 01:08:39,779 uvnitř této funkce, můžeme v podstatě použít p a pole v přesně stejným způsobem, 828 01:08:39,779 --> 01:08:43,710 kromě problému sizeof a měnící problém. 829 01:08:43,710 --> 01:08:49,810 Ale p [0] = 1, je stejný jako pořekadlo pole [0] = 1; 830 01:08:49,810 --> 01:08:55,600 A jakmile říkáme foo (array); nebo foo (p); 831 01:08:55,600 --> 01:08:59,760 uvnitř funkce foo, to je stejný hovor dvakrát. 832 01:08:59,760 --> 01:09:03,350 Není žádný rozdíl mezi těmito dvěma hovory. 833 01:09:07,029 --> 01:09:11,080 >> Všichni dobře na to? Dobře. 834 01:09:14,620 --> 01:09:17,950 Máme 10 minut. 835 01:09:17,950 --> 01:09:28,319 >> Budeme se snažit dostat se přes tento program Hacker Typer, 836 01:09:28,319 --> 01:09:32,350 tento web, který vyšel v loňském roce nebo tak něco. 837 01:09:34,149 --> 01:09:41,100 Je to prostě má být, jako píšete náhodně, a to vytiskne - 838 01:09:41,100 --> 01:09:46,729 Ať soubor se to stane, že v zásobníku se, jak to vypadá píšete. 839 01:09:46,729 --> 01:09:52,069 Vypadá to jako nějaký druh operačního systému kódu. 840 01:09:53,760 --> 01:09:56,890 To je to, co chceme realizovat. 841 01:10:08,560 --> 01:10:11,690 Měli byste mít binární spustitelný názvem hacker_typer 842 01:10:11,690 --> 01:10:14,350 který bere v jediném argumentu, soubor "hacker typu." 843 01:10:14,350 --> 01:10:16,480 Spuštění spustitelný by vyčistit obrazovku 844 01:10:16,480 --> 01:10:20,850 a pak vytisknout jeden znak z předaný v souboru pokaždé, když uživatel stiskne klávesu. 845 01:10:20,850 --> 01:10:24,990 Takže bez ohledu na klíč stisknutí, měl by vyhodit a místo toho vytiskne znak ze souboru 846 01:10:24,990 --> 01:10:27,810 že je argument. 847 01:10:29,880 --> 01:10:34,350 Budu docela hodně říci, co věci budeme potřebovat vědět, jsou. 848 01:10:34,350 --> 01:10:36,440 Ale chceme se podívat na knihovnu termios. 849 01:10:36,440 --> 01:10:44,840 Nikdy jsem používal tento knihovnu v celém mém životě, tak to má velmi minimální účely. 850 01:10:44,840 --> 01:10:48,610 Ale to bude knihovna můžeme použít vyhodit znak, který hit 851 01:10:48,610 --> 01:10:52,390 když píšete do standardu palců 852 01:10:56,970 --> 01:11:05,840 Takže hacker_typer.c, a budeme chtít, aby # include . 853 01:11:05,840 --> 01:11:12,870 Při pohledu na manuálové stránce pro termios - já hádat, že je to terminál OS nebo tak něco - 854 01:11:12,870 --> 01:11:16,240 Já nevím, jak to číst. 855 01:11:16,240 --> 01:11:21,040 Při pohledu na to, že říká, že i na tyto 2 soubory, takže budeme dělat, že. 856 01:11:37,620 --> 01:11:46,820 >> První věc, kterou jako první, chceme, aby se v jediném argumentu, který je soubor bychom měli otevřít. 857 01:11:46,820 --> 01:11:52,420 Tak co chci dělat? Jak mohu zkontrolovat, zda mám jediný argument? 858 01:11:52,420 --> 01:11:56,480 [Student] Pokud argc rovná ji. >> [Bowden] Jo. 859 01:11:56,480 --> 01:12:21,250 Takže if (argc = 2!) Printf ("Použití:% s [soubor otevřít]"). 860 01:12:21,250 --> 01:12:32,750 Takže teď, když spustím to bez udání druhý argument - oh, potřebuju novou linku - 861 01:12:32,750 --> 01:12:36,240 uvidíte, že říká použití:. / hacker_typer, 862 01:12:36,240 --> 01:12:39,770 a pak druhý argument by měl být soubor chci otevřít. 863 01:12:58,430 --> 01:13:01,260 Teď, co mám dělat? 864 01:13:01,260 --> 01:13:08,490 Chci číst z tohoto souboru. Jak jsem četl ze souboru? 865 01:13:08,490 --> 01:13:11,920 [Student] můžete otevřít jako první. Jo >>. 866 01:13:11,920 --> 01:13:15,010 Tak fopen. Co fopen vypadá? 867 01:13:15,010 --> 01:13:22,980 [Student] souboru. >> [Bowden] souboru bude argv [1]. 868 01:13:22,980 --> 01:13:26,110 [Student] A pak to, co chcete dělat s tím, aby - >> [Bowden] Jo. 869 01:13:26,110 --> 01:13:28,740 Takže pokud jste si vzpomenout, mohl by si udělat muž fopen, 870 01:13:28,740 --> 01:13:32,960 kde to bude const char * path, kde path je jméno souboru, 871 01:13:32,960 --> 01:13:34,970 const char * mode. 872 01:13:34,970 --> 01:13:38,660 Pokud jste náhodou nepamatujete, co je režim, pak se můžete podívat na režim. 873 01:13:38,660 --> 01:13:44,660 Uvnitř manuálových stránek, znak lomítko je to, co můžete použít k vyhledání věci. 874 01:13:44,660 --> 01:13:49,790 Tak jsem typ / režim vyhledávání pro režim. 875 01:13:49,790 --> 01:13:57,130 n a N jsou to, co můžete použít k procházení vyhledávání zápasů. 876 01:13:57,130 --> 01:13:59,800 Zde se říká, že body argumentů režimu na řetězec 877 01:13:59,800 --> 01:14:01,930 začíná s jedním z následujících posloupností. 878 01:14:01,930 --> 01:14:06,480 Takže r, Open textový soubor pro čtení. To je to, co chceme dělat. 879 01:14:08,930 --> 01:14:13,210 Pro čtení, a chci uložit, že. 880 01:14:13,210 --> 01:14:18,720 Věc bude FILE *. Teď, co chci dělat? 881 01:14:18,720 --> 01:14:21,200 Dejte mi chvilku. 882 01:14:28,140 --> 01:14:30,430 Dobře. Teď, co chci dělat? 883 01:14:30,430 --> 01:14:32,940 [Student] Zkontrolujte, zda je to NULL. >> [Bowden] Jo. 884 01:14:32,940 --> 01:14:38,690 Pokaždé, když otevřete soubor, ujistěte se, že jste úspěšně schopný otevřít. 885 01:14:58,930 --> 01:15:10,460 >> Teď chci udělat, aby termios věci tam, kde chci nejprve přečíst moje současné nastavení 886 01:15:10,460 --> 01:15:14,050 a zachránit ty, do něčeho, pak chci změnit své nastavení 887 01:15:14,050 --> 01:15:19,420 vyhodit libovolný znak, který jsem typ, 888 01:15:19,420 --> 01:15:22,520 a pak chci aktualizovat tato nastavení. 889 01:15:22,520 --> 01:15:27,250 A pak na konci programu, chci změnit zpět na své původní nastavení. 890 01:15:27,250 --> 01:15:32,080 Takže struct bude typových termios, a budu chtít dva ty. 891 01:15:32,080 --> 01:15:35,600 První z nich bude moje current_settings, 892 01:15:35,600 --> 01:15:42,010 a pak to bude moje hacker_settings. 893 01:15:42,010 --> 01:15:48,070 Za prvé, budu chtít uložit své aktuální nastavení, 894 01:15:48,070 --> 01:15:53,790 pak budu chtít aktualizovat hacker_settings, 895 01:15:53,790 --> 01:16:01,570 a pak jak na konci svého programu, chci se vrátit na aktuální nastavení. 896 01:16:01,570 --> 01:16:08,660 Takže uložení aktuální nastavení, tak, že funguje, my man termios. 897 01:16:08,660 --> 01:16:15,810 Vidíme, že máme tuto int tcsetattr, int tcgetattr. 898 01:16:15,810 --> 01:16:22,960 Minul jsem v termios struct svým ukazatel. 899 01:16:22,960 --> 01:16:30,640 Způsob, jakým to bude vypadat, je - I've už zapomněli, co funkce byla volána. 900 01:16:30,640 --> 01:16:34,930 Zkopírujte a vložte ji. 901 01:16:39,150 --> 01:16:45,500 Takže tcgetattr, pak chci předat v struct, že jsem uložení informací v, 902 01:16:45,500 --> 01:16:49,650 která se bude current_settings, 903 01:16:49,650 --> 01:16:59,120 a první argument je deskriptor souboru pro věc, kterou chci uložit atributy. 904 01:16:59,120 --> 01:17:04,360 Co popisovač souboru je je jako kdykoliv otevřete soubor, dostane popisovač souboru. 905 01:17:04,360 --> 01:17:14,560 Když jsem fopen argv [1], se dostane popisovač souboru, který jste odkazující 906 01:17:14,560 --> 01:17:16,730 pokaždé, když chcete číst nebo do ní zapisovat. 907 01:17:16,730 --> 01:17:19,220 To není deskriptor souboru chci používat zde. 908 01:17:19,220 --> 01:17:21,940 K dispozici jsou tři deskriptory souborů, které máte ve výchozím nastavení, 909 01:17:21,940 --> 01:17:24,310 které jsou standardní v, standardní výstup a standardní chyba. 910 01:17:24,310 --> 01:17:29,960 Ve výchozím nastavení, myslím, že je to standard v je 0, standardní výstup je 1 a směrodatná odchylka je 2. 911 01:17:29,960 --> 01:17:33,980 Takže to, co chci změnit nastavení? 912 01:17:33,980 --> 01:17:37,370 Chci změnit nastavení, když jsem trefil postavu, 913 01:17:37,370 --> 01:17:41,590 Chci, aby to hodit, že charakter pryč, místo tisku na obrazovku. 914 01:17:41,590 --> 01:17:45,960 Co potok - standard v, standardní výstup, nebo standardní chybou - 915 01:17:45,960 --> 01:17:52,050 reaguje na věci, když jsem typ na klávesnici? >> [Student] Standardní a. >> Jo. 916 01:17:52,050 --> 01:17:56,450 Tak jsem si buď udělat 0, nebo můžu udělat stdin. 917 01:17:56,450 --> 01:17:59,380 Začínám se current_settings z normy a. 918 01:17:59,380 --> 01:18:01,720 >> Teď chci aktualizovat tato nastavení, 919 01:18:01,720 --> 01:18:07,200 takže první budu kopírovat do hacker_settings, co moji current_settings jsou. 920 01:18:07,200 --> 01:18:10,430 A jak structs práce je, že bude jen kopírovat. 921 01:18:10,430 --> 01:18:14,510 To zkopíruje všechna pole, jak byste očekávali. 922 01:18:14,510 --> 01:18:17,410 >> Teď chci aktualizovat některé z polí. 923 01:18:17,410 --> 01:18:21,670 Při pohledu na termios, byste si přečíst přes hodně to 924 01:18:21,670 --> 01:18:24,110 jen aby viděl, co byste chtěli hledat, 925 01:18:24,110 --> 01:18:28,210 ale příznaky budete chtít hledat, jsou echo, 926 01:18:28,210 --> 01:18:33,110 tak ECHO znaky Echo vstupní. 927 01:18:33,110 --> 01:18:37,710 Nejprve chci nastavit - I've už zapomněli, co jsou pole. 928 01:18:45,040 --> 01:18:47,900 To je to, co struct vypadá. 929 01:18:47,900 --> 01:18:51,060 Takže vstupní režimy myslím, že chceme změnit. 930 01:18:51,060 --> 01:18:54,210 My se podíváme na řešení, aby se ujistil, že je to to, co chceme změnit. 931 01:19:04,060 --> 01:19:12,610 Chceme změnit lflag, aby se zabránilo nutnosti prohlédnout všechny tyto. 932 01:19:12,610 --> 01:19:14,670 Chceme změnit místní režimy. 933 01:19:14,670 --> 01:19:17,710 Budete muset přečíst tento celou věc pochopit, kde všechno patří 934 01:19:17,710 --> 01:19:19,320 že chceme změnit. 935 01:19:19,320 --> 01:19:24,120 Ale je to uvnitř místních režimů, kde budeme chtít změnit. 936 01:19:27,080 --> 01:19:33,110 Takže hacker_settings.cc_lmode je to, co se jmenuje. 937 01:19:39,630 --> 01:19:43,020 c_lflag. 938 01:19:49,060 --> 01:19:52,280 To je místo, kde jsme se dostali do bitové operátory. 939 01:19:52,280 --> 01:19:54,860 Jsme trochu opožděně, ale my půjdeme přes to opravdu rychle. 940 01:19:54,860 --> 01:19:56,600 To je místo, kde jsme se dostali do operátory bitové, 941 01:19:56,600 --> 01:19:59,950 kde Myslím, že jsem řekl, jeden čas dávno, že při každém spuštění zabývající se vlajkami, 942 01:19:59,950 --> 01:20:03,370 budete používat bitového součinu provozovateli hodně. 943 01:20:03,370 --> 01:20:08,240 Každý bit ve vlajce odpovídá nějaké chování. 944 01:20:08,240 --> 01:20:14,090 Tak tady, tento příznak má spoustu různých věcí, kde všichni z nich znamenat něco jiného. 945 01:20:14,090 --> 01:20:18,690 Ale to, co chci udělat, je prostě vypnout bit, který odpovídá ECHO. 946 01:20:18,690 --> 01:20:25,440 Takže zase, že vypnutí dělám & = ¬ ECHO. 947 01:20:25,440 --> 01:20:30,110 Vlastně si myslím, že je to jako TECHO, nebo tak něco. Jdu jen zkontrolovat znovu. 948 01:20:30,110 --> 01:20:34,050 Můžu termios to. Je to jen ECHO. 949 01:20:34,050 --> 01:20:38,440 ECHO se bude jeden bit. 950 01:20:38,440 --> 01:20:44,230 ¬ ECHO bude znamenat všechny bity jsou nastaveny na 1, což znamená, že všechny příznaky jsou nastaveny na hodnotu true 951 01:20:44,230 --> 01:20:47,140 s výjimkou ECHO bit. 952 01:20:47,140 --> 01:20:53,830 Tím končí mé místní příznaky s tím, to znamená všechny příznaky, které jsou v současné době nastaveny na hodnotu true 953 01:20:53,830 --> 01:20:56,520 bude stále nastavena na hodnotu true. 954 01:20:56,520 --> 01:21:03,240 Pokud je moje ECHO příznak nastaven na true, pak je to nutně nastavena na hodnotu false na ECHO vlajky. 955 01:21:03,240 --> 01:21:07,170 Takže tento řádek kódu jen vypne ECHO vlajkou. 956 01:21:07,170 --> 01:21:16,270 Další řádky kódu, budu jen zkopírovat v zájmu času a pak je vysvětlit. 957 01:21:27,810 --> 01:21:30,180 V roztoku, řekl 0. 958 01:21:30,180 --> 01:21:33,880 Je to asi lepší explicitně říct stdin. 959 01:21:33,880 --> 01:21:42,100 >> Všimněte si, že jsem také dělal ECHO | icanon zde. 960 01:21:42,100 --> 01:21:46,650 Icanon odkazuje na něco oddělený, což znamená, že kanonické režimu. 961 01:21:46,650 --> 01:21:50,280 Co kanonický režim znamená, je obvykle, když píšete z příkazového řádku, 962 01:21:50,280 --> 01:21:54,670 standard v nezpracovává nic, dokud nenarazíte nový řádek. 963 01:21:54,670 --> 01:21:58,230 Takže, když to GetString, zadejte spoustu věcí, pak hit nový řádek. 964 01:21:58,230 --> 01:22:00,590 To je, když je to poslal normy palců 965 01:22:00,590 --> 01:22:02,680 To je výchozí. 966 01:22:02,680 --> 01:22:05,830 Když jsem vypnout kanonickou režim, hned každý jednotlivý znak stisknete 967 01:22:05,830 --> 01:22:10,910 je to, co dostane zpracovávány, což je obvykle trochu špatně, protože je to pomalý zpracovat tyto věci, 968 01:22:10,910 --> 01:22:14,330 což je důvod, proč je dobré, aby se zmírnily do celých řádků. 969 01:22:14,330 --> 01:22:16,810 Ale chci každá postava má být zpracovány 970 01:22:16,810 --> 01:22:18,810 protože jsem to nechci čekat na mě zasáhnout nový řádek 971 01:22:18,810 --> 01:22:21,280 před zpracovává všechny znaky jsem psát. 972 01:22:21,280 --> 01:22:24,760 Toto vypne kanonickou režim. 973 01:22:24,760 --> 01:22:31,320 Tohle prostě znamená, když ve skutečnosti zpracovává znaky. 974 01:22:31,320 --> 01:22:35,830 To znamená, že zpracování je okamžitě, jakmile jsem psaní je, zpracovávat je. 975 01:22:35,830 --> 01:22:42,510 A to je funkce, která je aktualizace svoje nastavení pro standardní v, 976 01:22:42,510 --> 01:22:45,480 a TCSA prostředky to udělat právě teď. 977 01:22:45,480 --> 01:22:50,310 Další možnosti jsou počkat, až vše, co je v současné době na toku je zpracován. 978 01:22:50,310 --> 01:22:52,030 To opravdu nezáleží. 979 01:22:52,030 --> 01:22:56,920 Právě teď měnit mé nastavení je vše, co je v současné době v hacker_typer_settings. 980 01:22:56,920 --> 01:23:02,210 Myslím, že jsem ji nazval hacker_settings, tak se pojďme změnit. 981 01:23:09,610 --> 01:23:13,500 Změna všechno hacker_settings. 982 01:23:13,500 --> 01:23:16,870 >> Teď na konci našeho programu budeme chtít vrátit 983 01:23:16,870 --> 01:23:20,210 na to, co je v současné době uvnitř normal_settings, 984 01:23:20,210 --> 01:23:26,560 který se bude jen vypadat jako & normal_settings. 985 01:23:26,560 --> 01:23:30,650 Všimněte si, jsem se nezměnil žádný z mých normal_settings od původně dostat ji. 986 01:23:30,650 --> 01:23:34,520 Pak jen změnit zpět, předám je zpátky na konci. 987 01:23:34,520 --> 01:23:38,390 To bylo aktualizace. Dobře. 988 01:23:38,390 --> 01:23:43,900 >> Nyní uvnitř tady budu vysvětlovat kód v zájmu času. 989 01:23:43,900 --> 01:23:46,350 To není tak moc code. 990 01:23:50,770 --> 01:24:03,750 Vidíme čteme znak ze souboru. Říkali jsme, že f. 991 01:24:03,750 --> 01:24:07,850 Nyní si může člověk fgetc, ale jak fgetc bude fungovat 992 01:24:07,850 --> 01:24:11,910 je jen to bude vrátí znak, který jste právě přečetli, nebo EOF, 993 01:24:11,910 --> 01:24:15,680 který odpovídá konci souboru nebo nějaké chyby děje. 994 01:24:15,680 --> 01:24:19,900 Jsme smyčky, nadále číst znak ze souboru, 995 01:24:19,900 --> 01:24:22,420 dokud jsme došly znaků číst. 996 01:24:22,420 --> 01:24:26,650 A zatímco my děláme to, že budeme čekat na jeden znak z normy palců 997 01:24:26,650 --> 01:24:29,090 Pokaždé zadáte něco do příkazového řádku, 998 01:24:29,090 --> 01:24:32,820 že čte v charakteru od standardu a. 999 01:24:32,820 --> 01:24:38,330 Pak putchar se právě chystá dát char čteme tady ze souboru na standardní výstup. 1000 01:24:38,330 --> 01:24:42,890 Můžete muž putchar, ale je to jen uvedení na standardní výstup, je to tisk, že charakter. 1001 01:24:42,890 --> 01:24:51,600 Dalo by se také jen to, printf ("% c", c); Stejný nápad. 1002 01:24:53,330 --> 01:24:56,670 To bude dělat většinu naší práce. 1003 01:24:56,670 --> 01:25:00,300 >> Poslední věc, kterou budeme chtít udělat, je jen fclose náš soubor. 1004 01:25:00,300 --> 01:25:03,310 Pokud nechcete fclose, že je to k nevracení paměti. 1005 01:25:03,310 --> 01:25:06,680 Chceme fclose soubor jsme původně otevřen, a myslím, že je to ono. 1006 01:25:06,680 --> 01:25:13,810 Učiníme-li to, že jsem už nějaké problémy. 1007 01:25:13,810 --> 01:25:17,260 Pojďme se podívat,. 1008 01:25:17,260 --> 01:25:19,960 Co to stěžují? 1009 01:25:19,960 --> 01:25:30,220 Předpokládaný "int", ale argument je typu "struct _IO_FILE *". 1010 01:25:36,850 --> 01:25:39,370 Uvidíme, jestli to funguje. 1011 01:25:45,210 --> 01:25:53,540 Povolen pouze v C99. Augh. Dobře, aby hacker_typer. 1012 01:25:53,540 --> 01:25:57,760 Nyní jsme se dostali další užitečné popisy. 1013 01:25:57,760 --> 01:25:59,900 Takže použití nehlášené identifikátor "normal_settings". 1014 01:25:59,900 --> 01:26:04,170 Nevolal jsem, že normal_settings. Nazval jsem ji current_settings. 1015 01:26:04,170 --> 01:26:12,090 Takže pojďme změnit všechno. 1016 01:26:17,920 --> 01:26:21,710 Teď kolem argument. 1017 01:26:26,290 --> 01:26:29,500 Budu tuto 0 prozatím. 1018 01:26:29,500 --> 01:26:36,720 Dobře. . / Hacker_typer cp.c. 1019 01:26:36,720 --> 01:26:39,590 Také jsem vyčistit obrazovku na začátku. 1020 01:26:39,590 --> 01:26:42,960 Ale můžete se podívat na poslední problém, aby viděl, jak je vymazat obrazovku. 1021 01:26:42,960 --> 01:26:45,160 Je to prostě tisku některé znaky 1022 01:26:45,160 --> 01:26:47,210 což se dělá to, co chci dělat. 1023 01:26:47,210 --> 01:26:48,900 Dobře. 1024 01:26:48,900 --> 01:26:55,280 A přemýšlet o tom, proč to musela být 0 místo standardního vstupu, 1025 01:26:55,280 --> 01:27:00,560 , která by měla být # vymezit 0, 1026 01:27:00,560 --> 01:27:03,890 to si stěžuje, že - 1027 01:27:13,150 --> 01:27:19,360 Než když jsem řekl, že je to popisovače souborů, ale pak máte také svůj soubor *, 1028 01:27:19,360 --> 01:27:23,210 popisovač souboru je jen jeden integer, 1029 01:27:23,210 --> 01:27:26,970 vzhledem k tomu, FILE * má spoustu věcí s ním spojené. 1030 01:27:26,970 --> 01:27:30,380 Důvod, proč jsme třeba říkat 0 místo standardního vstupu 1031 01:27:30,380 --> 01:27:37,480 je to, že stdin je FILE *, který poukazuje na to, co je odkazování na deskriptor souboru 0. 1032 01:27:37,480 --> 01:27:45,070 Takže i tady, když jsem si fopen (argv [1], začínám si soubor * zpět. 1033 01:27:45,070 --> 01:27:51,180 Ale někde v tom souboru * je věc odpovídající deskriptor souboru pro daný soubor. 1034 01:27:51,180 --> 01:27:57,430 Pokud se podíváte na manuálové stránce pro otevřené, takže myslím, že budete muset udělat člověk 3 open - Ne - 1035 01:27:57,430 --> 01:27:59,380 man 2 open - jo. 1036 01:27:59,380 --> 01:28:06,250 Pokud se podíváte na stránky pro otevřenou, otevřený je jako nižší úrovně fopen, 1037 01:28:06,250 --> 01:28:09,350 a je to vrátí aktuální popisovač souboru. 1038 01:28:09,350 --> 01:28:12,050 fopen dělá spoustu věcí na vrcholu otevřené, 1039 01:28:12,050 --> 01:28:17,640 které namísto vrácení jen, že deskriptor souboru vrátí a celou souboru * ukazatel 1040 01:28:17,640 --> 01:28:20,590 uvnitř které je náš malý deskriptor souboru. 1041 01:28:20,590 --> 01:28:25,020 Takže standard se vztahuje na věci FILE *, 1042 01:28:25,020 --> 01:28:29,120 vzhledem k tomu, 0 odkazuje jen na standardu deskriptoru souboru v sobě. 1043 01:28:29,120 --> 01:28:32,160 >> Otázky? 1044 01:28:32,160 --> 01:28:35,930 [Smích] prohnal, že. 1045 01:28:35,930 --> 01:28:39,140 Dobrá. Skončili jsme. [Smích] 1046 01:28:39,140 --> 01:28:42,000 >> [CS50.TV]