1 00:00:00,000 --> 00:00:02,490 [Powered by Google Translate] [CS50 Raamatukogu] 2 00:00:02,490 --> 00:00:04,220 [Nate Hardison] [Harvardi Ülikool] 3 00:00:04,220 --> 00:00:07,260 [See on CS50. CS50.TV] 4 00:00:07,260 --> 00:00:11,510 CS50 raamatukogu on kasulik vahend, et meil on paigaldatud seade sisse 5 00:00:11,510 --> 00:00:15,870 et oleks lihtsam kirjutada programme, mis nõuab kasutajatel sisend. 6 00:00:15,870 --> 00:00:21,670 Selles videos, me tõmmake kardin ja vaatame, mida täpselt on CS50 raamatukogu. 7 00:00:21,670 --> 00:00:25,520 >> In video C raamatukogud, me räägime kuidas sa # include päised faili 8 00:00:25,520 --> 00:00:27,570 raamatukogu oma lähtekoodi, 9 00:00:27,570 --> 00:00:31,150 ja siis siduda binaarse teegi faili ajal ühendab etapp 10 00:00:31,150 --> 00:00:33,140 koostamise protsessi. 11 00:00:33,140 --> 00:00:36,440 Päisefaile täpsustada liides raamatukogu. 12 00:00:36,440 --> 00:00:41,280 See tähendab, et nad üksikasjalikult kõiki vahendeid, et raamatukogus on olemas, kus saab kasutada, 13 00:00:41,280 --> 00:00:45,250 nagu funktsioon deklaratsioonid, konstandid ja andmetüüpe. 14 00:00:45,250 --> 00:00:48,890 Binaarne raamatukogu fail sisaldab rakendamise raamatukogu, 15 00:00:48,890 --> 00:00:54,580 mis on koostatud raamatukogu päisefaile ja raamatukogu. c lähtekoodi failid. 16 00:00:54,580 --> 00:00:59,820 >> Binaarne raamatukogu fail ei ole väga huvitav vaadata, sest see on, noh, binaarne. 17 00:00:59,820 --> 00:01:03,300 Niisiis, oletame, kui heita pilk päisefaile raamatukogu asemel. 18 00:01:03,300 --> 00:01:07,710 Sel juhul on ainult üks header fail nimega cs50.h. 19 00:01:07,710 --> 00:01:11,040 Oleme paigaldatud see kasutaja sisaldavad kataloog 20 00:01:11,040 --> 00:01:15,150 koos teiste süsteemi raamatukogude päisefaile. 21 00:01:15,150 --> 00:01:21,530 >> Üks esimesi asju märkad on see, et cs50.h # sisaldab päisefaile teistest raamatukogudest - 22 00:01:21,530 --> 00:01:25,670 float, piirid, standard bool ja standard lib. 23 00:01:25,670 --> 00:01:28,800 Jällegi põhimõtet järgides ei jalgratta leiutamist, 24 00:01:28,800 --> 00:01:33,490 oleme loonud CS0 raamatukogu kasutades vahendeid, mida teised meile andnud. 25 00:01:33,490 --> 00:01:38,690 >> Järgmine asi, mida te näete on raamatukogu, mis me defineerime uue tüübi nimega "string." 26 00:01:38,690 --> 00:01:42,330 See liin on tõesti lihtsalt loob alias char * tüüpi, 27 00:01:42,330 --> 00:01:46,000 nii et see ei võluväel immutama uus string tüüpi atribuute 28 00:01:46,000 --> 00:01:49,650 tavaliselt seotud string objektid teistes keeltes, 29 00:01:49,650 --> 00:01:50,850 nagu pikkus. 30 00:01:50,850 --> 00:01:55,180 Põhjus, miks me seda teinud on kaitsta uus programmeerijad Verine üksikasjad 31 00:01:55,180 --> 00:01:57,580 osuti kuni nad on valmis. 32 00:01:57,580 --> 00:02:00,130 >> Järgmise osa päisefail on deklaratsiooni funktsioonid 33 00:02:00,130 --> 00:02:04,410 et CS50 raamatukogu pakub koos dokumentidega. 34 00:02:04,410 --> 00:02:06,940 Teade detailsus kommentaarid siia. 35 00:02:06,940 --> 00:02:10,560 See on super oluline, et inimesed teaksid, kuidas kasutada neid funktsioone. 36 00:02:10,560 --> 00:02:19,150 Me kuulutame, mis omakorda toimib ajendab kasutaja ja tagastamise tähemärki, kahekohalised, ujukite, ints, 37 00:02:19,150 --> 00:02:24,160 kaua igatseb, ja stringid, kasutades oma stringi tüüpi. 38 00:02:24,160 --> 00:02:26,260 Järgides põhimõtet tiedonpiilotus, 39 00:02:26,260 --> 00:02:31,640 oleme pannud meie määratlus eraldi. c rakendamise fail - cs50.c-- 40 00:02:31,640 --> 00:02:35,110 asub kasutaja allikas kataloog. 41 00:02:35,110 --> 00:02:38,040 Oleme lisanud selle faili nii, et saate seda vaadata, 42 00:02:38,040 --> 00:02:41,490 õppima, ja kompileeri see erinevate masinatega, kui soovite, 43 00:02:41,490 --> 00:02:45,510 kuigi me arvame, et see on parem töötada seadet selles klassis. 44 00:02:45,510 --> 00:02:47,580 Igatahes, võtame pilk see nüüd. 45 00:02:49,020 --> 00:02:54,620 >> Funktsioonid getchar, GetDouble, GetFloat, GetInt ja GetLongLong 46 00:02:54,620 --> 00:02:58,160 kõik ehitatud peal getString funktsioon. 47 00:02:58,160 --> 00:03:01,510 Selgub, et nad kõik järgivad sisuliselt sama muster. 48 00:03:01,510 --> 00:03:04,870 Nad kasutavad samas silmus ajendab kasutaja jaoks üks rida sisend. 49 00:03:04,870 --> 00:03:08,430 Nad naasta eriline väärtus, kui kasutaja sisendite tühi rida. 50 00:03:08,430 --> 00:03:11,750 Nad püüavad sõeluda kasutaja sisendit sobivat tüüpi, 51 00:03:11,750 --> 00:03:15,010 olgu see char, double, float, jne 52 00:03:15,010 --> 00:03:18,710 Ja siis nad kas naasta tulemus, kui sisend on edukalt sõeluda 53 00:03:18,710 --> 00:03:21,330 või nad reprompt kasutaja. 54 00:03:21,330 --> 00:03:24,230 >> Kõrgel tasemel, ei ole midagi tõesti keeruline siin. 55 00:03:24,230 --> 00:03:28,760 Te olete kirjutanud sarnaselt struktureeritud koodi ise minevikus. 56 00:03:28,760 --> 00:03:34,720 Võib-olla kõige segasena suunatud osa on sscanf kõne, et korrastab kasutaja sisendit. 57 00:03:34,720 --> 00:03:38,160 Sscanf on osa sisend formaadi konverteerimise pere. 58 00:03:38,160 --> 00:03:42,300 Ta elab standard io.h ja tema ülesanne on sõeluda C string, 59 00:03:42,300 --> 00:03:46,520 vastavalt kindlas vormingus, säilitades sõeluda tulemusi muutuja 60 00:03:46,520 --> 00:03:48,720 sätestatud helistaja. 61 00:03:48,720 --> 00:03:53,570 Kuna sisendvorming muutmise funktsioonid on väga kasulik, laialdaselt kasutatavad funktsioonid 62 00:03:53,570 --> 00:03:56,160 mis ei ole super intuitiivne alguses, 63 00:03:56,160 --> 00:03:58,300 läheme üle, kuidas sscanf töötab. 64 00:03:58,300 --> 00:04:03,330 >> Esimene argument sscanf on char * - kursor sümboli. 65 00:04:03,330 --> 00:04:05,150 Sest funktsioon korralikult töötada, 66 00:04:05,150 --> 00:04:08,340 et märk peaks olema esimene märk C string, 67 00:04:08,340 --> 00:04:12,270 lõpetatakse null \ 0 märk. 68 00:04:12,270 --> 00:04:15,120 See on string sõeluda 69 00:04:15,120 --> 00:04:18,269 Teine argument sscanf on stringi, 70 00:04:18,269 --> 00:04:20,839 tavaliselt möödus nagu string konstantne, 71 00:04:20,839 --> 00:04:24,040 ja sa võisid näha stringi nagu seda enne, kui kasutate printf. 72 00:04:24,040 --> 00:04:28,650 Protsendimärk vormingus stringi näitab teisenduse. 73 00:04:28,650 --> 00:04:30,850 Märgi kohe pärast protsendimärk, 74 00:04:30,850 --> 00:04:35,430 näitab C tüüpi, et me tahame sscanf teisendada. 75 00:04:35,430 --> 00:04:40,090 Aastal GetInt, näed, et seal on% d ja% c. 76 00:04:40,090 --> 00:04:48,690 See tähendab, et sscanf püüan koma int -% d - ja char -% c. 77 00:04:48,690 --> 00:04:51,510 Iga teisenduse stringi, 78 00:04:51,510 --> 00:04:56,620 sscanf loodab vastav argument hiljem oma väidet nimekirja. 79 00:04:56,620 --> 00:05:00,850 See argument tuleb viidata nõuetekohaselt trükitud asukoht 80 00:05:00,850 --> 00:05:04,000 , kuhu salvestada konverteerimise tulemuse. 81 00:05:04,000 --> 00:05:08,910 >> Tüüpiline viis seda teha on luua muutuja serva enne sscanf kõne 82 00:05:08,910 --> 00:05:11,440 iga kirje, mida soovite sõeluda alates string 83 00:05:11,440 --> 00:05:15,520 ja siis kasuta aadress operaator - märk - läbida viiteid 84 00:05:15,520 --> 00:05:19,100 nende muutujate sscanf kõne. 85 00:05:19,100 --> 00:05:22,720 Näete, et GetInt me seda täpselt. 86 00:05:22,720 --> 00:05:28,240 Vahetult enne sscanf kõne, me kuulutame int nimetatakse n ja char kõne c kohta virna, 87 00:05:28,240 --> 00:05:32,340 ja võtame viiteid need sscanf kõne. 88 00:05:32,340 --> 00:05:35,800 Haara need muutujad korstnat eelistatakse kasutada ruumi eraldatud 89 00:05:35,800 --> 00:05:39,350 edasi hunnik koos malloc, sest teil vältida õhuliini malloc kõne 90 00:05:39,350 --> 00:05:43,060 ja sa ei pea muretsema lekib mälu. 91 00:05:43,060 --> 00:05:47,280 Tegelased ei prefiksiga protsenti märk ei küsi vahetamisega. 92 00:05:47,280 --> 00:05:50,380 Pigem nad lihtsalt lisada formaadi kirjeldus. 93 00:05:50,380 --> 00:05:56,500 >> Näiteks kui formaat string GetInt olid% d asemel, 94 00:05:56,500 --> 00:05:59,800 sscanf näeks ette täht, millele järgneb int, 95 00:05:59,800 --> 00:06:04,360 ja kuigi see oleks üritada muuta int, see ei tee midagi muud. 96 00:06:04,360 --> 00:06:07,440 Ainus erand on see tühik. 97 00:06:07,440 --> 00:06:11,030 Valge ruum tähemärki stringi suvalise summa tühik - 98 00:06:11,030 --> 00:06:12,890 isegi üldse mitte. 99 00:06:12,890 --> 00:06:18,100 Nii, et miks kommentaar mainib olla juhtivate ja / või trailing tühik. 100 00:06:18,100 --> 00:06:22,910 Niisiis, siinkohal tundub meie sscanf kõne püüab sõeluda kasutaja sisend string 101 00:06:22,910 --> 00:06:25,380 kontrollides võimalik juhtiv tühik, 102 00:06:25,380 --> 00:06:29,300 järgneb int et konverteeritakse ja salvestatakse int muutuja n 103 00:06:29,300 --> 00:06:33,090 järgneb mingi summa tühik, millele järgneb märk 104 00:06:33,090 --> 00:06:35,810 salvestatud char muutujat c. 105 00:06:35,810 --> 00:06:37,790 >> Aga tagastatav väärtus? 106 00:06:37,790 --> 00:06:41,560 Sscanf on sõeluda sisendrida algusest lõpuni, 107 00:06:41,560 --> 00:06:44,860 peatudes lõpuks või kui märk sisend 108 00:06:44,860 --> 00:06:49,320 ei sobi formaadis iseloomu või kui ta ei saa teha vahetamisega. 109 00:06:49,320 --> 00:06:52,690 See on tagastatav väärtus kasutatakse eristada, kui ta katkestas. 110 00:06:52,690 --> 00:06:55,670 Kui ta lõpetas, sest see on jõudnud sisend string 111 00:06:55,670 --> 00:07:00,630 enne mis tahes ümberehitused ja enne ta ei sobi osa stringi, 112 00:07:00,630 --> 00:07:04,840 siis erilist pidev EOF tagastatakse. 113 00:07:04,840 --> 00:07:08,200 Vastasel korral tagastab arvu edukaid tulemusi, 114 00:07:08,200 --> 00:07:14,380 mis võiks olla 0, 1 või 2, sest me oleme palunud kaks konversioone. 115 00:07:14,380 --> 00:07:19,000 Meie puhul me tahame veenduda, et kasutaja sisestatud int ja ainult int. 116 00:07:19,000 --> 00:07:23,370 >> Niisiis, me tahame sscanf naasta 1. Vaata miks? 117 00:07:23,370 --> 00:07:26,850 Kui sscanf tagastatakse 0, siis ei ole ümberarvestus tehti, 118 00:07:26,850 --> 00:07:31,690 nii kasutaja sisestatud midagi muud kui int alguses sisend. 119 00:07:31,690 --> 00:07:37,100 Kui sscanf tagastab 2, siis kasutaja ei korralikult kirjuta see alguses sisend, 120 00:07:37,100 --> 00:07:41,390 kuid nad siis kirjutada mõnes mitte-tühimärk hiljem 121 00:07:41,390 --> 00:07:44,940 alates% c konverteerimine õnnestunud. 122 00:07:44,940 --> 00:07:49,570 Vau, see on päris pikk selgitus üks funktsioon kõne. 123 00:07:49,570 --> 00:07:53,460 Igatahes, kui soovite rohkem teavet sscanf ja tema õed-vennad, 124 00:07:53,460 --> 00:07:57,130 vaadake man-lehekülgi, Google, või mõlemad. 125 00:07:57,130 --> 00:07:58,780 Seal on palju vormingustringile võimalusi, 126 00:07:58,780 --> 00:08:03,830 ja need võib säästa palju füüsilist tööd, kui nad püüavad sõeluda stringid C. 127 00:08:03,830 --> 00:08:07,180 >> Lõplik funktsioon raamatukogu pilk on getString. 128 00:08:07,180 --> 00:08:10,310 Selgub, et getString on keeruline ülesanne kirjutada õigesti, 129 00:08:10,310 --> 00:08:14,290 kuigi tundub selline lihtne, ühine ülesanne. 130 00:08:14,290 --> 00:08:16,170 Miks on see nii? 131 00:08:16,170 --> 00:08:21,380 Noh, mõtleme, kuidas me kavatseme hoida joont, et kasutaja tipib sisse 132 00:08:21,380 --> 00:08:23,880 Kuna string on jada sümbolid, 133 00:08:23,880 --> 00:08:26,430 me võiksite seda säilitada massiivi kohta virna, 134 00:08:26,430 --> 00:08:31,250 kuid meil oleks vaja teada, kui kaua massiivi saab olema, kui me kuulutada. 135 00:08:31,250 --> 00:08:34,030 Samuti siis, kui me tahame panna see hunnik, 136 00:08:34,030 --> 00:08:38,090 me peame läbima, et malloc baitide arvu tahame reservi, 137 00:08:38,090 --> 00:08:39,730 kuid see on võimatu. 138 00:08:39,730 --> 00:08:42,760 Meil pole aimugi, kui palju tähemärki kasutaja sisestada 139 00:08:42,760 --> 00:08:46,590 enne kui kasutaja tegelikult ei kirjuta. 140 00:08:46,590 --> 00:08:50,720 >> Naiivne lahendus sellele probleemile on lihtsalt endale suure tüki ruumi, ütleme, 141 00:08:50,720 --> 00:08:54,540 plokk 1000 tähemärki kasutaja sisend, 142 00:08:54,540 --> 00:08:57,980 eeldades, et kasutaja oleks kunagi sisestada string, mis pikk. 143 00:08:57,980 --> 00:09:00,810 See on halb idee kahel põhjusel. 144 00:09:00,810 --> 00:09:05,280 Esiteks, eeldades, et kasutajad tavaliselt ei kirjuta stringe, mis pikk, 145 00:09:05,280 --> 00:09:07,610 võid jäätmete palju mälu. 146 00:09:07,610 --> 00:09:10,530 On kaasaegsete masinatega, see ei pruugi olla probleem, kui sa seda teed 147 00:09:10,530 --> 00:09:13,890 ühes või kahes üksikjuhtumid, 148 00:09:13,890 --> 00:09:17,630 aga kui te võtate kasutaja sisend tsüklina ja hoidmine hilisemaks kasutamiseks, 149 00:09:17,630 --> 00:09:20,870 saate kiiresti imege ton mälu. 150 00:09:20,870 --> 00:09:24,450 Lisaks, kui programm olete kirjalikult on väiksem arvuti - 151 00:09:24,450 --> 00:09:28,100 seade nagu nutitelefon või midagi muud piiratud mälu - 152 00:09:28,100 --> 00:09:32,060 see lahendus toob kaasa probleeme palju kiiremini. 153 00:09:32,060 --> 00:09:36,450 Teine, veel tõsine põhjus seda teha on see, et ta jätab oma programmi haavatav 154 00:09:36,450 --> 00:09:39,710 sellele, mida nimetatakse buffer overflow rünnak. 155 00:09:39,710 --> 00:09:45,840 Programmeerimise, puhver on mälu, mida kasutatakse ajutiselt talletada väljundseisundi andmed, 156 00:09:45,840 --> 00:09:48,980 mis antud juhul on meie 1000-char blokeerida. 157 00:09:48,980 --> 00:09:53,370 Buffer overflow tekib siis andmed kirjutatakse juba lõppenud blokeerida. 158 00:09:53,370 --> 00:09:57,790 >> Näiteks, kui kasutaja tegelikult ei kirjuta enam kui 1000 tähemärki. 159 00:09:57,790 --> 00:10:01,570 Te olete kogenud seda kogemata kavandamisel massiivid. 160 00:10:01,570 --> 00:10:05,620 Kui teil on massiiv 10. ints, miski ei takista sind üritab lugeda ega kirjutada 161 00:10:05,620 --> 00:10:07,810 15. int. 162 00:10:07,810 --> 00:10:10,000 Puuduvad kompilaator hoiatused või vigu. 163 00:10:10,000 --> 00:10:13,250 Programm lihtsalt vigu otse edasi ja pöördub mälu 164 00:10:13,250 --> 00:10:18,150 kus ta arvab, 15. int saab olema, ja seda saab kirjutada oma muudest muutujatest. 165 00:10:18,150 --> 00:10:22,040 Halvimal juhul võid kirjutada mõned oma programmi sisene 166 00:10:22,040 --> 00:10:26,820 kontrollimehhanismid, põhjustades oma programmi tegelikult täita erinevaid juhiseid 167 00:10:26,820 --> 00:10:28,340 kui soovite. 168 00:10:28,340 --> 00:10:31,360 >> Nüüd, see ei ole ühine teha seda kogemata, 169 00:10:31,360 --> 00:10:35,150 kuid see on üsna levinud meetod, mis halvad poisid kasutavad murda programmid 170 00:10:35,150 --> 00:10:39,080 ja pane pahatahtliku koodi teiste inimeste arvuteid. 171 00:10:39,080 --> 00:10:42,910 Seetõttu me ei saa lihtsalt kasutada meie naiivne lahendus. 172 00:10:42,910 --> 00:10:45,590 Meil on vaja ära hoida meie programmid on vähem kaitstud 173 00:10:45,590 --> 00:10:47,880 et buffer overflow rünnak. 174 00:10:47,880 --> 00:10:51,430 Selleks peame tagama, et meie puhver võib kasvada, kui loeme 175 00:10:51,430 --> 00:10:53,850 rohkem kasutajalt. 176 00:10:53,850 --> 00:10:57,440 Lahendus? Me kasutame hunnik eraldatud puhver. 177 00:10:57,440 --> 00:10:59,950 Kuna me suurust saab muuta, kasutades resize RealLOC funktsioon, 178 00:10:59,950 --> 00:11:04,580 ja me jälgida kahte numbrit - indeksi kõrval tühi pesa puhver 179 00:11:04,580 --> 00:11:08,390 ja pikkus või maht puhver. 180 00:11:08,390 --> 00:11:13,210 Me loeme tähemärki kasutaja ükshaaval kasutades fgetc funktsioon. 181 00:11:13,210 --> 00:11:19,360 Argument fgetc funktsioon võtab - stdin - on standardkõvera sisend string, 182 00:11:19,360 --> 00:11:23,810 mis on preconnected sisendkanal, mida kasutatakse üle kasutaja sisend 183 00:11:23,810 --> 00:11:26,270 terminalist programm. 184 00:11:26,270 --> 00:11:29,890 >> Kui kasutaja liigid uus tegelane, meil vaadata, kui indeks 185 00:11:29,890 --> 00:11:35,810 järgmise vaba pesa pluss 1 on suurem kui võimsus puhver. 186 00:11:35,810 --> 00:11:39,690 1 jõuab, sest kui järgmine vaba indeks on 5, 187 00:11:39,690 --> 00:11:44,150 siis meie puhver on pikkus peab olema 6 tänud kuni 0 indekseerimist. 188 00:11:44,150 --> 00:11:48,350 Kui me oleme ruum otsa puhvris, siis üritame suurust muuta, 189 00:11:48,350 --> 00:11:51,690 kahekordistades seda nii, et me kärpima mitu korda, et me resize 190 00:11:51,690 --> 00:11:54,760 kui kasutaja on kirjutades tõesti pikk jada. 191 00:11:54,760 --> 00:11:57,950 Kui string on saanud liiga pikk või kui me otsa hunnik mälu, 192 00:11:57,950 --> 00:12:01,350 me vabastada oma puhver ja tagastab null. 193 00:12:01,350 --> 00:12:04,170 >> Lõpuks lisab char puhver. 194 00:12:04,170 --> 00:12:08,200 Kui kasutaja tabamust siseneda või naasta, signalisatsiooni uus liin, 195 00:12:08,200 --> 00:12:12,050 või eriline char - kontrolli d - mis signaale lõpuks sisend, 196 00:12:12,050 --> 00:12:16,240 meil vaadata, kui kasutaja tegelikult sisestatud üldse midagi. 197 00:12:16,240 --> 00:12:18,820 Kui ei, siis tagastab null. 198 00:12:18,820 --> 00:12:22,280 Vastasel sest meie puhver on tõenäoliselt suurem kui vajame, 199 00:12:22,280 --> 00:12:24,830 halvimal juhul on peaaegu kaks korda nii suur kui vaja 200 00:12:24,830 --> 00:12:27,830 kuna me kahekordistub iga kord, kui me suurust, 201 00:12:27,830 --> 00:12:31,840 teeme uue koopia string kasutades lihtsalt palju ruumi, et me vajame. 202 00:12:31,840 --> 00:12:34,220 Lisame pildi 1 malloc kõne 203 00:12:34,220 --> 00:12:37,810 nii et seal on ruumi eriline null terminaator iseloomu - \ 0, 204 00:12:37,810 --> 00:12:41,990 mis me lisab stringi kui me kopeerige ülejäänud tegelased, 205 00:12:41,990 --> 00:12:45,060 kasutades strncpy asemel strcpy 206 00:12:45,060 --> 00:12:48,830 nii et saame määrata täpselt, kui palju tähemärki me soovite kopeerida. 207 00:12:48,830 --> 00:12:51,690 Strcpy kopeerib kuni see tabab \ 0. 208 00:12:51,690 --> 00:12:55,740 Siis me vabastada oma puhver ja tagastab eksemplari helistaja. 209 00:12:55,740 --> 00:12:59,840 >> Kes teadis sellise lihtsa-näilisest funktsiooni saab nii keeruline? 210 00:12:59,840 --> 00:13:02,820 Nüüd sa tead, mida läheb CS50 raamatukogu. 211 00:13:02,820 --> 00:13:06,470 >> Minu nimi on Nate Hardison, ja see on CS50. 212 00:13:06,470 --> 00:13:08,350 [CS50.TV]