1 00:00:00,000 --> 00:00:02,500 [Powered by Google Translate] [Secció 5 - Més Còmode] 2 00:00:02,500 --> 00:00:04,690 [Rob Bowden - Harvard University] 3 00:00:04,690 --> 00:00:07,250 [Aquesta és CS50. - CS50.TV] 4 00:00:08,990 --> 00:00:14,250 >> Com vaig dir en el meu correu electrònic, hi ha un munt de coses que vostè pot utilitzar 5 00:00:14,250 --> 00:00:17,060 que no sigui l'aparell per fer realitat els butlletins de problemes. 6 00:00:17,060 --> 00:00:19,910 Et recomanem que ho facis en l'aparell només perquè llavors ens serà més fàcil ajudar 7 00:00:19,910 --> 00:00:22,070 i sabem que tot va a funcionar. 8 00:00:22,070 --> 00:00:26,950 Però com un exemple que es poden fer coses si, per exemple, no tenen accés 9 00:00:26,950 --> 00:00:31,570 a un aparell o desitja treballar al soterrani del Centre de Ciències - 10 00:00:31,570 --> 00:00:33,090 que en realitat tenen l'aparell massa - 11 00:00:33,090 --> 00:00:35,150 si vols treballar en qualsevol lloc. 12 00:00:35,150 --> 00:00:42,370 Un exemple s'han vist / sentit de SSH? 13 00:00:44,380 --> 00:00:47,780 SSH és bàsicament la mateixa que connectar-se a alguna cosa. 14 00:00:47,780 --> 00:00:51,340 De fet, ara mateix estic SSHed en l'aparell. 15 00:00:51,340 --> 00:00:54,290 Mai treballar directament en l'aparell. 16 00:00:55,930 --> 00:01:01,060 Aquí està l'aparell, i si mires aquí baix es veu aquesta adreça IP. 17 00:01:01,060 --> 00:01:03,650 Mai treball en el propi aparell; 18 00:01:03,650 --> 00:01:08,840 Sempre vinc a un iTerm2 finestra / finestra de terminal. 19 00:01:08,840 --> 00:01:15,910 Vostè pot SSH a aquesta adreça IP, ssh jharvard@192.168.129.128. 20 00:01:15,910 --> 00:01:20,390 Recordo aquest nombre amb molta facilitat pel fet que és un bonic patró. 21 00:01:20,390 --> 00:01:24,920 Però això em demanarà la contrasenya, i ara estic en l'aparell. 22 00:01:24,920 --> 00:01:33,060 Bàsicament, en aquest punt, si s'obre un terminal a l'interior del propi aparell, 23 00:01:33,060 --> 00:01:36,350 aquesta interfície, però vostè ho fa servir, és exactament el mateix 24 00:01:36,350 --> 00:01:40,010 com la interfície que estic fent servir aquí, però ara estem SSHed. 25 00:01:42,240 --> 00:01:44,920 No ha de SSH al dispositiu. 26 00:01:44,920 --> 00:01:52,360 Un exemple d'un altre lloc que podria SSH és que estic bastant segur que té per defecte - 27 00:01:52,360 --> 00:01:55,020 Oh. Més gran. 28 00:01:55,020 --> 00:02:01,130 Tots vostès han de tenir en compte FAS per defecte en els servidors de FAS. 29 00:02:01,130 --> 00:02:06,840 Per a mi, ho faria SSH a rbowden@nice.fas.harvard.edu. 30 00:02:06,840 --> 00:02:11,610 Va a demanar-li que la primera vegada, i vostè diu que sí. 31 00:02:11,610 --> 00:02:15,840 La meva contrasenya és només serà la meva contrasenya FAS. 32 00:02:15,840 --> 00:02:22,650 I ara, estic SSHed als servidors bons, i puc fer el que vulgui aquí. 33 00:02:22,650 --> 00:02:28,560 Una gran quantitat de classes que es podrien adoptar, com 124, hauran de pujar coses a aquí 34 00:02:28,560 --> 00:02:30,950 de presentar efectivament els seus butlletins de problemes. 35 00:02:30,950 --> 00:02:34,100 Però diu que no té accés al seu aparell. 36 00:02:34,100 --> 00:02:37,910 A continuació, pot fer coses, com aquí es dirà - 37 00:02:37,910 --> 00:02:42,160 Això és només les preguntes. 38 00:02:42,160 --> 00:02:45,070 Se li demana que ho fem en l'aparell. 39 00:02:45,070 --> 00:02:47,790 En lloc d'això només ho farà al servidor. 40 00:02:47,790 --> 00:02:50,560 Me'n vaig a descomprimir això. 41 00:02:50,560 --> 00:02:55,670 El problema serà que vostè està acostumat a fer servir alguna cosa com gedit 42 00:02:55,670 --> 00:02:58,160 o el que sigui a l'interior de l'aparell. 43 00:02:58,160 --> 00:03:01,830 No hauràs al servidor de FAS. 44 00:03:01,830 --> 00:03:04,110 Tot això és només serà aquesta interfície textual. 45 00:03:04,110 --> 00:03:09,180 Així que vostè podria qualsevol d'ells, tractar d'aprendre un editor de text que té. 46 00:03:09,180 --> 00:03:12,130 Tenen Nano. 47 00:03:12,130 --> 00:03:14,990 Nano és bastant fàcil d'utilitzar. 48 00:03:14,990 --> 00:03:19,470 Vostè pot utilitzar les seves fletxes i escriu normalment. 49 00:03:19,470 --> 00:03:21,250 Així que no és difícil. 50 00:03:21,250 --> 00:03:24,720 Si vol aconseguir realment de luxe pot usar Emacs, 51 00:03:24,720 --> 00:03:29,850 que jo probablement no hauria d'haver obert perquè no sé ni com tancar Emacs. 52 00:03:29,850 --> 00:03:32,760 X Control, Control C? Si. 53 00:03:32,760 --> 00:03:35,310 O pot utilitzar Vim, que és el que jo faig servir. 54 00:03:35,310 --> 00:03:37,800 I aquestes són les seves opcions. 55 00:03:37,800 --> 00:03:43,830 Si no vols fer això, vostè també pot, si ens fixem en manual.cs50.net-- 56 00:03:43,830 --> 00:03:45,410 Oh. 57 00:03:45,410 --> 00:03:49,920 En un PC, pot usar SSH PuTTY, 58 00:03:49,920 --> 00:03:51,940 que hauràs de descarregar per separat. 59 00:03:51,940 --> 00:03:55,460 En un Mac, pot simplement usar predeterminat Terminal o pot descarregar iTerm2, 60 00:03:55,460 --> 00:03:58,490 que és com un terminal bonic, luxós. 61 00:03:58,490 --> 00:04:03,780 Si vostè va a manual.cs50.net veuràs un enllaç a Notepad + +, 62 00:04:03,780 --> 00:04:07,120 que és el que es pot utilitzar en un PC. 63 00:04:07,120 --> 00:04:13,340 Et permet SFTP de Notepad + +, que és bàsicament SSH. 64 00:04:13,340 --> 00:04:17,750 El que això li permetrà fer és editar els teus arxius de forma local, 65 00:04:17,750 --> 00:04:20,670 i després cada vegada que vulguis salvar, salvarà nice.fas, 66 00:04:20,670 --> 00:04:23,670 on vostè pot llavors córrer. 67 00:04:23,670 --> 00:04:26,880 I l'equivalent en Mac serà TextWrangler. 68 00:04:26,880 --> 00:04:28,760 Per tant, li permet fer el mateix. 69 00:04:28,760 --> 00:04:32,800 Et permet editar arxius de forma local i guardar-los en nice.fas, 70 00:04:32,800 --> 00:04:35,730 on vostè pot llavors córrer. 71 00:04:35,730 --> 00:04:40,400 Així que si mai atrapat sense un aparell, té les següents opcions 72 00:04:40,400 --> 00:04:44,230 que encara fa els seus butlletins de problemes. 73 00:04:44,230 --> 00:04:48,250 L'únic problema serà que no tindrem la biblioteca CS50 74 00:04:48,250 --> 00:04:51,580 perquè nice.fas per defecte no tenen això. 75 00:04:51,580 --> 00:04:55,970 Podeu descarregar la biblioteca CS50 - 76 00:04:55,970 --> 00:04:58,470 Jo no crec que sigui necessari que en aquest punt. 77 00:04:58,470 --> 00:05:03,270 Pot descarregar la biblioteca CS50 i copiar a nice.fas, 78 00:05:03,270 --> 00:05:07,450 o crec que en aquest moment no usar mai més de tota manera. 79 00:05:07,450 --> 00:05:12,720 O si ho fem, pot de moment, substituir-lo per 80 00:05:12,720 --> 00:05:18,480 les implementacions de les funcions a la biblioteca CS50 de totes maneres. 81 00:05:18,480 --> 00:05:21,370 Així que no hauria de ser part d'una restricció. 82 00:05:21,370 --> 00:05:23,710 I això és tot. 83 00:05:26,460 --> 00:05:29,820 >> Vaig a tornar a l'aplicació ara, farem tot el possible en l'aparell. 84 00:05:29,820 --> 00:05:37,510 Quant a les preguntes, al principi, com vaig dir en el meu correu electrònic, 85 00:05:37,510 --> 00:05:43,620 hem de parlar de la curta se suposava que veure. 86 00:05:43,620 --> 00:05:51,980 Tenim la reorientació i Tubs i aquestes tres preguntes. 87 00:05:51,980 --> 00:05:56,070 >> A què corrent no funciona com printf escriure per defecte? 88 00:05:56,070 --> 00:05:59,130 Així corrent. Què és un riu? 89 00:06:06,520 --> 00:06:15,100 Un corrent és bàsicament com si fos només una mica - 90 00:06:15,100 --> 00:06:21,450 Ni tan sols és una font de 1s i 0s. 91 00:06:21,450 --> 00:06:24,920 El corrent està demanant aquí és la sortida estàndard. 92 00:06:24,920 --> 00:06:27,250 I fos tan estàndard és un corrent que quan s'escriu en ell, 93 00:06:27,250 --> 00:06:30,940 que apareix a la pantalla. 94 00:06:30,940 --> 00:06:36,860 Fora Standard, per flux, això significa que vostè acaba d'escriure 1s i 0s a la mateixa, 95 00:06:36,860 --> 00:06:40,220 i l'altre extrem de sortida estàndard només llegeix d'aquest corrent. 96 00:06:40,220 --> 00:06:43,540 És només una cadena de 1s i 0s. 97 00:06:43,540 --> 00:06:45,570 Vostè pot escriure als rierols o pot llegir dels rierols 98 00:06:45,570 --> 00:06:47,950 depenent del que el corrent que realment és. 99 00:06:47,950 --> 00:06:52,800 Les altres dues corrents de defecte són estàndard i d'error estàndard. 100 00:06:52,800 --> 00:06:57,540 És estàndard en cada vegada que es GetString, està esperant per tu per matèria d'entrada. 101 00:06:57,540 --> 00:07:01,570 Pel que t'espera, en realitat espera a la norma en, 102 00:07:01,570 --> 00:07:04,880 que en realitat és el que passa quan s'escriu en el teclat. 103 00:07:04,880 --> 00:07:07,530 Estàs escrivint en estàndard polz 104 00:07:07,530 --> 00:07:10,050 Error estàndard és bàsicament equivalent a la sortida estàndard, 105 00:07:10,050 --> 00:07:13,280 però és especialitzada en la qual en imprimir en error estàndard, 106 00:07:13,280 --> 00:07:16,770 se suposa que has de imprimir només missatges d'error perquè 107 00:07:16,770 --> 00:07:20,200 perquè pugui diferenciar entre els missatges impresos regulars a la pantalla 108 00:07:20,200 --> 00:07:24,560 enfront dels missatges d'error depenent de si van ser a la sortida estàndard o error estàndard. 109 00:07:24,560 --> 00:07:28,660 Els arxius també. 110 00:07:28,660 --> 00:07:32,440 Fora estàndard, estàndard en, i l'error estàndard són corrents només especials, 111 00:07:32,440 --> 00:07:36,810 però en realitat qualsevol arxiu, quan s'obre un arxiu, aquest es converteix en un flux de bytes 112 00:07:36,810 --> 00:07:40,740 on només es pot llegir d'aquest corrent. 113 00:07:40,740 --> 00:07:47,770 Vostè, en la seva major part, només puc pensar en un arxiu com una seqüència de bytes. 114 00:07:47,770 --> 00:07:51,190 Llavors, què és el que els corrents escriure per defecte? Per Norma. 115 00:07:51,190 --> 00:07:56,980 >> Quina és la diferència entre> i >>? 116 00:07:58,140 --> 00:08:03,710 Algú veure el vídeo per endavant? Bé. 117 00:08:03,710 --> 00:08:10,960 > Serà com redirigir als arxius, 118 00:08:10,960 --> 00:08:15,240 i >> també va a redirigir la sortida en arxius, 119 00:08:15,240 --> 00:08:17,820 però aquesta vegada va a annexar a l'expedient. 120 00:08:17,820 --> 00:08:23,430 Per exemple, els direm és que tinc dict aquí, 121 00:08:23,430 --> 00:08:27,020 i les coses només a l'interior de dict és gat, gat, gos, peix, gos. 122 00:08:27,020 --> 00:08:31,530 Un ordre que vostè té en la línia d'ordres és gat, 123 00:08:31,530 --> 00:08:34,539 que només va a imprimir el que hi ha en un arxiu. 124 00:08:34,539 --> 00:08:40,679 Així que quan dic dict gat, que voleu imprimir gat, gat, gos, peix, gos. Això és tot gat fa. 125 00:08:40,679 --> 00:08:46,280 Això vol dir que s'imprimeix a la sortida estàndard gat, gat, gos, peix, gos. 126 00:08:46,280 --> 00:08:53,240 Si en lloc que desitgi redirigir a un arxiu, pot utilitzar> i redireccionar al que l'arxiu és. 127 00:08:53,240 --> 00:08:56,460 Vaig a trucar a la imatge arxiu. 128 00:08:56,460 --> 00:09:00,320 Així que ara si ls, vaig a veure que tinc un nou arxiu anomenat arxiu. 129 00:09:00,320 --> 00:09:05,700 I si l'obre, tindrà exactament el gats, condicionats a la línia d'ordres. 130 00:09:05,700 --> 00:09:11,040 Així que ara si ho faig de nou, llavors va a redirigir la sortida en un arxiu, 131 00:09:11,040 --> 00:09:13,930 i jo vaig a tenir exactament la mateixa cosa. 132 00:09:13,930 --> 00:09:17,910 Així que, tècnicament, es va anul · lar per complet el que teníem. 133 00:09:17,910 --> 00:09:22,970 I anem a veure si puc canviar dict, vaig treure gos. 134 00:09:22,970 --> 00:09:29,980 Ara bé, si dict gat a l'arxiu de nou, tindrem la nova versió amb el gos eliminat. 135 00:09:29,980 --> 00:09:32,400 Per tant, s'anul completament. 136 00:09:32,400 --> 00:09:36,640 En canvi, si fem servir >>, que va a adjuntar l'arxiu. 137 00:09:36,640 --> 00:09:40,860 Ara, en obrir l'arxiu, veiem que tenim la mateixa cosa dues vegades imprès 138 00:09:40,860 --> 00:09:44,920 perquè era allà un cop, llavors adjunta a l'original. 139 00:09:44,920 --> 00:09:48,130 Així que això és el que> i >> fer. 140 00:09:48,130 --> 00:09:50,580 La següent pregunta - No pregunti sobre això. 141 00:09:50,580 --> 00:09:59,050 >> L'altre que tenim és <, que si> redirecciona la sortida estàndard, 142 00:09:59,050 --> 00:10:01,970 00:10:12,050 A veure si tenim un exemple. 144 00:10:14,750 --> 00:10:16,930 Sóc capaç d'escriure un molt ràpid. 145 00:10:17,870 --> 00:10:25,700 Prenguem qualsevol arxiu, hello.c. 146 00:10:56,060 --> 00:10:59,070 Arxiu relativament senzill. 147 00:10:59,070 --> 00:11:03,570 M'estic fent una cadena i després imprimir "Hola" sigui quina sigui la cadena que acaba d'entrar era. 148 00:11:03,570 --> 00:11:07,990 Així que hola i després. / Hello. 149 00:11:07,990 --> 00:11:10,720 Ara em va portar a escriure alguna cosa, 150 00:11:10,720 --> 00:11:15,070 el que significa que està esperant en les coses que s'introduiran en estàndard polz 151 00:11:15,070 --> 00:11:20,450 Així que el que jo vulgui entrar en estàndard polz Només direm Hola, Rob! 152 00:11:20,450 --> 00:11:23,310 Llavors està imprimint a la sortida estàndard Hola, Rob! 153 00:11:23,310 --> 00:11:28,860 Si ho faig. / Hola i després redireccionar, 154 00:11:30,740 --> 00:11:34,310 per ara només es pot redirigir a un arxiu. 155 00:11:34,310 --> 00:11:41,720 Així que si em poso en algun arxiu, txt, i vaig posar Rob, 156 00:11:41,720 --> 00:11:52,300 hola si em quedo i després redirigir l'arxiu txt a. / hola, que dirà Hola, Rob! immediatament. 157 00:11:52,300 --> 00:11:57,160 Quan per primera vegada arriba a GetString i està esperant a la norma en, 158 00:11:57,160 --> 00:12:01,730 estàndard ja no s'espera en el teclat per a les dades que s'ingressen. 159 00:12:01,730 --> 00:12:05,980 En canvi, hem redirigit estàndard per llegir el fitxer txt. 160 00:12:05,980 --> 00:12:10,290 I pel que llegirà des del fitxer txt, que és només la línia de Rob, 161 00:12:10,290 --> 00:12:13,380 i llavors voleu imprimir Hola, Rob! 162 00:12:13,380 --> 00:12:18,180 I si jo volia, jo també podia fer. / Hello 00:12:21,500 i llavors l'estàndard que el mateix de la impressió, que és Hola, Rob!, 164 00:12:21,500 --> 00:12:24,700 Puc redireccionar que en el seu propi arxiu. 165 00:12:24,700 --> 00:12:29,790 Vaig a trucar a la imatge hola - no, no ho faré, perquè aquest és l'executable - txt2. 166 00:12:29,790 --> 00:12:40,150 Ara, txt2 tindrà la sortida de. / Hello 00:12:43,520 >> Preguntes? 168 00:12:45,900 --> 00:12:49,090 >> Bé. Així que aquí tenim canonada. 169 00:12:49,090 --> 00:12:53,510 Els tubs són l'última unitat de redirecció. 170 00:12:53,510 --> 00:12:58,750 >> Oh. Suposo que una unitat més de redirecció és si en comptes de> fer 2>, 171 00:12:58,750 --> 00:13:01,070 que està redirigint error estàndard. 172 00:13:01,070 --> 00:13:06,280 Així que si alguna cosa sortia d'error estàndard, no es posa en txt2. 173 00:13:06,280 --> 00:13:12,480 Però noti si ho faig 2>, llavors és encara la impressió Hola, Rob! a la línia d'ordres 174 00:13:12,480 --> 00:13:18,600 perquè estic sol redirigir l'error estàndard, no estic redirigint la sortida estàndard. 175 00:13:18,600 --> 00:13:22,210 Error estàndard i la sortida estàndard són diferents. 176 00:13:24,210 --> 00:13:27,080 Si volies escriure realment l'error estàndard 177 00:13:27,080 --> 00:13:35,080 llavors jo podria canviar això sigui fprintf a stderr. 178 00:13:35,080 --> 00:13:37,850 Així printf, per defecte, s'imprimeix a la sortida estàndard. 179 00:13:37,850 --> 00:13:41,720 Si voleu imprimir en l'error estàndard de forma manual, llavors he de fer servir fprintf 180 00:13:41,720 --> 00:13:45,010 i especificar el que voleu imprimir. 181 00:13:45,010 --> 00:13:49,720 Si en canvi ho vaig fer stdout fprintf, llavors això és bàsicament equivalent a printf. 182 00:13:49,720 --> 00:13:55,530 Però fprintf l'error estàndard. 183 00:13:57,790 --> 00:14:03,650 Així que ara, si puc redirigir això en txt2, Hola, Rob! encara s'està imprès en la línia d'ordres 184 00:14:03,650 --> 00:14:08,270 ja que s'està fent visualitza com error estàndard i només estic redirigint la sortida estàndard. 185 00:14:08,270 --> 00:14:16,420 Si ara redirigir l'error estàndard, ja que no s'imprimeixen i txt2 serà Hola, Rob! 186 00:14:16,420 --> 00:14:21,910 Així que ara, vostè pot imprimir els seus errors reals en l'error estàndard 187 00:14:21,910 --> 00:14:24,720 i imprimir els seus missatges regulars a la sortida estàndard. 188 00:14:24,720 --> 00:14:31,420 I així, quan s'executa el programa, es pot executar com. / Hola aquest tipus amb el 2> 189 00:14:31,420 --> 00:14:33,800 perquè el programa va a funcionar amb normalitat, 190 00:14:33,800 --> 00:14:38,400 però qualsevol missatge d'error que vostè rep pot comprovar més endavant en el seu registre d'errors, 191 00:14:38,400 --> 00:14:44,500 el que els errors, i després buscar l'arxiu més tard i tindrà errors els errors que van ocórrer. 192 00:14:45,200 --> 00:14:47,540 >> Preguntes? 193 00:14:47,540 --> 00:14:58,070 >> L'últim és pipa, que es pot pensar en com prendre la sortida estàndard d'una ordre 194 00:14:58,070 --> 00:15:01,210 i el que és l'estàndard en la següent comanda. 195 00:15:01,210 --> 00:15:05,570 Un exemple d'això és ressò és quelcom línia d'ordres 196 00:15:05,570 --> 00:15:11,840 que només va a fer-se ressò del que em posa com a argument. No vaig a posar cometes. 197 00:15:11,840 --> 00:15:16,150 Echo bla, bla, bla, només voleu imprimir, bla, bla, bla. 198 00:15:16,150 --> 00:15:20,600 Abans, quan em va dir que havia de posar Rob en un arxiu txt 199 00:15:20,600 --> 00:15:28,830 perquè només puc redirigir els arxius txt, en canvi, / si em faig ressò de Rob 200 00:15:28,830 --> 00:15:35,520 i després canalitzar-la en. / hola, que també farà el mateix tipus de coses. 201 00:15:35,520 --> 00:15:39,160 Això és prendre la sortida d'aquesta comanda, l'eco Rob, 202 00:15:39,160 --> 00:15:43,610 i que serveixi com a input per al. / hello. 203 00:15:44,790 --> 00:15:49,560 Vostè pot pensar en ell com el primer ressò Rob redirigir a un arxiu 204 00:15:49,560 --> 00:15:54,160 i entreu en. / hola aquest arxiu que s'emeten just. 205 00:15:54,160 --> 00:15:57,850 Però es necessita l'arxiu temporal de la imatge. 206 00:16:01,890 --> 00:16:04,460 >> Les preguntes sobre això? 207 00:16:04,460 --> 00:16:07,150 >> La pregunta que ve serà implicar això. 208 00:16:07,150 --> 00:16:15,310 Què gasoducte podria utilitzar per trobar el nombre de noms únics en un arxiu anomenat nombres.txt? 209 00:16:15,310 --> 00:16:24,160 Les comandes que anem a voler utilitzar aquí són únics, per uniq, a continuació, wc. 210 00:16:24,160 --> 00:16:28,840 Vostè pot fer uniq home a mirar realment el que fa, 211 00:16:28,840 --> 00:16:34,840 i que només va a filtrar les línies que coincideixin adjacents de l'entrada. 212 00:16:34,840 --> 00:16:40,690 I l'home wc voleu imprimir la paraula nova línia, i el recompte de bytes per cada arxiu. 213 00:16:40,690 --> 00:16:43,760 I l'últim que anem a voler utilitzar és una espècie, 214 00:16:43,760 --> 00:16:47,410 que es va a ordenar només les línies d'arxiu txt. 215 00:16:47,410 --> 00:16:58,080 Si faig algun arxiu txt, nombres.txt, i és Rob, Tommy, Joseph, Tommy, Joseph, RJ, Rob, 216 00:16:58,080 --> 00:17:03,910 el que vull fer aquí és trobar el nombre de noms únics en aquest arxiu. 217 00:17:03,910 --> 00:17:08,750 Llavors, què hauria de ser la resposta? >> [Estudiant] 4. Sí >>. 218 00:17:08,750 --> 00:17:13,780 Hauria de ser 4, ja que Rob, Tommy, Joseph, RJ són els únics noms únics en aquest arxiu. 219 00:17:13,780 --> 00:17:20,180 El primer pas, si acabo de fer recompte de paraules en nombres.txt, 220 00:17:20,180 --> 00:17:24,290 això és en realitat em diu tot. 221 00:17:24,290 --> 00:17:32,560 Això és en realitat la impressió - A veure, home wc - noves línies, paraules, i el recompte de bytes. 222 00:17:32,560 --> 00:17:38,270 Si només es preocupen per les línies, llavors només pot fer wc-l nombres.txt. 223 00:17:41,730 --> 00:17:44,300 Així que aquest és el pas 1. 224 00:17:44,300 --> 00:17:50,510 Però jo no vull wc-l nombres.txt nombres.txt perquè només conté tots els noms, 225 00:17:50,510 --> 00:17:54,170 i vull filtrar els éssers no únics. 226 00:17:54,170 --> 00:18:01,200 Així que si ho faig nombres.txt uniq, que no acaba de donar-me el que vull 227 00:18:01,200 --> 00:18:03,760 perquè els noms duplicats encara hi són. 228 00:18:03,760 --> 00:18:07,690 Per què és això? Per què no uniq fer el que vull? 229 00:18:07,690 --> 00:18:10,500 [Estudiant] Els duplicats no són [inaudible] >> Si. 230 00:18:10,500 --> 00:18:16,370 Recordeu que la pàgina de manual per uniq diu filtre de línies coincidents adjacents. 231 00:18:16,370 --> 00:18:19,680 No són adjacents, per la qual cosa no els filtra. 232 00:18:19,680 --> 00:18:31,100 Si ordenar en primer lloc, nombres.txt tipus posarà totes les línies duplicades entre si. 233 00:18:31,100 --> 00:18:34,450 Així que ara nombres.txt espècie és això. 234 00:18:34,450 --> 00:18:40,550 Vaig a voler utilitzar això com l'entrada a uniq, que és | uniq. 235 00:18:40,550 --> 00:18:43,390 Això em dóna Joseph, RJ, Rob, Tommy, 236 00:18:43,390 --> 00:18:49,260 i vull utilitzar això com l'entrada a wc-l, 237 00:18:49,260 --> 00:18:52,740 que em donarà 4. 238 00:18:52,740 --> 00:18:56,930 Com diu aquí, el gasoducte podria utilitzar? 239 00:18:56,930 --> 00:19:01,390 Vostè pot fer un munt de coses com l'ús d'una sèrie d'ordres 240 00:19:01,390 --> 00:19:05,130 on s'utilitza la sortida d'una ordre com a entrada per l'ordre següent. 241 00:19:05,130 --> 00:19:08,780 Vostè pot fer un munt de coses, un munt de coses intel · ligents. 242 00:19:08,780 --> 00:19:11,440 >> Preguntes? 243 00:19:12,910 --> 00:19:14,600 Bé. 244 00:19:14,600 --> 00:19:17,880 Això és per les canonades i la redirecció. 245 00:19:18,370 --> 00:19:24,090 >> Ara anem a les coses reals, les coses codificació. 246 00:19:24,090 --> 00:19:29,100 Dins d'aquest PDF, podràs veure aquesta comanda, 247 00:19:29,100 --> 00:19:32,950 i vol executar aquesta comanda a l'aparell. 248 00:19:36,240 --> 00:19:42,250 wget és la comanda per només aconseguir alguna cosa d'Internet, en el fons, 249 00:19:42,250 --> 00:19:45,180 així wget URL i això. 250 00:19:45,180 --> 00:19:49,110 Si va anar a la següent adreça URL al navegador, es descarrega l'arxiu. 251 00:19:49,110 --> 00:19:52,510 M'acaba de fer clic, de manera que l'arxiu descarregat per a mi. 252 00:19:52,510 --> 00:19:55,650 Però escriure wget d'aquesta cosa dins de la terminal 253 00:19:55,650 --> 00:19:58,620 només va a descarregar en el seu terminal. 254 00:19:58,620 --> 00:20:02,750 Tinc section5.zip, i vol descomprimir section5.zip, 255 00:20:02,750 --> 00:20:06,520 que et donarà una carpeta anomenada Secció 5, 256 00:20:06,520 --> 00:20:11,550 que tindrà tots els arxius que utilitzarem avui dia dins d'ella. 257 00:20:33,380 --> 00:20:37,710 Com els noms d'aquests programes suggereixen arxius, són una mica buggy, 258 00:20:37,710 --> 00:20:40,990 pel que la seva missió és esbrinar per què utilitzar gdb. 259 00:20:40,990 --> 00:20:44,560 Tothom els ha descarregat / saber com els ha descarregat 260 00:20:44,560 --> 00:20:47,480 en el seu electrodomèstic? Bé. 261 00:20:47,480 --> 00:20:56,400 >> Execució de ./buggy1, dirà segmentation fault (core dumped), 262 00:20:56,400 --> 00:21:00,500 que cada vegada que rep un error de segmentació, és negatiu. 263 00:21:00,500 --> 00:21:03,810 En quines circumstàncies es pot aconseguir una violació de segment? 264 00:21:03,810 --> 00:21:08,210 [Estudiant] desreferenciación un punter nul. Sí >>. Així que és un exemple. 265 00:21:08,210 --> 00:21:11,580 Desreferenciación un punter nul vas a aconseguir una violació de segment. 266 00:21:11,580 --> 00:21:16,720 El que significa és una violació de segment que està tocant de memòria que no s'ha de tocar. 267 00:21:16,720 --> 00:21:21,350 Així desreferencia un punter nul està tocant l'adreça 0, 268 00:21:21,350 --> 00:21:28,060 i, bàsicament, tots els ordinadors avui en dia diuen que el 0 és l'adreça de memòria que no s'ha de tocar. 269 00:21:28,060 --> 00:21:31,920 Així que per això es produeix una eliminació de referències a punters nuls en una violació de segment. 270 00:21:31,920 --> 00:21:37,210 Quan et quedes a no inicialitzar un punter, llavors té un valor escombraries, 271 00:21:37,210 --> 00:21:41,520 i així, quan s'intenta eliminar la referència que, amb tota probabilitat, vostè està tocant memòria 272 00:21:41,520 --> 00:21:43,540 que està al mig del no-res. 273 00:21:43,540 --> 00:21:45,650 Si li passa a tenir sort i el valor de les escombraries 274 00:21:45,650 --> 00:21:48,440 pas perquè apunti a algun lloc a la pila o alguna cosa, 275 00:21:48,440 --> 00:21:50,820 després quan desreferencia punter que els que no s'ha inicialitzat, 276 00:21:50,820 --> 00:21:52,730 res sortirà malament. 277 00:21:52,730 --> 00:21:55,480 Però si s'està assenyalant, per exemple, en algun lloc entre la pila i el heap, 278 00:21:55,480 --> 00:21:59,850 o és simplement apuntant a algun lloc que no ha estat utilitzat pel programa, però, 279 00:21:59,850 --> 00:22:02,240 llavors vostè està tocant de memòria que no s'ha de tocar i segfault tu. 280 00:22:02,240 --> 00:22:06,370 En escriure una funció recursiva i recursivament massa vegades 281 00:22:06,370 --> 00:22:08,720 i la seva pila és massa gran i xoca amb les coses de la pila 282 00:22:08,720 --> 00:22:12,270 que no ha de xocar amb, estàs tocant de memòria que no s'ha de tocar, 283 00:22:12,270 --> 00:22:14,810 per la qual cosa violació de segment. 284 00:22:14,810 --> 00:22:17,010 Això és el que és una violació de segment. 285 00:22:17,010 --> 00:22:21,810 >> També és la mateixa raó que si vostè té una cadena com - 286 00:22:21,810 --> 00:22:23,930 anem a tornar al programa anterior. 287 00:22:23,930 --> 00:22:28,530 En hello.c--sóc només farà altra cosa. 288 00:22:28,530 --> 00:22:33,770 char * s = "hola món"; 289 00:22:33,770 --> 00:22:42,310 Si utilitzo * s = alguna cosa o es [0] = 'X'; 290 00:22:42,310 --> 00:22:47,290 així que hola. / hola, per què aquesta violació de segment? 291 00:22:48,410 --> 00:22:51,250 Per què aquesta violació de segment? 292 00:22:55,660 --> 00:22:57,890 Què espera que passi? 293 00:22:57,890 --> 00:23:06,640 Si ho fes printf ("% s \ n", s), el que es pot esperar per ser imprès? 294 00:23:06,640 --> 00:23:09,930 [Estudiant] X hello. Sí >>. 295 00:23:09,930 --> 00:23:15,140 El problema és que quan es declara una cadena com aquesta, 296 00:23:15,140 --> 00:23:18,190 s és un punter que anirà a la pila, 297 00:23:18,190 --> 00:23:25,880 i el que s està assenyalant és aquesta cadena que està contingut en memòria de només lectura. 298 00:23:25,880 --> 00:23:30,560 Així que només pel nom, la memòria de només lectura, vostè ha d'aconseguir la idea 299 00:23:30,560 --> 00:23:33,010 que si intenta canviar el que hi ha en memòria de només lectura, 300 00:23:33,010 --> 00:23:36,670 vostè està fent una cosa que no hauria d'estar fent amb la memòria i la violació de segment tu. 301 00:23:36,670 --> 00:23:45,360 Això és realment una gran diferència entre char * s i char s []. 302 00:23:45,360 --> 00:23:48,790 Així char s [], ara aquesta cadena es posarà a la pila, 303 00:23:48,790 --> 00:23:53,960 i la pila no és de només lectura, el que significa que això hauria de funcionar perfectament bé. 304 00:23:55,500 --> 00:23:57,370 I ho fa. 305 00:23:57,370 --> 00:24:06,250 Recordeu que quan faig char * s = "hola món", s és en si mateix a la pila 306 00:24:06,250 --> 00:24:10,390 però assenyala sa en un altre lloc, i que en un altre lloc passa a ser de només lectura. 307 00:24:10,390 --> 00:24:15,640 Però char s [] és només una cosa a la pila. 308 00:24:17,560 --> 00:24:21,760 Així que aquest és un altre exemple d'una violació de segment succeint. 309 00:24:21,760 --> 00:24:27,820 >> Vam veure que ./buggy1 va donar lloc a una violació de segment. 310 00:24:27,820 --> 00:24:31,810 En teoria, no hauria de mirar buggy1.c immediatament. 311 00:24:31,810 --> 00:24:35,170 En el seu lloc, anem a mirar a través de gdb. 312 00:24:35,170 --> 00:24:37,750 Tingueu en compte que quan vostè aconsegueix segmentation fault (core dumped), 313 00:24:37,750 --> 00:24:40,850 rep aquest arxiu a través d'aquí es diu nucli. 314 00:24:40,850 --> 00:24:45,200 Si ls-l, veurem que el nucli és normalment un arxiu bastant gran. 315 00:24:45,200 --> 00:24:51,580 Aquest és el nombre de bytes de l'arxiu, de manera que sembla que és una cosa de 250 kilobytes. 316 00:24:51,580 --> 00:24:56,120 La raó d'això és que el que el bolcat del nucli és la manera 317 00:24:56,120 --> 00:25:01,410 Es presenta quan el programa es bloqueja, l'estat de la memòria del seu programa 318 00:25:01,410 --> 00:25:05,230 només es copia i s'enganxa en aquest arxiu. 319 00:25:05,230 --> 00:25:07,270 Això s'aboquen en aquest arxiu. 320 00:25:07,270 --> 00:25:13,060 Aquest programa, alhora que corria, va passar a tenir un ús de memòria de prop de 250 kilobytes 321 00:25:13,060 --> 00:25:17,040 i això és el que he abocament en aquest arxiu. 322 00:25:17,040 --> 00:25:23,630 Ara es pot veure a l'arxiu si ho fem gdb nucli buggy1. 323 00:25:23,630 --> 00:25:30,130 Només podem fer gdb buggy1, i que només es posarà en marxa gdb amb regularitat, 324 00:25:30,130 --> 00:25:33,800 utilitzant buggy1 com el seu arxiu d'entrada. 325 00:25:33,800 --> 00:25:38,260 Però si ho fa gdb nucli buggy1, llavors està específicament posarà en marxa gdb 326 00:25:38,260 --> 00:25:40,330 en veure que l'arxiu principal. 327 00:25:40,330 --> 00:25:45,560 I dient buggy1 gdb 1/2 sap que aquest arxiu central prové del programa buggy1. 328 00:25:45,560 --> 00:25:49,580 Així gdb buggy1 nucli va a portar immediatament 329 00:25:49,580 --> 00:25:52,060 als quals el programa va passar a acabar. 330 00:25:57,720 --> 00:26:02,340 Veiem aquí el programa va acabar amb senyal 11, fallada de segmentació. 331 00:26:02,340 --> 00:26:10,110 Ens va passar a veure una línia de muntatge, el que probablement no és molt útil. 332 00:26:10,110 --> 00:26:15,360 Però si escriu bt o backtrace, això serà la funció 333 00:26:15,360 --> 00:26:19,430 que ens dóna la llista dels nostres marcs de pila actual. 334 00:26:19,430 --> 00:26:23,150 Així backtrace. Sembla que només tenim dos marcs de pila. 335 00:26:23,150 --> 00:26:26,310 El primer és el nostre marc de pila principal, 336 00:26:26,310 --> 00:26:29,810 i el segon és el marc de pila per a aquesta funció que ens ha tocat estar, 337 00:26:29,810 --> 00:26:34,440 que sembla que només tenim el codi assemblador per. 338 00:26:34,440 --> 00:26:38,050 Així que anem a tornar a la nostra funció principal, 339 00:26:38,050 --> 00:26:42,300 i per això podem fer un marc, i crec que també podem fer cap avall, 340 00:26:42,300 --> 00:26:45,160 però gairebé mai ho fan cap avall - amunt o avall. Si. 341 00:26:45,160 --> 00:26:50,710 A dalt ia baix. Fins que ens porta a un marc de pila, sota et porta a baix un marc de pila. 342 00:26:50,710 --> 00:26:53,240 Tendeixo a cap utilitat específica. 343 00:26:53,240 --> 00:26:59,120 Acabo de dir específicament el quadre 1, que es vagi al fotograma amb l'etiqueta 1. 344 00:26:59,120 --> 00:27:01,750 Quadre 1 ens posarà en marc de pila principal, 345 00:27:01,750 --> 00:27:05,570 i diu que aquí la línia de codi que ens trobem en. 346 00:27:05,570 --> 00:27:07,950 Si volíem un parell de línies de codi, es pot afirmar llista, 347 00:27:07,950 --> 00:27:11,280 i que ens donarà totes les línies de codi que l'envolten. 348 00:27:11,280 --> 00:27:13,360 La línia que estava en segfaulted 6: 349 00:27:13,360 --> 00:27:17,360 if (strcmp ("CS50 roques", argv [1]) == 0). 350 00:27:17,360 --> 00:27:24,130 Si no està clar, però, vostè pot anar directament des d'aquí només pensar per què segfaulted. 351 00:27:24,130 --> 00:27:28,800 Però podem fer un pas més i dir: "Per què argv [1] violació de segment?" 352 00:27:28,800 --> 00:27:38,830 Anem a imprimir argv [1], i sembla que és 0x0, que és el punter nul. 353 00:27:38,830 --> 00:27:44,750 Estem strcmping CS50 roques i nuls, per el que va a violació de segment. 354 00:27:44,750 --> 00:27:48,280 I per què és argv [1] null? 355 00:27:48,640 --> 00:27:51,280 [Estudiant] A causa que no li va donar cap argument de línia d'ordres. 356 00:27:51,280 --> 00:27:53,390 Si. Nosaltres no li va donar cap argument de línia d'ordres. 357 00:27:53,390 --> 00:27:58,460 Així ./buggy1 només tindrà argv [0] sigui ./buggy1. 358 00:27:58,460 --> 00:28:02,100 No tindrà un argv [1], de manera que va a violació de segment. 359 00:28:02,100 --> 00:28:07,450 Però si, en canvi, ho faig només CS50, dirà que et donen un D 360 00:28:07,450 --> 00:28:09,950 perquè això és el que se suposa que ha de fer. 361 00:28:09,950 --> 00:28:15,240 Quant a buggy1.c, se suposa que d'imprimir "S'obté una D" - 362 00:28:15,240 --> 00:28:20,820 Si argv [1] no és "CS50 roques", "Vostè obté una D", del "S'obté una A!" 363 00:28:20,820 --> 00:28:25,660 Així que si volem una A, necessitem això per comparar com a veritable, 364 00:28:25,660 --> 00:28:28,710 el que significa que es compara amb 0. 365 00:28:28,710 --> 00:28:31,100 Així que argv [1] ha de ser "pedres" CS50. 366 00:28:31,100 --> 00:28:35,660 Si vols fer això a la línia de comandes, ha d'utilitzar \ per escapar a l'espai. 367 00:28:35,660 --> 00:28:41,690 Així CS50 \ roques i s'obté una A! 368 00:28:41,690 --> 00:28:44,060 Si no fa la barra invertida, per què no funciona? 369 00:28:44,060 --> 00:28:47,190 [Estudiant] Es tracta de dos arguments diferents. Sí >>. 370 00:28:47,190 --> 00:28:52,540 Argv [1] serà CS50, i argv [2] serà roques. Bé. 371 00:28:52,540 --> 00:28:56,470 >> Ara ./buggy2 va a violació de segment nou. 372 00:28:56,470 --> 00:29:01,880 En lloc d'obrir l'arxiu amb el seu nucli, només haurem d'obrir buggy2 directament, 373 00:29:01,880 --> 00:29:05,000 així gdb buggy2. 374 00:29:05,000 --> 00:29:09,590 Ara bé, si acaba d'executar el programa, llavors dirà el programa va rebre SIGSEGV, 375 00:29:09,590 --> 00:29:15,530 que és l'error de segmentació del senyal, i aquí és on va succeir a succeir. 376 00:29:15,530 --> 00:29:21,250 Quant al nostre backtrace, veiem que estàvem al oh_no funció, 377 00:29:21,250 --> 00:29:23,900 que va ser cridat pel Dinky funció, que va ser cridat pel binky funció, 378 00:29:23,900 --> 00:29:26,460 que va ser convocada per principal. 379 00:29:26,460 --> 00:29:31,680 També podem veure els arguments per a aquestes funcions. 380 00:29:31,680 --> 00:29:34,680 L'argument de mala mort i binky va ser d'1. 381 00:29:34,680 --> 00:29:44,390 Si tenim a punt la funció oh_no, veiem que només està fent oh_no char ** s = NULL; 382 00:29:44,390 --> 00:29:47,410 * S = "BOOM"; 383 00:29:47,410 --> 00:29:50,330 Per què no? 384 00:29:54,330 --> 00:29:58,380 [Estudiant] No es pot eliminar la referència al punter nul? Sí >>. 385 00:29:58,380 --> 00:30:06,090 Això és només dir s és NULL, independentment de si que passa a ser un char **, 386 00:30:06,090 --> 00:30:12,070 que, depenent de com s'interpreti, podria ser un punter a un punter a una cadena 387 00:30:12,070 --> 00:30:15,550 o una matriu de cadenes. 388 00:30:15,550 --> 00:30:21,430 És s és NULL, pel que * s es desreferencia un punter nul, 389 00:30:21,430 --> 00:30:24,800 de manera que aquest es va a estavellar. 390 00:30:24,800 --> 00:30:27,540 Aquesta és una de les maneres més ràpides li sigui possible violació de segment. 391 00:30:27,540 --> 00:30:31,300 És simplement declarar un punter nul i segfaulting immediatament. 392 00:30:31,300 --> 00:30:34,570 Això és el que oh_no està fent. 393 00:30:34,570 --> 00:30:43,400 Si pugem un marc, llavors entrarem en la funció que va cridar oh_no. 394 00:30:43,400 --> 00:30:44,830 He de fer això. 395 00:30:44,830 --> 00:30:48,610 Si no s'introdueix una ordre i premeu Enter, 396 00:30:48,610 --> 00:30:52,350 s'acaba de repetir la comanda anterior que es va executar. 397 00:30:52,350 --> 00:30:56,610 Som al quadre 1. 398 00:30:56,610 --> 00:31:04,650 Afegir aquest marc, veiem aquí és la nostra funció. 399 00:31:04,650 --> 00:31:08,520 Vostè pot colpejar llista de nou, o pots fer la llista 20 i una llista de més. 400 00:31:08,520 --> 00:31:13,640 La funció Dinky diu que si i és 1, llavors aneu a la funció oh_no, 401 00:31:13,640 --> 00:31:15,960 sinó va a la funció furtiu. 402 00:31:15,960 --> 00:31:18,700 I sé que és 1 perquè ens ha tocat veure aquí 403 00:31:18,700 --> 00:31:22,560 Dinky que s'ha anomenat amb l'argument 1. 404 00:31:22,560 --> 00:31:27,560 O pot simplement puc imprimir i dirà i és 1. 405 00:31:27,560 --> 00:31:33,770 Actualment estem en mala mort, i si ens anem a un altre marc, sabem que acabarà en binky. 406 00:31:33,770 --> 00:31:36,600 Amunt. Ara estem en binky. 407 00:31:36,600 --> 00:31:41,340 Afegir aquesta funció - la llista d'abans del descans em va interrompre - 408 00:31:41,340 --> 00:31:52,670 el que va començar com si i és 0, llavors anem a cridar oh_no, que truqui mala mort. 409 00:31:52,670 --> 00:31:57,000 Sabem que era 1, de manera que va cridar de mala mort. 410 00:31:57,000 --> 00:32:05,030 I ara que estem de tornada en main, i principal és només serà int i = rand ()% 3; 411 00:32:05,030 --> 00:32:08,790 Això només va a donar-li un nombre aleatori que és 0, 1 o 2. 412 00:32:08,790 --> 00:32:12,780 Es dirà binky amb aquest nombre, i el tornarà 0. 413 00:32:12,780 --> 00:32:16,700 Quant a això, 414 00:32:16,700 --> 00:32:19,880 caminant a través del programa de forma manual sense executar immediatament, 415 00:32:19,880 --> 00:32:25,400 hauria d'establir un punt de trencament en la principal, el que significa que quan es corre el programa 416 00:32:25,400 --> 00:32:31,020 seu programa s'executa fins que s'arriba a un punt d'inflexió. 417 00:32:31,020 --> 00:32:35,450 Llavors, executar el programa, s'executarà i després arribarà a la funció principal i deixar de córrer. 418 00:32:35,450 --> 00:32:44,700 Ara estem dins de la principal, i el pas següent o ens portarà a la següent línia de codi. 419 00:32:44,700 --> 00:32:47,050 Vostè pot fer el pas o la següent. 420 00:32:47,050 --> 00:32:51,800 Colpejar següent, ara m'ha estat ajustat a rand ()% 3, de manera que podem imprimir el valor de i, 421 00:32:51,800 --> 00:32:55,280 i ho vaig a dir que és 1. 422 00:32:55,280 --> 00:32:58,110 Ara bé, no importa si fem servir o següent pas. 423 00:32:58,110 --> 00:33:01,000 Suposo que importava en l'anterior, però ens agradaria utilitzar a continuació. 424 00:33:01,000 --> 00:33:06,000 Si fem servir pas, entrem en la funció, el que significa veure la cosa real 425 00:33:06,000 --> 00:33:07,940 que està succeint dins de Binky. 426 00:33:07,940 --> 00:33:10,510 Si fem servir següent, llavors vol dir anar sobre la funció 427 00:33:10,510 --> 00:33:14,070 i només ha d'anar a la següent línia de codi en la nostra funció principal. 428 00:33:14,070 --> 00:33:17,900 Aquí mateix, en aquesta línia, jo estava on deia rand ()% 3; 429 00:33:17,900 --> 00:33:21,320 si ho vaig fer pas, entraria en l'execució de rand 430 00:33:21,320 --> 00:33:25,110 i veure el que està passant allà, i podria passar per la funció rand. 431 00:33:25,110 --> 00:33:26,920 Però no es preocupen per la funció rand. 432 00:33:26,920 --> 00:33:30,190 Només vull anar a la següent línia de codi al principal, de manera que utilitzarà a continuació. 433 00:33:30,190 --> 00:33:35,800 Però ara sí que m'importa sobre la funció binky, així que vull entrar en això. 434 00:33:35,800 --> 00:33:37,730 Ara estic en binky. 435 00:33:37,730 --> 00:33:42,040 La primera línia de codi que dirà if (i == 0), faig un pas, 436 00:33:42,040 --> 00:33:44,930 veiem que acabem en mala mort. 437 00:33:44,930 --> 00:33:51,620 Si nosaltres, les coses de la llista, veiem que el revisi i és = 0. 438 00:33:51,620 --> 00:33:55,470 i no és igual a 0, de manera que es va anar a la condició més, 439 00:33:55,470 --> 00:33:59,540 que es dirà Dinky (i). 440 00:33:59,540 --> 00:34:04,030 És possible que es confongui. 441 00:34:04,030 --> 00:34:07,380 Si només s'observa en aquestes línies directament, es podria pensar if (i == 0), 442 00:34:07,380 --> 00:34:10,800 bé, llavors vaig donar un pas i ara estic en Dinky (i), 443 00:34:10,800 --> 00:34:14,120 es podria pensar que ha de significar i = 0 o alguna cosa així. 444 00:34:14,120 --> 00:34:18,980 No Només vol dir que sap que pot enganxar directament a la línia Dinky (i). 445 00:34:18,980 --> 00:34:23,300 Perquè no és 0, el següent pas no s'acabarà en l'altre. 446 00:34:23,300 --> 00:34:26,239 Més no és una línia que va a parar al. 447 00:34:26,239 --> 00:34:31,570 És només anirà a la següent línia en realitat pot executar, que és Dinky (i). 448 00:34:31,570 --> 00:34:36,090 En entrar a Dinky (i), veiem if (i == 1). 449 00:34:36,090 --> 00:34:42,670 El que sí que sé = 1, així que quan fem un pas, sabem que acabarem en oh_no 450 00:34:42,670 --> 00:34:46,489 i = 1, perquè crida a la funció oh_no, que es pot caminar en, 451 00:34:46,489 --> 00:34:52,969 que s'establirà char ** s = NULL i immediatament "BOOM". 452 00:34:54,270 --> 00:34:59,690 I després mirant realment l'aplicació de buggy2, 453 00:34:59,690 --> 00:35:04,590 això, m'acaba d'obtenir un nombre aleatori - 0, 1, o 2 - anomenat Binky, 454 00:35:04,590 --> 00:35:10,610 que si i és 0 en diu oh_no, del que anomena Dinky, que arriba fins aquí. 455 00:35:10,610 --> 00:35:18,100 Si i és 1, anomenada oh_no, que cridi Slinky, que ve aquí, 456 00:35:18,100 --> 00:35:20,460 si i és 2, trucar oh_no. 457 00:35:20,460 --> 00:35:24,720 Ni tan sols crec que hi hagi una manera - 458 00:35:24,720 --> 00:35:30,030 Algú veu una manera de fer d'aquest un programa que no violació de segment? 459 00:35:30,030 --> 00:35:37,530 Perquè si no em falta alguna cosa, si i és 0, vostè immediatament violació de segment, 460 00:35:37,530 --> 00:35:41,250 res més que anar a una funció que si i és vostè un error de segmentació, 461 00:35:41,250 --> 00:35:44,540 res més que anar a una funció en la qual si i és 2 que violació de segment. 462 00:35:44,540 --> 00:35:46,810 Així que no importa el que facis, violació de segment. 463 00:35:46,810 --> 00:35:52,380 >> Crec que una manera d'arreglar seria en lloc de fer char ** s = NULL, 464 00:35:52,380 --> 00:35:55,610 vostè podria malloc espai per aquesta cadena. 465 00:35:55,610 --> 00:36:04,230 Podríem fer malloc (sizeof) - sizeof què? 466 00:36:09,910 --> 00:36:15,190 [Estudiant] (char) * 5? >> Això sembla correcte? 467 00:36:15,190 --> 00:36:21,060 Assumeixo que això va a funcionar si realment va funcionar, però no és el que estic buscant. 468 00:36:24,400 --> 00:36:32,940 Mira el tipus de s. Anem a afegir * int, int mode * x. 469 00:36:32,940 --> 00:36:35,600 M'agradaria fer malloc (sizeof (int)). 470 00:36:35,600 --> 00:36:40,490 O hom volia una matriu de 5, ho faria (sizeof (int) * 5); 471 00:36:40,490 --> 00:36:44,210 Què passa si tinc un int **? 472 00:36:46,260 --> 00:36:49,140 El que jo faria malloc? 473 00:36:49,140 --> 00:36:53,510 [Estudiant] Mida del punter. Sí >>. (Sizeof (int *)); 474 00:36:53,510 --> 00:36:56,960 El mateix aquí. 475 00:36:56,960 --> 00:37:01,280 Vull (sizeof (char *)); 476 00:37:06,170 --> 00:37:12,840 Això va a assignar espai per al punter que apunta a "BOOM". 477 00:37:12,840 --> 00:37:15,330 No cal fer reserva espai per "BOOM" en si 478 00:37:15,330 --> 00:37:17,210 perquè això és bàsicament equivalent al que vaig dir abans 479 00:37:17,210 --> 00:37:20,870 de char * x = "BOOM". 480 00:37:20,870 --> 00:37:27,950 "BOOM" ja existeix. Succeeix que hi ha a la regió de només lectura de la memòria. 481 00:37:27,950 --> 00:37:35,200 Però el que ja existeix, el que significa que aquesta línia de codi, si s és un char **, 482 00:37:35,200 --> 00:37:43,900 llavors s * és un char * i que està configurant aquest char * per indicar "BOOM". 483 00:37:43,900 --> 00:37:50,040 Si volia copiar "BOOM" en si, llavors jo hauria de assignar espai per al 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 Per què cinc? 486 00:38:06,210 --> 00:38:10,860 4 Per què no? Sembla que "BOOM" és de 4 caràcters. >> [Estudiant] El caràcter nul. 487 00:38:10,860 --> 00:38:14,580 Si. Totes les cadenes van a necessitar el caràcter nul. 488 00:38:14,580 --> 00:38:23,590 Ara puc fer alguna cosa com strcat - Quina és la funció per copiar una cadena? 489 00:38:23,590 --> 00:38:28,520 [Estudiant] cpy? >> Strcpy. 490 00:38:28,520 --> 00:38:32,700 home strcpy. 491 00:38:36,120 --> 00:38:39,590 Així strcpy o strncpy. 492 00:38:39,590 --> 00:38:43,410 strncpy és una mica més segur ja que es pot especificar amb exactitud el nombre de caràcters, 493 00:38:43,410 --> 00:38:46,190 però en aquest cas no importa perquè el que sabem. 494 00:38:46,190 --> 00:38:50,340 Així strcpy i mirar en els arguments. 495 00:38:50,340 --> 00:38:53,100 El primer argument és el nostre destí. 496 00:38:53,100 --> 00:38:56,770 El segon argument és la nostra font. 497 00:38:56,770 --> 00:39:10,310 Anem a copiar al nostre destí * s el punter "BOOM". 498 00:39:10,310 --> 00:39:19,820 Per què voldria fer això amb un strcpy en lloc del que teníem abans 499 00:39:19,820 --> 00:39:22,800 de * s = "BOOM"? 500 00:39:22,800 --> 00:39:28,630 Hi ha una raó potser voldreu fer això, però què és això? 501 00:39:28,630 --> 00:39:31,940 [Estudiant] Per canviar alguna cosa al "BOOM". Sí >>. 502 00:39:31,940 --> 00:39:37,950 Ara puc fer alguna cosa com s [0] = 'X'; 503 00:39:37,950 --> 00:39:48,190 perquè els punts es al munt i espai que en el munt que s està apuntant a 504 00:39:48,190 --> 00:39:52,320 és un punter a més espai a la pila, que és l'emmagatzematge de "BOOM". 505 00:39:52,320 --> 00:39:55,150 Així que aquesta còpia de "BOOM" s'emmagatzema en el munt. 506 00:39:55,150 --> 00:39:58,780 Hi tècnicament dues còpies del "boom" del nostre programa. 507 00:39:58,780 --> 00:40:03,500 No és el primer que s'acaba de donar per aquesta constant cadena "BOOM", 508 00:40:03,500 --> 00:40:09,250 i la segona còpia del "boom", strcpy va crear la còpia de "BOOM". 509 00:40:09,250 --> 00:40:13,100 No obstant això, la còpia de "BOOM" s'emmagatzema a la pila, i el munt ets lliure de canviar. 510 00:40:13,100 --> 00:40:17,250 La pila no és de només lectura, el que significa que es [0] 511 00:40:17,250 --> 00:40:20,500 permetrà que vostè canviï el valor de "BOOM". 512 00:40:20,500 --> 00:40:23,130 Això permetrà canviar aquests caràcters. 513 00:40:23,130 --> 00:40:26,640 >> Preguntes? 514 00:40:27,740 --> 00:40:29,290 Bé. 515 00:40:29,290 --> 00:40:35,500 >> Passant a buggy3, gdb anem buggy3. 516 00:40:35,500 --> 00:40:39,840 Acabem de córrer i veiem que obtenim una violació de segment. 517 00:40:39,840 --> 00:40:46,550 Si backtrace, només hi ha dues funcions. 518 00:40:46,550 --> 00:40:52,970 Si pugem a la nostra funció principal, veiem que segfaulted en aquesta línia. 519 00:40:52,970 --> 00:41:00,180 Així que només mirar aquesta línia, for (int fila = 0; fgets això fa NULL no és igual; 520 00:41:00,180 --> 00:41:03,770 línia + +). 521 00:41:03,770 --> 00:41:08,010 El nostre quadre anterior es deia _IO_fgets. 522 00:41:08,010 --> 00:41:10,720 Vostè veurà que una gran quantitat de funcions integrades C, 523 00:41:10,720 --> 00:41:15,350 que quan arribi la violació de segment, hi haurà noms de les funcions realment críptic 524 00:41:15,350 --> 00:41:18,090 com aquest _IO_fgets. 525 00:41:18,090 --> 00:41:21,770 Però això va a relacionar amb aquesta convocatòria fgets. 526 00:41:21,770 --> 00:41:25,850 En algun lloc dins d'aquí, estem segfaulting. 527 00:41:25,850 --> 00:41:30,340 Si ens fixem en els arguments a fgets, podem imprimir buffer. 528 00:41:30,340 --> 00:41:41,180 Anem a imprimir com - Oh, no. 529 00:41:48,980 --> 00:41:51,900 Imprimir no funcionarà exactament com jo vull que faci. 530 00:41:55,460 --> 00:41:58,000 Anem a veure el programa actual. 531 00:42:02,200 --> 00:42:09,640 Buffer és una matriu de caràcters. Es tracta d'una matriu de caràcters de 128 caràcters. 532 00:42:09,640 --> 00:42:14,980 Així que quan dic memòria intermèdia d'impressió, d'imprimir aquests 128 caràcters, 533 00:42:14,980 --> 00:42:18,300 que suposo que és el que s'espera. 534 00:42:18,300 --> 00:42:21,390 El que es busca és imprimir la direcció de memòria intermèdia, 535 00:42:21,390 --> 00:42:23,680 però que en realitat no em diu molt. 536 00:42:23,680 --> 00:42:30,770 Així que quan se m'acut dir aquí amortidor x, que em mostra 0xbffff090, 537 00:42:30,770 --> 00:42:38,690 que, si et recordes d'abans o cap punt, Oxbffff tendeix a ser una regió de pila-ish. 538 00:42:38,690 --> 00:42:46,020 La pila tendeix a començar en algun lloc una mica menys de 0xc000. 539 00:42:46,020 --> 00:42:51,890 Només per veure aquesta direcció, ja sé que el buffer està passant a la pila. 540 00:42:51,890 --> 00:43:04,500 Reinici del meu programa, executar, dalt, esmorteir el que vam veure va ser aquesta seqüència de caràcters 541 00:43:04,500 --> 00:43:06,530 que són més o menys sentit. 542 00:43:06,530 --> 00:43:12,270 Després d'imprimir el fitxer, un arxiu sembla? 543 00:43:15,120 --> 00:43:17,310 [Estudiant] Null. Sí >>. 544 00:43:17,310 --> 00:43:22,610 L'arxiu és un de tipus * FILE, pel que és un punter, 545 00:43:22,610 --> 00:43:26,610 i el valor d'aquest punter és nul. 546 00:43:26,610 --> 00:43:33,240 Així fgets es tractarà de llegir aquest punter en forma indirecta, 547 00:43:33,240 --> 00:43:37,320 però per tal d'accedir a aquest punter, que ha de deixar de fer referència. 548 00:43:37,320 --> 00:43:40,550 O bé, per tal d'accedir al que ha d'apuntar a, It desreferencia. 549 00:43:40,550 --> 00:43:43,810 Així que és eliminar la referència a un punter nul i segfaults ella. 550 00:43:46,600 --> 00:43:48,730 Podria haver reiniciat allà. 551 00:43:48,730 --> 00:43:52,170 Si trenquem al nostre punt principal i córrer, 552 00:43:52,170 --> 00:43:57,320 la primera línia de codi és char * filename = "nonexistent.txt"; 553 00:43:57,320 --> 00:44:00,870 Això hauria de donar una pista bastant gran de per què aquest programa falla. 554 00:44:00,870 --> 00:44:06,080 Escrivint següent em porta a la següent línia, en què obrir aquest arxiu, 555 00:44:06,080 --> 00:44:11,140 i llavors immediatament entrar en la nostra línia, on una vegada em va colpejar proper, serà violació de segment. 556 00:44:11,140 --> 00:44:16,880 Algú vol fer una raó per la qual podria ser segfaulting? 557 00:44:16,880 --> 00:44:19,130 [Estudiant] El fitxer no existeix. Sí >>. 558 00:44:19,130 --> 00:44:22,250 Això se suposa que és un indici 559 00:44:22,250 --> 00:44:29,570 que cada vegada que va a obrir un arxiu que vostè necessita per comprovar que l'arxiu existeix en realitat. 560 00:44:29,570 --> 00:44:31,510 Així que aquí, "nonexistent.txt"; 561 00:44:31,510 --> 00:44:34,700 En nom de fitxer fopen per a la lectura, llavors necessito dir 562 00:44:34,700 --> 00:44:45,870 if (arxiu == NULL) i dir printf ("El fitxer no existeix!" 563 00:44:45,870 --> 00:44:56,340 o - millor encara - filename); return 1; 564 00:44:56,340 --> 00:45:00,300 Així que ara comprovem si és NULL 565 00:45:00,300 --> 00:45:03,930 abans de realment continuar i intentar llegir aquest arxiu. 566 00:45:03,930 --> 00:45:08,800 Podem refer només per veure que funciona. 567 00:45:11,020 --> 00:45:14,970 Tenia la intenció d'incloure una nova línia. 568 00:45:21,090 --> 00:45:25,290 Així que ara nonexistent.txt no existeix. 569 00:45:26,890 --> 00:45:30,040 Sempre s'ha de comprovar si aquest tipus de coses. 570 00:45:30,040 --> 00:45:33,870 Sempre s'ha de comprovar per veure si fopen retorna NULL. 571 00:45:33,870 --> 00:45:38,170 Sempre s'ha de comprovar per assegurar-se que malloc no torna NULL, 572 00:45:38,170 --> 00:45:41,410 o en cas contrari violació de segment. 573 00:45:42,200 --> 00:45:45,930 >> Ara buggy4.c. 574 00:45:49,190 --> 00:45:58,440 En execució. Suposo que això està a l'espera de l'entrada o possiblement bucle infinit. 575 00:45:58,440 --> 00:46:01,870 Sí, és un bucle infinit. 576 00:46:01,870 --> 00:46:05,560 Així buggy4. Sembla que estem en bucle infinit. 577 00:46:05,560 --> 00:46:12,590 Podem dividir principal, executeu el programa. 578 00:46:12,590 --> 00:46:20,180 En gdb, sempre que l'abreviatura que s'utilitza és ambigua 579 00:46:20,180 --> 00:46:23,420 o abreviatures especials que ofereixen per a vostè, 580 00:46:23,420 --> 00:46:29,020 llavors vostè pot utilitzar n per utilitzar a continuació en lloc d'haver de escriure al costat tot el camí. 581 00:46:29,020 --> 00:46:33,730 I ara que m'he colpejat núm una vegada, només pot prémer Enter per continuar al costat 582 00:46:33,730 --> 00:46:36,640 en lloc d'haver de prémer Enter n, n Intro, núm Intro. 583 00:46:36,640 --> 00:46:44,630 Sembla com si estigués en una mena de bucle perquè s'ajusti array [i] a 0. 584 00:46:44,630 --> 00:46:50,510 Sembla que mai estic sortint d'aquest bucle for. 585 00:46:50,510 --> 00:46:54,780 Si jo puc imprimir, així que és 2, llavors vaig a anar després. 586 00:46:54,780 --> 00:46:59,250 Vaig a imprimir i, i és 3, llavors vaig a anar després. 587 00:46:59,250 --> 00:47:05,360 Vaig a imprimir i i i és 3. A continuació, imprimiu i, i és 4. 588 00:47:05,360 --> 00:47:14,520 En realitat, la impressió sizeof (array), el que la mida de la matriu és de 20. 589 00:47:16,310 --> 00:47:32,870 Però sembla que hi ha alguna ordre gdb especial per anar fins que alguna cosa passa. 590 00:47:32,870 --> 00:47:37,620 És com fixar una condició sobre el valor de la variable. Però jo no me'n recordo del que és. 591 00:47:37,620 --> 00:47:44,100 Així que si segueix endavant - 592 00:47:44,100 --> 00:47:47,120 Què estava dient? Què has portat cap amunt? 593 00:47:47,120 --> 00:47:50,500 [Estudiant] No mostrar afegeixo - >> Yeah. Així que mostrar el que puc ajudar. 594 00:47:50,500 --> 00:47:54,530 Si ens limitem a mostrar i, es va posar aquí quin és el valor de i és 595 00:47:54,530 --> 00:47:56,470 així que no has de imprimir cada vegada. 596 00:47:56,470 --> 00:48:02,930 Si seguim endavant següent, veiem 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 Alguna cosa va malament, molt malament, i jo es posa a 0. 598 00:48:13,330 --> 00:48:22,220 Quant a buggy4.c, veiem tot el que passa és 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 Què és el que veiem que està malament aquí? 602 00:48:31,390 --> 00:48:39,480 Com una pista, quan estava fent el gdb buggy4 - anem a trencar la marxa principal, - 603 00:48:39,480 --> 00:48:45,980 Jo tenia la impressió sizeof (array) només per veure el que la condició és on finalment esclatés. 604 00:48:47,690 --> 00:48:51,100 On sóc? He córrer? 605 00:48:51,100 --> 00:48:54,280 Jo no declarar encara. 606 00:48:54,280 --> 00:48:58,680 Així imprimir sizeof (array) i això és 20, 607 00:48:58,680 --> 00:49:06,690 que s'espera ja que el meu matriu és de mida 5 i és de 5 punts, 608 00:49:06,690 --> 00:49:12,410 de manera que la cosa sencera ha de ser de 5 * sizeof (int) bytes, on sizeof (int) tendeix a ser 4. 609 00:49:12,410 --> 00:49:14,780 Així sizeof (array) és 20. 610 00:49:14,780 --> 00:49:17,420 Què hauria de ser? 611 00:49:17,420 --> 00:49:21,720 [Estudiant] Dividits per sizeof (int). >> Sí, / sizeof (int). 612 00:49:21,720 --> 00:49:30,630 Sembla que encara hi ha un problema aquí. Crec que això només hauria de ser < 613 00:49:30,630 --> 00:49:36,960 ja que és gairebé sempre 00:49:44,860 Ara anem a pensar en per què això va ser trencat en realitat. 615 00:49:44,860 --> 00:49:53,370 Algú s'endevina per què es em posa a 0 a través de cada iteració del bucle? 616 00:50:01,300 --> 00:50:09,350 L'única cosa dins del que està succeint aquí és que array [i] s'estableix en 0. 617 00:50:09,350 --> 00:50:15,350 D'alguna manera, aquesta línia de codi que està causant nostre int i que s'estableix en 0. 618 00:50:16,730 --> 00:50:23,130 [Estudiant] Podria ser perquè està reemplaçant la memòria d'aquesta part de i 619 00:50:23,130 --> 00:50:27,970 quan es pensa que és el següent element de la matriu? >> [Bowden] Sí 620 00:50:27,970 --> 00:50:33,880 Quan anem més enllà del final de la nostra matriu, 621 00:50:33,880 --> 00:50:39,870 d'alguna manera que l'espai que estem anul · lant està ignorant el valor de i. 622 00:50:39,870 --> 00:50:48,030 I si ens fixem en buggy4, trencar marxa principal, 623 00:50:48,030 --> 00:50:53,120 anem a imprimir la direcció de i. 624 00:50:53,120 --> 00:50:57,280 Sembla com si fos bffff124. 625 00:50:57,280 --> 00:51:03,930 Ara anem a imprimir la direcció de la matriu [0]. 110. 626 00:51:03,930 --> 00:51:06,290 Què passa amb [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] és bfff124. 629 00:51:14,530 --> 00:51:26,990 Així array [5] té la mateixa direcció que jo, el que significa que la matriu [5] és i. 630 00:51:26,990 --> 00:51:30,720 Si tenen la mateixa direcció, són la mateixa cosa. 631 00:51:30,720 --> 00:51:38,410 Així que quan ens vam posar array [5] a 0, estem i en 0. 632 00:51:38,410 --> 00:51:46,070 I si vostè pensa sobre això en termes de la pila, 633 00:51:46,070 --> 00:51:55,590 int i es declara en primer lloc, el que significa que té una mica d'espai a la pila. 634 00:51:55,590 --> 00:52:04,730 Llavors matriu [5] s'assigna, de manera que després de 20 bytes s'assignen a la pila. 635 00:52:04,730 --> 00:52:08,400 Així que s'assignaran en primer lloc, a continuació, aquests 20 bytes s'assignen. 636 00:52:08,400 --> 00:52:11,400 Així que passa just abans de la matriu, 637 00:52:11,400 --> 00:52:19,230 i pel camí, com vaig dir la setmana passada, quan sigui tècnicament la pila creix cap avall, 638 00:52:19,230 --> 00:52:28,520 Quan s'indexa en una matriu, se'ns garanteix que la posició de 0 a de la matriu 639 00:52:28,520 --> 00:52:31,970 sempre passa abans de la primera posició en la matriu. 640 00:52:31,970 --> 00:52:35,900 Això és una mica com ho va fer la setmana passada. 641 00:52:35,900 --> 00:52:42,210 Observeu que a la part inferior tenim l'adreça 0 i en la part superior tenim Max direcció. 642 00:52:42,210 --> 00:52:44,880 La pila sempre creix cap avall. 643 00:52:48,100 --> 00:52:53,500 Diguem que em assignen. 644 00:52:53,500 --> 00:52:59,680 Assignem sencer i, el que significa que direm aquí sencer i s'assignen. 645 00:52:59,680 --> 00:53:06,420 Llavors assignem la nostra matriu de 5 punts, el que significa que sota això, 646 00:53:06,420 --> 00:53:11,230 des que la pila creix cap avall, aquests 5 nombres enters s'assignen. 647 00:53:11,230 --> 00:53:15,900 No obstant això, a causa de com funcionen les matrius, es té la garantia que la primera posició en la matriu 648 00:53:15,900 --> 00:53:22,260 sempre té una direcció inferior a la segona cosa a la matriu. 649 00:53:22,260 --> 00:53:28,270 Així posició 0 array sempre ha de passar primer a la memòria, 650 00:53:28,270 --> 00:53:30,700 mentre que la posició de la matriu 1 ha de succeir després que 651 00:53:30,700 --> 00:53:33,310 i posició de matriu 2 ha de succeir després d'això, 652 00:53:33,310 --> 00:53:37,900 el que significa que la posició 0 array que succeiria en algun lloc per aquí, 653 00:53:37,900 --> 00:53:40,690 posició de matriu 1 passaria per sobre d'aquest 654 00:53:40,690 --> 00:53:45,530 perquè mou cap amunt significa majors adreces des de la direcció màxima és d'aquí. 655 00:53:45,530 --> 00:53:50,490 Així array [0] fins aquí, array [1] aquí, array [2] fins aquí, array [3] fins aquí. 656 00:53:50,490 --> 00:53:55,620 Note com abans hem destinat sencer i tot el camí fins aquí, 657 00:53:55,620 --> 00:54:01,040 a mesura que avancem més i més en el nostre arsenal, estem cada vegada més a prop i més a prop del nostre sencer i. 658 00:54:01,040 --> 00:54:07,640 El que passa és que array [5], que és una posició més enllà de la nostra matriu, 659 00:54:07,640 --> 00:54:13,010 és exactament on sencer i va passar a ser assignat. 660 00:54:13,010 --> 00:54:16,920 Així que aquest és el punt en què ens ha tocat estar colpejant l'espai a la pila 661 00:54:16,920 --> 00:54:21,680 que es van assignar sencer i, i estem establint que a 0. 662 00:54:21,680 --> 00:54:26,160 >> Això és el que funciona. Preguntes? Si. 663 00:54:26,160 --> 00:54:30,710 [Estudiant] És igual. Bé. 664 00:54:30,710 --> 00:54:33,090 [Estudiant] Com evitar aquest tipus d'errors? 665 00:54:33,090 --> 00:54:41,190 Aquesta classe d'errors? No utilitzeu C com a llenguatge de programació. 666 00:54:41,190 --> 00:54:45,840 Utilitza un llenguatge que té límits de la matriu de comprovació. 667 00:54:45,840 --> 00:54:55,900 Sempre que vostè té cura, vostè només ha d'evitar anar més enllà dels límits de la matriu. 668 00:54:55,900 --> 00:54:58,300 [Estudiant] Així que aquí quan vam ser més enllà dels límits de la matriu - 669 00:54:58,300 --> 00:55:01,840 [Bowden] Aquí és on les coses comencen a anar malament. >> [Estudiant] Oh, està bé. 670 00:55:01,840 --> 00:55:05,730 Sempre que es mantingui dins de la memòria assignada per la matriu, estàs bé. 671 00:55:05,730 --> 00:55:12,400 No obstant això, C no realitza comprovacions d'error. Si ho faig matriu [1000], que amb molt de gust n'hi ha prou amb modificar passi el que passi - 672 00:55:12,400 --> 00:55:16,500 Es va al principi de la matriu, llavors es va després de 1000 posicions i l'estableix a 0. 673 00:55:16,500 --> 00:55:20,000 No fa cap comprovació que oh, això no té realment 1000 coses en ell. 674 00:55:20,000 --> 00:55:22,750 1000 és molt més del que hauria d'estar canviant, 675 00:55:22,750 --> 00:55:26,940 mentre que Java o alguna cosa que vostè obtindrà la matriu fora de límits índex 676 00:55:26,940 --> 00:55:29,820 o l'índex d'excepció límits. 677 00:55:29,820 --> 00:55:33,950 És per això que una gran quantitat de llenguatges d'alt nivell té aquestes coses 678 00:55:33,950 --> 00:55:37,340 on si vostè va més enllà dels límits de la matriu, que no vagi 679 00:55:37,340 --> 00:55:40,070 de manera que vostè no pot canviar les coses des de baix que 680 00:55:40,070 --> 00:55:42,590 i llavors les coses van molt pitjor del que acaba d'aconseguir una excepció 681 00:55:42,590 --> 00:55:44,940 dient que anava més enllà del final de la matriu. 682 00:55:44,940 --> 00:55:50,970 [Estudiant] I així ho hem canviat el <= a només > [Bowden] Yeah. 683 00:55:50,970 --> 00:55:54,800 Ha de ser 00:55:59,560 des sizeof (array) és de 20, però només volem 5. >> [Estudiant] Dret. 685 00:55:59,560 --> 00:56:04,060 Més preguntes? Bé. 686 00:56:04,060 --> 00:56:07,380 >> [Estudiant] Tinc una pregunta. Sí >>. 687 00:56:07,380 --> 00:56:16,440 [Estudiant] Quina és la variable de matriu real? 688 00:56:16,440 --> 00:56:20,000 [Bowden] Igual que el que és matriu? 689 00:56:20,000 --> 00:56:24,930 Matriu en si és un símbol. 690 00:56:24,930 --> 00:56:31,490 És només l'adreça de començament dels 20 bytes que es fa referència. 691 00:56:31,490 --> 00:56:38,070 Vostè pot pensar en ell com un punter, però és un punter constant. 692 00:56:38,070 --> 00:56:44,140 Així que les coses es compila, la matriu de la variable ja no existeix. 693 00:56:44,140 --> 00:56:48,210 [Estudiant] Llavors, com trobar la mida de la matriu? 694 00:56:48,210 --> 00:56:54,130 Mida de matriu es refereix a la mida d'aquest bloc que fa referència a aquest símbol. 695 00:56:54,130 --> 00:57:01,240 Quan faig alguna cosa com printf ("% p \ n", array); 696 00:57:01,240 --> 00:57:05,140 anem a córrer. 697 00:57:12,960 --> 00:57:15,530 Què acabo de fer el mal? 698 00:57:15,530 --> 00:57:19,220 'Array' Matriu declarat aquí. 699 00:57:20,820 --> 00:57:23,200 Oh, aquí dalt. 700 00:57:23,200 --> 00:57:31,250 Clang és intel · ligent, i passa a notar que jo vaig declarar la matriu com 5 elements 701 00:57:31,250 --> 00:57:34,540 però estic en posició d'indexació 1000. 702 00:57:34,540 --> 00:57:38,450 Es pot fer això perquè aquests són només constants. 703 00:57:38,450 --> 00:57:43,370 Només es pot arribar a adonar-se que jo vaig més enllà dels límits de la matriu. 704 00:57:43,370 --> 00:57:46,880 Però noti abans, quan havíem de ser incorrecta, 705 00:57:46,880 --> 00:57:51,040 no és possible de determinar quants valors que podria assumir, 706 00:57:51,040 --> 00:57:55,540 pel que no pot determinar que i anava més enllà del final de la matriu. 707 00:57:55,540 --> 00:57:59,430 Això és només Clang ser intel · ligent. 708 00:57:59,430 --> 00:58:03,340 >> Però ara fer buggy4. Llavors, què estic fent malament? 709 00:58:03,340 --> 00:58:05,970 Implícitament es declara funció de biblioteca 'printf'. 710 00:58:05,970 --> 00:58:14,960 Vaig a voler incloure # . 711 00:58:14,960 --> 00:58:18,710 Bé. Ara executa buggy4. 712 00:58:18,710 --> 00:58:24,840 Impressió del valor de la matriu com ho vaig fer aquí, imprimir com un punter 713 00:58:24,840 --> 00:58:30,060 imprimeix una cosa que són aquestes - bfb8805c - que és una mica de direcció 714 00:58:30,060 --> 00:58:33,450 que és a la regió de pila-ish. 715 00:58:33,450 --> 00:58:41,820 Matriu en si és com un punter, però no és un punter real, 716 00:58:41,820 --> 00:58:45,410 des d'un punter normal que podem canviar. 717 00:58:45,410 --> 00:58:54,700 Array és només una constant. Els 20 blocs de memòria començarà a les 0xbfb8805c direcció. 718 00:58:54,700 --> 00:59:09,020 Així bfb8805c través d'aquesta adreça +20--o suposo -20 - 719 00:59:09,020 --> 00:59:17,400 és tota la memòria assignada a aquesta matriu. 720 00:59:17,400 --> 00:59:20,350 Array, la pròpia variable no s'emmagatzema en qualsevol lloc. 721 00:59:20,350 --> 00:59:27,660 Quan està compilant el compilador - onada mà-hi - 722 00:59:27,660 --> 00:59:33,060 el compilador només s'utilitzen on coneix matriu a ser. 723 00:59:33,060 --> 00:59:36,090 Se sap que la matriu s'inicia, 724 00:59:36,090 --> 00:59:40,910 i pel que sempre pot fer les coses en termes de compensacions d'aquest principi. 725 00:59:40,910 --> 00:59:43,960 No es necessita una variable en si per representar matriu. 726 00:59:43,960 --> 00:59:53,730 Però quan faig alguna cosa com int * p = array, ara que p és un punter que apunta a la matriu, 727 00:59:53,730 --> 00:59:57,830 i ara p en realitat no existeix a la pila. 728 00:59:57,830 --> 01:00:01,950 Sóc lliure per canviar p. Que puc fer p = malloc. 729 01:00:01,950 --> 01:00:06,500 Per tant, inicialment va assenyalar a la matriu, i ara apunta a un cert espai en el munt. 730 01:00:06,500 --> 01:00:09,620 No puc fer array = malloc. 731 01:00:09,620 --> 01:00:13,710 Si Clang és intel · ligent, em cridis la dreta del pal. 732 01:00:17,000 --> 01:00:21,430 De fet, estic bastant segur gcc de fer això també. 733 01:00:21,430 --> 01:00:25,010 Així que tipus de matriu 'int [5]' no és assignable. 734 01:00:25,010 --> 01:00:28,040 No es pot assignar alguna cosa a un tipus de matriu 735 01:00:28,040 --> 01:00:30,500 perquè la matriu és simplement una constant. 736 01:00:30,500 --> 01:00:34,760 És un símbol que fa referència a aquests 20 bytes. No ho puc canviar. 737 01:00:34,760 --> 01:00:37,690 >> [Estudiant] I on és la mida de la matriu emmagatzemada? 738 01:00:37,690 --> 01:00:40,670 [Bowden] No s'emmagatzema en qualsevol lloc. És quan està compilant. 739 01:00:40,670 --> 01:00:46,310 Llavors, on és la mida de la matriu emmagatzemada? 740 01:00:46,310 --> 01:00:51,870 Només es pot utilitzar sizeof (array) dins de la funció que la matriu s'hagi declarat. 741 01:00:51,870 --> 01:01:03,150 Així que si faig alguna funció, foo, i ho faig (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 i després per aquí em diuen foo (array); 744 01:01:21,330 --> 01:01:24,840 dins d'aquesta funció - anem a executar-lo. 745 01:01:34,200 --> 01:01:36,840 Es tracta de ser intel · ligent Clang nou. 746 01:01:36,840 --> 01:01:43,890 M'està dient que sizeof paràmetre de matriu en funció 747 01:01:43,890 --> 01:01:46,690 tornarà mida de 'int'. 748 01:01:46,690 --> 01:01:55,150 Això seria un error si no és el que jo volia que succeís. 749 01:01:55,150 --> 01:01:58,960 Anem realment apagar Werror. 750 01:02:14,950 --> 01:02:17,590 Advertència. Les advertències estan bé. 751 01:02:17,590 --> 01:02:19,960 Encara es compilarà el temps que té una advertència. 752 01:02:19,960 --> 01:02:22,910 . / A.out voleu imprimir 4. 753 01:02:22,910 --> 01:02:28,650 L'advertència que s'ha generat és un indicador clar del que va sortir malament. 754 01:02:28,650 --> 01:02:34,120 Aquesta matriu int és només voleu imprimir sizeof (int *). 755 01:02:34,120 --> 01:02:39,790 Fins i tot si poso matriu [5] aquí, segueix sent només voleu imprimir sizeof (int *). 756 01:02:39,790 --> 01:02:47,440 Així que tan aviat com vostè ho passa a una funció, la distinció entre matrius i punters 757 01:02:47,440 --> 01:02:49,670 és inexistent. 758 01:02:49,670 --> 01:02:52,640 Això passa a ser una matriu que es va declarar a la pila, 759 01:02:52,640 --> 01:02:58,300 però tan bon punt es passa aquest valor, que 0xbf bla, bla, bla, en aquesta funció, 760 01:02:58,300 --> 01:03:03,350 a continuació, aquest punter apunta a la matriu en la pila. 761 01:03:03,350 --> 01:03:08,310 Així que això significa que sizeof només s'aplica en la funció que el conjunt va ser declarat, 762 01:03:08,310 --> 01:03:11,230 el que significa que quan s'està compilant aquesta funció, 763 01:03:11,230 --> 01:03:17,330 Clang quan passa a través d'aquesta funció, veu matriu és una matriu de int mida 5. 764 01:03:17,330 --> 01:03:20,640 Així ho veu sizeof (array). Bé, això és 20. 765 01:03:20,640 --> 01:03:26,440 Això és en realitat com sizeof bàsicament funciona per a gairebé tots els casos. 766 01:03:26,440 --> 01:03:31,150 Sizeof no és una funció, és un operador. 767 01:03:31,150 --> 01:03:33,570 No cridi a la funció sizeof. 768 01:03:33,570 --> 01:03:38,280 Sizeof (int), el compilador només la traduirà a 4. 769 01:03:41,480 --> 01:03:43,700 Ho tens? Bé. 770 01:03:43,700 --> 01:03:47,520 >> [Estudiant] Quina és la diferència entre sizeof (array) de principal i en foo? 771 01:03:47,520 --> 01:03:52,840 Això és perquè estem dient sizeof (array), que és de tipus int *, 772 01:03:52,840 --> 01:03:57,120 mentre que la matriu d'aquí baix no és de tipus int *, és una matriu int. 773 01:03:57,120 --> 01:04:04,540 >> [Estudiant] Per tant, si vostè tenia el paràmetre de matriu [] en lloc de la matriu * int, 774 01:04:04,540 --> 01:04:09,230 Vol dir que encara podria canviar matriu perquè ara és un punter? 775 01:04:09,230 --> 01:04:14,250 [Bowden] D'aquesta manera? >> [Estudiant] Yeah. Es pot canviar array dins de la funció ara? 776 01:04:14,250 --> 01:04:18,420 [Bowden] Vostè podria canviar la matriu en ambdós casos. 777 01:04:18,420 --> 01:04:23,130 En ambdós casos, vostè és lliure de dir array [4] = 0. 778 01:04:23,130 --> 01:04:26,590 [Estudiant] Però pot vostè fer punt matriu a una altra cosa? 779 01:04:26,590 --> 01:04:30,230 [Bowden] Oh. Si. En qualsevol dels casos - >> [estudiant] Yeah. 780 01:04:30,230 --> 01:04:38,410 [Bowden] La distinció entre array [] i una matriu int *, no n'hi ha cap. 781 01:04:38,410 --> 01:04:42,570 També pot obtenir alguns matriu multidimensional aquí 782 01:04:42,570 --> 01:04:47,050 per alguna sintaxi convenient, però encara és només un indicador. 783 01:04:47,050 --> 01:04:56,400 Això vol dir que sóc lliure de fer array = malloc (sizeof (int)), i ara apunten a un altre lloc. 784 01:04:56,400 --> 01:04:59,610 Però igual que com això funciona sempre i sempre, 785 01:04:59,610 --> 01:05:03,210 canviar aquesta matriu fent que apunti a una altra cosa 786 01:05:03,210 --> 01:05:07,570 no canvia aquesta matriu per aquí perquè és una còpia de l'argument, 787 01:05:07,570 --> 01:05:10,780 no és un punter a aquest argument. 788 01:05:10,780 --> 01:05:16,070 I de fet, així com la indicació més que és exactament el mateix - 789 01:05:16,070 --> 01:05:21,100 ja hem vist el que s'imprimeix la matriu d'impressió - 790 01:05:21,100 --> 01:05:31,410 el que si imprimim la direcció de la matriu o la direcció de la direcció de la matriu 791 01:05:31,410 --> 01:05:36,290 a qualsevol d'aquests? 792 01:05:41,770 --> 01:05:45,220 Anem a passar per alt això. 793 01:05:48,140 --> 01:05:51,660 Bé. Això està bé. Ara està en marxa. / A.out. 794 01:05:51,660 --> 01:06:00,220 Matriu d'impressió, i després imprimir la direcció de la matriu, són la mateixa cosa. 795 01:06:00,220 --> 01:06:02,870 Matriu simplement no existeix. 796 01:06:02,870 --> 01:06:08,190 Se sap quan voleu imprimir array, que voleu el símbol que es refereix a aquests 20 bytes. 797 01:06:08,190 --> 01:06:11,940 Impressió de la direcció de la matriu, així, la matriu no existeix. 798 01:06:11,940 --> 01:06:17,200 No té una direcció, de manera que només imprimeix la direcció d'aquests 20 bytes. 799 01:06:20,820 --> 01:06:28,150 Així que es compila cap avall, com si buggy4 compilat. / A.out, 800 01:06:28,150 --> 01:06:30,340 matriu és inexistent. 801 01:06:30,340 --> 01:06:33,640 Punters existeix. Les matrius no. 802 01:06:34,300 --> 01:06:38,060 Els blocs de memòria que representa el conjunt encara existeix, 803 01:06:38,060 --> 01:06:43,270 però la matriu de variables i variables d'aquest tipus no existeixen. 804 01:06:46,260 --> 01:06:50,270 Aquests són com les principals diferències entre les matrius i punters 805 01:06:50,270 --> 01:06:55,590 estan tan aviat com feu trucades a funcions, no hi ha cap diferència. 806 01:06:55,590 --> 01:07:00,460 Però dins de la funció que la pròpia matriu es declara, sizeof funciona de manera diferent 807 01:07:00,460 --> 01:07:05,190 ja que voleu imprimir la mida dels blocs en lloc de la mida del tipus, 808 01:07:05,190 --> 01:07:08,950 i no es pot canviar perquè és un símbol. 809 01:07:08,950 --> 01:07:14,370 Impressió de la cosa i la direcció de la cosa imprimeix la mateixa cosa. 810 01:07:14,370 --> 01:07:18,480 I això és més o menys la mateixa. 811 01:07:18,480 --> 01:07:20,820 [Estudiant] Podria vostè dir que una vegada més? 812 01:07:21,170 --> 01:07:24,170 Em podria haver passat alguna cosa per alt. 813 01:07:24,170 --> 01:07:29,260 Matriu d'impressió i la direcció de la matriu imprimeix la mateixa cosa, 814 01:07:29,260 --> 01:07:33,180 mentre que si s'imprimeix un punter davant de la direcció del punter, 815 01:07:33,180 --> 01:07:36,010 l'única cosa que imprimeix la direcció del que estàs assenyalant, 816 01:07:36,010 --> 01:07:40,360 l'altre imprimeix la direcció del punter a la pila. 817 01:07:40,360 --> 01:07:47,040 Pot canviar un punter, no es pot canviar un símbol de matriu. 818 01:07:47,740 --> 01:07:53,270 I punter sizeof s'imprimirà la mida d'aquest tipus de punter. 819 01:07:53,270 --> 01:07:57,470 Així int * p sizeof (p) d'imprimir 4, 820 01:07:57,470 --> 01:08:04,110 però int array [5] impressió sizeof (array) es va a imprimir 20. 821 01:08:04,110 --> 01:08:07,480 [Estudiant] Així int array [5] s'imprimiran 20? Sí >>. 822 01:08:07,480 --> 01:08:13,300 És per això que dins buggy4 quan el que solia ser sizeof (array) 823 01:08:13,300 --> 01:08:16,660 això feia jo <20, que no és el que volíem. 824 01:08:16,660 --> 01:08:20,880 Volem i <5. >> [Estudiant] Bé. 825 01:08:20,880 --> 01:08:25,569 [Bowden] I després, tan aviat com vostè comenci a passar a les funcions, 826 01:08:25,569 --> 01:08:34,340 si ho féssim int * p = array; 827 01:08:34,340 --> 01:08:39,779 dins d'aquesta funció, que bàsicament pot utilitzar p i matriu en exactament les mateixes formes, 828 01:08:39,779 --> 01:08:43,710 excepte pel problema sizeof i el problema canviant. 829 01:08:43,710 --> 01:08:49,810 Però p [0] = 1, és el mateix que dir array [0] = 1; 830 01:08:49,810 --> 01:08:55,600 I tan bon punt diem foo (array), o foo (p); 831 01:08:55,600 --> 01:08:59,760 dins de la funció foo, aquesta és la mateixa trucada dues vegades. 832 01:08:59,760 --> 01:09:03,350 No hi ha cap diferència entre aquestes dues trucades. 833 01:09:07,029 --> 01:09:11,080 >> Tothom bo en això? Bé. 834 01:09:14,620 --> 01:09:17,950 Tenim 10 minuts. 835 01:09:17,950 --> 01:09:28,319 >> Tractarem d'aconseguir a través d'aquest programa Typer Hacker, 836 01:09:28,319 --> 01:09:32,350 Aquest lloc web, que va sortir l'any passat o alguna cosa així. 837 01:09:34,149 --> 01:09:41,100 És només suposa que és com s'escriu l'atzar i s'imprimeix - 838 01:09:41,100 --> 01:09:46,729 Qualsevol que sigui l'arxiu que resulta haver carregat és el que sembla que està escrivint. 839 01:09:46,729 --> 01:09:52,069 Sembla una espècie de codi del sistema operatiu. 840 01:09:53,760 --> 01:09:56,890 Això és el que volem fer. 841 01:10:08,560 --> 01:10:11,690 Vostè ha de tenir un binari executable anomenat hacker_typer 842 01:10:11,690 --> 01:10:14,350 que porta en un sol argument, l'arxiu de "tipus hacker." 843 01:10:14,350 --> 01:10:16,480 Executar l'executable ha d'esborrar la pantalla 844 01:10:16,480 --> 01:10:20,850 i després imprimir un caràcter del fitxer passat com cada vegada que l'usuari prem una tecla. 845 01:10:20,850 --> 01:10:24,990 Així que qualsevol tecla que premeu, s'ha de rebutjar i en el seu lloc mostra un personatge de l'arxiu 846 01:10:24,990 --> 01:10:27,810 que és l'argument. 847 01:10:29,880 --> 01:10:34,350 Jo gairebé li dirà quines són les coses que necessitarem saber el són. 848 01:10:34,350 --> 01:10:36,440 Però volem revisar la biblioteca termios. 849 01:10:36,440 --> 01:10:44,840 Mai he utilitzat aquesta biblioteca en tota la meva vida, el que té efectes molt mínims. 850 01:10:44,840 --> 01:10:48,610 Però això serà la biblioteca es pot utilitzar per rebutjar el caràcter que va colpejar 851 01:10:48,610 --> 01:10:52,390 quan s'està escrivint en estàndard polz 852 01:10:56,970 --> 01:11:05,840 Així hacker_typer.c, i anem a voler incloure # . 853 01:11:05,840 --> 01:11:12,870 Quant a la pàgina del manual de termios - estic endevinant que la terminal US o alguna cosa així - 854 01:11:12,870 --> 01:11:16,240 No sé com llegir-lo. 855 01:11:16,240 --> 01:11:21,040 Quant a això, es diu per incloure aquests dos arxius, de manera que farem això. 856 01:11:37,620 --> 01:11:46,820 >> Primer el primer, volem prendre en un sol argument, que és l'arxiu que s'ha d'obrir. 857 01:11:46,820 --> 01:11:52,420 Llavors, què és el que vull fer? Com puc comprovar que tinc un sol argument? 858 01:11:52,420 --> 01:11:56,480 [Estudiant] Si argc és igual. >> [Bowden] Yeah. 859 01:11:56,480 --> 01:12:21,250 Així que si (argc = 2!) Printf ("Ús:% s [arxiu per obrir]"). 860 01:12:21,250 --> 01:12:32,750 Així que ara si em quedo, sense aportar un segon argument - oh, necessito la nova línia - 861 01:12:32,750 --> 01:12:36,240 veuràs que diu ús:. / hacker_typer, 862 01:12:36,240 --> 01:12:39,770 i després el segon argument ha de ser el fitxer que voleu obrir. 863 01:12:58,430 --> 01:13:01,260 I ara què faig? 864 01:13:01,260 --> 01:13:08,490 Vull llegir d'aquest arxiu. Com puc llegir un arxiu? 865 01:13:08,490 --> 01:13:11,920 [Estudiant] Vostè obrir primer. Sí >>. 866 01:13:11,920 --> 01:13:15,010 Així fopen. Què fopen sembla? 867 01:13:15,010 --> 01:13:22,980 [Estudiant] Nom del fitxer. >> [Bowden] Nom de l'arxiu que serà argv [1]. 868 01:13:22,980 --> 01:13:26,110 [Estudiant] I llavors, què vols fer amb ell, així que el - >> [Bowden] Yeah. 869 01:13:26,110 --> 01:13:28,740 Així que si no s'acordava, es podia fer fopen home, 870 01:13:28,740 --> 01:13:32,960 on serà un camí const char * on ruta és nom de fitxer, 871 01:13:32,960 --> 01:13:34,970 manera const char *. 872 01:13:34,970 --> 01:13:38,660 Si per casualitat vostè no recorda quina manera és així, llavors vostè pot buscar la manera. 873 01:13:38,660 --> 01:13:44,660 A l'interior de les pàgines de manual, el caràcter de barra és el que pot utilitzar per buscar les coses. 874 01:13:44,660 --> 01:13:49,790 Així que escriure / mode per buscar la manera. 875 01:13:49,790 --> 01:13:57,130 ni N són el que vostè pot utilitzar per desplaçar-se per les coincidències de cerca. 876 01:13:57,130 --> 01:13:59,800 Aquí es diu que els argument manera apunta a una cadena 877 01:13:59,800 --> 01:14:01,930 començant amb una de les seqüències següents. 878 01:14:01,930 --> 01:14:06,480 Així que r, arxiu de text obert per a la lectura. Això és el que vull fer. 879 01:14:08,930 --> 01:14:13,210 Per llegir, i vull guardar això. 880 01:14:13,210 --> 01:14:18,720 La cosa serà un arxiu *. Ara, què és el que vull fer? 881 01:14:18,720 --> 01:14:21,200 Dóna'm un segon. 882 01:14:28,140 --> 01:14:30,430 Bé. Ara, què és el que vull fer? 883 01:14:30,430 --> 01:14:32,940 [Estudiant] Comproveu que és NULL. >> [Bowden] Yeah. 884 01:14:32,940 --> 01:14:38,690 Cada vegada que s'obre un arxiu, assegureu-vos que vostè és capaç amb èxit per obrir-lo. 885 01:14:58,930 --> 01:15:10,460 >> Ara vull fer aquestes coses termios on vull llegir primer la configuració actual 886 01:15:10,460 --> 01:15:14,050 i salvar aquells en alguna cosa, llavors vull canviar les meves configuracions 887 01:15:14,050 --> 01:15:19,420 llençar a les escombraries qualsevol personatge que m'escrigui, 888 01:15:19,420 --> 01:15:22,520 i després vull actualitzar aquests valors. 889 01:15:22,520 --> 01:15:27,250 I després, al final del programa, vull tornar al meu configuració original. 890 01:15:27,250 --> 01:15:32,080 Així que l'estructura serà de termios tipus, i ho vaig a voler-ne dos. 891 01:15:32,080 --> 01:15:35,600 La primera d'elles serà la meva current_settings, 892 01:15:35,600 --> 01:15:42,010 i després seran meus hacker_settings. 893 01:15:42,010 --> 01:15:48,070 En primer lloc, vaig a voler arxivar els paràmetres actuals, 894 01:15:48,070 --> 01:15:53,790 llavors vaig a voler actualitzar hacker_settings, 895 01:15:53,790 --> 01:16:01,570 i després camí al final del meu programa, vull tornar a la configuració actual. 896 01:16:01,570 --> 01:16:08,660 Així que arxivar els paràmetres actuals, la manera com funciona, termios home. 897 01:16:08,660 --> 01:16:15,810 Veiem que tenim aquest tcsetattr int, int tcgetattr. 898 01:16:15,810 --> 01:16:22,960 Pas en una estructura termios pel seu punter. 899 01:16:22,960 --> 01:16:30,640 La manera com es veurà és - HE oblidat i al que la funció va ser cridada. 900 01:16:30,640 --> 01:16:34,930 Copiar i enganxar. 901 01:16:39,150 --> 01:16:45,500 Així tcgetattr, llavors vull passar en l'estructura que estic estalviant la informació, 902 01:16:45,500 --> 01:16:49,650 que serà current_settings, 903 01:16:49,650 --> 01:16:59,120 i el primer argument és el descriptor d'arxiu per al que vull per guardar els atributs de. 904 01:16:59,120 --> 01:17:04,360 Què és el descriptor de fitxer és com cada vegada que obri un arxiu, s'obté un descriptor d'arxiu. 905 01:17:04,360 --> 01:17:14,560 Quan fopen argv [1], s'obté un descriptor de fitxer que es fa referència 906 01:17:14,560 --> 01:17:16,730 cada vegada que es vol llegir o escriure-hi. 907 01:17:16,730 --> 01:17:19,220 Aquest no és el descriptor de fitxer que voleu utilitzar aquí. 908 01:17:19,220 --> 01:17:21,940 Hi ha tres descriptors d'arxiu que té per defecte, 909 01:17:21,940 --> 01:17:24,310 que són estàndard, sortida d'estàndard i l'error estàndard. 910 01:17:24,310 --> 01:17:29,960 Per defecte, crec que és estàndard en és 0, la sortida estàndard és 1, i l'error estàndard és de 2. 911 01:17:29,960 --> 01:17:33,980 Llavors, què és el que vull canviar la configuració de? 912 01:17:33,980 --> 01:17:37,370 Vull canviar la configuració de cada vegada que em va tocar un personatge, 913 01:17:37,370 --> 01:17:41,590 Vull que llençar aquest caràcter immediat en lloc d'imprimir a la pantalla. 914 01:17:41,590 --> 01:17:45,960 Què corrent - estàndard in, out estàndard o error estàndard - 915 01:17:45,960 --> 01:17:52,050 respon a les coses quan escric en el teclat? >> [Estudiant] Standard polzades >> Yeah. 916 01:17:52,050 --> 01:17:56,450 Així que pot fer de 0 o jo puguem fer stdin. 917 01:17:56,450 --> 01:17:59,380 M'estic posant l'estàndard de current_settings polz 918 01:17:59,380 --> 01:18:01,720 >> Ara vull actualitzar aquests valors, 919 01:18:01,720 --> 01:18:07,200 el primer que vaig a copiar en hacker_settings el que els meus current_settings són. 920 01:18:07,200 --> 01:18:10,430 I com és el treball structs s'acaba de copiar. 921 01:18:10,430 --> 01:18:14,510 Això còpia tots els camps, com era d'esperar. 922 01:18:14,510 --> 01:18:17,410 >> Ara vull actualitzar alguns dels camps. 923 01:18:17,410 --> 01:18:21,670 Quant a termios, vostè hauria de llegir a través d'una gran quantitat d'aquest 924 01:18:21,670 --> 01:18:24,110 només per veure el que vostè vol buscar, 925 01:18:24,110 --> 01:18:28,210 però les banderes que vostè va a voler tenir en compte són ressò, 926 01:18:28,210 --> 01:18:33,110 així ECHO Echo caràcters d'entrada. 927 01:18:33,110 --> 01:18:37,710 En primer lloc vull deixar - HE oblidat i al que els camps són. 928 01:18:45,040 --> 01:18:47,900 Això és el que l'estructura s'assembla. 929 01:18:47,900 --> 01:18:51,060 Així modes d'entrada Crec que voleu canviar. 930 01:18:51,060 --> 01:18:54,210 Veurem la solució per assegurar-se que és el que volem canviar. 931 01:19:04,060 --> 01:19:12,610 Volem canviar lflag per tal d'evitar haver de buscar a través de tots aquests. 932 01:19:12,610 --> 01:19:14,670 Volem canviar les maneres locals. 933 01:19:14,670 --> 01:19:17,710 Vostè hauria de llegir tota aquesta cosa a entendre que tot pertany 934 01:19:17,710 --> 01:19:19,320 que volem canviar. 935 01:19:19,320 --> 01:19:24,120 Però és a l'interior de les maneres locals on anem a voler canviar això. 936 01:19:27,080 --> 01:19:33,110 Així hacker_settings.cc_lmode és el que es diu. 937 01:19:39,630 --> 01:19:43,020 c_lflag. 938 01:19:49,060 --> 01:19:52,280 Aquí és on ens fiquem en els operadors bit a bit. 939 01:19:52,280 --> 01:19:54,860 Estem una mica fora de temps, però anem a anar a través d'ell molt ràpid. 940 01:19:54,860 --> 01:19:56,600 Aquí és on ens fiquem en els operadors bit a bit, 941 01:19:56,600 --> 01:19:59,950 on crec que vaig dir un cop fa molt de temps que cada vegada de començar a tractar amb banderes, 942 01:19:59,950 --> 01:20:03,370 vostè estarà utilitzant l'operador bit a bit molt. 943 01:20:03,370 --> 01:20:08,240 Cada bit de la bandera correspon a algun tipus de comportament. 944 01:20:08,240 --> 01:20:14,090 Així que aquí, aquest indicador té un munt de coses diferents, on tots ells signifiquen alguna cosa diferent. 945 01:20:14,090 --> 01:20:18,690 Però el que vull fer és apagar el bit que correspon a ECHO. 946 01:20:18,690 --> 01:20:25,440 Així que per apagar això que faig i = ¬ ECHO. 947 01:20:25,440 --> 01:20:30,110 En realitat, crec que és com sostre o alguna cosa així. Vaig a comprovar de nou. 948 01:20:30,110 --> 01:20:34,050 Puc termios. És només ECHO. 949 01:20:34,050 --> 01:20:38,440 ECHO serà un sol bit. 950 01:20:38,440 --> 01:20:44,230 ¬ ECHO voldrà dir que tots els bits estan posats a 1, el que significa que tots els indicadors s'estableixen en true 951 01:20:44,230 --> 01:20:47,140 excepte per al bit d'ECHO. 952 01:20:47,140 --> 01:20:53,830 En posar fi als meus banderes properes amb això, vol dir totes les banderes que estan establertes actualment en true 953 01:20:53,830 --> 01:20:56,520 Encara s'estableix en true. 954 01:20:56,520 --> 01:21:03,240 Si la meva bandera ECHO s'estableix en true, llavors aquest és necessàriament estableix false a la bandera ECHO. 955 01:21:03,240 --> 01:21:07,170 Així que aquesta línia de codi només s'apaga l'indicador d'ECHO. 956 01:21:07,170 --> 01:21:16,270 Les altres línies de codi, només vaig a copiar en l'interès de temps i després explicar-los. 957 01:21:27,810 --> 01:21:30,180 En la solució, diu 0. 958 01:21:30,180 --> 01:21:33,880 És probable que sigui millor dir explícitament stdin. 959 01:21:33,880 --> 01:21:42,100 >> Recordeu que també estic fent ECHO | ICANON aquí. 960 01:21:42,100 --> 01:21:46,650 ICANON es refereix a alguna cosa diferent, és a dir, la manera canònic. 961 01:21:46,650 --> 01:21:50,280 Què significa la manera canònic és en general quan s'està escrivint la línia d'ordres, 962 01:21:50,280 --> 01:21:54,670 estàndard no processa res fins que arribis nova línia. 963 01:21:54,670 --> 01:21:58,230 Així que quan vostè GetString, escriu un munt de coses, llavors vostè colpeja nova línia. 964 01:21:58,230 --> 01:22:00,590 Va ser llavors quan s'envia a l'estàndard polz 965 01:22:00,590 --> 01:22:02,680 Aquest és el valor predeterminat. 966 01:22:02,680 --> 01:22:05,830 Quan desactiveu el mode canònic, ara cada personatge prem 967 01:22:05,830 --> 01:22:10,910 és el que es processa, que sol ser una mica malament perquè és lent per processar aquestes coses, 968 01:22:10,910 --> 01:22:14,330 pel que és bo per esmorteir en línies senceres. 969 01:22:14,330 --> 01:22:16,810 Però vull que cada personatge per ser processat 970 01:22:16,810 --> 01:22:18,810 ja que no vull que m'esperis per colpejar de nova línia 971 01:22:18,810 --> 01:22:21,280 abans de processar tots els personatges que he estat escrivint. 972 01:22:21,280 --> 01:22:24,760 Això desactiva la manera canònic. 973 01:22:24,760 --> 01:22:31,320 Aquestes coses només vol dir quan en realitat processa caràcters. 974 01:22:31,320 --> 01:22:35,830 Això significa processar immediatament, tan bon punt els estic escrivint, processar-los. 975 01:22:35,830 --> 01:22:42,510 I aquesta és la funció que està actualitzant la meva configuració estàndard a dins, 976 01:22:42,510 --> 01:22:45,480 i mitjans TCSA fer-ho ara mateix. 977 01:22:45,480 --> 01:22:50,310 Les altres opcions són esperar que tot el que es troba actualment en el corrent es processa. 978 01:22:50,310 --> 01:22:52,030 Això realment no importa. 979 01:22:52,030 --> 01:22:56,920 Just en aquest moment pot canviar les meves configuracions per ser el que actualment es troba en hacker_typer_settings. 980 01:22:56,920 --> 01:23:02,210 Suposo que el va anomenar hacker_settings, així que anem a canviar això. 981 01:23:09,610 --> 01:23:13,500 Canviar tot per hacker_settings. 982 01:23:13,500 --> 01:23:16,870 >> Ara, al final del nostre programa voldrem tornar 983 01:23:16,870 --> 01:23:20,210 al que és en l'actualitat dins de normal_settings, 984 01:23:20,210 --> 01:23:26,560 que es veurà igual i normal_settings. 985 01:23:26,560 --> 01:23:30,650 Tingueu en compte que no he canviat cap dels meus normal_settings ja que originalment aconseguint. 986 01:23:30,650 --> 01:23:34,520 Llavors per simplement canviar de nou, els passa de nou al final. 987 01:23:34,520 --> 01:23:38,390 Aquesta va ser l'actualització. Bé. 988 01:23:38,390 --> 01:23:43,900 >> Ara dins d'aquí només explicaré el codi en nom del temps. 989 01:23:43,900 --> 01:23:46,350 No és que molt. 990 01:23:50,770 --> 01:24:03,750 Veiem, llegim un caràcter de l'arxiu. L'anomenem f. 991 01:24:03,750 --> 01:24:07,850 Ara vostè pot l'home fgetc, però com fgetc va a funcionar 992 01:24:07,850 --> 01:24:11,910 només es tornarà el caràcter que vostè acaba de llegir o EOF, 993 01:24:11,910 --> 01:24:15,680 que es correspon amb el final de l'arxiu o algun succés d'error. 994 01:24:15,680 --> 01:24:19,900 Estem bucle, sense deixar de llegir un sol caràcter de les actuacions, 995 01:24:19,900 --> 01:24:22,420 fins que ens hem quedat sense caràcters a llegir. 996 01:24:22,420 --> 01:24:26,650 I ja que estem fent això, esperem en un sol caràcter de norma polz 997 01:24:26,650 --> 01:24:29,090 Cada vegada que escrigui alguna cosa en la línia d'ordres, 998 01:24:29,090 --> 01:24:32,820 que està llegint en un personatge de nivell polz 999 01:24:32,820 --> 01:24:38,330 Llavors putchar és només posarà el carbó llegim aquí dalt des de l'arxiu de sortida estàndard. 1000 01:24:38,330 --> 01:24:42,890 Pot putchar home, però és només posar en la sortida estàndard, s'imprimeix aquest caràcter. 1001 01:24:42,890 --> 01:24:51,600 També pot simplement fer printf ("% c", c); La mateixa idea. 1002 01:24:53,330 --> 01:24:56,670 Això farà la major part del nostre treball. 1003 01:24:56,670 --> 01:25:00,300 >> L'últim que vas a voler fer és fclose nostre arxiu. 1004 01:25:00,300 --> 01:25:03,310 Si no fclose, això és una pèrdua de memòria. 1005 01:25:03,310 --> 01:25:06,680 Volem fclose l'arxiu que es va obrir originalment, i crec que això és tot. 1006 01:25:06,680 --> 01:25:13,810 Si fem això, jo ja tinc problemes. 1007 01:25:13,810 --> 01:25:17,260 Anem a veure. 1008 01:25:17,260 --> 01:25:19,960 Què és el que queixar? 1009 01:25:19,960 --> 01:25:30,220 S'esperava 'int' però l'argument és de tipus 'struct _IO_FILE *'. 1010 01:25:36,850 --> 01:25:39,370 A veure si això funciona. 1011 01:25:45,210 --> 01:25:53,540 Només permès a C99. Augh. Està bé, fer hacker_typer. 1012 01:25:53,540 --> 01:25:57,760 Ara tenim descripcions més útils. 1013 01:25:57,760 --> 01:25:59,900 Per tant l'ús d'identificador no declarat "normal_settings '. 1014 01:25:59,900 --> 01:26:04,170 Jo no el va anomenar normal_settings. El vaig trucar current_settings. 1015 01:26:04,170 --> 01:26:12,090 Així que anem a canviar tot això. 1016 01:26:17,920 --> 01:26:21,710 Ara passa argument. 1017 01:26:26,290 --> 01:26:29,500 Vaig a fer això 0 per ara. 1018 01:26:29,500 --> 01:26:36,720 Bé. . / Hacker_typer cp.c. 1019 01:26:36,720 --> 01:26:39,590 Jo també no esborrar la pantalla al principi. 1020 01:26:39,590 --> 01:26:42,960 Però vostè pot mirar cap enrere al conjunt últim problema per veure com netejar la pantalla. 1021 01:26:42,960 --> 01:26:45,160 És simplement imprimir alguns caràcters 1022 01:26:45,160 --> 01:26:47,210 mentre que això està fent el que vull fer. 1023 01:26:47,210 --> 01:26:48,900 Bé. 1024 01:26:48,900 --> 01:26:55,280 I pensant en per què això havia de ser 0 en lloc de l'entrada estàndard, 1025 01:26:55,280 --> 01:27:00,560 que ha de ser # defineix 0, 1026 01:27:00,560 --> 01:27:03,890 aquest es queixa que - 1027 01:27:13,150 --> 01:27:19,360 Abans, quan he dit que no hi ha descriptors d'arxiu, però després també tens el teu * FILE, 1028 01:27:19,360 --> 01:27:23,210 un descriptor d'arxiu és només un únic nombre enter, 1029 01:27:23,210 --> 01:27:26,970 mentre que un FILE * té un munt de coses associada a ella. 1030 01:27:26,970 --> 01:27:30,380 La raó per la qual hem de dir 0 en lloc de l'entrada estàndard 1031 01:27:30,380 --> 01:27:37,480 és que stdin és un FILE * que apunta al que fa referència descriptor d'arxiu 0. 1032 01:27:37,480 --> 01:27:45,070 Així que fins aquí quan faig fopen (argv [1], m'estic posant un * fitxer. 1033 01:27:45,070 --> 01:27:51,180 Però en algun lloc on * FILE és una cosa que correspon al descriptor d'arxiu per a l'arxiu. 1034 01:27:51,180 --> 01:27:57,430 Si ens fixem en la pàgina del manual de obert, així que crec que hauré de fer man 3 obert - No - 1035 01:27:57,430 --> 01:27:59,380 man 2 obert - si. 1036 01:27:59,380 --> 01:28:06,250 Si ens fixem en la pàgina d'obert, obert és com un fopen de nivell inferior, 1037 01:28:06,250 --> 01:28:09,350 i es torna el descriptor d'arxiu real. 1038 01:28:09,350 --> 01:28:12,050 fopen fa un munt de coses sobre obert, 1039 01:28:12,050 --> 01:28:17,640 que en lloc de tornar només el descriptor de fitxer retorna un arxiu complet punter * 1040 01:28:17,640 --> 01:28:20,590 dins dels quals és el nostre descriptor d'arxiu petit. 1041 01:28:20,590 --> 01:28:25,020 Així estàndard es refereix a la cosa * FILE, 1042 01:28:25,020 --> 01:28:29,120 mentre que 0 es refereix només a la norma descriptor de fitxer en si mateix. 1043 01:28:29,120 --> 01:28:32,160 >> Preguntes? 1044 01:28:32,160 --> 01:28:35,930 [Rialles] va bufar a través d'això. 1045 01:28:35,930 --> 01:28:39,140 Està bé. Hem acabat. [Rialles] 1046 01:28:39,140 --> 01:28:42,000 >> [CS50.TV]