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 Egyetem] 3 00:00:04,220 --> 00:00:07,260 [Ez CS50. CS50.TV] 4 00:00:07,260 --> 00:00:11,510 A CS50 könyvtár egy hasznos eszköz, hogy már telepített a készülékre 5 00:00:11,510 --> 00:00:15,870 annak érdekében, hogy könnyebben programokat írhassanak, hogy a prompt felhasználók bemenet. 6 00:00:15,870 --> 00:00:21,670 Ebben a videóban, akkor húzza vissza a függönyt, és nézd meg, mi is pontosan a CS50 könyvtárban. 7 00:00:21,670 --> 00:00:25,520 >> A videó a C könyvtárak, beszélünk arról, hogy hogyan # include fejléc fájlokat 8 00:00:25,520 --> 00:00:27,570 A könyvtár a forráskódot, 9 00:00:27,570 --> 00:00:31,150 és akkor összekapcsolni egy bináris könyvtárfájlt alatt összekötő szakasz 10 00:00:31,150 --> 00:00:33,140 A fordítási folyamat. 11 00:00:33,140 --> 00:00:36,440 A fejléc fájlokat adja meg a felület a könyvtár. 12 00:00:36,440 --> 00:00:41,280 Ez azt jelenti, hogy minden részlet a források, hogy a könyvtár áll rendelkezésre, hogy használd, 13 00:00:41,280 --> 00:00:45,250 mint funkció nyilatkozatok, állandók, és adattípusok. 14 00:00:45,250 --> 00:00:48,890 A bináris könyvtár fájl tartalmazza a végrehajtását a könyvtár, 15 00:00:48,890 --> 00:00:54,580 amely össze a könyvtár header fájlokat és a könyvtár. c forráskód fájlokat. 16 00:00:54,580 --> 00:00:59,820 >> A bináris könyvtár fájl nem nagyon érdekes, hogy nézd meg, mivel ez, nos, a bináris. 17 00:00:59,820 --> 00:01:03,300 Nos, vessünk egy pillantást a header fájlokat a könyvtár helyett. 18 00:01:03,300 --> 00:01:07,710 Ebben az esetben csak egy header file neve cs50.h. 19 00:01:07,710 --> 00:01:11,040 Már telepítettem a felhasználói include könyvtárban 20 00:01:11,040 --> 00:01:15,150 együtt a másik rendszer könyvtárak header fájlokat. 21 00:01:15,150 --> 00:01:21,530 >> Az egyik első dolog, észre fogod venni, hogy az magában foglalja a cs50.h # header fájlokat más könyvtárak - 22 00:01:21,530 --> 00:01:25,670 úszó, korlátok, standard bool, és a standard lib. 23 00:01:25,670 --> 00:01:28,800 Ismét elvét követve nem újra feltalálja a kereket, 24 00:01:28,800 --> 00:01:33,490 hoztuk létre a könyvtárat CS0 eszközök használatával, hogy a többi biztosított számunkra. 25 00:01:33,490 --> 00:01:38,690 >> A következő dolog, látni fogod, a könyvtárban, hogy mi határozza meg egy új típusú úgynevezett "string." 26 00:01:38,690 --> 00:01:42,330 Ez a vonal tényleg csak létrehoz egy fedőnevet a char * típusú, 27 00:01:42,330 --> 00:01:46,000 így nem mágikusan beivódnak az új karakterlánc típusú attribútumok 28 00:01:46,000 --> 00:01:49,650 gyakran társul húr tárgyakat más nyelveken, 29 00:01:49,650 --> 00:01:50,850 mint a hossza. 30 00:01:50,850 --> 00:01:55,180 Azért tettem ezt, hogy megvédje új programozók a véres részletek 31 00:01:55,180 --> 00:01:57,580 mutatókat amíg készen. 32 00:01:57,580 --> 00:02:00,130 >> A következő rész a fejléc fájl a nyilatkozatot a funkciók 33 00:02:00,130 --> 00:02:04,410 hogy a CS50 könyvtár együtt dokumentációt. 34 00:02:04,410 --> 00:02:06,940 Figyeljük meg a részletezettség szintjét a megjegyzések itt. 35 00:02:06,940 --> 00:02:10,560 Ez szuper fontos, hogy az emberek tudják, hogyan kell használni ezeket a funkciókat. 36 00:02:10,560 --> 00:02:19,150 Kijelentjük, viszont működik, hogy figyelmezteti a felhasználót és a visszatérő karakter, kétágyas, úszók, ints, 37 00:02:19,150 --> 00:02:24,160 Hosszú vágyik, és a vonósok, a saját string típusú. 38 00:02:24,160 --> 00:02:26,260 Elvét követve az információ rejtőzik, 39 00:02:26,260 --> 00:02:31,640 mi valósult meg a meghatározást egy külön. c végrehajtás fájl - cs50.c-- 40 00:02:31,640 --> 00:02:35,110 található, a felhasználói forrás könyvtárba. 41 00:02:35,110 --> 00:02:38,040 Már feltéve, hogy a fájl így vessen egy pillantást rá, 42 00:02:38,040 --> 00:02:41,490 tanulni, és újrafordítani azt különböző gépeken, ha szeretné, 43 00:02:41,490 --> 00:02:45,510 még ha azt gondoljuk, hogy jobb dolgozni a készüléket ebben az osztályban. 44 00:02:45,510 --> 00:02:47,580 Mindegy, vessünk egy pillantást a most. 45 00:02:49,020 --> 00:02:54,620 >> A funkciók GetChar, GetDouble, getFloat, getInt és GetLongLong 46 00:02:54,620 --> 00:02:58,160 mind épül a getString funkciót. 47 00:02:58,160 --> 00:03:01,510 Kiderül, hogy mindannyian követik lényegében ugyanazt a mintát. 48 00:03:01,510 --> 00:03:04,870 Ezek használata while kérje a felhasználótól egy sor bemenet. 49 00:03:04,870 --> 00:03:08,430 Ők vissza különleges értéket, ha a felhasználó be egy üres sort. 50 00:03:08,430 --> 00:03:11,750 Azt próbálja meg értelmezni a felhasználó bemenet a megfelelő típust, 51 00:03:11,750 --> 00:03:15,010 legyen az char, egy kétágyas, egy úszó, stb 52 00:03:15,010 --> 00:03:18,710 És akkor sem tér vissza az eredmény, ha a bemeneti sikeresen értelmezhető 53 00:03:18,710 --> 00:03:21,330 vagy azok reprompt a felhasználó. 54 00:03:21,330 --> 00:03:24,230 >> Egy magas szintű, semmi sem igazán trükkös itt. 55 00:03:24,230 --> 00:03:28,760 Lehet, hogy írt hasonlóan szerkesztett kódot magad a múltban. 56 00:03:28,760 --> 00:03:34,720 Talán a leginkább titokzatos kinézetű része a sscanf hívást, hogy elemzi a felhasználó bemenet. 57 00:03:34,720 --> 00:03:38,160 Sscanf része a bemeneti formátum konverziós család. 58 00:03:38,160 --> 00:03:42,300 Él standard io.h, és a feladata, hogy elemezze a C string, 59 00:03:42,300 --> 00:03:46,520 szerint egy adott formában, tárolja a feldolgozási eredményeket változó 60 00:03:46,520 --> 00:03:48,720 által a hívó. 61 00:03:48,720 --> 00:03:53,570 Mivel a bemeneti formátum konverziós funkció nagyon hasznos, széles körben használt funkcióit 62 00:03:53,570 --> 00:03:56,160 , amelyek nem szuper intuitív először, 63 00:03:56,160 --> 00:03:58,300 megyünk át, hogyan sscanf működik. 64 00:03:58,300 --> 00:04:03,330 >> Az első érv, hogy sscanf egy char * - a mutató egy karaktert. 65 00:04:03,330 --> 00:04:05,150 A funkció működik megfelelően, 66 00:04:05,150 --> 00:04:08,340 hogy a karakter legyen az első karaktere a C string, 67 00:04:08,340 --> 00:04:12,270 leállt a null \ 0 karakter. 68 00:04:12,270 --> 00:04:15,120 Ez a string értelmezni 69 00:04:15,120 --> 00:04:18,269 A második érv, hogy sscanf egy formátum string, 70 00:04:18,269 --> 00:04:20,839 jellegzetesen telt, mint egy string állandó, 71 00:04:20,839 --> 00:04:24,040 és lehet, hogy láttam egy string, mint ez előtt használatakor printf. 72 00:04:24,040 --> 00:04:28,650 A százalék jel a format string jelez az átalakítás meghatározása. 73 00:04:28,650 --> 00:04:30,850 A karakter követő egy százalék jelet, 74 00:04:30,850 --> 00:04:35,430 jelzi, C típusú, hogy szeretnénk sscanf konvertálni. 75 00:04:35,430 --> 00:04:40,090 A getInt, látod, hogy van egy% d és% c. 76 00:04:40,090 --> 00:04:48,690 Ez azt jelenti, hogy sscanf megpróbál decimális int - a% d - és a char - a% c. 77 00:04:48,690 --> 00:04:51,510 Minden átalakító meghatározása az a formátum string, 78 00:04:51,510 --> 00:04:56,620 sscanf elvárja a megfelelő érvet később a paraméterek listája. 79 00:04:56,620 --> 00:05:00,850 Ez az érv kell mutatnia egy megfelelően tipizált location 80 00:05:00,850 --> 00:05:04,000 amelyben tárolni az eredményét a konverzió. 81 00:05:04,000 --> 00:05:08,910 >> A tipikus módja ennek az, hogy hozzon létre egy változót a verem előtt sscanf hívás 82 00:05:08,910 --> 00:05:11,440 minden kívánt elemet értelmezni a húr 83 00:05:11,440 --> 00:05:15,520 majd a cím operátor - a jelet - át mutatók 84 00:05:15,520 --> 00:05:19,100 e változók a sscanf hívást. 85 00:05:19,100 --> 00:05:22,720 Láthatjuk, hogy a getInt mi pontosan ezt. 86 00:05:22,720 --> 00:05:28,240 Jobb előtt sscanf hívást, akkor állapítsa int hívott n, és egy char c hívás a verem, 87 00:05:28,240 --> 00:05:32,340 és mi át mutatókat őket a sscanf hívást. 88 00:05:32,340 --> 00:05:35,800 Elhelyezés ezek a változók a verem előnyösebb, mint a térben elkülönített 89 00:05:35,800 --> 00:05:39,350 A heap a malloc, mert így elkerülhető a felső a malloc hívás 90 00:05:39,350 --> 00:05:43,060 és nem kell aggódnod szivárgó memóriát. 91 00:05:43,060 --> 00:05:47,280 Karakterek nem előtaggal a százalék jel nem kér konverziót. 92 00:05:47,280 --> 00:05:50,380 Inkább csak hozzá a formátum specifikáció. 93 00:05:50,380 --> 00:05:56,500 >> Például, ha a formátum karakterláncot getInt volt egy% d helyette, 94 00:05:56,500 --> 00:05:59,800 sscanf nézne ki a levelet egy, majd egy int, 95 00:05:59,800 --> 00:06:04,360 és bár ez megpróbálja átalakítani a int, hogy nem csinál semmi mást az a. 96 00:06:04,360 --> 00:06:07,440 Az egyetlen kivétel ez alól whitespace. 97 00:06:07,440 --> 00:06:11,030 White space karaktereket a format string meccsek bármilyen összegű whitespace - 98 00:06:11,030 --> 00:06:12,890 még egyáltalán. 99 00:06:12,890 --> 00:06:18,100 Szóval, ezért a kommentár említi esetleg vezető-és / vagy záró szóközöket. 100 00:06:18,100 --> 00:06:22,910 Szóval, ezen a ponton úgy néz ki, mint a mi sscanf hívás megpróbálja elemezni a felhasználó bemeneti karakterlánc 101 00:06:22,910 --> 00:06:25,380 ellenőrzésével lehetséges vezető szóközök, 102 00:06:25,380 --> 00:06:29,300 követ int, hogy lesz átváltani, és tárolni az int változó n 103 00:06:29,300 --> 00:06:33,090 majd bizonyos mennyiségű whitespace, és utána egy karakter 104 00:06:33,090 --> 00:06:35,810 tárolt char változó c. 105 00:06:35,810 --> 00:06:37,790 >> Mi a helyzet a visszatérési érték? 106 00:06:37,790 --> 00:06:41,560 Sscanf fogja elemezni a beviteli sor az elejétől a végéig, 107 00:06:41,560 --> 00:06:44,860 megállás, amikor az eléri a vég, vagy ha egy karakter a bemenő 108 00:06:44,860 --> 00:06:49,320 nem felel meg a formátum karaktert, vagy ha nem tudja, hogy egy konverzió. 109 00:06:49,320 --> 00:06:52,690 Ez a visszatérési értéket használja azonosítottam, amikor megállt. 110 00:06:52,690 --> 00:06:55,670 Ha megállt, mert elérte a végét a bemeneti karakterlánc 111 00:06:55,670 --> 00:07:00,630 mielőtt bármilyen konverziók előtt nem, hogy megfeleljen része a format string, 112 00:07:00,630 --> 00:07:04,840 akkor a speciális konstans EOF vissza. 113 00:07:04,840 --> 00:07:08,200 Ellenkező esetben, visszatér a sikeres konverziók, 114 00:07:08,200 --> 00:07:14,380 amely lehet 0, 1, vagy 2, hiszen már kért két konverziót. 115 00:07:14,380 --> 00:07:19,000 A mi esetünkben azt szeretnénk, hogy győződjön meg arról, hogy a felhasználó beírt egy int, és csak int. 116 00:07:19,000 --> 00:07:23,370 >> Szóval, mi szeretnénk sscanf vissza 1. Nézze meg, miért? 117 00:07:23,370 --> 00:07:26,850 Ha sscanf vissza 0, akkor nincs konverzió történt, 118 00:07:26,850 --> 00:07:31,690 így a felhasználó beírt valami más, mint egy int elején a bemenet. 119 00:07:31,690 --> 00:07:37,100 Ha sscanf visszatér 2, akkor a felhasználó nem megfelelően gépelje be az elején a bemeneti, 120 00:07:37,100 --> 00:07:41,390 de aztán beírt néhány nem szóköz-karaktere utána 121 00:07:41,390 --> 00:07:44,940 mivel a% c konverzió sikerült. 122 00:07:44,940 --> 00:07:49,570 Wow, ez elég hosszú magyarázatot egy függvényhívás. 123 00:07:49,570 --> 00:07:53,460 Egyébként, ha többet szeretne tudni sscanf és testvérek, 124 00:07:53,460 --> 00:07:57,130 nézd meg a man oldalakat, a Google, vagy mindkettő. 125 00:07:57,130 --> 00:07:58,780 Sok format string lehetőségek, 126 00:07:58,780 --> 00:08:03,830 és ezek mentheti meg egy csomó manuális munka, amikor megpróbálják értelmezni húrok C. 127 00:08:03,830 --> 00:08:07,180 >> Az utolsó funkció a könyvtárban, hogy nézd meg getString. 128 00:08:07,180 --> 00:08:10,310 Kiderül, hogy getString egy trükkös funkció írni megfelelően, 129 00:08:10,310 --> 00:08:14,290 bár úgy tűnik, mint egy ilyen egyszerű, közös feladat. 130 00:08:14,290 --> 00:08:16,170 Miért van ez így? 131 00:08:16,170 --> 00:08:21,380 Hát, gondolom, arról, hogy hogyan fogjuk tárolni a sort, hogy a felhasználói típusokat be 132 00:08:21,380 --> 00:08:23,880 Mivel a string sorozata karakter, 133 00:08:23,880 --> 00:08:26,430 talán szeretnénk tárolni egy tömbben a stack, 134 00:08:26,430 --> 00:08:31,250 de azt kell tudni, hogy milyen hosszú a tömb lesz, amikor nyilvánítja. 135 00:08:31,250 --> 00:08:34,030 Hasonlóképpen, ha azt akarjuk, hogy azt a halom, 136 00:08:34,030 --> 00:08:38,090 kell átadni a malloc bájtok számát szeretnénk tartalékba, 137 00:08:38,090 --> 00:08:39,730 ez azonban nem lehetséges. 138 00:08:39,730 --> 00:08:42,760 Fogalmunk sincs, hogy hány karakter a felhasználó írja 139 00:08:42,760 --> 00:08:46,590 mielőtt a felhasználó valóban nem írja őket. 140 00:08:46,590 --> 00:08:50,720 >> A naiv megoldás erre a problémára az, hogy csak fenn egy nagy darab helyet, mondjuk, 141 00:08:50,720 --> 00:08:54,540 egy blokk az 1000 karakter a felhasználó bemenet, 142 00:08:54,540 --> 00:08:57,980 feltételezve, hogy a felhasználó soha nem írjon be egy string, amely hosszú. 143 00:08:57,980 --> 00:09:00,810 Ez egy rossz ötlet, két okból. 144 00:09:00,810 --> 00:09:05,280 Először is, feltételezve, hogy a felhasználók általában nem írja be a vonósok, hogy a hosszú, 145 00:09:05,280 --> 00:09:07,610 akkor hulladék rengeteg memória. 146 00:09:07,610 --> 00:09:10,530 A modern gépek, ez nem lehet probléma, ha ezt 147 00:09:10,530 --> 00:09:13,890 egy vagy két egyedi esettől, 148 00:09:13,890 --> 00:09:17,630 de ha veszed felhasználói input egy hurok és tárolását későbbi használatra, 149 00:09:17,630 --> 00:09:20,870 gyorsan szopni egy csomó memória. 150 00:09:20,870 --> 00:09:24,450 Továbbá, ha a programot írsz Az egy kisebb számítógép - 151 00:09:24,450 --> 00:09:28,100 Egy eszköz, mint egy okostelefon, vagy valami más korlátozott memória - 152 00:09:28,100 --> 00:09:32,060 ez a megoldás problémát fog okozni sokkal gyorsabb. 153 00:09:32,060 --> 00:09:36,450 A második, komolyabb ok arra, hogy nem ez az, hogy nem hagy a program sebezhető 154 00:09:36,450 --> 00:09:39,710 hogy az úgynevezett puffer túlcsordulást támadást. 155 00:09:39,710 --> 00:09:45,840 A programozás, a puffer memória átmeneti tárolására bemeneti vagy kimeneti adatokat, 156 00:09:45,840 --> 00:09:48,980 amely ebben az esetben a mi 1000-char blokk. 157 00:09:48,980 --> 00:09:53,370 Puffer túlcsordulás akkor beszélünk, ha az adatok írása múlt az a mondat végén. 158 00:09:53,370 --> 00:09:57,790 >> Például, ha a felhasználó valójában mire típus több, mint 1000 karakter. 159 00:09:57,790 --> 00:10:01,570 Lehet, hogy tapasztalta ezt véletlenül programozás a tömbök. 160 00:10:01,570 --> 00:10:05,620 Ha van egy sor 10 ints, semmi nem gátolja Önt próbál írni vagy olvasni 161 00:10:05,620 --> 00:10:07,810 15. int. 162 00:10:07,810 --> 00:10:10,000 Nincsenek fordító figyelmeztetések vagy hibák. 163 00:10:10,000 --> 00:10:13,250 A program csak a baklövéseket egyenesen előre, és hozzáfér a memória 164 00:10:13,250 --> 00:10:18,150 ha úgy gondolja, a 15. int lesz, és ez felülírja a többi változót. 165 00:10:18,150 --> 00:10:22,040 A legrosszabb esetben, akkor felülírhatja néhány program belső 166 00:10:22,040 --> 00:10:26,820 ellenőrzési mechanizmusok, így a program, hogy ténylegesen végrehajtani különböző utasítások 167 00:10:26,820 --> 00:10:28,340 , mint ahogy tervezte. 168 00:10:28,340 --> 00:10:31,360 >> Nos, ez nem gyakori, hogy ezt véletlenül, 169 00:10:31,360 --> 00:10:35,150 de ez egy meglehetősen gyakori módszer, hogy a rossz fiúk használják megtörni programok 170 00:10:35,150 --> 00:10:39,080 és tedd rosszindulatú kódot mások számítógépeken. 171 00:10:39,080 --> 00:10:42,910 Ezért nem lehet csak használni a naiv megoldást. 172 00:10:42,910 --> 00:10:45,590 Szükségünk van egy módja annak, hogy megakadályozzák a programok veszélyeztetett 173 00:10:45,590 --> 00:10:47,880 a buffer overflow támadást. 174 00:10:47,880 --> 00:10:51,430 Ehhez meg kell, hogy megbizonyosodjon arról, hogy a puffer képes növekedni, mint olvasunk 175 00:10:51,430 --> 00:10:53,850 több bemenet a felhasználó elől. 176 00:10:53,850 --> 00:10:57,440 A megoldás? Az általunk használt halom lefoglalt pufferbe. 177 00:10:57,440 --> 00:10:59,950 Mivel tudjuk átméretezni használatával az átméretezés a realloc funkció 178 00:10:59,950 --> 00:11:04,580 és mi nyomon követheti a két szám - az index a következő üres helyet a puffer 179 00:11:04,580 --> 00:11:08,390 és a hosszát vagy a puffer kapacitását. 180 00:11:08,390 --> 00:11:13,210 Azt olvassuk a karakter a felhasználó egyesével a fgetc funkciót. 181 00:11:13,210 --> 00:11:19,360 Az érvelés a fgetc függvény - stdin - utalás a standard input string, 182 00:11:19,360 --> 00:11:23,810 amely egy preconnected bemeneti csatorna átviteléhez használt a felhasználó által megadott 183 00:11:23,810 --> 00:11:26,270 A terminál a programhoz. 184 00:11:26,270 --> 00:11:29,890 >> Amikor a felhasználó beír egy új karaktert, akkor nézze meg, ha az index 185 00:11:29,890 --> 00:11:35,810 A következő szabad, valamint 1 nyílás nagyobb, mint a kapacitása a puffer. 186 00:11:35,810 --> 00:11:39,690 A +1 jön, mert ha a következő szabad index 5, 187 00:11:39,690 --> 00:11:44,150 akkor a puffer hosszúnak kell lennie 6 hála 0 indexelés. 188 00:11:44,150 --> 00:11:48,350 Ha már elfogy a hely a pufferben, akkor próbálja átméretezni azt, 189 00:11:48,350 --> 00:11:51,690 megduplázásával úgy, hogy vágjuk le, hogy hányszor, hogy átméretezni 190 00:11:51,690 --> 00:11:54,760 ha a felhasználó beírja egy nagyon hosszú string. 191 00:11:54,760 --> 00:11:57,950 Ha a string ütött túl hosszú, vagy ha elfogy a heap memória, 192 00:11:57,950 --> 00:12:01,350 mi szabadítani a puffer és vissza null. 193 00:12:01,350 --> 00:12:04,170 >> Végül, fűzze hozzá a karakter a pufferbe. 194 00:12:04,170 --> 00:12:08,200 Ha a felhasználó látogatottság be vagy vissza-, jelző-egy új sort, 195 00:12:08,200 --> 00:12:12,050 vagy a speciális char - control d - amely jelzi véget bemenet, 196 00:12:12,050 --> 00:12:16,240 mi egy csekket, hogy ha a felhasználó ténylegesen beírt semmit. 197 00:12:16,240 --> 00:12:18,820 Ha nem, akkor vissza null. 198 00:12:18,820 --> 00:12:22,280 Ellenkező esetben, mert a puffer valószínűleg nagyobb, mint amire szükségünk van, 199 00:12:22,280 --> 00:12:24,830 a legrosszabb esetben ez majdnem kétszer akkora, mint van szükségünk 200 00:12:24,830 --> 00:12:27,830 hiszen dupla valahányszor átméretezni, 201 00:12:27,830 --> 00:12:31,840 teszünk egy új példányát a húr segítségével csak a térköz mértékét, amire szükségünk van. 202 00:12:31,840 --> 00:12:34,220 Mi hozzá egy extra 1 a malloc hívás 203 00:12:34,220 --> 00:12:37,810 úgy, hogy van hely a különleges null terminátor jelleg - a \ 0, 204 00:12:37,810 --> 00:12:41,990 amelyhez csatolja a string amint másolni a többi karakter, 205 00:12:41,990 --> 00:12:45,060 felhasználásával strncpy helyett strcpy 206 00:12:45,060 --> 00:12:48,830 annak érdekében, hogy tudjuk meg, hogy pontosan hány karakter akarunk másolni. 207 00:12:48,830 --> 00:12:51,690 Strcpy másolja, amíg eléri a \ 0. 208 00:12:51,690 --> 00:12:55,740 Akkor szabad a puffer és a példányt visszaadja a hívónak. 209 00:12:55,740 --> 00:12:59,840 >> Ki tudta, hogy egy ilyen egyszerű látszó funkció lehet olyan bonyolult? 210 00:12:59,840 --> 00:13:02,820 Most már tudod, mi kerül a CS50 könyvtárba. 211 00:13:02,820 --> 00:13:06,470 >> A nevem Nate Hardison, és ez CS50. 212 00:13:06,470 --> 00:13:08,350 [CS50.TV]