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] [Universitatea Harvard] 3 00:00:04,220 --> 00:00:07,260 [Acest lucru este CS50. CS50.TV] 4 00:00:07,260 --> 00:00:11,510 Biblioteca CS50 este un instrument util, care ne-am instalat pe aparat 5 00:00:11,510 --> 00:00:15,870 pentru a face mai ușor pentru tine de a scrie programe pe care utilizatorii prompt pentru intrare. 6 00:00:15,870 --> 00:00:21,670 În acest videoclip, vom trage înapoi cortina si uita-te la ceea ce este exact în bibliotecă CS50. 7 00:00:21,670 --> 00:00:25,520 >> În video de pe bibliotecile C, vorbim despre modul în care fișierele header # include 8 00:00:25,520 --> 00:00:27,570 de bibliotecă în codul sursă, 9 00:00:27,570 --> 00:00:31,150 și apoi vă legați cu un fișier binar bibliotecă în timpul fazei de legătură 10 00:00:31,150 --> 00:00:33,140 din procesul de compilare. 11 00:00:33,140 --> 00:00:36,440 Fișierele antet specifica interfata a bibliotecii. 12 00:00:36,440 --> 00:00:41,280 Asta este, ei detaliu toate resursele pe care biblioteca are disponibile pentru tine de a utiliza, 13 00:00:41,280 --> 00:00:45,250 cum ar fi declarațiile funcțiilor, constante, tipuri de date și. 14 00:00:45,250 --> 00:00:48,890 Fișierul binar Biblioteca conține punerea în aplicare a bibliotecii, 15 00:00:48,890 --> 00:00:54,580 care este compilat din fișierele header bibliotecii și despre biblioteca C fișiere. codul sursă. 16 00:00:54,580 --> 00:00:59,820 >> Fișier binar Biblioteca nu este foarte interesant să se uite la, deoarece e, bine, în binar. 17 00:00:59,820 --> 00:01:03,300 Deci, haideți să aruncăm o privire la fișierele header pentru bibliotecă în loc. 18 00:01:03,300 --> 00:01:07,710 În acest caz, nu există decât un singur fișier header numit cs50.h. 19 00:01:07,710 --> 00:01:11,040 L-am instalat în directorul de utilizare includ 20 00:01:11,040 --> 00:01:15,150 împreună cu fișierele de alte biblioteci de sisteme de antet. 21 00:01:15,150 --> 00:01:21,530 >> Unul dintre primele lucruri pe care le veți observa este faptul că cs50.h include # fișiere antet de la alte biblioteci - 22 00:01:21,530 --> 00:01:25,670 float, bool limite, de iarnă, și lib standard. 23 00:01:25,670 --> 00:01:28,800 Din nou, ca urmare a principiului de a nu reinventa roata, 24 00:01:28,800 --> 00:01:33,490 am construit biblioteca CS0 folosind unelte pe care alte prevăzute pentru noi. 25 00:01:33,490 --> 00:01:38,690 >> Următorul lucru pe care îl veți vedea în bibliotecă este ca putem defini un nou tip numit "string". 26 00:01:38,690 --> 00:01:42,330 Această linie de fapt doar creează un alias pentru tipul char *, 27 00:01:42,330 --> 00:01:46,000 astfel încât să nu satura magic de tip sir nou cu atribute 28 00:01:46,000 --> 00:01:49,650 frecvent asociate cu obiecte de coarde în alte limbi, 29 00:01:49,650 --> 00:01:50,850 cum ar fi lungimea. 30 00:01:50,850 --> 00:01:55,180 Motivul pentru care am făcut acest lucru este de a proteja programatori de noi de la detaliile gory 31 00:01:55,180 --> 00:01:57,580 de pointeri până când sunt gata. 32 00:01:57,580 --> 00:02:00,130 >> Următoarea parte a fișierului header este declarația de funcții 33 00:02:00,130 --> 00:02:04,410 că biblioteca CS50 ofera împreună cu documentația. 34 00:02:04,410 --> 00:02:06,940 Observați nivelul de detaliere în comentariile de aici. 35 00:02:06,940 --> 00:02:10,560 Acest lucru este foarte important pentru ca oamenii să știe cum să folosească aceste funcții. 36 00:02:10,560 --> 00:02:19,150 Ne pronunțăm, la rândul lor, funcționează pentru a solicita utilizatorului și caractere de returnare, duble, flotoare, Ints, 37 00:02:19,150 --> 00:02:24,160 lungă doreste, si siruri de caractere, folosind tipul nostru șir proprie. 38 00:02:24,160 --> 00:02:26,260 În urma principiul de ascundere de informații, 39 00:02:26,260 --> 00:02:31,640 ne-am pus definiția noastră într-un fișier separat, punerea în aplicare c -. cs50.c-- 40 00:02:31,640 --> 00:02:35,110 situat în directorul sursă de utilizator. 41 00:02:35,110 --> 00:02:38,040 Am condiția ca fișier, astfel încât să puteți lua o privire la ea, 42 00:02:38,040 --> 00:02:41,490 învăța de la el, și recompilați-l pe mașini diferite, dacă doriți, 43 00:02:41,490 --> 00:02:45,510 chiar dacă credem că e mai bine pentru a lucra la aparat pentru această clasă. 44 00:02:45,510 --> 00:02:47,580 Oricum, haideți să aruncăm o privire la ea acum. 45 00:02:49,020 --> 00:02:54,620 >> Funcțiile getchar, GetDouble, GetFloat, GetInt, și GetLongLong 46 00:02:54,620 --> 00:02:58,160 sunt toate construite pe partea de sus a funcției getString. 47 00:02:58,160 --> 00:03:01,510 Se pare că ei vor urma în esență, același model. 48 00:03:01,510 --> 00:03:04,870 Ei folosesc o buclă în timp ce pentru a cere utilizatorului pentru o linie de intrare. 49 00:03:04,870 --> 00:03:08,430 Ei se întorc o valoare deosebită în cazul în care utilizatorul introduce o linie goală. 50 00:03:08,430 --> 00:03:11,750 Ei încearcă pentru a analiza intrarea utilizatorului ca tipul de caz, 51 00:03:11,750 --> 00:03:15,010 fie el un char, un dublu, un float, etc 52 00:03:15,010 --> 00:03:18,710 Și apoi se vor întoarce fie rezultatul dacă intrarea a fost cu succes analizat 53 00:03:18,710 --> 00:03:21,330 sau ei reprompt utilizator. 54 00:03:21,330 --> 00:03:24,230 >> La un nivel ridicat, nu este nimic adevarat complicat aici. 55 00:03:24,230 --> 00:03:28,760 S-ar putea fi scris codul structurate în mod similar vă în trecut. 56 00:03:28,760 --> 00:03:34,720 Poate că partea cea mai criptic-aspect este apelul sscanf care analizează intrarea utilizatorului. 57 00:03:34,720 --> 00:03:38,160 Sscanf face parte din familia de conversie de intrare format. 58 00:03:38,160 --> 00:03:42,300 Ea locuiește în io.h de iarnă, iar treaba lui este de a interpreta un șir C, 59 00:03:42,300 --> 00:03:46,520 în conformitate cu un anumit format, stocarea rezultatelor în analiza variabilei 60 00:03:46,520 --> 00:03:48,720 furnizate de către apelant. 61 00:03:48,720 --> 00:03:53,570 Deoarece formatul funcții de conversie de intrare sunt foarte utile, funcțiile utilizate pe scară largă 62 00:03:53,570 --> 00:03:56,160 care nu sunt super intuitiv la început, 63 00:03:56,160 --> 00:03:58,300 vom trece peste modul în care funcționează sscanf. 64 00:03:58,300 --> 00:04:03,330 >> Primul argument a sscanf este un char * - un pointer la un caracter. 65 00:04:03,330 --> 00:04:05,150 Pentru funcția să funcționeze corect, 66 00:04:05,150 --> 00:04:08,340 caracterul ar trebui să fie primul caracter al unui șir C, 67 00:04:08,340 --> 00:04:12,270 încheiată cu nul \ 0 caractere. 68 00:04:12,270 --> 00:04:15,120 Aceasta este șir pentru a analiza 69 00:04:15,120 --> 00:04:18,269 Al doilea argument pentru a sscanf este un șir format, 70 00:04:18,269 --> 00:04:20,839 de obicei, a trecut într-o constantă șir ca, 71 00:04:20,839 --> 00:04:24,040 și este posibil să fi văzut un șir ca acest lucru înainte atunci când se utilizează printf. 72 00:04:24,040 --> 00:04:28,650 Un semn la sută în șir format indică un specificator de conversie. 73 00:04:28,650 --> 00:04:30,850 Caracterul imediat după un semn la sută, 74 00:04:30,850 --> 00:04:35,430 indică tipul C pe care ne-o dorim pentru a converti la sscanf. 75 00:04:35,430 --> 00:04:40,090 În GetInt, veți vedea că există o d% și o c.%. 76 00:04:40,090 --> 00:04:48,690 Acest lucru înseamnă că sscanf va încerca să o int zecimal -% d - și un char - C%. 77 00:04:48,690 --> 00:04:51,510 Pentru fiecare specificatorul de conversie în șir format, 78 00:04:51,510 --> 00:04:56,620 sscanf așteaptă un argument corespunzătoare mai târziu în lista de argumentul său. 79 00:04:56,620 --> 00:05:00,850 Acest argument trebuie să indice într-o locație adecvată tastat 80 00:05:00,850 --> 00:05:04,000 în care se păstrează rezultatul conversiei. 81 00:05:04,000 --> 00:05:08,910 >> Modul tipic de a face acest lucru este de a crea o variabilă pe stivă înainte de apelul sscanf 82 00:05:08,910 --> 00:05:11,440 pentru fiecare element pe care doriți să-parsa din șirul 83 00:05:11,440 --> 00:05:15,520 și de a folosi apoi operatorul adresa - ampersand - pentru a trece pointeri 84 00:05:15,520 --> 00:05:19,100 pentru aceste variabile la apelul sscanf. 85 00:05:19,100 --> 00:05:22,720 Puteți vedea că, în GetInt facem exact acest lucru. 86 00:05:22,720 --> 00:05:28,240 Chiar înainte de apelul sscanf, ne declara un int n numit și un apel c char pe stivă, 87 00:05:28,240 --> 00:05:32,340 și trecem pointeri la ele în apel sscanf. 88 00:05:32,340 --> 00:05:35,800 Punerea acestor variabile pe stiva este preferat de peste folosind spațiul alocat 89 00:05:35,800 --> 00:05:39,350 pe morman cu malloc, din moment ce evita aeriene de apel malloc, 90 00:05:39,350 --> 00:05:43,060 și nu trebuie să vă faceți griji cu privire la scurgeri de memorie. 91 00:05:43,060 --> 00:05:47,280 Caractere care nu sunt prefixate de un semn de procent, nu cere de conversie. 92 00:05:47,280 --> 00:05:50,380 Mai degrabă ei trebuie doar să adăugați la caietul de sarcini formatul. 93 00:05:50,380 --> 00:05:56,500 >> De exemplu, dacă șirul formatul în GetInt au fost o d%, în loc, 94 00:05:56,500 --> 00:05:59,800 sscanf s-ar uita pentru o scrisoare urmat de un int, 95 00:05:59,800 --> 00:06:04,360 și în timp ce-l va încerca să convertească int, aceasta nu ar face nimic altceva cu o. 96 00:06:04,360 --> 00:06:07,440 Singura excepție de la acest lucru este un spațiu. 97 00:06:07,440 --> 00:06:11,030 Caractere spațiu alb în șir format meciul orice cantitate de spații albe - 98 00:06:11,030 --> 00:06:12,890 chiar deloc. 99 00:06:12,890 --> 00:06:18,100 Deci, de aceea comentariul menționează, eventual, cu conducerea și / sau la sfârșitul numelui spațiu. 100 00:06:18,100 --> 00:06:22,910 Deci, în acest moment se pare că apelul nostru va încerca sscanf pentru a analiza șir de utilizator de intrare 101 00:06:22,910 --> 00:06:25,380 prin verificarea pentru posibile de conducere spații albe, 102 00:06:25,380 --> 00:06:29,300 urmat de un int care vor fi transformate și stocate în variabila int n 103 00:06:29,300 --> 00:06:33,090 urmată de o anumită cantitate de spații albe, și urmată de un caracter 104 00:06:33,090 --> 00:06:35,810 stocate în variabila char c. 105 00:06:35,810 --> 00:06:37,790 >> Ce zici de valoarea de returnare? 106 00:06:37,790 --> 00:06:41,560 Sscanf va analiza linia de intrare de la început până la sfârșit, 107 00:06:41,560 --> 00:06:44,860 oprire atunci când ajunge la capăt sau atunci când un personaj din intrare 108 00:06:44,860 --> 00:06:49,320 nu se potrivește cu un caracter format sau atunci când nu se poate face o conversie. 109 00:06:49,320 --> 00:06:52,690 Valoarea ei de retur este utilizat pentru a unic atunci când sa oprit. 110 00:06:52,690 --> 00:06:55,670 În cazul în care sa oprit, pentru că a ajuns la sfârșitul șirului de intrare 111 00:06:55,670 --> 00:07:00,630 înainte de a face orice conversie și înainte de faptul că nu pentru a se potrivi o parte din stringul de format, 112 00:07:00,630 --> 00:07:04,840 apoi EOF specială constanta este returnat. 113 00:07:04,840 --> 00:07:08,200 În caz contrar, returnează numărul de conversii de succes, 114 00:07:08,200 --> 00:07:14,380 care ar putea fi 0, 1, sau 2, când ne-am rugat pentru două conversii. 115 00:07:14,380 --> 00:07:19,000 În cazul nostru, vrem să ne asigurăm că utilizatorul tastat într-un int si numai un int. 116 00:07:19,000 --> 00:07:23,370 >> Deci, vrem să se întoarcă sscanf 1. Vezi de ce? 117 00:07:23,370 --> 00:07:26,850 Dacă sscanf returnat 0, atunci nu s-au făcut conversii, 118 00:07:26,850 --> 00:07:31,690 astfel încât utilizatorul tastat altceva decât o int de la începutul intrare. 119 00:07:31,690 --> 00:07:37,100 Dacă sscanf returnează 2, apoi utilizatorul sa scrie corect în la începutul anului de intrare, 120 00:07:37,100 --> 00:07:41,390 dar apoi introdus într-un caracter non-spațiu după aceea 121 00:07:41,390 --> 00:07:44,940 întrucât% c conversie a reușit. 122 00:07:44,940 --> 00:07:49,570 Wow, asta e destul de o explicație lungă pentru apelul funcției unul. 123 00:07:49,570 --> 00:07:53,460 Oricum, dacă doriți mai multe informații despre sscanf și frații săi, 124 00:07:53,460 --> 00:07:57,130 a verifica afară de paginile man, Google, sau ambele. 125 00:07:57,130 --> 00:07:58,780 Există o mulțime de opțiuni șir format, 126 00:07:58,780 --> 00:08:03,830 și acestea pot economisi o mulțime de muncă manuală atunci când încearcă să elimine siruri de caractere în C 127 00:08:03,830 --> 00:08:07,180 >> Funcția finală în bibliotecă să se uite la este getString. 128 00:08:07,180 --> 00:08:10,310 Se pare că este o funcție getString dificil de a scrie corect, 129 00:08:10,310 --> 00:08:14,290 chiar daca se pare ca o astfel de sarcină simplă, comună. 130 00:08:14,290 --> 00:08:16,170 De ce este acest caz? 131 00:08:16,170 --> 00:08:21,380 Ei bine, hai să ne gândim cum vom stoca linia pe care utilizatorul tipuri de inch 132 00:08:21,380 --> 00:08:23,880 Din moment ce un șir este o secvență de caractere, 133 00:08:23,880 --> 00:08:26,430 am putea dori să-l stocați într-o matrice pe stivă, 134 00:08:26,430 --> 00:08:31,250 dar ne-ar trebui să știe cât timp matrice va fi atunci când l-am declara. 135 00:08:31,250 --> 00:08:34,030 De asemenea, dacă vrem să-l pună pe heap, 136 00:08:34,030 --> 00:08:38,090 avem nevoie pentru a trece la malloc numărul de octeți vrem să rezerve, 137 00:08:38,090 --> 00:08:39,730 dar acest lucru este imposibil. 138 00:08:39,730 --> 00:08:42,760 Nu avem nici o idee cât de multe caractere utilizatorul va introduce în 139 00:08:42,760 --> 00:08:46,590 înainte de utilizare, de fapt nu le tastați. 140 00:08:46,590 --> 00:08:50,720 >> O soluție naiv la această problemă este de a rezerva doar o bucată mare de spațiu, să zicem, 141 00:08:50,720 --> 00:08:54,540 un bloc de 1000 de caractere de intrare pentru utilizator, 142 00:08:54,540 --> 00:08:57,980 presupunând că utilizatorul nu ar tastați într-un șir atât de mult. 143 00:08:57,980 --> 00:09:00,810 Aceasta este o idee rea pentru două motive. 144 00:09:00,810 --> 00:09:05,280 În primul rând, presupunând că utilizatorii de obicei nu tastați în siruri de caractere atât de mult, 145 00:09:05,280 --> 00:09:07,610 ai putea deșeuri o mulțime de memorie. 146 00:09:07,610 --> 00:09:10,530 Pe mașinile moderne, acest lucru nu ar putea fi o problemă dacă faci acest lucru 147 00:09:10,530 --> 00:09:13,890 în una sau două cazuri izolate, 148 00:09:13,890 --> 00:09:17,630 dar dacă luați datele introduse de utilizator într-o buclă și depozitarea pentru utilizare ulterioară, 149 00:09:17,630 --> 00:09:20,870 vă poate suge rapid o tona de memorie. 150 00:09:20,870 --> 00:09:24,450 În plus, în cazul în care programul scrii este pentru un computer mai mic - 151 00:09:24,450 --> 00:09:28,100 un dispozitiv cum ar fi un smartphone sau altceva cu memorie limitată - 152 00:09:28,100 --> 00:09:32,060 această soluție va provoca probleme mult mai repede. 153 00:09:32,060 --> 00:09:36,450 Al doilea motiv, mult mai grav să nu facă acest lucru este că lasă programul dumneavoastră vulnerabil 154 00:09:36,450 --> 00:09:39,710 la ceea ce se numește un overflow atac buffer. 155 00:09:39,710 --> 00:09:45,840 În programare, un buffer de memorie este utilizată pentru stocarea temporară a datelor de intrare sau de ieșire, 156 00:09:45,840 --> 00:09:48,980 care în acest caz este nostru 1000-char bloc. 157 00:09:48,980 --> 00:09:53,370 Un buffer overflow apare atunci când datele sunt scrise trecut sfârșitul blocului. 158 00:09:53,370 --> 00:09:57,790 >> De exemplu, dacă un utilizator face de fapt de tip în mai mult de 1000 de caractere. 159 00:09:57,790 --> 00:10:01,570 Este posibil să fi experimentat acest lucru accidental la programare cu matrice. 160 00:10:01,570 --> 00:10:05,620 Dacă aveți o serie de 10 Ints, nimic nu te opreste de la încercarea de a citi sau a scrie 161 00:10:05,620 --> 00:10:07,810 15 int. 162 00:10:07,810 --> 00:10:10,000 Nu există avertizări sau erori de compilare. 163 00:10:10,000 --> 00:10:13,250 Programului doar gafe drept înainte și accesează memoria 164 00:10:13,250 --> 00:10:18,150 în cazul în care se crede că va fi int cincisprezecelea, iar acest lucru poate suprascrie variabilele alte. 165 00:10:18,150 --> 00:10:22,040 În cel mai rău caz, puteți suprascrie o parte din program intern dvs. 166 00:10:22,040 --> 00:10:26,820 mecanisme de control, provocând programul dvs. pentru a executa efectiv instrucțiuni diferite 167 00:10:26,820 --> 00:10:28,340 decât ați intenționat. 168 00:10:28,340 --> 00:10:31,360 >> Acum, nu e obișnuit să facă acest lucru accidental, 169 00:10:31,360 --> 00:10:35,150 dar aceasta este o tehnica destul de comună că băieții răi utilizați pentru a sparge programe 170 00:10:35,150 --> 00:10:39,080 și a pus cod malitios pe computerele altor persoane. 171 00:10:39,080 --> 00:10:42,910 De aceea, nu putem folosi doar soluția noastră naiv. 172 00:10:42,910 --> 00:10:45,590 Avem nevoie de o modalitate de a preveni programele noastre de a fi vulnerabil 173 00:10:45,590 --> 00:10:47,880 la un buffer overflow atac. 174 00:10:47,880 --> 00:10:51,430 Pentru a face acest lucru, avem nevoie să ne asigurăm că buffer-ul nostru poate creste asa cum am citit 175 00:10:51,430 --> 00:10:53,850 intrare mai mult de la utilizator. 176 00:10:53,850 --> 00:10:57,440 Soluția? Noi folosim un tampon alocat heap. 177 00:10:57,440 --> 00:10:59,950 Din moment ce se poate redimensiona folosind funcția de redimensionare realloc, 178 00:10:59,950 --> 00:11:04,580 și ne ține evidența două numere - indicele de slotul gol următor în tampon 179 00:11:04,580 --> 00:11:08,390 și lungimea sau capacitatea de a tampon. 180 00:11:08,390 --> 00:11:13,210 Citim în caractere de la utilizator la un moment dat folosind funcția fgetc. 181 00:11:13,210 --> 00:11:19,360 Argumentul funcția fgetc ia - stdin - este o trimitere la șirul de intrare standard, 182 00:11:19,360 --> 00:11:23,810 care este un canal de intrare preconnected, care este utilizat pentru a transfera de intrare utilizatorului 183 00:11:23,810 --> 00:11:26,270 de la terminal la program. 184 00:11:26,270 --> 00:11:29,890 >> Ori de câte ori utilizatorul tastează într-un nou personaj, vom verifica pentru a vedea dacă indexul 185 00:11:29,890 --> 00:11:35,810 din slot liber următoarea plus 1 este mai mare decât capacitatea de tampon. 186 00:11:35,810 --> 00:11:39,690 The 1, deoarece vine în cazul în care indicele următor liber este de 5, 187 00:11:39,690 --> 00:11:44,150 atunci lungimea buffer nostru trebuie să fie mulțumită 6 la 0 indexare. 188 00:11:44,150 --> 00:11:48,350 Dacă ne-am alerga afară de spațiu în tampon, apoi am încerca să-l redimensiona, 189 00:11:48,350 --> 00:11:51,690 dublarea în așa fel încât am tăiat în jos, pe numărul de ori pe care le redimensiona 190 00:11:51,690 --> 00:11:54,760 dacă utilizatorul este tastarea într-un șir foarte lung. 191 00:11:54,760 --> 00:11:57,950 Dacă șirul a devenit prea mult timp sau dacă ne alerga afară de memorie heap, 192 00:11:57,950 --> 00:12:01,350 ne eliberăm tampon noastră și nul retur. 193 00:12:01,350 --> 00:12:04,170 >> În cele din urmă, am adăuga la char buffer. 194 00:12:04,170 --> 00:12:08,200 Odată ce hit-uri de utilizator intra sau reveni, de semnalizare o linie nouă, 195 00:12:08,200 --> 00:12:12,050 sau speciale char - de control d - care semnalează un sfârșit de intrare, 196 00:12:12,050 --> 00:12:16,240 facem o verificare pentru a vedea dacă utilizatorul de fapt tastat nimic, la toate. 197 00:12:16,240 --> 00:12:18,820 Dacă nu, ne vom întoarce null. 198 00:12:18,820 --> 00:12:22,280 În caz contrar, pentru ca tampon nostru este, probabil, mai mare decât avem nevoie, 199 00:12:22,280 --> 00:12:24,830 în cel mai rău caz e aproape de două ori mai mare ca avem nevoie de 200 00:12:24,830 --> 00:12:27,830 când ne-am dubla fiecare dată când ne redimensiona, 201 00:12:27,830 --> 00:12:31,840 vom face o nouă copie a șirului folosind doar cantitatea de spațiu de care avem nevoie. 202 00:12:31,840 --> 00:12:34,220 Am adăuga un extra de la 1 la apelul malloc, 203 00:12:34,220 --> 00:12:37,810 astfel că există spațiu pentru construcții nul caracterul terminator - pentru \ 0, 204 00:12:37,810 --> 00:12:41,990 care să anexeze la șirul odată ce vom copia in restul personajelor, 205 00:12:41,990 --> 00:12:45,060 folosind strncpy loc de strcpy 206 00:12:45,060 --> 00:12:48,830 astfel încât să putem specifica exact cât de multe caractere dorim să copiați. 207 00:12:48,830 --> 00:12:51,690 Strcpy copiază până când lovește un \ 0. 208 00:12:51,690 --> 00:12:55,740 Apoi ne-am elibera tampon noastră și a reveni copie apelantului. 209 00:12:55,740 --> 00:12:59,840 >> Cine a știut astfel o funcție de simplu, aparent ar putea fi atat de complicat? 210 00:12:59,840 --> 00:13:02,820 Acum știi ce se întâmplă în bibliotecă CS50. 211 00:13:02,820 --> 00:13:06,470 >> Numele meu este Nate Hardison, iar acest lucru este CS50. 212 00:13:06,470 --> 00:13:08,350 [CS50.TV]