1 00:00:00,000 --> 00:00:02,500 [Powered by Google Translate] [§ 5 - Mer komfortabelt] 2 00:00:02,500 --> 00:00:04,690 [Rob Bowden - Harvard University] 3 00:00:04,690 --> 00:00:07,250 [Dette er CS50. - CS50.TV] 4 00:00:08,990 --> 00:00:14,250 >> Som jeg sa i min e-post, er det mange ting du kan bruke 5 00:00:14,250 --> 00:00:17,060 annet enn apparatet til å faktisk gjøre problemet sett. 6 00:00:17,060 --> 00:00:19,910 Vi anbefaler at du gjør det i skapet bare fordi da kan vi lettere hjelpe deg 7 00:00:19,910 --> 00:00:22,070 og vi vet hvordan alt skal fungere. 8 00:00:22,070 --> 00:00:26,950 Men som et eksempel på hvor du kan gjøre ting hvis, sier, trenger du ikke har tilgang 9 00:00:26,950 --> 00:00:31,570 et apparat eller du ønsker å jobbe i Science Center kjelleren - 10 00:00:31,570 --> 00:00:33,090 som faktisk har de apparatet også - 11 00:00:33,090 --> 00:00:35,150 Hvis du ønsker å jobbe hvor som helst. 12 00:00:35,150 --> 00:00:42,370 Et eksempel er at du har sett / hørt om SSH? 13 00:00:44,380 --> 00:00:47,780 SSH er i utgangspunktet akkurat som å koble til noe. 14 00:00:47,780 --> 00:00:51,340 Egentlig akkurat nå er jeg SSHed inn i apparatet. 15 00:00:51,340 --> 00:00:54,290 Jeg har aldri arbeide direkte i apparatet. 16 00:00:55,930 --> 00:01:01,060 Her er apparatet, og hvis du ser ned her ser du denne IP-adressen. 17 00:01:01,060 --> 00:01:03,650 Jeg har aldri jobbe i selve apparatet; 18 00:01:03,650 --> 00:01:08,840 Jeg kommer alltid bort til en iTerm2 vindu / terminal-vinduet. 19 00:01:08,840 --> 00:01:15,910 Du kan SSH til at IP-adressen, jharvard@192.168.129.128 ssh. 20 00:01:15,910 --> 00:01:20,390 Jeg husker at antallet veldig lett fordi det er slik et fint mønster. 21 00:01:20,390 --> 00:01:24,920 Men det vil spørre meg om passordet mitt, og nå er jeg i apparatet. 22 00:01:24,920 --> 00:01:33,060 I utgangspunktet, på dette punktet, hvis du åpnet opp en terminal inne i selve apparatet, 23 00:01:33,060 --> 00:01:36,350 dette grensesnittet, men du vil bruke det, er nøyaktig det samme 24 00:01:36,350 --> 00:01:40,010 som grensesnitt jeg bruker over her, men nå er du SSHed. 25 00:01:42,240 --> 00:01:44,920 Du trenger ikke å SSH til apparatet. 26 00:01:44,920 --> 00:01:52,360 Et eksempel på et annet sted du kunne SSH til er jeg ganske sikker på at du har som standard - 27 00:01:52,360 --> 00:01:55,020 Oh. Større. 28 00:01:55,020 --> 00:02:01,130 Alle dere bør ha som standard FAS kontoer på FAS servere. 29 00:02:01,130 --> 00:02:06,840 For meg, ville jeg SSH til rbowden@nice.fas.harvard.edu. 30 00:02:06,840 --> 00:02:11,610 Det kommer til å spørre deg at den første gangen, og du sier ja. 31 00:02:11,610 --> 00:02:15,840 Mitt passord er bare kommer til å være min FAS passord. 32 00:02:15,840 --> 00:02:22,650 Og så nå er jeg SSHed til hyggelig servere, og jeg kan gjøre hva jeg vil på her. 33 00:02:22,650 --> 00:02:28,560 Mange klasser du kan ta, som 124, kommer til å ha deg laste opp ting til her 34 00:02:28,560 --> 00:02:30,950 å faktisk sende inn oppgavesett. 35 00:02:30,950 --> 00:02:34,100 Men si at du ikke har tilgang til maskinen din. 36 00:02:34,100 --> 00:02:37,910 Så kan du gjøre ting, som på her vil det si - 37 00:02:37,910 --> 00:02:42,160 Dette er bare vår del av spørsmålene. 38 00:02:42,160 --> 00:02:45,070 Det vil be deg om å gjøre dette i apparatet. 39 00:02:45,070 --> 00:02:47,790 I stedet vil jeg bare gjøre det på serveren. 40 00:02:47,790 --> 00:02:50,560 Jeg kommer til å pakke det. 41 00:02:50,560 --> 00:02:55,670 Problemet kommer til å være som du er vant til å bruke noe sånt som gedit 42 00:02:55,670 --> 00:02:58,160 eller hva innsiden av apparatet. 43 00:02:58,160 --> 00:03:01,830 Du kommer ikke til å ha det på FAS-serveren. 44 00:03:01,830 --> 00:03:04,110 Alt er bare kommer til å være denne tekstgrensesnittet. 45 00:03:04,110 --> 00:03:09,180 Så du kan enten ett, kan du prøve å lære en tekst editor som de har. 46 00:03:09,180 --> 00:03:12,130 De har Nano. 47 00:03:12,130 --> 00:03:14,990 Nano er vanligvis ganske enkelt å bruke. 48 00:03:14,990 --> 00:03:19,470 Du kan bruke pilene og skriv normalt. 49 00:03:19,470 --> 00:03:21,250 Så det er ikke vanskelig. 50 00:03:21,250 --> 00:03:24,720 Hvis du ønsker å få virkelig fancy du kan bruke Emacs, 51 00:03:24,720 --> 00:03:29,850 som jeg sannsynligvis ikke burde ha åpnet fordi jeg ikke engang vet hvordan du lukker Emacs. 52 00:03:29,850 --> 00:03:32,760 Kontroll X, Control C? Ja. 53 00:03:32,760 --> 00:03:35,310 Eller du kan bruke Vim, som er det jeg bruker. 54 00:03:35,310 --> 00:03:37,800 Og så de er dine alternativer. 55 00:03:37,800 --> 00:03:43,830 Hvis du ikke ønsker å gjøre det, kan du også, hvis du ser på manual.cs50.net-- 56 00:03:43,830 --> 00:03:45,410 Oh. 57 00:03:45,410 --> 00:03:49,920 På en PC kan du SSH bruker PuTTY, 58 00:03:49,920 --> 00:03:51,940 som du er nødt til å laste ned separat. 59 00:03:51,940 --> 00:03:55,460 På en Mac, kan du bare standard bruk Terminal eller kan du laste ned iTerm2, 60 00:03:55,460 --> 00:03:58,490 som er som en hyggelig, fancy Terminal. 61 00:03:58,490 --> 00:04:03,780 Hvis du går til manual.cs50.net vil du se en kobling til Notepad + +, 62 00:04:03,780 --> 00:04:07,120 som er hva du kan bruke på en PC. 63 00:04:07,120 --> 00:04:13,340 Den lar deg SFTP fra Notepad + +, som er utgangspunktet SSH. 64 00:04:13,340 --> 00:04:17,750 Hva dette vil la deg gjøre er redigere filene dine lokalt, 65 00:04:17,750 --> 00:04:20,670 og deretter når du vil lagre dem, vil det spare til nice.fas, 66 00:04:20,670 --> 00:04:23,670 Der kan du kjøre dem. 67 00:04:23,670 --> 00:04:26,880 Og tilsvarende på en Mac kommer til å være TextWrangler. 68 00:04:26,880 --> 00:04:28,760 Så det lar deg gjøre det samme. 69 00:04:28,760 --> 00:04:32,800 Den lar deg redigere filer lokalt og lagre dem til nice.fas, 70 00:04:32,800 --> 00:04:35,730 Der kan du kjøre dem. 71 00:04:35,730 --> 00:04:40,400 Så hvis du noen gang fast uten et apparat, har du disse alternativene 72 00:04:40,400 --> 00:04:44,230 å fortsatt gjøre dine oppgavesett. 73 00:04:44,230 --> 00:04:48,250 Den ene problemet kommer til å være at du ikke kommer til å ha CS50 bibliotek 74 00:04:48,250 --> 00:04:51,580 fordi nice.fas ikke har som standard at. 75 00:04:51,580 --> 00:04:55,970 Du kan enten laste ned CS50 bibliotek - 76 00:04:55,970 --> 00:04:58,470 Jeg tror ikke jeg trenger det på dette punktet. 77 00:04:58,470 --> 00:05:03,270 Du kan enten laste ned CS50 biblioteket og kopiere den over til nice.fas, 78 00:05:03,270 --> 00:05:07,450 eller jeg tror på dette punktet vi ikke bruker det lenger uansett. 79 00:05:07,450 --> 00:05:12,720 Eller hvis vi gjør det, kan du foreløpig erstatte den med 80 00:05:12,720 --> 00:05:18,480 implementeringer av funksjonene i CS50 biblioteket uansett. 81 00:05:18,480 --> 00:05:21,370 Så det bør ikke være så mye av en begrensning. 82 00:05:21,370 --> 00:05:23,710 Og det er det. 83 00:05:26,460 --> 00:05:29,820 >> Jeg vil gå tilbake til apparatet nå, vi vil gjøre alt i apparatet. 84 00:05:29,820 --> 00:05:37,510 Ser på vår del av spørsmålene, i begynnelsen, som jeg sa i min e-post, 85 00:05:37,510 --> 00:05:43,620 Vi må snakke om en kort du skulle se. 86 00:05:43,620 --> 00:05:51,980 Vi har omdirigere & Rør og disse tre spørsmålene. 87 00:05:51,980 --> 00:05:56,070 >> Til hvilken stream vil funksjoner som printf skrive som standard? 88 00:05:56,070 --> 00:05:59,130 Så stream. Hva er en strøm? 89 00:06:06,520 --> 00:06:15,100 En strøm er i utgangspunktet som det er bare noen - 90 00:06:15,100 --> 00:06:21,450 Det er ikke engang en kilde 1s og 0s. 91 00:06:21,450 --> 00:06:24,920 Strømmen den spør etter her er standard ut. 92 00:06:24,920 --> 00:06:27,250 Og så standard ut er en bekk som når du skriver til den, 93 00:06:27,250 --> 00:06:30,940 det vises på skjermen. 94 00:06:30,940 --> 00:06:36,860 Standard ut, med strøm, betyr det at du bare skrive 1s og 0s til det, 95 00:06:36,860 --> 00:06:40,220 og den andre enden av standard ut leser bare fra den datastrømmen. 96 00:06:40,220 --> 00:06:43,540 Det er bare en streng av 1s og 0s. 97 00:06:43,540 --> 00:06:45,570 Du kan skrive til bekker eller du kan lese fra bekker 98 00:06:45,570 --> 00:06:47,950 avhengig av hva strømmen faktisk er. 99 00:06:47,950 --> 00:06:52,800 De to andre standard bekker er standard i og standard feil. 100 00:06:52,800 --> 00:06:57,540 Standard i er når du GetString, det venter på deg for å legge inn ting. 101 00:06:57,540 --> 00:07:01,570 Så det venter på deg, det er faktisk venter på standard i, 102 00:07:01,570 --> 00:07:04,880 som er virkelig hva du får når du skriver på tastaturet. 103 00:07:04,880 --> 00:07:07,530 Du skriver inn standard i. 104 00:07:07,530 --> 00:07:10,050 Standard feil er i utgangspunktet tilsvarer standard ut, 105 00:07:10,050 --> 00:07:13,280 men det er spesialisert på at når du skriver ut til standard feil, 106 00:07:13,280 --> 00:07:16,770 du skal bare skrive ut feilmeldinger til at 107 00:07:16,770 --> 00:07:20,200 slik at du kan skille mellom vanlige meldinger skrevet til skjermen 108 00:07:20,200 --> 00:07:24,560 versus feilmeldinger avhengig av om de gikk til standard ut eller standard feil. 109 00:07:24,560 --> 00:07:28,660 Filer også. 110 00:07:28,660 --> 00:07:32,440 Standard ut, standard i, og standard feil er kun spesielle bekker, 111 00:07:32,440 --> 00:07:36,810 men egentlig en fil, når du åpner en fil, blir det en strøm av bytes 112 00:07:36,810 --> 00:07:40,740 hvor du kan bare lese fra den datastrømmen. 113 00:07:40,740 --> 00:07:47,770 Deg, for det meste, kan bare tenke på en fil som en strøm av bytes. 114 00:07:47,770 --> 00:07:51,190 Så hva bekker skriver de til som standard? Standard ut. 115 00:07:51,190 --> 00:07:56,980 >> Hva er forskjellen mellom> og >>? 116 00:07:58,140 --> 00:08:03,710 Var det noen som ser videoen på forhånd? Okay. 117 00:08:03,710 --> 00:08:10,960 > Kommer til å være hvordan du viderekobler til filer, 118 00:08:10,960 --> 00:08:15,240 og >> er også kommer til å omdirigere utdata til filer, 119 00:08:15,240 --> 00:08:17,820 men det er i stedet kommer til å føye til filen. 120 00:08:17,820 --> 00:08:23,430 For eksempel, la oss si at jeg tilfeldigvis har dict akkurat her, 121 00:08:23,430 --> 00:08:27,020 og den eneste ting innsiden av dict er katt, katt, hund, fisk, hund. 122 00:08:27,020 --> 00:08:31,530 En kommando som du har på kommandolinjen er katt, 123 00:08:31,530 --> 00:08:34,539 som er bare kommer til å skrive hva som er i en fil. 124 00:08:34,539 --> 00:08:40,679 Så når jeg sier katt dict, det kommer til å skrive ut katten, katt, hund, fisk, hund. Det er alt katt gjør. 125 00:08:40,679 --> 00:08:46,280 Det betyr at det skrives ut til standard ut katten, katt, hund, fisk, hund. 126 00:08:46,280 --> 00:08:53,240 Hvis jeg i stedet ønsker å omdirigere det til en fil, kan jeg bruke> og omdirigere den til hva filen er. 127 00:08:53,240 --> 00:08:56,460 Jeg ringer filen filen. 128 00:08:56,460 --> 00:09:00,320 Så nå hvis jeg ls, jeg ser jeg har en ny fil som heter fil. 129 00:09:00,320 --> 00:09:05,700 Og hvis jeg åpner den opp, det kommer til å ha akkurat det katten satt på kommandolinjen. 130 00:09:05,700 --> 00:09:11,040 Så nå hvis jeg gjør det igjen, så det kommer til å omdirigere utdataene til fil, 131 00:09:11,040 --> 00:09:13,930 og jeg kommer til å ha de samme ting. 132 00:09:13,930 --> 00:09:17,910 Så teknisk sett det helt overvurdere hva vi hadde. 133 00:09:17,910 --> 00:09:22,970 Og vi får se om jeg endrer dict, tok jeg ut hunden. 134 00:09:22,970 --> 00:09:29,980 Hvis vi nå katt dict inn filen på nytt, vi kommer til å ha den nye versjonen med hunden fjernet. 135 00:09:29,980 --> 00:09:32,400 Så det overstyrer helt det. 136 00:09:32,400 --> 00:09:36,640 I stedet, hvis vi bruker >>, det kommer til å føye fil. 137 00:09:36,640 --> 00:09:40,860 Nå åpner filen, ser vi at vi har akkurat det samme trykket to ganger 138 00:09:40,860 --> 00:09:44,920 fordi det var der en gang, så vi lagt til den opprinnelige. 139 00:09:44,920 --> 00:09:48,130 Så det er hva> og >> gjøre. 140 00:09:48,130 --> 00:09:50,580 Spør den neste - Det spør ikke om det. 141 00:09:50,580 --> 00:09:59,050 >> Den andre som vi har er <, som hvis> ruter standard ut, 142 00:09:59,050 --> 00:10:01,970 00:10:12,050 La oss se om vi har et eksempel. 144 00:10:14,750 --> 00:10:16,930 Jeg kan skrive en virkelig rask. 145 00:10:17,870 --> 00:10:25,700 La oss ta en fil, hallo.c. 146 00:10:56,060 --> 00:10:59,070 Relativt enkel fil. 147 00:10:59,070 --> 00:11:03,570 Jeg bare får en streng og deretter skrive "Hei" uansett strengen jeg bare oppgitt var. 148 00:11:03,570 --> 00:11:07,990 Så sørg hei og da. / Hallo. 149 00:11:07,990 --> 00:11:10,720 Nå er det å spørre meg å gå inn noe, 150 00:11:10,720 --> 00:11:15,070 noe som betyr at den venter på ting som skal inngås standard i. 151 00:11:15,070 --> 00:11:20,450 Så skriv hva jeg vil i standard i. Vi skal bare si Hei, Rob! 152 00:11:20,450 --> 00:11:23,310 Da er det som skrives til standard ut Hei, Rob! 153 00:11:23,310 --> 00:11:28,860 Hvis jeg gjør. / Hei og deretter omdirigere, 154 00:11:30,740 --> 00:11:34,310 for nå kan du bare omdirigere fra en fil. 155 00:11:34,310 --> 00:11:41,720 Så hvis jeg satt i noen fil, txt, og jeg satte Rob, 156 00:11:41,720 --> 00:11:52,300 hvis jeg kjører hei og deretter omdirigere filen txt inn. / hallo, det kommer til å si Hei, Rob! umiddelbart. 157 00:11:52,300 --> 00:11:57,160 Når det blir første til å GetString og den venter på standard i, 158 00:11:57,160 --> 00:12:01,730 standard i er ikke lenger venter på tastaturet for data for å få lagt inn. 159 00:12:01,730 --> 00:12:05,980 I stedet har vi omdirigert standard i å lese fra filen txt. 160 00:12:05,980 --> 00:12:10,290 Og så det kommer til å lese fra filen txt, som er akkurat den linjen Rob, 161 00:12:10,290 --> 00:12:13,380 og så det kommer til å skrive ut Hallo, Rob! 162 00:12:13,380 --> 00:12:18,180 Og hvis jeg ville, kunne jeg også gjøre. / Hallo 00:12:21,500 og deretter standard ut at det er utskrift, som er Hello, Rob!, 164 00:12:21,500 --> 00:12:24,700 Jeg kan omdirigere det inn sin egen fil. 165 00:12:24,700 --> 00:12:29,790 Jeg skal bare ringe filen hallo - Nei, jeg vil ikke, fordi det er den kjørbare - txt2. 166 00:12:29,790 --> 00:12:40,150 Nå er txt2 kommer til å ha effekt på. / Hallo 00:12:43,520 >> Spørsmål? 168 00:12:45,900 --> 00:12:49,090 >> Okay. Så da her har vi rørledning. 169 00:12:49,090 --> 00:12:53,510 Rør er den siste enheten av omdirigering. 170 00:12:53,510 --> 00:12:58,750 >> Oh. Jeg antar en mer enhet omdirigering er hvis i stedet for> gjør du 2>, 171 00:12:58,750 --> 00:13:01,070 som er omdirigere standard feil. 172 00:13:01,070 --> 00:13:06,280 Så hvis noe gikk til standard feil, ville det ikke bli satt i txt2. 173 00:13:06,280 --> 00:13:12,480 Men legg merke hvis jeg gjør 2>, så er det fortsatt skrive Hei, Rob! i kommandolinjen 174 00:13:12,480 --> 00:13:18,600 fordi jeg bare omdirigere standard feil, jeg er ikke omdirigere standard ut. 175 00:13:18,600 --> 00:13:22,210 Standard feil og standard ut er forskjellige. 176 00:13:24,210 --> 00:13:27,080 Hvis du ønsket å faktisk skrive til standard feil, 177 00:13:27,080 --> 00:13:35,080 så jeg kunne endre dette for å være fprintf til standardfeil. 178 00:13:35,080 --> 00:13:37,850 Så printf, som standard, skriver til standard ut. 179 00:13:37,850 --> 00:13:41,720 Hvis jeg ønsker å skrive ut på standard feil manuelt, så jeg må bruke fprintf 180 00:13:41,720 --> 00:13:45,010 og angi hva jeg vil skrive til. 181 00:13:45,010 --> 00:13:49,720 Hvis du i stedet jeg gjorde fprintf stdout, så det er i utgangspunktet tilsvarende printf. 182 00:13:49,720 --> 00:13:55,530 Men fprintf til standard error. 183 00:13:57,790 --> 00:14:03,650 Så nå, hvis jeg omdirigere dette inn txt2, Hello, Rob! er fortsatt å få skrevet ut på kommandolinjen 184 00:14:03,650 --> 00:14:08,270 siden det begynner å bli trykt til standard error og jeg bare omdirigere standard ut. 185 00:14:08,270 --> 00:14:16,420 Hvis jeg nå omdirigere standard feil, nå er det ikke får skrevet ut, og txt2 kommer til å bli Hei, Rob! 186 00:14:16,420 --> 00:14:21,910 Så nå kan du skrive ut dine faktiske feil til standard error 187 00:14:21,910 --> 00:14:24,720 og skrive ut vanlige meldinger til standard ut. 188 00:14:24,720 --> 00:14:31,420 Og så når du kjører programmet, kan du kjøre det som. / Hallo denne typen med 2> 189 00:14:31,420 --> 00:14:33,800 slik at programmet kommer til å kjøre normalt, 190 00:14:33,800 --> 00:14:38,400 men eventuelle feilmeldinger som du får kan du sjekke senere i feilloggen, 191 00:14:38,400 --> 00:14:44,500 så feil, og deretter se senere og feil fil vil ha noen feil som skjedde. 192 00:14:45,200 --> 00:14:47,540 >> Spørsmål? 193 00:14:47,540 --> 00:14:58,070 >> Den siste er rør, som du kan tenke på som å ta standard ut fra en kommando 194 00:14:58,070 --> 00:15:01,210 og gjør det standard i til neste kommando. 195 00:15:01,210 --> 00:15:05,570 Et eksempel her er ekko er et kommandolinje ting 196 00:15:05,570 --> 00:15:11,840 som bare kommer til å ekko hva jeg satt som argument sin. Jeg vil ikke sette anførselstegn. 197 00:15:11,840 --> 00:15:16,150 Echo blah, blah, er blah bare kommer til å skrive ut blah, blah, blah. 198 00:15:16,150 --> 00:15:20,600 Før, da jeg sa at jeg måtte sette Rob inn en txt-fil 199 00:15:20,600 --> 00:15:28,830 fordi jeg kan bare omdirigere txt-filer, i stedet, / hvis jeg ekko Rob 200 00:15:28,830 --> 00:15:35,520 og deretter rør det inn. / hallo, vil det også gjøre det samme type ting. 201 00:15:35,520 --> 00:15:39,160 Dette tar produksjonen av denne kommandoen, ekko Rob, 202 00:15:39,160 --> 00:15:43,610 og bruke det som input for. / hallo. 203 00:15:44,790 --> 00:15:49,560 Du kan tenke på det som første omdirigeringen ekko Rob inn en fil 204 00:15:49,560 --> 00:15:54,160 og deretter inn i. / hallo denne filen som nettopp ble generert. 205 00:15:54,160 --> 00:15:57,850 Men det tar den midlertidige filen ut av bildet. 206 00:16:01,890 --> 00:16:04,460 >> Spørsmål om det? 207 00:16:04,460 --> 00:16:07,150 >> Det neste spørsmålet kommer til å involvere dette. 208 00:16:07,150 --> 00:16:15,310 Hva rørledning kan du bruke til å finne antall unike navn i en fil som heter names.txt? 209 00:16:15,310 --> 00:16:24,160 Kommandoene vi kommer til å ønske å bruke her er unike, så Uniq, og deretter wc. 210 00:16:24,160 --> 00:16:28,840 Du kan gjøre mennesket uniq å faktisk se på hva som gjør det, 211 00:16:28,840 --> 00:16:34,840 og det er bare kommer til å filtrere tilstøtende matchende linjer fra inngangen. 212 00:16:34,840 --> 00:16:40,690 Og mannen wc kommer til å skrive ut linjeskift, ord og bytes for hver fil. 213 00:16:40,690 --> 00:16:43,760 Og den siste vi kommer til å ønske å bruke er sortering, 214 00:16:43,760 --> 00:16:47,410 som kommer til å bare sortere linjene i txt-fil. 215 00:16:47,410 --> 00:16:58,080 Hvis jeg gjør noe txt fil, names.txt, og det er Rob, Tommy, Joseph, Tommy, Joseph, RJ, Rob, 216 00:16:58,080 --> 00:17:03,910 hva jeg vil gjøre her er å finne antall unike i denne fila. 217 00:17:03,910 --> 00:17:08,750 Så hva bør svaret være? >> [Student] 4. >> Ja. 218 00:17:08,750 --> 00:17:13,780 Det bør være 4 siden Rob, Tommy, Joseph, RJ er de eneste unike i denne fila. 219 00:17:13,780 --> 00:17:20,180 Det første trinnet, hvis jeg bare gjøre ordtelling på names.txt, 220 00:17:20,180 --> 00:17:24,290 Dette er faktisk fortelle meg alt. 221 00:17:24,290 --> 00:17:32,560 Dette er faktisk utskrift - la oss se, mann wc - linjeskift, ord og byte teller. 222 00:17:32,560 --> 00:17:38,270 Hvis jeg bare bryr seg om linjer, så jeg kan bare gjøre wc-l names.txt. 223 00:17:41,730 --> 00:17:44,300 Så det er trinn 1. 224 00:17:44,300 --> 00:17:50,510 Men jeg ønsker ikke å wc-l names.txt fordi names.txt bare inneholder alle navnene, 225 00:17:50,510 --> 00:17:54,170 og jeg ønsker å filtrere ut eventuelle ikke-entydige seg. 226 00:17:54,170 --> 00:18:01,200 Så hvis jeg gjør Uniq names.txt, som ikke helt gi meg det jeg vil ha 227 00:18:01,200 --> 00:18:03,760 fordi de dupliserte navn er fremdeles der. 228 00:18:03,760 --> 00:18:07,690 Hvorfor er det? Hvorfor er uniq ikke gjør hva jeg vil? 229 00:18:07,690 --> 00:18:10,500 [Student] The duplikater er ikke [hørbar] >> Ja. 230 00:18:10,500 --> 00:18:16,370 Husk mannen siden for uniq sier filter tilstøtende matchende linjer. 231 00:18:16,370 --> 00:18:19,680 De er ikke tilstøtende, så det vil ikke filtrere dem. 232 00:18:19,680 --> 00:18:31,100 Hvis jeg sortere dem først, er liksom names.txt kommer til å sette alle de dupliserte linjer sammen. 233 00:18:31,100 --> 00:18:34,450 Så nå sortere names.txt er det. 234 00:18:34,450 --> 00:18:40,550 Jeg kommer til å ønske å bruke det som input til Uniq, som er | uniq. 235 00:18:40,550 --> 00:18:43,390 Det gir meg Joseph, RJ, Rob, Tommy, 236 00:18:43,390 --> 00:18:49,260 og jeg ønsker å bruke det som input til wc-l, 237 00:18:49,260 --> 00:18:52,740 som kommer til å gi meg 4. 238 00:18:52,740 --> 00:18:56,930 Som det står her, hva rørledning du bruke? 239 00:18:56,930 --> 00:19:01,390 Du kan gjøre mange ting som å bruke en rekke kommandoer 240 00:19:01,390 --> 00:19:05,130 der du bruker output fra en kommando som input til neste kommando. 241 00:19:05,130 --> 00:19:08,780 Du kan gjøre mange ting, mye smarte ting. 242 00:19:08,780 --> 00:19:11,440 >> Spørsmål? 243 00:19:12,910 --> 00:19:14,600 Okay. 244 00:19:14,600 --> 00:19:17,880 Det er det for rør og omdirigering. 245 00:19:18,370 --> 00:19:24,090 >> Nå går vi videre til selve ting, koding ting. 246 00:19:24,090 --> 00:19:29,100 Innsiden av denne PDF, vil du se denne kommandoen, 247 00:19:29,100 --> 00:19:32,950 og du ønsker å kjøre denne kommandoen i apparatet. 248 00:19:36,240 --> 00:19:42,250 wget er kommandoen for bare å få noe fra Internett, i utgangspunktet, 249 00:19:42,250 --> 00:19:45,180 så wget og denne nettadressen. 250 00:19:45,180 --> 00:19:49,110 Hvis du gikk til denne nettadressen i nettleseren din, vil den laste ned denne filen. 251 00:19:49,110 --> 00:19:52,510 Jeg bare klikket på den, så det lastet ned filen for meg. 252 00:19:52,510 --> 00:19:55,650 Men å skrive wget av at ting inne i terminalen 253 00:19:55,650 --> 00:19:58,620 er bare kommer til å laste det ned terminalen. 254 00:19:58,620 --> 00:20:02,750 Jeg har section5.zip, og du ønsker å pakke section5.zip, 255 00:20:02,750 --> 00:20:06,520 som kommer til å gi deg en mappe som heter section5, 256 00:20:06,520 --> 00:20:11,550 som kommer til å ha alle filene vi skal bruke i dag inne i den. 257 00:20:33,380 --> 00:20:37,710 Som disse programmenes filnavnene foreslår, er de litt buggy, 258 00:20:37,710 --> 00:20:40,990 så din oppgave er å finne ut hvorfor du bruker gdb. 259 00:20:40,990 --> 00:20:44,560 Har alle har dem ned / vet hvordan de skal få dem ned 260 00:20:44,560 --> 00:20:47,480 i tørketrommelen deres? Okay. 261 00:20:47,480 --> 00:20:56,400 >> Kjører ./buggy1, vil det si Segmentation fault (core dumpet), 262 00:20:56,400 --> 00:21:00,500 som noen gang du får en segfault, er det en dårlig ting. 263 00:21:00,500 --> 00:21:03,810 Under hvilke omstendigheter får du en segfault? 264 00:21:03,810 --> 00:21:08,210 [Student] Dereferencing en nullpeker. >> Ja. Så det er ett eksempel. 265 00:21:08,210 --> 00:21:11,580 Dereferencing en nullpeker du kommer til å få en segfault. 266 00:21:11,580 --> 00:21:16,720 Hva en segfault betyr er du berører minne du ikke bør berøre. 267 00:21:16,720 --> 00:21:21,350 Så dereferencing en nullpeker berører adresse 0, 268 00:21:21,350 --> 00:21:28,060 og i utgangspunktet, alle datamaskiner i dag si at 0 er minne du ikke bør berøre. 269 00:21:28,060 --> 00:21:31,920 Så det er derfor dereferencing en nullpeker resulterer i en segfault. 270 00:21:31,920 --> 00:21:37,210 Når du tilfeldigvis ikke initialisere en peker, da den har en søppel verdi, 271 00:21:37,210 --> 00:21:41,520 og så når du prøver å dereference det, i all sannsynlighet du berører minne 272 00:21:41,520 --> 00:21:43,540 som er i midten av ingensteds. 273 00:21:43,540 --> 00:21:45,650 Hvis du tilfeldigvis ha flaks og søppel verdi 274 00:21:45,650 --> 00:21:48,440 skjedd for å peke til et sted på stakken eller noe, 275 00:21:48,440 --> 00:21:50,820 så når du dereferanse at pekeren som du ikke har initialisert, 276 00:21:50,820 --> 00:21:52,730 ingenting skal gå galt. 277 00:21:52,730 --> 00:21:55,480 Men hvis det peker til, si, et sted mellom bunken og haugen, 278 00:21:55,480 --> 00:21:59,850 eller den peker bare til et sted som ikke har blitt brukt av programmet ennå, 279 00:21:59,850 --> 00:22:02,240 så du berører minne du ikke bør berøre og du segfault. 280 00:22:02,240 --> 00:22:06,370 Når du skriver en rekursiv funksjon, og det recurses for mange ganger 281 00:22:06,370 --> 00:22:08,720 og stakk vokser for stor og stakken kolliderer inn i ting 282 00:22:08,720 --> 00:22:12,270 at det ikke skal være å kollidere med, du berører minne du ikke bør berøre, 283 00:22:12,270 --> 00:22:14,810 så du segfault. 284 00:22:14,810 --> 00:22:17,010 Det er hva en segfault er. 285 00:22:17,010 --> 00:22:21,810 >> Det er også av samme grunn at hvis du har en streng som - 286 00:22:21,810 --> 00:22:23,930 la oss gå tilbake til det forrige programmet. 287 00:22:23,930 --> 00:22:28,530 I hallo.c--Jeg bare kommer til å gjøre noe annet. 288 00:22:28,530 --> 00:22:33,770 char * s = "Hei, verden!"; 289 00:22:33,770 --> 00:22:42,310 Hvis jeg bruker * s = noe eller s [0] = 'X'; 290 00:22:42,310 --> 00:22:47,290 så sørg hallo,. / hallo, hvorfor det segfault? 291 00:22:48,410 --> 00:22:51,250 Hvorfor har dette segfault? 292 00:22:55,660 --> 00:22:57,890 Hva ville du forvente å skje? 293 00:22:57,890 --> 00:23:06,640 Hvis jeg gjorde printf ("% s \ n", s), hva ville du forvente å bli skrevet ut? 294 00:23:06,640 --> 00:23:09,930 [Student] X hallo. >> Ja. 295 00:23:09,930 --> 00:23:15,140 Problemet er at når du deklarerer en streng som dette, 296 00:23:15,140 --> 00:23:18,190 s er en peker som kommer til å gå på stakken, 297 00:23:18,190 --> 00:23:25,880 og hva er peker til er denne strengen som finnes i read-only minne. 298 00:23:25,880 --> 00:23:30,560 Så bare ved navn, read-only minne, bør du få ideen 299 00:23:30,560 --> 00:23:33,010 at hvis du prøver å endre hva som er i skrivebeskyttet minne, 300 00:23:33,010 --> 00:23:36,670 du gjør noe du ikke bør gjøre med minne og du segfault. 301 00:23:36,670 --> 00:23:45,360 Dette er faktisk en stor forskjell mellom char * s og røye s []. 302 00:23:45,360 --> 00:23:48,790 Så røye s [], nå denne strengen kommer til å bli satt på stakken, 303 00:23:48,790 --> 00:23:53,960 og stakken er ikke skrivebeskyttet, noe som betyr at dette skal fungere helt fint. 304 00:23:55,500 --> 00:23:57,370 Og det gjør. 305 00:23:57,370 --> 00:24:06,250 Husk at når jeg gjør char * s = "Hei, verden!", S selv på stakken 306 00:24:06,250 --> 00:24:10,390 men s peker på et annet sted, og at et annet skjer for å være skrivebeskyttet. 307 00:24:10,390 --> 00:24:15,640 Men røye s [] er bare noe på stakken. 308 00:24:17,560 --> 00:24:21,760 Så det er et annet eksempel på en segfault skjer. 309 00:24:21,760 --> 00:24:27,820 >> Vi så at ./buggy1 resulterte i en segfault. 310 00:24:27,820 --> 00:24:31,810 I teorien skal du ikke se på buggy1.c umiddelbart. 311 00:24:31,810 --> 00:24:35,170 I stedet vil vi se på det gjennom gdb. 312 00:24:35,170 --> 00:24:37,750 Legg merke til at når du får Segmentation fault (core dumpet), 313 00:24:37,750 --> 00:24:40,850 du får denne filen over her kalt kjerne. 314 00:24:40,850 --> 00:24:45,200 Hvis vi ls-l, vil vi se at kjernen er vanligvis en ganske stor fil. 315 00:24:45,200 --> 00:24:51,580 Dette er antall byte av filen, slik at det ser ut som det er 250-noe kilobyte. 316 00:24:51,580 --> 00:24:56,120 Grunnen til dette er at det kjernen dump faktisk er 317 00:24:56,120 --> 00:25:01,410 er når programmet krasjer, staten minne programmet 318 00:25:01,410 --> 00:25:05,230 bare blir kopiert og limt inn i denne filen. 319 00:25:05,230 --> 00:25:07,270 Det blir dumpet i denne filen. 320 00:25:07,270 --> 00:25:13,060 Dette programmet, mens det var i gang, har skjedd å ha et minne bruk av rundt 250 kilobyte, 321 00:25:13,060 --> 00:25:17,040 og så det er det ble dumpet inn i denne filen. 322 00:25:17,040 --> 00:25:23,630 Nå kan du se på denne filen hvis vi gjør gdb buggy1 kjerne. 323 00:25:23,630 --> 00:25:30,130 Vi kan bare gjøre gdb buggy1, og det vil bare starte opp gdb regelmessig, 324 00:25:30,130 --> 00:25:33,800 bruker buggy1 som sin inndatafilen. 325 00:25:33,800 --> 00:25:38,260 Men hvis du gjør gdb buggy1 kjerne, så det er spesielt kommer til å starte opp gdb 326 00:25:38,260 --> 00:25:40,330 ved å se på at kjerneinflasjonen fil. 327 00:25:40,330 --> 00:25:45,560 Og du sier buggy1 betyr gdb vet at at kjerneinflasjonen filen kommer fra buggy1 programmet. 328 00:25:45,560 --> 00:25:49,580 Så gdb buggy1 kjerne kommer til å umiddelbart bringe oss 329 00:25:49,580 --> 00:25:52,060 til der programmet skjedde å avslutte. 330 00:25:57,720 --> 00:26:02,340 Vi ser her Program avsluttet med 11 signal, Segmentation fault. 331 00:26:02,340 --> 00:26:10,110 Vi ser en linje av forsamlingen, som sannsynligvis ikke er veldig nyttig. 332 00:26:10,110 --> 00:26:15,360 Men hvis du skriver bt eller tilbakesporing, som kommer til å være funksjonen 333 00:26:15,360 --> 00:26:19,430 som gir oss en liste over våre nåværende stack rammer. 334 00:26:19,430 --> 00:26:23,150 Så tilbakesporing. Det ser ut som vi bare har to stack rammer. 335 00:26:23,150 --> 00:26:26,310 Den første er vår viktigste stabelen ramme, 336 00:26:26,310 --> 00:26:29,810 og den andre er stabelen rammen for denne funksjonen som vi måtte være i, 337 00:26:29,810 --> 00:26:34,440 som ser ut som vi bare har forsamlingen kode for. 338 00:26:34,440 --> 00:26:38,050 Så la oss gå tilbake til vår viktigste funksjon, 339 00:26:38,050 --> 00:26:42,300 og å gjøre at vi kan gjøre ramme 1, og jeg tror vi kan også gjøre ned, 340 00:26:42,300 --> 00:26:45,160 men jeg nesten aldri gjøre ned - eller opp. Ja. 341 00:26:45,160 --> 00:26:50,710 Opp og ned. Opp bringer deg opp en stabel ramme, ned, kommer du ned en stabel ramme. 342 00:26:50,710 --> 00:26:53,240 Jeg pleier å aldri bruke det. 343 00:26:53,240 --> 00:26:59,120 Jeg bare spesifikt si en ramme, som er å gå til rammen er merket 1. 344 00:26:59,120 --> 00:27:01,750 Ramme 1 kommer til å bringe oss inn i hoved stack frame, 345 00:27:01,750 --> 00:27:05,570 og det sier her kodelinjen vi måtte være på. 346 00:27:05,570 --> 00:27:07,950 Hvis vi ønsket et par flere linjer med kode, kan vi si liste, 347 00:27:07,950 --> 00:27:11,280 og det kommer til å gi oss alle linjene med kode rundt den. 348 00:27:11,280 --> 00:27:13,360 Linjen vi segfaulted på var 6: 349 00:27:13,360 --> 00:27:17,360 if (strcmp ("CS50 rocks", argv [1]) == 0). 350 00:27:17,360 --> 00:27:24,130 Hvis det ikke er opplagt ennå, kan du få det rett fra her bare ved å tenke på hvorfor det segfaulted. 351 00:27:24,130 --> 00:27:28,800 Men vi kan ta det ett skritt videre og si: "Hvorfor ville argv [1] segfault?" 352 00:27:28,800 --> 00:27:38,830 La oss print argv [1], og det ser ut som det er 0x0, som er den nullpeker. 353 00:27:38,830 --> 00:27:44,750 Vi strcmping CS50 steiner og null, og så det kommer til å segfault. 354 00:27:44,750 --> 00:27:48,280 Og hvorfor er argv [1] null? 355 00:27:48,640 --> 00:27:51,280 [Student] Fordi vi ikke gi det noen kommandolinjeargumenter. 356 00:27:51,280 --> 00:27:53,390 Ja. Vi gjorde ikke gi det noen kommandolinjeargumenter. 357 00:27:53,390 --> 00:27:58,460 Så ./buggy1 er bare nødt til argv [0] være ./buggy1. 358 00:27:58,460 --> 00:28:02,100 Det kommer ikke til å ha en argv [1], så det kommer til å segfault. 359 00:28:02,100 --> 00:28:07,450 Men hvis, i stedet, jeg bare CS50, det kommer til å si at du får en D 360 00:28:07,450 --> 00:28:09,950 fordi det er hva det er ment å gjøre. 361 00:28:09,950 --> 00:28:15,240 Ser på buggy1.c, det er ment å skrive ut "Du får et D" - 362 00:28:15,240 --> 00:28:20,820 Hvis argv [1] ikke er "CS50 rocks", "Du får et D", ellers "Du får en A!" 363 00:28:20,820 --> 00:28:25,660 Så hvis vi ønsker en A, trenger vi denne til å sammenligne som sant, 364 00:28:25,660 --> 00:28:28,710 noe som betyr at det kan sammenlignes med 0. 365 00:28:28,710 --> 00:28:31,100 Så argv [1] må være "CS50 rocks". 366 00:28:31,100 --> 00:28:35,660 Hvis du ønsker å gjøre det på kommandolinjen, må du bruke \ for å unnslippe rommet. 367 00:28:35,660 --> 00:28:41,690 Så CS50 \ steiner og du får en A! 368 00:28:41,690 --> 00:28:44,060 Hvis du ikke gjør det backslash, hvorfor dette ikke fungerer? 369 00:28:44,060 --> 00:28:47,190 [Student] Det er to forskjellige argumenter. >> Ja. 370 00:28:47,190 --> 00:28:52,540 Argv [1] kommer til å bli CS50 og argv [2] kommer til å være stein. Okay. 371 00:28:52,540 --> 00:28:56,470 >> Nå ./buggy2 kommer til å segfault igjen. 372 00:28:56,470 --> 00:29:01,880 I stedet for å åpne den med sin kjernevirksomhet filen, vil vi bare åpne opp buggy2 direkte, 373 00:29:01,880 --> 00:29:05,000 så GDB buggy2. 374 00:29:05,000 --> 00:29:09,590 Hvis vi nå bare kjøre programmet vårt, så det kommer til å si Program mottatt signal SIGSEGV, 375 00:29:09,590 --> 00:29:15,530 som er segfault signal, og det er her det skjedde skulle skje. 376 00:29:15,530 --> 00:29:21,250 Ser på backtrace vår, ser vi at vi var i funksjon oh_no, 377 00:29:21,250 --> 00:29:23,900 som ble kalt av funksjonen Eagle, som ble kalt av funksjonen binky, 378 00:29:23,900 --> 00:29:26,460 som ble kalt av main. 379 00:29:26,460 --> 00:29:31,680 Vi kan også se argumentene til disse funksjonene. 380 00:29:31,680 --> 00:29:34,680 Argumentet til Eagle og binky var en. 381 00:29:34,680 --> 00:29:44,390 Hvis vi liste funksjonen oh_no, ser vi at oh_no bare gjør char ** s = NULL; 382 00:29:44,390 --> 00:29:47,410 * S = "BOOM"; 383 00:29:47,410 --> 00:29:50,330 Hvorfor skulle det ikke? 384 00:29:54,330 --> 00:29:58,380 [Student] Du kan ikke dereferanse den nullpeker? >> Ja. 385 00:29:58,380 --> 00:30:06,090 Dette er bare å si s er NULL, uansett om det skjer for å være en røye **, 386 00:30:06,090 --> 00:30:12,070 som, avhengig av hvordan du tolker det, kan det være en peker til en peker til en streng 387 00:30:12,070 --> 00:30:15,550 eller en rekke strenger. 388 00:30:15,550 --> 00:30:21,430 Det er s er NULL, så * s er dereferencing en nullpeker, 389 00:30:21,430 --> 00:30:24,800 og så dette kommer til å krasje. 390 00:30:24,800 --> 00:30:27,540 Dette er en av de raskeste måtene du kan muligens segfault. 391 00:30:27,540 --> 00:30:31,300 Det er bare å erklære en nullpeker og umiddelbart segfaulting. 392 00:30:31,300 --> 00:30:34,570 Det er det oh_no gjør. 393 00:30:34,570 --> 00:30:43,400 Hvis vi går opp ett bilde, så vi kommer til å få inn i funksjonen som heter oh_no. 394 00:30:43,400 --> 00:30:44,830 Jeg trenger å gjøre det ned. 395 00:30:44,830 --> 00:30:48,610 Hvis du ikke skriver en kommando, og du bare trykke Enter igjen, 396 00:30:48,610 --> 00:30:52,350 det vil bare gjenta forrige kommandoen du kjørte. 397 00:30:52,350 --> 00:30:56,610 Vi er i ramme 1.. 398 00:30:56,610 --> 00:31:04,650 Notering denne rammen ser vi her er vår funksjon. 399 00:31:04,650 --> 00:31:08,520 Du kan treffe listen igjen, eller du kan gjøre listen 20 og det vil gi mer. 400 00:31:08,520 --> 00:31:13,640 Funksjonen dinky sier at hvis jeg er 1, og deretter gå til oh_no funksjon, 401 00:31:13,640 --> 00:31:15,960 annet gå til slinky funksjonen. 402 00:31:15,960 --> 00:31:18,700 Og vi vet at jeg er en fordi vi måtte se opp her 403 00:31:18,700 --> 00:31:22,560 at Eagle ble kalt med argumentet 1. 404 00:31:22,560 --> 00:31:27,560 Eller du kan bare skrives ut i, og det vil si jeg er en. 405 00:31:27,560 --> 00:31:33,770 Vi er for øyeblikket i Eagle, og hvis vi går opp en annen ramme, vi vet at vi vil ende opp i binky. 406 00:31:33,770 --> 00:31:36,600 Opp. Nå er vi i binky. 407 00:31:36,600 --> 00:31:41,340 Notering denne funksjonen - listen fra før halvparten kuttet meg - 408 00:31:41,340 --> 00:31:52,670 Det startet som om jeg er 0, så vi kommer til å kalle det oh_no, ellers ringer Eagle. 409 00:31:52,670 --> 00:31:57,000 Vi vet jeg var en, så det kalles Eagle. 410 00:31:57,000 --> 00:32:05,030 Og nå er vi tilbake i main, og viktigste er bare kommer til å være int i = rand ()% 3; 411 00:32:05,030 --> 00:32:08,790 Det er bare kommer til å gi deg et tilfeldig tall som er enten 0, 1 eller 2. 412 00:32:08,790 --> 00:32:12,780 Det kommer til å ringe binky med det nummeret, og det vil returnere 0. 413 00:32:12,780 --> 00:32:16,700 Ser på dette, 414 00:32:16,700 --> 00:32:19,880 bare vandre gjennom programmet manuelt uten å kjøre det umiddelbart, 415 00:32:19,880 --> 00:32:25,400 du ville sette en pause punkt på main, noe som betyr at når vi kjører programmet 416 00:32:25,400 --> 00:32:31,020 programmet går opp til den treffer en pause punkt. 417 00:32:31,020 --> 00:32:35,450 Så kjører programmet, vil den kjøre og deretter vil det treffe hovedfunksjon og slutte å kjøre. 418 00:32:35,450 --> 00:32:44,700 Nå er vi inne i main, og step eller neste kommer til å bringe oss til neste linje med kode. 419 00:32:44,700 --> 00:32:47,050 Du kan gjøre trinn eller neste. 420 00:32:47,050 --> 00:32:51,800 Treffer neste, nå jeg har blitt satt til rand ()% 3, slik at vi kan skrive verdien av jeg, 421 00:32:51,800 --> 00:32:55,280 og det vil si i er en. 422 00:32:55,280 --> 00:32:58,110 Nå er det ingen rolle om vi bruker neste eller trinn. 423 00:32:58,110 --> 00:33:01,000 Jeg antar det betydde noe i den forrige, men vi ønsker å bruke neste. 424 00:33:01,000 --> 00:33:06,000 Hvis vi bruker trinn, trinn vi inn i funksjonen, noe som betyr titt på den faktiske ting 425 00:33:06,000 --> 00:33:07,940 som skjer på innsiden av binky. 426 00:33:07,940 --> 00:33:10,510 Hvis vi bruker neste, så det betyr å gå over funksjonen 427 00:33:10,510 --> 00:33:14,070 og bare gå til neste linje med kode i våre viktigste funksjon. 428 00:33:14,070 --> 00:33:17,900 Her på denne linjen, var jeg på hvor det sto rand ()% 3; 429 00:33:17,900 --> 00:33:21,320 hvis jeg gjorde trinn, vil det gå inn i gjennomføringen av rand 430 00:33:21,320 --> 00:33:25,110 og se på hva som skjer der, og jeg kunne gå gjennom tilf-funksjonen. 431 00:33:25,110 --> 00:33:26,920 Men jeg bryr meg ikke om tilf-funksjonen. 432 00:33:26,920 --> 00:33:30,190 Jeg vil bare gå til neste linje med kode i main, så jeg bruker neste. 433 00:33:30,190 --> 00:33:35,800 Men nå er jeg bryr meg om den binky funksjon, slik jeg ønsker å gå inn i det. 434 00:33:35,800 --> 00:33:37,730 Nå er jeg i binky. 435 00:33:37,730 --> 00:33:42,040 Den første linjen med kode skal si if (i == 0), tar jeg et skritt, 436 00:33:42,040 --> 00:33:44,930 vi ser vi ender opp på Eagle. 437 00:33:44,930 --> 00:33:51,620 Hvis vi liste ting, ser vi at det sjekket er i = 0. 438 00:33:51,620 --> 00:33:55,470 Jeg er ikke lik 0, så det gikk til annet tilstand, 439 00:33:55,470 --> 00:33:59,540 som kommer til å ringe dinky (i). 440 00:33:59,540 --> 00:34:04,030 Du kan bli forvirret. 441 00:34:04,030 --> 00:34:07,380 Hvis du bare ser på disse linjene direkte, kan du tenke if (i == 0), 442 00:34:07,380 --> 00:34:10,800 okay, så jeg tok et skritt og nå er jeg på dinky (i), 443 00:34:10,800 --> 00:34:14,120 du kanskje tror det må bety i = 0 eller noe. 444 00:34:14,120 --> 00:34:18,980 Nei, det betyr bare at det vet det kan holde direkte til linjen Eagle (i). 445 00:34:18,980 --> 00:34:23,300 Fordi jeg ikke er 0, er neste skritt ikke kommer til å ende på annet. 446 00:34:23,300 --> 00:34:26,239 Else er ikke en linje det kommer til å stoppe på. 447 00:34:26,239 --> 00:34:31,570 Det er bare kommer til å gå til neste linje kan det faktisk utføre, som er dinky (i). 448 00:34:31,570 --> 00:34:36,090 Stepping i dinky (i), ser vi if (i == 1). 449 00:34:36,090 --> 00:34:42,670 Vi vet i = 1, så når vi går, vet vi at vi kommer til å ende opp i oh_no 450 00:34:42,670 --> 00:34:46,489 fordi i = 1 kaller funksjonen oh_no, som du kan gå inn i, 451 00:34:46,489 --> 00:34:52,969 som kommer til å sette char ** s = til NULL og umiddelbart "BOOM". 452 00:34:54,270 --> 00:34:59,690 Og deretter faktisk ser på gjennomføringen av buggy2, 453 00:34:59,690 --> 00:35:04,590 Dette er jeg bare får et tilfeldig tall - 0, 1 eller 2 - kall binky, 454 00:35:04,590 --> 00:35:10,610 som om jeg er 0 kaller oh_no, ellers kaller Eagle, kommer som her oppe. 455 00:35:10,610 --> 00:35:18,100 Hvis jeg er en, ring oh_no, ellers kalle slinky som kommer opp her, 456 00:35:18,100 --> 00:35:20,460 hvis jeg er to, ring oh_no. 457 00:35:20,460 --> 00:35:24,720 Jeg tror ikke engang det er en måte - 458 00:35:24,720 --> 00:35:30,030 Ser noen en måte å gjøre dette til et program som ikke vil segfault? 459 00:35:30,030 --> 00:35:37,530 Fordi hvis jeg mangler noe, hvis jeg er 0, vil du umiddelbart segfault, 460 00:35:37,530 --> 00:35:41,250 annet du gå til en funksjon som hvis jeg er en du segfault, 461 00:35:41,250 --> 00:35:44,540 annet du gå til en funksjon der hvis jeg er to segfault deg. 462 00:35:44,540 --> 00:35:46,810 Så uansett hva du gjør, segfault deg. 463 00:35:46,810 --> 00:35:52,380 >> Jeg antar en måte å fikse det ville være stedet for å gjøre char ** s = NULL, 464 00:35:52,380 --> 00:35:55,610 du kan malloc plass til strengen. 465 00:35:55,610 --> 00:36:04,230 Vi kunne gjøre malloc (sizeof) - sizeof hva? 466 00:36:09,910 --> 00:36:15,190 [Student] (char) * 5? >> Virker dette riktig? 467 00:36:15,190 --> 00:36:21,060 Jeg antar at dette vil fungere dersom jeg faktisk kjørte den, men det er ikke det jeg leter etter. 468 00:36:24,400 --> 00:36:32,940 Se på den type s. La oss legge til int *, så int * x. 469 00:36:32,940 --> 00:36:35,600 Jeg ville gjøre malloc (sizeof (int)). 470 00:36:35,600 --> 00:36:40,490 Eller hvis jeg ønsket en rekke av 5, ville jeg gjøre (sizeof (int) * 5); 471 00:36:40,490 --> 00:36:44,210 Hva om jeg har en int **? 472 00:36:46,260 --> 00:36:49,140 Hva ville jeg malloc? 473 00:36:49,140 --> 00:36:53,510 [Student] Størrelse på pekeren. >> Ja. (Sizeof (int *)); 474 00:36:53,510 --> 00:36:56,960 Samme her nede. 475 00:36:56,960 --> 00:37:01,280 Jeg ønsker (sizeof (char *)); 476 00:37:06,170 --> 00:37:12,840 Dette kommer til å tildele plass for pekeren som peker til "BOOM". 477 00:37:12,840 --> 00:37:15,330 Jeg trenger ikke å tildele plass for "BOOM" seg selv 478 00:37:15,330 --> 00:37:17,210 fordi dette er i utgangspunktet tilsvarer det jeg sa før 479 00:37:17,210 --> 00:37:20,870 av char * x = "BOOM". 480 00:37:20,870 --> 00:37:27,950 "BOOM" finnes allerede. Det skjer for å eksistere i read-only regionen minne. 481 00:37:27,950 --> 00:37:35,200 Men det finnes allerede, noe som betyr denne linjen med kode, hvis s er en røye **, 482 00:37:35,200 --> 00:37:43,900 deretter * s er en char * og du setter denne char * til å peke "BOOM". 483 00:37:43,900 --> 00:37:50,040 Hvis jeg ønsket å kopiere "BOOM" i s, så jeg måtte sette av plass for s. 484 00:37:55,170 --> 00:38:03,900 Jeg skal gjøre * s = malloc (sizeof (char) * 5); 485 00:38:03,900 --> 00:38:06,210 Hvorfor 5? 486 00:38:06,210 --> 00:38:10,860 Hvorfor ikke 4? Det ser ut som "BOOM" er 4 tegn. >> [Student] Null karakter. 487 00:38:10,860 --> 00:38:14,580 Ja. Alle dine strenger kommer til å trenge null karakter. 488 00:38:14,580 --> 00:38:23,590 Nå kan jeg gjøre noe sånt strcat - Hva er funksjonen for kopiering en streng? 489 00:38:23,590 --> 00:38:28,520 [Student] CpY? >> Strcpy. 490 00:38:28,520 --> 00:38:32,700 Mannen strcpy. 491 00:38:36,120 --> 00:38:39,590 Så strcpy eller strncpy. 492 00:38:39,590 --> 00:38:43,410 strncpy er litt tryggere siden du kan angi nøyaktig hvor mange tegn, 493 00:38:43,410 --> 00:38:46,190 men her er det ingen rolle, fordi vi vet. 494 00:38:46,190 --> 00:38:50,340 Så strcpy og se i argumentene. 495 00:38:50,340 --> 00:38:53,100 Det første argumentet er vår destinasjon. 496 00:38:53,100 --> 00:38:56,770 Det andre argumentet er vår kilde. 497 00:38:56,770 --> 00:39:10,310 Vi kommer til å kopiere inn i vår destinasjon * s pekeren "BOOM". 498 00:39:10,310 --> 00:39:19,820 Hvorfor kan det være lurt å gjøre dette med en strcpy i stedet for bare hva vi hadde før 499 00:39:19,820 --> 00:39:22,800 av * s = "BOOM"? 500 00:39:22,800 --> 00:39:28,630 Det er en grunn til at du kanskje ønsker å gjøre dette, men hva er det grunn? 501 00:39:28,630 --> 00:39:31,940 [Student] Hvis du ønsker å endre noe i "BOOM". >> Ja. 502 00:39:31,940 --> 00:39:37,950 Nå kan jeg gjøre noe som er [0] = 'X'; 503 00:39:37,950 --> 00:39:48,190 fordi s peker på haugen, og at plassen på haugen som s peker til 504 00:39:48,190 --> 00:39:52,320 er en peker til mer plass på haugen, som er lagring "BOOM". 505 00:39:52,320 --> 00:39:55,150 Så dette eksemplaret av "BOOM" blir lagret i haugen. 506 00:39:55,150 --> 00:39:58,780 Det er teknisk to kopier av "BOOM" i vårt program. 507 00:39:58,780 --> 00:40:03,500 Det er den første som er bare gitt av dette "BOOM" streng konstant, 508 00:40:03,500 --> 00:40:09,250 og den andre kopien av "BOOM", skapt strcpy kopien av "BOOM". 509 00:40:09,250 --> 00:40:13,100 Men kopien av "BOOM" blir lagret på haugen, og haugen er du fri til å endre. 510 00:40:13,100 --> 00:40:17,250 Haugen er ikke skrivebeskyttet, betyr at det er [0] 511 00:40:17,250 --> 00:40:20,500 kommer til å la deg endre verdien av "BOOM". 512 00:40:20,500 --> 00:40:23,130 Det kommer til å la deg endre disse tegnene. 513 00:40:23,130 --> 00:40:26,640 >> Spørsmål? 514 00:40:27,740 --> 00:40:29,290 Okay. 515 00:40:29,290 --> 00:40:35,500 >> Flytte til buggy3, la oss GDB buggy3. 516 00:40:35,500 --> 00:40:39,840 Vi bare kjøre den, og vi ser vi få en segfault. 517 00:40:39,840 --> 00:40:46,550 Hvis vi backtrace, er det bare to funksjoner. 518 00:40:46,550 --> 00:40:52,970 Hvis vi går opp i våre viktigste funksjon, ser vi at vi segfaulted på denne linjen. 519 00:40:52,970 --> 00:41:00,180 Så bare å se på denne linjen, int line = 0 for (; fgets denne ting ikke lik NULL; 520 00:41:00,180 --> 00:41:03,770 linje + +). 521 00:41:03,770 --> 00:41:08,010 Vår forrige rammen ble kalt _IO_fgets. 522 00:41:08,010 --> 00:41:10,720 Du vil se at mye med innebygd C-funksjoner, 523 00:41:10,720 --> 00:41:15,350 at når du får segfault, vil det være veldig kryptiske funksjon navn 524 00:41:15,350 --> 00:41:18,090 som dette _IO_fgets. 525 00:41:18,090 --> 00:41:21,770 Men det kommer til å forholde seg til dette fgets samtalen. 526 00:41:21,770 --> 00:41:25,850 Et sted inni her, vi segfaulting. 527 00:41:25,850 --> 00:41:30,340 Hvis vi ser på argumentene til fgets, kan vi skrive buffer. 528 00:41:30,340 --> 00:41:41,180 La oss skrive ut som en - Å, nei. 529 00:41:48,980 --> 00:41:51,900 Utskriften er ikke til å fungere akkurat som jeg vil ha det til. 530 00:41:55,460 --> 00:41:58,000 La oss se på selve programmet. 531 00:42:02,200 --> 00:42:09,640 Buffer er et tegn array. Det er et tegn rekke 128 tegn. 532 00:42:09,640 --> 00:42:14,980 Så når jeg sier print buffer, det kommer til å skrive ut de 128 tegn, 533 00:42:14,980 --> 00:42:18,300 som jeg tror er det som er forventet. 534 00:42:18,300 --> 00:42:21,390 Det jeg var ute etter, er skrive ut adressen buffer, 535 00:42:21,390 --> 00:42:23,680 men det betyr ikke fortelle meg virkelig mye. 536 00:42:23,680 --> 00:42:30,770 Så når jeg tilfeldigvis si opp her x buffer, viser det meg 0xbffff090, 537 00:42:30,770 --> 00:42:38,690 som, hvis du husker fra tidligere eller annet tidspunkt, har en tendens Oxbffff å være en stabel-ish regionen. 538 00:42:38,690 --> 00:42:46,020 Stabelen tendens til å begynne et sted i underkant 0xc000. 539 00:42:46,020 --> 00:42:51,890 Bare ved å se denne adressen, vet jeg at buffer som skjer på stakken. 540 00:42:51,890 --> 00:43:04,500 Starte min program, løpe, opp, buffer vi så var denne sekvensen av tegn 541 00:43:04,500 --> 00:43:06,530 som er ganske mye meningsløs. 542 00:43:06,530 --> 00:43:12,270 Deretter skrive filen, hva filen se ut? 543 00:43:15,120 --> 00:43:17,310 [Student] Null. >> Ja. 544 00:43:17,310 --> 00:43:22,610 Filen er en type fil *, så det er en peker, 545 00:43:22,610 --> 00:43:26,610 og verdien av at pekeren er null. 546 00:43:26,610 --> 00:43:33,240 Så fgets kommer til å prøve å lese fra den peker på en indirekte måte, 547 00:43:33,240 --> 00:43:37,320 men for å få tilgang til det pekeren, har det å dereferanse den. 548 00:43:37,320 --> 00:43:40,550 Eller, for å få tilgang hva det skal peke til, det dereferences det. 549 00:43:40,550 --> 00:43:43,810 Så det dereferencing en nullpeker og det segfaults. 550 00:43:46,600 --> 00:43:48,730 Jeg kunne ha startet den der. 551 00:43:48,730 --> 00:43:52,170 Hvis vi bryter på våre viktigste punkt og kjøre, 552 00:43:52,170 --> 00:43:57,320 den første linjen i koden er char * filename = "nonexistent.txt"; 553 00:43:57,320 --> 00:44:00,870 Det burde gi en ganske stor hint om hvorfor dette programmet mislykkes. 554 00:44:00,870 --> 00:44:06,080 Skrive neste bringer meg til neste linje, hvor jeg åpner denne filen, 555 00:44:06,080 --> 00:44:11,140 og da jeg umiddelbart komme inn vår linje, der en gang jeg traff neste, det kommer til å segfault. 556 00:44:11,140 --> 00:44:16,880 Ønsker noen å kaste ut en grunn til at vi kan bli segfaulting? 557 00:44:16,880 --> 00:44:19,130 [Student] Filen eksisterer ikke. >> Ja. 558 00:44:19,130 --> 00:44:22,250 Dette er ment å være et hint 559 00:44:22,250 --> 00:44:29,570 at når du åpner en fil må du sjekke at filen faktisk eksisterer. 560 00:44:29,570 --> 00:44:31,510 Så her, "nonexistent.txt"; 561 00:44:31,510 --> 00:44:34,700 Når vi fopen filnavn for lesing, vi da trenger å si 562 00:44:34,700 --> 00:44:45,870 if (fil == NULL) og si printf ("Filen eksisterer ikke!" 563 00:44:45,870 --> 00:44:56,340 eller - enda bedre - filnavn); return 1; 564 00:44:56,340 --> 00:45:00,300 Så nå er vi sjekke for å se om det er NULL 565 00:45:00,300 --> 00:45:03,930 før du faktisk fortsetter og prøver å lese fra filen. 566 00:45:03,930 --> 00:45:08,800 Vi kan remake det bare for å se at det fungerer. 567 00:45:11,020 --> 00:45:14,970 Jeg ment å omfatte en ny linje. 568 00:45:21,090 --> 00:45:25,290 Så nå nonexistent.txt ikke eksisterer. 569 00:45:26,890 --> 00:45:30,040 Du bør alltid sjekke om denne typen ting. 570 00:45:30,040 --> 00:45:33,870 Du bør alltid sjekke for å se om fopen returnerer NULL. 571 00:45:33,870 --> 00:45:38,170 Du bør alltid sjekke for å være sikker på at malloc ikke returnerer NULL, 572 00:45:38,170 --> 00:45:41,410 eller annet du segfault. 573 00:45:42,200 --> 00:45:45,930 >> Nå buggy4.c. 574 00:45:49,190 --> 00:45:58,440 Kjører. Jeg gjetter dette venter på innspill eller muligens uendelig looping. 575 00:45:58,440 --> 00:46:01,870 Ja, det er uendelig looping. 576 00:46:01,870 --> 00:46:05,560 Så buggy4. Det ser ut som vi er uendelig looping. 577 00:46:05,560 --> 00:46:12,590 Vi kan bryte på main, kjøre programmet vårt. 578 00:46:12,590 --> 00:46:20,180 I gdb, så lenge forkortelsen du bruker er entydig 579 00:46:20,180 --> 00:46:23,420 eller spesielle forkortelser som de gir for deg, 580 00:46:23,420 --> 00:46:29,020 så kan du bruke n til å bruke neste stedet for å måtte skrive ut neste hele veien. 581 00:46:29,020 --> 00:46:33,730 Og nå som jeg har truffet n gang, kan jeg bare trykke Enter for å holde det gående neste 582 00:46:33,730 --> 00:46:36,640 i stedet for å måtte treffe n Enter, n Enter n Enter. 583 00:46:36,640 --> 00:46:44,630 Det ser ut som jeg er i en slags for loop som er å sette array [i] til 0. 584 00:46:44,630 --> 00:46:50,510 Det ser ut som jeg aldri bryte ut av dette for loop. 585 00:46:50,510 --> 00:46:54,780 Hvis jeg skriver i, så jeg er 2, så skal jeg gå neste. 586 00:46:54,780 --> 00:46:59,250 Jeg skal skrive i, i er 3, så skal jeg gå neste. 587 00:46:59,250 --> 00:47:05,360 Jeg skal skrive i og jeg er 3. Deretter skriver jeg, er jeg 4. 588 00:47:05,360 --> 00:47:14,520 Egentlig er print sizeof (matrise), så størrelsen på matrisen 20. 589 00:47:16,310 --> 00:47:32,870 Men det ser ut som om det er noen spesiell gdb kommando for å gå til noe skjer. 590 00:47:32,870 --> 00:47:37,620 Det er som å sette en tilstand på verdien av variabelen. Men jeg husker ikke hva det er. 591 00:47:37,620 --> 00:47:44,100 Så hvis vi fortsetter - 592 00:47:44,100 --> 00:47:47,120 Hva sa du? Hva gjorde du med opp? 593 00:47:47,120 --> 00:47:50,500 [Student] Vises jeg legge - >> Ja. Så viser jeg kan hjelpe. 594 00:47:50,500 --> 00:47:54,530 Hvis vi bare vise i, vil det satt opp her hva verdien av jeg er 595 00:47:54,530 --> 00:47:56,470 så jeg trenger ikke å skrive den ut hver gang. 596 00:47:56,470 --> 00:48:02,930 Hvis vi fortsetter bare neste, ser vi 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 Noe kommer fryktelig galt, og jeg er tilbakestilt blir til 0. 598 00:48:13,330 --> 00:48:22,220 Ser på buggy4.c, ser vi alt som skjer er int array [5]; 599 00:48:22,220 --> 00:48:26,200 for (i = 0; i <= sizeof (matrise); i + +) 600 00:48:26,200 --> 00:48:28,550 array [i] = 0; 601 00:48:28,550 --> 00:48:31,390 Hva ser vi det er galt her? 602 00:48:31,390 --> 00:48:39,480 Som et hint, da jeg gjorde gdb buggy4 - la oss bryte viktigste, run - 603 00:48:39,480 --> 00:48:45,980 Jeg gjorde print sizeof (matrise) bare for å se hva tilstanden er der jeg skal endelig bryte ut. 604 00:48:47,690 --> 00:48:51,100 Hvor er jeg? Sa jeg kjøre? 605 00:48:51,100 --> 00:48:54,280 Jeg gjorde ikke erklære ennå. 606 00:48:54,280 --> 00:48:58,680 Så ut sizeof (matrise), og det er 20, 607 00:48:58,680 --> 00:49:06,690 som er forventet siden min array er av størrelse 5 og det er av 5 heltall, 608 00:49:06,690 --> 00:49:12,410 så hele greia bør være 5 * sizeof (int) byte, hvor sizeof (int) har en tendens til å være fire. 609 00:49:12,410 --> 00:49:14,780 Så sizeof (array) er 20 år. 610 00:49:14,780 --> 00:49:17,420 Hva skal dette være? 611 00:49:17,420 --> 00:49:21,720 [Student] Fordelt på sizeof (int). >> Ja, / sizeof (int). 612 00:49:21,720 --> 00:49:30,630 Det ser ut som det fortsatt er et problem her. Jeg tror dette bør bare være < 613 00:49:30,630 --> 00:49:36,960 siden det er stort sett alltid 00:49:44,860 Nå la oss tenke på hvorfor dette ble faktisk brutt. 615 00:49:44,860 --> 00:49:53,370 Har noen gjetninger hvorfor ble jeg tilbakestilt til 0 gjennom hver iterasjon av loopen? 616 00:50:01,300 --> 00:50:09,350 Det eneste innsiden av her som skjer er at array [i] blir satt til 0. 617 00:50:09,350 --> 00:50:15,350 Så noe, er denne linjen med kode forårsaker vår int i å bli satt til 0. 618 00:50:16,730 --> 00:50:23,130 [Student] Kan det være fordi det overordnede minnet om denne delen av jeg 619 00:50:23,130 --> 00:50:27,970 når det mener det er det neste elementet av array? >> [Bowden] Ja. 620 00:50:27,970 --> 00:50:33,880 Når vi kommer utover slutten av tabellen vår, 621 00:50:33,880 --> 00:50:39,870 liksom at rommet som vi overstyrer overstyrer verdien av jeg. 622 00:50:39,870 --> 00:50:48,030 Og så hvis vi ser inn buggy4, bryte viktigste, løpe, 623 00:50:48,030 --> 00:50:53,120 la oss skrive inn adressen i. 624 00:50:53,120 --> 00:50:57,280 Det ser ut som det er bffff124. 625 00:50:57,280 --> 00:51:03,930 La oss nå skrive inn adressen til array [0]. 110. 626 00:51:03,930 --> 00:51:06,290 Hva om [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] er bfff124. 629 00:51:14,530 --> 00:51:26,990 Så matrise [5] har samme adresse som jeg, som betyr at matrisen [5] er i. 630 00:51:26,990 --> 00:51:30,720 Hvis de har samme adresse, er de samme. 631 00:51:30,720 --> 00:51:38,410 Så når vi setter array [5] til 0, setter vi i til 0. 632 00:51:38,410 --> 00:51:46,070 Og hvis du tenker på dette i form av stabelen, 633 00:51:46,070 --> 00:51:55,590 int i er erklært først, noe som betyr at jeg får litt plass på stakken. 634 00:51:55,590 --> 00:52:04,730 Så array [5] er tildelt, så da 20 byte fordeles på stakken. 635 00:52:04,730 --> 00:52:08,400 Så jeg blir tildelt først, deretter disse 20 bytes får tildelt. 636 00:52:08,400 --> 00:52:11,400 Så jeg skjer rett før array, 637 00:52:11,400 --> 00:52:19,230 og på grunn av måten som jeg sa i forrige uke, der teknisk stabelen vokser ned, 638 00:52:19,230 --> 00:52:28,520 når du indeks til en matrise, er vi garantert at 0th posisjonen i matrisen 639 00:52:28,520 --> 00:52:31,970 alltid skjer før den første posisjonen i matrisen. 640 00:52:31,970 --> 00:52:35,900 Dette er slags hvordan jeg trakk det forrige uke. 641 00:52:35,900 --> 00:52:42,210 Legg merke til at på bunnen har vi adresse 0 og øverst har vi adresse Maks. 642 00:52:42,210 --> 00:52:44,880 Stabelen er alltid vokser ned. 643 00:52:48,100 --> 00:52:53,500 La oss si at vi fordele jeg. 644 00:52:53,500 --> 00:52:59,680 Vi tildeler heltall i, som betyr la oss bare si opp her heltall i blir tildelt. 645 00:52:59,680 --> 00:53:06,420 Da vi fordele vår rekke av 5 heltall, noe som betyr at under det, 646 00:53:06,420 --> 00:53:11,230 siden stabelen vokser ned, får de 5 heltall tildelt. 647 00:53:11,230 --> 00:53:15,900 Men på grunn av hvordan arrayer fungerer, vi garantert at den første posisjonen i matrisen 648 00:53:15,900 --> 00:53:22,260 alltid har en adresse mindre enn den andre ting i matrisen. 649 00:53:22,260 --> 00:53:28,270 Så matrise posisjon 0 har alltid skje først i minnet, 650 00:53:28,270 --> 00:53:30,700 mens matrise posisjon 1 må skje etter at 651 00:53:30,700 --> 00:53:33,310 og utvalg posisjon 2 må skje etter det, 652 00:53:33,310 --> 00:53:37,900 noe som betyr at matrisen posisjon 0 ville skje et sted her nede, 653 00:53:37,900 --> 00:53:40,690 matrise posisjon 1 ville skje over at 654 00:53:40,690 --> 00:53:45,530 fordi flytte opp betyr høyere adresser siden det maksimale adresse er her oppe. 655 00:53:45,530 --> 00:53:50,490 Så array [0] her nede, array [1] her oppe, array [2] opp her, array [3] opp her. 656 00:53:50,490 --> 00:53:55,620 Legg merke til hvordan før vi tildelt heltall i hele veien opp her, 657 00:53:55,620 --> 00:54:01,040 når vi flytter lenger og lenger inn i matrisen vår, vi kommer nærmere og nærmere vår heltall jeg. 658 00:54:01,040 --> 00:54:07,640 Det bare så skjer at array [5], som er en posisjon utenfor rekke vår, 659 00:54:07,640 --> 00:54:13,010 er akkurat der heltall jeg skjedd å bli tildelt. 660 00:54:13,010 --> 00:54:16,920 Så det er det punktet hvor vi måtte bli trykket plassen på stakken 661 00:54:16,920 --> 00:54:21,680 som ble tildelt for heltall i, og vi setter det til 0. 662 00:54:21,680 --> 00:54:26,160 >> Det er slik det fungerer. Spørsmål? Ja. 663 00:54:26,160 --> 00:54:30,710 [Student] Never mind. Okay. 664 00:54:30,710 --> 00:54:33,090 [Student] Hvordan kan du unngå disse slags feil? 665 00:54:33,090 --> 00:54:41,190 Disse slags feil? Ikke bruk C som programmeringsspråk. 666 00:54:41,190 --> 00:54:45,840 Bruke et språk som har matrise grensekontroll. 667 00:54:45,840 --> 00:54:55,900 Så lenge du er forsiktig, du trenger bare å unngå å gå forbi grensene av arrayet. 668 00:54:55,900 --> 00:54:58,300 [Student] Så her når vi gikk forbi grensene for arrayet - 669 00:54:58,300 --> 00:55:01,840 [Bowden] Det er der ting begynner å gå galt. >> [Student] Oh, okay. 670 00:55:01,840 --> 00:55:05,730 Så lenge du holder deg innenfor den minnebruken for arrayet, du er fin. 671 00:55:05,730 --> 00:55:12,400 Men C gjør ingen feilkontroll. Hvis jeg gjør array [1000], vil det gjerne bare endre hva som skjer - 672 00:55:12,400 --> 00:55:16,500 Det går til begynnelsen av tabellen, så det går 1000 stillinger etter og setter den til 0. 673 00:55:16,500 --> 00:55:20,000 Det gjør ikke noe sjekke at oh, betyr ikke egentlig har 1000 ting i den. 674 00:55:20,000 --> 00:55:22,750 1000 er langt mer enn hva jeg bør forandres, 675 00:55:22,750 --> 00:55:26,940 mens Java eller noe du får rekke utenfor banen indeksen 676 00:55:26,940 --> 00:55:29,820 eller indeks utenfor banen unntak. 677 00:55:29,820 --> 00:55:33,950 Det er derfor mye høyere nivå språk har disse tingene 678 00:55:33,950 --> 00:55:37,340 der hvis du går utenfor grensene av tabellen, mislykkes du 679 00:55:37,340 --> 00:55:40,070 slik at du ikke kan endre ting fra under deg 680 00:55:40,070 --> 00:55:42,590 og deretter ting går mye verre enn bare å få et unntak 681 00:55:42,590 --> 00:55:44,940 si at du gikk utover slutten av tabellen. 682 00:55:44,940 --> 00:55:50,970 [Student] Og så bør vi ha bare endret <= å bare > [Bowden] Yeah. 683 00:55:50,970 --> 00:55:54,800 Det bør være 00:55:59,560 siden sizeof (matrise) er 20, men vi vil bare fem. >> [Student] Høyre. 685 00:55:59,560 --> 00:56:04,060 Flere spørsmål? Okay. 686 00:56:04,060 --> 00:56:07,380 >> [Student] Jeg har et spørsmål. >> Ja. 687 00:56:07,380 --> 00:56:16,440 [Student] Hva er den faktiske tabell variabel? 688 00:56:16,440 --> 00:56:20,000 [Bowden] Som hva er array? 689 00:56:20,000 --> 00:56:24,930 Array seg selv er et symbol. 690 00:56:24,930 --> 00:56:31,490 Det er bare adressen til starten av 20 byte som vi refererer. 691 00:56:31,490 --> 00:56:38,070 Du kan tenke på det som en peker, men det er en konstant peker. 692 00:56:38,070 --> 00:56:44,140 Så snart ting blir samlet, ikke variabel rekke ikke eksisterer lenger. 693 00:56:44,140 --> 00:56:48,210 [Student] Så hvordan finner det størrelsen på array? 694 00:56:48,210 --> 00:56:54,130 Størrelse av array refererer til størrelsen av denne blokken som det symbolet refererer til. 695 00:56:54,130 --> 00:57:01,240 Når jeg gjør noe sånt printf ("% p \ n", array); 696 00:57:01,240 --> 00:57:05,140 la oss kjøre den. 697 00:57:12,960 --> 00:57:15,530 Hva gjorde jeg bare gjøre galt? 698 00:57:15,530 --> 00:57:19,220 Array 'utvalg' erklærte her. 699 00:57:20,820 --> 00:57:23,200 Oh, her oppe. 700 00:57:23,200 --> 00:57:31,250 Clang er flink, og det skjer for å legge merke til at jeg erklærte matrisen som 5 elementer 701 00:57:31,250 --> 00:57:34,540 men jeg indeksering i posisjon 1000. 702 00:57:34,540 --> 00:57:38,450 Det kan gjøre det fordi dette er bare konstanter. 703 00:57:38,450 --> 00:57:43,370 Det kan bare gå så langt i å legge merke til at jeg går utover grensene i tabellen. 704 00:57:43,370 --> 00:57:46,880 Men legg merke før når vi hadde jeg være feil, 705 00:57:46,880 --> 00:57:51,040 det kan umulig bestemme hvor mange verdier jeg kunne ta på, 706 00:57:51,040 --> 00:57:55,540 så det ikke kan fastslå at jeg skulle utover slutten av tabellen. 707 00:57:55,540 --> 00:57:59,430 Det er bare Clang være flink. 708 00:57:59,430 --> 00:58:03,340 >> Men nå gjør buggy4. Så hva annet jeg gjør galt? 709 00:58:03,340 --> 00:58:05,970 Implisitt erklære biblioteket funksjon 'printf'. 710 00:58:05,970 --> 00:58:14,960 Jeg kommer til å ønske å # include . 711 00:58:14,960 --> 00:58:18,710 Okay. Nå kjører buggy4. 712 00:58:18,710 --> 00:58:24,840 Skrive verdien i matrisen som jeg gjorde her, skrive den som en peker 713 00:58:24,840 --> 00:58:30,060 utskrifter noe som ser ut som dette - bfb8805c - som er noen adresse 714 00:58:30,060 --> 00:58:33,450 som er i bunken-ish regionen. 715 00:58:33,450 --> 00:58:41,820 Array selv er som en peker, men det er ikke en faktisk peker, 716 00:58:41,820 --> 00:58:45,410 siden en vanlig pekeren kan vi endre. 717 00:58:45,410 --> 00:58:54,700 Array er bare noen konstant. De 20 minneblokker starter på adresse 0xbfb8805c. 718 00:58:54,700 --> 00:59:09,020 Så bfb8805c gjennom denne adressen +20--eller jeg antar -20 - 719 00:59:09,020 --> 00:59:17,400 er hele hukommelsen allokert for denne matrisen. 720 00:59:17,400 --> 00:59:20,350 Matrise, blir variabelen selv ikke lagret noe. 721 00:59:20,350 --> 00:59:27,660 Når du kompilering, kompilatoren - hånd bølge på det - 722 00:59:27,660 --> 00:59:33,060 men kompilatoren vil bare bruke hvor det vet matrise å være. 723 00:59:33,060 --> 00:59:36,090 Det vet hvor denne matrisen starter, 724 00:59:36,090 --> 00:59:40,910 og slik at det kan alltid bare gjøre ting i form av forskyvninger fra at begynnelsen. 725 00:59:40,910 --> 00:59:43,960 Det trenger ikke en variabel i seg selv å representere array. 726 00:59:43,960 --> 00:59:53,730 Men når jeg gjør noe sånt int * p = array, nå p er en peker som peker til denne matrisen, 727 00:59:53,730 --> 00:59:57,830 og nå p faktisk eksisterer på stakken. 728 00:59:57,830 --> 01:00:01,950 Jeg er fri til å endre p. Jeg kan gjøre p = malloc. 729 01:00:01,950 --> 01:00:06,500 Så det opprinnelig pekte rekke, nå den peker på noen plass på haugen. 730 01:00:06,500 --> 01:00:09,620 Jeg kan ikke gjøre rekke = malloc. 731 01:00:09,620 --> 01:00:13,710 Hvis Clang er smart, vil det kjefte på meg rett utenfor balltre. 732 01:00:17,000 --> 01:00:21,430 Faktisk er jeg ganske sikker på at gcc ville gjøre dette også. 733 01:00:21,430 --> 01:00:25,010 Så rekke type 'int [5]' er ikke overdras. 734 01:00:25,010 --> 01:00:28,040 Du kan ikke tildele noe til en rekke typer 735 01:00:28,040 --> 01:00:30,500 fordi matrise er bare en konstant. 736 01:00:30,500 --> 01:00:34,760 Det er et symbol som refererer de 20 bytes. Jeg kan ikke endre det. 737 01:00:34,760 --> 01:00:37,690 >> [Student] Og hvor er størrelsen på tabellen lagret? 738 01:00:37,690 --> 01:00:40,670 [Bowden] Det er ikke lagret noe sted. Det er når det er kompilering. 739 01:00:40,670 --> 01:00:46,310 Så der er størrelsen på matrisen lagret? 740 01:00:46,310 --> 01:00:51,870 Du kan bare bruke sizeof (matrise) innsiden av den funksjonen som matrisen er erklært seg selv. 741 01:00:51,870 --> 01:01:03,150 Så hvis jeg gjør noen funksjon, foo, og jeg (int array []) 742 01:01:03,150 --> 01:01:10,450 printf ("% d \ n", sizeof (matrise)); 743 01:01:10,450 --> 01:01:21,330 og deretter ned her jeg kaller foo (array); 744 01:01:21,330 --> 01:01:24,840 innsiden av denne funksjonen - la oss kjøre den. 745 01:01:34,200 --> 01:01:36,840 Dette er Clang være flink igjen. 746 01:01:36,840 --> 01:01:43,890 Det forteller meg at sizeof på rekke funksjon parameter 747 01:01:43,890 --> 01:01:46,690 vil returnere størrelsen 'int *'. 748 01:01:46,690 --> 01:01:55,150 Dette ville være en feil hvis det ikke er det jeg ønsket skulle skje. 749 01:01:55,150 --> 01:01:58,960 La oss faktisk slå av Werror. 750 01:02:14,950 --> 01:02:17,590 Advarsel. Advarsler er fine. 751 01:02:17,590 --> 01:02:19,960 Det vil fortsatt kompilere så lenge den har en advarsel. 752 01:02:19,960 --> 01:02:22,910 . / A.out kommer til å skrive ut 4. 753 01:02:22,910 --> 01:02:28,650 Advarselen som ble generert er en klar indikator på hva som gikk galt. 754 01:02:28,650 --> 01:02:34,120 Dette int array er bare kommer til å skrive ut sizeof (int *). 755 01:02:34,120 --> 01:02:39,790 Selv om jeg setter array [5] her, er det fortsatt bare kommer til å skrive ut sizeof (int *). 756 01:02:39,790 --> 01:02:47,440 Så så snart du passerer det inn i en funksjon, skillet mellom arrays og pekere 757 01:02:47,440 --> 01:02:49,670 er ikke-eksisterende. 758 01:02:49,670 --> 01:02:52,640 Dette skjer for å være en matrise som ble erklært på stakken, 759 01:02:52,640 --> 01:02:58,300 men så snart vi passerer den verdien som 0xBF blah, blah, blah inn i denne funksjonen, 760 01:02:58,300 --> 01:03:03,350 så denne pekeren peker på at matrisen på stakken. 761 01:03:03,350 --> 01:03:08,310 Så det betyr at sizeof gjelder bare i funksjonen at matrisen ble erklært, 762 01:03:08,310 --> 01:03:11,230 noe som betyr at når du kompilere denne funksjonen, 763 01:03:11,230 --> 01:03:17,330 når Clang går gjennom denne funksjonen, ser det matrise er en int array av størrelse 5. 764 01:03:17,330 --> 01:03:20,640 Så da det ser sizeof (array). Vel, det er 20. 765 01:03:20,640 --> 01:03:26,440 Det er faktisk hvordan sizeof utgangspunktet fungerer for nesten alle tilfeller. 766 01:03:26,440 --> 01:03:31,150 Sizeof er ikke en funksjon, det er en operatør. 767 01:03:31,150 --> 01:03:33,570 Du trenger ikke kalle sizeof funksjonen. 768 01:03:33,570 --> 01:03:38,280 Sizeof (int), vil kompilatoren bare oversette det til 4. 769 01:03:41,480 --> 01:03:43,700 Fikk den? Okay. 770 01:03:43,700 --> 01:03:47,520 >> [Student] Så hva er forskjellen mellom sizeof (matrise) i hoved-og i Foo? 771 01:03:47,520 --> 01:03:52,840 Dette er fordi vi sier sizeof (matrise), som er av typen int *, 772 01:03:52,840 --> 01:03:57,120 mens tabellen her nede er ikke av typen int *, er det en int array. 773 01:03:57,120 --> 01:04:04,540 >> [Student] Så hvis du hadde parameter i array [] i stedet for int * array, 774 01:04:04,540 --> 01:04:09,230 ville det bety at du kan fortsatt endre utvalg fordi nå er det en peker? 775 01:04:09,230 --> 01:04:14,250 [Bowden] Liker du dette? >> [Student] Yeah. Kan du endre utvalg i funksjonen nå? 776 01:04:14,250 --> 01:04:18,420 [Bowden] Du kan endre array i begge tilfeller. 777 01:04:18,420 --> 01:04:23,130 I begge disse tilfellene er du fri til å si array [4] = 0. 778 01:04:23,130 --> 01:04:26,590 [Student] Men kan du gjøre utvalg peker på noe annet? 779 01:04:26,590 --> 01:04:30,230 [Bowden] Oh. Ja. I begge tilfeller - >> [student] Yeah. 780 01:04:30,230 --> 01:04:38,410 [Bowden] Skillet mellom array [] og en int * array, det er ingen. 781 01:04:38,410 --> 01:04:42,570 Du kan også få noen flerdimensjonal array her 782 01:04:42,570 --> 01:04:47,050 for noen praktisk syntaks, men det er fortsatt bare en peker. 783 01:04:47,050 --> 01:04:56,400 Dette betyr at jeg er fri til å gjøre utvalg = malloc (sizeof (int)), og nå peker et annet sted. 784 01:04:56,400 --> 01:04:59,610 Men akkurat som hvordan dette fungerer for evig og alltid, 785 01:04:59,610 --> 01:05:03,210 endre denne tabellen ved å gjøre det peke på noe annet 786 01:05:03,210 --> 01:05:07,570 endrer ikke denne tabellen her nede fordi det er en kopi av argumentet, 787 01:05:07,570 --> 01:05:10,780 det er ikke en peker til dette argumentet. 788 01:05:10,780 --> 01:05:16,070 Og faktisk, akkurat som mer indikasjon på at det er akkurat det samme - 789 01:05:16,070 --> 01:05:21,100 vi allerede så hva utskrift rekke utskrifter - 790 01:05:21,100 --> 01:05:31,410 hva om vi skriver inn adressen til matrisen eller adressen til adressen i matrisen 791 01:05:31,410 --> 01:05:36,290 til en av dem? 792 01:05:41,770 --> 01:05:45,220 La oss ignorere dette. 793 01:05:48,140 --> 01:05:51,660 Okay. Dette er greit. Det er nå i gang. / A.out. 794 01:05:51,660 --> 01:06:00,220 Utskrift array, deretter skrive inn adressen til array, er det samme. 795 01:06:00,220 --> 01:06:02,870 Array bare ikke eksisterer. 796 01:06:02,870 --> 01:06:08,190 Den vet når du skal skrive ut matrisen, du skriver symbolet som refererer til de 20 byte. 797 01:06:08,190 --> 01:06:11,940 Skrive ut adressen til array, vel, ikke matrise ikke eksisterer. 798 01:06:11,940 --> 01:06:17,200 Det har ikke en adresse, slik at det bare skriver adresse til de 20 byte. 799 01:06:20,820 --> 01:06:28,150 Så snart du kompilere ned, som i en samlet buggy4. / A.out, 800 01:06:28,150 --> 01:06:30,340 matrise er ikke tilstede. 801 01:06:30,340 --> 01:06:33,640 Pekere eksisterer. Arrays ikke. 802 01:06:34,300 --> 01:06:38,060 Blokkene minne representerer tabellen fortsatt eksisterer, 803 01:06:38,060 --> 01:06:43,270 men den variable matrise og variabler av denne typen ikke eksisterer. 804 01:06:46,260 --> 01:06:50,270 De er som de viktigste forskjellene mellom arrays og pekere 805 01:06:50,270 --> 01:06:55,590 er så snart du gjør funksjonskall, er det ingen forskjell. 806 01:06:55,590 --> 01:07:00,460 Men innsiden av funksjonen som matrisen selv er erklært, fungerer sizeof annerledes 807 01:07:00,460 --> 01:07:05,190 siden du skriver størrelsen av blokkene i stedet for størrelsen av den type, 808 01:07:05,190 --> 01:07:08,950 og du kan ikke endre det fordi det er et symbol. 809 01:07:08,950 --> 01:07:14,370 Skrive ut ting og adressen til ting skriver det samme. 810 01:07:14,370 --> 01:07:18,480 Og det er ganske mye det. 811 01:07:18,480 --> 01:07:20,820 [Student] Kan du si det en gang til? 812 01:07:21,170 --> 01:07:24,170 Jeg kan ha gått glipp av noe. 813 01:07:24,170 --> 01:07:29,260 Utskrift rekke og adresse rekke skriver det samme, 814 01:07:29,260 --> 01:07:33,180 mens hvis du skriver ut en peker mot adressen pekeren, 815 01:07:33,180 --> 01:07:36,010 den ene tingen skriver adressen på hva du peker til, 816 01:07:36,010 --> 01:07:40,360 den andre skriver adressen pekeren på stakken. 817 01:07:40,360 --> 01:07:47,040 Du kan endre en peker, du kan ikke endre en rekke symbol. 818 01:07:47,740 --> 01:07:53,270 Og sizeof pekeren kommer til å skrive ut størrelsen på at pekeren type. 819 01:07:53,270 --> 01:07:57,470 Så int * p sizeof (p) kommer til å skrive ut 4, 820 01:07:57,470 --> 01:08:04,110 men int array [5] print sizeof (matrise) kommer til å skrive ut 20. 821 01:08:04,110 --> 01:08:07,480 [Student] Så int array [5] vil skrive 20? >> Ja. 822 01:08:07,480 --> 01:08:13,300 Det er derfor inne i buggy4 når det pleide å være sizeof (array) 823 01:08:13,300 --> 01:08:16,660 dette gjorde jeg <20, som er ikke hva vi ønsket. 824 01:08:16,660 --> 01:08:20,880 Vi ønsker i <5. >> [Student] Okay. 825 01:08:20,880 --> 01:08:25,569 [Bowden] Og så så snart du begynner å passere i funksjonene, 826 01:08:25,569 --> 01:08:34,340 hvis vi gjorde int * p = array; 827 01:08:34,340 --> 01:08:39,779 innsiden av denne funksjonen, kan vi i utgangspunktet bruke p og utvalg i nøyaktig de samme måter, 828 01:08:39,779 --> 01:08:43,710 unntak sizeof problemet og skiftende problem. 829 01:08:43,710 --> 01:08:49,810 Men p [0] = 1; er det samme som å si matrise [0] = 1; 830 01:08:49,810 --> 01:08:55,600 Og så snart vi si foo (array), eller foo (p); 831 01:08:55,600 --> 01:08:59,760 innsiden av foo funksjon, er dette det samme anropet to ganger. 832 01:08:59,760 --> 01:09:03,350 Det er ingen forskjell mellom disse to samtalene. 833 01:09:07,029 --> 01:09:11,080 >> Alle gode på det? Okay. 834 01:09:14,620 --> 01:09:17,950 Vi har 10 minutter. 835 01:09:17,950 --> 01:09:28,319 >> Vi skal prøve å komme gjennom denne Hacker Typer program, 836 01:09:28,319 --> 01:09:32,350 dette nettstedet, som kom ut i fjor eller noe. 837 01:09:34,149 --> 01:09:41,100 Det er bare ment å være som du skriver tilfeldig og det skrives ut - 838 01:09:41,100 --> 01:09:46,729 Uansett fil det skjer å ha lastet er hva det ser ut som du skriver. 839 01:09:46,729 --> 01:09:52,069 Det ser ut som en slags operativsystem kode. 840 01:09:53,760 --> 01:09:56,890 Det er hva vi ønsker å gjennomføre. 841 01:10:08,560 --> 01:10:11,690 Du bør ha en binær kjørbar heter hacker_typer 842 01:10:11,690 --> 01:10:14,350 som tar i et enkelt argument, filen til "hacker type." 843 01:10:14,350 --> 01:10:16,480 Kjører den kjørbare bør tømme skjermen 844 01:10:16,480 --> 01:10:20,850 og deretter skrive ut en karakter fra bestått-in fil hver gang brukeren trykker på en knapp. 845 01:10:20,850 --> 01:10:24,990 Så uansett hva tast du trykker på, bør det kaste bort og i stedet skrive ut et tegn fra filen 846 01:10:24,990 --> 01:10:27,810 som er argumentet. 847 01:10:29,880 --> 01:10:34,350 Jeg får ganske mye fortelle deg hva de tingene vi kommer til å trenge å vite er. 848 01:10:34,350 --> 01:10:36,440 Men vi ønsker å sjekke ut termios biblioteket. 849 01:10:36,440 --> 01:10:44,840 Jeg har aldri brukt dette biblioteket i hele mitt liv, så det har svært minimale formål. 850 01:10:44,840 --> 01:10:48,610 Men dette kommer til å være på biblioteket vi kan bruke til å kaste bort tegnet du treffer 851 01:10:48,610 --> 01:10:52,390 når du skriver inn standard i. 852 01:10:56,970 --> 01:11:05,840 Så hacker_typer.c, og vi kommer til å ønske å # include . 853 01:11:05,840 --> 01:11:12,870 Ser på mannen siden for termios - jeg gjetter det er terminal OS eller noe - 854 01:11:12,870 --> 01:11:16,240 Jeg vet ikke hvordan du skal lese den. 855 01:11:16,240 --> 01:11:21,040 Ser på dette, sier det å inkludere disse to filene, så vi får gjøre det. 856 01:11:37,620 --> 01:11:46,820 >> Første ting først, ønsker vi å ta i et enkelt argument, som er filen vi skal åpne. 857 01:11:46,820 --> 01:11:52,420 Så hva ønsker jeg å gjøre? Hvordan sjekker jeg å se jeg har et enkelt argument? 858 01:11:52,420 --> 01:11:56,480 [Student] Hvis argc lik den. >> [Bowden] Yeah. 859 01:11:56,480 --> 01:12:21,250 Så hvis (argc = 2!) Printf ("bruk:% s [filen for å åpne]"). 860 01:12:21,250 --> 01:12:32,750 Så nå hvis jeg kjører denne uten å gi et annet argument - oh, jeg trenger den nye linjen - 861 01:12:32,750 --> 01:12:36,240 vil du se det står bruk:. / hacker_typer, 862 01:12:36,240 --> 01:12:39,770 og deretter det andre argumentet bør være filen jeg ønsker å åpne. 863 01:12:58,430 --> 01:13:01,260 Nå hva gjør jeg? 864 01:13:01,260 --> 01:13:08,490 Jeg ønsker å lese fra denne filen. Hvordan leser jeg fra en fil? 865 01:13:08,490 --> 01:13:11,920 [Student] Du åpner den først. >> Ja. 866 01:13:11,920 --> 01:13:15,010 Så fopen. Hvordan ser fopen ut? 867 01:13:15,010 --> 01:13:22,980 [Student] Filnavn. >> [Bowden] Filnavn kommer til å være argv [1]. 868 01:13:22,980 --> 01:13:26,110 [Student] Og hva du vil gjøre med det, så - >> [Bowden] Yeah. 869 01:13:26,110 --> 01:13:28,740 Så hvis du ikke husker, kan du bare gjøre mennesket fopen, 870 01:13:28,740 --> 01:13:32,960 hvor det kommer til å bli en const char * banen der bane er filnavn, 871 01:13:32,960 --> 01:13:34,970 const char * modus. 872 01:13:34,970 --> 01:13:38,660 Hvis du tilfeldigvis ikke huske hvilken modus er, så kan du se etter modus. 873 01:13:38,660 --> 01:13:44,660 Innsiden av man-sidene, er skråstreken tegnet hva du kan bruke til å søke etter ting. 874 01:13:44,660 --> 01:13:49,790 Så jeg skriver / modus for å søke etter modus. 875 01:13:49,790 --> 01:13:57,130 n og N er hva du kan bruke til å bla gjennom søk kamper. 876 01:13:57,130 --> 01:13:59,800 Her står det argumentet modus peker til en streng 877 01:13:59,800 --> 01:14:01,930 begynner med en av de følgende sekvenser. 878 01:14:01,930 --> 01:14:06,480 Så r, Open tekstfil for lesing. Det er hva vi ønsker å gjøre. 879 01:14:08,930 --> 01:14:13,210 For å lese, og jeg ønsker å lagre det. 880 01:14:13,210 --> 01:14:18,720 Saken kommer til å bli en FIL *. Nå hva gjør jeg ønsker å gjøre? 881 01:14:18,720 --> 01:14:21,200 Gi meg et sekund. 882 01:14:28,140 --> 01:14:30,430 Okay. Nå hva gjør jeg ønsker å gjøre? 883 01:14:30,430 --> 01:14:32,940 [Student] Sjekk om det er NULL. >> [Bowden] Yeah. 884 01:14:32,940 --> 01:14:38,690 Hver gang du åpner en fil, sørg for at du er vellykket i stand til å åpne den. 885 01:14:58,930 --> 01:15:10,460 >> Nå ønsker jeg å gjøre det termios ting der jeg ønsker å først lese min nåværende innstillinger 886 01:15:10,460 --> 01:15:14,050 og lagre dem til noe, så jeg ønsker å endre innstillingene mine 887 01:15:14,050 --> 01:15:19,420 å kaste bort alle tegn som jeg skriver, 888 01:15:19,420 --> 01:15:22,520 og da vil jeg oppdatere disse innstillingene. 889 01:15:22,520 --> 01:15:27,250 Og deretter på slutten av programmet, vil jeg bytte tilbake til mitt opprinnelige innstillinger. 890 01:15:27,250 --> 01:15:32,080 Så struct kommer til å være av type termios, og jeg kommer til å ha to av disse. 891 01:15:32,080 --> 01:15:35,600 Den første kommer til å være mine current_settings, 892 01:15:35,600 --> 01:15:42,010 og da de kommer til å være mine hacker_settings. 893 01:15:42,010 --> 01:15:48,070 Først, jeg kommer til å ønske å lagre mine gjeldende innstillinger, 894 01:15:48,070 --> 01:15:53,790 så jeg kommer til å ønske å oppdatere hacker_settings, 895 01:15:53,790 --> 01:16:01,570 og deretter helt på slutten av mitt program, vil jeg gå tilbake til gjeldende innstillinger. 896 01:16:01,570 --> 01:16:08,660 Så sparer gjeldende innstillinger, slik som fungerer, vi mann termios. 897 01:16:08,660 --> 01:16:15,810 Vi ser at vi har denne int tcsetattr, int tcgetattr. 898 01:16:15,810 --> 01:16:22,960 Jeg passerer i en termios struct av pekeren sin. 899 01:16:22,960 --> 01:16:30,640 Måten dette skal se ut er - jeg har allerede glemt hva funksjonen ble kalt. 900 01:16:30,640 --> 01:16:34,930 Kopier og lim inn. 901 01:16:39,150 --> 01:16:45,500 Så tcgetattr, så jeg ønsker å passere i struct at jeg lagrer informasjonen i, 902 01:16:45,500 --> 01:16:49,650 som kommer til å bli current_settings, 903 01:16:49,650 --> 01:16:59,120 og det første argumentet er filen beskrivelse for ting jeg ønsker å lagre egenskapene til. 904 01:16:59,120 --> 01:17:04,360 Hva filen descriptor er er som når du åpner en fil, blir det en fil descriptor. 905 01:17:04,360 --> 01:17:14,560 Når jeg fopen argv [1], blir det en fil descriptor som du refererer 906 01:17:14,560 --> 01:17:16,730 når du ønsker å lese eller skrive til den. 907 01:17:16,730 --> 01:17:19,220 Det er ikke filen descriptor jeg ønsker å bruke her. 908 01:17:19,220 --> 01:17:21,940 Det er tre fildeskriptorer du har som standard, 909 01:17:21,940 --> 01:17:24,310 som er standard i, standard ut, og standard feil. 910 01:17:24,310 --> 01:17:29,960 Som standard, tror jeg det er standard i er 0, er standard ut 1, og standard feil er to. 911 01:17:29,960 --> 01:17:33,980 Så hva ønsker jeg å endre innstillingene for? 912 01:17:33,980 --> 01:17:37,370 Jeg ønsker å endre innstillingene for hver gang jeg traff en karakter, 913 01:17:37,370 --> 01:17:41,590 Jeg vil at det skal kaste det tegnet bort i stedet for å skrive den til skjermen. 914 01:17:41,590 --> 01:17:45,960 Hva stream - standard inn, standard ut, eller standard feil - 915 01:17:45,960 --> 01:17:52,050 reagerer på ting når jeg skriver på tastaturet? >> [Student] Standard i. >> Ja. 916 01:17:52,050 --> 01:17:56,450 Så jeg kan enten gjøre 0 eller jeg kan gjøre stdin. 917 01:17:56,450 --> 01:17:59,380 Jeg får current_settings av standard i. 918 01:17:59,380 --> 01:18:01,720 >> Nå ønsker jeg å oppdatere disse innstillingene, 919 01:18:01,720 --> 01:18:07,200 så først skal jeg kopiere inn hacker_settings hva mine current_settings er. 920 01:18:07,200 --> 01:18:10,430 Og hvordan structs arbeid er det bare kopiere. 921 01:18:10,430 --> 01:18:14,510 Dette kopierer alle feltene, som du forventer. 922 01:18:14,510 --> 01:18:17,410 >> Nå ønsker jeg å oppdatere noen av feltene. 923 01:18:17,410 --> 01:18:21,670 Ser på termios, ville du nødt til å lese gjennom mye av dette 924 01:18:21,670 --> 01:18:24,110 bare for å se hva du ønsker å se etter, 925 01:18:24,110 --> 01:18:28,210 men flaggene du kommer til å ønske å se etter er ekko, 926 01:18:28,210 --> 01:18:33,110 så ECHO ECHO inn tegn. 927 01:18:33,110 --> 01:18:37,710 Først vil jeg sette - jeg har allerede glemt hva feltene er. 928 01:18:45,040 --> 01:18:47,900 Dette er hva struct ser ut. 929 01:18:47,900 --> 01:18:51,060 Så inntastingsmoduser jeg tror vi ønsker å endre. 930 01:18:51,060 --> 01:18:54,210 Vi skal se på løsningen for å sikre det er det vi ønsker å endre. 931 01:19:04,060 --> 01:19:12,610 Vi ønsker å endre lflag for å hindre ønsker å se gjennom alle disse. 932 01:19:12,610 --> 01:19:14,670 Vi ønsker å endre lokale moduser. 933 01:19:14,670 --> 01:19:17,710 Du vil måtte lese gjennom hele denne tingen å forstå hvor alt tilhører 934 01:19:17,710 --> 01:19:19,320 at vi ønsker å endre. 935 01:19:19,320 --> 01:19:24,120 Men det er på innsiden av lokale moduser hvor vi kommer til å ønske å endre det. 936 01:19:27,080 --> 01:19:33,110 Så hacker_settings.cc_lmode er hva det heter. 937 01:19:39,630 --> 01:19:43,020 c_lflag. 938 01:19:49,060 --> 01:19:52,280 Det er her vi kommer inn bitvis operatører. 939 01:19:52,280 --> 01:19:54,860 Vi er slags ut av tiden, men vi vil gå gjennom det virkelig rask. 940 01:19:54,860 --> 01:19:56,600 Det er her vi kommer inn bitvis operatører, 941 01:19:56,600 --> 01:19:59,950 hvor jeg tror jeg sa en gang for lenge siden at når du begynner å gjøre med flagg, 942 01:19:59,950 --> 01:20:03,370 du kommer til å bruke bitvis operatør mye. 943 01:20:03,370 --> 01:20:08,240 Hver bit i flagget tilsvarer en slags oppførsel. 944 01:20:08,240 --> 01:20:14,090 Så her har dette flagget en haug med forskjellige ting, hvor alle av dem mener noe annet. 945 01:20:14,090 --> 01:20:18,690 Men det jeg ønsker å gjøre er å slå like ved litt som tilsvarer ECHO. 946 01:20:18,690 --> 01:20:25,440 Så for å slå det av jeg gjør og = ¬ ECHO. 947 01:20:25,440 --> 01:20:30,110 Egentlig tror jeg det er som Techo eller noe. Jeg skal bare sjekke igjen. 948 01:20:30,110 --> 01:20:34,050 Jeg kan termios det. Det er ECHO bare. 949 01:20:34,050 --> 01:20:38,440 ECHO skal være en enkelt bit. 950 01:20:38,440 --> 01:20:44,230 ¬ ECHO kommer til å bety alle biter er satt til 1, som betyr at alle flagg er satt til sann 951 01:20:44,230 --> 01:20:47,140 unntatt for ECHO bit. 952 01:20:47,140 --> 01:20:53,830 Ved å avslutte min lokale flagg med dette, betyr det alle flagg som for øyeblikket satt til sann 953 01:20:53,830 --> 01:20:56,520 vil fortsatt bli satt til true. 954 01:20:56,520 --> 01:21:03,240 Hvis min ECHO flagget er satt til true, så dette er nødvendigvis satt til false på ECHO flagg. 955 01:21:03,240 --> 01:21:07,170 Så denne linjen med kode bare slår av ECHO flagg. 956 01:21:07,170 --> 01:21:16,270 De andre linjer med kode, vil jeg bare kopiere dem av hensyn til tid og deretter forklare dem. 957 01:21:27,810 --> 01:21:30,180 I løsningen, sa han 0. 958 01:21:30,180 --> 01:21:33,880 Det er trolig bedre å eksplisitt si stdin. 959 01:21:33,880 --> 01:21:42,100 >> Legg merke til at jeg også gjør ECHO | icanon her. 960 01:21:42,100 --> 01:21:46,650 Icanon refererer til noe separat, noe som betyr kanoniske modus. 961 01:21:46,650 --> 01:21:50,280 Hva kanoniske modus betyr er vanligvis når du skriver ut kommandolinjen, 962 01:21:50,280 --> 01:21:54,670 standard i ikke behandler noe før du treffer linjeskift. 963 01:21:54,670 --> 01:21:58,230 Så når du GetString, skriver du en haug av ting, så du treffer linjeskift. 964 01:21:58,230 --> 01:22:00,590 Det er da det er sendt til standard i. 965 01:22:00,590 --> 01:22:02,680 Det er standard. 966 01:22:02,680 --> 01:22:05,830 Når jeg slår av kanonisk modus, nå hver enkelt tegn du trykker 967 01:22:05,830 --> 01:22:10,910 er hva som blir behandlet, som vanligvis er slags dårlig fordi den er treg til å behandle disse tingene, 968 01:22:10,910 --> 01:22:14,330 det er derfor det er godt å bufre det inn hele linjer. 969 01:22:14,330 --> 01:22:16,810 Men jeg vil hvert tegn som skal behandles 970 01:22:16,810 --> 01:22:18,810 siden jeg ikke vil at den skal vente på meg til å treffe linjeskift 971 01:22:18,810 --> 01:22:21,280 før den behandler alle tegnene jeg har vært å skrive. 972 01:22:21,280 --> 01:22:24,760 Dette slår av kanoniske modus. 973 01:22:24,760 --> 01:22:31,320 Dette ting betyr bare når det faktisk behandler tegn. 974 01:22:31,320 --> 01:22:35,830 Dette betyr behandle dem umiddelbart, så snart jeg skriver dem, behandle dem. 975 01:22:35,830 --> 01:22:42,510 Og dette er den funksjonen som oppdaterer mine innstillinger for standard i, 976 01:22:42,510 --> 01:22:45,480 og TCSA del gjøre det akkurat nå. 977 01:22:45,480 --> 01:22:50,310 De andre alternativene er vente til alt som er på strømmen er behandlet. 978 01:22:50,310 --> 01:22:52,030 Det spiller ingen rolle. 979 01:22:52,030 --> 01:22:56,920 Akkurat nå endre innstillingene mine for å være det som er for tiden i hacker_typer_settings. 980 01:22:56,920 --> 01:23:02,210 Jeg antar jeg kalte det hacker_settings, så la oss endre det. 981 01:23:09,610 --> 01:23:13,500 Endre alt til hacker_settings. 982 01:23:13,500 --> 01:23:16,870 >> Nå på slutten av vårt program vi kommer til å ønske å gå tilbake 983 01:23:16,870 --> 01:23:20,210 til det som nå er inne i normal_settings, 984 01:23:20,210 --> 01:23:26,560 som kommer til å bare se ut og normal_settings. 985 01:23:26,560 --> 01:23:30,650 Merker jeg har ikke endret noen av mine normal_settings siden opprinnelig å få det. 986 01:23:30,650 --> 01:23:34,520 Deretter å bare endre dem tilbake, passerer jeg dem tilbake på slutten. 987 01:23:34,520 --> 01:23:38,390 Dette var oppdateringen. Okay. 988 01:23:38,390 --> 01:23:43,900 >> Nå inne for her vil jeg bare forklare koden i interesse av tid. 989 01:23:43,900 --> 01:23:46,350 Det er ikke så mye kode. 990 01:23:50,770 --> 01:24:03,750 Vi ser vi leser et tegn fra filen. Vi kalte det f. 991 01:24:03,750 --> 01:24:07,850 Nå kan du mann fgetc, men hvordan fgetc skal fungere 992 01:24:07,850 --> 01:24:11,910 er bare det kommer til å returnere tegnet du bare lese eller EOF, 993 01:24:11,910 --> 01:24:15,680 som svarer til slutten av filen eller noen feil skjer. 994 01:24:15,680 --> 01:24:19,900 Vi er looping, fortsetter å lese en enkelt tegn fra filen, 995 01:24:19,900 --> 01:24:22,420 før vi har kjørt ut av tegn å lese. 996 01:24:22,420 --> 01:24:26,650 Og mens vi gjør det, vi vente på et enkelt tegn fra standard i. 997 01:24:26,650 --> 01:24:29,090 Hver eneste gang du skriver noe på kommandolinjen, 998 01:24:29,090 --> 01:24:32,820 som er å lese i en karakter fra standard i. 999 01:24:32,820 --> 01:24:38,330 Da putchar er bare kommer til å sette char vi leser opp her fra filen til standard ut. 1000 01:24:38,330 --> 01:24:42,890 Du kan mannen putchar, men det er bare å sette til standard ut, det skriver det tegnet. 1001 01:24:42,890 --> 01:24:51,600 Du kan også bare gjøre printf ("% c", c); Samme idé. 1002 01:24:53,330 --> 01:24:56,670 Det kommer til å gjøre mesteparten av arbeidet vårt. 1003 01:24:56,670 --> 01:25:00,300 >> Det siste vi kommer til å ønske å gjøre er bare fclose vår fil. 1004 01:25:00,300 --> 01:25:03,310 Hvis du ikke fclose, det er en minnelekkasje. 1005 01:25:03,310 --> 01:25:06,680 Vi ønsker å fclose filen vi opprinnelig åpnet, og jeg tror det er det. 1006 01:25:06,680 --> 01:25:13,810 Hvis vi gjør det, jeg har allerede fått problemer. 1007 01:25:13,810 --> 01:25:17,260 La oss se. 1008 01:25:17,260 --> 01:25:19,960 Hva gjorde det klage? 1009 01:25:19,960 --> 01:25:30,220 Forventet 'int', men argumentet er av typen 'struct _IO_FILE *'. 1010 01:25:36,850 --> 01:25:39,370 Vi får se om det fungerer. 1011 01:25:45,210 --> 01:25:53,540 Bare tillatt i C99. Augh. Ok, gjør hacker_typer. 1012 01:25:53,540 --> 01:25:57,760 Nå får vi mer nyttige beskrivelser. 1013 01:25:57,760 --> 01:25:59,900 Så bruk av svart identifikator 'normal_settings'. 1014 01:25:59,900 --> 01:26:04,170 Jeg gjorde ikke kalle det normal_settings. Jeg kalte det current_settings. 1015 01:26:04,170 --> 01:26:12,090 Så la oss endre alt dette. 1016 01:26:17,920 --> 01:26:21,710 Nå passerer argument. 1017 01:26:26,290 --> 01:26:29,500 Jeg skal gjøre dette 0 for nå. 1018 01:26:29,500 --> 01:26:36,720 Okay. . / Hacker_typer cp.c. 1019 01:26:36,720 --> 01:26:39,590 Jeg gjorde ikke også tømme skjermen i begynnelsen. 1020 01:26:39,590 --> 01:26:42,960 Men du kan se tilbake til den siste oppgavesettet for å se hvordan du fjerner skjermen. 1021 01:26:42,960 --> 01:26:45,160 Det er bare å skrive ut noen tegn 1022 01:26:45,160 --> 01:26:47,210 mens dette gjør hva jeg vil gjøre. 1023 01:26:47,210 --> 01:26:48,900 Okay. 1024 01:26:48,900 --> 01:26:55,280 Og tenker på hvorfor dette måtte være 0 i stedet for stdin, 1025 01:26:55,280 --> 01:27:00,560 som bør # define 0, 1026 01:27:00,560 --> 01:27:03,890 Dette er klager på at - 1027 01:27:13,150 --> 01:27:19,360 Før når jeg sa at det er fildeskriptorer men så har du også din FIL *, 1028 01:27:19,360 --> 01:27:23,210 en fil descriptor er bare en enkelt heltall, 1029 01:27:23,210 --> 01:27:26,970 mens en fil * har en hel haug med ting knyttet til den. 1030 01:27:26,970 --> 01:27:30,380 Grunnen til at vi trenger å si 0 i stedet for stdin 1031 01:27:30,380 --> 01:27:37,480 er at stdin er en fil * som peker til det som er refererer fil descriptor 0. 1032 01:27:37,480 --> 01:27:45,070 Så selv opp her når jeg gjør fopen (argv [1], jeg får en fil * tilbake. 1033 01:27:45,070 --> 01:27:51,180 Men et sted i denne filen * er en ting som tilsvarer filen descriptor for denne filen. 1034 01:27:51,180 --> 01:27:57,430 Hvis du ser på mannen siden for å åpne, så jeg tror du må gjøre mann 3 open - nope - 1035 01:27:57,430 --> 01:27:59,380 man 2 open - yeah. 1036 01:27:59,380 --> 01:28:06,250 Hvis du ser på siden for å åpne, er åpen som en lavere nivå fopen, 1037 01:28:06,250 --> 01:28:09,350 og den returnerer selve filen descriptor. 1038 01:28:09,350 --> 01:28:12,050 fopen gjør en haug med ting på toppen av åpne, 1039 01:28:12,050 --> 01:28:17,640 som i stedet for å returnere bare den filen descriptor returnerer en hel fil * pekeren 1040 01:28:17,640 --> 01:28:20,590 innsiden av som er vår lille fil descriptor. 1041 01:28:20,590 --> 01:28:25,020 Så standard i refererer til FIL * ting, 1042 01:28:25,020 --> 01:28:29,120 mens 0 refererer til bare filen descriptor standard i seg selv. 1043 01:28:29,120 --> 01:28:32,160 >> Spørsmål? 1044 01:28:32,160 --> 01:28:35,930 [Ler] blåste gjennom det. 1045 01:28:35,930 --> 01:28:39,140 OK. Vi er ferdige. [Ler] 1046 01:28:39,140 --> 01:28:42,000 >> [CS50.TV]