1 00:00:00,000 --> 00:00:02,500 [Powered by Google Translate] [Sezione 5 - più confortevole] 2 00:00:02,500 --> 00:00:04,690 [Rob Bowden - Harvard University] 3 00:00:04,690 --> 00:00:07,250 [Questo è CS50. - CS50.TV] 4 00:00:08,990 --> 00:00:14,250 >> Come ho detto nella mia e-mail, ci sono un sacco di cose che si possono utilizzare 5 00:00:14,250 --> 00:00:17,060 oltre l'apparecchio di fare effettivamente i set problema. 6 00:00:17,060 --> 00:00:19,910 Si consiglia di farlo in macchina solo perché allora possiamo più facilmente aiutare 7 00:00:19,910 --> 00:00:22,070 e sappiamo quanto tutto sta andando a lavorare. 8 00:00:22,070 --> 00:00:26,950 Ma, come un esempio di dove si possono fare le cose se, per esempio, non si dispone di accesso 9 00:00:26,950 --> 00:00:31,570 ad un apparecchio o si desidera lavorare nel seminterrato Science Center - 10 00:00:31,570 --> 00:00:33,090 che in realtà hanno la macchina troppo - 11 00:00:33,090 --> 00:00:35,150 se si desidera lavorare ovunque. 12 00:00:35,150 --> 00:00:42,370 Un esempio è hai visto / sentito parlare di SSH? 13 00:00:44,380 --> 00:00:47,780 SSH è fondamentalmente solo come connettersi a qualcosa. 14 00:00:47,780 --> 00:00:51,340 In realtà, in questo momento sto SSHed nell'apparecchio. 15 00:00:51,340 --> 00:00:54,290 Non ho mai lavorare direttamente nell'apparecchio. 16 00:00:55,930 --> 00:01:01,060 Ecco l'apparecchio, e se si guarda qui si vede l'indirizzo IP. 17 00:01:01,060 --> 00:01:03,650 Non ho mai lavorare l'apparecchio stesso; 18 00:01:03,650 --> 00:01:08,840 Ho sempre venire a un iTerm2 finestra / finestra terminale. 19 00:01:08,840 --> 00:01:15,910 È possibile SSH a tale indirizzo IP, ssh jharvard@192.168.129.128. 20 00:01:15,910 --> 00:01:20,390 Ricordo che il numero molto facilmente perché è un bel modello. 21 00:01:20,390 --> 00:01:24,920 Ma che mi chiede la password, e ora sono in macchina. 22 00:01:24,920 --> 00:01:33,060 Fondamentalmente, a questo punto, se si apre un terminale all'interno dell'apparecchio stesso, 23 00:01:33,060 --> 00:01:36,350 questa interfaccia, ma lo si dovrebbe utilizzare, è esattamente lo stesso 24 00:01:36,350 --> 00:01:40,010 come l'interfaccia che sto usando qui, ma ora si sta SSHed. 25 00:01:42,240 --> 00:01:44,920 Non c'è bisogno di SSH per la macchina. 26 00:01:44,920 --> 00:01:52,360 Un esempio di un altro luogo si potrebbe SSH è che io sono abbastanza sicuro di avere di default - 27 00:01:52,360 --> 00:01:55,020 Oh. Più grande. 28 00:01:55,020 --> 00:02:01,130 Tutti si dovrebbe avere di account di default sui server FAS FAS. 29 00:02:01,130 --> 00:02:06,840 Per quanto mi riguarda, vorrei SSH al rbowden@nice.fas.harvard.edu. 30 00:02:06,840 --> 00:02:11,610 E 'intenzione di chiedere che la prima volta, e tu dici di sì. 31 00:02:11,610 --> 00:02:15,840 La mia password è solo andare a essere la mia password FAS. 32 00:02:15,840 --> 00:02:22,650 E così ora, sto SSHed ai server belle, e posso fare tutto quello che voglio qui. 33 00:02:22,650 --> 00:02:28,560 Un sacco di classi che si possono adottare, come 124, stanno per avere di caricare roba da qui 34 00:02:28,560 --> 00:02:30,950 effettivamente presentare le serie di problemi. 35 00:02:30,950 --> 00:02:34,100 Ma dire che non si ha accesso al vostro apparecchio. 36 00:02:34,100 --> 00:02:37,910 Poi si può fare le cose, come qui si dirà - 37 00:02:37,910 --> 00:02:42,160 Questo è solo la nostra sezione di domande. 38 00:02:42,160 --> 00:02:45,070 Ti verrà chiesto di farlo in dell'apparecchio. 39 00:02:45,070 --> 00:02:47,790 Invece mi limiterò a fare sul server. 40 00:02:47,790 --> 00:02:50,560 Io vado a decomprimere questo. 41 00:02:50,560 --> 00:02:55,670 Il problema sarà che siete abituati ad usare qualcosa di simile a gedit 42 00:02:55,670 --> 00:02:58,160 o qualunque interno dell'apparecchio. 43 00:02:58,160 --> 00:03:01,830 Tu non stai andando ad avere che sul server FAS. 44 00:03:01,830 --> 00:03:04,110 E 'tutto solo sarà questa interfaccia testuale. 45 00:03:04,110 --> 00:03:09,180 Così si potrebbe uno dei due, cercare di imparare un editor di testo che essi hanno. 46 00:03:09,180 --> 00:03:12,130 Hanno Nano. 47 00:03:12,130 --> 00:03:14,990 Nano di solito è abbastanza facile da usare. 48 00:03:14,990 --> 00:03:19,470 È possibile utilizzare le frecce e digitare normalmente. 49 00:03:19,470 --> 00:03:21,250 In modo che non è difficile. 50 00:03:21,250 --> 00:03:24,720 Se si vuole ottenere davvero fantasia si può usare Emacs, 51 00:03:24,720 --> 00:03:29,850 che probabilmente non avrebbe dovuto avviare, perché io non so nemmeno come chiudere Emacs. 52 00:03:29,850 --> 00:03:32,760 Controllo X, Controllo C? Gia '. 53 00:03:32,760 --> 00:03:35,310 Oppure si può usare Vim, che è quello che uso. 54 00:03:35,310 --> 00:03:37,800 E così quelli che sono le vostre opzioni. 55 00:03:37,800 --> 00:03:43,830 Se non si vuole fare questo, si può anche, se si guarda al manual.cs50.net-- 56 00:03:43,830 --> 00:03:45,410 Oh. 57 00:03:45,410 --> 00:03:49,920 Su un PC, è possibile utilizzare SSH PuTTY, 58 00:03:49,920 --> 00:03:51,940 che si sta andando ad avere per scaricare separatamente. 59 00:03:51,940 --> 00:03:55,460 Su un Mac, si può solo da terminale predefinito l'uso o è possibile scaricare iTerm2, 60 00:03:55,460 --> 00:03:58,490 che è come un bel terminale fantasia. 61 00:03:58,490 --> 00:04:03,780 Se andate a manual.cs50.net vedrai un link per Notepad + +, 62 00:04:03,780 --> 00:04:07,120 che è quello che si può usare su un PC. 63 00:04:07,120 --> 00:04:13,340 Esso consente di SFTP da Notepad + +, che è fondamentalmente SSH. 64 00:04:13,340 --> 00:04:17,750 Ciò vi permetterà di fare è modificare i file in locale, 65 00:04:17,750 --> 00:04:20,670 e poi ogni volta che si desidera salvare loro, sarà salvare nice.fas, 66 00:04:20,670 --> 00:04:23,670 dove si può poi eseguire. 67 00:04:23,670 --> 00:04:26,880 E l'equivalente per Mac sta per essere TextWrangler. 68 00:04:26,880 --> 00:04:28,760 Quindi ti permette di fare la stessa cosa. 69 00:04:28,760 --> 00:04:32,800 Ti permette di modificare i file in locale e salvarli nice.fas, 70 00:04:32,800 --> 00:04:35,730 dove si può poi eseguire. 71 00:04:35,730 --> 00:04:40,400 Quindi, se siete mai bloccati senza un apparecchio, ci sono queste opzioni 72 00:04:40,400 --> 00:04:44,230 a fare ancora le serie di problemi. 73 00:04:44,230 --> 00:04:48,250 L'unico problema sarà che non si sta andando ad avere la libreria CS50 74 00:04:48,250 --> 00:04:51,580 nice.fas perché non ha che per impostazione predefinita. 75 00:04:51,580 --> 00:04:55,970 È possibile scaricare la libreria CS50 - 76 00:04:55,970 --> 00:04:58,470 Io non credo di aver bisogno che a questo punto. 77 00:04:58,470 --> 00:05:03,270 È possibile scaricare la libreria CS50 e copiarlo nel nice.fas, 78 00:05:03,270 --> 00:05:07,450 o credo che a questo punto non ne fanno uso più comunque. 79 00:05:07,450 --> 00:05:12,720 Oppure, se lo facciamo, è possibile per il momento non viene sostituito da 80 00:05:12,720 --> 00:05:18,480 le implementazioni delle funzioni della libreria CS50 comunque. 81 00:05:18,480 --> 00:05:21,370 In modo che non dovrebbe essere molto più di una restrizione. 82 00:05:21,370 --> 00:05:23,710 E questo è tutto. 83 00:05:26,460 --> 00:05:29,820 >> Torno alla macchina ora, faremo tutto l'apparecchio. 84 00:05:29,820 --> 00:05:37,510 Guardando la nostra sezione di domande, all'inizio, come ho detto nella mia e-mail, 85 00:05:37,510 --> 00:05:43,620 dobbiamo parlare di quello corto si dovevano guardare. 86 00:05:43,620 --> 00:05:51,980 Abbiamo il riorientamento & Tubi e queste tre domande. 87 00:05:51,980 --> 00:05:56,070 >> Per quale flusso non funzioni come printf scrivere di default? 88 00:05:56,070 --> 00:05:59,130 Così flusso. Che cosa è un flusso? 89 00:06:06,520 --> 00:06:15,100 Un flusso è fondamentalmente come è solo un po '- 90 00:06:15,100 --> 00:06:21,450 Non è nemmeno una fonte di 1 e 0. 91 00:06:21,450 --> 00:06:24,920 Il flusso è chiedere qui è fuori standard. 92 00:06:24,920 --> 00:06:27,250 E in modo standard è un torrente che quando si vada a scrivere, 93 00:06:27,250 --> 00:06:30,940 appare sullo schermo. 94 00:06:30,940 --> 00:06:36,860 Fuori standard, dal torrente, vuol dire che basta scrivere 1 e 0 ad esso, 95 00:06:36,860 --> 00:06:40,220 e l'altra estremità out standard legge semplicemente da tale flusso. 96 00:06:40,220 --> 00:06:43,540 E 'solo una serie di 1 e 0. 97 00:06:43,540 --> 00:06:45,570 È possibile scrivere nei flussi o si può leggere dai flussi 98 00:06:45,570 --> 00:06:47,950 seconda di ciò che il flusso è in realtà. 99 00:06:47,950 --> 00:06:52,800 Gli altri due flussi predefiniti sono standard e standard error. 100 00:06:52,800 --> 00:06:57,540 È standard in ogni volta che si fa GetString, è in attesa di cose ingresso. 101 00:06:57,540 --> 00:07:01,570 Così è in attesa per voi, in realtà è in attesa di standard, 102 00:07:01,570 --> 00:07:04,880 che è davvero quello che si ottiene quando si digita sulla tastiera. 103 00:07:04,880 --> 00:07:07,530 Stai scrivendo in standard da 104 00:07:07,530 --> 00:07:10,050 Errore standard è sostanzialmente equivalente a fuori standard, 105 00:07:10,050 --> 00:07:13,280 ma è specializzata in che quando si stampa su standard error, 106 00:07:13,280 --> 00:07:16,770 si suppone di stampare solo i messaggi di errore a quella 107 00:07:16,770 --> 00:07:20,200 in modo da poter distinguere tra messaggi normali visualizzati sullo schermo 108 00:07:20,200 --> 00:07:24,560 contro i messaggi di errore a seconda che sono andati a fuori standard o errore standard. 109 00:07:24,560 --> 00:07:28,660 File troppo. 110 00:07:28,660 --> 00:07:32,440 Fuori standard, standard, e lo standard error sono flussi solo speciali, 111 00:07:32,440 --> 00:07:36,810 ma in realtà qualsiasi tipo di file, quando si apre un file, diventa un flusso di byte 112 00:07:36,810 --> 00:07:40,740 dove si può solo leggere da tale flusso. 113 00:07:40,740 --> 00:07:47,770 Ti, per la maggior parte, può solo pensare di un file come un flusso di byte. 114 00:07:47,770 --> 00:07:51,190 Quindi, ciò che i flussi si scrivono per default? Fuori standard. 115 00:07:51,190 --> 00:07:56,980 >> Qual è la differenza tra> e >>? 116 00:07:58,140 --> 00:08:03,710 Qualcuno guarda il video in anticipo? Va bene. 117 00:08:03,710 --> 00:08:10,960 > Sta per essere come si reindirizza in file, 118 00:08:10,960 --> 00:08:15,240 e >> è anche andare a reindirizzare l'output in file, 119 00:08:15,240 --> 00:08:17,820 ma è invece andare da aggiungere al file. 120 00:08:17,820 --> 00:08:23,430 Per esempio, diciamo che mi capita di avere dict proprio qui, 121 00:08:23,430 --> 00:08:27,020 e la roba solo all'interno di dict è il gatto, gatto, cane, pesce, cane. 122 00:08:27,020 --> 00:08:31,530 Un comando che permette di avere a riga di comando è cat, 123 00:08:31,530 --> 00:08:34,539 che è solo andare a stampare il contenuto di un file. 124 00:08:34,539 --> 00:08:40,679 Quindi, quando dico dict gatto, sta andando per la stampa gatto, gatto, cane, pesce, cane. Questo è tutto cat fa. 125 00:08:40,679 --> 00:08:46,280 Ciò significa che è stampato sullo standard output gatto, gatto, cane, pesce, cane. 126 00:08:46,280 --> 00:08:53,240 Se invece desidera reindirizzare che a un file, posso usare> e destinarli a tutto ciò che il file è. 127 00:08:53,240 --> 00:08:56,460 Chiamo il file file. 128 00:08:56,460 --> 00:09:00,320 Così ora se I ls, vedrò ho un nuovo file chiamato file. 129 00:09:00,320 --> 00:09:05,700 E se aprirlo, che sta per avere esattamente quello che gatti, condizionati dalla riga di comando. 130 00:09:05,700 --> 00:09:11,040 Così ora se lo faccio di nuovo, poi va a reindirizzare l'output in file, 131 00:09:11,040 --> 00:09:13,930 e ho intenzione di avere la stessa cosa esatta. 132 00:09:13,930 --> 00:09:17,910 Tecnicamente, quindi, completamente calpestato quello che abbiamo avuto. 133 00:09:17,910 --> 00:09:22,970 E vedremo se cambio dict, ho tirato fuori il cane. 134 00:09:22,970 --> 00:09:29,980 Ora, se gatto dict in file di nuovo, stiamo per avere la nuova versione con il cane rimosso. 135 00:09:29,980 --> 00:09:32,400 Quindi sostituisce completamente. 136 00:09:32,400 --> 00:09:36,640 Al contrario, se usiamo >>, che sta per aggiungere file. 137 00:09:36,640 --> 00:09:40,860 Ora, l'apertura del file, si vede che abbiamo proprio la stessa cosa stampato due volte 138 00:09:40,860 --> 00:09:44,920 perché era una volta, poi allegata all'originale. 139 00:09:44,920 --> 00:09:48,130 Quindi questo è quello che> e >> fare. 140 00:09:48,130 --> 00:09:50,580 L'prossima chiedere - Non chiedere al riguardo. 141 00:09:50,580 --> 00:09:59,050 >> L'altra che abbiamo è <, che se> reindirizza fuori standard, 142 00:09:59,050 --> 00:10:01,970 00:10:12,050 Vediamo se abbiamo un esempio. 144 00:10:14,750 --> 00:10:16,930 Riesco a scrivere un rapido reale. 145 00:10:17,870 --> 00:10:25,700 Prendiamo un qualsiasi file, hello.c. 146 00:10:56,060 --> 00:10:59,070 File di relativamente semplice. 147 00:10:59,070 --> 00:11:03,570 Sto solo prendendo una stringa e quindi la stampa "Ciao", qualunque sia la stringa che era appena entrato. 148 00:11:03,570 --> 00:11:07,990 Quindi, fare ciao e poi. / Ciao. 149 00:11:07,990 --> 00:11:10,720 Ora mi chiede di inserire qualcosa, 150 00:11:10,720 --> 00:11:15,070 che significa che è in attesa di cose da inserire in standard da 151 00:11:15,070 --> 00:11:20,450 Quindi quello che voglio entrare in standard trovi Stiamo solo andando a dire Ciao, Rob! 152 00:11:20,450 --> 00:11:23,310 Poi è la stampa sullo standard output Ciao, Rob! 153 00:11:23,310 --> 00:11:28,860 Se lo faccio. / Ciao e quindi reindirizzare, 154 00:11:30,740 --> 00:11:34,310 per ora si può solo reindirizzare da un file. 155 00:11:34,310 --> 00:11:41,720 Quindi, se ho messo in qualche file, txt, e ho messo Rob, 156 00:11:41,720 --> 00:11:52,300 se corro ciao e quindi reindirizzare il file txt in. / ciao, sta andando a dire Ciao, Rob! immediatamente. 157 00:11:52,300 --> 00:11:57,160 Quando si arriva per primo GetString ed è in attesa di standard, 158 00:11:57,160 --> 00:12:01,730 standard non è più in attesa sulla tastiera per ottenere dati inseriti. 159 00:12:01,730 --> 00:12:05,980 Invece, abbiamo reindirizzato standard per leggere dal file txt. 160 00:12:05,980 --> 00:12:10,290 E così sta andando a leggere dal file txt, che è solo la linea di Rob, 161 00:12:10,290 --> 00:12:13,380 e poi è andato in stampa Ciao, Rob! 162 00:12:13,380 --> 00:12:18,180 E se avessi voluto, avrei potuto anche fare. / Ciao 00:12:21,500 e poi lo standard che si tratta di stampa, che è Ciao, Rob!, 164 00:12:21,500 --> 00:12:24,700 Posso reindirizzare che nel proprio file. 165 00:12:24,700 --> 00:12:29,790 Mi limiterò a chiamare il file ciao - no, non lo farò, perché questo è il file eseguibile - txt2. 166 00:12:29,790 --> 00:12:40,150 Ora, txt2 sta per avere l'output di. / Ciao 00:12:43,520 >> Domande? 168 00:12:45,900 --> 00:12:49,090 >> Va bene. Allora qui abbiamo pipeline. 169 00:12:49,090 --> 00:12:53,510 I tubi sono l'ultima unità di reindirizzamento. 170 00:12:53,510 --> 00:12:58,750 >> Oh. Credo che una unità in più di reindirizzamento è se invece di> fare 2>, 171 00:12:58,750 --> 00:13:01,070 che sta reindirizzando errore standard. 172 00:13:01,070 --> 00:13:06,280 Quindi, se qualcosa è andato a standard error, che non si sarebbe messo in txt2. 173 00:13:06,280 --> 00:13:12,480 Ma bando se lo faccio 2>, quindi è ancora la stampa Ciao, Rob! alla riga di comando 174 00:13:12,480 --> 00:13:18,600 perché io sono solo il reindirizzamento errore standard, non sto reindirizzando standard output. 175 00:13:18,600 --> 00:13:22,210 Errore standard e fuori standard sono diversi. 176 00:13:24,210 --> 00:13:27,080 Se si voleva scrivere effettivamente errore standard, 177 00:13:27,080 --> 00:13:35,080 quindi ho potuto cambiare questo sia fprintf per stderr. 178 00:13:35,080 --> 00:13:37,850 Così printf, per impostazione predefinita, viene stampato fuori standard. 179 00:13:37,850 --> 00:13:41,720 Se voglio stampare su standard error manualmente, quindi devo usare fprintf 180 00:13:41,720 --> 00:13:45,010 e specificare quello che voglio stampare. 181 00:13:45,010 --> 00:13:49,720 Se invece ho fatto fprintf stdout, allora questo è sostanzialmente equivalente a printf. 182 00:13:49,720 --> 00:13:55,530 Ma fprintf standard error. 183 00:13:57,790 --> 00:14:03,650 Così ora, se mi reindirizzare questo in txt2, Ciao, Rob! è ancora ottenere stampato nella riga di comando 184 00:14:03,650 --> 00:14:08,270 dal momento che è ottenere stampato errore standard e sono solo il reindirizzamento standard output. 185 00:14:08,270 --> 00:14:16,420 Se ora ridirige lo standard error, ora non vengono stampati, e txt2 sarà Ciao, Rob! 186 00:14:16,420 --> 00:14:21,910 Così ora, è possibile stampare i vostri errori effettivi standard error 187 00:14:21,910 --> 00:14:24,720 e stampare i messaggi regolari fuori standard. 188 00:14:24,720 --> 00:14:31,420 E così, quando si esegue il programma, è possibile eseguirlo come. / Ciao questo tipo con il 2> 189 00:14:31,420 --> 00:14:33,800 in modo che il programma sta andando a funzionare normalmente, 190 00:14:33,800 --> 00:14:38,400 ma gli eventuali messaggi di errore che si ottiene è possibile controllare più avanti nel log degli errori, 191 00:14:38,400 --> 00:14:44,500 così gli errori e poi guardare più tardi e il file errori avrà eventuali errori che sono successe. 192 00:14:45,200 --> 00:14:47,540 >> Domande? 193 00:14:47,540 --> 00:14:58,070 >> L'ultimo è del tubo, che si può pensare come prendere standard fuori da un comando 194 00:14:58,070 --> 00:15:01,210 e che lo rende lo standard in del comando successivo. 195 00:15:01,210 --> 00:15:05,570 Un esempio qui è eco è una cosa riga di comando 196 00:15:05,570 --> 00:15:11,840 che è solo andare a eco ciò che ho messo come argomento. Non voglio mettere le virgolette. 197 00:15:11,840 --> 00:15:16,150 Echo bla, bla, bla è solo andare a stampare bla, bla, bla. 198 00:15:16,150 --> 00:15:20,600 Prima, quando ho detto che ho dovuto mettere Rob in un file txt 199 00:15:20,600 --> 00:15:28,830 perché posso solo reindirizzare i file txt, invece, / se io eco Rob 200 00:15:28,830 --> 00:15:35,520 e poi tubo in esso. / ciao, che farà anche lo stesso tipo di cosa. 201 00:15:35,520 --> 00:15:39,160 Questo sta prendendo l'output di questo comando, echo Rob, 202 00:15:39,160 --> 00:15:43,610 e usarlo come input per. / ciao. 203 00:15:44,790 --> 00:15:49,560 Si può pensare ad esso come primo redirect eco Rob in un file 204 00:15:49,560 --> 00:15:54,160 e poi ingresso in. / ciao il file che è stato appena emesso. 205 00:15:54,160 --> 00:15:57,850 Ma ci vuole il file temporaneo fuori dal quadro. 206 00:16:01,890 --> 00:16:04,460 >> Domande su questo? 207 00:16:04,460 --> 00:16:07,150 >> La domanda successiva sta per coinvolgere questo. 208 00:16:07,150 --> 00:16:15,310 Cosa gasdotto potrebbe utilizzare per trovare il numero di nomi univoci in un file chiamato names.txt? 209 00:16:15,310 --> 00:16:24,160 I comandi che andremo a voler usare qui sono unici, così uniq, e wc. 210 00:16:24,160 --> 00:16:28,840 Si può fare uniq l'uomo a guardare effettivamente a ciò che fa, 211 00:16:28,840 --> 00:16:34,840 ed è solo andando a filtrare adiacenti righe corrispondenti dall'ingresso. 212 00:16:34,840 --> 00:16:40,690 E l'uomo wc sta per stampare la nuova riga, parola, e il numero di byte per ogni file. 213 00:16:40,690 --> 00:16:43,760 E l'ultimo che stiamo andando a voler utilizzare è sorta, 214 00:16:43,760 --> 00:16:47,410 che sta per ordinare solo righe di file txt. 215 00:16:47,410 --> 00:16:58,080 Se faccio un po 'di file txt, names.txt, ed è Rob, Tommy, Joseph, Tommy, Joseph, RJ, Rob, 216 00:16:58,080 --> 00:17:03,910 quello che voglio fare è trovare il numero di nomi univoci in questo file. 217 00:17:03,910 --> 00:17:08,750 Quindi, quello che dovrebbe essere la risposta? >> [Studente] 4. Sì >>. 218 00:17:08,750 --> 00:17:13,780 Dovrebbe essere 4 da Rob, Tommy, Joseph, RJ sono i nomi univoci solo in questo file. 219 00:17:13,780 --> 00:17:20,180 Il primo passo, se mi limito a fare il conteggio delle parole names.txt, 220 00:17:20,180 --> 00:17:24,290 questo è in realtà mi sta dicendo tutto. 221 00:17:24,290 --> 00:17:32,560 Questo è in realtà la stampa - Vediamo un po ', man wc - newline, parole e numero di byte. 222 00:17:32,560 --> 00:17:38,270 Se mi interessa solo le linee, allora posso solo fare wc-l names.txt. 223 00:17:41,730 --> 00:17:44,300 Così che è passaggio 1. 224 00:17:44,300 --> 00:17:50,510 Ma io non voglio wc-l names.txt names.txt perché contiene solo tutti i nomi, 225 00:17:50,510 --> 00:17:54,170 e voglio filtrare alcun quelli non univoci. 226 00:17:54,170 --> 00:18:01,200 Quindi, se faccio names.txt uniq, che non tutto mi dà quello che voglio 227 00:18:01,200 --> 00:18:03,760 perché i nomi duplicati sono ancora lì. 228 00:18:03,760 --> 00:18:07,690 Perché è così? Perché non uniq fare ciò che voglio? 229 00:18:07,690 --> 00:18:10,500 [Studente] I duplicati non sono [incomprensibile] >> Si '. 230 00:18:10,500 --> 00:18:16,370 Ricordate la pagina di manuale di uniq dice filtri corrispondenti linee adiacenti. 231 00:18:16,370 --> 00:18:19,680 Non sono adiacenti, in modo che non li filtra. 232 00:18:19,680 --> 00:18:31,100 Se ordinarli prima names.txt ordinamento sta per mettere tutte le linee duplicate insieme. 233 00:18:31,100 --> 00:18:34,450 Così ora names.txt tipo è che. 234 00:18:34,450 --> 00:18:40,550 Ho intenzione di voler utilizzare tale come input per uniq, che è | uniq. 235 00:18:40,550 --> 00:18:43,390 Questo mi dà Giuseppe, RJ, Rob, Tommy, 236 00:18:43,390 --> 00:18:49,260 e voglio utilizzarlo come input per wc-l, 237 00:18:49,260 --> 00:18:52,740 che sta per darmi 4. 238 00:18:52,740 --> 00:18:56,930 Come si dice qui, che cosa gasdotto potrebbe usare? 239 00:18:56,930 --> 00:19:01,390 Si può fare un sacco di cose come l'utilizzo di una serie di comandi 240 00:19:01,390 --> 00:19:05,130 in cui si utilizza l'output di un comando come input per il comando successivo. 241 00:19:05,130 --> 00:19:08,780 Si può fare un sacco di cose, un sacco di cose intelligenti. 242 00:19:08,780 --> 00:19:11,440 >> Domande? 243 00:19:12,910 --> 00:19:14,600 Va bene. 244 00:19:14,600 --> 00:19:17,880 Questo è tutto per tubi e reindirizzamento. 245 00:19:18,370 --> 00:19:24,090 >> Ora andiamo al roba vera, la roba di codifica. 246 00:19:24,090 --> 00:19:29,100 All'interno di questo PDF, vedrete questo comando, 247 00:19:29,100 --> 00:19:32,950 e ti consigliamo di eseguire questo comando nel vostro apparecchio. 248 00:19:36,240 --> 00:19:42,250 wget è il comando solo per ottenere qualcosa da Internet, in fondo, 249 00:19:42,250 --> 00:19:45,180 così wget e questo URL. 250 00:19:45,180 --> 00:19:49,110 Se si è andato a questo URL nel browser, sarebbe scaricare il file. 251 00:19:49,110 --> 00:19:52,510 Ho appena cliccato su di esso, in modo che il file scaricato per me. 252 00:19:52,510 --> 00:19:55,650 Ma scrivere wget di quella cosa all'interno del terminale 253 00:19:55,650 --> 00:19:58,620 è solo andare a scaricarlo nel vostro terminale. 254 00:19:58,620 --> 00:20:02,750 Ho section5.zip, e ti consigliamo di decomprimere section5.zip, 255 00:20:02,750 --> 00:20:06,520 che sta per darvi una cartella denominata section5, 256 00:20:06,520 --> 00:20:11,550 che sta per avere tutti i file che andremo a utilizzare oggi all'interno di esso. 257 00:20:33,380 --> 00:20:37,710 Poiché i nomi dei file di questi programmi suggeriscono, sono un po 'buggy, 258 00:20:37,710 --> 00:20:40,990 così la vostra missione è quella di capire perché con gdb. 259 00:20:40,990 --> 00:20:44,560 Ha tutti li hanno scaricato / sa come farli scaricare 260 00:20:44,560 --> 00:20:47,480 nel loro apparecchio? Va bene. 261 00:20:47,480 --> 00:20:56,400 >> Correre ./buggy1, si dirà Segmentation fault (core dumped), 262 00:20:56,400 --> 00:21:00,500 che ogni volta che si ottiene un segmentation fault, è una brutta cosa. 263 00:21:00,500 --> 00:21:03,810 In quali circostanze si ottiene un segfault? 264 00:21:03,810 --> 00:21:08,210 [Studente] Dereferenziare un puntatore nullo. Sì >>. Così che è un esempio. 265 00:21:08,210 --> 00:21:11,580 Dereferenziare un puntatore nullo che si vuole ottenere un segfault. 266 00:21:11,580 --> 00:21:16,720 Che segfault significa che stai toccando la memoria non si deve toccare. 267 00:21:16,720 --> 00:21:21,350 Così dereference un puntatore nullo sta toccando l'indirizzo 0, 268 00:21:21,350 --> 00:21:28,060 e in fondo, tutti i computer al giorno d'oggi dire che 0 è l'indirizzo di memoria non si deve toccare. 269 00:21:28,060 --> 00:21:31,920 Ecco perché dereferenziazione un risultato puntatore null in un segfault. 270 00:21:31,920 --> 00:21:37,210 Quando vi capita di non inizializzare un puntatore, allora ha un valore di spazzatura, 271 00:21:37,210 --> 00:21:41,520 e così quando si tenta di dereferenziarlo, con ogni probabilità si sta toccando la memoria 272 00:21:41,520 --> 00:21:43,540 che è in mezzo al nulla. 273 00:21:43,540 --> 00:21:45,650 Se vi capita di avere fortuna e il valore dei rifiuti 274 00:21:45,650 --> 00:21:48,440 successo per puntare da qualche parte sullo stack o qualcosa del genere, 275 00:21:48,440 --> 00:21:50,820 poi quando si dereference quel puntatore che non si è inizializzato, 276 00:21:50,820 --> 00:21:52,730 nulla vada storto. 277 00:21:52,730 --> 00:21:55,480 Ma se sta puntando, per esempio, da qualche parte tra lo stack e l'heap, 278 00:21:55,480 --> 00:21:59,850 o è solo per indicare da qualche parte che non è stata utilizzata dal programma ancora, 279 00:21:59,850 --> 00:22:02,240 allora stai toccando la memoria non si deve toccare e segfault. 280 00:22:02,240 --> 00:22:06,370 Quando si scrive una funzione ricorsiva e ricorsiva troppe volte 281 00:22:06,370 --> 00:22:08,720 e il vostro stack diventa troppo grande e si scontra pila in cose 282 00:22:08,720 --> 00:22:12,270 che non dovrebbe essere in collisione con, stai toccando la memoria non si deve toccare, 283 00:22:12,270 --> 00:22:14,810 in modo da segfault. 284 00:22:14,810 --> 00:22:17,010 Questo è ciò che è un segfault. 285 00:22:17,010 --> 00:22:21,810 >> E 'anche lo stesso motivo che, se si dispone di una stringa come - 286 00:22:21,810 --> 00:22:23,930 torniamo al programma precedente. 287 00:22:23,930 --> 00:22:28,530 In hello.c--Sto solo andando a fare qualcosa d'altro. 288 00:22:28,530 --> 00:22:33,770 char * s = "ciao mondo!"; 289 00:22:33,770 --> 00:22:42,310 Se uso * s = qualcosa o s [0] = 'X'; 290 00:22:42,310 --> 00:22:47,290 in modo da rendere ciao,. / ciao, perché che segfault? 291 00:22:48,410 --> 00:22:51,250 Perché questo segfault? 292 00:22:55,660 --> 00:22:57,890 Che cosa vi aspettate che succeda? 293 00:22:57,890 --> 00:23:06,640 Se ho fatto printf ("% s \ n", s); ci si può aspettare da stampare? 294 00:23:06,640 --> 00:23:09,930 [Studente] X ciao. Sì >>. 295 00:23:09,930 --> 00:23:15,140 Il problema è che quando si dichiara una stringa come questa, 296 00:23:15,140 --> 00:23:18,190 s è un puntatore che sta per andare in pila, 297 00:23:18,190 --> 00:23:25,880 e ciò s punta a questa stringa è contenuta in memoria di sola lettura. 298 00:23:25,880 --> 00:23:30,560 Quindi, solo per il nome, memoria di sola lettura, si dovrebbe ottenere l'idea 299 00:23:30,560 --> 00:23:33,010 che se si tenta di modificare ciò che è in memoria di sola lettura, 300 00:23:33,010 --> 00:23:36,670 si sta facendo qualcosa che non dovrebbe fare con la memoria e si segfault. 301 00:23:36,670 --> 00:23:45,360 Questo è in realtà una grande differenza tra char * s e char s []. 302 00:23:45,360 --> 00:23:48,790 Così char s [], ora questa stringa sta per essere messa in pila, 303 00:23:48,790 --> 00:23:53,960 e lo stack non è di sola lettura, il che significa che questo dovrebbe funzionare perfettamente. 304 00:23:55,500 --> 00:23:57,370 E lo fa. 305 00:23:57,370 --> 00:24:06,250 Ricordate che quando faccio char * s = "ciao mondo!", S è di per sé in pila 306 00:24:06,250 --> 00:24:10,390 ma i punti s per qualche altra parte, e che da qualche altra parte sembra essere di sola lettura. 307 00:24:10,390 --> 00:24:15,640 Ma char s [] è solo qualcosa in pila. 308 00:24:17,560 --> 00:24:21,760 Ecco, questo è un altro esempio di un segfault accadendo. 309 00:24:21,760 --> 00:24:27,820 >> Abbiamo visto che ./buggy1 provocato un segfault. 310 00:24:27,820 --> 00:24:31,810 In teoria, non si dovrebbe guardare buggy1.c immediatamente. 311 00:24:31,810 --> 00:24:35,170 Invece, vedremo attraverso gdb. 312 00:24:35,170 --> 00:24:37,750 Si noti che quando si arriva Segmentation fault (core dumped), 313 00:24:37,750 --> 00:24:40,850 si ottiene il file sopra il centro qui chiamato. 314 00:24:40,850 --> 00:24:45,200 Se ls-l, vedremo che il nucleo di solito è un file abbastanza grande. 315 00:24:45,200 --> 00:24:51,580 Questo è il numero di byte del file, in modo che appaia come se fosse qualcosa da 250 kilobyte. 316 00:24:51,580 --> 00:24:56,120 La ragione di questo è che cosa il core dump è effettivamente 317 00:24:56,120 --> 00:25:01,410 è quando il programma va in crash, lo stato della memoria del programma 318 00:25:01,410 --> 00:25:05,230 viene semplicemente copiato e incollato in questo file. 319 00:25:05,230 --> 00:25:07,270 Essa viene scaricato in quel file. 320 00:25:07,270 --> 00:25:13,060 Questo programma, mentre era in esecuzione, è capitato di avere un utilizzo di memoria di circa 250 kilobyte, 321 00:25:13,060 --> 00:25:17,040 e così questo è quello che ho scaricato in questo file. 322 00:25:17,040 --> 00:25:23,630 Ora si può guardare a quel file, se facciamo gdb nucleo buggy1. 323 00:25:23,630 --> 00:25:30,130 Possiamo solo fare gdb buggy1, e che semplicemente avviare gdb regolarmente, 324 00:25:30,130 --> 00:25:33,800 utilizzando buggy1 come file di input. 325 00:25:33,800 --> 00:25:38,260 Ma se lo fai gdb nucleo buggy1, allora è specificamente sta per avviare gdb 326 00:25:38,260 --> 00:25:40,330 cercando in quel file core. 327 00:25:40,330 --> 00:25:45,560 E dicendo buggy1 gdb significa sa che il file principale viene dal programma buggy1. 328 00:25:45,560 --> 00:25:49,580 Così gdb buggy1 nucleo sta per portarci subito 329 00:25:49,580 --> 00:25:52,060 al punto in cui il programma è successo a terminare. 330 00:25:57,720 --> 00:26:02,340 Vediamo qui Programma terminato con segnale 11, Segmentation fault. 331 00:26:02,340 --> 00:26:10,110 Ci capita di vedere una linea di montaggio, che probabilmente non è molto utile. 332 00:26:10,110 --> 00:26:15,360 Ma se si digita bt o backtrace, che sta per essere la funzione 333 00:26:15,360 --> 00:26:19,430 che ci dà la lista dei nostri stack frame corrente. 334 00:26:19,430 --> 00:26:23,150 Così backtrace. Sembra che abbiamo solo due stack frame. 335 00:26:23,150 --> 00:26:26,310 Il primo è il nostro stack frame principale, 336 00:26:26,310 --> 00:26:29,810 e il secondo è la stack frame per questa funzione che ci capita di essere in, 337 00:26:29,810 --> 00:26:34,440 che sembra non ci resta che il codice assembly per. 338 00:26:34,440 --> 00:26:38,050 Quindi cerchiamo di tornare nella nostra funzione principale, 339 00:26:38,050 --> 00:26:42,300 e per fare ciò che possiamo fare frame 1, e penso che possiamo anche fare verso il basso, 340 00:26:42,300 --> 00:26:45,160 ma io quasi mai verso il basso - o verso l'alto. Gia '. 341 00:26:45,160 --> 00:26:50,710 Su e giù. Porta in primo piano in su uno stack frame, giù ti porta giù uno stack frame. 342 00:26:50,710 --> 00:26:53,240 Io tendo ad usare mai che. 343 00:26:53,240 --> 00:26:59,120 Ho appena specificamente dire telaio 1, che è andare al fotogramma 1. 344 00:26:59,120 --> 00:27:01,750 Fotogramma 1 sta per portarci in stack frame principale, 345 00:27:01,750 --> 00:27:05,570 e si dice che proprio qui la riga di codice ci capita di essere a. 346 00:27:05,570 --> 00:27:07,950 Se volevamo un altro paio di righe di codice, possiamo dire elenco, 347 00:27:07,950 --> 00:27:11,280 e questo ci darà tutte le righe di codice che lo circondano. 348 00:27:11,280 --> 00:27:13,360 La linea che era segfaulted a 6: 349 00:27:13,360 --> 00:27:17,360 if (strcmp ("CS50 rocce", argv [1]) == 0). 350 00:27:17,360 --> 00:27:24,130 Se non è ancora chiaro, si può ottenere direttamente da qui semplicemente pensando perché segfaulted. 351 00:27:24,130 --> 00:27:28,800 Ma possiamo fare un ulteriore passo avanti e dire: "Perché argv [1] segfault?" 352 00:27:28,800 --> 00:27:38,830 Stampa Facciamo argv [1], e sembra come se fosse 0x0, che è il puntatore nullo. 353 00:27:38,830 --> 00:27:44,750 Stiamo strcmping CS50 rocce e nulli, e così che sta andando a segfault. 354 00:27:44,750 --> 00:27:48,280 E perché è argv [1] null? 355 00:27:48,640 --> 00:27:51,280 [Studente] Perché non le ha dato della riga di comando argomenti. 356 00:27:51,280 --> 00:27:53,390 Gia '. Non l'abbiamo dato nessun comando argomenti della riga. 357 00:27:53,390 --> 00:27:58,460 Così ./buggy1 è solo andare per avere argv [0] è ./buggy1. 358 00:27:58,460 --> 00:28:02,100 E non ha intenzione di avere un argv [1], in modo che sta per segfault. 359 00:28:02,100 --> 00:28:07,450 Ma se, invece, lo faccio solo CS50, è andare a dire È possibile ottenere una D 360 00:28:07,450 --> 00:28:09,950 perché questo è quello che dovrebbe fare. 361 00:28:09,950 --> 00:28:15,240 Guardando buggy1.c, si suppone di stampa "Si ottiene una D" - 362 00:28:15,240 --> 00:28:20,820 Se argv [1] non è "CS50 rocce", "Si ottiene una D", altrimenti "Si ottiene una A!" 363 00:28:20,820 --> 00:28:25,660 Quindi, se vogliamo una A, abbiamo bisogno di questo per confrontare come vero, 364 00:28:25,660 --> 00:28:28,710 il che significa che paragona a 0. 365 00:28:28,710 --> 00:28:31,100 Quindi, argv [1], deve essere "CS50 rocce". 366 00:28:31,100 --> 00:28:35,660 Se si vuole fare che sulla riga di comando, è necessario utilizzare \ per sfuggire allo spazio. 367 00:28:35,660 --> 00:28:41,690 Così CS50 \ rocce e si ottiene una A! 368 00:28:41,690 --> 00:28:44,060 Se non si esegue la barra rovesciata, perché non questo lavoro? 369 00:28:44,060 --> 00:28:47,190 [Studente] Sono due argomenti diversi. Sì >>. 370 00:28:47,190 --> 00:28:52,540 Argv [1] sta per essere CS50, e argv [2] sarà rocce. Va bene. 371 00:28:52,540 --> 00:28:56,470 >> Ora ./buggy2 sta per segfault di nuovo. 372 00:28:56,470 --> 00:29:01,880 Invece di aprire con il suo file core, dobbiamo solo aprire buggy2 direttamente, 373 00:29:01,880 --> 00:29:05,000 così gdb buggy2. 374 00:29:05,000 --> 00:29:09,590 Ora, se basta eseguire il nostro programma, quindi sta andando a dire Programma segnale ricevuto SIGSEGV, 375 00:29:09,590 --> 00:29:15,530 che è il segfault segnale, ed è qui che è successo a succedere. 376 00:29:15,530 --> 00:29:21,250 Guardando alla nostra backtrace, vediamo che eravamo in oh_no funzione, 377 00:29:21,250 --> 00:29:23,900 che è stato chiamato dalla Dinky funzione, che è stato chiamato dal Binky funzione, 378 00:29:23,900 --> 00:29:26,460 che è stato chiamato da principale. 379 00:29:26,460 --> 00:29:31,680 Possiamo anche vedere gli argomenti di queste funzioni. 380 00:29:31,680 --> 00:29:34,680 L'argomento di Dinky e Binky è stato di 1. 381 00:29:34,680 --> 00:29:44,390 Se riportiamo la funzione oh_no, vediamo che oh_no sta solo facendo char ** s = NULL; 382 00:29:44,390 --> 00:29:47,410 * S = "BOOM"; 383 00:29:47,410 --> 00:29:50,330 Perchè dovrebbe fallire? 384 00:29:54,330 --> 00:29:58,380 [Studente] Non è possibile dereference il puntatore nullo? Sì >>. 385 00:29:58,380 --> 00:30:06,090 Questo è solo per dire s è NULL, indipendentemente se questo sembra essere un char **, 386 00:30:06,090 --> 00:30:12,070 che, a seconda di come lo si interpreta, potrebbe essere un puntatore a un puntatore a una stringa 387 00:30:12,070 --> 00:30:15,550 o un array di stringhe. 388 00:30:15,550 --> 00:30:21,430 E 's è NULL, per cui s * è dereference un puntatore nullo, 389 00:30:21,430 --> 00:30:24,800 e quindi questo sta andando in crash. 390 00:30:24,800 --> 00:30:27,540 Questo è uno dei modi più veloci si può eventualmente segfault. 391 00:30:27,540 --> 00:30:31,300 E 'solo che dichiara un puntatore nullo e subito va in segfault. 392 00:30:31,300 --> 00:30:34,570 Questo è ciò che sta facendo oh_no. 393 00:30:34,570 --> 00:30:43,400 Se andiamo su un fotogramma, quindi stiamo per entrare nella funzione che ha chiamato oh_no. 394 00:30:43,400 --> 00:30:44,830 Ho bisogno di fare che verso il basso. 395 00:30:44,830 --> 00:30:48,610 Se non si immette un comando e basta premere Invio di nuovo, 396 00:30:48,610 --> 00:30:52,350 sarà solo ripetere il comando precedente che è stato eseguito. 397 00:30:52,350 --> 00:30:56,610 Siamo nel frame 1. 398 00:30:56,610 --> 00:31:04,650 La vendita di questo telaio, vediamo qui è la nostra funzione. 399 00:31:04,650 --> 00:31:08,520 Si può colpire di nuovo elenco, oppure si può fare la lista 20 e verranno mostrati più. 400 00:31:08,520 --> 00:31:13,640 La funzione di dinky dice che se i è 1, quindi andare alla funzione oh_no, 401 00:31:13,640 --> 00:31:15,960 altrimenti andare alla funzione slinky. 402 00:31:15,960 --> 00:31:18,700 E sappiamo che i è 1 perché ci capita di vedere qui 403 00:31:18,700 --> 00:31:22,560 dinky che è stato chiamato con l'argomento 1. 404 00:31:22,560 --> 00:31:27,560 Oppure si può semplicemente faccio a stampare e dirà che è 1. 405 00:31:27,560 --> 00:31:33,770 Siamo attualmente in dinky, e se andiamo su un altro fotogramma, sappiamo che finirai in Binky. 406 00:31:33,770 --> 00:31:36,600 Up. Ora siamo in Binky. 407 00:31:36,600 --> 00:31:41,340 Listato questa funzione - l'elenco da prima di metà mi ha interrotto - 408 00:31:41,340 --> 00:31:52,670 ha iniziato come se i è 0, allora andremo a chiamare oh_no, altrimenti chiamare dinky. 409 00:31:52,670 --> 00:31:57,000 Sappiamo che ero 1, quindi ha chiamato dinky. 410 00:31:57,000 --> 00:32:05,030 E ora siamo di nuovo in main, e principale è solo andare a essere int i = rand ()% 3; 411 00:32:05,030 --> 00:32:08,790 Questo è solo per darvi un numero casuale che è 0, 1 o 2. 412 00:32:08,790 --> 00:32:12,780 E 'intenzione di chiamare binky con quel numero, e verrà restituito 0. 413 00:32:12,780 --> 00:32:16,700 Guardando a questo, 414 00:32:16,700 --> 00:32:19,880 solo a piedi attraverso il programma manualmente senza correre immediatamente, 415 00:32:19,880 --> 00:32:25,400 è necessario impostare un punto di interruzione alla centrale, il che significa che quando si esegue il programma 416 00:32:25,400 --> 00:32:31,020 l'esecuzione del programma fino fino a quando non colpisce un punto di rottura. 417 00:32:31,020 --> 00:32:35,450 Quindi, l'esecuzione del programma, verrà eseguito e poi colpirà la funzione principale e interrompere l'esecuzione. 418 00:32:35,450 --> 00:32:44,700 Ora siamo all'interno del principale, e il passo successivo o sta per portarci alla riga successiva di codice. 419 00:32:44,700 --> 00:32:47,050 È possibile eseguire il passaggio o successivo. 420 00:32:47,050 --> 00:32:51,800 Colpire successivo, ora mi è stato impostato su rand ()% 3, in modo da poter stampare il valore di i, 421 00:32:51,800 --> 00:32:55,280 e dirà che è 1. 422 00:32:55,280 --> 00:32:58,110 Ora non importa se usiamo o successivo passo. 423 00:32:58,110 --> 00:33:01,000 Credo che importava in quello precedente, ma ci vorrebbe usare successivo. 424 00:33:01,000 --> 00:33:06,000 Se usiamo passo, entrare dentro la funzione, il che significa che un'occhiata alla cosa reale 425 00:33:06,000 --> 00:33:07,940 che sta accadendo dentro di Binky. 426 00:33:07,940 --> 00:33:10,510 Se usiamo prossimo, significa andare oltre la funzione 427 00:33:10,510 --> 00:33:14,070 e basta andare alla riga successiva di codice nella nostra funzione principale. 428 00:33:14,070 --> 00:33:17,900 Proprio qui, su questa linea, sono stato a dove si dice rand ()% 3; 429 00:33:17,900 --> 00:33:21,320 se l'ho fatto passo, sarebbe andare in attuazione di rand 430 00:33:21,320 --> 00:33:25,110 e guardare a ciò che sta succedendo lì, e ho potuto passare attraverso la funzione rand. 431 00:33:25,110 --> 00:33:26,920 Ma non mi interessa la funzione rand. 432 00:33:26,920 --> 00:33:30,190 Voglio solo passare alla riga successiva di codice in main, per cui uso successivo. 433 00:33:30,190 --> 00:33:35,800 Ma ora mi importa la funzione Binky, quindi voglio fare un passo in quella. 434 00:33:35,800 --> 00:33:37,730 Ora sono in Binky. 435 00:33:37,730 --> 00:33:42,040 La prima riga di codice sta per dire se (i == 0), faccio un passo, 436 00:33:42,040 --> 00:33:44,930 vediamo finiamo a Dinky. 437 00:33:44,930 --> 00:33:51,620 Se noi le cose della lista, vediamo che controllare i è = 0. 438 00:33:51,620 --> 00:33:55,470 i non è uguale a 0, quindi è andato a la condizione else, 439 00:33:55,470 --> 00:33:59,540 che sta per chiamare Dinky (i). 440 00:33:59,540 --> 00:34:04,030 Si potrebbe confondersi. 441 00:34:04,030 --> 00:34:07,380 Se si basta guardare queste righe direttamente, si potrebbe pensare che se (i == 0), 442 00:34:07,380 --> 00:34:10,800 ok, allora ho fatto un passo e ora sono a Dinky (i), 443 00:34:10,800 --> 00:34:14,120 si potrebbe pensare che deve significare i = 0 o qualcosa del genere. 444 00:34:14,120 --> 00:34:18,980 No. Significa solo che sa di poter attaccare direttamente alla Dinky linea (i). 445 00:34:18,980 --> 00:34:23,300 Perché non è 0, il passo successivo non sta per finire in altro. 446 00:34:23,300 --> 00:34:26,239 Altrimenti non è una linea che sta per fermarsi a. 447 00:34:26,239 --> 00:34:31,570 E 'solo per andare alla riga successiva si può effettivamente eseguire, che è dinky (i). 448 00:34:31,570 --> 00:34:36,090 Entrare nel Dinky (i), vediamo se (i == 1). 449 00:34:36,090 --> 00:34:42,670 Ci faccio a sapere = 1, quindi quando facciamo un passo, sappiamo che stiamo andando a finire in oh_no 450 00:34:42,670 --> 00:34:46,489 perché i = 1 chiama la oh_no funzione, che si può entrare in, 451 00:34:46,489 --> 00:34:52,969 che sta per impostare char ** s = a NULL e subito "BOOM". 452 00:34:54,270 --> 00:34:59,690 E poi in realtà guardando la realizzazione di buggy2, 453 00:34:59,690 --> 00:35:04,590 questo, i è solo ottenere un numero casuale - 0, 1, o 2 - chiamata Binky, 454 00:35:04,590 --> 00:35:10,610 che se i è 0 si chiama oh_no, altrimenti chiama dinky, di cui si parla qui. 455 00:35:10,610 --> 00:35:18,100 Se i è 1, chiamata oh_no, altrimenti chiamare slinky, che venire qui, 456 00:35:18,100 --> 00:35:20,460 se i è 2, chiamare oh_no. 457 00:35:20,460 --> 00:35:24,720 Non so nemmeno che ci sia un modo - 458 00:35:24,720 --> 00:35:30,030 Qualcuno vedere un modo di rendere questo un programma che non si segfault? 459 00:35:30,030 --> 00:35:37,530 Perché a meno che non mi manca qualcosa, se i è 0, verrà immediatamente segfault, 460 00:35:37,530 --> 00:35:41,250 altrimenti si va a una funzione che se i è 1 si segfault, 461 00:35:41,250 --> 00:35:44,540 altrimenti si va a una funzione in cui se i è 2 si segfault. 462 00:35:44,540 --> 00:35:46,810 Quindi, non importa quello che fai, segfault. 463 00:35:46,810 --> 00:35:52,380 >> Credo che un modo per risolverlo sarebbe invece di fare char ** s = NULL, 464 00:35:52,380 --> 00:35:55,610 si potrebbe malloc spazio per quella stringa. 465 00:35:55,610 --> 00:36:04,230 Potremmo fare malloc (sizeof) - sizeof cosa? 466 00:36:09,910 --> 00:36:15,190 [Studente] (char) * 5? >> Vi sembra giusto? 467 00:36:15,190 --> 00:36:21,060 Sto assumendo questo funziona se io in realtà ha funzionato, ma non è quello che sto cercando. 468 00:36:24,400 --> 00:36:32,940 Guardate il tipo di s. Lasciatemi aggiungere int *, in modo int * x. 469 00:36:32,940 --> 00:36:35,600 Vorrei fare malloc (sizeof (int)). 470 00:36:35,600 --> 00:36:40,490 Oppure, se volevo un array di 5, farei (sizeof (int) * 5); 471 00:36:40,490 --> 00:36:44,210 Che cosa succede se ho un int **? 472 00:36:46,260 --> 00:36:49,140 Quello che mi sarebbe malloc? 473 00:36:49,140 --> 00:36:53,510 [Studente] Dimensione del puntatore. Sì >>. (Sizeof (int *)); 474 00:36:53,510 --> 00:36:56,960 Stessa cosa qui. 475 00:36:56,960 --> 00:37:01,280 Voglio (sizeof (char *)); 476 00:37:06,170 --> 00:37:12,840 Questo sta per allocare lo spazio per il puntatore che punta a "BOOM". 477 00:37:12,840 --> 00:37:15,330 Non ho bisogno di allocare lo spazio per "BOOM" stesso 478 00:37:15,330 --> 00:37:17,210 perché questo è sostanzialmente equivalente a quello che ho detto prima 479 00:37:17,210 --> 00:37:20,870 di char * x = "BOOM". 480 00:37:20,870 --> 00:37:27,950 "BOOM" esiste già. Succede esistere in sola lettura regione di memoria. 481 00:37:27,950 --> 00:37:35,200 Ma esiste già, il che significa che questa riga di codice, se s è un char **, 482 00:37:35,200 --> 00:37:43,900 allora * s è un char * e si sta impostando questo char * per puntare a "BOOM". 483 00:37:43,900 --> 00:37:50,040 Se io volessi copiare "BOOM" in s, allora avrei bisogno di allocare lo spazio per s. 484 00:37:55,170 --> 00:38:03,900 Farò * s = malloc (sizeof (char) * 5); 485 00:38:03,900 --> 00:38:06,210 Perché 5? 486 00:38:06,210 --> 00:38:10,860 Perché non 4? Sembra che "BOOM" è di 4 caratteri. >> [Studente] Il carattere null. 487 00:38:10,860 --> 00:38:14,580 Gia '. Tutte le corde si sta per necessità il carattere null. 488 00:38:14,580 --> 00:38:23,590 Ora posso fare qualcosa di simile strcat - Qual è la funzione per la copia di una stringa? 489 00:38:23,590 --> 00:38:28,520 [Studente] cpy? Strcpy >>. 490 00:38:28,520 --> 00:38:32,700 uomo strcpy. 491 00:38:36,120 --> 00:38:39,590 Così strcpy o strncpy. 492 00:38:39,590 --> 00:38:43,410 strncpy è un po 'più sicuro in quanto è possibile specificare esattamente il numero di caratteri, 493 00:38:43,410 --> 00:38:46,190 ma qui non importa perché sappiamo. 494 00:38:46,190 --> 00:38:50,340 Così strcpy e guardare negli argomenti. 495 00:38:50,340 --> 00:38:53,100 Il primo argomento è la nostra destinazione. 496 00:38:53,100 --> 00:38:56,770 Il secondo argomento è la nostra fonte. 497 00:38:56,770 --> 00:39:10,310 Stiamo andando a copiare nella nostra destinazione * s il "BOOM" puntatore. 498 00:39:10,310 --> 00:39:19,820 Perché potrebbe voler fare questo con un strcpy invece di quello che avevamo prima 499 00:39:19,820 --> 00:39:22,800 di * s = "BOOM"? 500 00:39:22,800 --> 00:39:28,630 C'è una ragione si potrebbe desiderare di fare questo, ma quello che è che la ragione? 501 00:39:28,630 --> 00:39:31,940 [Studente] Se si vuole cambiare qualcosa in "BOOM". Sì >>. 502 00:39:31,940 --> 00:39:37,950 Ora posso fare qualcosa di simile s [0] = 'X'; 503 00:39:37,950 --> 00:39:48,190 perché i punti s al mucchio e che lo spazio sul mucchio che s sta puntando 504 00:39:48,190 --> 00:39:52,320 è un puntatore a un maggior spazio sul mucchio, che memorizza "BOOM". 505 00:39:52,320 --> 00:39:55,150 Quindi questa copia di "BOOM" viene memorizzato nel mucchio. 506 00:39:55,150 --> 00:39:58,780 Ci sono tecnicamente due copie di "BOOM" nel nostro programma. 507 00:39:58,780 --> 00:40:03,500 C'è il primo che ha appena dato da questa costante "BOOM" stringa, 508 00:40:03,500 --> 00:40:09,250 e la seconda copia del "BOOM", strcpy creato la copia di "BOOM". 509 00:40:09,250 --> 00:40:13,100 Ma la copia di "BOOM" viene memorizzato sul mucchio, e il mucchio sei libero di cambiare. 510 00:40:13,100 --> 00:40:17,250 L'heap non è di sola lettura, in modo che significa che s [0] 511 00:40:17,250 --> 00:40:20,500 sta per ti permette di cambiare il valore di "BOOM". 512 00:40:20,500 --> 00:40:23,130 E 'intenzione di farvi cambiare i caratteri. 513 00:40:23,130 --> 00:40:26,640 >> Domande? 514 00:40:27,740 --> 00:40:29,290 Va bene. 515 00:40:29,290 --> 00:40:35,500 >> Passando alla buggy3, andiamo gdb buggy3. 516 00:40:35,500 --> 00:40:39,840 Ci basta eseguirlo e vediamo otteniamo un segfault. 517 00:40:39,840 --> 00:40:46,550 Se si backtrace, ci sono solo due funzioni. 518 00:40:46,550 --> 00:40:52,970 Se saliamo nella nostra funzione principale, vediamo che segfaulted a questa linea. 519 00:40:52,970 --> 00:41:00,180 Quindi, solo guardando questa linea, per (int riga = 0; fgets questa roba non è uguale a NULL; 520 00:41:00,180 --> 00:41:03,770 linea + +). 521 00:41:03,770 --> 00:41:08,010 Il nostro quadro precedente si chiamava _IO_fgets. 522 00:41:08,010 --> 00:41:10,720 Vedrete che un sacco con built-in funzioni C, 523 00:41:10,720 --> 00:41:15,350 che quando si ottiene il segfault, ci saranno i nomi delle funzioni davvero criptici 524 00:41:15,350 --> 00:41:18,090 come questo _IO_fgets. 525 00:41:18,090 --> 00:41:21,770 Ma che sta per riferirsi a questa chiamata fgets. 526 00:41:21,770 --> 00:41:25,850 Da qualche parte qui dentro, ci va in segfault. 527 00:41:25,850 --> 00:41:30,340 Se guardiamo gli argomenti di fgets, ci permette di stampare buffer. 528 00:41:30,340 --> 00:41:41,180 Facciamo stampare come - Oh, no. 529 00:41:48,980 --> 00:41:51,900 Stampa non è andare a lavorare esattamente come voglio io. 530 00:41:55,460 --> 00:41:58,000 Vediamo il programma vero e proprio. 531 00:42:02,200 --> 00:42:09,640 Buffer è un array di caratteri. Si tratta di un array di caratteri di 128 caratteri. 532 00:42:09,640 --> 00:42:14,980 Quindi, quando dico buffer di stampa, sta andando a stampare le 128 caratteri, 533 00:42:14,980 --> 00:42:18,300 che credo sia quello che ci si aspetta. 534 00:42:18,300 --> 00:42:21,390 Quello che stavo cercando è stampare l'indirizzo del buffer, 535 00:42:21,390 --> 00:42:23,680 ma che in realtà non mi dice molto. 536 00:42:23,680 --> 00:42:30,770 Così, quando mi capita di dire qui tampone x, mi mostra 0xbffff090, 537 00:42:30,770 --> 00:42:38,690 che, se ti ricordi di prima o un certo punto, Oxbffff tende ad essere uno stack-ish regione. 538 00:42:38,690 --> 00:42:46,020 Lo stack tende a cominciare da qualche parte appena sotto 0xc000. 539 00:42:46,020 --> 00:42:51,890 Solo vedendo questo indirizzo, so che sta accadendo sul buffer di stack. 540 00:42:51,890 --> 00:43:04,500 Riavvio il mio programma, eseguito, su, tampone che abbiamo visto era questa sequenza di caratteri 541 00:43:04,500 --> 00:43:06,530 che sono praticamente senza senso. 542 00:43:06,530 --> 00:43:12,270 Poi la stampa di file, file di che cosa assomiglia? 543 00:43:15,120 --> 00:43:17,310 [Studente] Null. Sì >>. 544 00:43:17,310 --> 00:43:22,610 File è un di tipo * FILE, quindi è un puntatore, 545 00:43:22,610 --> 00:43:26,610 e che il valore di puntatore è nullo. 546 00:43:26,610 --> 00:43:33,240 Così fgets sta per provare a leggere da tale puntatore in modo indiretto, 547 00:43:33,240 --> 00:43:37,320 ma per accedere a tale puntatore, deve dereferenziarlo. 548 00:43:37,320 --> 00:43:40,550 Oppure, per poter accedere a quello che dovrebbe essere rivolto a, lo dereferenziazioni. 549 00:43:40,550 --> 00:43:43,810 Quindi è dereference un puntatore nullo e si segfault. 550 00:43:46,600 --> 00:43:48,730 Avrei potuto riavviato lì. 551 00:43:48,730 --> 00:43:52,170 Se si spezza al nostro punto principale ed eseguire, 552 00:43:52,170 --> 00:43:57,320 la prima riga di codice è di tipo char * filename = "nonexistent.txt"; 553 00:43:57,320 --> 00:44:00,870 Questo dovrebbe dare un suggerimento abbastanza grande perché questo programma non riesce. 554 00:44:00,870 --> 00:44:06,080 Digitando accanto mi porta alla riga successiva, in cui ho aperto questo file, 555 00:44:06,080 --> 00:44:11,140 e poi ho subito entrare nella nostra linea, dove una volta mi ha colpito prossimo, sta andando a segfault. 556 00:44:11,140 --> 00:44:16,880 Qualcuno ha voglia di buttare via un motivo per cui potrebbe essere andare in segfault? 557 00:44:16,880 --> 00:44:19,130 [Studente] Il file non esiste. Sì >>. 558 00:44:19,130 --> 00:44:22,250 Questo dovrebbe essere un suggerimento 559 00:44:22,250 --> 00:44:29,570 che ogni volta che si sta aprendo un file è necessario controllare che il file esiste realmente. 560 00:44:29,570 --> 00:44:31,510 Quindi, ecco, "nonexistent.txt"; 561 00:44:31,510 --> 00:44:34,700 Quando abbiamo filename fopen per la lettura, abbiamo quindi bisogno di dire 562 00:44:34,700 --> 00:44:45,870 if (file == NULL) e dire printf ("Il file non esiste!" 563 00:44:45,870 --> 00:44:56,340 o - meglio ancora - filename); return 1; 564 00:44:56,340 --> 00:45:00,300 Così ora controlliamo per vedere se è NULL 565 00:45:00,300 --> 00:45:03,930 prima di poter realmente continua e cercando di leggere da quel file. 566 00:45:03,930 --> 00:45:08,800 Possiamo rifare solo per vedere che funziona. 567 00:45:11,020 --> 00:45:14,970 Avevo intenzione di inserire una nuova riga. 568 00:45:21,090 --> 00:45:25,290 Così ora nonexistent.txt non esiste. 569 00:45:26,890 --> 00:45:30,040 Si consiglia di controllare sempre per questo genere di cose. 570 00:45:30,040 --> 00:45:33,870 Si dovrebbe sempre verificare se fopen restituisce NULL. 571 00:45:33,870 --> 00:45:38,170 Si dovrebbe sempre assicurarsi che malloc non ritorna NULL, 572 00:45:38,170 --> 00:45:41,410 altrimenti si segfault. 573 00:45:42,200 --> 00:45:45,930 >> Ora buggy4.c. 574 00:45:49,190 --> 00:45:58,440 Esecuzione. Sto indovinando questo è in attesa di ingresso o eventualmente loop infinito. 575 00:45:58,440 --> 00:46:01,870 Sì, è loop infinito. 576 00:46:01,870 --> 00:46:05,560 Così buggy4. Sembra che siamo loop infinito. 577 00:46:05,560 --> 00:46:12,590 Siamo in grado di rompere al principale, eseguire il nostro programma. 578 00:46:12,590 --> 00:46:20,180 In gdb, purché l'abbreviazione si utilizza è inequivocabile 579 00:46:20,180 --> 00:46:23,420 o abbreviazioni speciali che essi forniscono per voi, 580 00:46:23,420 --> 00:46:29,020 quindi è possibile utilizzare n per uso successivo, invece di dover digitare a fianco tutta la strada. 581 00:46:29,020 --> 00:46:33,730 E ora che ho colpito n una volta, posso solo premere Invio per andare avanti dopo 582 00:46:33,730 --> 00:46:36,640 invece di dover premere Invio n, n Inserisci, n Invio. 583 00:46:36,640 --> 00:46:44,630 Sembra come se fossi in una sorta di ciclo for che è l'impostazione di matrice [i] a 0. 584 00:46:44,630 --> 00:46:50,510 Sembra che io non sono mai la rottura di questo ciclo for. 585 00:46:50,510 --> 00:46:54,780 Se i stampa, così ho è 2, poi me ne andrò dopo. 586 00:46:54,780 --> 00:46:59,250 Io i stampa, i è 3, poi me ne andrò dopo. 587 00:46:59,250 --> 00:47:05,360 Io ho stampare e i è 3. Quindi, stampare i, i è 4. 588 00:47:05,360 --> 00:47:14,520 In realtà, stampa sizeof (array), quindi dimensione della matrice è 20. 589 00:47:16,310 --> 00:47:32,870 Ma sembra che ci sia qualche comando gdb speciale per andare fino a quando succede qualcosa. 590 00:47:32,870 --> 00:47:37,620 E 'come la creazione di una condizione sul valore della variabile. Ma non mi ricordo quello che è. 591 00:47:37,620 --> 00:47:44,100 Quindi, se andare avanti - 592 00:47:44,100 --> 00:47:47,120 Che cosa ha detto? Che cosa hai portato su? 593 00:47:47,120 --> 00:47:50,500 [Studente] non visualizza i add - >> Si '. Quindi visualizzare posso aiutare. 594 00:47:50,500 --> 00:47:54,530 Se solo i visualizzazione, sarà inserire qui ciò che il valore di i è 595 00:47:54,530 --> 00:47:56,470 quindi non c'è bisogno di stamparlo ogni volta. 596 00:47:56,470 --> 00:48:02,930 Se solo continuare prossima, vediamo 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 Sta succedendo qualcosa di terribilmente sbagliato, e mi viene reimpostato a 0. 598 00:48:13,330 --> 00:48:22,220 Guardando buggy4.c, si vede tutto ciò che accade è array 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 array [i] = 0; 601 00:48:28,550 --> 00:48:31,390 Che cosa si vede che c'è di sbagliato? 602 00:48:31,390 --> 00:48:39,480 Come un suggerimento, quando stavo facendo il gdb buggy4 - rompiamo principale di esecuzione - 603 00:48:39,480 --> 00:48:45,980 Ho fatto stampare sizeof (array) solo per vedere cosa la condizione è dove dovrei finalmente scoppiare. 604 00:48:47,690 --> 00:48:51,100 Dove sono? Ho eseguito? 605 00:48:51,100 --> 00:48:54,280 Io non ha dichiarato ancora. 606 00:48:54,280 --> 00:48:58,680 Quindi stampare sizeof (array) e che è 20, 607 00:48:58,680 --> 00:49:06,690 che si prevede in quanto la mia matrice è di dimensione 5 ed è su 5 numeri interi, 608 00:49:06,690 --> 00:49:12,410 così l'intera cosa dovrebbe essere 5 * sizeof (int) byte, dove sizeof (int) tende ad essere 4. 609 00:49:12,410 --> 00:49:14,780 Quindi, sizeof (array) è 20. 610 00:49:14,780 --> 00:49:17,420 Che cosa dovrebbe essere? 611 00:49:17,420 --> 00:49:21,720 [Studente] Diviso per sizeof (int). Sì >>, / sizeof (int). 612 00:49:21,720 --> 00:49:30,630 Sembra che ci sia ancora un problema qui. Credo che questo dovrebbe essere solo < 613 00:49:30,630 --> 00:49:36,960 dal momento che è più o meno sempre 00:49:44,860 Ora pensiamo a perché questo è stato effettivamente rotto. 615 00:49:44,860 --> 00:49:53,370 Qualcuno ha ipotesi Perché mi è stato resettato a 0 a ogni iterazione del ciclo? 616 00:50:01,300 --> 00:50:09,350 L'unica cosa che dentro di qui che sta succedendo è che array [i] viene impostato su 0. 617 00:50:09,350 --> 00:50:15,350 Così in qualche modo, questa riga di codice che causa il nostro int i per essere impostato a 0. 618 00:50:16,730 --> 00:50:23,130 [Studente] Potrebbe essere perché è prevalente il ricordo di questa parte i 619 00:50:23,130 --> 00:50:27,970 quando si pensa che sia il successivo elemento dell'array? >> [Bowden] Sì. 620 00:50:27,970 --> 00:50:33,880 Quando stiamo andando al di là della fine del nostro array, 621 00:50:33,880 --> 00:50:39,870 in qualche modo quello spazio che stiamo prevalente è prevalente il valore di i. 622 00:50:39,870 --> 00:50:48,030 E così, se guardiamo in buggy4, rompere principale, corsa, 623 00:50:48,030 --> 00:50:53,120 cerchiamo di stampare l'indirizzo di i. 624 00:50:53,120 --> 00:50:57,280 Sembra come se fosse bffff124. 625 00:50:57,280 --> 00:51:03,930 Ora stampare l'indirizzo di array [0]. 110. 626 00:51:03,930 --> 00:51:06,290 Che dire [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] è bfff124. 629 00:51:14,530 --> 00:51:26,990 Così array [5] ha lo stesso indirizzo di i, il che significa che array [5] i è. 630 00:51:26,990 --> 00:51:30,720 Se hanno lo stesso indirizzo, sono la stessa cosa. 631 00:51:30,720 --> 00:51:38,410 Così, quando abbiamo fissato array [5] a 0, ci sono i impostazione a 0. 632 00:51:38,410 --> 00:51:46,070 E se pensi di questo in termini di stack, 633 00:51:46,070 --> 00:51:55,590 int i è dichiarato prima, il che significa che si po 'di spazio nello stack. 634 00:51:55,590 --> 00:52:04,730 Poi array [5] è assegnata, in modo quindi 20 byte sono allocati sullo stack. 635 00:52:04,730 --> 00:52:08,400 Così i vengono assegnate in primo luogo, allora questi 20 byte vengono assegnati. 636 00:52:08,400 --> 00:52:11,400 Così ho succede a destra prima la matrice, 637 00:52:11,400 --> 00:52:19,230 e per il modo in cui, come ho detto la scorsa settimana, ove tecnicamente lo stack cresce verso il basso, 638 00:52:19,230 --> 00:52:28,520 quando si indice in un array, abbiamo la garanzia che la posizione 0 nella matrice 639 00:52:28,520 --> 00:52:31,970 succede sempre prima della prima posizione nella matrice. 640 00:52:31,970 --> 00:52:35,900 Questa è una specie di come ho disegnato la settimana scorsa. 641 00:52:35,900 --> 00:52:42,210 Si noti che in fondo abbiamo indirizzo 0 e superiormente abbiamo Max indirizzo. 642 00:52:42,210 --> 00:52:44,880 Lo stack è sempre in crescita verso il basso. 643 00:52:48,100 --> 00:52:53,500 Diciamo che i allocare. 644 00:52:53,500 --> 00:52:59,680 Abbiamo allocare intero i, il che significa che diciamo solo che qui intero i viene assegnato. 645 00:52:59,680 --> 00:53:06,420 Poi allocare il nostro array di 5 interi, il che significa che al di sotto che, 646 00:53:06,420 --> 00:53:11,230 in quanto lo stack cresce verso il basso, quei 5 numeri interi vengono assegnati. 647 00:53:11,230 --> 00:53:15,900 Ma a causa di come gli array funzionano, abbiamo la garanzia che la prima posizione nella matrice 648 00:53:15,900 --> 00:53:22,260 ha sempre indirizzo inferiore alla seconda cosa nella matrice. 649 00:53:22,260 --> 00:53:28,270 Così la posizione di 0 array deve sempre avvenire prima in memoria, 650 00:53:28,270 --> 00:53:30,700 considerando che la posizione matrice 1 deve avvenire dopo che 651 00:53:30,700 --> 00:53:33,310 e la posizione di matrice 2 deve avvenire dopo che, 652 00:53:33,310 --> 00:53:37,900 il che significa che la posizione 0 dell'array sarebbe accaduto da qualche parte qui, 653 00:53:37,900 --> 00:53:40,690 posizione matrice 1 sarebbe accaduto in precedenza che 654 00:53:40,690 --> 00:53:45,530 perché salendo significa indirizzi superiori in quanto l'indirizzo massimo è qui. 655 00:53:45,530 --> 00:53:50,490 Così array [0] qui, array [1] qui, array [2] qui, array [3] qui. 656 00:53:50,490 --> 00:53:55,620 Notate come prima assegnato intero i tutta la strada fino qui, 657 00:53:55,620 --> 00:54:01,040 come ci muoviamo sempre più nel nostro array, ci stiamo avvicinando sempre di più al nostro intero i. 658 00:54:01,040 --> 00:54:07,640 Si dà il caso che la matrice [5], che è una posizione oltre la nostra matrice, 659 00:54:07,640 --> 00:54:13,010 è esattamente dove mi è capitato intero da assegnare. 660 00:54:13,010 --> 00:54:16,920 Ecco, questo è il punto in cui ci capita di essere colpendo lo spazio sullo stack 661 00:54:16,920 --> 00:54:21,680 che è stato assegnato per intero i, e che stiamo impostando a 0. 662 00:54:21,680 --> 00:54:26,160 >> È così che funziona. Domande? Gia '. 663 00:54:26,160 --> 00:54:30,710 [Studente] Non importa. Va bene. 664 00:54:30,710 --> 00:54:33,090 [Studente] Come si fa a evitare questo tipo di errori? 665 00:54:33,090 --> 00:54:41,190 Questi tipo di errori? Non utilizzare C come linguaggio di programmazione. 666 00:54:41,190 --> 00:54:45,840 Utilizzare un linguaggio che ha limiti di matrice di controllo. 667 00:54:45,840 --> 00:54:55,900 Finché si sta attenti, non vi resta che evitare di andare oltre i confini della vostra matrice. 668 00:54:55,900 --> 00:54:58,300 [Studente] Così qui quando siamo andati oltre i limiti della matrice - 669 00:54:58,300 --> 00:55:01,840 [Bowden] Questo è dove le cose iniziano ad andare male. >> [Studente] Oh, va bene. 670 00:55:01,840 --> 00:55:05,730 Fino a quando si rimane all'interno della memoria allocata per l'array, che stai bene. 671 00:55:05,730 --> 00:55:12,400 Ma C non fa il controllo degli errori. Se faccio array [1000], che sarà lieto di solo modificare qualunque cosa accada - 672 00:55:12,400 --> 00:55:16,500 Va all'inizio della matrice, poi va 1000 posizioni dopo e lo imposta a 0. 673 00:55:16,500 --> 00:55:20,000 Non fa alcun controllo che oh, questo in realtà non ha 1000 cose in esso. 674 00:55:20,000 --> 00:55:22,750 1000 è ben oltre quello che deve cambiare, 675 00:55:22,750 --> 00:55:26,940 che Java o qualcosa avrai serie di limiti dell'indice 676 00:55:26,940 --> 00:55:29,820 o indice di eccezione limiti. 677 00:55:29,820 --> 00:55:33,950 È per questo che un sacco di linguaggi di livello superiore hanno queste cose 678 00:55:33,950 --> 00:55:37,340 dove se si va oltre i limiti della matrice, non si riesce 679 00:55:37,340 --> 00:55:40,070 in modo che non è possibile cambiare le cose da sotto di voi 680 00:55:40,070 --> 00:55:42,590 e poi le cose vanno molto peggio di un semplice ottenere un'eccezione 681 00:55:42,590 --> 00:55:44,940 dicendo che sei andato oltre la fine della matrice. 682 00:55:44,940 --> 00:55:50,970 [Studente] E così dovrebbe abbiamo appena cambiato il <= a solo > [Bowden] Si '. 683 00:55:50,970 --> 00:55:54,800 Dovrebbe essere 00:55:59,560 dal sizeof (array) è 20, ma vogliamo solo 5. >> [Studente] destro. 685 00:55:59,560 --> 00:56:04,060 Altre domande? Va bene. 686 00:56:04,060 --> 00:56:07,380 >> [Studente] Ho una domanda. Sì >>. 687 00:56:07,380 --> 00:56:16,440 [Studente] Qual è la variabile di matrice reale? 688 00:56:16,440 --> 00:56:20,000 [Bowden] Come quello che è array? 689 00:56:20,000 --> 00:56:24,930 Matrice stessa è un simbolo. 690 00:56:24,930 --> 00:56:31,490 È solo l'indirizzo iniziale dei 20 byte che stiamo riferimento. 691 00:56:31,490 --> 00:56:38,070 Si può pensare ad esso come un puntatore, ma è un puntatore costante. 692 00:56:38,070 --> 00:56:44,140 Non appena le cose si compilato, l'array variabile non esiste più. 693 00:56:44,140 --> 00:56:48,210 [Studente] Così come si trova la dimensione della matrice? 694 00:56:48,210 --> 00:56:54,130 Dimensione della matrice si riferisce alla dimensione del blocco che quel simbolo si riferisce. 695 00:56:54,130 --> 00:57:01,240 Quando faccio qualcosa di simile a printf ("% p \ n", array); 696 00:57:01,240 --> 00:57:05,140 cerchiamo di farlo funzionare. 697 00:57:12,960 --> 00:57:15,530 Cosa ho appena fatto di sbagliato? 698 00:57:15,530 --> 00:57:19,220 'Allineamento' Array dichiarato qui. 699 00:57:20,820 --> 00:57:23,200 Oh, qui. 700 00:57:23,200 --> 00:57:31,250 Clang è intelligente, e capita di notare che ho dichiarato l'array come 5 elementi 701 00:57:31,250 --> 00:57:34,540 ma io sono l'indicizzazione in posizione 1000. 702 00:57:34,540 --> 00:57:38,450 Si può farlo perché questi sono solo costanti. 703 00:57:38,450 --> 00:57:43,370 Si può solo andare così lontano a meno di notare che sto andando oltre i limiti della matrice. 704 00:57:43,370 --> 00:57:46,880 Ma notate prima, quando abbiamo avuto i non essere corretto, 705 00:57:46,880 --> 00:57:51,040 non è in grado di determinare il numero di valori che ho potuto assumere, 706 00:57:51,040 --> 00:57:55,540 quindi non può determinare che andavo oltre la fine della matrice. 707 00:57:55,540 --> 00:57:59,430 Questo è solo Clang di essere intelligente. 708 00:57:59,430 --> 00:58:03,340 >> Ma ora fare buggy4. Quindi, che cosa sto facendo di sbagliato? 709 00:58:03,340 --> 00:58:05,970 Implicitamente dichiarando la funzione di libreria 'printf'. 710 00:58:05,970 --> 00:58:14,960 Ho intenzione di voler includere # . 711 00:58:14,960 --> 00:58:18,710 Va bene. Ora esecuzione buggy4. 712 00:58:18,710 --> 00:58:24,840 Stampa il valore della matrice come ho fatto qui, la stampa come un puntatore 713 00:58:24,840 --> 00:58:30,060 stampe qualcosa che assomiglia a questo - bfb8805c - che è un po 'di indirizzo 714 00:58:30,060 --> 00:58:33,450 che è nello stack-ish regione. 715 00:58:33,450 --> 00:58:41,820 Matrice stessa è come un puntatore, ma non è un puntatore effettivo, 716 00:58:41,820 --> 00:58:45,410 da un normale puntatore possiamo cambiare. 717 00:58:45,410 --> 00:58:54,700 Array è solo una costante. I 20 blocchi di memoria partono 0xbfb8805c indirizzo. 718 00:58:54,700 --> 00:59:09,020 Quindi bfb8805c attraverso questo indirizzo +20--o credo -20 - 719 00:59:09,020 --> 00:59:17,400 è tutta la memoria allocata per questa matrice. 720 00:59:17,400 --> 00:59:20,350 Array, la variabile stessa non viene memorizzata da nessuna parte. 721 00:59:20,350 --> 00:59:27,660 Quando si sta compilando, il compilatore - onda mano a questo - 722 00:59:27,660 --> 00:59:33,060 ma il compilatore, basta usare dove sa di essere di matrice. 723 00:59:33,060 --> 00:59:36,090 Si sa dove tale array inizia, 724 00:59:36,090 --> 00:59:40,910 e in modo che possa sempre e solo fare le cose in termini di offset da quell'inizio. 725 00:59:40,910 --> 00:59:43,960 Non ha bisogno di una stessa variabile per rappresentare array. 726 00:59:43,960 --> 00:59:53,730 Ma quando faccio qualcosa di simile int * p = array, ora p è un puntatore che punta a tale matrice, 727 00:59:53,730 --> 00:59:57,830 e ora p in realtà non esistono in pila. 728 00:59:57,830 --> 01:00:01,950 Sono liberi di cambiare p. Posso fare p = malloc. 729 01:00:01,950 --> 01:00:06,500 Quindi, in origine indicava matrice, ora punta a un pò di spazio sul mucchio. 730 01:00:06,500 --> 01:00:09,620 Non posso fare di matrice = malloc. 731 01:00:09,620 --> 01:00:13,710 Se Clang è intelligente, sarà urlarmi destra fuori del blocco. 732 01:00:17,000 --> 01:00:21,430 A dire il vero, sono abbastanza sicuro che gcc avrebbe fatto anche questo. 733 01:00:21,430 --> 01:00:25,010 Quindi tipo di matrice 'int [5]' non è cedibile. 734 01:00:25,010 --> 01:00:28,040 Non è possibile assegnare qualcosa a un tipo di matrice 735 01:00:28,040 --> 01:00:30,500 perché array è solo una costante. 736 01:00:30,500 --> 01:00:34,760 E 'un simbolo che fa riferimento a quei 20 byte. Non si può cambiare. 737 01:00:34,760 --> 01:00:37,690 >> [Studente] E dove è la dimensione della matrice memorizzata? 738 01:00:37,690 --> 01:00:40,670 [Bowden] Non è memorizzato da nessuna parte. E 'quando si sta compilando. 739 01:00:40,670 --> 01:00:46,310 Allora, dove è la dimensione di array memorizzato? 740 01:00:46,310 --> 01:00:51,870 È possibile utilizzare solo sizeof (array) all'interno della funzione che l'array è si è dichiarata. 741 01:00:51,870 --> 01:01:03,150 Quindi, se faccio qualche funzione, foo, e lo faccio (int array []) 742 01:01:03,150 --> 01:01:10,450 printf ("% d \ n", sizeof (array)); 743 01:01:10,450 --> 01:01:21,330 e poi qui io chiamo foo (array); 744 01:01:21,330 --> 01:01:24,840 all'interno di questa funzione - cerchiamo di farlo funzionare. 745 01:01:34,200 --> 01:01:36,840 Questo è Clang essere intelligente ancora. 746 01:01:36,840 --> 01:01:43,890 Mi sta dicendo che sizeof il parametro di matrice funzione 747 01:01:43,890 --> 01:01:46,690 tornerà dimensione del 'int *'. 748 01:01:46,690 --> 01:01:55,150 Questo sarebbe un errore se non è quello che volevo per accadere. 749 01:01:55,150 --> 01:01:58,960 Andiamo in realtà spegnere Werror. 750 01:02:14,950 --> 01:02:17,590 Attenzione. Avvertenze vanno bene. 751 01:02:17,590 --> 01:02:19,960 Sarà comunque compilare purché dotato di un allarme. 752 01:02:19,960 --> 01:02:22,910 . / A.out sta per stampare 4. 753 01:02:22,910 --> 01:02:28,650 L'avviso che è stato generato è un chiaro indicatore di ciò che è andato storto. 754 01:02:28,650 --> 01:02:34,120 Questa matrice int è solo andare a stampare sizeof (int *). 755 01:02:34,120 --> 01:02:39,790 Anche se ho messo array [5] qui dentro, è ancora solo andando a stampare sizeof (int *). 756 01:02:39,790 --> 01:02:47,440 Quindi, non appena si passa in una funzione, la distinzione tra array e puntatori 757 01:02:47,440 --> 01:02:49,670 è inesistente. 758 01:02:49,670 --> 01:02:52,640 Questa sembra essere una matrice che è stata dichiarata in pila, 759 01:02:52,640 --> 01:02:58,300 ma non appena si passa tale valore, che 0xBF blah, blah, blah in questa funzione, 760 01:02:58,300 --> 01:03:03,350 allora questo puntatore punta a tale matrice nello stack. 761 01:03:03,350 --> 01:03:08,310 Quindi questo significa che sizeof vale solo per la funzione che l'array è stato dichiarato, 762 01:03:08,310 --> 01:03:11,230 il che significa che quando si compila questa funzione, 763 01:03:11,230 --> 01:03:17,330 Clang quando passa attraverso questa funzione, vede array è un array di int di dimensione 5. 764 01:03:17,330 --> 01:03:20,640 Allora vede sizeof (array). Beh, e '20. 765 01:03:20,640 --> 01:03:26,440 Che in realtà è come sizeof funziona praticamente per quasi tutti i casi. 766 01:03:26,440 --> 01:03:31,150 Sizeof non è una funzione, è un operatore. 767 01:03:31,150 --> 01:03:33,570 Non si chiama la funzione sizeof. 768 01:03:33,570 --> 01:03:38,280 Sizeof (int), il compilatore sarà solo tradurlo a 4. 769 01:03:41,480 --> 01:03:43,700 Capito? Va bene. 770 01:03:43,700 --> 01:03:47,520 >> [Studente] Allora, qual è la differenza tra sizeof (array) in main e in foo? 771 01:03:47,520 --> 01:03:52,840 Questo è dovuto al fatto che stiamo dicendo sizeof (array), che è di tipo int *, 772 01:03:52,840 --> 01:03:57,120 mentre la matrice quaggiù è non di tipo int *, è un array int. 773 01:03:57,120 --> 01:04:04,540 >> [Studente] Quindi, se si ha il parametro in array [] invece di matrice * int, 774 01:04:04,540 --> 01:04:09,230 potrebbe significare che si potrebbe ancora cambiare matrice perché ora si tratta di un puntatore? 775 01:04:09,230 --> 01:04:14,250 [Bowden] Ti piace questa? >> [Studente] Si '. Potete cambiare matrice all'interno della funzione ora? 776 01:04:14,250 --> 01:04:18,420 [Bowden] Si potrebbe cambiare matrice in entrambi i casi. 777 01:04:18,420 --> 01:04:23,130 In entrambi i casi si è liberi di dire array [4] = 0. 778 01:04:23,130 --> 01:04:26,590 [Studente] Ma si può fare il punto matrice a qualcos'altro? 779 01:04:26,590 --> 01:04:30,230 [Bowden] Oh. Gia '. In entrambi i casi - >> [studente] Si '. 780 01:04:30,230 --> 01:04:38,410 [Bowden] La distinzione tra array [] e un array int *, non c'è nessuno. 781 01:04:38,410 --> 01:04:42,570 È inoltre possibile ottenere un po 'di array multidimensionale in qui 782 01:04:42,570 --> 01:04:47,050 per un po 'la sintassi conveniente, ma è ancora solo un puntatore. 783 01:04:47,050 --> 01:04:56,400 Questo significa che sono libero di fare array = malloc (sizeof (int)), e ora puntare da qualche altra parte. 784 01:04:56,400 --> 01:04:59,610 Ma proprio come come questo funziona sempre e sempre, 785 01:04:59,610 --> 01:05:03,210 modificare questa matrice facendolo puntare a qualcosa d'altro 786 01:05:03,210 --> 01:05:07,570 non modifica l'array qui perché è una copia della tesi, 787 01:05:07,570 --> 01:05:10,780 non è un puntatore a tale argomento. 788 01:05:10,780 --> 01:05:16,070 E in realtà, proprio come più indicazione che è esattamente la stessa cosa - 789 01:05:16,070 --> 01:05:21,100 abbiamo già visto che cosa stampe di matrice di stampa - 790 01:05:21,100 --> 01:05:31,410 cosa succederebbe se stampare l'indirizzo della matrice o l'indirizzo dell'indirizzo della matrice 791 01:05:31,410 --> 01:05:36,290 a uno di questi? 792 01:05:41,770 --> 01:05:45,220 Ignoriamo questo. 793 01:05:48,140 --> 01:05:51,660 Va bene. Questo va bene. E 'ora in esecuzione. / A.out. 794 01:05:51,660 --> 01:06:00,220 Matrice di stampa, quindi stampando l'indirizzo della matrice, sono la stessa cosa. 795 01:06:00,220 --> 01:06:02,870 Array semplicemente non esiste. 796 01:06:02,870 --> 01:06:08,190 Si sa quando si stampa matrice, si stampa il simbolo che si riferisce a quei 20 byte. 797 01:06:08,190 --> 01:06:11,940 Stampa l'indirizzo dell'array, beh, di matrice non esiste. 798 01:06:11,940 --> 01:06:17,200 Non ha un indirizzo, quindi viene stampato solo l'indirizzo di questi 20 byte. 799 01:06:20,820 --> 01:06:28,150 Non appena si compila il basso, come nel vostro buggy4 compilato. / A.out, 800 01:06:28,150 --> 01:06:30,340 array è inesistente. 801 01:06:30,340 --> 01:06:33,640 Puntatori esistono. Array non lo fanno. 802 01:06:34,300 --> 01:06:38,060 I blocchi di memoria che rappresentano la matrice esistono ancora, 803 01:06:38,060 --> 01:06:43,270 ma la matrice variabile e variabili di tale tipo non esistono. 804 01:06:46,260 --> 01:06:50,270 Quelli sono come le principali differenze tra vettori e puntatori 805 01:06:50,270 --> 01:06:55,590 sono appena si effettua una chiamata di funzione, non c'è differenza. 806 01:06:55,590 --> 01:07:00,460 Ma all'interno della funzione che la stessa matrice viene dichiarata, sizeof funziona in modo diverso 807 01:07:00,460 --> 01:07:05,190 poiché si sta stampando la dimensione dei blocchi invece della dimensione del tipo, 808 01:07:05,190 --> 01:07:08,950 e non si può cambiare perché è un simbolo. 809 01:07:08,950 --> 01:07:14,370 Stampa la cosa e l'indirizzo della cosa stampa la stessa cosa. 810 01:07:14,370 --> 01:07:18,480 E questo è più o meno di esso. 811 01:07:18,480 --> 01:07:20,820 [Studente] Puoi dire che ancora una volta? 812 01:07:21,170 --> 01:07:24,170 Potrei aver perso qualcosa. 813 01:07:24,170 --> 01:07:29,260 Matrice di stampa e l'indirizzo della matrice di stampa la stessa cosa, 814 01:07:29,260 --> 01:07:33,180 mentre se si stampa un puntatore contro l'indirizzo del puntatore, 815 01:07:33,180 --> 01:07:36,010 l'unica cosa che viene stampato l'indirizzo di quello che stai puntando, 816 01:07:36,010 --> 01:07:40,360 l'altra stampa l'indirizzo del puntatore in pila. 817 01:07:40,360 --> 01:07:47,040 È possibile modificare un puntatore, non è possibile modificare un simbolo di matrice. 818 01:07:47,740 --> 01:07:53,270 E sizeof puntatore sta per stampare la dimensione di quel tipo puntatore. 819 01:07:53,270 --> 01:07:57,470 Così int * p sizeof (p) sta per stampare 4, 820 01:07:57,470 --> 01:08:04,110 ma int array [5] stampa sizeof (array) è andare in stampa 20. 821 01:08:04,110 --> 01:08:07,480 [Studente] Così int array [5] viene stampato 20? Sì >>. 822 01:08:07,480 --> 01:08:13,300 Ecco perché all'interno di buggy4 quando è usato per essere sizeof (array) 823 01:08:13,300 --> 01:08:16,660 questo è stato fatto i <20, che non è quello che volevamo. 824 01:08:16,660 --> 01:08:20,880 Vogliamo che i <5. >> [Studente] Ok. 825 01:08:20,880 --> 01:08:25,569 [Bowden] E poi, non appena si inizia il passaggio nelle funzioni, 826 01:08:25,569 --> 01:08:34,340 se abbiamo fatto int * p = array; 827 01:08:34,340 --> 01:08:39,779 all'interno di questa funzione, si può sostanzialmente usare p e matrice in esattamente gli stessi metodi, 828 01:08:39,779 --> 01:08:43,710 tranne per il problema sizeof e il problema cambiando. 829 01:08:43,710 --> 01:08:49,810 Ma p [0] = 1; è come dire array [0] = 1; 830 01:08:49,810 --> 01:08:55,600 E non appena si dice foo (array), oppure foo (p); 831 01:08:55,600 --> 01:08:59,760 all'interno della funzione foo, questa è la stessa chiamata due volte. 832 01:08:59,760 --> 01:09:03,350 Non vi è alcuna differenza tra queste due chiamate. 833 01:09:07,029 --> 01:09:11,080 >> Tutti bene su questo? Va bene. 834 01:09:14,620 --> 01:09:17,950 Abbiamo 10 minuti. 835 01:09:17,950 --> 01:09:28,319 >> Cercheremo di ottenere attraverso questo programma Hacker Typer, 836 01:09:28,319 --> 01:09:32,350 questo sito, che è uscito l'anno scorso o qualcosa del genere. 837 01:09:34,149 --> 01:09:41,100 E 'solo dovrebbe essere come si digita in modo casuale e stampata - 838 01:09:41,100 --> 01:09:46,729 Qualsiasi file, capita di aver caricato è quello che sembra si sta digitando. 839 01:09:46,729 --> 01:09:52,069 Sembra una specie di codice del sistema operativo. 840 01:09:53,760 --> 01:09:56,890 Questo è quello che vogliamo implementare. 841 01:10:08,560 --> 01:10:11,690 Si dovrebbe avere un binario eseguibile di nome hacker_typer 842 01:10:11,690 --> 01:10:14,350 che prende in un singolo argomento, il file in "tipo di hacker." 843 01:10:14,350 --> 01:10:16,480 L'esecuzione del file eseguibile deve pulire lo schermo 844 01:10:16,480 --> 01:10:20,850 e poi stampare un carattere dalla passata nel file ogni volta che l'utente preme un tasto. 845 01:10:20,850 --> 01:10:24,990 Quindi, qualsiasi tasto premuto, si dovrebbe buttare via e invece stampare un carattere dal file 846 01:10:24,990 --> 01:10:27,810 che è l'argomento. 847 01:10:29,880 --> 01:10:34,350 Io più o meno quello che ti dico le cose che stiamo andando ad avere bisogno di sapere sono. 848 01:10:34,350 --> 01:10:36,440 Ma noi vogliamo controllare la libreria termios. 849 01:10:36,440 --> 01:10:44,840 Non ho mai usato questa libreria in tutta la mia vita, quindi ha scopi molto minimale. 850 01:10:44,840 --> 01:10:48,610 Ma questo sta andando essere la biblioteca che possiamo usare per buttare via il personaggio che ha colpito 851 01:10:48,610 --> 01:10:52,390 quando si sta digitando in standard da 852 01:10:56,970 --> 01:11:05,840 Così hacker_typer.c, e stiamo andando a voler includere # . 853 01:11:05,840 --> 01:11:12,870 Guardando la pagina di manuale di termios - Sto indovinando che terminale di sistema operativo o qualcosa del genere - 854 01:11:12,870 --> 01:11:16,240 Io non so come leggerlo. 855 01:11:16,240 --> 01:11:21,040 Guardando questa, si dice per includere questi 2 file, quindi lo faremo. 856 01:11:37,620 --> 01:11:46,820 >> Per prima cosa, vogliamo prendere in un singolo argomento, che è il file che deve aprire. 857 01:11:46,820 --> 01:11:52,420 Allora, cosa voglio fare? Come posso controllare per vedere che ho un solo argomento? 858 01:11:52,420 --> 01:11:56,480 [Studente] Se argc è uguale. >> [Bowden] Si '. 859 01:11:56,480 --> 01:12:21,250 Quindi, se (argc = 2!) Printf ("Uso:% s [file per aprire]"). 860 01:12:21,250 --> 01:12:32,750 Così ora se corro questo senza fornire un secondo argomento - oh, mi serve la nuova linea - 861 01:12:32,750 --> 01:12:36,240 vedrete che dice di utilizzo:. / hacker_typer, 862 01:12:36,240 --> 01:12:39,770 e poi il secondo argomento deve essere il file che voglio aprire. 863 01:12:58,430 --> 01:13:01,260 Ora cosa devo fare? 864 01:13:01,260 --> 01:13:08,490 Voglio leggere da questo file. Come faccio a leggere da un file? 865 01:13:08,490 --> 01:13:11,920 [Studente] Lo aprire prima. Sì >>. 866 01:13:11,920 --> 01:13:15,010 Così fopen. Che cosa significa fopen assomiglia? 867 01:13:15,010 --> 01:13:22,980 [Studente] Nome file. >> [Bowden] Nome del file sta per essere argv [1]. 868 01:13:22,980 --> 01:13:26,110 [Studente] E poi che cosa si vuole fare con essa, in modo che il - >> [Bowden] Si '. 869 01:13:26,110 --> 01:13:28,740 Quindi, se non si ricordava, appena poteva fare fopen uomo, 870 01:13:28,740 --> 01:13:32,960 dove sta andando ad essere un percorso const char * dove percorso è il nome file, 871 01:13:32,960 --> 01:13:34,970 const char * mode. 872 01:13:34,970 --> 01:13:38,660 Se vi capita di non ricordare ciò che modo è, allora si può guardare per la modalità. 873 01:13:38,660 --> 01:13:44,660 All'interno delle pagine man, il carattere barra è quello che è possibile utilizzare per la ricerca di cose. 874 01:13:44,660 --> 01:13:49,790 Così ho tipo / modalità per la ricerca di modalità. 875 01:13:49,790 --> 01:13:57,130 n e N sono ciò che è possibile utilizzare per scorrere le partite di ricerca. 876 01:13:57,130 --> 01:13:59,800 Qui si dice che i punti argomento mode di una stringa 877 01:13:59,800 --> 01:14:01,930 iniziando con una delle seguenti sequenze. 878 01:14:01,930 --> 01:14:06,480 Quindi r, file di testo aperto per la lettura. Questo è quello che vogliamo fare. 879 01:14:08,930 --> 01:14:13,210 Per la lettura, e voglio conservare questo. 880 01:14:13,210 --> 01:14:18,720 La cosa sta andando essere un * FILE. Ora, che cosa voglio fare? 881 01:14:18,720 --> 01:14:21,200 Dammi un secondo. 882 01:14:28,140 --> 01:14:30,430 Va bene. Ora, che cosa voglio fare? 883 01:14:30,430 --> 01:14:32,940 [Studente] Controllare se è NULL. >> [Bowden] Si '. 884 01:14:32,940 --> 01:14:38,690 Ogni volta che si apre un file, assicurarsi che siete successo in grado di aprirlo. 885 01:14:58,930 --> 01:15:10,460 >> Ora voglio fare quella roba termios dove voglio prima leggere le mie impostazioni correnti 886 01:15:10,460 --> 01:15:14,050 e salvare quelli in qualcosa, allora voglio cambiare le mie impostazioni 887 01:15:14,050 --> 01:15:19,420 buttare via qualsiasi carattere di tipo I, 888 01:15:19,420 --> 01:15:22,520 e poi voglio aggiornare tali impostazioni. 889 01:15:22,520 --> 01:15:27,250 E poi alla fine del programma, voglio tornare ai miei impostazioni originali. 890 01:15:27,250 --> 01:15:32,080 Così la struttura sta per essere di termios tipo, e ho intenzione di voler due di questi. 891 01:15:32,080 --> 01:15:35,600 Il primo sta per essere i miei current_settings, 892 01:15:35,600 --> 01:15:42,010 e poi si sta andando ad essere i miei hacker_settings. 893 01:15:42,010 --> 01:15:48,070 In primo luogo, ho intenzione di salvare le impostazioni correnti, 894 01:15:48,070 --> 01:15:53,790 allora ho intenzione di voler aggiornare hacker_settings, 895 01:15:53,790 --> 01:16:01,570 e poi via, alla fine del mio programma, voglio ripristinare le impostazioni correnti. 896 01:16:01,570 --> 01:16:08,660 Quindi il salvataggio delle impostazioni correnti, il modo in cui funziona, noi termios uomo. 897 01:16:08,660 --> 01:16:15,810 Vediamo che abbiamo questo tcsetattr int, int tcgetattr. 898 01:16:15,810 --> 01:16:22,960 Passo in una struttura termios dal suo puntatore. 899 01:16:22,960 --> 01:16:30,640 Il modo in cui questo aspetto è - ho già dimenticato quello che la funzione è stata chiamata. 900 01:16:30,640 --> 01:16:34,930 Copia e incolla. 901 01:16:39,150 --> 01:16:45,500 Così tcgetattr, allora voglio passare nella struttura che sto salvando le informazioni, 902 01:16:45,500 --> 01:16:49,650 che sta per essere current_settings, 903 01:16:49,650 --> 01:16:59,120 e il primo argomento è il descrittore di file per la cosa che desidera salvare gli attributi di. 904 01:16:59,120 --> 01:17:04,360 Quello che il descrittore di file è è come ogni volta che si apre un file, si ottiene un descrittore di file. 905 01:17:04,360 --> 01:17:14,560 Quando ho fopen argv [1], si ottiene un descrittore di file, che si fa riferimento 906 01:17:14,560 --> 01:17:16,730 ogni volta che si vuole leggere o scrivere su di esso. 907 01:17:16,730 --> 01:17:19,220 Questo non è il descrittore di file che voglio usare qui. 908 01:17:19,220 --> 01:17:21,940 Ci sono tre descrittori di file che avete per impostazione predefinita, 909 01:17:21,940 --> 01:17:24,310 che sono standard, fuori standard, e di errore standard. 910 01:17:24,310 --> 01:17:29,960 Per impostazione predefinita, penso che sia standard è 0, fuori standard è 1, e l'errore standard è 2. 911 01:17:29,960 --> 01:17:33,980 Allora, cosa voglio cambiare le impostazioni di? 912 01:17:33,980 --> 01:17:37,370 Voglio cambiare le impostazioni ogni volta che mi ha colpito un personaggio, 913 01:17:37,370 --> 01:17:41,590 Voglio che buttare via quel carattere invece di stamparlo sullo schermo. 914 01:17:41,590 --> 01:17:45,960 Che acqua - standard, fuori standard o errore standard - 915 01:17:45,960 --> 01:17:52,050 risponde alle cose quando si digita sulla tastiera? >> [Studente] Standard trovi >> Gia '. 916 01:17:52,050 --> 01:17:56,450 Così può fare 0 o posso fare stdin. 917 01:17:56,450 --> 01:17:59,380 Sto ricevendo il current_settings di standard da 918 01:17:59,380 --> 01:18:01,720 >> Ora voglio aggiornare tali impostazioni, 919 01:18:01,720 --> 01:18:07,200 quindi prima mi copiare nel hacker_settings quello che i miei current_settings sono. 920 01:18:07,200 --> 01:18:10,430 E come il lavoro di strutture è sarà solo copiare. 921 01:18:10,430 --> 01:18:14,510 Questo consente di copiare tutti i campi, come ci si aspetterebbe. 922 01:18:14,510 --> 01:18:17,410 >> Ora voglio aggiornare alcuni dei campi. 923 01:18:17,410 --> 01:18:21,670 Guardando termios, si dovrà leggere un sacco di questo 924 01:18:21,670 --> 01:18:24,110 solo per vedere quello che si desidera cercare, 925 01:18:24,110 --> 01:18:28,210 ma le bandiere si sta andando a voler cercare sono eco, 926 01:18:28,210 --> 01:18:33,110 così ECHO caratteri di input Echo. 927 01:18:33,110 --> 01:18:37,710 Prima di tutto voglio impostare - ho già dimenticato quello che i campi sono. 928 01:18:45,040 --> 01:18:47,900 Questo è ciò che la struttura assomiglia. 929 01:18:47,900 --> 01:18:51,060 Così modalità di ingresso penso che vogliamo cambiare. 930 01:18:51,060 --> 01:18:54,210 Vedremo la soluzione per fare in modo che è quello che vogliamo cambiare. 931 01:19:04,060 --> 01:19:12,610 Vogliamo cambiare lflag per evitare la necessità di guardare attraverso tutti questi. 932 01:19:12,610 --> 01:19:14,670 Vogliamo cambiare le modalità locali. 933 01:19:14,670 --> 01:19:17,710 Si dovrebbe leggere tutta questa cosa per capire dove tutto appartiene 934 01:19:17,710 --> 01:19:19,320 che si desidera modificare. 935 01:19:19,320 --> 01:19:24,120 Ma è all'interno di modalità di locali dove stiamo andando a voler cambiare la situazione. 936 01:19:27,080 --> 01:19:33,110 Quindi hacker_settings.cc_lmode è come si chiama. 937 01:19:39,630 --> 01:19:43,020 c_lflag. 938 01:19:49,060 --> 01:19:52,280 Questo è dove si riesce a mettere gli operatori bit per bit. 939 01:19:52,280 --> 01:19:54,860 Siamo un po 'fuori dal tempo, ma andremo in fretta reale. 940 01:19:54,860 --> 01:19:56,600 E 'qui che entriamo in operatori bit a bit, 941 01:19:56,600 --> 01:19:59,950 dove credo di aver detto una volta tempo fa che ogni volta che iniziare a trattare con le bandiere, 942 01:19:59,950 --> 01:20:03,370 avete intenzione di utilizzare l'operatore bit a bit molto. 943 01:20:03,370 --> 01:20:08,240 Ogni bit nella bandiera corrisponde a una sorta di comportamento. 944 01:20:08,240 --> 01:20:14,090 Ecco, questo flag ha un sacco di cose diverse, dove tutti significano qualcosa di diverso. 945 01:20:14,090 --> 01:20:18,690 Ma quello che voglio fare è semplicemente spegnere il bit che corrisponde a ECHO. 946 01:20:18,690 --> 01:20:25,440 Quindi, per spegnerlo faccio & = ¬ ECHO. 947 01:20:25,440 --> 01:20:30,110 A dire il vero, penso che sia come techo o qualcosa del genere. Sto solo andando a controllare di nuovo. 948 01:20:30,110 --> 01:20:34,050 Posso termios. E 'solo ECHO. 949 01:20:34,050 --> 01:20:38,440 ECHO sta per essere un po 'sola. 950 01:20:38,440 --> 01:20:44,230 ¬ ECHO sta a significare tutti i bit sono impostati a 1, il che significa che tutti i parametri sono impostati su true 951 01:20:44,230 --> 01:20:47,140 tranne che per il bit di ECHO. 952 01:20:47,140 --> 01:20:53,830 Per finire i miei bandiere locali con questo, vuol dire tutti i flag che sono attualmente impostata su true 953 01:20:53,830 --> 01:20:56,520 sarà ancora impostata su true. 954 01:20:56,520 --> 01:21:03,240 Se la mia bandiera ECHO è impostato su true, allora questo è necessariamente impostato su false sulla bandiera ECHO. 955 01:21:03,240 --> 01:21:07,170 Quindi, questa riga di codice si appena fuori la bandiera ECHO. 956 01:21:07,170 --> 01:21:16,270 Le altre linee di codice, mi limiterò a copiarli nell'interesse di tempo e poi spiegarle. 957 01:21:27,810 --> 01:21:30,180 Nella soluzione, ha detto 0. 958 01:21:30,180 --> 01:21:33,880 E 'probabilmente meglio dire esplicitamente stdin. 959 01:21:33,880 --> 01:21:42,100 >> Si noti che sto facendo anche ECHO | icanon qui. 960 01:21:42,100 --> 01:21:46,650 Icanon si riferisce a qualcosa di separato, il che significa che la modalità canonica. 961 01:21:46,650 --> 01:21:50,280 Che cosa significa la modalità canonica è di solito quando si sta digitando la riga di comando, 962 01:21:50,280 --> 01:21:54,670 standard non elabora nulla fino a colpire newline. 963 01:21:54,670 --> 01:21:58,230 Così, quando si fa GetString, si digita un sacco di cose, allora si colpisce newline. 964 01:21:58,230 --> 01:22:00,590 Questo è quando è inviato a standard da 965 01:22:00,590 --> 01:22:02,680 Questo è il valore predefinito. 966 01:22:02,680 --> 01:22:05,830 Quando ho disattivare la modalità canonica, ora ogni singolo carattere che si preme 967 01:22:05,830 --> 01:22:10,910 è ciò che viene elaborato, che di solito è tipo di male, perché è lento per elaborare queste cose, 968 01:22:10,910 --> 01:22:14,330 è per questo che è bene di tamponare in linee intere. 969 01:22:14,330 --> 01:22:16,810 Ma voglio che ogni carattere da elaborare 970 01:22:16,810 --> 01:22:18,810 dal momento che non ne vogliono sapere di attendere per me per colpire newline 971 01:22:18,810 --> 01:22:21,280 prima di elaborare tutti i personaggi che ho scrivendo. 972 01:22:21,280 --> 01:22:24,760 Questo disattiva la modalità canonica. 973 01:22:24,760 --> 01:22:31,320 Questa roba significa solo durante l'elaborazione in realtà caratteri. 974 01:22:31,320 --> 01:22:35,830 Ciò significa elaborare immediatamente, non appena li sto scrivendo, la loro elaborazione. 975 01:22:35,830 --> 01:22:42,510 E questa è la funzione che sta aggiornando le mie impostazioni per la standard, 976 01:22:42,510 --> 01:22:45,480 e mezzi TCSA farlo adesso. 977 01:22:45,480 --> 01:22:50,310 Le altre opzioni sono attendere che tutto ciò che è attualmente il flusso viene elaborato. 978 01:22:50,310 --> 01:22:52,030 Questo non ha molta importanza. 979 01:22:52,030 --> 01:22:56,920 Proprio in questo momento modificare le impostazioni di essere tutto ciò che è attualmente in hacker_typer_settings. 980 01:22:56,920 --> 01:23:02,210 Credo che ho chiamato hacker_settings, quindi cerchiamo di cambiare la situazione. 981 01:23:09,610 --> 01:23:13,500 Cambiare tutto per hacker_settings. 982 01:23:13,500 --> 01:23:16,870 >> Ora, alla fine del nostro programma che stiamo andando a voler tornare 983 01:23:16,870 --> 01:23:20,210 a ciò che è attualmente all'interno di normal_settings, 984 01:23:20,210 --> 01:23:26,560 che sta a guardare, proprio come e normal_settings. 985 01:23:26,560 --> 01:23:30,650 Avviso Non ho cambiato nessuno dei miei normal_settings quanto originariamente sempre. 986 01:23:30,650 --> 01:23:34,520 Poi, per semplicemente cambiare di nuovo, li passare di nuovo alla fine. 987 01:23:34,520 --> 01:23:38,390 Questo era l'aggiornamento. Va bene. 988 01:23:38,390 --> 01:23:43,900 >> Ora, all'interno di qui mi limiterò a spiegare il codice nell'interesse del tempo. 989 01:23:43,900 --> 01:23:46,350 Non è che molto codice. 990 01:23:50,770 --> 01:24:03,750 Vediamo si legge un carattere dal file. Lo abbiamo chiamato f. 991 01:24:03,750 --> 01:24:07,850 Ora è possibile fgetc uomo, ma come fgetc sta andando a lavorare 992 01:24:07,850 --> 01:24:11,910 è solo sta andando a restituire il carattere che hai appena letto o EOF, 993 01:24:11,910 --> 01:24:15,680 che corrisponde alla fine del file o qualche evento di errore. 994 01:24:15,680 --> 01:24:19,900 Stiamo looping, continuando a leggere un singolo carattere dal file, 995 01:24:19,900 --> 01:24:22,420 finché non avremo finito di caratteri da leggere. 996 01:24:22,420 --> 01:24:26,650 E mentre lo stiamo facendo, siamo in attesa di un singolo carattere da standard da 997 01:24:26,650 --> 01:24:29,090 Ogni volta che si digita qualcosa nella riga di comando, 998 01:24:29,090 --> 01:24:32,820 che è la lettura di un carattere da standard da 999 01:24:32,820 --> 01:24:38,330 Poi putchar è solo andare a mettere il char si legge qui dal file di standard out. 1000 01:24:38,330 --> 01:24:42,890 È possibile putchar uomo, ma è solo mettendo sullo standard output, è la stampa di quel personaggio. 1001 01:24:42,890 --> 01:24:51,600 Si potrebbe anche fare solo printf ("% c", c); stessa idea. 1002 01:24:53,330 --> 01:24:56,670 Quello sta andando a fare la maggior parte del nostro lavoro. 1003 01:24:56,670 --> 01:25:00,300 >> L'ultima cosa che stiamo andando a voler fare è solo fclose il nostro file. 1004 01:25:00,300 --> 01:25:03,310 Se non si fclose, che è una perdita di memoria. 1005 01:25:03,310 --> 01:25:06,680 Vogliamo fclose il file che originariamente aperto, e penso che sia. 1006 01:25:06,680 --> 01:25:13,810 Se facciamo questo, ho già avuto problemi. 1007 01:25:13,810 --> 01:25:17,260 Vediamo un po '. 1008 01:25:17,260 --> 01:25:19,960 Che cosa ha lamentarsi? 1009 01:25:19,960 --> 01:25:30,220 Previsto 'int', ma l'argomento è di tipo 'struct _IO_FILE *'. 1010 01:25:36,850 --> 01:25:39,370 Staremo a vedere se funziona. 1011 01:25:45,210 --> 01:25:53,540 Consentito solo in C99. Augh. Ok, fare hacker_typer. 1012 01:25:53,540 --> 01:25:57,760 Ora abbiamo descrizioni più utili. 1013 01:25:57,760 --> 01:25:59,900 Quindi, l'uso di identificatore non dichiarato 'normal_settings'. 1014 01:25:59,900 --> 01:26:04,170 Io non chiamo normal_settings. Ho chiamato current_settings. 1015 01:26:04,170 --> 01:26:12,090 Quindi cerchiamo di cambiare tutto questo. 1016 01:26:17,920 --> 01:26:21,710 Ora passa argomento. 1017 01:26:26,290 --> 01:26:29,500 Farò questo 0 per ora. 1018 01:26:29,500 --> 01:26:36,720 Va bene. . / Hacker_typer cp.c. 1019 01:26:36,720 --> 01:26:39,590 Ho anche non pulire lo schermo all'inizio. 1020 01:26:39,590 --> 01:26:42,960 Ma si può guardare indietro al set ultimo problema per vedere come cancellare lo schermo. 1021 01:26:42,960 --> 01:26:45,160 E 'solo la stampa di alcuni caratteri 1022 01:26:45,160 --> 01:26:47,210 mentre questo è fare quello che voglio fare. 1023 01:26:47,210 --> 01:26:48,900 Va bene. 1024 01:26:48,900 --> 01:26:55,280 E pensare perché questo doveva essere 0 invece che da stdin, 1025 01:26:55,280 --> 01:27:00,560 che dovrebbe essere # define 0, 1026 01:27:00,560 --> 01:27:03,890 questo si lamenta che - 1027 01:27:13,150 --> 01:27:19,360 Prima quando ho detto che non c'è descrittori di file, ma poi hai anche il tuo * FILE, 1028 01:27:19,360 --> 01:27:23,210 un descrittore di file è solo un numero intero, 1029 01:27:23,210 --> 01:27:26,970 mentre un * FILE ha un sacco di cose ad esso associati. 1030 01:27:26,970 --> 01:27:30,380 La ragione per cui abbiamo bisogno di dire 0 invece che da stdin 1031 01:27:30,380 --> 01:27:37,480 è che stdin è un FILE * che punta alla cosa che fa riferimento descrittore di file 0. 1032 01:27:37,480 --> 01:27:45,070 Così, anche qui quando faccio fopen (argv [1], sto diventando un FILE * indietro. 1033 01:27:45,070 --> 01:27:51,180 Ma da qualche parte in quel * FILE è una cosa corrispondente al descrittore di file per quel file. 1034 01:27:51,180 --> 01:27:57,430 Se guardate la pagina man per open, quindi penso che dovrete fare man 3 aperto - No. - 1035 01:27:57,430 --> 01:27:59,380 man 2 open - si '. 1036 01:27:59,380 --> 01:28:06,250 Se guardate la pagina per open, aperto è come un livello inferiore fopen, 1037 01:28:06,250 --> 01:28:09,350 ed è restituire il descrittore di file effettivo. 1038 01:28:09,350 --> 01:28:12,050 fopen fa un po 'di cose su di aperto, 1039 01:28:12,050 --> 01:28:17,640 che invece di restituire solo che descrittore di file restituisce un puntatore FILE intero * 1040 01:28:17,640 --> 01:28:20,590 all'interno del quale è il nostro piccolo descrittore di file. 1041 01:28:20,590 --> 01:28:25,020 Così standard si riferisce alla cosa * FILE, 1042 01:28:25,020 --> 01:28:29,120 mentre 0 si riferisce al solo standard di descrittore di file in sé. 1043 01:28:29,120 --> 01:28:32,160 >> Domande? 1044 01:28:32,160 --> 01:28:35,930 [Ride] si è allargato attraverso quella. 1045 01:28:35,930 --> 01:28:39,140 Bene. Abbiamo finito. [Ride] 1046 01:28:39,140 --> 01:28:42,000 >> [CS50.TV]