1 00:00:00,000 --> 00:00:02,500 [Powered by Google Translate] [Sectie 5 - Meer Comfortabele] 2 00:00:02,500 --> 00:00:04,690 [Rob Bowden - Harvard University] 3 00:00:04,690 --> 00:00:07,250 [Dit is CS50. - CS50.TV] 4 00:00:08,990 --> 00:00:14,250 >> Zoals ik al zei in mijn e-mail, zijn er een heleboel dingen die je kunt gebruiken 5 00:00:14,250 --> 00:00:17,060 anders dan het apparaat eigenlijk het probleem sets. 6 00:00:17,060 --> 00:00:19,910 Wij raden u het in het apparaat, alleen maar omdat dan kunnen we makkelijker helpen 7 00:00:19,910 --> 00:00:22,070 en we weten hoe alles gaat werken. 8 00:00:22,070 --> 00:00:26,950 Maar als een voorbeeld van waar je dingen kunt doen als, zeg, hebt u geen toegang 9 00:00:26,950 --> 00:00:31,570 om een ​​apparaat of u wilt werken in het Science Center kelder - 10 00:00:31,570 --> 00:00:33,090 die in feite hebben ze het apparaat ook - 11 00:00:33,090 --> 00:00:35,150 als je wilt overal werken. 12 00:00:35,150 --> 00:00:42,370 Een voorbeeld is heb je gezien / gehoord van SSH? 13 00:00:44,380 --> 00:00:47,780 SSH is eigenlijk net als verbinding te maken met iets. 14 00:00:47,780 --> 00:00:51,340 Eigenlijk, nu ben ik SSHed in het apparaat. 15 00:00:51,340 --> 00:00:54,290 Ik heb nooit rechtstreeks in het apparaat. 16 00:00:55,930 --> 00:01:01,060 Hier is het apparaat, en als je naar beneden kijkt hier zie je dit IP-adres. 17 00:01:01,060 --> 00:01:03,650 Ik heb nooit werken in het apparaat zelf; 18 00:01:03,650 --> 00:01:08,840 Ik heb altijd meer dan komen tot een iTerm2 venster / terminal-venster. 19 00:01:08,840 --> 00:01:15,910 U kunt SSH naar dat IP-adres, ssh jharvard@192.168.129.128. 20 00:01:15,910 --> 00:01:20,390 Ik herinner me dat nummer heel gemakkelijk, want het is zo'n mooi patroon. 21 00:01:20,390 --> 00:01:24,920 Maar dat zal mij vragen om mijn wachtwoord, en nu ben ik in het apparaat. 22 00:01:24,920 --> 00:01:33,060 Kortom, op dit punt, als het openen van een terminal binnenkant van het apparaat zelf, 23 00:01:33,060 --> 00:01:36,350 deze interface, maar u zou gebruiken, is precies hetzelfde 24 00:01:36,350 --> 00:01:40,010 als de interface die ik gebruik hier maar nu ben je SSHed. 25 00:01:42,240 --> 00:01:44,920 Je hoeft niet te SSH aan het apparaat. 26 00:01:44,920 --> 00:01:52,360 Een voorbeeld van een andere plaats kon je SSH is dat ik ben er vrij zeker van je standaard - 27 00:01:52,360 --> 00:01:55,020 Oh. Groter. 28 00:01:55,020 --> 00:02:01,130 Al moet je standaard FAS accounts op de FAS-servers. 29 00:02:01,130 --> 00:02:06,840 Voor mij, ik zou SSH naar rbowden@nice.fas.harvard.edu. 30 00:02:06,840 --> 00:02:11,610 Het zal u dat de eerste keer te vragen, en je zegt ja. 31 00:02:11,610 --> 00:02:15,840 Mijn wachtwoord is gewoon mijn FAS wachtwoord. 32 00:02:15,840 --> 00:02:22,650 En nu, ik ben SSHed naar de mooie servers, en ik kan wat ik wil hier doen. 33 00:02:22,650 --> 00:02:28,560 Veel van klassen die u zou kunnen uitvoeren, bijvoorbeeld 124, zullen moeten je spullen uploaden naar hier 34 00:02:28,560 --> 00:02:30,950 om daadwerkelijk in te dienen uw probleem sets. 35 00:02:30,950 --> 00:02:34,100 Maar zeggen dat je geen toegang heeft tot uw apparaat te hebben. 36 00:02:34,100 --> 00:02:37,910 Dan kunt u dingen doen, zoals hier zal het zeggen - 37 00:02:37,910 --> 00:02:42,160 Dit is gewoon onze rubriek vragen. 38 00:02:42,160 --> 00:02:45,070 Het zal u vragen om dit te doen in het apparaat. 39 00:02:45,070 --> 00:02:47,790 In plaats daarvan zal ik gewoon doen op de server. 40 00:02:47,790 --> 00:02:50,560 Ik ga uit te pakken dat. 41 00:02:50,560 --> 00:02:55,670 Het probleem zal zijn dat je gewend bent aan het gebruik van iets als gedit 42 00:02:55,670 --> 00:02:58,160 of wat binnenkant van het apparaat. 43 00:02:58,160 --> 00:03:01,830 Je gaat niet naar dat hebben op de FAS-server. 44 00:03:01,830 --> 00:03:04,110 Het is allemaal gewoon aan deze tekstuele interface. 45 00:03:04,110 --> 00:03:09,180 Dus je zou kunnen een van beide, probeer dan een teksteditor die ze hebben leren. 46 00:03:09,180 --> 00:03:12,130 Ze hebben Nano. 47 00:03:12,130 --> 00:03:14,990 Nano is meestal vrij eenvoudig te gebruiken. 48 00:03:14,990 --> 00:03:19,470 U kunt gebruik maken van uw pijlen en typ normaal. 49 00:03:19,470 --> 00:03:21,250 Dus dat is niet moeilijk. 50 00:03:21,250 --> 00:03:24,720 Als u wilt krijgen echt aantrekkelijk kunt u gebruik maken Emacs, 51 00:03:24,720 --> 00:03:29,850 die waarschijnlijk had ik niet moeten geopend, omdat ik weet niet eens hoe je Emacs te sluiten. 52 00:03:29,850 --> 00:03:32,760 Controle X, Control-C? Ja. 53 00:03:32,760 --> 00:03:35,310 Of u kunt gebruik maken van Vim, dat is wat ik gebruik. 54 00:03:35,310 --> 00:03:37,800 En dus die zijn uw opties. 55 00:03:37,800 --> 00:03:43,830 Als u niet wilt dat te doen, kunt u ook, als je kijkt naar manual.cs50.net-- 56 00:03:43,830 --> 00:03:45,410 Oh. 57 00:03:45,410 --> 00:03:49,920 Op een pc kunt u met behulp van SSH PuTTY, 58 00:03:49,920 --> 00:03:51,940 die je gaat te hebben om afzonderlijk te downloaden. 59 00:03:51,940 --> 00:03:55,460 Op een Mac kun je gewoon standaard gebruik Terminal of u kunt downloaden iTerm2, 60 00:03:55,460 --> 00:03:58,490 die is als een mooie, chique Terminal. 61 00:03:58,490 --> 00:04:03,780 Als je naar manual.cs50.net zie je een link naar Notepad + +, 62 00:04:03,780 --> 00:04:07,120 dat is wat u kunt gebruiken op een pc. 63 00:04:07,120 --> 00:04:13,340 Hiermee kunt u SFTP van Notepad + +, die in feite SSH. 64 00:04:13,340 --> 00:04:17,750 Wat dit zal u laten doen is lokaal bewerken van uw bestanden, 65 00:04:17,750 --> 00:04:20,670 en dan wanneer u maar wilt om hen te redden, zal het op te slaan in nice.fas, 66 00:04:20,670 --> 00:04:23,670 waar u kunt dan lopen ze. 67 00:04:23,670 --> 00:04:26,880 En het equivalent op een Mac gaat worden TextWrangler. 68 00:04:26,880 --> 00:04:28,760 Dus het laat je hetzelfde doen. 69 00:04:28,760 --> 00:04:32,800 Het laat je lokaal bewerken bestanden en sla deze op nice.fas, 70 00:04:32,800 --> 00:04:35,730 waar u kunt dan lopen ze. 71 00:04:35,730 --> 00:04:40,400 Dus als je ooit vast zonder een apparaat, moet u deze opties 72 00:04:40,400 --> 00:04:44,230 om nog te doen uw probleem sets. 73 00:04:44,230 --> 00:04:48,250 Het enige probleem zal zijn dat je niet naar de CS50 bibliotheek 74 00:04:48,250 --> 00:04:51,580 omdat nice.fas heeft geen standaard dat. 75 00:04:51,580 --> 00:04:55,970 U kunt het downloaden van de CS50 bibliotheek - 76 00:04:55,970 --> 00:04:58,470 Ik denk niet dat ik heb dat op dit punt. 77 00:04:58,470 --> 00:05:03,270 U kunt het downloaden van de CS50 bibliotheek en kopieer het naar nice.fas, 78 00:05:03,270 --> 00:05:07,450 of ik denk dat op dit punt hebben we het niet toch meer gebruiken. 79 00:05:07,450 --> 00:05:12,720 Of als we dat doen, dan kunt u voor de tijd die wordt vervangen door een 80 00:05:12,720 --> 00:05:18,480 de implementaties van de functies in de CS50 bibliotheek toch. 81 00:05:18,480 --> 00:05:21,370 Dus dat niet zo'n groot beperking. 82 00:05:21,370 --> 00:05:23,710 En dat is dat. 83 00:05:26,460 --> 00:05:29,820 >> Ik ga nu terug naar het apparaat, we zullen alles doen wat in het apparaat. 84 00:05:29,820 --> 00:05:37,510 Als we kijken naar onze rubriek vragen, in het begin, zoals ik al zei in mijn e-mail, 85 00:05:37,510 --> 00:05:43,620 We moeten praten over de ene korte je moest kijken. 86 00:05:43,620 --> 00:05:51,980 We hebben de heroriëntatie & Buizen en deze drie vragen. 87 00:05:51,980 --> 00:05:56,070 >> Om die stroom niet functioneert als printf schrijven standaard? 88 00:05:56,070 --> 00:05:59,130 Dus stroom. Wat is een stream? 89 00:06:06,520 --> 00:06:15,100 Een stroom is in principe net als het is gewoon een aantal - 90 00:06:15,100 --> 00:06:21,450 Het is niet eens een bron van 1s en 0s. 91 00:06:21,450 --> 00:06:24,920 De stroom het om vraagt ​​is hier standaard uit. 92 00:06:24,920 --> 00:06:27,250 En zo standaard out is een stroom die bij het schrijven van het, 93 00:06:27,250 --> 00:06:30,940 het op het scherm. 94 00:06:30,940 --> 00:06:36,860 Standaard uit, door stroom, betekent dit dat je gewoon schrijven 1s en 0s aan, 95 00:06:36,860 --> 00:06:40,220 en het andere uiteinde van standard leest alleen van die stroom. 96 00:06:40,220 --> 00:06:43,540 Het is gewoon een reeks van 1s en 0s. 97 00:06:43,540 --> 00:06:45,570 U kunt schrijven naar streams of je kunt lezen uit beken 98 00:06:45,570 --> 00:06:47,950 afhankelijk van de stroom in werkelijkheid is. 99 00:06:47,950 --> 00:06:52,800 De andere twee standaard streams zijn standaard in en standaard fout. 100 00:06:52,800 --> 00:06:57,540 Standaard in is wanneer u getString, is het voor u klaar voor het invoeren van spullen. 101 00:06:57,540 --> 00:07:01,570 Dus het wachten op je, het is eigenlijk te wachten op standaard in, 102 00:07:01,570 --> 00:07:04,880 dat is echt wat je krijgt als je typt op het toetsenbord. 103 00:07:04,880 --> 00:07:07,530 Je typt in een standaard inch 104 00:07:07,530 --> 00:07:10,050 De standaardfout is in principe gelijk aan standaard uit, 105 00:07:10,050 --> 00:07:13,280 maar het is gespecialiseerd in dat wanneer u afdrukt naar standaardfout, 106 00:07:13,280 --> 00:07:16,770 je moet alleen foutmeldingen af ​​te drukken die 107 00:07:16,770 --> 00:07:20,200 dus je kunt onderscheid maken tussen gewone berichten naar het scherm 108 00:07:20,200 --> 00:07:24,560 versus foutmeldingen, afhankelijk van het feit of ze gingen naar standaard uit of standaard fout. 109 00:07:24,560 --> 00:07:28,660 Bestanden ook. 110 00:07:28,660 --> 00:07:32,440 Standaard uit, standaard in, en standaardfout zijn gewoon speciale streams, 111 00:07:32,440 --> 00:07:36,810 maar echt een bestand, wanneer u een bestand opent, wordt het een stroom van bytes 112 00:07:36,810 --> 00:07:40,740 waar je kunt gewoon lezen van die stroom. 113 00:07:40,740 --> 00:07:47,770 U, voor het grootste deel kunnen denk van een bestand als een stroom bytes. 114 00:07:47,770 --> 00:07:51,190 Dus wat streams ze schrijven naar standaard? Standaard uit. 115 00:07:51,190 --> 00:07:56,980 >> Wat is het verschil tussen> en >>? 116 00:07:58,140 --> 00:08:03,710 Heeft iemand op voorhand kijken naar de video? Oke. 117 00:08:03,710 --> 00:08:10,960 > Gaat worden hoe je stuurt in bestanden, 118 00:08:10,960 --> 00:08:15,240 en >> gaat ook om output te sturen naar bestanden, 119 00:08:15,240 --> 00:08:17,820 maar het in plaats daarvan zal toevoegen aan het bestand. 120 00:08:17,820 --> 00:08:23,430 Bijvoorbeeld, laten we zeggen dat ik toevallig aan dict hebben hier, 121 00:08:23,430 --> 00:08:27,020 en de enige dingen binnenkant van dict is kat, kat, hond, vis, hond. 122 00:08:27,020 --> 00:08:31,530 Een opdracht die u op de opdrachtregel is kat, 123 00:08:31,530 --> 00:08:34,539 dat is gewoon om af te drukken wat er in een bestand. 124 00:08:34,539 --> 00:08:40,679 Dus als ik kat dict zeggen, gaat het aan de kat, kat, hond, vis, hond af te drukken. Dat is alles wat kat doet. 125 00:08:40,679 --> 00:08:46,280 Dat betekent dat het afgedrukt op standaard uit kat, kat, hond, vis, hond. 126 00:08:46,280 --> 00:08:53,240 Als ik in plaats daarvan wil die omleiden naar een bestand, kan ik> en deze om te buigen naar wat het bestand is. 127 00:08:53,240 --> 00:08:56,460 Ik bel het bestand bestand. 128 00:08:56,460 --> 00:09:00,320 Dus als ik nu ls, zal ik zien dat ik heb een nieuw bestand genaamd bestand. 129 00:09:00,320 --> 00:09:05,700 En als ik open it up, gaat het om precies wat knuppel in op de opdrachtregel. 130 00:09:05,700 --> 00:09:11,040 Dus nu als ik dat doe dat nog eens, dan gaat de output omleiden in het dossier, 131 00:09:11,040 --> 00:09:13,930 en ik ga precies hetzelfde hebben. 132 00:09:13,930 --> 00:09:17,910 Dus technisch gezien, het volledig laten voorgaan wat we hadden. 133 00:09:17,910 --> 00:09:22,970 En we zullen zien of ik veranderen dict, ik haalde hond. 134 00:09:22,970 --> 00:09:29,980 Als we nu cat dict in bestand opnieuw, we gaan naar de nieuwe versie met hond laten verwijderen. 135 00:09:29,980 --> 00:09:32,400 Dus het overschrijft volledig het. 136 00:09:32,400 --> 00:09:36,640 In plaats daarvan, als we >>, het gaat om het bestand toe te voegen. 137 00:09:36,640 --> 00:09:40,860 Nu, het openen van bestanden, dan zien we dat we hebben net twee keer hetzelfde afgedrukt 138 00:09:40,860 --> 00:09:44,920 want het was daar een keer, dan zijn we gehecht aan de minuut. 139 00:09:44,920 --> 00:09:48,130 Dus dat is wat> en >> doen. 140 00:09:48,130 --> 00:09:50,580 Heeft de volgende vragen - Het maakt niet vragen. 141 00:09:50,580 --> 00:09:59,050 >> De andere die we hebben is <, die, indien> redirects standaard uit, 142 00:09:59,050 --> 00:10:01,970 00:10:12,050 Laten we eens kijken of we een voorbeeld. 144 00:10:14,750 --> 00:10:16,930 Ik kan een heel snel. 145 00:10:17,870 --> 00:10:25,700 Laten we eens een bestand, hello.c. 146 00:10:56,060 --> 00:10:59,070 Relatief eenvoudig dossier. 147 00:10:59,070 --> 00:11:03,570 Ik ben net een string en dan af te drukken "Hello" wat de string ik zojuist was. 148 00:11:03,570 --> 00:11:07,990 Zorg er dus voor hallo en dan. / Hello. 149 00:11:07,990 --> 00:11:10,720 Nu is het gevraagd dat ik iets in te voeren, 150 00:11:10,720 --> 00:11:15,070 wat betekent dat het wacht op de dingen die zal worden aangegaan standaard inch 151 00:11:15,070 --> 00:11:20,450 Dus voer wat ik wil in een standaard inch We zijn net gaan zeggen Hallo, Rob! 152 00:11:20,450 --> 00:11:23,310 Dan is het af te drukken naar standaard uit Hallo, Rob! 153 00:11:23,310 --> 00:11:28,860 Als ik dat doe. / Hello en dan redirect, 154 00:11:30,740 --> 00:11:34,310 voor nu kunt u alleen doorschakelen vanaf een bestand. 155 00:11:34,310 --> 00:11:41,720 Dus als ik in een bestand, txt, en ik Rob, 156 00:11:41,720 --> 00:11:52,300 als ik hallo rennen en dan redirect het bestand txt naar. / hallo, gaat het om hallo te zeggen, Rob! onmiddellijk. 157 00:11:52,300 --> 00:11:57,160 Wanneer het wordt als eerste GetString en het is wachten op standaard in, 158 00:11:57,160 --> 00:12:01,730 standaard niet langer wachten op het toetsenbord data te krijgen ingevoerd. 159 00:12:01,730 --> 00:12:05,980 In plaats daarvan hebben we doorgestuurd standaard in te lezen uit het bestand txt. 160 00:12:05,980 --> 00:12:10,290 En dus het gaat om te lezen uit het bestand txt, dat is net de lijn Rob, 161 00:12:10,290 --> 00:12:13,380 en dan het zal Hallo, Rob printen! 162 00:12:13,380 --> 00:12:18,180 En als ik wilde, kon ik ook doen. / Hello 00:12:21,500 en dan de standaard uit dat het printen, die Hallo is, Rob!, 164 00:12:21,500 --> 00:12:24,700 Ik kan omleiden die in zijn eigen bestand. 165 00:12:24,700 --> 00:12:29,790 Ik bel het bestand hello - nee, dat doe ik niet, want dat is het uitvoerbare - txt2. 166 00:12:29,790 --> 00:12:40,150 Nu, txt2 gaat om de output van. / Hello 00:12:43,520 >> Vragen? 168 00:12:45,900 --> 00:12:49,090 >> Oke. Dus dan hebben we hier pijplijn. 169 00:12:49,090 --> 00:12:53,510 Buizen zijn de laatste eenheid van omleiding. 170 00:12:53,510 --> 00:12:58,750 >> Oh. Ik denk dat een extra eenheid omleiding is als in plaats van> je doet 2>, 171 00:12:58,750 --> 00:13:01,070 dat is omgeleid standaardfout. 172 00:13:01,070 --> 00:13:06,280 Dus als er iets ging naar standaardfout, zou het niet komen gebracht txt2. 173 00:13:06,280 --> 00:13:12,480 Maar let op als ik dat doe 2>, dan is het nog steeds afdrukken Hallo, Rob! aan de opdrachtregel 174 00:13:12,480 --> 00:13:18,600 want ik ben alleen omgeleid standaardfout, ik ben niet omgeleid standaard uit. 175 00:13:18,600 --> 00:13:22,210 Standaardfout en standaard uit zijn verschillend. 176 00:13:24,210 --> 00:13:27,080 Als je wilde eigenlijk schrijven standaardfout, 177 00:13:27,080 --> 00:13:35,080 dan kon ik dit veranderen als fprintf naar stderr. 178 00:13:35,080 --> 00:13:37,850 Dus printf, standaard afdrukken op standaard uit. 179 00:13:37,850 --> 00:13:41,720 Als ik handmatig wilt afdrukken naar standaardfout, dan moet ik fprintf gebruiken 180 00:13:41,720 --> 00:13:45,010 en opgeven wat ik wil afdrukken. 181 00:13:45,010 --> 00:13:49,720 Als in plaats daarvan heb ik fprintf stdout, dan is dat in principe gelijk aan printf. 182 00:13:49,720 --> 00:13:55,530 Maar fprintf de standaard fout. 183 00:13:57,790 --> 00:14:03,650 Dus nu, als ik deze te sturen naar txt2, Hallo, Rob! is nog steeds het krijgen afgedrukt op de opdrachtregel 184 00:14:03,650 --> 00:14:08,270 omdat het wordt steeds afgedrukt op standaard fout en ik ben alleen omgeleid standaard uit. 185 00:14:08,270 --> 00:14:16,420 Als ik nu redirect standaardfout, nu is het niet te krijgen gedrukt, en txt2 gaat worden Hallo, Rob! 186 00:14:16,420 --> 00:14:21,910 Dus nu kunt u afdrukken uw werkelijke fouten te standaardfout 187 00:14:21,910 --> 00:14:24,720 en print uw regelmatige berichten naar standaard uit. 188 00:14:24,720 --> 00:14:31,420 En dus als je je programma uit te voeren, kunt u het als. / Hello dit type met de 2> 189 00:14:31,420 --> 00:14:33,800 zodat uw programma gaat normaal lopen, 190 00:14:33,800 --> 00:14:38,400 maar eventuele foutmeldingen die je krijgt kun je later in uw foutenlogboek, 191 00:14:38,400 --> 00:14:44,500 zodat fouten, en dan later kijken en je fouten bestand zal de eventuele fouten die gebeurd is. 192 00:14:45,200 --> 00:14:47,540 >> Vragen? 193 00:14:47,540 --> 00:14:58,070 >> De laatste is pijp, die u kunt bedenken als het nemen van de standaard uit een opdracht 194 00:14:58,070 --> 00:15:01,210 en maakt het de standaard van het volgende commando. 195 00:15:01,210 --> 00:15:05,570 Een voorbeeld is hier echo is een command line ding 196 00:15:05,570 --> 00:15:11,840 dat is gewoon gaan echo alles wat ik als argument. Ik zal niet aanhalingstekens. 197 00:15:11,840 --> 00:15:16,150 Echo blah, blah, blah is gewoon gaan bla, bla, bla af te drukken. 198 00:15:16,150 --> 00:15:20,600 Vroeger, toen ik zei dat ik moest Rob zetten in een txt-bestand 199 00:15:20,600 --> 00:15:28,830 want ik kan alleen txt-bestanden doorsturen, in plaats daarvan, / als ik echo Rob 200 00:15:28,830 --> 00:15:35,520 en dan pijp het in. / hello, dat zal ook hetzelfde doen soort dingen. 201 00:15:35,520 --> 00:15:39,160 Dit is het nemen van de uitvoer van deze opdracht, echo Rob, 202 00:15:39,160 --> 00:15:43,610 en het te gebruiken als input voor. / hello. 203 00:15:44,790 --> 00:15:49,560 U kunt denken aan het als eerste echo Rob redirect naar een bestand 204 00:15:49,560 --> 00:15:54,160 en voer in. / hello dat bestand dat was gewoon uitgevoerd. 205 00:15:54,160 --> 00:15:57,850 Maar het duurt het tijdelijke bestand uit het beeld. 206 00:16:01,890 --> 00:16:04,460 >> Vragen over zeggen? 207 00:16:04,460 --> 00:16:07,150 >> De volgende vraag gaat deze te betrekken. 208 00:16:07,150 --> 00:16:15,310 Wat pijpleiding kan je gebruiken om het aantal unieke namen in een bestand met de naam names.txt vinden? 209 00:16:15,310 --> 00:16:24,160 De commando's gaan we hier willen gebruiken zijn uniek, dus uniq, en dan wc. 210 00:16:24,160 --> 00:16:28,840 U kunt dit doen man uniq om daadwerkelijk te kijken naar wat dat doet, 211 00:16:28,840 --> 00:16:34,840 en het is gewoon naar de aangrenzende bijpassende lijnen filteren van de ingang. 212 00:16:34,840 --> 00:16:40,690 En de mens wc gaat naar de nieuwe regel, woord en bytes voor elk bestand af te drukken. 213 00:16:40,690 --> 00:16:43,760 En de laatste gaan we willen gebruiken is een soort, 214 00:16:43,760 --> 00:16:47,410 die gaat gewoon soort lijnen van txt-bestand. 215 00:16:47,410 --> 00:16:58,080 Als ik een paar txt bestand, names.txt, en het is Rob, Tommy, Joseph, Tommy, Joseph, RJ, Rob, 216 00:16:58,080 --> 00:17:03,910 wat ik hier wil doen is het vinden van het aantal unieke namen in dit bestand. 217 00:17:03,910 --> 00:17:08,750 Dus wat moet het antwoord zijn? >> [Student] 4. >> Ja. 218 00:17:08,750 --> 00:17:13,780 Het moet 4 zijn, omdat Rob, Tommy, Joseph, RJ zijn de enige unieke namen in dit bestand. 219 00:17:13,780 --> 00:17:20,180 De eerste stap, als ik gewoon het aantal woorden op names.txt, 220 00:17:20,180 --> 00:17:24,290 Dit is eigenlijk vertelt me ​​alles. 221 00:17:24,290 --> 00:17:32,560 Dit is eigenlijk afdrukken - laten we eens kijken, man wc - nieuwe regels, woorden en bytes. 222 00:17:32,560 --> 00:17:38,270 Als ik alleen de zorg over lijnen, dan kan ik gewoon doen wc-l names.txt. 223 00:17:41,730 --> 00:17:44,300 Dus dat is stap 1. 224 00:17:44,300 --> 00:17:50,510 Maar ik wil niet wc-l names.txt omdat names.txt net bevat alle namen, 225 00:17:50,510 --> 00:17:54,170 en ik wil om te filteren op alle niet-unieke degenen. 226 00:17:54,170 --> 00:18:01,200 Dus als ik dat doe uniq names.txt, betekent dat niet helemaal geef me wat ik wil 227 00:18:01,200 --> 00:18:03,760 omdat de gedupliceerde namen zijn er nog steeds. 228 00:18:03,760 --> 00:18:07,690 Waarom is dat? Waarom is uniq niet doen wat ik wil? 229 00:18:07,690 --> 00:18:10,500 [Student] De duplicaten zijn niet [onverstaanbaar] >> Ja. 230 00:18:10,500 --> 00:18:16,370 Denk aan de man pagina voor uniq zegt filter aangrenzende overeenkomende regels. 231 00:18:16,370 --> 00:18:19,680 Ze zijn niet aangrenzend, dus het zal niet filteren. 232 00:18:19,680 --> 00:18:31,100 Als ik sorteer ze eerst, wordt sorteren names.txt gaan in elkaar te zetten alle dubbele lijnen. 233 00:18:31,100 --> 00:18:34,450 Dus nu soort names.txt is dat. 234 00:18:34,450 --> 00:18:40,550 Ik ga wil dat gebruiken als input voor Uniq, dat is | uniq. 235 00:18:40,550 --> 00:18:43,390 Dat geeft me Joseph, RJ, Rob, Tommy, 236 00:18:43,390 --> 00:18:49,260 en ik wil dat gebruiken als input voor wc-l, 237 00:18:49,260 --> 00:18:52,740 die zal mij 4. 238 00:18:52,740 --> 00:18:56,930 Zoals hier staat, kun je wat pijplijn gebruiken? 239 00:18:56,930 --> 00:19:01,390 U kunt dit doen een heleboel dingen zoals het gebruik van een reeks opdrachten 240 00:19:01,390 --> 00:19:05,130 waar u gebruik maken van de output van een commando als invoer voor de volgende opdracht. 241 00:19:05,130 --> 00:19:08,780 U kunt dit doen een heleboel dingen, een hoop slimme dingen. 242 00:19:08,780 --> 00:19:11,440 >> Vragen? 243 00:19:12,910 --> 00:19:14,600 Oke. 244 00:19:14,600 --> 00:19:17,880 Dat is het voor pipes en redirection. 245 00:19:18,370 --> 00:19:24,090 >> Nu gaan we door naar de eigenlijke dingen, de codering spul. 246 00:19:24,090 --> 00:19:29,100 Binnenkant van deze PDF, zie je deze opdracht, 247 00:19:29,100 --> 00:19:32,950 en je wilt deze opdracht uit te voeren in uw apparaat. 248 00:19:36,240 --> 00:19:42,250 wget is de opdracht voor net iets van het internet, in principe, 249 00:19:42,250 --> 00:19:45,180 dus wget en deze URL. 250 00:19:45,180 --> 00:19:49,110 Als je naar deze URL in je browser, zou het downloaden dat bestand. 251 00:19:49,110 --> 00:19:52,510 Ik klikte op, dus het het bestand heeft gedownload voor mij. 252 00:19:52,510 --> 00:19:55,650 Maar het schrijven van wget van dat ding in de terminal 253 00:19:55,650 --> 00:19:58,620 is gewoon om het te downloaden naar uw toestel. 254 00:19:58,620 --> 00:20:02,750 Ik heb section5.zip, en je wilt section5.zip unzip, 255 00:20:02,750 --> 00:20:06,520 die zal u een map met de naam section5, 256 00:20:06,520 --> 00:20:11,550 die gaat naar alle bestanden gaan we gebruiken vandaag de dag binnen van het hebben. 257 00:20:33,380 --> 00:20:37,710 Omdat deze programma's 'bestand namen al aangeven, ze zijn een beetje buggy, 258 00:20:37,710 --> 00:20:40,990 dus je missie is om erachter te komen waarom het gebruik van gdb. 259 00:20:40,990 --> 00:20:44,560 Heeft iedereen hebben ze gedownload / weet hoe je ze gedownload 260 00:20:44,560 --> 00:20:47,480 in hun apparaat? Oke. 261 00:20:47,480 --> 00:20:56,400 >> Running ./buggy1 zal het zeggen Segmentation fault (core dumped), 262 00:20:56,400 --> 00:21:00,500 die elke keer krijg je een segfault, het is een slechte zaak. 263 00:21:00,500 --> 00:21:03,810 Onder welke omstandigheden krijg je een segfault? 264 00:21:03,810 --> 00:21:08,210 [Student] dereferentie een null pointer. >> Ja. Dat is een voorbeeld. 265 00:21:08,210 --> 00:21:11,580 Dereferentie een null pointer je gaat een segfault te krijgen. 266 00:21:11,580 --> 00:21:16,720 Wat een segfault betekent is dat je geheugen te raken moet je niet aanraken. 267 00:21:16,720 --> 00:21:21,350 Dus dereferentie een null pointer is ontroerend adres 0, 268 00:21:21,350 --> 00:21:28,060 en eigenlijk, alle computers tegenwoordig zeggen dat adres 0 is het geheugen moet je niet aanraken. 269 00:21:28,060 --> 00:21:31,920 Dus dat is waarom dereferentie een null pointer resulteert in een segfault. 270 00:21:31,920 --> 00:21:37,210 Als je toevallig niet initialiseren een pointer, dan heeft het een vuilnis waarde, 271 00:21:37,210 --> 00:21:41,520 en dus wanneer u probeert om dereferentie het, naar alle waarschijnlijkheid je raakt het geheugen 272 00:21:41,520 --> 00:21:43,540 dat is in het midden van nergens. 273 00:21:43,540 --> 00:21:45,650 Als je toevallig je geluk en het vuilnis waarde 274 00:21:45,650 --> 00:21:48,440 toevallig ergens wijzen op op de stapel of iets, 275 00:21:48,440 --> 00:21:50,820 dan wanneer je dereference die aanwijzing die u niet hebt geïnitialiseerd, 276 00:21:50,820 --> 00:21:52,730 er zal niets mis gaan. 277 00:21:52,730 --> 00:21:55,480 Maar als het te wijzen op, laten we zeggen, ergens tussen de stack en de heap, 278 00:21:55,480 --> 00:21:59,850 of het is te wijzen alleen maar om ergens dat niet is gebruikt door uw programma nog niet, 279 00:21:59,850 --> 00:22:02,240 dan ben je aanraken geheugen moet je niet aanraken en je segfault. 280 00:22:02,240 --> 00:22:06,370 Als je schrijft een recursieve functie en het recurses te vaak 281 00:22:06,370 --> 00:22:08,720 en je stack te groot wordt en de stapel botst tegen dingen 282 00:22:08,720 --> 00:22:12,270 dat het niet moet worden botsing met, je raakt het geheugen moet je niet aanraken, 283 00:22:12,270 --> 00:22:14,810 dus je segfault. 284 00:22:14,810 --> 00:22:17,010 Dat is wat een segfault is. 285 00:22:17,010 --> 00:22:21,810 >> Het is ook dezelfde reden dat als je een string als - 286 00:22:21,810 --> 00:22:23,930 laten we terug gaan naar het vorige programma. 287 00:22:23,930 --> 00:22:28,530 In hello.c--Ik ben gewoon naar iets anders te maken. 288 00:22:28,530 --> 00:22:33,770 char * s = "hello world!"; 289 00:22:33,770 --> 00:22:42,310 Als ik * s = iets of s [0] = 'X'; 290 00:22:42,310 --> 00:22:47,290 dus zorg hallo,. / hello, waarom dat segfault? 291 00:22:48,410 --> 00:22:51,250 Waarom is dit segfault? 292 00:22:55,660 --> 00:22:57,890 Wat zou je verwachten dat er gebeurt? 293 00:22:57,890 --> 00:23:06,640 Als ik dat deed printf ("% s \ n", s); wat zou je verwachten dat moet worden afgedrukt? 294 00:23:06,640 --> 00:23:09,930 [Student] X hello. >> Ja. 295 00:23:09,930 --> 00:23:15,140 Het probleem is dat wanneer je verklaart een string als deze, 296 00:23:15,140 --> 00:23:18,190 s is een pointer die gaat naar de stapel, 297 00:23:18,190 --> 00:23:25,880 s en wat wijst naar Hierdoor string die is opgenomen in leesgeheugen. 298 00:23:25,880 --> 00:23:30,560 Dus gewoon door de naam, alleen-lezen geheugen, moet je op het idee 299 00:23:30,560 --> 00:23:33,010 dat als je probeert te veranderen wat daar in alleen-lezen geheugen, 300 00:23:33,010 --> 00:23:36,670 je doet iets wat je niet zou moeten doen met het geheugen en u segfault. 301 00:23:36,670 --> 00:23:45,360 Dit is eigenlijk een groot verschil tussen char * s en char s []. 302 00:23:45,360 --> 00:23:48,790 Dus char s [], nu deze string zal worden op de stapel gelegd, 303 00:23:48,790 --> 00:23:53,960 en de stack is niet alleen-lezen, wat betekent dat dit zou moeten werken prima. 304 00:23:55,500 --> 00:23:57,370 En het doet. 305 00:23:57,370 --> 00:24:06,250 Vergeet niet dat als ik dat doe char * s = "hello world!", S zelf is op de stapel 306 00:24:06,250 --> 00:24:10,390 maar s punten ergens anders, en dat ergens anders gebeurt er als alleen-lezen. 307 00:24:10,390 --> 00:24:15,640 Maar char s [] is gewoon iets op de stapel. 308 00:24:17,560 --> 00:24:21,760 Dus dat is een ander voorbeeld van een segfault gebeurt. 309 00:24:21,760 --> 00:24:27,820 >> We zagen dat ./buggy1 resulteerde in een segfault. 310 00:24:27,820 --> 00:24:31,810 In theorie zou je niet meteen kijken buggy1.c. 311 00:24:31,810 --> 00:24:35,170 In plaats daarvan zullen we kijken naar het door gdb. 312 00:24:35,170 --> 00:24:37,750 Merk op dat als je Segmentation fault (core dumped), 313 00:24:37,750 --> 00:24:40,850 krijg je dit bestand dan hier de naam kern. 314 00:24:40,850 --> 00:24:45,200 Als we ls-l, zullen we zien dat kern is meestal een vrij groot bestand. 315 00:24:45,200 --> 00:24:51,580 Dit is het aantal bytes van het bestand, zodat het lijkt alsof het is 250-iets kilobytes. 316 00:24:51,580 --> 00:24:56,120 De reden hiervoor is dat hetgeen de kern is dump 317 00:24:56,120 --> 00:25:01,410 is wanneer uw programma vastloopt, de toestand van het geheugen van uw programma 318 00:25:01,410 --> 00:25:05,230 gewoon wordt gekopieerd en geplakt in dit bestand. 319 00:25:05,230 --> 00:25:07,270 Het wordt gedumpt in dat bestand. 320 00:25:07,270 --> 00:25:13,060 Dit programma, dat deze actief is, is er gebeurd met een geheugengebruik van ongeveer 250 kilobytes hebben, 321 00:25:13,060 --> 00:25:17,040 en dus dat is wat gedumpt in dit bestand. 322 00:25:17,040 --> 00:25:23,630 Nu kun je kijken naar dat bestand als we gdb buggy1 kern. 323 00:25:23,630 --> 00:25:30,130 We kunnen gewoon doen gdb buggy1, en dat zal gewoon opstarten gdb regelmatig, 324 00:25:30,130 --> 00:25:33,800 met behulp van buggy1 als zijn invoerbestand. 325 00:25:33,800 --> 00:25:38,260 Maar als je gdb buggy1 kern, dan is het specifiek gaat om het opstarten van gdb 326 00:25:38,260 --> 00:25:40,330 door te kijken naar die kern-bestand. 327 00:25:40,330 --> 00:25:45,560 En zeg je buggy1 betekent gdb weet dat die kern-bestand afkomstig is van de buggy1 programma. 328 00:25:45,560 --> 00:25:49,580 Dus gdb buggy1 kern gaat direct brengen ons 329 00:25:49,580 --> 00:25:52,060 naar de plaats waar het programma is er gebeurd met beëindigen. 330 00:25:57,720 --> 00:26:02,340 We zien hier Programma beëindigd met signaal 11, Segmentation fault. 331 00:26:02,340 --> 00:26:10,110 We toevallig een lijn van vergadering, die waarschijnlijk niet erg behulpzaam zien. 332 00:26:10,110 --> 00:26:15,360 Maar als je typt bt of backtrace, dat gaat om de functie te 333 00:26:15,360 --> 00:26:19,430 dat geeft ons de lijst van onze huidige stack frames. 334 00:26:19,430 --> 00:26:23,150 Dus backtrace. Het lijkt erop dat we maar twee stack frames. 335 00:26:23,150 --> 00:26:26,310 De eerste is onze belangrijkste stack frame, 336 00:26:26,310 --> 00:26:29,810 en de tweede is de stack frame deze functie die we toevallig in, 337 00:26:29,810 --> 00:26:34,440 die eruit ziet als we alleen de assemblage-code voor hebben. 338 00:26:34,440 --> 00:26:38,050 Dus laten we terug gaan naar onze belangrijkste functie, 339 00:26:38,050 --> 00:26:42,300 en om dat te doen kunnen we gestel 1 doen, en ik denk dat we ook doen beneden, 340 00:26:42,300 --> 00:26:45,160 maar ik bijna nooit naar beneden - of omhoog. Ja. 341 00:26:45,160 --> 00:26:50,710 Op en neer. Up brengt u een stapel frame, naar beneden brengt je in een stack frame. 342 00:26:50,710 --> 00:26:53,240 Ik heb de neiging om nooit gebruiken. 343 00:26:53,240 --> 00:26:59,120 Ik specifiek zeggen frame 1, dat naar het frame met 1. 344 00:26:59,120 --> 00:27:01,750 Frame 1 gaat ons in grote stack frame, 345 00:27:01,750 --> 00:27:05,570 en het zegt hier de lijn van code die we toevallig op. 346 00:27:05,570 --> 00:27:07,950 Als we wilden een paar regels code, kunnen we zeggen lijst, 347 00:27:07,950 --> 00:27:11,280 en dat gaat ons alle regels code eromheen. 348 00:27:11,280 --> 00:27:13,360 De lijn die we segfault op was 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 Als het niet voor de hand bent, kun je meteen het krijgen van hier gewoon door te denken waarom het segfault. 351 00:27:24,130 --> 00:27:28,800 Maar we kunnen nog een stap verder en zegt: "Waarom zou argv [1] segfault?" 352 00:27:28,800 --> 00:27:38,830 Let's afdrukken argv [1], en het lijkt alsof het 0x0, dat is de null pointer. 353 00:27:38,830 --> 00:27:44,750 We strcmping CS50 rotsen en nul, en dus dat gaat segfault. 354 00:27:44,750 --> 00:27:48,280 En waarom is argv [1] null? 355 00:27:48,640 --> 00:27:51,280 [Student] Omdat we niet geven elke command-line argumenten. 356 00:27:51,280 --> 00:27:53,390 Ja. We hebben niet geven geen command-line argumenten. 357 00:27:53,390 --> 00:27:58,460 Dus ./buggy1 is alleen maar te hebben argv [0] zijn ./buggy1. 358 00:27:58,460 --> 00:28:02,100 Het gaat niet om een ​​argv [1], zodat dat gaat segfault. 359 00:28:02,100 --> 00:28:07,450 Maar als, in plaats daarvan, ik doe gewoon CS50, het gaat om te zeggen Je krijgt een D 360 00:28:07,450 --> 00:28:09,950 want dat is wat het verondersteld wordt te doen. 361 00:28:09,950 --> 00:28:15,240 Kijkend naar buggy1.c, het is de bedoeling om af te drukken "Je krijgt een D" - 362 00:28:15,240 --> 00:28:20,820 Als argv [1] is niet "CS50 rocks", "Je krijgt een D", anders "Je krijgt een A!" 363 00:28:20,820 --> 00:28:25,660 Dus als we een A willen, moeten we deze te vergelijken als waar, 364 00:28:25,660 --> 00:28:28,710 Dit betekent dat het vergeleken met 0. 365 00:28:28,710 --> 00:28:31,100 Dus argv [1] moet worden "CS50 rocks". 366 00:28:31,100 --> 00:28:35,660 Als u wilt dat te doen op de opdrachtregel, moet u \ te gebruiken om de ruimte te ontsnappen. 367 00:28:35,660 --> 00:28:41,690 Dus CS50 \ rotsen en U krijgt een A! 368 00:28:41,690 --> 00:28:44,060 Als u dit niet doet de backslash, waarom dit niet werkt? 369 00:28:44,060 --> 00:28:47,190 [Student] Het is twee verschillende argumenten. >> Ja. 370 00:28:47,190 --> 00:28:52,540 Argv [1] zal worden CS50, en argv [2] zal worden rotsen. Oke. 371 00:28:52,540 --> 00:28:56,470 >> Nu ./buggy2 gaat weer segfault. 372 00:28:56,470 --> 00:29:01,880 In plaats van het openen van het met haar core-bestand, zullen we gewoon open buggy2 direct, 373 00:29:01,880 --> 00:29:05,000 dus gdb buggy2. 374 00:29:05,000 --> 00:29:09,590 Als we nu alleen nog maar ons programma, dan is het gaan zeggen Programma ontvangen signaal SIGSEGV, 375 00:29:09,590 --> 00:29:15,530 dat is de segfault signaal, en dit is waar het is gebeurd gebeuren. 376 00:29:15,530 --> 00:29:21,250 Kijkend naar onze backtrace, zien we dat we in de functie oh_no, 377 00:29:21,250 --> 00:29:23,900 die werd genoemd door de functie dinky, die werd genoemd door de functie binky, 378 00:29:23,900 --> 00:29:26,460 die werd genoemd door de belangrijkste. 379 00:29:26,460 --> 00:29:31,680 We zien ook de argumenten voor deze functies. 380 00:29:31,680 --> 00:29:34,680 Het argument voor dinky en Binky was 1. 381 00:29:34,680 --> 00:29:44,390 Als we een lijst van de functie oh_no, zien we dat oh_no is gewoon char ** s = NULL doen; 382 00:29:44,390 --> 00:29:47,410 * S = "BOOM"; 383 00:29:47,410 --> 00:29:50,330 Waarom zou dat niet? 384 00:29:54,330 --> 00:29:58,380 [Student] U kunt niet dereference de null pointer? >> Ja. 385 00:29:58,380 --> 00:30:06,090 Dit wordt alleen maar zeggen s NULL is, ongeacht of die toevallig een char **, 386 00:30:06,090 --> 00:30:12,070 die, afhankelijk van hoe je interpreteren, kan het een pointer naar een pointer naar een string 387 00:30:12,070 --> 00:30:15,550 of een array van strings. 388 00:30:15,550 --> 00:30:21,430 Het is s NULL is, dus * s is dereferentie een null pointer, 389 00:30:21,430 --> 00:30:24,800 en dus dit gaat crashen. 390 00:30:24,800 --> 00:30:27,540 Dit is een van de snelste manieren kunt u eventueel segfault. 391 00:30:27,540 --> 00:30:31,300 Het is gewoon waarbij een null pointer en onmiddellijk segfaulting. 392 00:30:31,300 --> 00:30:34,570 Dat is wat oh_no doet. 393 00:30:34,570 --> 00:30:43,400 Als we samen een frame, dan zijn we van plan om in de functie die oh_no genoemd. 394 00:30:43,400 --> 00:30:44,830 Ik moet naar beneden doen. 395 00:30:44,830 --> 00:30:48,610 Als u geen een opdracht en je gewoon op ENTER drukt, 396 00:30:48,610 --> 00:30:52,350 zal het gewoon herhaalt u de vorige opdracht die u liep. 397 00:30:52,350 --> 00:30:56,610 We zijn in frame 1. 398 00:30:56,610 --> 00:31:04,650 Aankondiging Dit frame, we hier zien is onze functie. 399 00:31:04,650 --> 00:31:08,520 U kunt weer hit list, of u kunt de lijst 20 doen en het zal een lijst van meer. 400 00:31:08,520 --> 00:31:13,640 De functie dinky zegt dat als i 1 is, ga dan naar de oh_no functie, 401 00:31:13,640 --> 00:31:15,960 anders heen te gaan naar de slinky functie. 402 00:31:15,960 --> 00:31:18,700 En we weten i is 1, omdat we toevallig zie hierboven 403 00:31:18,700 --> 00:31:22,560 dat dinky werd aangeroepen met het argument 1. 404 00:31:22,560 --> 00:31:27,560 Of je kunt gewoon printen i en het zal zeggen dat ik: 1. 405 00:31:27,560 --> 00:31:33,770 We zijn momenteel in dinky, en als we gaan een ander frame, we weten dat we eindigen in binky. 406 00:31:33,770 --> 00:31:36,600 Up. Nu zijn we in binky. 407 00:31:36,600 --> 00:31:41,340 Notering van deze functie - de lijst van voor de rust sneed me af - 408 00:31:41,340 --> 00:31:52,670 het begon als i 0, dan gaan we noemen het oh_no, anders dinky noemen. 409 00:31:52,670 --> 00:31:57,000 We weten dat ik was 1, dus het heet dinky. 410 00:31:57,000 --> 00:32:05,030 En nu zijn we terug in de belangrijkste, en de belangrijkste is gewoon gaat worden int i = rand ()% 3; 411 00:32:05,030 --> 00:32:08,790 Dat is gewoon om u een willekeurig nummer dat is 0, 1, of 2. 412 00:32:08,790 --> 00:32:12,780 Het gaat om binky gesprek met dat nummer, en het zal terugkeren 0. 413 00:32:12,780 --> 00:32:16,700 Kijkend naar deze, 414 00:32:16,700 --> 00:32:19,880 gewoon wandelen door het programma handmatig zonder stromend onmiddellijk, 415 00:32:19,880 --> 00:32:25,400 je zou een breekpunt ingesteld op de belangrijkste, wat betekent dat wanneer we het programma te starten 416 00:32:25,400 --> 00:32:31,020 uw programma loopt totdat het een breekpunt. 417 00:32:31,020 --> 00:32:35,450 Dus het uitvoeren van het programma, zal het uit te voeren en dan zal de belangrijkste functie raken en stoppen. 418 00:32:35,450 --> 00:32:44,700 Nu we binnen van de belangrijkste, en stap of naast ons gaat brengen naar de volgende regel code. 419 00:32:44,700 --> 00:32:47,050 U kunt dit doen stap of het volgende. 420 00:32:47,050 --> 00:32:51,800 Volgende Slaan, nu heb ik is ingesteld op rand ()% 3, dus we kunnen de waarde van i te drukken, 421 00:32:51,800 --> 00:32:55,280 en het zal zeggen dat ik: 1. 422 00:32:55,280 --> 00:32:58,110 Nu is het er wel toe doet of we volgende of stap te gebruiken. 423 00:32:58,110 --> 00:33:01,000 Ik denk dat het ertoe deed in de vorige, maar we zouden willen naar de volgende te gebruiken. 424 00:33:01,000 --> 00:33:06,000 Als we stap, stappen we in de functie, wat betekent kijken naar de werkelijke ding 425 00:33:06,000 --> 00:33:07,940 wat er gebeurt binnenkant van Binky. 426 00:33:07,940 --> 00:33:10,510 Als we de volgende, dan betekent dit gaan over de functie 427 00:33:10,510 --> 00:33:14,070 en ga je gewoon naar de volgende regel code op de hoofd-functie. 428 00:33:14,070 --> 00:33:17,900 Hier op deze lijn, was ik op waar het zei rand ()% 3; 429 00:33:17,900 --> 00:33:21,320 als ik dat deed stap, zou het gaan in de uitvoering van de rand 430 00:33:21,320 --> 00:33:25,110 en kijken naar wat er daar gebeurt, en ik kon gaan door de rand-functie. 431 00:33:25,110 --> 00:33:26,920 Maar kan me niet schelen over de rand functie. 432 00:33:26,920 --> 00:33:30,190 Ik wil gewoon naar de volgende regel code te gaan in de belangrijkste, dus ik gebruik volgende. 433 00:33:30,190 --> 00:33:35,800 Maar nu doe ik de zorg over de binky functie, dus ik wil om de stap naar dat. 434 00:33:35,800 --> 00:33:37,730 Nu ben ik in binky. 435 00:33:37,730 --> 00:33:42,040 De eerste regel van de code gaat zeggen indien (i == 0), neem ik een stap, 436 00:33:42,040 --> 00:33:44,930 we zien dat we terecht bij dinky. 437 00:33:44,930 --> 00:33:51,620 Als we de lijst dingen, zien we dat het gecontroleerd is i = 0. 438 00:33:51,620 --> 00:33:55,470 i is gelijk aan 0, zodat het naar de andere toestand, 439 00:33:55,470 --> 00:33:59,540 die zal dinky (i) te bellen. 440 00:33:59,540 --> 00:34:04,030 Je zou in de war raken. 441 00:34:04,030 --> 00:34:07,380 Als je gewoon rechtstreeks naar deze lijnen, zou je denken als (i == 0), 442 00:34:07,380 --> 00:34:10,800 oke, dan nam ik een stap en nu ben ik bij dinky (i), 443 00:34:10,800 --> 00:34:14,120 je zou denken dat moet betekenen i = 0 of zoiets. 444 00:34:14,120 --> 00:34:18,980 Nee, het betekent gewoon dat het weet dat het kan direct vasthouden aan de lijn dinky (i). 445 00:34:18,980 --> 00:34:23,300 Omdat i niet 0 is, wordt de volgende stap niet eindigen bij de andere. 446 00:34:23,300 --> 00:34:26,239 Else is niet een lijn het gaat om te stoppen bij. 447 00:34:26,239 --> 00:34:31,570 Het zal alleen maar om naar de volgende regel kan daadwerkelijk uit te voeren, dat is dinky (i). 448 00:34:31,570 --> 00:34:36,090 Stap in dinky (i), zien we als (i == 1). 449 00:34:36,090 --> 00:34:42,670 We weten i = 1, dus toen we stappen, we weten dat we gaan eindigen in oh_no 450 00:34:42,670 --> 00:34:46,489 omdat i = 1 roept de functie oh_no, die u kunt stap in, 451 00:34:46,489 --> 00:34:52,969 die gaat om char ** s = onmiddellijk NULL en "BOOM". 452 00:34:54,270 --> 00:34:59,690 En vervolgens daadwerkelijk te kijken naar de uitvoering van buggy2, 453 00:34:59,690 --> 00:35:04,590 dit wordt ik net een willekeurig getal - 0, 1, of 2 - bellen binky, 454 00:35:04,590 --> 00:35:10,610 die, indien i 0 het noemt oh_no, anders dinky noemt, die komt hier. 455 00:35:10,610 --> 00:35:18,100 Als ik 1 is, bellen oh_no, anders bellen slinky, die hier komen, 456 00:35:18,100 --> 00:35:20,460 als ik 2 is, bel oh_no. 457 00:35:20,460 --> 00:35:24,720 Ik weet niet eens dat er een manier - 458 00:35:24,720 --> 00:35:30,030 Ziet iemand een manier om dit een programma dat niet zal segfault? 459 00:35:30,030 --> 00:35:37,530 Omdat tenzij ik mis iets, als ik gelijk is aan 0, dan heb je meteen segfault, 460 00:35:37,530 --> 00:35:41,250 anders ga je naar een functie die als ik is 1 segfault u, 461 00:35:41,250 --> 00:35:44,540 anders ga je naar een functie waar als ik is 2 u segfault. 462 00:35:44,540 --> 00:35:46,810 Dus niet uit wat je doet, je segfault. 463 00:35:46,810 --> 00:35:52,380 >> Ik denk dat een manier om hem vast te zetten zou zijn in plaats van het doen van char ** s = NULL, 464 00:35:52,380 --> 00:35:55,610 je zou kunnen malloc ruimte voor die string. 465 00:35:55,610 --> 00:36:04,230 We konden doen malloc (sizeof) - sizeof wat? 466 00:36:09,910 --> 00:36:15,190 [Student] (char) * 5? >> Lijkt dit toch? 467 00:36:15,190 --> 00:36:21,060 Ik neem aan dat dit zal werken als ik eigenlijk liep, maar het is niet wat ik zoek. 468 00:36:24,400 --> 00:36:32,940 Kijk naar de aard van de s. We voegen int *, dus int * x. 469 00:36:32,940 --> 00:36:35,600 Ik zou doen malloc (sizeof (int)). 470 00:36:35,600 --> 00:36:40,490 Of als ik een blok van 5 wilde, zou ik doen (sizeof (int) * 5); 471 00:36:40,490 --> 00:36:44,210 Wat als ik een int ** hebben? 472 00:36:46,260 --> 00:36:49,140 Wat zou ik malloc? 473 00:36:49,140 --> 00:36:53,510 [Student] Grootte van de aanwijzer. >> Ja. (Sizeof (int *)); 474 00:36:53,510 --> 00:36:56,960 Hetzelfde hier beneden. 475 00:36:56,960 --> 00:37:01,280 Ik wil (sizeof (char *)); 476 00:37:06,170 --> 00:37:12,840 Dit gaat de ruimte toe te wijzen voor de pointer die wijst naar "BOOM". 477 00:37:12,840 --> 00:37:15,330 Ik hoef niet om ruimte toe te wijzen voor "BOOM" zelf 478 00:37:15,330 --> 00:37:17,210 want dit is eigenlijk gelijk aan wat ik al eerder zei 479 00:37:17,210 --> 00:37:20,870 van char * x = "BOOM". 480 00:37:20,870 --> 00:37:27,950 "BOOM" bestaat reeds. Het gebeurt bestaan ​​in het alleen-lezen gebied van geheugen. 481 00:37:27,950 --> 00:37:35,200 Maar het bestaat al, wat betekent dat deze regel code, als s een char **, 482 00:37:35,200 --> 00:37:43,900 dan * s is een char * en je bent het instellen van deze char * om te wijzen op "BOOM". 483 00:37:43,900 --> 00:37:50,040 Als ik wilde "BOOM" in s te kopiëren, dan zou ik moeten ruimte s toe te wijzen. 484 00:37:55,170 --> 00:38:03,900 Ik doe * s = malloc (sizeof (char) * 5); 485 00:38:03,900 --> 00:38:06,210 Waarom 5? 486 00:38:06,210 --> 00:38:10,860 Waarom niet 4? Het ziet eruit als "BOOM" is 4 karakters. >> [Student] De nul karakter. 487 00:38:10,860 --> 00:38:14,580 Ja. Al uw snaren gaan naar de nul-karakter nodig hebben. 488 00:38:14,580 --> 00:38:23,590 Nu kan ik iets doen als strcat - Wat is de functie voor het kopiëren van een string? 489 00:38:23,590 --> 00:38:28,520 [Student] CPY? >> Strcpy. 490 00:38:28,520 --> 00:38:32,700 man strcpy. 491 00:38:36,120 --> 00:38:39,590 Dus strcpy of strncpy. 492 00:38:39,590 --> 00:38:43,410 strncpy is een beetje veiliger, omdat u opgeeft, kan precies hoeveel tekens, 493 00:38:43,410 --> 00:38:46,190 maar hier maakt het niet uit omdat we weten. 494 00:38:46,190 --> 00:38:50,340 Dus strcpy en kijk in de argumenten. 495 00:38:50,340 --> 00:38:53,100 Het eerste argument is onze bestemming. 496 00:38:53,100 --> 00:38:56,770 Het tweede argument is onze bron. 497 00:38:56,770 --> 00:39:10,310 We gaan kopiëren naar onze bestemming * s de aanwijzer "BOOM". 498 00:39:10,310 --> 00:39:19,820 Waarom zou je dit willen doen met een strcpy in plaats van alleen wat we hebben gehad 499 00:39:19,820 --> 00:39:22,800 van * s = "BOOM"? 500 00:39:22,800 --> 00:39:28,630 Er is een reden waarom je zou willen om dit te doen, maar wat is die reden? 501 00:39:28,630 --> 00:39:31,940 [Student] Als je iets wilt veranderen in "BOOM". >> Ja. 502 00:39:31,940 --> 00:39:37,950 Nu kan ik iets als het doen [0] = 'X'; 503 00:39:37,950 --> 00:39:48,190 omdat s wijst op de heap en ruimte op de heap dat is naar wijst 504 00:39:48,190 --> 00:39:52,320 is een pointer naar meer ruimte op de heap, die het opslaan van "BOOM". 505 00:39:52,320 --> 00:39:55,150 Dus dit exemplaar van "BOOM" wordt opgeslagen in de heap. 506 00:39:55,150 --> 00:39:58,780 Er zijn technisch gezien twee exemplaren van "boom" in ons programma. 507 00:39:58,780 --> 00:40:03,500 Daar is het eerste dat is gewoon gegeven door deze "BOOM" string constante, 508 00:40:03,500 --> 00:40:09,250 en het tweede exemplaar van "boom", strcpy creëerde de kopie van "boom". 509 00:40:09,250 --> 00:40:13,100 Maar het exemplaar van "BOOM" wordt opgeslagen op de heap, en de hoop je bent vrij om te veranderen. 510 00:40:13,100 --> 00:40:17,250 De hoop is niet alleen-lezen, dus dat betekent dat s [0] 511 00:40:17,250 --> 00:40:20,500 gaat om u te laten de waarde van "boom". 512 00:40:20,500 --> 00:40:23,130 Het gaat om je te laten veranderen die tekens. 513 00:40:23,130 --> 00:40:26,640 >> Vragen? 514 00:40:27,740 --> 00:40:29,290 Oke. 515 00:40:29,290 --> 00:40:35,500 >> Over te gaan tot buggy3, laten we gdb buggy3. 516 00:40:35,500 --> 00:40:39,840 We draaien en we zien we een segfault. 517 00:40:39,840 --> 00:40:46,550 Als we backtrace zijn er slechts twee functies. 518 00:40:46,550 --> 00:40:52,970 Als we gaan in onze belangrijkste functie, zien we dat we een segfault op deze lijn. 519 00:40:52,970 --> 00:41:00,180 Dus gewoon kijken naar deze lijn, int lijn = 0 voor (; fgets dit spul is niet gelijk aan NULL; 520 00:41:00,180 --> 00:41:03,770 lijn + +). 521 00:41:03,770 --> 00:41:08,010 Onze vorige frame heette _IO_fgets. 522 00:41:08,010 --> 00:41:10,720 Je zult zien dat er veel met ingebouwde C-functies, 523 00:41:10,720 --> 00:41:15,350 dat wanneer u de segfault te krijgen, zal er echt cryptische functienamen 524 00:41:15,350 --> 00:41:18,090 als dit _IO_fgets. 525 00:41:18,090 --> 00:41:21,770 Maar dat gaat hebben betrekking op deze fgets oproep. 526 00:41:21,770 --> 00:41:25,850 Ergens binnen hier, zijn we segfaulting. 527 00:41:25,850 --> 00:41:30,340 Als we kijken naar de argumenten om fgets, kunnen we afdrukken buffer. 528 00:41:30,340 --> 00:41:41,180 Laten we af te drukken als een - Oh, nee. 529 00:41:48,980 --> 00:41:51,900 Print is niet van plan om precies zoals ik het wil werken. 530 00:41:55,460 --> 00:41:58,000 Laten we eens kijken naar de actuele programma. 531 00:42:02,200 --> 00:42:09,640 Buffer is een karakter array. Het is een karakter array van 128 tekens. 532 00:42:09,640 --> 00:42:14,980 Dus als ik zeg afdrukbuffer, het gaat om die 128 tekens af te drukken, 533 00:42:14,980 --> 00:42:18,300 dat ik denk dat is wat er verwacht wordt. 534 00:42:18,300 --> 00:42:21,390 Wat ik was op zoek naar is af te drukken het adres van de buffer, 535 00:42:21,390 --> 00:42:23,680 maar dat betekent niet echt vertellen mij veel. 536 00:42:23,680 --> 00:42:30,770 Dus als ik toevallig zeg hier x buffer, het toont mij 0xbffff090, 537 00:42:30,770 --> 00:42:38,690 die, als je nog van vroeger of een bepaald punt, Oxbffff heeft de neiging om een ​​stack-achtige regio. 538 00:42:38,690 --> 00:42:46,020 De stapel heeft de neiging om ergens beginnen net onder 0xc000. 539 00:42:46,020 --> 00:42:51,890 Alleen al door het zien van dit adres, ik weet dat buffer gebeurt op de stapel. 540 00:42:51,890 --> 00:43:04,500 Opnieuw opstarten van mijn programma, aanloop,, bufferen we zagen was deze opeenvolging van karakters 541 00:43:04,500 --> 00:43:06,530 die zijn vrij veel betekenis. 542 00:43:06,530 --> 00:43:12,270 Dan afdrukken-bestand, wat doet-bestand eruit? 543 00:43:15,120 --> 00:43:17,310 [Student] Null. >> Ja. 544 00:43:17,310 --> 00:43:22,610 Bestand is een van het type FILE *, dus het is een pointer, 545 00:43:22,610 --> 00:43:26,610 en de waarde van die wijzer is null. 546 00:43:26,610 --> 00:43:33,240 Dus fgets gaat proberen om van die pointer lezen op een indirecte manier, 547 00:43:33,240 --> 00:43:37,320 maar om toegang tot die pointer, moet het dereference. 548 00:43:37,320 --> 00:43:40,550 Of, om toegang te krijgen wat moeten wijzen naar het referentie aan het. 549 00:43:40,550 --> 00:43:43,810 Dus het is dereferentie een null pointer en segfaults. 550 00:43:46,600 --> 00:43:48,730 Ik had herstart het daar. 551 00:43:48,730 --> 00:43:52,170 Als we breken op onze belangrijkste punt en lopen, 552 00:43:52,170 --> 00:43:57,320 de eerste regel van de code is char * filename = "nonexistent.txt"; 553 00:43:57,320 --> 00:44:00,870 Dat geeft een vrij grote hint over de vraag waarom dit programma niet. 554 00:44:00,870 --> 00:44:06,080 Typen naast brengt me naar de volgende regel, waar ik dit bestand openen, 555 00:44:06,080 --> 00:44:11,140 en dan onmiddellijk ik in onze lijn, waar ooit ik raakte volgende, het gaat om segfault. 556 00:44:11,140 --> 00:44:16,880 Wil iemand te gooien een reden waarom we zouden kunnen worden segfaulting? 557 00:44:16,880 --> 00:44:19,130 [Student] Bestand bestaat niet. >> Ja. 558 00:44:19,130 --> 00:44:22,250 Dit wordt verondersteld een hint te zijn 559 00:44:22,250 --> 00:44:29,570 dat wanneer u een bestand opent dat u nodig hebt om te controleren of het bestand daadwerkelijk bestaat. 560 00:44:29,570 --> 00:44:31,510 Dus hier, "nonexistent.txt"; 561 00:44:31,510 --> 00:44:34,700 Als we fopen bestandsnaam voor het lezen, wij dan moeten zeggen 562 00:44:34,700 --> 00:44:45,870 if (file == NULL) en zeg printf ("Bestand bestaat niet!" 563 00:44:45,870 --> 00:44:56,340 of - beter nog - filename); return 1; 564 00:44:56,340 --> 00:45:00,300 Dus nu kijken we of het NULL 565 00:45:00,300 --> 00:45:03,930 voordat u daadwerkelijk voort te zetten en probeert te lezen van dat bestand. 566 00:45:03,930 --> 00:45:08,800 We kunnen herscheppen het gewoon om dat dat werkt. 567 00:45:11,020 --> 00:45:14,970 Ik was van plan om een ​​nieuwe regel te nemen. 568 00:45:21,090 --> 00:45:25,290 Nu nonexistent.txt bestaat niet. 569 00:45:26,890 --> 00:45:30,040 Je moet altijd controleren op dit soort dingen. 570 00:45:30,040 --> 00:45:33,870 Je moet altijd controleren of fopen geeft NULL. 571 00:45:33,870 --> 00:45:38,170 U moet altijd controleren om ervoor te zorgen dat malloc niet NULL terug, 572 00:45:38,170 --> 00:45:41,410 of anders je segfault. 573 00:45:42,200 --> 00:45:45,930 >> Nu buggy4.c. 574 00:45:49,190 --> 00:45:58,440 Running. Ik gok deze wacht op invoer of eventueel oneindig looping. 575 00:45:58,440 --> 00:46:01,870 Ja, het is oneindig looping. 576 00:46:01,870 --> 00:46:05,560 Dus buggy4. Het lijkt erop dat we oneindige lus. 577 00:46:05,560 --> 00:46:12,590 We kunnen breken bij grote, start ons programma. 578 00:46:12,590 --> 00:46:20,180 In gdb, zolang de afkorting u eenduidig 579 00:46:20,180 --> 00:46:23,420 of speciale afkortingen die zij leveren voor u, 580 00:46:23,420 --> 00:46:29,020 dan kunt u gebruik maken van n naar de volgende te gebruiken in plaats van het hebben van te typen naast de hele weg. 581 00:46:29,020 --> 00:46:33,730 En nu ik raakte een keer n, kan ik gewoon op Enter om door te gaan volgend 582 00:46:33,730 --> 00:46:36,640 in plaats van te slaan n Voer, n Voer, n Enter. 583 00:46:36,640 --> 00:46:44,630 Het lijkt alsof ik in een soort lus die array is het instellen van [i] op 0. 584 00:46:44,630 --> 00:46:50,510 Het lijkt erop dat ik nooit ben uitbreken van deze for-lus. 585 00:46:50,510 --> 00:46:54,780 Als ik afdrukken i, dus ik 2 is, dan zal ik de volgende te gaan. 586 00:46:54,780 --> 00:46:59,250 Ik zal afdrukken i, i 3 is, dan zal ik de volgende te gaan. 587 00:46:59,250 --> 00:47:05,360 Ik zal afdrukken i en i is 3. Daarna drukt u i, i 4. 588 00:47:05,360 --> 00:47:14,520 Eigenlijk, print sizeof (array), dus grootte van de array is 20. 589 00:47:16,310 --> 00:47:32,870 Maar het lijkt erop dat er een aantal speciale gdb commando om uit te gaan totdat er iets gebeurt. 590 00:47:32,870 --> 00:47:37,620 Het is als het instellen van een aandoening die op de waarde van de variabele. Maar ik weet niet meer wat het is. 591 00:47:37,620 --> 00:47:44,100 Dus als we blijven gaan - 592 00:47:44,100 --> 00:47:47,120 Wat zei je? Wat heb je te brengen? 593 00:47:47,120 --> 00:47:50,500 [Student] Heeft weer te geven voeg ik - >> Ja. Dus weer te geven ik kan helpen. 594 00:47:50,500 --> 00:47:54,530 Als we alleen maar weer te geven i, zal het hier zetten wat de waarde van i is 595 00:47:54,530 --> 00:47:56,470 dus ik hoef het niet te drukken elke keer. 596 00:47:56,470 --> 00:48:02,930 Als we gewoon heen zien we 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 Er gaat iets vreselijk mis, en ik wordt weer op 0. 598 00:48:13,330 --> 00:48:22,220 Kijkend naar buggy4.c, zien we alles wat er gebeurt is 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 Wat zien we dat hier aan de hand? 602 00:48:31,390 --> 00:48:39,480 Als een hint, toen ik de gdb buggy4 doen - laten we breken de belangrijkste, run - 603 00:48:39,480 --> 00:48:45,980 Ik heb afdrukken sizeof (array) om te zien wat de conditie is waar ik moet eindelijk uitbreken. 604 00:48:47,690 --> 00:48:51,100 Waar ben ik? Heb ik lopen? 605 00:48:51,100 --> 00:48:54,280 Ik heb nog niet verklaren. 606 00:48:54,280 --> 00:48:58,680 Zo af te drukken sizeof (array) en dat is 20, 607 00:48:58,680 --> 00:49:06,690 waarvan verwacht wordt dat sinds mijn array is van maat 5 en het is van 5 gehele getallen, 608 00:49:06,690 --> 00:49:12,410 dus het hele ding zou moeten zijn 5 * sizeof (int) bytes, waar sizeof (int) heeft de neiging om 4. 609 00:49:12,410 --> 00:49:14,780 Dus sizeof (array) is 20. 610 00:49:14,780 --> 00:49:17,420 Wat moet dit zijn? 611 00:49:17,420 --> 00:49:21,720 [Student] gedeeld door sizeof (int). >> Ja, / sizeof (int). 612 00:49:21,720 --> 00:49:30,630 Het lijkt erop dat er nog steeds een probleem. Ik denk dat dit moet gewoon < 613 00:49:30,630 --> 00:49:36,960 want het is vrijwel altijd 00:49:44,860 Laten we nu eens na te denken over waarom dit was eigenlijk gebroken. 615 00:49:44,860 --> 00:49:53,370 Heeft iemand raden waarom was ik weer op 0 tot en met elke herhaling van de lus? 616 00:50:01,300 --> 00:50:09,350 Het enige wat binnenkant van hier dat er gebeurt is dat de array [i] wordt ingesteld op 0. 617 00:50:09,350 --> 00:50:15,350 Dus een of andere manier is deze regel code waardoor onze int i in te stellen op 0. 618 00:50:16,730 --> 00:50:23,130 [Student] Zou het kunnen zijn omdat het overschrijven van de herinnering aan dit deel van i 619 00:50:23,130 --> 00:50:27,970 wanneer het denkt dat het het volgende element van de array? >> [Bowden] Ja. 620 00:50:27,970 --> 00:50:33,880 Als we verder gaan dan het einde van ons aanbod, 621 00:50:33,880 --> 00:50:39,870 een of andere manier die ruimte dat we dwingende is het overschrijven van de waarde van i. 622 00:50:39,870 --> 00:50:48,030 En dus als we kijken naar buggy4, breken de belangrijkste, rennen, 623 00:50:48,030 --> 00:50:53,120 laten we drukken het adres van i. 624 00:50:53,120 --> 00:50:57,280 Het lijkt erop dat het is bffff124. 625 00:50:57,280 --> 00:51:03,930 Laten we nu eens af te drukken het adres van de array [0]. 110. 626 00:51:03,930 --> 00:51:06,290 Hoe zit het met [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] is bfff124. 629 00:51:14,530 --> 00:51:26,990 Dus array [5] heeft hetzelfde adres als ik, wat betekent dat array [5] is i. 630 00:51:26,990 --> 00:51:30,720 Als ze hetzelfde adres hebben, zijn ze hetzelfde. 631 00:51:30,720 --> 00:51:38,410 Dus toen we array [5] ingesteld op 0, zetten we i op 0. 632 00:51:38,410 --> 00:51:46,070 En als u denkt over dit in termen van de stapel, 633 00:51:46,070 --> 00:51:55,590 int i wordt eerst verklaard, wat betekent dat ik krijgt wat ruimte op de stack. 634 00:51:55,590 --> 00:52:04,730 Dan array [5] wordt toegewezen, dus dan 20 bytes worden toegewezen op de stapel. 635 00:52:04,730 --> 00:52:08,400 Dus ik wordt eerst toegerekend, dan zijn deze 20 bytes krijgen toegewezen. 636 00:52:08,400 --> 00:52:11,400 Dus ik gebeurt er vlak voor de array, 637 00:52:11,400 --> 00:52:19,230 en door de manier waarop, zoals ik al zei vorige week, waar technisch de stapel naar beneden groeit, 638 00:52:19,230 --> 00:52:28,520 Wanneer u index in een array zijn we gegarandeerd dat de 0e positie in het stelsel 639 00:52:28,520 --> 00:52:31,970 altijd gebeurt voordat de eerste positie in de array. 640 00:52:31,970 --> 00:52:35,900 Dit is een soort van hoe ik trok het vorige week. 641 00:52:35,900 --> 00:52:42,210 Merk op dat aan de onderkant hebben we het adres 0 hebben en aan de top hebben we mailadres Max. 642 00:52:42,210 --> 00:52:44,880 De stapel wordt steeds groeit naar beneden. 643 00:52:48,100 --> 00:52:53,500 Laten we zeggen dat we wijzen i. 644 00:52:53,500 --> 00:52:59,680 Wij wijzen integer i, wat betekent dat laten we maar zeggen dat hier geheel getal i wordt toegewezen. 645 00:52:59,680 --> 00:53:06,420 Dan wijzen we ons aanbod van 5 gehele getallen, wat betekent dat onder die, 646 00:53:06,420 --> 00:53:11,230 omdat de stapel groeit naar beneden, krijg deze 5 gehele getallen toegewezen. 647 00:53:11,230 --> 00:53:15,900 Maar vanwege de manier waarop arrays werken, we gegarandeerd dat de eerste positie in de array 648 00:53:15,900 --> 00:53:22,260 altijd een adres dan het tweede punt in de array. 649 00:53:22,260 --> 00:53:28,270 Dus scala stand 0 heeft altijd eerst gebeuren in het geheugen, 650 00:53:28,270 --> 00:53:30,700 terwijl scala positie 1 moet gebeuren na dat 651 00:53:30,700 --> 00:53:33,310 en array positie 2 moet gebeuren daarna 652 00:53:33,310 --> 00:53:37,900 wat betekent dat scala stand 0 zou ergens gebeuren hier beneden, 653 00:53:37,900 --> 00:53:40,690 matrix positie 1 zou gebeuren daarboven 654 00:53:40,690 --> 00:53:45,530 omdat omhoog te bewegen betekent een hogere adressen aangezien de maximale adres is hier. 655 00:53:45,530 --> 00:53:50,490 Dus array [0] hier beneden, array [1] hier, array [2] hier, array [3] hier. 656 00:53:50,490 --> 00:53:55,620 Merk op hoe voordat we integer toegewezen i helemaal tot hier, 657 00:53:55,620 --> 00:54:01,040 als we verder en verder in ons aanbod, zijn we dichter en dichter bij onze integer i. 658 00:54:01,040 --> 00:54:07,640 Het is gewoon zo gebeurt het dat array [5], dat is een positie buiten ons aanbod, 659 00:54:07,640 --> 00:54:13,010 is precies waar integer ik toevallig worden toegewezen. 660 00:54:13,010 --> 00:54:16,920 Dus dat is het punt waar we toevallig het raken van de ruimte op de stack 661 00:54:16,920 --> 00:54:21,680 dat werd toegewezen voor integer i, en we zijn het instellen van die op 0. 662 00:54:21,680 --> 00:54:26,160 >> Dat is hoe dat werkt. Vragen? Ja. 663 00:54:26,160 --> 00:54:30,710 [Student] Never mind. Oke. 664 00:54:30,710 --> 00:54:33,090 [Student] Hoe voorkom je dit soort fouten? 665 00:54:33,090 --> 00:54:41,190 Deze soort van fouten? Gebruik geen C als programmeertaal. 666 00:54:41,190 --> 00:54:45,840 Gebruik een taal die array bounds checking heeft. 667 00:54:45,840 --> 00:54:55,900 Zolang je voorzichtig bent, je hoeft alleen maar om te voorkomen dat die voorbij de grenzen van de array. 668 00:54:55,900 --> 00:54:58,300 [Student] Dus hier toen we gingen langs de grenzen van de array - 669 00:54:58,300 --> 00:55:01,840 [Bowden] Dat is waar de dingen beginnen mis gaat. >> [Student] Oh, oke. 670 00:55:01,840 --> 00:55:05,730 Zolang u binnen het geheugen toegewezen voor de array, je bent in orde. 671 00:55:05,730 --> 00:55:12,400 Maar C heeft geen controle op fouten. Als ik dat doe array [1000], zal het graag gewoon wijzigen wat er ook gebeurt - 672 00:55:12,400 --> 00:55:16,500 Het gaat naar het begin van de array, dan gaat 1000 posities na en geeft deze 0. 673 00:55:16,500 --> 00:55:20,000 Het doet geen controle, zodat de oh, dit niet echt 1000 dingen in hebben. 674 00:55:20,000 --> 00:55:22,750 1000 is veel verder dan wat ik zou moeten veranderen, 675 00:55:22,750 --> 00:55:26,940 terwijl Java of iets wat je krijgt scala out of bounds index 676 00:55:26,940 --> 00:55:29,820 of index out of bounds uitzondering. 677 00:55:29,820 --> 00:55:33,950 Dat is de reden waarom veel hoger niveau talen die dingen 678 00:55:33,950 --> 00:55:37,340 waar als je verder gaan dan de grenzen van de array, je faalt 679 00:55:37,340 --> 00:55:40,070 zodat je niet kunt veranderen dingen onder je 680 00:55:40,070 --> 00:55:42,590 en dan gaat het veel erger dan alleen het krijgen van een uitzondering 681 00:55:42,590 --> 00:55:44,940 zeggen dat je verder ging dan het einde van de array. 682 00:55:44,940 --> 00:55:50,970 [Student] En zo zouden we hebben net de <= gewoon > [Bowden] Ja. 683 00:55:50,970 --> 00:55:54,800 Het moet 00:55:59,560 sinds sizeof (array) is 20, maar we willen alleen 5. >> [Student] Juist. 685 00:55:59,560 --> 00:56:04,060 Meer vragen? Oke. 686 00:56:04,060 --> 00:56:07,380 >> [Student] Ik heb een vraag. >> Ja. 687 00:56:07,380 --> 00:56:16,440 [Student] Wat is de eigenlijke array variabele? 688 00:56:16,440 --> 00:56:20,000 [Bowden] Zoals wat is array? 689 00:56:20,000 --> 00:56:24,930 Array zelf als symbool. 690 00:56:24,930 --> 00:56:31,490 Het is alleen het adres van de start van de 20 bytes dat we verwijzen. 691 00:56:31,490 --> 00:56:38,070 U kunt hierbij denken aan het als een pointer, maar het is een constante pointer. 692 00:56:38,070 --> 00:56:44,140 Zodra dingen krijgen gecompileerd, wordt de variabele array niet meer bestaat. 693 00:56:44,140 --> 00:56:48,210 [Student] Dus wat is het vinden van de grootte van de array? 694 00:56:48,210 --> 00:56:54,130 Grootte van array verwijst naar de grootte van dat blok dat symbool verwijst. 695 00:56:54,130 --> 00:57:01,240 Als ik iets doen als printf ("% p \ n", array); 696 00:57:01,240 --> 00:57:05,140 laten we voer het uit. 697 00:57:12,960 --> 00:57:15,530 Wat heb ik net verkeerd gedaan? 698 00:57:15,530 --> 00:57:19,220 Array 'array' verklaarde hier. 699 00:57:20,820 --> 00:57:23,200 Oh, hier. 700 00:57:23,200 --> 00:57:31,250 Clang is slim, en het gebeurt te merken dat ik de array als 5 elementen verklaard 701 00:57:31,250 --> 00:57:34,540 maar ik ben het indexeren in positie 1000. 702 00:57:34,540 --> 00:57:38,450 Het kan dat doen, omdat dit zijn slechts constanten. 703 00:57:38,450 --> 00:57:43,370 Het kan alleen zo ver gaan in het opmerken dat ik die verder gaan dan de grenzen van de array. 704 00:57:43,370 --> 00:57:46,880 Maar let op toen we hadden i onjuist zijn, 705 00:57:46,880 --> 00:57:51,040 het kan niet mogelijk te bepalen hoeveel waarden i zou kunnen nemen op, 706 00:57:51,040 --> 00:57:55,540 zodat het niet kan bepalen of i ging na het einde van de array. 707 00:57:55,540 --> 00:57:59,430 Dat is gewoon Clang slim zijn. 708 00:57:59,430 --> 00:58:03,340 >> Maar nu maken buggy4. Dus wat doe ik verkeerd? 709 00:58:03,340 --> 00:58:05,970 Impliciet verklaren bibliotheekfunctie 'printf'. 710 00:58:05,970 --> 00:58:14,960 Ik ga wilt # include . 711 00:58:14,960 --> 00:58:18,710 Oke. Nu draait buggy4. 712 00:58:18,710 --> 00:58:24,840 Het afdrukken van de waarde van de array zoals ik deed hier, af te drukken als een pointer 713 00:58:24,840 --> 00:58:30,060 prints iets dat er zo uitziet - bfb8805c - dat is wat mailadres 714 00:58:30,060 --> 00:58:33,450 dat is in de stapel-ish regio. 715 00:58:33,450 --> 00:58:41,820 Array zelf is een pointer, maar is geen echte pointer, 716 00:58:41,820 --> 00:58:45,410 aangezien een gewone pointer we kunnen veranderen. 717 00:58:45,410 --> 00:58:54,700 Array is slechts enkele constant. De 20 blokken van het geheugen beginnen bij adres 0xbfb8805c. 718 00:58:54,700 --> 00:59:09,020 Dus bfb8805c via dit adres +20--of denk ik -20 - 719 00:59:09,020 --> 00:59:17,400 is al het geheugen toegewezen voor deze array. 720 00:59:17,400 --> 00:59:20,350 Array, wordt de variabele zelf nergens opgeslagen. 721 00:59:20,350 --> 00:59:27,660 Wanneer u samenstellen, de compiler - hand zwaaien naar het - 722 00:59:27,660 --> 00:59:33,060 maar de compiler zal gewoon gebruiken waarvan het bedrijf weet array te. 723 00:59:33,060 --> 00:59:36,090 Het weet waar die array begint, 724 00:59:36,090 --> 00:59:40,910 en kan dus altijd gewoon dingen doen op het gebied van offsets van dat begin. 725 00:59:40,910 --> 00:59:43,960 Het hoeft niet een variabele zelf aan array te vertegenwoordigen. 726 00:59:43,960 --> 00:59:53,730 Maar als ik iets als int * p = array doen, nu p is een pointer die wijst naar die array, 727 00:59:53,730 --> 00:59:57,830 en nu p doet eigenlijk bestaan ​​op de stapel. 728 00:59:57,830 --> 01:00:01,950 Ik ben vrij om te p te veranderen. Ik kan p = malloc. 729 01:00:01,950 --> 01:00:06,500 Dus het oorspronkelijk gewezen op rij, nu het wijst op wat ruimte op de heap. 730 01:00:06,500 --> 01:00:09,620 Ik kan het niet array = malloc. 731 01:00:09,620 --> 01:00:13,710 Als Clang is slim, zal het tegen me schreeuwen recht uit de vleermuis. 732 01:00:17,000 --> 01:00:21,430 Eigenlijk ben ik er vrij zeker van gcc zou dit ook doen. 733 01:00:21,430 --> 01:00:25,010 Dus scala type 'int [5]' is niet overdraagbaar. 734 01:00:25,010 --> 01:00:28,040 U kunt geen iets om een ​​array-type 735 01:00:28,040 --> 01:00:30,500 omdat array is gewoon een constante. 736 01:00:30,500 --> 01:00:34,760 Het is een symbool dat referenties die 20 bytes. Ik kan het niet veranderen. 737 01:00:34,760 --> 01:00:37,690 >> [Student] En waar is de grootte van de array opgeslagen? 738 01:00:37,690 --> 01:00:40,670 [Bowden] Het is nergens opgeslagen. Het is als het compileren. 739 01:00:40,670 --> 01:00:46,310 Dus waar is de grootte van de array opgeslagen? 740 01:00:46,310 --> 01:00:51,870 U kunt alleen gebruik maken van sizeof (array) binnenkant van de functie die de array zelf verklaard. 741 01:00:51,870 --> 01:01:03,150 Dus als ik doe wat functie, foo, en ik doe (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 en dan naar beneden hier noem ik foo (array); 744 01:01:21,330 --> 01:01:24,840 binnenkant van deze functie - laten we voer het uit. 745 01:01:34,200 --> 01:01:36,840 Dit is Clang slim zijn weer. 746 01:01:36,840 --> 01:01:43,890 Het is me te vertellen dat sizeof op array functie parameter 747 01:01:43,890 --> 01:01:46,690 zal terugkeren grootte van 'int *'. 748 01:01:46,690 --> 01:01:55,150 Dit zou een fout zijn als het is niet wat ik wilde gebeuren. 749 01:01:55,150 --> 01:01:58,960 Laten we in feite uit te schakelen Werror. 750 01:02:14,950 --> 01:02:17,590 Waarschuwing. Waarschuwingen zijn prima. 751 01:02:17,590 --> 01:02:19,960 Het zal het compileren zolang het een waarschuwing. 752 01:02:19,960 --> 01:02:22,910 . / A.out gaat 4 drukken. 753 01:02:22,910 --> 01:02:28,650 De waarschuwing dat werd gegenereerd is een duidelijke indicatie van wat er mis ging. 754 01:02:28,650 --> 01:02:34,120 Deze int array wordt gewoon op sizeof (int *) af te drukken. 755 01:02:34,120 --> 01:02:39,790 Zelfs als ik array [5] hier in zet, is het nog steeds gewoon op sizeof (int *) af te drukken. 756 01:02:39,790 --> 01:02:47,440 Dus zodra je voorbij het in een functie, het onderscheid tussen arrays en pointers 757 01:02:47,440 --> 01:02:49,670 is niet-bestaand. 758 01:02:49,670 --> 01:02:52,640 Dit gebeurt als een array die werd uitgeroepen op de stapel, 759 01:02:52,640 --> 01:02:58,300 maar zodra we langs die waarde, dat 0xbf bla, bla, bla in deze functie, 760 01:02:58,300 --> 01:03:03,350 Dan pointer wijst die array op de stapel. 761 01:03:03,350 --> 01:03:08,310 Dus dat betekent dat sizeof alleen van toepassing op de functie die de array werd verklaard, 762 01:03:08,310 --> 01:03:11,230 wat betekent dat wanneer u het samenstellen van deze functie, 763 01:03:11,230 --> 01:03:17,330 wanneer Clang gaat door deze functie, ziet het array is een int array van grootte 5. 764 01:03:17,330 --> 01:03:20,640 Dus dan ziet ze sizeof (array). Nou, dat is 20. 765 01:03:20,640 --> 01:03:26,440 Dat is eigenlijk hoe sizeof werkt in principe voor bijna alle gevallen. 766 01:03:26,440 --> 01:03:31,150 Sizeof is geen functie, het is een operator. 767 01:03:31,150 --> 01:03:33,570 U hoeft niet bellen met de sizeof functie. 768 01:03:33,570 --> 01:03:38,280 Sizeof (int), zal de compiler gewoon vertalen dat naar 4. 769 01:03:41,480 --> 01:03:43,700 Heb je het? Oke. 770 01:03:43,700 --> 01:03:47,520 >> [Student] Dus wat is het verschil tussen sizeof (array) in hoofd-en in foo? 771 01:03:47,520 --> 01:03:52,840 Dit komt omdat we zeggen sizeof (array), dat is van het type int *, 772 01:03:52,840 --> 01:03:57,120 terwijl de array hier beneden is niet van het type int *, het is een int array. 773 01:03:57,120 --> 01:04:04,540 >> [Student] Dus als je de parameter in array [] in plaats van int * array, 774 01:04:04,540 --> 01:04:09,230 zou dat betekenen dat je nog zou kunnen scala veranderen want nu is het een pointer? 775 01:04:09,230 --> 01:04:14,250 [Bowden] Vind je deze? >> [Student] Ja. Kun je serie nu veranderen binnen de functie? 776 01:04:14,250 --> 01:04:18,420 [Bowden] Je kon scala veranderen in beide gevallen. 777 01:04:18,420 --> 01:04:23,130 In beide gevallen bent u vrij om te zeggen array [4] = 0. 778 01:04:23,130 --> 01:04:26,590 [Student] Maar je kunt scala punt te maken om iets anders? 779 01:04:26,590 --> 01:04:30,230 [Bowden] Oh. Ja. In beide gevallen - >> [student] Ja. 780 01:04:30,230 --> 01:04:38,410 [Bowden] Het onderscheid tussen array [] en een int * array, er is niemand. 781 01:04:38,410 --> 01:04:42,570 U kunt een aantal multidimensionale array ook hier 782 01:04:42,570 --> 01:04:47,050 voor een aantal handige syntax, maar het is nog steeds slechts een wijzer. 783 01:04:47,050 --> 01:04:56,400 Dit betekent dat ik vrij ben om array doen = malloc (sizeof (int)), en wijzen nu ergens anders. 784 01:04:56,400 --> 01:04:59,610 Maar net als hoe dit werkt voor eeuwig en altijd, 785 01:04:59,610 --> 01:05:03,210 het wijzigen van deze serie door het maken van het wijzen op iets anders 786 01:05:03,210 --> 01:05:07,570 verandert niets aan deze reeks hier beneden, want het is een kopie van het argument, 787 01:05:07,570 --> 01:05:10,780 het is niet een pointer naar dat argument. 788 01:05:10,780 --> 01:05:16,070 En eigenlijk, net als meer aanwijzingen dat het precies hetzelfde - 789 01:05:16,070 --> 01:05:21,100 we al zagen wat afdrukken serie prints - 790 01:05:21,100 --> 01:05:31,410 wat als we drukken het adres van de array of het adres van het adres van de array 791 01:05:31,410 --> 01:05:36,290 op een van deze? 792 01:05:41,770 --> 01:05:45,220 Laten we negeren deze. 793 01:05:48,140 --> 01:05:51,660 Oke. Dit is prima. Het is nu actief. / A.out. 794 01:05:51,660 --> 01:06:00,220 Printing array Het afdrukken het adres van de array hetzelfde zijn. 795 01:06:00,220 --> 01:06:02,870 Array werkt gewoon niet. 796 01:06:02,870 --> 01:06:08,190 Het weet wanneer u afdrukt scala, je het symbool dat verwijst naar die 20 bytes afdrukken. 797 01:06:08,190 --> 01:06:11,940 Het afdrukken van de adres van de array, nou ja, niet array niet bestaat. 798 01:06:11,940 --> 01:06:17,200 Het heeft geen adres, dus het is gewoon print het adres van die 20 bytes. 799 01:06:20,820 --> 01:06:28,150 Zodra je compileren naar beneden, zoals in uw gecompileerde buggy4. / A.out, 800 01:06:28,150 --> 01:06:30,340 array is onbestaande. 801 01:06:30,340 --> 01:06:33,640 Pointers bestaan. Arrays niet. 802 01:06:34,300 --> 01:06:38,060 De geheugenblokken die de matrix nog steeds, 803 01:06:38,060 --> 01:06:43,270 maar de variabele array en variabelen van dat type niet bestaan. 804 01:06:46,260 --> 01:06:50,270 Dat zijn net de belangrijkste verschillen tussen arrays en pointers 805 01:06:50,270 --> 01:06:55,590 worden zodra u de functie bellen, is er geen verschil. 806 01:06:55,590 --> 01:07:00,460 Maar de binnenkant van de functie die de array zelf wordt verklaard, sizeof werkt anders 807 01:07:00,460 --> 01:07:05,190 aangezien u afdrukt de grootte van de blokken in plaats van de grootte van het type, 808 01:07:05,190 --> 01:07:08,950 en je kunt het niet veranderen want het is een symbool. 809 01:07:08,950 --> 01:07:14,370 Het afdrukken van de zaak en het adres van de zaak drukt hetzelfde. 810 01:07:14,370 --> 01:07:18,480 En dat is het zowat. 811 01:07:18,480 --> 01:07:20,820 [Student] Zou je kunnen zeggen dat nog een keer? 812 01:07:21,170 --> 01:07:24,170 Ik zou iets gemist hebben. 813 01:07:24,170 --> 01:07:29,260 Afdrukken array en adres van array drukt hetzelfde, 814 01:07:29,260 --> 01:07:33,180 terwijl als je afdrukken van een pointer versus het adres van de aanwijzer, 815 01:07:33,180 --> 01:07:36,010 het enige wat drukt het adres van wat je te wijzen op, 816 01:07:36,010 --> 01:07:40,360 de andere drukt het adres van de aanwijzer op de stapel. 817 01:07:40,360 --> 01:07:47,040 U kunt een pointer, je kunt niet veranderen een reeks symbool. 818 01:07:47,740 --> 01:07:53,270 En sizeof aanwijzer gaat naar de grootte van die pointer-type af te drukken. 819 01:07:53,270 --> 01:07:57,470 Dus int * p sizeof (p) gaat tot 4 af te drukken, 820 01:07:57,470 --> 01:08:04,110 maar int array [5] Print sizeof (array) gaat tot 20 af te drukken. 821 01:08:04,110 --> 01:08:07,480 [Student] Dus int array [5] wordt afgedrukt 20? >> Ja. 822 01:08:07,480 --> 01:08:13,300 Dat is waarom de binnenkant van buggy4 wanneer het wordt gebruikt om sizeof (array) worden 823 01:08:13,300 --> 01:08:16,660 Dit deed i <20, dat is niet wat we wilden. 824 01:08:16,660 --> 01:08:20,880 We willen i <5. >> [Student] Oke. 825 01:08:20,880 --> 01:08:25,569 [Bowden] En dan, zodra je begint het passeren in de functies, 826 01:08:25,569 --> 01:08:34,340 als we dat deden int * p = array; 827 01:08:34,340 --> 01:08:39,779 in deze functie kunnen we in principe gebruik p en array op dezelfde manier, 828 01:08:39,779 --> 01:08:43,710 behalve de sizeof probleem en de veranderende probleem. 829 01:08:43,710 --> 01:08:49,810 Maar p [0] = 1, is hetzelfde als zeggen array [0] = 1; 830 01:08:49,810 --> 01:08:55,600 En zodra we foo (matrix) zeggen, of foo (p); 831 01:08:55,600 --> 01:08:59,760 binnenkant van de foo functie, dit is tweemaal dezelfde oproep. 832 01:08:59,760 --> 01:09:03,350 Er is geen verschil tussen deze twee gesprekken. 833 01:09:07,029 --> 01:09:11,080 >> Iedereen goed op dat? Oke. 834 01:09:14,620 --> 01:09:17,950 We hebben 10 minuten. 835 01:09:17,950 --> 01:09:28,319 >> We zullen proberen om door dit Hacker Typer programma, 836 01:09:28,319 --> 01:09:32,350 deze website, die vorig jaar uitkwam, of zoiets. 837 01:09:34,149 --> 01:09:41,100 Het is gewoon hoort te zijn als u typt willekeurig en print - 838 01:09:41,100 --> 01:09:46,729 Wat bestand het gebeurt te zijn geladen is wat het lijkt alsof je aan het typen bent. 839 01:09:46,729 --> 01:09:52,069 Het ziet eruit als een soort besturingssysteem code. 840 01:09:53,760 --> 01:09:56,890 Dat is wat we willen implementeren. 841 01:10:08,560 --> 01:10:11,690 U moet een binaire uitvoerbare naam hacker_typer 842 01:10:11,690 --> 01:10:14,350 dat duurt in een enkel argument, het bestand "hacker type." 843 01:10:14,350 --> 01:10:16,480 Het uitvoeren van de executable moet het scherm op 844 01:10:16,480 --> 01:10:20,850 en print een karakter uit de doorrekeningen in het bestand telkens wanneer de gebruiker op een toets drukt. 845 01:10:20,850 --> 01:10:24,990 Dus wat ingedrukte toets, moet het weg te gooien en in plaats daarvan drukt u een karakter uit het bestand 846 01:10:24,990 --> 01:10:27,810 dat is het argument. 847 01:10:29,880 --> 01:10:34,350 Ik zal vrij veel vertellen wat de dingen die we gaan moeten weten zijn. 848 01:10:34,350 --> 01:10:36,440 Maar we willen kijken op de termios bibliotheek. 849 01:10:36,440 --> 01:10:44,840 Ik heb nog nooit gebruik gemaakt van deze bibliotheek in mijn hele leven, dus het is zeer minimaal doeleinden. 850 01:10:44,840 --> 01:10:48,610 Maar dit gaat naar de bibliotheek die we kunnen gebruiken om weg te gooien het teken dat u geraakt worden 851 01:10:48,610 --> 01:10:52,390 tijdens het typen in standaard inch 852 01:10:56,970 --> 01:11:05,840 Dus hacker_typer.c, en we gaan willen # include . 853 01:11:05,840 --> 01:11:12,870 Als we kijken naar de man pagina voor termios - ik ben gok dat het aansluitpunt van OS of iets - 854 01:11:12,870 --> 01:11:16,240 Ik weet niet hoe het te lezen. 855 01:11:16,240 --> 01:11:21,040 Kijkend naar deze, het zegt op te nemen deze 2 bestanden, dus we zullen dat doen. 856 01:11:37,620 --> 01:11:46,820 >> Beginnen bij het begin, we willen nemen in een enkel argument, dat is het bestand dat we moeten openen. 857 01:11:46,820 --> 01:11:52,420 Dus wat wil ik doen? Hoe kan ik controleren om te zien ik heb een argument? 858 01:11:52,420 --> 01:11:56,480 [Student] Als argc het gelijk. >> [Bowden] Ja. 859 01:11:56,480 --> 01:12:21,250 Dus als (argc = 2!) Printf ("Gebruik:% s [-bestand te openen]"). 860 01:12:21,250 --> 01:12:32,750 Dus nu als ik zonder dit zonder een tweede argument - oh, ik heb de nieuwe lijn - 861 01:12:32,750 --> 01:12:36,240 zie je het zegt gebruik:. / hacker_typer, 862 01:12:36,240 --> 01:12:39,770 en dan het tweede argument moet het bestand dat ik wil openen zijn. 863 01:12:58,430 --> 01:13:01,260 Nu, wat moet ik doen? 864 01:13:01,260 --> 01:13:08,490 Ik wil lezen uit dit bestand. Hoe kan ik een bestand lezen? 865 01:13:08,490 --> 01:13:11,920 [Student] U opent het eerst. >> Ja. 866 01:13:11,920 --> 01:13:15,010 Dus fopen. Hoe ziet fopen eruit? 867 01:13:15,010 --> 01:13:22,980 [Student] Bestandsnaam. >> [Bowden] Bestandsnaam gaat worden argv [1]. 868 01:13:22,980 --> 01:13:26,110 [Student] En dan wat je wilt doen met het, zodat het - >> [Bowden] Ja. 869 01:13:26,110 --> 01:13:28,740 Dus als je niet meer weet, kan je gewoon doen man fopen, 870 01:13:28,740 --> 01:13:32,960 waar het gaat om een ​​const char * pad waarbij pad bestandsnaam te zijn, 871 01:13:32,960 --> 01:13:34,970 const char * mode. 872 01:13:34,970 --> 01:13:38,660 Als je toevallig niet meer weet wat mode is, dan kunt u zoeken naar mode. 873 01:13:38,660 --> 01:13:44,660 Binnenkant van man-pagina's, de slash is wat u kunt gebruiken om te zoeken naar dingen. 874 01:13:44,660 --> 01:13:49,790 Dus ik typ / mode om te zoeken naar de modus. 875 01:13:49,790 --> 01:13:57,130 n en N zijn wat je kunt om te fietsen gebruiken via de zoekmachine resultaten. 876 01:13:57,130 --> 01:13:59,800 Hier staat het argument mode wijst naar een string 877 01:13:59,800 --> 01:14:01,930 beginnen met een van de volgende sequenties. 878 01:14:01,930 --> 01:14:06,480 Dus r, Open tekstbestand om te lezen. Dat is wat we willen doen. 879 01:14:08,930 --> 01:14:13,210 Voor het lezen, en ik wil op te slaan dat. 880 01:14:13,210 --> 01:14:18,720 Het ding gaat een FILE * worden. Nu, wat wil ik doen? 881 01:14:18,720 --> 01:14:21,200 Geef me een seconde. 882 01:14:28,140 --> 01:14:30,430 Oke. Nu, wat wil ik doen? 883 01:14:30,430 --> 01:14:32,940 [Student] Controleer of het NULL. >> [Bowden] Ja. 884 01:14:32,940 --> 01:14:38,690 Elke keer dat u een bestand opent, zorg ervoor dat u met succes in staat bent om het te openen. 885 01:14:58,930 --> 01:15:10,460 >> Nu wil ik dat termios dingen te doen waar ik wil het eerst las mijn huidige instellingen 886 01:15:10,460 --> 01:15:14,050 en op te slaan die in iets, dan wil ik mijn instellingen wijzigen 887 01:15:14,050 --> 01:15:19,420 weg te gooien elk karakter dat ik typ, 888 01:15:19,420 --> 01:15:22,520 en dan wil ik die instellingen bij te werken. 889 01:15:22,520 --> 01:15:27,250 En dan aan het einde van het programma, ik wil om terug te keren naar mijn oorspronkelijke instellingen. 890 01:15:27,250 --> 01:15:32,080 Dus de struct gaat worden van het type termios, en ik ga twee van die wil. 891 01:15:32,080 --> 01:15:35,600 De eerste gaat worden mijn current_settings, 892 01:15:35,600 --> 01:15:42,010 en dan zijn ze gaan worden mijn hacker_settings. 893 01:15:42,010 --> 01:15:48,070 Ten eerste, ik ga wil mijn huidige instellingen op te slaan, 894 01:15:48,070 --> 01:15:53,790 dan ga ik willen hacker_settings bijwerken, 895 01:15:53,790 --> 01:16:01,570 en dan weg aan het eind van mijn programma, ik wil terug naar de huidige instellingen. 896 01:16:01,570 --> 01:16:08,660 Dus het opslaan van de huidige instellingen, de manier die werkt, we man termios. 897 01:16:08,660 --> 01:16:15,810 We zien dat we deze int tcsetattr, int tcgetattr hebben. 898 01:16:15,810 --> 01:16:22,960 Ik passeer in een termios struct door de aanwijzer. 899 01:16:22,960 --> 01:16:30,640 De manier waarop dit zal zien is - ik heb al vergeten wat de functie is aangeroepen. 900 01:16:30,640 --> 01:16:34,930 Kopieer en plak deze. 901 01:16:39,150 --> 01:16:45,500 Dus tcgetattr, dan wil ik pas in de struct dat ik de informatie opslaan in, 902 01:16:45,500 --> 01:16:49,650 die zal worden current_settings, 903 01:16:49,650 --> 01:16:59,120 en het eerste argument is de file descriptor voor het ding wil ik de eigenschappen van op te slaan. 904 01:16:59,120 --> 01:17:04,360 Wat de file descriptor is is net als iedere keer dat u een bestand opent, krijgt het een file descriptor. 905 01:17:04,360 --> 01:17:14,560 Toen ik fopen argv [1], het wordt een file descriptor die u verwijst 906 01:17:14,560 --> 01:17:16,730 wanneer u wilt lezen of schrijven. 907 01:17:16,730 --> 01:17:19,220 Dat is niet de file descriptor Ik wil hier gebruiken. 908 01:17:19,220 --> 01:17:21,940 Er zijn drie file descriptors u standaard, 909 01:17:21,940 --> 01:17:24,310 die standaard, standaard uit en standaardfout. 910 01:17:24,310 --> 01:17:29,960 Standaard, ik denk dat het standaard in is 0, standaard uit is 1, en standaard fout is 2. 911 01:17:29,960 --> 01:17:33,980 Dus wat wil ik de instellingen van veranderen? 912 01:17:33,980 --> 01:17:37,370 Ik wil de instellingen van wanneer ik raakte een teken te wijzigen, 913 01:17:37,370 --> 01:17:41,590 Ik wil dat het dat karakter weg te gooien in plaats van deze af te drukken op het scherm. 914 01:17:41,590 --> 01:17:45,960 Wat stream - standaard in, standaard uit, of standaardfout - 915 01:17:45,960 --> 01:17:52,050 reageert op dingen als ik typ op het toetsenbord? >> [Student] Standaard inch >> Ja. 916 01:17:52,050 --> 01:17:56,450 Dus ik kan dit doen 0 of wat ik kan doen stdin. 917 01:17:56,450 --> 01:17:59,380 Ik krijg de current_settings van standaard inch 918 01:17:59,380 --> 01:18:01,720 >> Nu wil ik deze instellingen bij te werken, 919 01:18:01,720 --> 01:18:07,200 dus eerst zal ik kopiëren naar hacker_settings wat mijn current_settings zijn. 920 01:18:07,200 --> 01:18:10,430 En hoe structs werk is zal het gewoon kopiëren. 921 01:18:10,430 --> 01:18:14,510 Dit kopieert alle van de velden, zoals je zou verwachten. 922 01:18:14,510 --> 01:18:17,410 >> Nu wil ik een aantal van de velden te werken. 923 01:18:17,410 --> 01:18:21,670 Kijkend naar termios, zou je moeten lezen veel van deze 924 01:18:21,670 --> 01:18:24,110 gewoon om te zien wat je zou willen zoeken, 925 01:18:24,110 --> 01:18:28,210 maar de vlaggen je gaat te willen zoeken naar zijn echo, 926 01:18:28,210 --> 01:18:33,110 zodat ECHO Echo ingevoerde tekens. 927 01:18:33,110 --> 01:18:37,710 Eerst wil ik stellen - ik heb al vergeten wat de velden zijn. 928 01:18:45,040 --> 01:18:47,900 Dit is wat de struct eruit ziet. 929 01:18:47,900 --> 01:18:51,060 Dus invoermodi ik denk dat we willen veranderen. 930 01:18:51,060 --> 01:18:54,210 We kijken naar de oplossing om ervoor te zorgen dat is wat we willen veranderen. 931 01:19:04,060 --> 01:19:12,610 We willen lflag veranderen om te voorkomen om te kijken door al deze. 932 01:19:12,610 --> 01:19:14,670 We willen de lokale modus te wijzigen. 933 01:19:14,670 --> 01:19:17,710 U zou hebben om door te lezen dit hele ding om te begrijpen waar alles hoort 934 01:19:17,710 --> 01:19:19,320 dat we willen veranderen. 935 01:19:19,320 --> 01:19:24,120 Maar het is de binnenkant van de lokale modes waar we gaan willen dat veranderen. 936 01:19:27,080 --> 01:19:33,110 Dus hacker_settings.cc_lmode is hoe het heet. 937 01:19:39,630 --> 01:19:43,020 c_lflag. 938 01:19:49,060 --> 01:19:52,280 Dit is waar we in bitwise operators. 939 01:19:52,280 --> 01:19:54,860 We zijn een beetje uit de tijd, maar we gaan er doorheen heel snel. 940 01:19:54,860 --> 01:19:56,600 Dit is waar we in bitwise operators, 941 01:19:56,600 --> 01:19:59,950 waar ik denk dat ik zei een tijd lang geleden dat wanneer je te maken kreeg met vlaggen, 942 01:19:59,950 --> 01:20:03,370 je gaat worden met behulp van logische bewerking veel. 943 01:20:03,370 --> 01:20:08,240 Elk bit in de vlag komt overeen met een soort van gedrag. 944 01:20:08,240 --> 01:20:14,090 Dus hier, deze vlag heeft een heleboel verschillende dingen, waar ze allemaal betekenen iets anders. 945 01:20:14,090 --> 01:20:18,690 Maar wat ik wil doen is gewoon uitschakelen van de bit die overeenkomt ECHO. 946 01:20:18,690 --> 01:20:25,440 Dus om dat uitzetten doe ik & = ¬ ECHO. 947 01:20:25,440 --> 01:20:30,110 Eigenlijk denk ik dat het is alsof Techo of zoiets. Ik ga gewoon opnieuw te controleren. 948 01:20:30,110 --> 01:20:34,050 Ik kan termios het. Het is gewoon ECHO. 949 01:20:34,050 --> 01:20:38,440 ECHO gaat een beetje. 950 01:20:38,440 --> 01:20:44,230 ¬ ECHO gaat betekenen alle bits zijn ingesteld op 1, wat betekent dat alle vlaggen zijn ingesteld op true 951 01:20:44,230 --> 01:20:47,140 behalve voor de ECHO bit. 952 01:20:47,140 --> 01:20:53,830 Door de beëindiging van mijn lokale vlaggen met deze, betekent alle vlaggen die momenteel zijn ingesteld op true 953 01:20:53,830 --> 01:20:56,520 zal nog steeds worden ingesteld op true. 954 01:20:56,520 --> 01:21:03,240 Als mijn ECHO vlag is ingesteld op true, dan wordt dit per se ingesteld op false op de ECHO vlag. 955 01:21:03,240 --> 01:21:07,170 Dus deze regel code wordt net naast de ECHO vlag. 956 01:21:07,170 --> 01:21:16,270 De andere lijnen van de code, zal ik gewoon kopiëren in het belang van tijd en dan uitleggen. 957 01:21:27,810 --> 01:21:30,180 In de oplossing, zei hij 0. 958 01:21:30,180 --> 01:21:33,880 Het is waarschijnlijk beter om expliciet te zeggen stdin. 959 01:21:33,880 --> 01:21:42,100 >> Merk op dat ik ook ben ECHO doet | icanon hier. 960 01:21:42,100 --> 01:21:46,650 Icanon verwijst naar iets apart, die canonieke functie betekent. 961 01:21:46,650 --> 01:21:50,280 Wat canonieke modus middel is meestal als je het typen van de command line, 962 01:21:50,280 --> 01:21:54,670 standaard in niet bewerkt niets totdat je raakt newline. 963 01:21:54,670 --> 01:21:58,230 Dus als je getString, typt u een heleboel dingen, dan heb je newline raken. 964 01:21:58,230 --> 01:22:00,590 Dat is wanneer het wordt verzonden naar standaard inch 965 01:22:00,590 --> 01:22:02,680 Dat is de standaard. 966 01:22:02,680 --> 01:22:05,830 Wanneer schakel ik canonieke mode, nu elk teken dat u op 967 01:22:05,830 --> 01:22:10,910 is wat wordt verwerkt, die meestal soort slecht omdat het langzaam deze dingen verwerken 968 01:22:10,910 --> 01:22:14,330 dat is waarom het is goed om het te bufferen in complete lijnen. 969 01:22:14,330 --> 01:22:16,810 Maar ik wil elk teken moet worden verwerkt 970 01:22:16,810 --> 01:22:18,810 want ik wil niet dat het wachten voor mij om newline raken 971 01:22:18,810 --> 01:22:21,280 voordat het verwerkt alle karakters heb ik te typen. 972 01:22:21,280 --> 01:22:24,760 Deze schakelt canonieke modus. 973 01:22:24,760 --> 01:22:31,320 Dit spul betekent alleen wanneer het echt verwerkt karakters. 974 01:22:31,320 --> 01:22:35,830 Dit betekent meteen verwerken, zodra ik ze te typen, te verwerken. 975 01:22:35,830 --> 01:22:42,510 En dit is de functie die mijn instellingen aan het bijwerken is voor standaard in, 976 01:22:42,510 --> 01:22:45,480 en TCSA betekent het nu doen. 977 01:22:45,480 --> 01:22:50,310 De andere opties zijn wachten tot alles dat op dit moment op de stream wordt verwerkt. 978 01:22:50,310 --> 01:22:52,030 Dat maakt eigenlijk niet uit. 979 01:22:52,030 --> 01:22:56,920 Net nu verander ik mijn instellingen te zijn wat op dit moment in hacker_typer_settings. 980 01:22:56,920 --> 01:23:02,210 Ik denk dat ik noemde het hacker_settings, dus laten we dat veranderen. 981 01:23:09,610 --> 01:23:13,500 Alles veranderen aan hacker_settings. 982 01:23:13,500 --> 01:23:16,870 >> Nu aan het einde van ons programma gaan we wilt terugkeren 983 01:23:16,870 --> 01:23:20,210 wat is nu de binnenkant van normal_settings, 984 01:23:20,210 --> 01:23:26,560 die zal net lijken & normal_settings. 985 01:23:26,560 --> 01:23:30,650 Merk op dat ik zijn niet veranderd een van mijn normal_settings sinds oorspronkelijk het krijgen van het. 986 01:23:30,650 --> 01:23:34,520 Dan gewoon veranderen ze terug, ik geef ze terug aan het eind. 987 01:23:34,520 --> 01:23:38,390 Dit was de update. Oke. 988 01:23:38,390 --> 01:23:43,900 >> Nu binnenkant van hier zal ik de code even uitleggen in het belang van de tijd. 989 01:23:43,900 --> 01:23:46,350 Het is niet zo veel code. 990 01:23:50,770 --> 01:24:03,750 We zien lezen we een personage uit het bestand. We noemden het f. 991 01:24:03,750 --> 01:24:07,850 Nu kunt u man fgetc, maar hoe fgetc gaat werken 992 01:24:07,850 --> 01:24:11,910 is gewoon dat het gaat om het karakter dat je net hebt gelezen of EOF terug te keren, 993 01:24:11,910 --> 01:24:15,680 dat overeenkomt met het einde van het bestand of een foutmelding voorkomt. 994 01:24:15,680 --> 01:24:19,900 We looping, blijven een teken uit het bestand te lezen, 995 01:24:19,900 --> 01:24:22,420 totdat we opraken van de tekens te lezen. 996 01:24:22,420 --> 01:24:26,650 En terwijl we dat doen, we wachten op een teken van de standaard inch 997 01:24:26,650 --> 01:24:29,090 Elke keer dat je iets typt op de opdrachtregel, 998 01:24:29,090 --> 01:24:32,820 dat is te lezen in een personage uit standaard inch 999 01:24:32,820 --> 01:24:38,330 Dan putchar is gewoon naar de char lezen we hier van het bestand naar standaard uit te zetten. 1000 01:24:38,330 --> 01:24:42,890 U kunt de mens putchar, maar het is zomaar de standaard uit, het is het afdrukken van dat karakter. 1001 01:24:42,890 --> 01:24:51,600 Je kan ook gewoon printf doen ("% c", c); Zelfde idee. 1002 01:24:53,330 --> 01:24:56,670 Dat zal het grootste deel van ons werk te doen. 1003 01:24:56,670 --> 01:25:00,300 >> Het laatste wat we gaan willen doen is gewoon fclose ons bestand. 1004 01:25:00,300 --> 01:25:03,310 Als je niet fclose, dat is een geheugenlek. 1005 01:25:03,310 --> 01:25:06,680 We willen het bestand dat we oorspronkelijk geopend fclose, en ik denk dat is het. 1006 01:25:06,680 --> 01:25:13,810 Als we dat, ik heb al problemen. 1007 01:25:13,810 --> 01:25:17,260 Laten we eens kijken. 1008 01:25:17,260 --> 01:25:19,960 Wat heeft het klagen over? 1009 01:25:19,960 --> 01:25:30,220 Verwachte 'int', maar argument is van het type 'struct _IO_FILE *'. 1010 01:25:36,850 --> 01:25:39,370 We zullen zien of dat werkt. 1011 01:25:45,210 --> 01:25:53,540 Alleen toegestaan ​​in C99. Augh. Oke, maken hacker_typer. 1012 01:25:53,540 --> 01:25:57,760 Nu krijgen we meer bruikbare beschrijvingen. 1013 01:25:57,760 --> 01:25:59,900 Dus gebruik van niet-aangegeven identifier 'normal_settings'. 1014 01:25:59,900 --> 01:26:04,170 Ik heb niet noemen normal_settings. Ik noemde het current_settings. 1015 01:26:04,170 --> 01:26:12,090 Dus laten we veranderen allemaal. 1016 01:26:17,920 --> 01:26:21,710 Nu passeren argument. 1017 01:26:26,290 --> 01:26:29,500 Ik zal dit aan 0 voor nu. 1018 01:26:29,500 --> 01:26:36,720 Oke. . / Hacker_typer cp.c. 1019 01:26:36,720 --> 01:26:39,590 Ik wist ook het scherm niet duidelijk in het begin. 1020 01:26:39,590 --> 01:26:42,960 Maar je kunt terugkijken op het laatste probleem set om te zien hoe u het scherm leeg. 1021 01:26:42,960 --> 01:26:45,160 Het is gewoon af te drukken sommige karakters 1022 01:26:45,160 --> 01:26:47,210 terwijl dit te doen wat ik wil doen. 1023 01:26:47,210 --> 01:26:48,900 Oke. 1024 01:26:48,900 --> 01:26:55,280 En na te denken over waarom dit moest zijn 0 in plaats van stdin, 1025 01:26:55,280 --> 01:27:00,560 # die worden gedefinieerd 0, 1026 01:27:00,560 --> 01:27:03,890 Dit klaagt dat - 1027 01:27:13,150 --> 01:27:19,360 Voordat toen ik zei dat er file descriptors, maar dan heb je ook je FILE *, 1028 01:27:19,360 --> 01:27:23,210 een file descriptor is slechts een enkel geheel getal, 1029 01:27:23,210 --> 01:27:26,970 terwijl een FILE * heeft een heleboel dingen die ermee verbonden zijn. 1030 01:27:26,970 --> 01:27:30,380 De reden dat we nodig hebben om 0 te zeggen in plaats van stdin 1031 01:27:30,380 --> 01:27:37,480 is dat stdin is een FILE * die verwijst naar het ding dat verwijst file descriptor 0. 1032 01:27:37,480 --> 01:27:45,070 Dus zelfs hier als ik fopen doen (argv [1], ik krijg een FILE * terug. 1033 01:27:45,070 --> 01:27:51,180 Maar ergens in dat bestand * is een ding die overeenkomt met de file descriptor voor dat bestand. 1034 01:27:51,180 --> 01:27:57,430 Als je kijkt naar de man pagina voor open, dus ik denk dat je hoeft te doen man 3 open - nope - 1035 01:27:57,430 --> 01:27:59,380 man 2 open - ja. 1036 01:27:59,380 --> 01:28:06,250 Als je kijkt naar de pagina voor open, open is als een lager niveau fopen, 1037 01:28:06,250 --> 01:28:09,350 en het is het retourneren van de eigenlijke file descriptor. 1038 01:28:09,350 --> 01:28:12,050 fopen doet een heleboel dingen op de top van open, 1039 01:28:12,050 --> 01:28:17,640 die in plaats van terug te keren op dat bestand tem geeft een hele FILE * pointer 1040 01:28:17,640 --> 01:28:20,590 binnenkant van die onze kleine file descriptor. 1041 01:28:20,590 --> 01:28:25,020 Dus standaard in verwijst naar de FILE * ding, 1042 01:28:25,020 --> 01:28:29,120 terwijl 0 verwijst naar alleen de file descriptor standaard op zich. 1043 01:28:29,120 --> 01:28:32,160 >> Vragen? 1044 01:28:32,160 --> 01:28:35,930 [Lacht] Blew doorheen. 1045 01:28:35,930 --> 01:28:39,140 Oke. We zijn klaar. [Lacht] 1046 01:28:39,140 --> 01:28:42,000 >> [CS50.TV]