1 00:00:00,000 --> 00:00:02,500 [Powered by Google Translate] [Afsnit 5 - Mere behagelig] 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 sagde i min e-mail, er der en masse ting, du kan bruge 5 00:00:14,250 --> 00:00:17,060 andet end apparatet til rent faktisk at gøre problemet sæt. 6 00:00:17,060 --> 00:00:19,910 Vi anbefaler, at du gør det i maskinen, bare fordi så kan vi lettere hjælpe dig 7 00:00:19,910 --> 00:00:22,070 og vi ved, hvordan alting kommer til at arbejde. 8 00:00:22,070 --> 00:00:26,950 Men som et eksempel på, hvor du kan gøre ting, hvis sige, du ikke har adgang til 9 00:00:26,950 --> 00:00:31,570 til et apparat eller du ønsker at arbejde i Science Center kælderen - 10 00:00:31,570 --> 00:00:33,090 som de faktisk har apparatet også - 11 00:00:33,090 --> 00:00:35,150 hvis du ønsker at arbejde hvor som helst. 12 00:00:35,150 --> 00:00:42,370 Et eksempel er har du set / hørt af SSH? 13 00:00:44,380 --> 00:00:47,780 SSH er dybest set ligesom forbinde til noget. 14 00:00:47,780 --> 00:00:51,340 Faktisk lige nu er jeg SSHed ind i apparatet. 15 00:00:51,340 --> 00:00:54,290 Jeg har aldrig arbejde direkte i apparatet. 16 00:00:55,930 --> 00:01:01,060 Her er apparatet, og hvis du kigger ned her kan du se denne IP-adresse. 17 00:01:01,060 --> 00:01:03,650 Jeg har aldrig arbejdet i selve apparatet; 18 00:01:03,650 --> 00:01:08,840 Jeg kommer altid hen til en iTerm2 vindue / terminalvindue. 19 00:01:08,840 --> 00:01:15,910 Du kan SSH til at IP-adressen, ssh jharvard@192.168.129.128. 20 00:01:15,910 --> 00:01:20,390 Jeg husker, at antallet meget nemt, fordi det er sådan en nice mønster. 21 00:01:20,390 --> 00:01:24,920 Men det vil spørge mig om min adgangskode, og nu er jeg i apparatet. 22 00:01:24,920 --> 00:01:33,060 Dybest set, på dette tidspunkt, hvis du har åbnet en terminal inde i selve apparatet, 23 00:01:33,060 --> 00:01:36,350 dette interface, men du ville bruge det, er nøjagtig det samme 24 00:01:36,350 --> 00:01:40,010 som grænsefladen jeg bruger herovre, men nu er du SSHed. 25 00:01:42,240 --> 00:01:44,920 Du behøver ikke at SSH til apparatet. 26 00:01:44,920 --> 00:01:52,360 Et eksempel på et andet sted du kunne SSH til, er jeg temmelig sikker på at du har som standard - 27 00:01:52,360 --> 00:01:55,020 Oh. Bigger. 28 00:01:55,020 --> 00:02:01,130 Alle jer burde have som standard FAS konti på de ansvarlige for bedriftsrådgivningsordningen servere. 29 00:02:01,130 --> 00:02:06,840 For mig, ville jeg SSH til rbowden@nice.fas.harvard.edu. 30 00:02:06,840 --> 00:02:11,610 Det kommer til at bede dig om, at den første gang, og du siger ja. 31 00:02:11,610 --> 00:02:15,840 Min adgangskode er bare at være min FAS password. 32 00:02:15,840 --> 00:02:22,650 Og så nu, jeg SSHed til nice servere, og jeg kan gøre noget, jeg vil have på her. 33 00:02:22,650 --> 00:02:28,560 En masse af klasser du kan tage, ligesom 124, vil have dig uploade ting til her 34 00:02:28,560 --> 00:02:30,950 til rent faktisk at indsende dit problem sæt. 35 00:02:30,950 --> 00:02:34,100 Men siger du ikke har adgang til dit apparat. 36 00:02:34,100 --> 00:02:37,910 Så kan du gøre ting, som på her det vil sige - 37 00:02:37,910 --> 00:02:42,160 Dette er blot vores afsnit med spørgsmål. 38 00:02:42,160 --> 00:02:45,070 Den vil bede dig om at gøre dette i apparatet. 39 00:02:45,070 --> 00:02:47,790 I stedet vil jeg bare gøre det på serveren. 40 00:02:47,790 --> 00:02:50,560 Jeg har tænkt mig at lyne det. 41 00:02:50,560 --> 00:02:55,670 Problemet vil være, at du er vant til at bruge noget som gedit 42 00:02:55,670 --> 00:02:58,160 eller hvad indersiden af ​​apparatet. 43 00:02:58,160 --> 00:03:01,830 Du kommer ikke til at have den på FAS-serveren. 44 00:03:01,830 --> 00:03:04,110 Det hele er bare at være denne tekst interface. 45 00:03:04,110 --> 00:03:09,180 Så du kan enten en, så prøv at 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 normalt ret nemt at bruge. 48 00:03:14,990 --> 00:03:19,470 Du kan bruge dine pile og skrive normalt. 49 00:03:19,470 --> 00:03:21,250 Så det er ikke svært. 50 00:03:21,250 --> 00:03:24,720 Hvis du ønsker at få virkelig fancy, kan du bruge Emacs, 51 00:03:24,720 --> 00:03:29,850 som jeg burde nok ikke have åbnet, da jeg ikke engang ved, hvordan man lukke Emacs. 52 00:03:29,850 --> 00:03:32,760 Kontrol X, Control C? Yeah. 53 00:03:32,760 --> 00:03:35,310 Eller du kan bruge Vim, hvilket er hvad jeg bruger. 54 00:03:35,310 --> 00:03:37,800 Og så dem er dine muligheder. 55 00:03:37,800 --> 00:03:43,830 Hvis du ikke ønsker at gøre det, kan du også, hvis man 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 bruger PuTTY, 58 00:03:49,920 --> 00:03:51,940 som du bliver nødt til at hente separat. 59 00:03:51,940 --> 00:03:55,460 På en Mac, kan du bare som standard bruge Terminal eller du kan downloade iTerm2, 60 00:03:55,460 --> 00:03:58,490 der er som et rart, fancy Terminal. 61 00:03:58,490 --> 00:04:03,780 Hvis du går til manual.cs50.net kan du se et link til Notepad + +, 62 00:04:03,780 --> 00:04:07,120 hvilket er hvad du kan bruge på en pc. 63 00:04:07,120 --> 00:04:13,340 Det giver dig mulighed SFTP fra Notepad + +, som er dybest set SSH. 64 00:04:13,340 --> 00:04:17,750 Hvad dette vil lade dig gøre, er at redigere dine filer lokalt, 65 00:04:17,750 --> 00:04:20,670 og derefter når du ønsker at gemme dem, vil det spare på nice.fas, 66 00:04:20,670 --> 00:04:23,670 hvor du kan derefter køre dem. 67 00:04:23,670 --> 00:04:26,880 Og tilsvarende på en Mac bliver TextWrangler. 68 00:04:26,880 --> 00:04:28,760 Så det lader dig gøre det samme. 69 00:04:28,760 --> 00:04:32,800 Det lader dig redigere filer lokalt og gemme dem til nice.fas, 70 00:04:32,800 --> 00:04:35,730 hvor du kan derefter køre dem. 71 00:04:35,730 --> 00:04:40,400 Så hvis du nogensinde sidder fast uden et apparat, har du disse muligheder 72 00:04:40,400 --> 00:04:44,230 til stadig gøre dit problem sæt. 73 00:04:44,230 --> 00:04:48,250 Det ene problem vil være, at du ikke vil have den CS50 bibliotek 74 00:04:48,250 --> 00:04:51,580 fordi nice.fas ikke som standard have det. 75 00:04:51,580 --> 00:04:55,970 Du kan enten downloade den CS50 bibliotek - 76 00:04:55,970 --> 00:04:58,470 Jeg tror ikke jeg har brug for, at der på dette punkt. 77 00:04:58,470 --> 00:05:03,270 Du kan enten downloade den CS50 biblioteket og kopiere den over til nice.fas, 78 00:05:03,270 --> 00:05:07,450 eller jeg tror på dette punkt har vi ikke bruge det længere alligevel. 79 00:05:07,450 --> 00:05:12,720 Eller hvis vi gør det, kan du for øjeblikket, erstatte det med 80 00:05:12,720 --> 00:05:18,480 de implementeringer af funktionerne i CS50 biblioteket alligevel. 81 00:05:18,480 --> 00:05:21,370 Så det burde ikke være så meget af en begrænsning. 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å tilbage til apparatet nu, vi vil gøre alt i apparatet. 84 00:05:29,820 --> 00:05:37,510 Ser man på vores afsnit med spørgsmål i begyndelsen, ligesom jeg sagde i min e-mail, 85 00:05:37,510 --> 00:05:43,620 vi er nødt til at tale om en kort du skulle se. 86 00:05:43,620 --> 00:05:51,980 Vi har omdirigere & Rør og disse tre spørgsmål. 87 00:05:51,980 --> 00:05:56,070 >> Til hvilken stream gør funktioner som printf skrive som standard? 88 00:05:56,070 --> 00:05:59,130 Så stream. Hvad er en strøm? 89 00:06:06,520 --> 00:06:15,100 En strøm er dybest set ligesom det er bare nogle - 90 00:06:15,100 --> 00:06:21,450 Det er ikke engang en kilde til 1s og 0'erne. 91 00:06:21,450 --> 00:06:24,920 Strømmen det er at bede om her er standard ud. 92 00:06:24,920 --> 00:06:27,250 Og så standard ud er en strøm, at når du skriver til det, 93 00:06:27,250 --> 00:06:30,940 det vises på skærmen. 94 00:06:30,940 --> 00:06:36,860 Standard ud, ved åen, betyder det du bare skrive 1s og 0'erne til det, 95 00:06:36,860 --> 00:06:40,220 og den anden ende af standard ud bare læser fra denne stream. 96 00:06:40,220 --> 00:06:43,540 Det er bare en perlerække af 1s og 0'erne. 97 00:06:43,540 --> 00:06:45,570 Du kan skrive til streams, eller du kan læse fra vandløb 98 00:06:45,570 --> 00:06:47,950 afhængigt af hvad strømmen faktisk er. 99 00:06:47,950 --> 00:06:52,800 De to andre standard strømme er standard i og standard fejl. 100 00:06:52,800 --> 00:06:57,540 Standard i er, når du gør GetString, det venter på at input stuff. 101 00:06:57,540 --> 00:07:01,570 Så det venter på dig, er det faktisk venter på standard ind, 102 00:07:01,570 --> 00:07:04,880 som er virkelig, hvad du får, når du skriver på tastaturet. 103 00:07:04,880 --> 00:07:07,530 Du skriver i standard i. 104 00:07:07,530 --> 00:07:10,050 Standardfejl svarer grundlæggende til standard ud, 105 00:07:10,050 --> 00:07:13,280 men det er specialiseret i at når du udskriver til standard fejl, 106 00:07:13,280 --> 00:07:16,770 du skulle kun udskrive fejlmeddelelser til at 107 00:07:16,770 --> 00:07:20,200 så du kan skelne mellem almindelige meddelelser udskrives til skærmen 108 00:07:20,200 --> 00:07:24,560 versus fejlmeddelelser, afhængigt af, om de gik til standard ud eller standard fejl. 109 00:07:24,560 --> 00:07:28,660 Filer også. 110 00:07:28,660 --> 00:07:32,440 Standard ud, standard i, og standard error er blot særlige streams, 111 00:07:32,440 --> 00:07:36,810 men virkelig enhver fil, når du åbner en fil, bliver den en strøm af bytes 112 00:07:36,810 --> 00:07:40,740 hvor du kan bare læse fra denne stream. 113 00:07:40,740 --> 00:07:47,770 Du, for det meste, kan bare tænke på en fil som en strøm af bytes. 114 00:07:47,770 --> 00:07:51,190 Så hvad vandløb skal de skrive til som standard? Standard ud. 115 00:07:51,190 --> 00:07:56,980 >> Hvad er forskellen mellem> og >>? 116 00:07:58,140 --> 00:08:03,710 Har nogen se videoen på forhånd? Okay. 117 00:08:03,710 --> 00:08:10,960 > Vil være, hvordan du omdirigerer til filer, 118 00:08:10,960 --> 00:08:15,240 og >> også vil omdirigere output til filer, 119 00:08:15,240 --> 00:08:17,820 men det er i stedet kommer til at tilføje til filen. 120 00:08:17,820 --> 00:08:23,430 For eksempel sige, lad os jeg tilfældigvis har dict lige her, 121 00:08:23,430 --> 00:08:27,020 og den eneste ting indersiden af ​​dict er kat, kat, hund, fisk, hund. 122 00:08:27,020 --> 00:08:31,530 En kommando, som du har på kommandolinjen er kat, 123 00:08:31,530 --> 00:08:34,539 der er bare at udskrive hvad der er i en fil. 124 00:08:34,539 --> 00:08:40,679 Så når jeg siger kat dict, går det at udskrive kat, kat, hund, fisk, hund. Det er alt kat gør. 125 00:08:40,679 --> 00:08:46,280 Det betyder, at det trykte til standard ud kat, kat, hund, fisk, hund. 126 00:08:46,280 --> 00:08:53,240 Hvis jeg i stedet ønsker at omdirigere det til en fil, kan jeg bruge> og kanalisere den til, hvad filen er. 127 00:08:53,240 --> 00:08:56,460 Jeg ringer filen fil. 128 00:08:56,460 --> 00:09:00,320 Så nu hvis jeg ls, vil jeg se, at jeg har en ny fil kaldet fil. 129 00:09:00,320 --> 00:09:05,700 Og hvis jeg åbner det op, det kommer til at have præcis, hvad kat sat på kommandolinjen. 130 00:09:05,700 --> 00:09:11,040 Så nu hvis jeg gør det igen, så det kommer til at omdirigere outputtet i filen, 131 00:09:11,040 --> 00:09:13,930 og jeg har tænkt mig at have nøjagtig de samme ting. 132 00:09:13,930 --> 00:09:17,910 Så teknisk set er det helt tilsidesatte hvad vi havde. 133 00:09:17,910 --> 00:09:22,970 Og vi vil se, om jeg skifter dict, jeg tog ud hund. 134 00:09:22,970 --> 00:09:29,980 Nu, hvis vi kat dict i filen igen, vi vil have den nye version med hund fjernet. 135 00:09:29,980 --> 00:09:32,400 Så det fuldstændigt tilsidesætter den. 136 00:09:32,400 --> 00:09:36,640 I stedet, hvis vi bruger >>, går det at tilføje fil. 137 00:09:36,640 --> 00:09:40,860 Nu åbner en fil, vi se, vi har bare det samme udskrives to gange 138 00:09:40,860 --> 00:09:44,920 fordi det var der én gang, så vi vedlagt originalen. 139 00:09:44,920 --> 00:09:48,130 Så det er hvad> og >> gør. 140 00:09:48,130 --> 00:09:50,580 Er den næste spørge - Det spørger ikke om det. 141 00:09:50,580 --> 00:09:59,050 >> Den anden, som vi har, er <, som hvis> omdirigerer standard ud, 142 00:09:59,050 --> 00:10:01,970 00:10:12,050 Lad os se, om vi har et eksempel. 144 00:10:14,750 --> 00:10:16,930 Jeg kan skrive en virkelig hurtig. 145 00:10:17,870 --> 00:10:25,700 Lad os tage en fil, hello.c. 146 00:10:56,060 --> 00:10:59,070 Relativt enkel fil. 147 00:10:59,070 --> 00:11:03,570 Jeg er bare at få en snor og derefter udskrive "Hello" uanset hvilken streng jeg lige har indtastet var. 148 00:11:03,570 --> 00:11:07,990 Så gør goddag og derefter. / Hej. 149 00:11:07,990 --> 00:11:10,720 Nu er det at spørge mig om at indtaste noget, 150 00:11:10,720 --> 00:11:15,070 hvilket betyder, at det venter på ting, der skal opføres i standard i. 151 00:11:15,070 --> 00:11:20,450 Så skrive hvad jeg vil ind i standard i. Vi bare vil sige Hej, Rob! 152 00:11:20,450 --> 00:11:23,310 Så er det der udskrives til standard ud Hello, Rob! 153 00:11:23,310 --> 00:11:28,860 Hvis jeg gør. / Goddag og derefter omdirigere, 154 00:11:30,740 --> 00:11:34,310 for nu kan du kun omdirigere fra en fil. 155 00:11:34,310 --> 00:11:41,720 Så hvis jeg sætte nogle fil, txt, og jeg satte Rob, 156 00:11:41,720 --> 00:11:52,300 hvis jeg løber goddag og derefter omdirigere filen txt ind. / hej, det vil sige Hej, Rob! øjeblikkeligt. 157 00:11:52,300 --> 00:11:57,160 Når det først bliver til GetString og det venter på standard ind, 158 00:11:57,160 --> 00:12:01,730 standard i er ikke længere at vente på tastaturet for data at blive indtastet. 159 00:12:01,730 --> 00:12:05,980 I stedet har vi omdirigeret standard i at læse fra filen txt. 160 00:12:05,980 --> 00:12:10,290 Og så det kommer til at læse fra filen txt, som er lige linien Rob, 161 00:12:10,290 --> 00:12:13,380 og så det kommer til at udskrive Hej, Rob! 162 00:12:13,380 --> 00:12:18,180 Og hvis jeg ville, kunne jeg også gøre. / Hej 00:12:21,500 og så den standard ud, at det er udskrivning, som er Hej, Rob!, 164 00:12:21,500 --> 00:12:24,700 Jeg kan omdirigere det til sin egen fil. 165 00:12:24,700 --> 00:12:29,790 Jeg vil bare kalde filen hallo - nej, jeg vil ikke, fordi det er den eksekverbare - txt2. 166 00:12:29,790 --> 00:12:40,150 Nu er txt2 vil have outputtet af. / Hej 00:12:43,520 >> Spørgsmål? 168 00:12:45,900 --> 00:12:49,090 >> Okay. Så her har vi pipeline. 169 00:12:49,090 --> 00:12:53,510 Pipes er den sidste enhed af omdirigering. 170 00:12:53,510 --> 00:12:58,750 >> Oh. Jeg gætter yderligere en omdirigering er, hvis i stedet for> du gør 2>, 171 00:12:58,750 --> 00:13:01,070 der er omdirigere standardfejl. 172 00:13:01,070 --> 00:13:06,280 Så hvis noget gik til standard fejl, ville det ikke blive sat i txt2. 173 00:13:06,280 --> 00:13:12,480 Men bemærk hvis jeg gør 2>, så er det stadig udskrive Hej, Rob! til kommandolinjen 174 00:13:12,480 --> 00:13:18,600 fordi jeg kun omdirigere standardfejl, jeg ikke omdirigere standard ud. 175 00:13:18,600 --> 00:13:22,210 Standardfejl og standard ud er forskellige. 176 00:13:24,210 --> 00:13:27,080 Hvis du ville faktisk skrive til standard fejl, 177 00:13:27,080 --> 00:13:35,080 så jeg kunne ændre dette for at være fprintf til stderr. 178 00:13:35,080 --> 00:13:37,850 Så printf, som standard, udskriver til standard ud. 179 00:13:37,850 --> 00:13:41,720 Hvis jeg ønsker at udskrive til standard fejl manuelt, så jeg er nødt til at bruge fprintf 180 00:13:41,720 --> 00:13:45,010 og angive, hvad jeg vil udskrive til. 181 00:13:45,010 --> 00:13:49,720 Hvis man i stedet gjorde jeg fprintf stdout, så det er dybest set svarer til printf. 182 00:13:49,720 --> 00:13:55,530 Men fprintf til standard fejl. 183 00:13:57,790 --> 00:14:03,650 Så nu, hvis jeg kanalisere denne ind i txt2, Hej, Rob! stadig få trykt på kommandolinjen 184 00:14:03,650 --> 00:14:08,270 da det bliver udskrevet til standard fejl, og jeg er kun omdirigere standard ud. 185 00:14:08,270 --> 00:14:16,420 Hvis jeg nu omdirigere standard fejl, nu det ikke bliver udskrevet, og txt2 bliver Hej, Rob! 186 00:14:16,420 --> 00:14:21,910 Så nu kan du printe dine egentlige fejl til standard fejl 187 00:14:21,910 --> 00:14:24,720 og printe dine almindelige meddelelser til standard ud. 188 00:14:24,720 --> 00:14:31,420 Og så når du kører dit program, kan du køre det som. / Hej denne type med 2> 189 00:14:31,420 --> 00:14:33,800 så din program kommer til at køre normalt, 190 00:14:33,800 --> 00:14:38,400 men eventuelle fejlmeddelelser, du får, kan du tjekke senere i din fejllog, 191 00:14:38,400 --> 00:14:44,500 så fejl, og derefter se senere, og din fejl fil vil have eventuelle fejl, der skete. 192 00:14:45,200 --> 00:14:47,540 >> Spørgsmål? 193 00:14:47,540 --> 00:14:58,070 >> Den sidste er rør, som du kan tænke på som at tage standarden ud fra en kommando 194 00:14:58,070 --> 00:15:01,210 og derfor er dette det standard i den næste kommando. 195 00:15:01,210 --> 00:15:05,570 Et eksempel her er echo er en kommandolinje ting 196 00:15:05,570 --> 00:15:11,840 der er bare at gentage, hvad jeg sætter som sit argument. Jeg vil ikke sætte anførselstegn. 197 00:15:11,840 --> 00:15:16,150 Echo blah, blah, blah er bare at udskrive blah, blah, blah. 198 00:15:16,150 --> 00:15:20,600 Før, da jeg sagde, at jeg var nødt til at sætte Rob ind i en txt-fil 199 00:15:20,600 --> 00:15:28,830 fordi jeg kun kan omdirigere txt-filer i stedet, / hvis jeg gentager Rob 200 00:15:28,830 --> 00:15:35,520 og derefter rør det til. / hej, vil det også gøre det samme slags ting. 201 00:15:35,520 --> 00:15:39,160 Dette tager outputtet fra denne kommando, echo Rob, 202 00:15:39,160 --> 00:15:43,610 og bruge det som input til. / hej. 203 00:15:44,790 --> 00:15:49,560 Du kan tænke på det som første omdirigering echo Rob ind i en fil 204 00:15:49,560 --> 00:15:54,160 og derefter input til. / hej denne fil, der lige er udsendt. 205 00:15:54,160 --> 00:15:57,850 Men det tager den midlertidige fil ud af billedet. 206 00:16:01,890 --> 00:16:04,460 >> Spørgsmål om det? 207 00:16:04,460 --> 00:16:07,150 >> Det næste spørgsmål kommer til at involvere dette. 208 00:16:07,150 --> 00:16:15,310 Hvad rørledningen kunne du bruge til at finde antallet af unikke navne i en fil kaldet names.txt? 209 00:16:15,310 --> 00:16:24,160 Kommandoerne vi kommer til at ønsker at bruge her er unikke, så uniq, og derefter wc. 210 00:16:24,160 --> 00:16:28,840 Du kan gøre mennesket uniq til rent faktisk at se på, hvad der gør, 211 00:16:28,840 --> 00:16:34,840 og det er bare at filtrere tilstødende matchende linjer fra indgangen. 212 00:16:34,840 --> 00:16:40,690 Og mennesket wc kommer til at udskrive ny linje, ord og byte for hver fil. 213 00:16:40,690 --> 00:16:43,760 Og det sidste, vi vil ønsker at bruge er sortering, 214 00:16:43,760 --> 00:16:47,410 som vil bare sortere linjer af txt-fil. 215 00:16:47,410 --> 00:16:58,080 Hvis jeg gør nogle txt-fil, names.txt, og det er Rob, Tommy, Joseph, Tommy, Joseph, RJ, Rob, 216 00:16:58,080 --> 00:17:03,910 hvad jeg ønsker at gøre her, er at finde antallet af unikke navne i denne fil. 217 00:17:03,910 --> 00:17:08,750 Så hvad bør svaret være? >> [Studerende] 4. >> Yeah. 218 00:17:08,750 --> 00:17:13,780 Det bør være 4 siden Rob, Tommy, Joseph, RJ er de eneste entydige navne i denne fil. 219 00:17:13,780 --> 00:17:20,180 Det første skridt, hvis jeg bare ord tæller på names.txt, 220 00:17:20,180 --> 00:17:24,290 dette er faktisk fortæller mig alt. 221 00:17:24,290 --> 00:17:32,560 Dette er faktisk udskrivning - lad os se, mand wc - newlines, ord og byte tæller. 222 00:17:32,560 --> 00:17:38,270 Hvis jeg kun bekymre sig om linjer, så jeg kan bare gøre wc-l names.txt. 223 00:17:41,730 --> 00:17:44,300 Så det er trin 1. 224 00:17:44,300 --> 00:17:50,510 Men jeg ønsker ikke at wc-l names.txt fordi names.txt bare indeholder alle de navne, 225 00:17:50,510 --> 00:17:54,170 og jeg ønsker at filtrere alle ikke-unikke dem. 226 00:17:54,170 --> 00:18:01,200 Så hvis jeg gør uniq names.txt, betyder det ikke helt give mig, hvad jeg vil 227 00:18:01,200 --> 00:18:03,760 fordi de duplikerede navne er der stadig. 228 00:18:03,760 --> 00:18:07,690 Hvorfor er det? Hvorfor er uniq ikke gør, hvad jeg vil? 229 00:18:07,690 --> 00:18:10,500 [Studerende] Den gentagede ikke [uhørlige] >> Yeah. 230 00:18:10,500 --> 00:18:16,370 Husk manden side for uniq siger filter tilstødende matchende linjer. 231 00:18:16,370 --> 00:18:19,680 De er ikke tilstødende, så det vil ikke filtrere dem. 232 00:18:19,680 --> 00:18:31,100 Hvis jeg sortere dem først, sort names.txt vil sætte alle de dublerede linjer sammen. 233 00:18:31,100 --> 00:18:34,450 Så nu sortere names.txt er det. 234 00:18:34,450 --> 00:18:40,550 Jeg har tænkt mig at ønsker at bruge det som input til uniq, der er | uniq. 235 00:18:40,550 --> 00:18:43,390 Det giver mig Joseph, RJ, Rob, Tommy, 236 00:18:43,390 --> 00:18:49,260 og jeg vil gerne bruge det som input til wc-l, 237 00:18:49,260 --> 00:18:52,740 som vil give mig 4. 238 00:18:52,740 --> 00:18:56,930 Ligesom der står her, hvad kunne pipeline du bruge? 239 00:18:56,930 --> 00:19:01,390 Du kan gøre en masse ting som at bruge en række kommandoer 240 00:19:01,390 --> 00:19:05,130 hvor du bruger output fra en kommando som input til den næste kommando. 241 00:19:05,130 --> 00:19:08,780 Du kan gøre en masse ting, en masse smarte ting. 242 00:19:08,780 --> 00:19:11,440 >> Spørgsmå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 >> Nu skal vi gå videre til den faktiske ting, den kodende ting. 246 00:19:24,090 --> 00:19:29,100 Inde i denne PDF, vil du se denne kommando, 247 00:19:29,100 --> 00:19:32,950 og du vil få lyst til at køre denne kommando i dit apparat. 248 00:19:36,240 --> 00:19:42,250 wget er kommandoen for bare at få noget fra internettet, dybest set, 249 00:19:42,250 --> 00:19:45,180 så wget og denne webadresse. 250 00:19:45,180 --> 00:19:49,110 Hvis du gik til denne URL i din browser, vil den downloade denne fil. 251 00:19:49,110 --> 00:19:52,510 Jeg har lige klikket på den, så den hentede fil for mig. 252 00:19:52,510 --> 00:19:55,650 Men skrivning wget af den ting inde i terminalen 253 00:19:55,650 --> 00:19:58,620 er bare at hente det ind i din terminal. 254 00:19:58,620 --> 00:20:02,750 Jeg har section5.zip, og du vil få lyst til at lyne section5.zip, 255 00:20:02,750 --> 00:20:06,520 som vil give dig en mappe kaldet section5, 256 00:20:06,520 --> 00:20:11,550 som vil have alle de filer, vi kommer til at bruge i dag inde i den. 257 00:20:33,380 --> 00:20:37,710 Da disse programmers filnavne antyder, de er en smule buggy, 258 00:20:37,710 --> 00:20:40,990 så din mission er at finde ud af hvorfor bruger gdb. 259 00:20:40,990 --> 00:20:44,560 Skal alle dem downloades / ved hvordan man får dem downloadet 260 00:20:44,560 --> 00:20:47,480 i deres apparat? Okay. 261 00:20:47,480 --> 00:20:56,400 >> Løb ./buggy1 vil det sige Segmentation fault (core dumpet), 262 00:20:56,400 --> 00:21:00,500 som helst du får en segfault, det er en dårlig ting. 263 00:21:00,500 --> 00:21:03,810 Under hvilke omstændigheder får du en segfault? 264 00:21:03,810 --> 00:21:08,210 [Studerende] dereference en null-pointer. >> Yeah. Så er et eksempel. 265 00:21:08,210 --> 00:21:11,580 Dereferere en null-pointer du kommer til at få en segfault. 266 00:21:11,580 --> 00:21:16,720 Hvad en segfault betyder, at du rører hukommelse, bør du ikke røre. 267 00:21:16,720 --> 00:21:21,350 Så dereferere en null-pointer rører adresse 0, 268 00:21:21,350 --> 00:21:28,060 og dybest set, alle computere i dag sige, at adressen 0 er hukommelse, bør du ikke røre. 269 00:21:28,060 --> 00:21:31,920 Så det er derfor dereferere en null-pointer resulterer i en segfault. 270 00:21:31,920 --> 00:21:37,210 Når du tilfældigvis ikke initialisere en pegepind, så det har en garbage værdi, 271 00:21:37,210 --> 00:21:41,520 og så når du forsøger at dereference det, efter al sandsynlighed, du rører hukommelse 272 00:21:41,520 --> 00:21:43,540 det er midt i himlen. 273 00:21:43,540 --> 00:21:45,650 Hvis du tilfældigvis til at få heldige og garbage værdi 274 00:21:45,650 --> 00:21:48,440 sket til at pege på et sted på stakken eller noget, 275 00:21:48,440 --> 00:21:50,820 så når du dereference at pointer, som du ikke har initialiseret, 276 00:21:50,820 --> 00:21:52,730 intet vil gå galt. 277 00:21:52,730 --> 00:21:55,480 Men hvis det er at pege på, siger, et sted mellem stakken og bunke, 278 00:21:55,480 --> 00:21:59,850 eller det peger bare til et sted, der ikke er blevet brugt af dit program endnu, 279 00:21:59,850 --> 00:22:02,240 så er du rører hukommelse du skal ikke røre, og du segfault. 280 00:22:02,240 --> 00:22:06,370 Når du skriver en rekursiv funktion, og det recurses for mange gange 281 00:22:06,370 --> 00:22:08,720 og din stack bliver for stor, og de stak kolliderer ind i ting 282 00:22:08,720 --> 00:22:12,270 at det ikke bør kolliderede med, er du rører hukommelse du ikke bør røre, 283 00:22:12,270 --> 00:22:14,810 så du segfault. 284 00:22:14,810 --> 00:22:17,010 Det er, hvad en segfault er. 285 00:22:17,010 --> 00:22:21,810 >> Det er også af samme grund, at hvis du har en streng som - 286 00:22:21,810 --> 00:22:23,930 lad os gå tilbage til det forrige program. 287 00:22:23,930 --> 00:22:28,530 I hello.c--Jeg er bare at lave noget andet. 288 00:22:28,530 --> 00:22:33,770 char * s = "Hej Verden!" 289 00:22:33,770 --> 00:22:42,310 Hvis jeg bruger * s = noget eller s [0] = 'X'; 290 00:22:42,310 --> 00:22:47,290 så gør goddag. / hej, hvorfor det segfault? 291 00:22:48,410 --> 00:22:51,250 Hvorfor dette segfault? 292 00:22:55,660 --> 00:22:57,890 Hvad ville du forvente at ske? 293 00:22:57,890 --> 00:23:06,640 Hvis jeg gjorde printf ("% s \ n", s), hvad ville du forvente at blive udskrevet? 294 00:23:06,640 --> 00:23:09,930 [Studerende] X hej. >> Yeah. 295 00:23:09,930 --> 00:23:15,140 Problemet er, at når du erklærer en streng som denne, 296 00:23:15,140 --> 00:23:18,190 s er en pointer, der kommer til at gå på stakken, 297 00:23:18,190 --> 00:23:25,880 og hvad s peger på, er denne streng, som er indeholdt i læselageret. 298 00:23:25,880 --> 00:23:30,560 Så bare ved navn, read-only memory, bør du få den idé 299 00:23:30,560 --> 00:23:33,010 at hvis du forsøger at ændre hvad der er i read-only memory, 300 00:23:33,010 --> 00:23:36,670 du laver noget, du ikke bør gøre med hukommelse, og du segfault. 301 00:23:36,670 --> 00:23:45,360 Dette er faktisk en stor forskel mellem char * s og char s []. 302 00:23:45,360 --> 00:23:48,790 Så char s [], nu denne streng vil blive lagt på stakken, 303 00:23:48,790 --> 00:23:53,960 og stakken er ikke skrivebeskyttet, hvilket betyder, at dette bør arbejde helt fint. 304 00:23:55,500 --> 00:23:57,370 Og det gør det. 305 00:23:57,370 --> 00:24:06,250 Husk, at når jeg gør char * s = "Hej Verden!", S selv er på stakken 306 00:24:06,250 --> 00:24:10,390 men s peger på et andet sted, og at et andet sker for at være skrivebeskyttet. 307 00:24:10,390 --> 00:24:15,640 Men char s [] er bare noget på stakken. 308 00:24:17,560 --> 00:24:21,760 Så det er et andet eksempel på en segfault sker. 309 00:24:21,760 --> 00:24:27,820 >> Vi så, at ./buggy1 resulterede i en segfault. 310 00:24:27,820 --> 00:24:31,810 I teorien bør du ikke se på buggy1.c straks. 311 00:24:31,810 --> 00:24:35,170 I stedet vil vi se på det gennem gdb. 312 00:24:35,170 --> 00:24:37,750 Bemærk, at når du får Segmentation fault (core dumpet), 313 00:24:37,750 --> 00:24:40,850 du får denne fil herovre kaldet kerne. 314 00:24:40,850 --> 00:24:45,200 Hvis vi ls-l, vil vi se, at kernen er normalt en temmelig stor fil. 315 00:24:45,200 --> 00:24:51,580 Dette er antallet af bytes af filen, så det ser ud som det er 250-noget kilobytes. 316 00:24:51,580 --> 00:24:56,120 Grunden til dette er, at det, kernen dump faktisk er 317 00:24:56,120 --> 00:25:01,410 er, når dit program går ned, status for hukommelse af dit program 318 00:25:01,410 --> 00:25:05,230 bare bliver kopieret og indsat i denne fil. 319 00:25:05,230 --> 00:25:07,270 Det bliver dumpet i den pågældende fil. 320 00:25:07,270 --> 00:25:13,060 Dette program, mens den kørte, tilfældigvis har en hukommelse på omkring 250 kilobyte, 321 00:25:13,060 --> 00:25:17,040 og så det er hvad fik dumpet ind i denne fil. 322 00:25:17,040 --> 00:25:23,630 Nu kan du se på denne fil, hvis vi gør GDB buggy1 kerne. 323 00:25:23,630 --> 00:25:30,130 Vi kan bare gøre gdb buggy1, og det vil bare starte gdb regelmæssigt, 324 00:25:30,130 --> 00:25:33,800 hjælp buggy1 som sit input fil. 325 00:25:33,800 --> 00:25:38,260 Men hvis du gør gdb buggy1 kerne, så er det specifikt kommer til at starte op gdb 326 00:25:38,260 --> 00:25:40,330 ved at se på det centrale fil. 327 00:25:40,330 --> 00:25:45,560 Og du siger buggy1 betyder gdb ved, at denne kerne fil kommer fra buggy1 program. 328 00:25:45,560 --> 00:25:49,580 Så gdb buggy1 kerne vil straks bringe os 329 00:25:49,580 --> 00:25:52,060 til hvor programmet skete for at afslutte. 330 00:25:57,720 --> 00:26:02,340 Vi ser her Program afsluttet med signal 11, Segmentation fault. 331 00:26:02,340 --> 00:26:10,110 Vi tilfældigvis til at se en linje forsamlingsfrihed, og som sandsynligvis er ikke meget nyttigt. 332 00:26:10,110 --> 00:26:15,360 Men hvis du skriver bt eller backtrace, er der vil være den funktion 333 00:26:15,360 --> 00:26:19,430 det giver os en liste over vores nuværende stakrammer. 334 00:26:19,430 --> 00:26:23,150 Så backtrace. Det ser ud til at vi kun har to stakrammer. 335 00:26:23,150 --> 00:26:26,310 Den første er vores vigtigste stakramme, 336 00:26:26,310 --> 00:26:29,810 og den anden er den stakramme for denne funktion, at vi tilfældigvis er i, 337 00:26:29,810 --> 00:26:34,440 som ligner vi kun har forsamlingen kode til. 338 00:26:34,440 --> 00:26:38,050 Så lad os gå tilbage til vores vigtigste funktion, 339 00:26:38,050 --> 00:26:42,300 og for at gøre, at vi kan gøre ramme 1, og jeg tror, ​​vi kan også gøre ned, 340 00:26:42,300 --> 00:26:45,160 men jeg næsten aldrig gøre ned - eller op. Yeah. 341 00:26:45,160 --> 00:26:50,710 Op og ned. Up bringer dig op en stakramme, ned bringer dig ned en stak ramme. 342 00:26:50,710 --> 00:26:53,240 Jeg er tilbøjelig til aldrig at bruge det. 343 00:26:53,240 --> 00:26:59,120 Jeg har lige specifikt sige ramme 1, som er at gå til rammen mærket 1. 344 00:26:59,120 --> 00:27:01,750 Frame 1 kommer til at bringe os ind i main stakramme, 345 00:27:01,750 --> 00:27:05,570 og det siger lige her kodelinjen vi tilfældigvis at være på. 346 00:27:05,570 --> 00:27:07,950 Hvis vi ønskede et par flere linjer kode, kan vi sige liste, 347 00:27:07,950 --> 00:27:11,280 og det kommer til at give os alle de linjer kode omkring det. 348 00:27:11,280 --> 00:27:13,360 Den linje, 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 indlysende endnu, kan du få det lige herfra blot ved at tænke, hvorfor det segfaulted. 351 00:27:24,130 --> 00:27:28,800 Men vi kan tage det et skridt videre og sige, "Hvorfor ville argv [1] segfault?" 352 00:27:28,800 --> 00:27:38,830 Lad os print argv [1], og det ser ud som det er 0x0, som er den null-pointer. 353 00:27:38,830 --> 00:27:44,750 Vi strcmping CS50 sten og null, og så kommer til at 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 [Studerende] Fordi vi ikke gav det nogen kommandolinjeargumenter. 356 00:27:51,280 --> 00:27:53,390 Yeah. Vi har ikke givet det nogen kommandolinjeargumenter. 357 00:27:53,390 --> 00:27:58,460 Så ./buggy1 kun vil have argv [0] være ./buggy1. 358 00:27:58,460 --> 00:28:02,100 Det kommer ikke til at have en argv [1], så der kommer til at segfault. 359 00:28:02,100 --> 00:28:07,450 Men hvis, i stedet, det gør jeg bare CS50, det vil sige Du får et D 360 00:28:07,450 --> 00:28:09,950 fordi det er, hvad det er meningen at gøre. 361 00:28:09,950 --> 00:28:15,240 Ser man på buggy1.c, er det meningen at udskrive "Du får en D" - 362 00:28:15,240 --> 00:28:20,820 Hvis argv [1] er ikke "CS50 rocks", "Du får en D", ellers "Du får et A!" 363 00:28:20,820 --> 00:28:25,660 Så hvis vi ønsker en A, vi har brug for denne for at sammenligne så sandt, 364 00:28:25,660 --> 00:28:28,710 hvilket betyder, at det skal sammenlignes med 0. 365 00:28:28,710 --> 00:28:31,100 Så argv [1] skal være "CS50 rocks". 366 00:28:31,100 --> 00:28:35,660 Hvis du ønsker at gøre det på kommandolinjen, skal du bruge \ at undslippe rummet. 367 00:28:35,660 --> 00:28:41,690 Så CS50 \ klipper og du får en A! 368 00:28:41,690 --> 00:28:44,060 Hvis du ikke gør det omvendte skråstreg, hvorfor dette ikke virker? 369 00:28:44,060 --> 00:28:47,190 [Studerende] Det er to forskellige argumenter. >> Yeah. 370 00:28:47,190 --> 00:28:52,540 Argv [1] bliver CS50, og argv [2] vil være sten. Okay. 371 00:28:52,540 --> 00:28:56,470 >> Nu ./buggy2 vil segfault igen. 372 00:28:56,470 --> 00:29:01,880 I stedet for at åbne det med sin kerne-fil, vil vi bare åbne buggy2 direkte, 373 00:29:01,880 --> 00:29:05,000 så gdb buggy2. 374 00:29:05,000 --> 00:29:09,590 Nu, hvis vi bare køre vores program, så det kommer til at sige Program modtagne signal SIGSEGV, 375 00:29:09,590 --> 00:29:15,530 som er den segfault signal, og det er her det skete at ske. 376 00:29:15,530 --> 00:29:21,250 Ser man på vores backtrace, ser vi, at vi var i funktion oh_no, 377 00:29:21,250 --> 00:29:23,900 som blev kaldt af den funktion Dinky, som blev kaldt af funktionen binky, 378 00:29:23,900 --> 00:29:26,460 som blev kaldt af main. 379 00:29:26,460 --> 00:29:31,680 Vi kan også se de argumenter til disse funktioner. 380 00:29:31,680 --> 00:29:34,680 Argumentet til Dinky og Binky var 1. 381 00:29:34,680 --> 00:29:44,390 Hvis vi en liste over funktionen oh_no, ser vi, at oh_no bare gø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 mislykkes? 384 00:29:54,330 --> 00:29:58,380 [Studerende] Du kan ikke dereference null pointer? >> Yeah. 385 00:29:58,380 --> 00:30:06,090 Dette er bare at sige s er NULL, uanset om det sker for at være en char **, 386 00:30:06,090 --> 00:30:12,070 som, afhængigt af hvordan du fortolker det, kunne det være en pointer til en pointer til en streng 387 00:30:12,070 --> 00:30:15,550 eller et array af strenge. 388 00:30:15,550 --> 00:30:21,430 Det er s er NULL, så * s dereferere en null-pointer, 389 00:30:21,430 --> 00:30:24,800 og så dette kommer til at gå ned. 390 00:30:24,800 --> 00:30:27,540 Dette er en af ​​de hurtigste måder, du kan muligvis segfault. 391 00:30:27,540 --> 00:30:31,300 Det er bare at erklære en null-pointer og straks segfaulting. 392 00:30:31,300 --> 00:30:34,570 Det er, hvad oh_no gør. 393 00:30:34,570 --> 00:30:43,400 Hvis vi går op én ramme, så vi vil komme ind i den funktion, der hedder oh_no. 394 00:30:43,400 --> 00:30:44,830 Jeg har brug for at gøre det ned. 395 00:30:44,830 --> 00:30:48,610 Hvis du ikke indtaster en kommando, og du bare trykke Enter igen, 396 00:30:48,610 --> 00:30:52,350 det vil bare gentage den forrige kommando, du kørte. 397 00:30:52,350 --> 00:30:56,610 Vi er i frame 1. 398 00:30:56,610 --> 00:31:04,650 Notering denne ramme ser vi her er vores funktion. 399 00:31:04,650 --> 00:31:08,520 Du kan ramme liste igen, eller du kan gøre liste 20, og det vil vise mere. 400 00:31:08,520 --> 00:31:13,640 Funktionen dinky siger, at hvis jeg er 1, derefter gå til oh_no funktionen, 401 00:31:13,640 --> 00:31:15,960 ellers gå til den tætsiddende funktion. 402 00:31:15,960 --> 00:31:18,700 Og vi ved, at jeg er 1, fordi vi tilfældigvis til at se heroppe 403 00:31:18,700 --> 00:31:22,560 at dinky blev kaldt med argumentet 1. 404 00:31:22,560 --> 00:31:27,560 Eller du kan bare printe jeg, og det vil sige jeg er 1. 405 00:31:27,560 --> 00:31:33,770 Vi er i øjeblikket i dinky, og hvis vi går op en anden ramme, vi ved, vi vil ende i binky. 406 00:31:33,770 --> 00:31:36,600 Up. Nu er vi i binky. 407 00:31:36,600 --> 00:31:41,340 Notering denne funktion - listen fra før halv afbrød mig - 408 00:31:41,340 --> 00:31:52,670 det startede som om jeg er 0, så vil vi kalde det oh_no, ellers kalde dinky. 409 00:31:52,670 --> 00:31:57,000 Vi ved, jeg var 1, så det kaldte dinky. 410 00:31:57,000 --> 00:32:05,030 Og nu er vi tilbage i main, og vigtigste er bare at være int i = rand ()% 3; 411 00:32:05,030 --> 00:32:08,790 Det er bare at give dig et tilfældigt tal, der er enten 0, 1 eller 2. 412 00:32:08,790 --> 00:32:12,780 Det kommer til at kalde binky med dette nummer, og det vil vende tilbage 0. 413 00:32:12,780 --> 00:32:16,700 Ser på dette, 414 00:32:16,700 --> 00:32:19,880 bare gå gennem programmet manuelt uden at køre med det samme, 415 00:32:19,880 --> 00:32:25,400 du ville sætte en pause punkt på main, hvilket betyder, at når vi kører programmet 416 00:32:25,400 --> 00:32:31,020 Deres program løber indtil den rammer et knækpunkt. 417 00:32:31,020 --> 00:32:35,450 Så kører programmet, vil det køre og så vil det ramme den primære funktion og stopper. 418 00:32:35,450 --> 00:32:44,700 Nu er vi inde i main, og trin eller næste vil bringe os til den næste linje kode. 419 00:32:44,700 --> 00:32:47,050 Du kan gøre trin eller næste. 420 00:32:47,050 --> 00:32:51,800 Hitting næste, nu jeg er sat til rand ()% 3, så vi kan printe værdien af ​​i, 421 00:32:51,800 --> 00:32:55,280 og det vil sige jeg er 1. 422 00:32:55,280 --> 00:32:58,110 Nu er det ligegyldigt, om vi bruger næste eller trin. 423 00:32:58,110 --> 00:33:01,000 Jeg gætter det betød noget i den foregående, men vi ønsker at bruge næste. 424 00:33:01,000 --> 00:33:06,000 Hvis vi bruger skridt, vi træder ind i funktionen, hvilket betyder, kig på den faktiske ting 425 00:33:06,000 --> 00:33:07,940 der sker inde i binky. 426 00:33:07,940 --> 00:33:10,510 Hvis vi bruge næste, så betyder det gå over den funktion 427 00:33:10,510 --> 00:33:14,070 og bare gå til den næste linje kode i vores vigtigste funktion. 428 00:33:14,070 --> 00:33:17,900 Lige her på denne linje, var jeg på, hvor det sagde rand ()% 3; 429 00:33:17,900 --> 00:33:21,320 hvis jeg gjorde skridt, ville det gå i gennemførelsen af ​​rand 430 00:33:21,320 --> 00:33:25,110 og se på, hvad der sker der, og jeg kunne gå gennem den rand-funktionen. 431 00:33:25,110 --> 00:33:26,920 Men jeg er ligeglad med den rand-funktionen. 432 00:33:26,920 --> 00:33:30,190 Jeg vil bare gå til den næste linje kode i main, så jeg bruge næste. 433 00:33:30,190 --> 00:33:35,800 Men nu har jeg ligeglad med binky funktion, så jeg ønsker at træde ind i det. 434 00:33:35,800 --> 00:33:37,730 Nu er jeg i binky. 435 00:33:37,730 --> 00:33:42,040 Den første linje kode vil sige, hvis (i == 0), jeg tager et skridt, 436 00:33:42,040 --> 00:33:44,930 vi se, at vi ender på Dinky. 437 00:33:44,930 --> 00:33:51,620 Hvis vi liste ting, vi kan se, at det kontrolleres, er i = 0. 438 00:33:51,620 --> 00:33:55,470 Jeg er ikke lig med 0, så det gik til andet betingelse, 439 00:33:55,470 --> 00:33:59,540 der ringer dinky (i). 440 00:33:59,540 --> 00:34:04,030 Du kan blive forvirret. 441 00:34:04,030 --> 00:34:07,380 Hvis man bare ser på disse linjer direkte, kan du tror, ​​at hvis (i == 0), 442 00:34:07,380 --> 00:34:10,800 okay, så jeg tog et skridt og nu er jeg på Dinky (i), 443 00:34:10,800 --> 00:34:14,120 du måske tror det må betyde i = 0 eller sådan noget. 444 00:34:14,120 --> 00:34:18,980 Nej, det betyder bare, at det ved det kan holde sig direkte til den linje dinky (i). 445 00:34:18,980 --> 00:34:23,300 Fordi jeg ikke er 0, er det næste skridt ikke vil ende på andet. 446 00:34:23,300 --> 00:34:26,239 Else er ikke en linje det kommer til at stoppe ved. 447 00:34:26,239 --> 00:34:31,570 Det er bare kommer til at gå til næste linje kan det faktisk at gennemføre, hvilket er dinky (i). 448 00:34:31,570 --> 00:34:36,090 At træde ind i Dinky (i), ser vi, om (i == 1). 449 00:34:36,090 --> 00:34:42,670 Vi kender i = 1, så når vi skridt, vi ved, vi kommer til at ende op i oh_no 450 00:34:42,670 --> 00:34:46,489 fordi i = 1 kalder funktionen oh_no, som du kan træde ind, 451 00:34:46,489 --> 00:34:52,969 som vil sætte char ** s = til NULL og straks "BOOM". 452 00:34:54,270 --> 00:34:59,690 Og så faktisk ser på gennemførelsen af ​​buggy2, 453 00:34:59,690 --> 00:35:04,590 dette, er jeg bare at få et tilfældigt tal - 0, 1 eller 2 - calling binky, 454 00:35:04,590 --> 00:35:10,610 som, hvis i er 0 den kalder oh_no, ellers kalder Dinky, der kommer op her. 455 00:35:10,610 --> 00:35:18,100 Hvis jeg er 1, kald oh_no, ellers kalde slinky, som kommer op her, 456 00:35:18,100 --> 00:35:20,460 hvis i er 2, kalder oh_no. 457 00:35:20,460 --> 00:35:24,720 Jeg tror ikke engang der er en vej - 458 00:35:24,720 --> 00:35:30,030 Er der nogen se en måde at gøre dette et program, der ikke segfault? 459 00:35:30,030 --> 00:35:37,530 Fordi medmindre jeg mangler noget, hvis jeg er 0, vil du straks segfault, 460 00:35:37,530 --> 00:35:41,250 ellers kan du gå til en funktion, som hvis i er 1 du segfault, 461 00:35:41,250 --> 00:35:44,540 ellers kan du gå til en funktion, hvor hvis jeg er 2 du segfault. 462 00:35:44,540 --> 00:35:46,810 Så uanset hvad du gør, du segfault. 463 00:35:46,810 --> 00:35:52,380 >> Jeg gætte en måde at ordne det ville være stedet for at gøre char ** s = NULL, 464 00:35:52,380 --> 00:35:55,610 du kunne allokere plads til denne streng. 465 00:35:55,610 --> 00:36:04,230 Vi kunne gøre malloc (sizeof) - sizeof hvad? 466 00:36:09,910 --> 00:36:15,190 [Studerende] (char) * 5? >> Betyder dette synes ret? 467 00:36:15,190 --> 00:36:21,060 Jeg antager det vil virke, hvis jeg rent faktisk kørte det, men det er ikke hvad jeg leder efter. 468 00:36:24,400 --> 00:36:32,940 Kig på den type s. Lad os tilføje int *, så int * x. 469 00:36:32,940 --> 00:36:35,600 Jeg ville gøre malloc (sizeof (int)). 470 00:36:35,600 --> 00:36:40,490 Eller hvis jeg ønskede et array af 5, ville jeg gøre (sizeof (int) * 5); 471 00:36:40,490 --> 00:36:44,210 Hvad hvis jeg har en int **? 472 00:36:46,260 --> 00:36:49,140 Hvad ville jeg malloc? 473 00:36:49,140 --> 00:36:53,510 [Elev] Størrelse af markøren. >> Yeah. (Sizeof (int *)); 474 00:36:53,510 --> 00:36:56,960 Samme ting hernede. 475 00:36:56,960 --> 00:37:01,280 Jeg ønsker (sizeof (char *)); 476 00:37:06,170 --> 00:37:12,840 Dette vil afsætte plads til den pointer, peger på "BOOM". 477 00:37:12,840 --> 00:37:15,330 Jeg behøver ikke at afsætte plads til "BOOM" i sig selv 478 00:37:15,330 --> 00:37:17,210 fordi det er dybest set svarer til, hvad jeg sagde før 479 00:37:17,210 --> 00:37:20,870 af char * x = "BOOM". 480 00:37:20,870 --> 00:37:27,950 "BOOM" findes allerede. Det sker for at eksistere i read-only region af hukommelsen. 481 00:37:27,950 --> 00:37:35,200 Men den allerede findes, hvilket betyder denne linje kode, hvis s er en char **, 482 00:37:35,200 --> 00:37:43,900 så * s er en char *, og du indstiller denne char * at pege på "BOOM". 483 00:37:43,900 --> 00:37:50,040 Hvis jeg ønskede at kopiere "BOOM" i s, så ville jeg nødt til at afsætte plads til s. 484 00:37:55,170 --> 00:38:03,900 Jeg vil gø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 ud som "BOOM" er 4 tegn. >> [Studerende] The null-tegn. 487 00:38:10,860 --> 00:38:14,580 Yeah. Alle dine strenge vil få brug for den null-tegn. 488 00:38:14,580 --> 00:38:23,590 Nu kan jeg gøre noget som strcat - Hvad er funktionen til at kopiere en streng? 489 00:38:23,590 --> 00:38:28,520 [Studerende] CpY? >> Strcpy. 490 00:38:28,520 --> 00:38:32,700 mand 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 lidt sikrere, da du kan angive præcist, hvor mange tegn, 493 00:38:43,410 --> 00:38:46,190 men her er det ligegyldigt, fordi vi kender. 494 00:38:46,190 --> 00:38:50,340 Så strcpy og kigge i argumenterne. 495 00:38:50,340 --> 00:38:53,100 Det første argument er vores destination. 496 00:38:53,100 --> 00:38:56,770 Det andet argument er vores kilde. 497 00:38:56,770 --> 00:39:10,310 Vi kommer til at kopiere ind i vores destination * s markøren "BOOM". 498 00:39:10,310 --> 00:39:19,820 Hvorfor kan du ønsker at gøre dette med et strcpy i stedet for lige, hvad vi havde før 499 00:39:19,820 --> 00:39:22,800 af * s = "BOOM"? 500 00:39:22,800 --> 00:39:28,630 Der er en grund du måske ønsker at gøre dette, men hvad er det årsagen? 501 00:39:28,630 --> 00:39:31,940 [Studerende] Hvis du ønsker at ændre noget i "BOOM". >> Yeah. 502 00:39:31,940 --> 00:39:37,950 Nu kan jeg gøre noget som s [0] = 'X'; 503 00:39:37,950 --> 00:39:48,190 fordi s peger på den bunke, og at rummet på heapen at s peger på 504 00:39:48,190 --> 00:39:52,320 er en pegepind til mere plads på heapen, som er lagring "BOOM". 505 00:39:52,320 --> 00:39:55,150 Så denne kopi af "BOOM" bliver gemt i bunke. 506 00:39:55,150 --> 00:39:58,780 Der er teknisk set to kopier af "BOOM" i vores program. 507 00:39:58,780 --> 00:40:03,500 Der er den første, som er bare givet af denne "BOOM" strengen konstant, 508 00:40:03,500 --> 00:40:09,250 og den anden kopi af "BOOM", strcpy skabte kopi af "BOOM". 509 00:40:09,250 --> 00:40:13,100 Men kopi af "BOOM" bliver lagret på bunke, og den bunke du er fri for at skifte. 510 00:40:13,100 --> 00:40:17,250 Den bunke er ikke skrivebeskyttet, så det betyder, at s [0] 511 00:40:17,250 --> 00:40:20,500 vil lade dig ændre værdien af ​​"BOOM". 512 00:40:20,500 --> 00:40:23,130 Det kommer til at lade dig ændre disse tegn. 513 00:40:23,130 --> 00:40:26,640 >> Spørgsmål? 514 00:40:27,740 --> 00:40:29,290 Okay. 515 00:40:29,290 --> 00:40:35,500 >> Flytning til buggy3, lad os gdb buggy3. 516 00:40:35,500 --> 00:40:39,840 Vi bare køre det, og vi ser vi får en segfault. 517 00:40:39,840 --> 00:40:46,550 Hvis vi backtrace, er der kun to funktioner. 518 00:40:46,550 --> 00:40:52,970 Hvis vi går op i vores vigtigste funktion, ser vi, at vi segfaulted på denne linje. 519 00:40:52,970 --> 00:41:00,180 Så bare at kigge på denne linje, int linie = 0 for (; fgets denne ting ikke er lig med NULL; 520 00:41:00,180 --> 00:41:03,770 line + +). 521 00:41:03,770 --> 00:41:08,010 Vores tidligere ramme hed _IO_fgets. 522 00:41:08,010 --> 00:41:10,720 Du vil se, at en masse med indbygget i C-funktioner, 523 00:41:10,720 --> 00:41:15,350 at når du får den segfault, vil der være rigtig kryptiske funktionsnavne 524 00:41:15,350 --> 00:41:18,090 som denne _IO_fgets. 525 00:41:18,090 --> 00:41:21,770 Men det kommer til at forholde sig til dette fgets opkald. 526 00:41:21,770 --> 00:41:25,850 Et eller andet sted inde her, vi segfaulting. 527 00:41:25,850 --> 00:41:30,340 Hvis vi ser på de argumenter til fgets, kan vi udskrive buffer. 528 00:41:30,340 --> 00:41:41,180 Lad os udskrive som en - Åh, nej. 529 00:41:48,980 --> 00:41:51,900 Print kommer ikke til at fungere præcis som jeg ønsker det. 530 00:41:55,460 --> 00:41:58,000 Lad os se på det aktuelle program. 531 00:42:02,200 --> 00:42:09,640 Buffer er et tegn array. Det er et tegn array af 128 tegn. 532 00:42:09,640 --> 00:42:14,980 Så når jeg siger udskriftsbufferen, går det at udskrive disse 128 tegn, 533 00:42:14,980 --> 00:42:18,300 som jeg gætte er, hvad der forventes. 534 00:42:18,300 --> 00:42:21,390 Hvad jeg var på udkig efter, er udskrive adresse buffer, 535 00:42:21,390 --> 00:42:23,680 men det betyder ikke rigtig fortælle mig meget. 536 00:42:23,680 --> 00:42:30,770 Så når jeg tilfældigvis sige op her x buffer, det viser mig 0xbffff090, 537 00:42:30,770 --> 00:42:38,690 som, hvis du husker fra tidligere eller andet tidspunkt, Oxbffff tendens til at være en stabel-ish region. 538 00:42:38,690 --> 00:42:46,020 Stakken tendens til at starte et sted lige under 0xc000. 539 00:42:46,020 --> 00:42:51,890 Bare ved at se denne adresse ved jeg, at buffer sker på stakken. 540 00:42:51,890 --> 00:43:04,500 Genoptages mit program, løbe, op, buffer vi så var denne sekvens af tegn 541 00:43:04,500 --> 00:43:06,530 der er temmelig meget meningsløs. 542 00:43:06,530 --> 00:43:12,270 Så udskrivning fil, hvad fil ud? 543 00:43:15,120 --> 00:43:17,310 [Studerende] Null. >> Yeah. 544 00:43:17,310 --> 00:43:22,610 Filen er en af ​​typen FILE *, så det er en pointer, 545 00:43:22,610 --> 00:43:26,610 og værdien af ​​denne pegepind er null. 546 00:43:26,610 --> 00:43:33,240 Så fgets vil forsøge at læse fra denne pegepind på en indirekte måde, 547 00:43:33,240 --> 00:43:37,320 men for at få adgang til denne pegepind, det skal dereference det. 548 00:43:37,320 --> 00:43:40,550 Eller, for at få adgang til, hvad det skal pege på, det dereferences det. 549 00:43:40,550 --> 00:43:43,810 Så det er dereferere en null-pointer og det segfault'er. 550 00:43:46,600 --> 00:43:48,730 Jeg kunne have genstartet det der. 551 00:43:48,730 --> 00:43:52,170 Hvis vi bryder vores vigtigste punkt og køre, 552 00:43:52,170 --> 00:43:57,320 den første linje kode er char * filename = "nonexistent.txt"; 553 00:43:57,320 --> 00:44:00,870 Det burde give en temmelig stor vink om, hvorfor dette program mislykkes. 554 00:44:00,870 --> 00:44:06,080 Indtastning næste bringer mig til næste linje, hvor jeg åbner denne fil, 555 00:44:06,080 --> 00:44:11,140 og så er jeg straks komme ind i vores linje, hvor der engang jeg ramte næste, går det til segfault. 556 00:44:11,140 --> 00:44:16,880 Er der nogen ønsker at smide en grund til, at vi måske segfaulting? 557 00:44:16,880 --> 00:44:19,130 [Studerende] Filen findes ikke. >> Yeah. 558 00:44:19,130 --> 00:44:22,250 Dette formodes at være en antydning 559 00:44:22,250 --> 00:44:29,570 at når du åbner en fil, du har brug for at kontrollere, at filen rent 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 til læsning, vi så nødt til at sige 562 00:44:34,700 --> 00:44:45,870 if (fil == NULL) og sige printf ("Filen findes ikke!" 563 00:44:45,870 --> 00:44:56,340 eller - endnu bedre - filename) tilbagevenden 1; 564 00:44:56,340 --> 00:45:00,300 Så nu tjekker vi for at se, om det er NULL 565 00:45:00,300 --> 00:45:03,930 før der rent faktisk fortsætter og forsøger at læse fra den pågældende fil. 566 00:45:03,930 --> 00:45:08,800 Vi kan lave den bare for at se, at det virker. 567 00:45:11,020 --> 00:45:14,970 Jeg skal indbefatte en ny linje. 568 00:45:21,090 --> 00:45:25,290 Så nu nonexistent.txt findes ikke. 569 00:45:26,890 --> 00:45:30,040 Du bør altid tjekke for den slags ting. 570 00:45:30,040 --> 00:45:33,870 Du bør altid tjekke om fopen returnerer NULL. 571 00:45:33,870 --> 00:45:38,170 Du bør altid tjekke at sikre, at malloc ikke returnerer NULL, 572 00:45:38,170 --> 00:45:41,410 ellers kan du segfault. 573 00:45:42,200 --> 00:45:45,930 >> Nu buggy4.c. 574 00:45:49,190 --> 00:45:58,440 Løb. Jeg kan gætte dette venter på input eller eventuelt uendelig løkke. 575 00:45:58,440 --> 00:46:01,870 Ja, det er uendelig løkke. 576 00:46:01,870 --> 00:46:05,560 Så buggy4. Det ser ud til vi er uendelig løkke. 577 00:46:05,560 --> 00:46:12,590 Vi kan knække ved main, køre vores program. 578 00:46:12,590 --> 00:46:20,180 I gdb, så så længe forkortelsen du bruger, er entydig 579 00:46:20,180 --> 00:46:23,420 eller særlige forkortelser, som de leverer til dig, 580 00:46:23,420 --> 00:46:29,020 så kan du bruge n til at bruge næste i stedet for at skulle skrive ud næste hele vejen. 581 00:46:29,020 --> 00:46:33,730 Og nu hvor jeg har ramt n gang, kan jeg bare trykke Enter for at holde i gang næste 582 00:46:33,730 --> 00:46:36,640 stedet for at skulle slå n Indtast, n Enter, n Enter. 583 00:46:36,640 --> 00:46:44,630 Det ser ud som jeg er i en slags for-løkke, der er fastsættelsen array [i] til 0. 584 00:46:44,630 --> 00:46:50,510 Det ser ud som jeg aldrig jeg bryde ud af dette for-løkke. 585 00:46:50,510 --> 00:46:54,780 Hvis jeg udskriver i, så jeg er 2, så vil jeg gå næste. 586 00:46:54,780 --> 00:46:59,250 Jeg vil printe jeg, jeg er 3, så vil jeg gå næste. 587 00:46:59,250 --> 00:47:05,360 Jeg vil printe i, og jeg er 3. Næste, printe jeg, jeg er 4. 588 00:47:05,360 --> 00:47:14,520 Faktisk print sizeof (array), så størrelsen af ​​tabel er 20. 589 00:47:16,310 --> 00:47:32,870 Men det ser ud som om der er nogle særlige gdb kommando til at gå indtil der sker noget. 590 00:47:32,870 --> 00:47:37,620 Det er ligesom at sætte en betingelse på værdien af ​​den variable. Men jeg kan ikke huske hvad det er. 591 00:47:37,620 --> 00:47:44,100 Så hvis vi holder gang - 592 00:47:44,100 --> 00:47:47,120 Hvad sagde du? Hvad tog du op? 593 00:47:47,120 --> 00:47:50,500 [Studerende] ikke udviser jeg tilføje - >> Yeah. Så vise jeg kan hjælpe. 594 00:47:50,500 --> 00:47:54,530 Hvis vi bare vise i, vil det lægge op her, hvad værdien af ​​i er 595 00:47:54,530 --> 00:47:56,470 så jeg behøver ikke at printe det ud hver gang. 596 00:47:56,470 --> 00:48:02,930 Hvis vi bare holde går næste, vi ser 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 Noget går galt, og jeg er ved at blive nulstillet til 0. 598 00:48:13,330 --> 00:48:22,220 Ser man på buggy4.c, ser vi alt, hvad der sker, er int array [5]; 599 00:48:22,220 --> 00:48:26,200 for (i = 0; i <= sizeof (array), i + +) 600 00:48:26,200 --> 00:48:28,550 array [i] = 0; 601 00:48:28,550 --> 00:48:31,390 Hvad kan vi se, at der er galt her? 602 00:48:31,390 --> 00:48:39,480 Som et tip, da jeg lavede gdb buggy4 - lad os bryde main, run - 603 00:48:39,480 --> 00:48:45,980 Jeg gjorde print sizeof (array) bare for at se, hvad den betingelse er, hvor jeg skal endelig bryde ud. 604 00:48:47,690 --> 00:48:51,100 Hvor er jeg? Har jeg køre? 605 00:48:51,100 --> 00:48:54,280 Jeg har ikke erklære endnu. 606 00:48:54,280 --> 00:48:58,680 Så print sizeof (array), og det er 20, 607 00:48:58,680 --> 00:49:06,690 som forventes siden min array er af størrelse 5, og det er af 5 heltal, 608 00:49:06,690 --> 00:49:12,410 så det hele ting bør være 5 * sizeof (int) bytes, hvor sizeof (int) tendens til at være 4. 609 00:49:12,410 --> 00:49:14,780 Så sizeof (array) er 20. 610 00:49:14,780 --> 00:49:17,420 Hvad skal det være? 611 00:49:17,420 --> 00:49:21,720 [Studerende] divideret med sizeof (int). >> Ja, / sizeof (int). 612 00:49:21,720 --> 00:49:30,630 Det ser ud som om der er stadig et problem her. Jeg tror, ​​det skal bare være < 613 00:49:30,630 --> 00:49:36,960 da det er stort set altid 00:49:44,860 Nu lad os tænke over, hvorfor dette blev faktisk brudt. 615 00:49:44,860 --> 00:49:53,370 Er der nogen har gæt hvorfor blev jeg nulstiller til 0 gennem hver iteration af løkken? 616 00:50:01,300 --> 00:50:09,350 Det eneste inde i her, der sker, er, at array [i] er ved at blive sat til 0. 617 00:50:09,350 --> 00:50:15,350 Så en eller anden måde er denne linje kode forårsager vores int i at være sat til 0. 618 00:50:16,730 --> 00:50:23,130 [Studerende] Kunne det være, fordi det er tvingende mindet om denne del af i 619 00:50:23,130 --> 00:50:27,970 når den mener, det er det næste element af array? >> [Bowden] Ja. 620 00:50:27,970 --> 00:50:33,880 Når vi går ud over slutningen af ​​vores array, 621 00:50:33,880 --> 00:50:39,870 en eller anden måde dette rum, at vi altovervejende er tvingende værdien af ​​i. 622 00:50:39,870 --> 00:50:48,030 Og så hvis vi ser på buggy4, bryde main, køre, 623 00:50:48,030 --> 00:50:53,120 lad os udskrive adresse i. 624 00:50:53,120 --> 00:50:57,280 Det ser ud til det er bffff124. 625 00:50:57,280 --> 00:51:03,930 Lad os nu udskrive adressen på array [0]. 110. 626 00:51:03,930 --> 00:51:06,290 Hvad med [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å array [5] har samme adresse som jeg, hvilket betyder, at array [5] i. 630 00:51:26,990 --> 00:51:30,720 Hvis de har samme adresse, de er de samme ting. 631 00:51:30,720 --> 00:51:38,410 Så når vi sætter array [5] til 0, sætter vi i til 0. 632 00:51:38,410 --> 00:51:46,070 Og hvis du synes om dette i form af stablen, 633 00:51:46,070 --> 00:51:55,590 int i er erklæret først, hvilket betyder, at jeg får noget plads på stakken. 634 00:51:55,590 --> 00:52:04,730 Så array [5] er allokeret, så derefter 20 byte fordeles på stakken. 635 00:52:04,730 --> 00:52:08,400 Så jeg bliver tildelt først, derefter disse 20 bytes bliver tildelt. 636 00:52:08,400 --> 00:52:11,400 Så jeg sker lige før array, 637 00:52:11,400 --> 00:52:19,230 og på grund af den måde, som jeg sagde i sidste uge, hvor det er teknisk stakken vokser ned, 638 00:52:19,230 --> 00:52:28,520 når man indeks i et array, er vi garanteret, at 0. position i arrayet 639 00:52:28,520 --> 00:52:31,970 altid sker før den første position i opstillingen. 640 00:52:31,970 --> 00:52:35,900 Det er en slags hvordan jeg trak det i sidste uge. 641 00:52:35,900 --> 00:52:42,210 Bemærk, at i bunden har vi adressen 0 og øverst har vi adresse Max. 642 00:52:42,210 --> 00:52:44,880 Stakken vokser konstant ned. 643 00:52:48,100 --> 00:52:53,500 Lad os sige, vi tildeler jeg. 644 00:52:53,500 --> 00:52:59,680 Vi afsætter heltal i, hvilket betyder, lad os bare sige op her heltal i bliver tildelt. 645 00:52:59,680 --> 00:53:06,420 Så vi tildeler vores array af 5 heltal, hvilket betyder, at under det, 646 00:53:06,420 --> 00:53:11,230 da stakken vokser ned, får de 5 heltal tildelt. 647 00:53:11,230 --> 00:53:15,900 Men på grund af hvordan arrays fungerer, er vi garanteret, at den første position i arrayet 648 00:53:15,900 --> 00:53:22,260 altid adressen mindre end den anden ting i arrayet. 649 00:53:22,260 --> 00:53:28,270 Så array-position 0 altid skal ske først i hukommelsen, 650 00:53:28,270 --> 00:53:30,700 hvorimod array-position 1 skal ske efter det 651 00:53:30,700 --> 00:53:33,310 og array position 2 skal ske efter det, 652 00:53:33,310 --> 00:53:37,900 hvilket betyder, at array-position 0 ville ske et eller andet sted hernede, 653 00:53:37,900 --> 00:53:40,690 matrix position 1 ville ske ovenfor, 654 00:53:40,690 --> 00:53:45,530 fordi at bevæge sig op betyder højere adresser siden den maksimale adresse er heroppe. 655 00:53:45,530 --> 00:53:50,490 Så array [0] hernede, array [1] heroppe, array [2] op her, array [3] op her. 656 00:53:50,490 --> 00:53:55,620 Bemærk, hvordan før vi tildelt heltal i hele vejen op her, 657 00:53:55,620 --> 00:54:01,040 som vi bevæger os længere og længere ind i vores array, får vi tættere og tættere på vores heltal i. 658 00:54:01,040 --> 00:54:07,640 Det er bare sådan, at array [5], hvilket er en position uden for vores array, 659 00:54:07,640 --> 00:54:13,010 er præcis, hvor heltal jeg tilfældigvis skal tildeles. 660 00:54:13,010 --> 00:54:16,920 Så det er det punkt, hvor vi tilfældigvis rammer plads på stakken 661 00:54:16,920 --> 00:54:21,680 der blev afsat til heltal i, og vi sætte det til 0. 662 00:54:21,680 --> 00:54:26,160 >> Det er sådan det fungerer. Spørgsmål? Yeah. 663 00:54:26,160 --> 00:54:30,710 [Studerende] Pyt. Okay. 664 00:54:30,710 --> 00:54:33,090 [Studerende] Hvordan undgår man den slags fejl? 665 00:54:33,090 --> 00:54:41,190 Disse slags fejl? Brug ikke C som dit programmeringssprog. 666 00:54:41,190 --> 00:54:45,840 Brug et sprog, der har tabelgrænsekontrollering. 667 00:54:45,840 --> 00:54:55,900 Så længe du er forsigtig, du skal bare undgå at gå forbi grænserne for dit array. 668 00:54:55,900 --> 00:54:58,300 [Studerende] Så her, når vi gik forbi grænserne for dit array - 669 00:54:58,300 --> 00:55:01,840 [Bowden] Det er, hvor tingene begynder at gå galt. >> [Studerende] Åh, okay. 670 00:55:01,840 --> 00:55:05,730 Så længe du holder sig inden for hukommelse der er allokeret til dit array, du er fint. 671 00:55:05,730 --> 00:55:12,400 Men C gør ingen fejlkontrol. Hvis jeg gør array [1000], vil det gerne bare ændre uanset hvad der sker - 672 00:55:12,400 --> 00:55:16,500 Det går til begyndelsen af ​​array, så det går 1000 stillinger efter og indstiller den til 0. 673 00:55:16,500 --> 00:55:20,000 Det gør ikke noget kontrol af, at åh, betyder det faktisk ikke have 1000 ting i det. 674 00:55:20,000 --> 00:55:22,750 1000 er langt ud over hvad jeg skal ændre, 675 00:55:22,750 --> 00:55:26,940 hvorimod Java eller noget du får vifte out of bounds-indeks 676 00:55:26,940 --> 00:55:29,820 eller indeks out of bounds undtagelse. 677 00:55:29,820 --> 00:55:33,950 Det er derfor en masse af højere niveau sprog har disse ting 678 00:55:33,950 --> 00:55:37,340 hvor hvis du går ud over grænserne for den array, du ikke 679 00:55:37,340 --> 00:55:40,070 så du kan ikke ændre tingene nedefra dig 680 00:55:40,070 --> 00:55:42,590 og derefter går det meget værre end blot at få en undtagelse 681 00:55:42,590 --> 00:55:44,940 sige, at du gik ud over enden af ​​arrayet. 682 00:55:44,940 --> 00:55:50,970 [Studerende] Og så skulle vi lige har ændret <= til bare > [Bowden] Yeah. 683 00:55:50,970 --> 00:55:54,800 Det bør være 00:55:59,560 da sizeof (array) er 20, men vi ønsker kun 5. >> [Studerende] Right. 685 00:55:59,560 --> 00:56:04,060 Flere spørgsmål? Okay. 686 00:56:04,060 --> 00:56:07,380 >> [Studerende] Jeg har et spørgsmål. >> Yeah. 687 00:56:07,380 --> 00:56:16,440 [Studerende] Hvad er den aktuelle array-variabel? 688 00:56:16,440 --> 00:56:20,000 [Bowden] Som hvad er array? 689 00:56:20,000 --> 00:56:24,930 Array selv er et symbol. 690 00:56:24,930 --> 00:56:31,490 Det er bare adressen på starten af ​​de 20 bytes, som vi refererer til. 691 00:56:31,490 --> 00:56:38,070 Du kan tænke på det som en pegepind, men det er en konstant pegepind. 692 00:56:38,070 --> 00:56:44,140 Så snart tingene bliver kompileret, er den variable opstilling ikke eksisterer længere. 693 00:56:44,140 --> 00:56:48,210 [Studerende] Så hvordan virker det finde størrelsen af ​​array? 694 00:56:48,210 --> 00:56:54,130 Størrelsen af ​​tabellen refererer til størrelsen af ​​den pågældende blok, at dette symbol vedrører. 695 00:56:54,130 --> 00:57:01,240 Når jeg gør noget som printf ("% p \ n", array); 696 00:57:01,240 --> 00:57:05,140 lad os køre den. 697 00:57:12,960 --> 00:57:15,530 Hvad gjorde jeg bare forkert? 698 00:57:15,530 --> 00:57:19,220 Array 'array' erklæret her. 699 00:57:20,820 --> 00:57:23,200 Åh, heroppe. 700 00:57:23,200 --> 00:57:31,250 Klang er klog, og det sker for at opdage, at jeg erklærede array som 5 elementer 701 00:57:31,250 --> 00:57:34,540 men jeg indeksere i position 1000. 702 00:57:34,540 --> 00:57:38,450 Det kan gøre det, fordi disse er blot konstanter. 703 00:57:38,450 --> 00:57:43,370 Det kan kun gå så langt i at lægge mærke til, at jeg har tænkt mig ud over rammerne for opstillingen. 704 00:57:43,370 --> 00:57:46,880 Men bemærk før, når vi havde jeg være forkert, 705 00:57:46,880 --> 00:57:51,040 det kan umuligt afgøre, hvor mange værdier, jeg kunne tage på, 706 00:57:51,040 --> 00:57:55,540 så det kan ikke bestemme, at jeg skulle ud over enden af ​​matrixen. 707 00:57:55,540 --> 00:57:59,430 Det er bare Dunk at være dygtig. 708 00:57:59,430 --> 00:58:03,340 >> Men nu gør buggy4. Så hvad ellers gør jeg forkert? 709 00:58:03,340 --> 00:58:05,970 Implicit erklære bibliotek funktionen 'printf'. 710 00:58:05,970 --> 00:58:14,960 Jeg vil ønsker at # include . 711 00:58:14,960 --> 00:58:18,710 Okay. Nu kører buggy4. 712 00:58:18,710 --> 00:58:24,840 Udskrivning af værdien af ​​array som jeg gjorde her, udskrive den som en pegepind 713 00:58:24,840 --> 00:58:30,060 prints noget, der ligner dette - bfb8805c - hvilket er noget adresse 714 00:58:30,060 --> 00:58:33,450 der er i stakken-ish region. 715 00:58:33,450 --> 00:58:41,820 Array selv er som en pegepind, men det er ikke et virkeligt pointer, 716 00:58:41,820 --> 00:58:45,410 da en regelmæssig pointer, vi kan ændre. 717 00:58:45,410 --> 00:58:54,700 Array er blot nogle konstant. De 20 blokke af hukommelse starter ved adresse 0xbfb8805c. 718 00:58:54,700 --> 00:59:09,020 Så bfb8805c gennem denne adresse +20--eller jeg gætte -20 - 719 00:59:09,020 --> 00:59:17,400 er hele den hukommelse, der er afsat til dette array. 720 00:59:17,400 --> 00:59:20,350 Array, er variablen i sig selv ikke gemt nogen steder. 721 00:59:20,350 --> 00:59:27,660 Når du kompilerer, compileren - hånd bølge ved det - 722 00:59:27,660 --> 00:59:33,060 men compileren vil bare bruge hvor det ved opstilling at være. 723 00:59:33,060 --> 00:59:36,090 Det ved, hvor denne matrix starter, 724 00:59:36,090 --> 00:59:40,910 og så kan det altid bare gøre tingene i form af forskydninger fra begyndelsen. 725 00:59:40,910 --> 00:59:43,960 Det behøver ikke en variabel i sig selv til at repræsentere array. 726 00:59:43,960 --> 00:59:53,730 Men når jeg gør noget som int * p = array, nu p er en pointer, som peger på, at array, 727 00:59:53,730 --> 00:59:57,830 og nu p faktisk eksisterer på stakken. 728 00:59:57,830 --> 01:00:01,950 Jeg er fri til at ændre p. Jeg kan gøre p = malloc. 729 01:00:01,950 --> 01:00:06,500 Så det oprindeligt pegede på opstilling, og nu peger på noget plads på den bunke. 730 01:00:06,500 --> 01:00:09,620 Jeg kan ikke gøre vifte = malloc. 731 01:00:09,620 --> 01:00:13,710 Hvis Dunk er klog, vil det råbe ad mig ret off the bat. 732 01:00:17,000 --> 01:00:21,430 Faktisk er jeg temmelig sikker på gcc ville gøre dette også. 733 01:00:21,430 --> 01:00:25,010 Så array-type 'int [5]' er ikke overdrages. 734 01:00:25,010 --> 01:00:28,040 Du kan ikke tildele noget til en tabeltype 735 01:00:28,040 --> 01:00:30,500 fordi matrix er bare en konstant. 736 01:00:30,500 --> 01:00:34,760 Det er et symbol, som referencer de 20 bytes. Jeg kan ikke ændre det. 737 01:00:34,760 --> 01:00:37,690 >> [Studerende] Og hvor er størrelsen af ​​array opbevaret? 738 01:00:37,690 --> 01:00:40,670 [Bowden] Det er ikke gemt nogen steder. Det er, når det er kompilering. 739 01:00:40,670 --> 01:00:46,310 Så hvor er størrelsen af ​​arrayet opbevaret? 740 01:00:46,310 --> 01:00:51,870 Du kan kun bruge sizeof (array) indersiden af ​​funktion, array er erklæret sig selv. 741 01:00:51,870 --> 01:01:03,150 Så hvis jeg gør nogle funktion, foo, og jeg gør (int array []) 742 01:01:03,150 --> 01:01:10,450 printf ("% d \ n", sizeof (array)); 743 01:01:10,450 --> 01:01:21,330 og derefter ned her kalder jeg foo (array); 744 01:01:21,330 --> 01:01:24,840 indersiden af ​​denne funktion - lad os køre den. 745 01:01:34,200 --> 01:01:36,840 Dette er Dunk være dygtig igen. 746 01:01:36,840 --> 01:01:43,890 Det fortæller mig, at sizeof på array-funktion parameter 747 01:01:43,890 --> 01:01:46,690 vil returnere størrelse af 'int * «. 748 01:01:46,690 --> 01:01:55,150 Det ville være en fejl, hvis det ikke er, hvad jeg ønskede at ske. 749 01:01:55,150 --> 01:01:58,960 Lad os faktisk slukke Werror. 750 01:02:14,950 --> 01:02:17,590 Advarsel. Advarsler er fint. 751 01:02:17,590 --> 01:02:19,960 Det vil stadig indsamle så længe det har en advarsel. 752 01:02:19,960 --> 01:02:22,910 . / A.out vil udskrive 4. 753 01:02:22,910 --> 01:02:28,650 Den advarsel, der blev genereret er en klar indikator for, hvad der gik galt. 754 01:02:28,650 --> 01:02:34,120 Denne int array bare at udskrive sizeof (int *). 755 01:02:34,120 --> 01:02:39,790 Selv hvis jeg sætter array [5] her, er det stadig bare at udskrive sizeof (int *). 756 01:02:39,790 --> 01:02:47,440 Så så snart du passerer det ind i en funktion, at sondringen mellem arrays og pointers 757 01:02:47,440 --> 01:02:49,670 er ikke-eksisterende. 758 01:02:49,670 --> 01:02:52,640 Dette sker for at være et array, der blev erklæret på stakken, 759 01:02:52,640 --> 01:02:58,300 men så snart vi passerer denne værdi, at 0xbf blah, blah, blah ind i denne funktion, 760 01:02:58,300 --> 01:03:03,350 så er denne pointer peger på, at arrayet på stakken. 761 01:03:03,350 --> 01:03:08,310 Så det betyder, at sizeof kun gælder i den funktion, at den matrix blev erklæret, 762 01:03:08,310 --> 01:03:11,230 hvilket betyder, at når du kompilerer denne funktion, 763 01:03:11,230 --> 01:03:17,330 når Dunk går gennem denne funktion, den ser array er en int array af størrelse 5. 764 01:03:17,330 --> 01:03:20,640 Så det ser sizeof (array). Tja, det er 20. 765 01:03:20,640 --> 01:03:26,440 Det er faktisk hvordan sizeof dybest set virker for næsten alle tilfælde. 766 01:03:26,440 --> 01:03:31,150 Sizeof er ikke en funktion, det er en operatør. 767 01:03:31,150 --> 01:03:33,570 Du behøver ikke ringe til sizeof funktion. 768 01:03:33,570 --> 01:03:38,280 Sizeof (int), vil compileren bare oversætte det til 4. 769 01:03:41,480 --> 01:03:43,700 Forstået? Okay. 770 01:03:43,700 --> 01:03:47,520 >> [Studerende] Så hvad er forskellen mellem sizeof (array) i hoved-og i Foo? 771 01:03:47,520 --> 01:03:52,840 Dette skyldes, at vi siger sizeof (array), som er af typen int *, 772 01:03:52,840 --> 01:03:57,120 henviser til, at arrayet ned her er ikke af typen int *, det er en int array. 773 01:03:57,120 --> 01:04:04,540 >> [Studerende] Så hvis du havde parameter i array [] i stedet for int * array, 774 01:04:04,540 --> 01:04:09,230 ville det betyde, at du stadig kunne ændre array, fordi nu er det en pointer? 775 01:04:09,230 --> 01:04:14,250 [Bowden] Kan du lide det? >> [Studerende] Yeah. Kan du ændre opstilling i funktionen nu? 776 01:04:14,250 --> 01:04:18,420 [Bowden] Du kan ændre array i begge tilfælde. 777 01:04:18,420 --> 01:04:23,130 I begge disse tilfælde er du velkommen til at sige array [4] = 0. 778 01:04:23,130 --> 01:04:26,590 [Studerende] Men kan du gøre array-point til noget andet? 779 01:04:26,590 --> 01:04:30,230 [Bowden] Oh. Yeah. I begge tilfælde - >> [studerende] Yeah. 780 01:04:30,230 --> 01:04:38,410 [Bowden] Sondringen mellem array [] og en int * array, der er ingen. 781 01:04:38,410 --> 01:04:42,570 Du kan også få nogle flerdimensional tabel i her 782 01:04:42,570 --> 01:04:47,050 for nogle bekvem syntaks, men det er stadig bare en pegepind. 783 01:04:47,050 --> 01:04:56,400 Det betyder, at jeg er fri til at gøre opstilling = malloc (sizeof (int)), og nu peger et andet sted. 784 01:04:56,400 --> 01:04:59,610 Men ligesom hvordan det fungerer for evigt og altid, 785 01:04:59,610 --> 01:05:03,210 ændre dette array ved at gøre det peger på noget andet 786 01:05:03,210 --> 01:05:07,570 ændrer ikke dette array ned her, fordi det er en kopi af argumentet, 787 01:05:07,570 --> 01:05:10,780 det er ikke en pointer til dette argument. 788 01:05:10,780 --> 01:05:16,070 Og faktisk, ligesom flere tegn på, at det er præcis det samme - 789 01:05:16,070 --> 01:05:21,100 vi allerede har set, hvad trykning array-prints - 790 01:05:21,100 --> 01:05:31,410 hvad hvis vi printer adressen på arrayet eller adressen på adressen på arrayet 791 01:05:31,410 --> 01:05:36,290 til enten af ​​dem? 792 01:05:41,770 --> 01:05:45,220 Lad os se bort fra denne ene. 793 01:05:48,140 --> 01:05:51,660 Okay. Det er fint. Det er nu kører. / A.out. 794 01:05:51,660 --> 01:06:00,220 Trykning array, derefter trykning af adressen på arrayet, 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 Det ved, hvornår du udskriver array, er du udskriver det symbol, der henviser til de 20 bytes. 797 01:06:08,190 --> 01:06:11,940 Udskrivning af adressen på arrayet, ja, går matrix ikke. 798 01:06:11,940 --> 01:06:17,200 Det har ikke en adresse, så den netop udskriver adressen på de 20 bytes. 799 01:06:20,820 --> 01:06:28,150 Så snart du kompilere ned, gerne i din kompileret buggy4. / A.out, 800 01:06:28,150 --> 01:06:30,340 matrix er ikke-eksisterende. 801 01:06:30,340 --> 01:06:33,640 Pointers eksisterer. Arrays ikke. 802 01:06:34,300 --> 01:06:38,060 Blokkene af hukommelsen repræsenterer sættet stadig eksisterer, 803 01:06:38,060 --> 01:06:43,270 men den variable array og variable af denne type ikke eksisterer. 804 01:06:46,260 --> 01:06:50,270 Det er ligesom de vigtigste forskelle mellem arrays og pointers 805 01:06:50,270 --> 01:06:55,590 er, så snart du foretager funktionskald, er der ingen forskel. 806 01:06:55,590 --> 01:07:00,460 Men inde i den funktion, at den matrix selv er erklæret arbejder sizeof anderledes 807 01:07:00,460 --> 01:07:05,190 idet du udskriver størrelsen af ​​blokke i stedet for størrelsen af ​​den type, 808 01:07:05,190 --> 01:07:08,950 og du kan ikke ændre det, fordi det er et symbol. 809 01:07:08,950 --> 01:07:14,370 Udskrivning af ting og adressen på den ting udskriver det samme. 810 01:07:14,370 --> 01:07:18,480 Og det er temmelig meget det. 811 01:07:18,480 --> 01:07:20,820 [Studerende] Kan du sige det en gang til? 812 01:07:21,170 --> 01:07:24,170 Jeg kunne have overset noget. 813 01:07:24,170 --> 01:07:29,260 Udskrivning array og adresse på arrayet udskriver det samme, 814 01:07:29,260 --> 01:07:33,180 hvorimod hvis du udskriver en pointer i forhold til adressen på markøren, 815 01:07:33,180 --> 01:07:36,010 den ene ting udskriver adressen på hvad du peger på, 816 01:07:36,010 --> 01:07:40,360 den anden udskriver adressen på markøren på stakken. 817 01:07:40,360 --> 01:07:47,040 Du kan ændre en pegepind, og du kan ikke ændre et array symbol. 818 01:07:47,740 --> 01:07:53,270 Og sizeof pointer kommer til at udskrive størrelsen af ​​denne pointer type. 819 01:07:53,270 --> 01:07:57,470 Så int * p sizeof (p) vil udskrive 4, 820 01:07:57,470 --> 01:08:04,110 men int array [5] print sizeof (array) kommer til at udskrive 20. 821 01:08:04,110 --> 01:08:07,480 [Studerende] Så int array [5] vil udskrive 20? >> Ja. 822 01:08:07,480 --> 01:08:13,300 Det er derfor inde i buggy4 når det plejer at være sizeof (array) 823 01:08:13,300 --> 01:08:16,660 dette gjorde i <20, som er ikke, hvad vi ønskede. 824 01:08:16,660 --> 01:08:20,880 Vi ønsker i <5. >> [Studerende] Okay. 825 01:08:20,880 --> 01:08:25,569 [Bowden] Og så så snart du begynder at passerer i de funktioner, 826 01:08:25,569 --> 01:08:34,340 hvis vi gjorde int * p = array; 827 01:08:34,340 --> 01:08:39,779 indersiden af ​​denne funktion, kan vi dybest set bruge p og array i nøjagtig samme måde, 828 01:08:39,779 --> 01:08:43,710 bortset fra sizeof problem og den skiftende problem. 829 01:08:43,710 --> 01:08:49,810 Men p [0] = 1, er det samme som at sige array [0] = 1; 830 01:08:49,810 --> 01:08:55,600 Og så snart vi siger foo (array), eller foo (p); 831 01:08:55,600 --> 01:08:59,760 indersiden af ​​Foo funktion, er dette det samme opkald to gange. 832 01:08:59,760 --> 01:09:03,350 Der er ingen forskel mellem disse to opkald. 833 01:09:07,029 --> 01:09:11,080 >> Alle godt 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 vil forsøge at komme igennem denne Hacker Typer program, 836 01:09:28,319 --> 01:09:32,350 denne hjemmeside, som kom ud sidste år eller sådan noget. 837 01:09:34,149 --> 01:09:41,100 Det er bare skulle være som du skriver tilfældigt, og det udskrives - 838 01:09:41,100 --> 01:09:46,729 Uanset fil det sker for at have læsset er, hvad det ser ud som om du skriver. 839 01:09:46,729 --> 01:09:52,069 Det ligner en slags styresystem kode. 840 01:09:53,760 --> 01:09:56,890 Det er, hvad vi ønsker at gennemføre. 841 01:10:08,560 --> 01:10:11,690 Du bør have en binær eksekverbar navn hacker_typer 842 01:10:11,690 --> 01:10:14,350 der tager i et enkelt argument, filen til "hacker type." 843 01:10:14,350 --> 01:10:16,480 Kørsel den eksekverbare bør rydde skærmen 844 01:10:16,480 --> 01:10:20,850 og derefter udskrive et tegn fra de beståede-in-filen, hver gang brugeren trykker på en tast. 845 01:10:20,850 --> 01:10:24,990 Så uanset tast du trykker på, skal det smide væk og i stedet udskrive en karakter fra filen 846 01:10:24,990 --> 01:10:27,810 der er argumentet. 847 01:10:29,880 --> 01:10:34,350 Jeg vil stort set fortælle dig, hvad de ting, vi vil få brug for at vide er. 848 01:10:34,350 --> 01:10:36,440 Men vi ønsker at tjekke termios biblioteket. 849 01:10:36,440 --> 01:10:44,840 Jeg har aldrig brugt dette bibliotek i hele mit liv, så det har meget minimale formål. 850 01:10:44,840 --> 01:10:48,610 Men det vil være på biblioteket, vi kan bruge til at smide det tegn, du ramte 851 01:10:48,610 --> 01:10:52,390 når du skriver ind i standard i. 852 01:10:56,970 --> 01:11:05,840 Så hacker_typer.c, og vi vil gerne # include . 853 01:11:05,840 --> 01:11:12,870 Ser man på manden side for termios - jeg gætte det er terminal OS eller noget - 854 01:11:12,870 --> 01:11:16,240 Jeg ved ikke, hvordan det skal læses. 855 01:11:16,240 --> 01:11:21,040 Ser man på dette, siger det at medtage disse 2 filer, så vi vil gøre det. 856 01:11:37,620 --> 01:11:46,820 >> Første ting først, vi ønsker at tage i et enkelt argument, som er den fil, vi skal åbne. 857 01:11:46,820 --> 01:11:52,420 Så hvad vil jeg gøre? Hvordan kan jeg kontrollere at se, at jeg har et enkelt argument? 858 01:11:52,420 --> 01:11:56,480 [Studerende] Hvis argc lig det. >> [Bowden] Yeah. 859 01:11:56,480 --> 01:12:21,250 Så hvis (argc = 2!) Printf ("Brug:% s [fil for at åbne]"). 860 01:12:21,250 --> 01:12:32,750 Så nu hvis jeg køre dette uden at give et andet argument - åh, jeg har brug for den nye linje - 861 01:12:32,750 --> 01:12:36,240 du vil se det siger brug:. / hacker_typer, 862 01:12:36,240 --> 01:12:39,770 og derefter det andet argument bør være den fil jeg vil åbne. 863 01:12:58,430 --> 01:13:01,260 Nu hvad gør jeg? 864 01:13:01,260 --> 01:13:08,490 Jeg ønsker at læse fra denne fil. Hvordan læser jeg fra en fil? 865 01:13:08,490 --> 01:13:11,920 [Studerende] Du åbner det første. >> Yeah. 866 01:13:11,920 --> 01:13:15,010 Så fopen. Hvad betyder fopen ud? 867 01:13:15,010 --> 01:13:22,980 [Elev] Filename. >> [Bowden] Filename bliver argv [1]. 868 01:13:22,980 --> 01:13:26,110 [Studerende] Og hvad du vil gøre med det, så det - >> [Bowden] Yeah. 869 01:13:26,110 --> 01:13:28,740 Så hvis du ikke kan huske, kan du bare gøre mennesket fopen, 870 01:13:28,740 --> 01:13:32,960 hvor det vil være en const char * sti hvor sti er filnavn, 871 01:13:32,960 --> 01:13:34,970 const char * mode. 872 01:13:34,970 --> 01:13:38,660 Hvis du tilfældigvis ikke huske, hvad mode er, så kan du kigge efter mode. 873 01:13:38,660 --> 01:13:44,660 Inde i manualsider, er det skråstreg hvad du kan bruge til at søge efter ting. 874 01:13:44,660 --> 01:13:49,790 Så jeg skriver / mode for at søge efter mode. 875 01:13:49,790 --> 01:13:57,130 n og N er, hvad du kan bruge til at cykle gennem de søgeord kampe. 876 01:13:57,130 --> 01:13:59,800 Her står det argument tilstand peger på en streng 877 01:13:59,800 --> 01:14:01,930 begyndende med en af ​​følgende sekvenser. 878 01:14:01,930 --> 01:14:06,480 Så r, Open tekstfil til læsning. Det er, hvad vi ønsker at gøre. 879 01:14:08,930 --> 01:14:13,210 Til læsning, og jeg vil gemme det. 880 01:14:13,210 --> 01:14:18,720 De ting kommer til at være en fil *. Nu hvad vil jeg gøre? 881 01:14:18,720 --> 01:14:21,200 Giv mig et sekund. 882 01:14:28,140 --> 01:14:30,430 Okay. Nu hvad vil jeg gøre? 883 01:14:30,430 --> 01:14:32,940 [Studerende] Check om det er NULL. >> [Bowden] Yeah. 884 01:14:32,940 --> 01:14:38,690 Hver gang du åbner en fil, så sørg for at du er med held i stand til at åbne den. 885 01:14:58,930 --> 01:15:10,460 >> Nu vil jeg gøre det termios ting, hvor jeg vil først læse mine aktuelle indstillinger 886 01:15:10,460 --> 01:15:14,050 og gemme dem til noget, så jeg ønsker at ændre mine indstillinger 887 01:15:14,050 --> 01:15:19,420 at smide noget tegn, jeg skriver, 888 01:15:19,420 --> 01:15:22,520 og så vil jeg opdatere disse indstillinger. 889 01:15:22,520 --> 01:15:27,250 Og så ved afslutningen af ​​programmet, vil jeg gerne skifte tilbage til mine oprindelige indstillinger. 890 01:15:27,250 --> 01:15:32,080 Så struct bliver af typen termios, og jeg har tænkt mig at have to af dem. 891 01:15:32,080 --> 01:15:35,600 Den første vil være mine current_settings, 892 01:15:35,600 --> 01:15:42,010 og så de kommer til at være mine hacker_settings. 893 01:15:42,010 --> 01:15:48,070 Først, jeg lyst til at gemme mine aktuelle indstillinger, 894 01:15:48,070 --> 01:15:53,790 så jeg har tænkt mig at ønsker at opdatere hacker_settings, 895 01:15:53,790 --> 01:16:01,570 og derefter vej i slutningen af ​​mit program, jeg vil vende tilbage til de aktuelle indstillinger. 896 01:16:01,570 --> 01:16:08,660 Så sparer aktuelle indstillinger, den måde der virker, vi mand 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 passere i en termios struct ved sin pointer. 899 01:16:22,960 --> 01:16:30,640 Den måde det vil se er - jeg har allerede glemt hvad funktionen blev kaldt. 900 01:16:30,640 --> 01:16:34,930 Kopier og indsæt det. 901 01:16:39,150 --> 01:16:45,500 Så tcgetattr, så jeg ønsker at videregive i struct, at jeg gemmer oplysningerne i, 902 01:16:45,500 --> 01:16:49,650 der bliver current_settings, 903 01:16:49,650 --> 01:16:59,120 og det første argument er file descriptor for de ting, jeg ønsker at gemme attributter. 904 01:16:59,120 --> 01:17:04,360 Hvad file descriptor er er ligesom enhver tid du åbner en fil, det får en file descriptor. 905 01:17:04,360 --> 01:17:14,560 Når jeg fopen argv [1], det får en file descriptor, som du henviser til 906 01:17:14,560 --> 01:17:16,730 når du ønsker at læse eller skrive til den. 907 01:17:16,730 --> 01:17:19,220 Det er ikke den file descriptor jeg vil bruge her. 908 01:17:19,220 --> 01:17:21,940 Der er tre arkivbeskrivere du har som standard, 909 01:17:21,940 --> 01:17:24,310 som er standard i, standard ud, og standardfejlen. 910 01:17:24,310 --> 01:17:29,960 Som standard, tror jeg, det er standard i er 0, standard ud er 1, og standard error er 2. 911 01:17:29,960 --> 01:17:33,980 Så hvad gør jeg ønsker at ændre indstillingerne for? 912 01:17:33,980 --> 01:17:37,370 Jeg ønsker at ændre indstillingerne for hver gang jeg ramte en karakter, 913 01:17:37,370 --> 01:17:41,590 Jeg vil have det til at smide karakter væk i stedet for at udskrive det på skærmen. 914 01:17:41,590 --> 01:17:45,960 Hvad stream - standard i, standard ud, eller standardfejlen - 915 01:17:45,960 --> 01:17:52,050 reagerer på ting, når jeg skriver på tastaturet? >> [Studerende] Standard i. >> Yeah. 916 01:17:52,050 --> 01:17:56,450 Så jeg kan enten gøre 0 eller jeg kan gøre stdin. 917 01:17:56,450 --> 01:17:59,380 Jeg får current_settings af standard i. 918 01:17:59,380 --> 01:18:01,720 >> Nu vil jeg opdatere disse indstillinger, 919 01:18:01,720 --> 01:18:07,200 så først vil jeg kopiere ind hacker_settings hvad mine current_settings er. 920 01:18:07,200 --> 01:18:10,430 Og hvordan struct arbejde er det vil bare kopiere. 921 01:18:10,430 --> 01:18:14,510 Dette kopierer alle de felter, som du ville forvente. 922 01:18:14,510 --> 01:18:17,410 >> Nu vil jeg opdatere nogle af felterne. 923 01:18:17,410 --> 01:18:21,670 Ser man på termios, ville du nødt til at læse igennem en masse af denne 924 01:18:21,670 --> 01:18:24,110 bare for at se, hvad du ønsker at se efter, 925 01:18:24,110 --> 01:18:28,210 men flagene, du vil ønsker at søge er ekko, 926 01:18:28,210 --> 01:18:33,110 så ECHO Echo input tegn. 927 01:18:33,110 --> 01:18:37,710 Først vil jeg indstille - jeg har allerede glemt hvad felterne er. 928 01:18:45,040 --> 01:18:47,900 Dette er, hvad den struct ser ud. 929 01:18:47,900 --> 01:18:51,060 Så inputtilstande jeg tror, ​​at vi vil ændre. 930 01:18:51,060 --> 01:18:54,210 Vi vil se på en løsning for at sikre, det er hvad vi ønsker at ændre. 931 01:19:04,060 --> 01:19:12,610 Vi ønsker at ændre lflag for at forhindre at skulle se igennem alle disse. 932 01:19:12,610 --> 01:19:14,670 Vi ønsker at ændre lokale modes. 933 01:19:14,670 --> 01:19:17,710 Du ville have til at læse igennem hele denne ting at forstå, hvor alt hører 934 01:19:17,710 --> 01:19:19,320 at vi ønsker at ændre. 935 01:19:19,320 --> 01:19:24,120 Men det er inde i lokale tilstande, hvor vi kommer til at ønsker at ændre det. 936 01:19:27,080 --> 01:19:33,110 Så hacker_settings.cc_lmode er hvad det hedder. 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 ind i bitvise operatører. 939 01:19:52,280 --> 01:19:54,860 Vi er slags ud af tid, men vi vil gå igennem det virkelig hurtig. 940 01:19:54,860 --> 01:19:56,600 Det er her vi kommer ind bitvise operatører, 941 01:19:56,600 --> 01:19:59,950 hvor jeg tror, ​​jeg sagde en gang for længe siden, at når du begynde at behandle med flag, 942 01:19:59,950 --> 01:20:03,370 du skal bruge bitvis operatør en masse. 943 01:20:03,370 --> 01:20:08,240 Hver bit i flaget svarer til en slags opførsel. 944 01:20:08,240 --> 01:20:14,090 Så her, dette flag har en masse forskellige ting, hvor de alle betyder noget andet. 945 01:20:14,090 --> 01:20:18,690 Men hvad jeg ønsker at gøre, er bare at slukke for bit, som svarer til ECHO. 946 01:20:18,690 --> 01:20:25,440 Så for at slå funktionen fra jeg gøre & = ¬ ECHO. 947 01:20:25,440 --> 01:20:30,110 Jeg tror faktisk, det er ligesom Techo eller noget. Jeg skal bare for at tjekke igen. 948 01:20:30,110 --> 01:20:34,050 Jeg kan termios det. Det er bare ECHO. 949 01:20:34,050 --> 01:20:38,440 ECHO vil være en enkelt bit. 950 01:20:38,440 --> 01:20:44,230 ¬ ECHO kommer til at betyde alle bit er sat til 1, hvilket betyder, at alle flag er sat til sand 951 01:20:44,230 --> 01:20:47,140 bortset fra ECHO bit. 952 01:20:47,140 --> 01:20:53,830 Ved at ende mine lokale flag med dette, betyder det, alle flag, der i øjeblikket er indstillet til sand 953 01:20:53,830 --> 01:20:56,520 vil stadig blive sat til sand. 954 01:20:56,520 --> 01:21:03,240 Hvis min ECHO flag er sat til sand, så dette er nødvendigvis indstillet til FALSE på ECHO flag. 955 01:21:03,240 --> 01:21:07,170 Så denne linje kode bare slukker ECHO flag. 956 01:21:07,170 --> 01:21:16,270 De andre linjer kode, vil jeg bare kopiere dem af hensyn til tid og derefter forklare dem. 957 01:21:27,810 --> 01:21:30,180 I løsningen, sagde han 0. 958 01:21:30,180 --> 01:21:33,880 Det er nok bedre til eksplicit at sige stdin. 959 01:21:33,880 --> 01:21:42,100 >> Bemærk, at jeg også laver ECHO | ICANON her. 960 01:21:42,100 --> 01:21:46,650 ICANON henviser til noget separat, hvilket betyder kanoniske tilstand. 961 01:21:46,650 --> 01:21:50,280 Hvad kanoniske tilstand betyder som regel, når du skriver ud kommandolinjen, 962 01:21:50,280 --> 01:21:54,670 standard i ikke behandler noget, før du rammer newline. 963 01:21:54,670 --> 01:21:58,230 Så når du GetString, du skriver en masse ting, så du rammer newline. 964 01:21:58,230 --> 01:22:00,590 Det er, når den 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 slukker kanoniske mode, nu hver eneste tegn, du trykker 967 01:22:05,830 --> 01:22:10,910 er, hvad der bliver behandlet, som normalt er slags dårlig, fordi det er længe om at behandle disse ting, 968 01:22:10,910 --> 01:22:14,330 hvilket er hvorfor det er godt at buffer det i hele linjer. 969 01:22:14,330 --> 01:22:16,810 Men jeg vil hver karakter skal behandles 970 01:22:16,810 --> 01:22:18,810 da jeg ikke vil have det til at vente på mig at ramme newline 971 01:22:18,810 --> 01:22:21,280 før den behandler alle de tegn, jeg har at skrive. 972 01:22:21,280 --> 01:22:24,760 Dette slår kanoniske tilstand. 973 01:22:24,760 --> 01:22:31,320 Denne ting bare betyder, når det rent faktisk behandler tegn. 974 01:22:31,320 --> 01:22:35,830 Det betyder, behandle dem straks, så snart jeg skriver dem, bearbejde dem. 975 01:22:35,830 --> 01:22:42,510 Og det er den funktion, som opdaterer mine indstillinger for standard i, 976 01:22:42,510 --> 01:22:45,480 og TCSA midler at gøre det lige nu. 977 01:22:45,480 --> 01:22:50,310 De andre muligheder er vente alt, hvad der er i øjeblikket på strøm er behandlet. 978 01:22:50,310 --> 01:22:52,030 Det betyder ikke rigtig noget. 979 01:22:52,030 --> 01:22:56,920 Lige nu ændre mine indstillinger til at være, hvad der er i øjeblikket i hacker_typer_settings. 980 01:22:56,920 --> 01:23:02,210 Jeg tror, ​​jeg kaldte det hacker_settings, så lad os ændre det. 981 01:23:09,610 --> 01:23:13,500 Ændre alt til hacker_settings. 982 01:23:13,500 --> 01:23:16,870 >> Nu ved afslutningen af ​​vores program vil vi ønsker at vende tilbage 983 01:23:16,870 --> 01:23:20,210 til hvad der for tiden inde i normal_settings, 984 01:23:20,210 --> 01:23:26,560 som vil bare ligne & normal_settings. 985 01:23:26,560 --> 01:23:30,650 Bemærk, at jeg har ikke ændret nogen af ​​mine normal_settings siden oprindeligt at få det. 986 01:23:30,650 --> 01:23:34,520 Så bare at ændre dem tilbage, jeg passerer dem tilbage i slutningen. 987 01:23:34,520 --> 01:23:38,390 Det var opdateringen. Okay. 988 01:23:38,390 --> 01:23:43,900 >> Nu inde i her vil jeg lige forklare koden til gavn for tiden. 989 01:23:43,900 --> 01:23:46,350 Det er ikke så meget kode. 990 01:23:50,770 --> 01:24:03,750 Vi ser vi læse et tegn fra filen. Vi kaldte det f.. 991 01:24:03,750 --> 01:24:07,850 Nu kan du mand fgetc, men hvordan fgetc kommer til at arbejde 992 01:24:07,850 --> 01:24:11,910 er bare det kommer til at returnere det tegn, du lige har læst eller EOF, 993 01:24:11,910 --> 01:24:15,680 som svarer til slutningen af ​​filen eller en fejl sker. 994 01:24:15,680 --> 01:24:19,900 Vi looping, fortsætter med at læse et enkelt tegn fra filen, 995 01:24:19,900 --> 01:24:22,420 indtil vi har kørt ud af tegn at læse. 996 01:24:22,420 --> 01:24:26,650 Og mens vi gør det, vi venter på et enkelt tegn fra standard i. 997 01:24:26,650 --> 01:24:29,090 Hver eneste gang du skriver noget på kommandolinjen, 998 01:24:29,090 --> 01:24:32,820 der er læsning i en karakter fra standard i. 999 01:24:32,820 --> 01:24:38,330 Derefter putchar er bare at sætte den char vi læser op her fra filen til standard ud. 1000 01:24:38,330 --> 01:24:42,890 Du kan mennesket putchar, men det er bare at sætte til standard ud, er det udskriver tegn. 1001 01:24:42,890 --> 01:24:51,600 Du kunne også bare gøre printf ("% c", c) Samme idé. 1002 01:24:53,330 --> 01:24:56,670 Det kommer til at gøre størstedelen af ​​vores arbejde. 1003 01:24:56,670 --> 01:25:00,300 >> Den sidste ting vi vil ønsker at gøre, er bare fclose vores fil. 1004 01:25:00,300 --> 01:25:03,310 Hvis du ikke fclose, det er en hukommelsesfejl. 1005 01:25:03,310 --> 01:25:06,680 Vi ønsker at fclose den fil, vi oprindeligt åbnet, og jeg tror, ​​det er det. 1006 01:25:06,680 --> 01:25:13,810 Hvis vi gør det, jeg allerede har problemer. 1007 01:25:13,810 --> 01:25:17,260 Lad os se. 1008 01:25:17,260 --> 01:25:19,960 Hvad gjorde det klage over? 1009 01:25:19,960 --> 01:25:30,220 Forventede 'int' men argument er af typen 'struct _IO_FILE *'. 1010 01:25:36,850 --> 01:25:39,370 Vi vil se, om det virker. 1011 01:25:45,210 --> 01:25:53,540 Kun tilladt i C99. Augh. Okay, gør hacker_typer. 1012 01:25:53,540 --> 01:25:57,760 Nu får vi mere nyttige beskrivelser. 1013 01:25:57,760 --> 01:25:59,900 Så brug af sort identifikator «normal_settings«. 1014 01:25:59,900 --> 01:26:04,170 Jeg kaldte det ikke normal_settings. Jeg kaldte det current_settings. 1015 01:26:04,170 --> 01:26:12,090 Så lad os ændre alt dette. 1016 01:26:17,920 --> 01:26:21,710 Nu passerer argument. 1017 01:26:26,290 --> 01:26:29,500 Jeg vil gøre dette 0 for nu. 1018 01:26:29,500 --> 01:26:36,720 Okay. . / Hacker_typer cp.c. 1019 01:26:36,720 --> 01:26:39,590 Jeg heller ikke rydde skærmen i begyndelsen. 1020 01:26:39,590 --> 01:26:42,960 Men du kan se tilbage på det sidste problem sæt for at se, hvordan du rydder skærmen. 1021 01:26:42,960 --> 01:26:45,160 Det er bare at udskrive nogle tegn 1022 01:26:45,160 --> 01:26:47,210 mens dette gør, hvad jeg vil gøre. 1023 01:26:47,210 --> 01:26:48,900 Okay. 1024 01:26:48,900 --> 01:26:55,280 Og tænke over, hvorfor dette skulle 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 over, at - 1027 01:27:13,150 --> 01:27:19,360 Før da jeg sagde, at der er arkivbeskrivere men så skal du også have din fil *, 1028 01:27:19,360 --> 01:27:23,210 en file descriptor er blot et enkelt heltal, 1029 01:27:23,210 --> 01:27:26,970 hvorimod en FILE * har en hel masse ting forbundet med det. 1030 01:27:26,970 --> 01:27:30,380 Årsagen til at vi er nødt til at sige 0 i stedet for stdin 1031 01:27:30,380 --> 01:27:37,480 er, at stdin er en fil *, som peger mod ting, der refererer file descriptor 0. 1032 01:27:37,480 --> 01:27:45,070 Så selv op her, når jeg gør fopen (argv [1], jeg får en FIL * tilbage. 1033 01:27:45,070 --> 01:27:51,180 Men et eller andet sted i denne fil * er en ting, der svarer til file descriptor for den pågældende fil. 1034 01:27:51,180 --> 01:27:57,430 Hvis man ser på den mand side for åben, så jeg tror, ​​du bliver nødt til at gøre mennesket 3 open - nej - 1035 01:27:57,430 --> 01:27:59,380 mand 2 åben - ja. 1036 01:27:59,380 --> 01:28:06,250 Hvis man ser på siden for åben, åben er ligesom et lavere niveau fopen, 1037 01:28:06,250 --> 01:28:09,350 og det er tilbage den faktiske file descriptor. 1038 01:28:09,350 --> 01:28:12,050 fopen gør en masse ting på toppen af ​​åbne, 1039 01:28:12,050 --> 01:28:17,640 som i stedet for at returnere bare at file descriptor returnerer en hel FILE * pointer 1040 01:28:17,640 --> 01:28:20,590 inde i som er vores lille file descriptor. 1041 01:28:20,590 --> 01:28:25,020 Så standard i refererer til den fil * ting, 1042 01:28:25,020 --> 01:28:29,120 hvorimod 0 refererer til bare file descriptor standard i sig selv. 1043 01:28:29,120 --> 01:28:32,160 >> Spørgsmål? 1044 01:28:32,160 --> 01:28:35,930 [Griner] blæste gennem det. 1045 01:28:35,930 --> 01:28:39,140 Ok. Vi er fćrdige. [Griner] 1046 01:28:39,140 --> 01:28:42,000 >> [CS50.TV]