1 00:00:00,000 --> 00:00:02,490 [Powered by Google Translate] [CS50 Library] 2 00:00:02,490 --> 00:00:04,220 [Nate Hardison] [Harvard University] 3 00:00:04,220 --> 00:00:07,260 [Dit is CS50. CS50.TV] 4 00:00:07,260 --> 00:00:11,510 De CS50 bibliotheek is een handig hulpmiddel dat we hebben geïnstalleerd op het apparaat 5 00:00:11,510 --> 00:00:15,870 om het gemakkelijker maken voor u om programma's te schrijven die prompt gebruikers om input. 6 00:00:15,870 --> 00:00:21,670 In deze video gaan we trekken het gordijn en kijken naar wat er precies in de CS50 bibliotheek. 7 00:00:21,670 --> 00:00:25,520 >> In de video op C bibliotheken, we praten over hoe je # include headers bestanden 8 00:00:25,520 --> 00:00:27,570 van de bibliotheek in uw broncode, 9 00:00:27,570 --> 00:00:31,150 en dan heb je te verbinden met een binaire bibliotheek bestand tijdens het koppelen fase 10 00:00:31,150 --> 00:00:33,140 van de compilatie-proces. 11 00:00:33,140 --> 00:00:36,440 De header-bestanden geeft u de interface van de bibliotheek. 12 00:00:36,440 --> 00:00:41,280 Dat wil zeggen, ze detail alle middelen die de bibliotheek heeft voor u beschikbaar te gebruiken, 13 00:00:41,280 --> 00:00:45,250 zoals functie declaraties, constanten en gegevenstypen. 14 00:00:45,250 --> 00:00:48,890 De binaire bibliotheek bestand bevat de uitvoering van de bibliotheek, 15 00:00:48,890 --> 00:00:54,580 die is samengesteld uit header van de bibliotheek bestanden en de bibliotheek. c broncode-bestanden. 16 00:00:54,580 --> 00:00:59,820 >> Het binaire bibliotheek bestand is niet erg interessant om naar te kijken want het is, nou ja, in binaire. 17 00:00:59,820 --> 00:01:03,300 Dus, laten we een kijkje nemen op de header-bestanden voor de bibliotheek in plaats daarvan. 18 00:01:03,300 --> 00:01:07,710 In dit geval is er maar een header bestand genaamd cs50.h. 19 00:01:07,710 --> 00:01:11,040 We hebben geïnstalleerd in de gebruiker zijn directory 20 00:01:11,040 --> 00:01:15,150 samen met het andere systeem bibliotheken 'header-bestanden. 21 00:01:15,150 --> 00:01:21,530 >> Een van de eerste dingen die je zal opvallen is dat cs50.h # header-bestanden van andere bibliotheken omvat - 22 00:01:21,530 --> 00:01:25,670 vlotter, grenzen, standaard bool, en standaard lib. 23 00:01:25,670 --> 00:01:28,800 Nogmaals, volgens het principe van niet het wiel opnieuw uitvinden, 24 00:01:28,800 --> 00:01:33,490 we hebben opgebouwd de CS0 bibliotheek met behulp van tools die andere voorzien voor ons. 25 00:01:33,490 --> 00:01:38,690 >> Het volgende wat je ziet in de bibliotheek is dat we definiëren van een nieuw type genaamd "string". 26 00:01:38,690 --> 00:01:42,330 Deze lijn eigenlijk alleen maar creëert een alias voor de char * type, 27 00:01:42,330 --> 00:01:46,000 zodat het niet op magische wijze doordringen van de nieuwe string type met attributen 28 00:01:46,000 --> 00:01:49,650 vaak geassocieerd met String-objecten in andere talen, 29 00:01:49,650 --> 00:01:50,850 zoals lengte. 30 00:01:50,850 --> 00:01:55,180 De reden dat we dit gedaan hebt is om nieuwe programmeurs te beschermen tegen de bloedige details 31 00:01:55,180 --> 00:01:57,580 van pointers totdat ze klaar zijn. 32 00:01:57,580 --> 00:02:00,130 >> Het volgende deel van de header-bestand is de verklaring van de functies 33 00:02:00,130 --> 00:02:04,410 dat de CS50 bibliotheek biedt, samen met documentatie. 34 00:02:04,410 --> 00:02:06,940 Let op de mate van detail in de comments hier. 35 00:02:06,940 --> 00:02:10,560 Dit is super belangrijk, zodat mensen weten hoe deze functies te gebruiken. 36 00:02:10,560 --> 00:02:19,150 Wij verklaren op hun beurt functioneert om de gebruiker vragen en terug te keren tekens, doubles, drijvers, ints, 37 00:02:19,150 --> 00:02:24,160 lang naar verlangt, en strijkers, met behulp van onze eigen string type. 38 00:02:24,160 --> 00:02:26,260 Volgens het principe van informatie verbergen, 39 00:02:26,260 --> 00:02:31,640 hebben we onze definitie in een apart c implementatie-bestand -. cs50.c-- 40 00:02:31,640 --> 00:02:35,110 gelegen in de gebruiker bron directory. 41 00:02:35,110 --> 00:02:38,040 We hebben op voorwaarde dat bestand, zodat u kunt een kijkje nemen op het, 42 00:02:38,040 --> 00:02:41,490 leren, en het op verschillende machines hercompileren als je wilt, 43 00:02:41,490 --> 00:02:45,510 hoewel we denken dat het beter is om met het apparaat werken voor deze klasse. 44 00:02:45,510 --> 00:02:47,580 Hoe dan ook, laten we nu een kijkje nemen op het. 45 00:02:49,020 --> 00:02:54,620 >> De functies getchar, GetDouble, GetFloat, GetInt en GetLongLong 46 00:02:54,620 --> 00:02:58,160 zijn gebouwd bovenop de GetString functie. 47 00:02:58,160 --> 00:03:01,510 Het blijkt dat ze allemaal in wezen hetzelfde patroon volgen. 48 00:03:01,510 --> 00:03:04,870 Zij maken gebruik van een while-lus aan de gebruiker voor een lijn van invoer te vragen. 49 00:03:04,870 --> 00:03:08,430 Zij keren een bijzondere waarde als de gebruiker ingangen een lege regel. 50 00:03:08,430 --> 00:03:11,750 Ze proberen de gebruiker ingang ontleden als het juiste type, 51 00:03:11,750 --> 00:03:15,010 of het nu een char, een dubbele, een float, enz. 52 00:03:15,010 --> 00:03:18,710 En dan zijn ze ofwel terug te keren het resultaat als de ingang werd succesvol geparsed 53 00:03:18,710 --> 00:03:21,330 of ze reprompt de gebruiker. 54 00:03:21,330 --> 00:03:24,230 >> Op een hoog niveau, er is niets echt lastig hier. 55 00:03:24,230 --> 00:03:28,760 Je zou kunnen hebben geschreven op soortgelijke wijze gestructureerde code zelf in het verleden. 56 00:03:28,760 --> 00:03:34,720 Misschien wel het meest cryptische ogende deel is de sscanf gesprek dat invoer van de gebruiker parseert. 57 00:03:34,720 --> 00:03:38,160 Sscanf maakt deel uit van de input conversie familie. 58 00:03:38,160 --> 00:03:42,300 Het leeft in standaard io.h, en zijn werk is te ontleden een C string, 59 00:03:42,300 --> 00:03:46,520 volgens een bepaald formaat, opslaan van de resultaten in variabele parse 60 00:03:46,520 --> 00:03:48,720 die door de beller. 61 00:03:48,720 --> 00:03:53,570 Omdat de ingang conversie functies zijn zeer nuttig, op grote schaal gebruikte functies 62 00:03:53,570 --> 00:03:56,160 die niet zijn super intuïtief op het eerste, 63 00:03:56,160 --> 00:03:58,300 we gaan over hoe sscanf werkt. 64 00:03:58,300 --> 00:04:03,330 >> Het eerste argument om sscanf is een char * - een pointer naar een karakter. 65 00:04:03,330 --> 00:04:05,150 Voor de functie goed te laten werken, 66 00:04:05,150 --> 00:04:08,340 dat karakter zal het eerste teken van een C string zijn, 67 00:04:08,340 --> 00:04:12,270 beëindigd met de nul \ 0 karakter. 68 00:04:12,270 --> 00:04:15,120 Dit is de string te parsen 69 00:04:15,120 --> 00:04:18,269 Het tweede argument om sscanf is een format string, 70 00:04:18,269 --> 00:04:20,839 meestal doorgegeven als een string constante, 71 00:04:20,839 --> 00:04:24,040 en u zou kunnen hebben gezien een string als dit eerder bij het gebruik van printf. 72 00:04:24,040 --> 00:04:28,650 Een procent teken in de format string geeft een conversie specificatie. 73 00:04:28,650 --> 00:04:30,850 Het karakter onmiddellijk na een procent teken, 74 00:04:30,850 --> 00:04:35,430 geeft het C-type dat we willen sscanf converteren naar. 75 00:04:35,430 --> 00:04:40,090 In GetInt, zie je dat er een% d en een% c. 76 00:04:40,090 --> 00:04:48,690 Dit betekent dat sscanf zal proberen om een ​​decimaal int - de% d - en een char - de% c. 77 00:04:48,690 --> 00:04:51,510 Voor elke conversie specificatie in de format string, 78 00:04:51,510 --> 00:04:56,620 sscanf verwacht een corresponderende argument later in de lijst met argumenten. 79 00:04:56,620 --> 00:05:00,850 Dit argument moet verwijzen naar een voldoende getypte locatie 80 00:05:00,850 --> 00:05:04,000 waarin het resultaat van de conversie slaan. 81 00:05:04,000 --> 00:05:08,910 >> De typische manier om dit te doen is om een ​​variabele te maken op de stapel voor de sscanf oproep 82 00:05:08,910 --> 00:05:11,440 voor elk item dat u wilt parseren op basis van de string 83 00:05:11,440 --> 00:05:15,520 en gebruik dan de adres-operator - de ampersand - om pointers geven 84 00:05:15,520 --> 00:05:19,100 variabelen die de sscanf gesprek. 85 00:05:19,100 --> 00:05:22,720 Je kunt zien dat in GetInt we precies doen. 86 00:05:22,720 --> 00:05:28,240 Vlak voor de sscanf oproep, verklaren we een int genoemd n en een char oproep c op de stapel, 87 00:05:28,240 --> 00:05:32,340 en passeren we verwijzingen naar hen in de sscanf gesprek. 88 00:05:32,340 --> 00:05:35,800 Putting deze variabelen op de stack heeft de voorkeur boven het gebruik van toegewezen ruimte 89 00:05:35,800 --> 00:05:39,350 op de heap met malloc, omdat je de overhead van de malloc oproep te voorkomen, 90 00:05:39,350 --> 00:05:43,060 en je hoeft geen zorgen te maken over het lekken geheugen. 91 00:05:43,060 --> 00:05:47,280 Tekens niet voorafgegaan door een procentteken niet vragen conversie. 92 00:05:47,280 --> 00:05:50,380 In plaats van ze alleen maar toe te voegen aan het formaat specificatie. 93 00:05:50,380 --> 00:05:56,500 >> Als bijvoorbeeld de opmaakreeks in GetInt waren% d plaats, 94 00:05:56,500 --> 00:05:59,800 sscanf zou kijken naar de letter een, gevolgd door een int, 95 00:05:59,800 --> 00:06:04,360 en terwijl het zou proberen om de int te zetten, zou het niet iets anders doen met de een. 96 00:06:04,360 --> 00:06:07,440 De enige uitzondering hierop is witruimte. 97 00:06:07,440 --> 00:06:11,030 Witruimte tekens in de format string passende hoeveelheid witruimte - 98 00:06:11,030 --> 00:06:12,890 zelfs helemaal geen. 99 00:06:12,890 --> 00:06:18,100 Dus, dat is de reden waarom de opmerking vermeldt eventueel met voor-en / of eindigen met spaties. 100 00:06:18,100 --> 00:06:22,910 Dus, zal proberen op dit punt lijkt ons sscanf oproep aan de gebruiker input string parsen 101 00:06:22,910 --> 00:06:25,380 door te controleren op mogelijke toonaangevende witruimte, 102 00:06:25,380 --> 00:06:29,300 gevolgd door een int die wordt omgezet en opgeslagen in de variabele n int 103 00:06:29,300 --> 00:06:33,090 gevolgd door een hoeveelheid witruimte en gevolgd door een teken 104 00:06:33,090 --> 00:06:35,810 opgeslagen in de char variabele c. 105 00:06:35,810 --> 00:06:37,790 >> Hoe zit het met de return waarde? 106 00:06:37,790 --> 00:06:41,560 Sscanf zal ontleden de invoerregel van begin tot eind, 107 00:06:41,560 --> 00:06:44,860 stoppen wanneer zij tot het einde of bij een karakter in de input 108 00:06:44,860 --> 00:06:49,320 komt niet overeen met een format of wanneer het niet kan maken een conversie. 109 00:06:49,320 --> 00:06:52,690 Het rendement van waarde wordt gebruikt om enkel wanneer het gestopt. 110 00:06:52,690 --> 00:06:55,670 Indien gestopt, omdat het einde van de invoertekenreeks 111 00:06:55,670 --> 00:07:00,630 voordat u conversies en alvorens het als mislukt om een ​​deel van de format string overeenkomt, 112 00:07:00,630 --> 00:07:04,840 dan is de speciale constante EOF wordt geretourneerd. 113 00:07:04,840 --> 00:07:08,200 Anders wordt het aantal succesvolle conversies, 114 00:07:08,200 --> 00:07:14,380 waardoor 0, 1 of 2, want heeft gevraagd twee conversies. 115 00:07:14,380 --> 00:07:19,000 In ons geval willen we ervoor zorgen dat de gebruiker heeft ingevoerd in een int en alleen een int. 116 00:07:19,000 --> 00:07:23,370 >> Dus willen we sscanf tot 1 terug te keren. Zie waarom? 117 00:07:23,370 --> 00:07:26,850 Als sscanf leverde 0, dan is er geen conversies werden gemaakt, 118 00:07:26,850 --> 00:07:31,690 zodat de gebruiker heeft ingevoerd iets anders dan een int begin van de ingang. 119 00:07:31,690 --> 00:07:37,100 Als sscanf retourneert 2, dan is de gebruiker heeft goed typt u deze in het begin van de input, 120 00:07:37,100 --> 00:07:41,390 maar ze vervolgens getypt in een aantal niet-scheidingsteken achteraf 121 00:07:41,390 --> 00:07:44,940 omdat de% c conversie gelukt. 122 00:07:44,940 --> 00:07:49,570 Wow, dat is nogal een uitgebreide uitleg voor een functie oproep. 123 00:07:49,570 --> 00:07:53,460 Hoe dan ook, als je wilt meer informatie over sscanf en haar broers en zussen, 124 00:07:53,460 --> 00:07:57,130 check out de man pagina's, Google, of beide. 125 00:07:57,130 --> 00:07:58,780 Er zijn tal van format string opties, 126 00:07:58,780 --> 00:08:03,830 en deze kunnen besparen u een hoop handwerk wanneer het proberen om strings te ontleden in C. 127 00:08:03,830 --> 00:08:07,180 >> De laatste functie in de bibliotheek om te kijken is GetString. 128 00:08:07,180 --> 00:08:10,310 Het blijkt dat GetString is een lastige functie om goed te schrijven, 129 00:08:10,310 --> 00:08:14,290 ook al lijkt zo'n eenvoudige, gemeenschappelijke taak. 130 00:08:14,290 --> 00:08:16,170 Waarom is dit het geval? 131 00:08:16,170 --> 00:08:21,380 Nou, laten we nadenken over hoe we gaan de lijn op te slaan dat de gebruiker typt inch 132 00:08:21,380 --> 00:08:23,880 Omdat een string is een opeenvolging van tekens, 133 00:08:23,880 --> 00:08:26,430 we zouden willen op te slaan in een array op de stapel, 134 00:08:26,430 --> 00:08:31,250 maar we zouden moeten weten hoe lang de array zal zijn wanneer we het te verklaren. 135 00:08:31,250 --> 00:08:34,030 Evenzo, als we willen het op de hoop, 136 00:08:34,030 --> 00:08:38,090 moeten we doorgeven aan malloc het aantal bytes dat we willen reserveren, 137 00:08:38,090 --> 00:08:39,730 maar dit is onmogelijk. 138 00:08:39,730 --> 00:08:42,760 We hebben geen idee hoeveel tekens de gebruiker typt in 139 00:08:42,760 --> 00:08:46,590 voordat de gebruiker doet eigenlijk typt. 140 00:08:46,590 --> 00:08:50,720 >> Een naïeve oplossing voor dit probleem is om gewoon behouden een groot deel van de ruimte, bijvoorbeeld 141 00:08:50,720 --> 00:08:54,540 een blok van 1000 tekens voor invoer van de gebruiker, 142 00:08:54,540 --> 00:08:57,980 in de veronderstelling dat de gebruiker nooit zou typen in een string zo lang. 143 00:08:57,980 --> 00:09:00,810 Dit is een slecht idee om twee redenen. 144 00:09:00,810 --> 00:09:05,280 Ten eerste, in de veronderstelling dat gebruikers meestal niet typen in snaren die lange, 145 00:09:05,280 --> 00:09:07,610 je zou verspillen veel geheugen. 146 00:09:07,610 --> 00:09:10,530 Op moderne machines, zou dit niet een probleem als je dit doet 147 00:09:10,530 --> 00:09:13,890 in een of twee afzonderlijke gevallen 148 00:09:13,890 --> 00:09:17,630 maar als je het nemen van gebruikers input in een lus en opslaan voor later gebruik, 149 00:09:17,630 --> 00:09:20,870 kunt u snel opzuigen van een ton van het geheugen. 150 00:09:20,870 --> 00:09:24,450 Bovendien, als het programma dat u aan het schrijven bent is voor een kleinere computer - 151 00:09:24,450 --> 00:09:28,100 een apparaat zoals een smartphone of iets anders met een beperkt geheugen - 152 00:09:28,100 --> 00:09:32,060 deze oplossing problemen veel sneller. 153 00:09:32,060 --> 00:09:36,450 De tweede, meer serieuze reden om dit niet doen is dat het uw programma kwetsbaar verlaat 154 00:09:36,450 --> 00:09:39,710 aan wat heet een buffer overflow aanval. 155 00:09:39,710 --> 00:09:45,840 Bij het programmeren, een buffer is het geheugen wordt gebruikt voor de tijdelijke opslag in-of uitgang van gegevens, 156 00:09:45,840 --> 00:09:48,980 in dit geval is onze 1000 char blok. 157 00:09:48,980 --> 00:09:53,370 Een buffer overflow optreedt wanneer gegevens geschreven voorbij het einde van het blok. 158 00:09:53,370 --> 00:09:57,790 >> Als bijvoorbeeld een gebruiker daadwerkelijk soort doet in meer dan 1000 tekens. 159 00:09:57,790 --> 00:10:01,570 Je zou kunnen hebben ervaren per ongeluk bij het programmeren met arrays. 160 00:10:01,570 --> 00:10:05,620 Als u een array van 10 ints, niets houdt je tegen probeert te lezen of te schrijven 161 00:10:05,620 --> 00:10:07,810 15 int. 162 00:10:07,810 --> 00:10:10,000 Er zijn geen compiler waarschuwingen of fouten. 163 00:10:10,000 --> 00:10:13,250 Het programma gewoon blunders rechtdoor en toegang tot het geheugen 164 00:10:13,250 --> 00:10:18,150 waar hij denkt dat de 15e int zal zijn, en dit kan overschrijven uw andere variabelen. 165 00:10:18,150 --> 00:10:22,040 In het ergste geval kunt u overschrijven enkele van interne je programma's 166 00:10:22,040 --> 00:10:26,820 controlemechanismen, het veroorzaken van uw programma daadwerkelijk uit te voeren verschillende instructies 167 00:10:26,820 --> 00:10:28,340 dan je bedoeling was. 168 00:10:28,340 --> 00:10:31,360 >> Nu, het is niet gebruikelijk om per ongeluk doen, 169 00:10:31,360 --> 00:10:35,150 maar dit is een vrij algemeen techniek die slechteriken gebruiken om programma's te doorbreken 170 00:10:35,150 --> 00:10:39,080 en zet kwaadaardige code op andermans computer. 171 00:10:39,080 --> 00:10:42,910 Daarom kunnen we niet alleen gebruik maken van onze naïeve oplossing. 172 00:10:42,910 --> 00:10:45,590 We moeten een manier vinden om onze programma's te voorkomen dat kwetsbare 173 00:10:45,590 --> 00:10:47,880 voor een buffer overflow aanval. 174 00:10:47,880 --> 00:10:51,430 Om dit te doen, moeten we ervoor zorgen dat onze buffer kan groeien als we lezen 175 00:10:51,430 --> 00:10:53,850 meer input van de gebruiker. 176 00:10:53,850 --> 00:10:57,440 De oplossing? We gebruiken een hoop toegewezen buffer. 177 00:10:57,440 --> 00:10:59,950 Aangezien wij kunt de grootte van het gebruik van de de grootte van de realloc functie, 178 00:10:59,950 --> 00:11:04,580 en we houden van twee getallen - de index van de volgende lege sleuf in de buffer 179 00:11:04,580 --> 00:11:08,390 en door de lengte van de buffer. 180 00:11:08,390 --> 00:11:13,210 We lezen in tekens van de gebruiker een voor een met de fgetc functie. 181 00:11:13,210 --> 00:11:19,360 Het argument van de fgetc functie neemt - stdin - is een verwijzing naar de standaard input string, 182 00:11:19,360 --> 00:11:23,810 die een voorgeschakelde ingangskanaal waarmee invoer van de gebruiker overbrengen 183 00:11:23,810 --> 00:11:26,270 van de terminal naar het programma. 184 00:11:26,270 --> 00:11:29,890 >> Wanneer de gebruiker een nieuw karakter, we controleren of de index 185 00:11:29,890 --> 00:11:35,810 van de volgende vrije slot plus 1 groter is dan de capaciteit van de buffer. 186 00:11:35,810 --> 00:11:39,690 De +1 komt in, want als de volgende vrije index is 5, 187 00:11:39,690 --> 00:11:44,150 dan is onze buffer lengte moet 6 dankzij 0 indexering. 188 00:11:44,150 --> 00:11:48,350 Als we geen ruimte meer in de buffer, dan proberen we hem te vergroten of verkleinen, 189 00:11:48,350 --> 00:11:51,690 een verdubbeling van het zo dat we bezuinigen op het aantal keren dat we de grootte van 190 00:11:51,690 --> 00:11:54,760 als de gebruiker in te typen een heel lange string. 191 00:11:54,760 --> 00:11:57,950 Als de string heeft gekregen te lang is of als we opraken van heap-geheugen, 192 00:11:57,950 --> 00:12:01,350 bevrijden we onze buffer en terug te keren null. 193 00:12:01,350 --> 00:12:04,170 >> Tenslotte voegt de char we de buffer. 194 00:12:04,170 --> 00:12:08,200 Zodra de gebruiker op Enter of Return, het signaleren van een nieuwe lijn, 195 00:12:08,200 --> 00:12:12,050 of de speciale tekens - controle d - die een einde van de ingangssignalen, 196 00:12:12,050 --> 00:12:16,240 we doen een controle om te zien of de gebruiker daadwerkelijk getypt in helemaal niets. 197 00:12:16,240 --> 00:12:18,820 Zo niet, dan keren we terug null. 198 00:12:18,820 --> 00:12:22,280 Anders, omdat onze buffer is waarschijnlijk groter dan we nodig hebben, 199 00:12:22,280 --> 00:12:24,830 in het ergste geval bijna tweemaal zo groot als we 200 00:12:24,830 --> 00:12:27,830 omdat we verdubbelen elke keer als we vergroten of verkleinen, 201 00:12:27,830 --> 00:12:31,840 maken we een nieuwe kopie van de string met behulp van alleen de hoeveelheid ruimte die we nodig hebben. 202 00:12:31,840 --> 00:12:34,220 We voegen een extra 1 tot en met de malloc oproep, 203 00:12:34,220 --> 00:12:37,810 zodat er ruimte is voor de speciale null-terminator karakter - de \ 0, 204 00:12:37,810 --> 00:12:41,990 die we toevoegen aan de string een keer kopiëren we in de rest van de personages, 205 00:12:41,990 --> 00:12:45,060 met strncpy plaats van strcpy 206 00:12:45,060 --> 00:12:48,830 zodat wij precies aan te geven hoeveel tekens we willen kopiëren. 207 00:12:48,830 --> 00:12:51,690 Strcpy kopieert totdat het een \ 0. 208 00:12:51,690 --> 00:12:55,740 Dan bevrijden we onze buffer en zendt het exemplaar naar de beller. 209 00:12:55,740 --> 00:12:59,840 >> Wie had gedacht dat een dergelijke eenvoudige uitziende functie kan zo ingewikkeld? 210 00:12:59,840 --> 00:13:02,820 Nu weet je wat er in de CS50 bibliotheek. 211 00:13:02,820 --> 00:13:06,470 >> Mijn naam is Nate Hardison, en dit is CS50. 212 00:13:06,470 --> 00:13:08,350 [CS50.TV]