[Powered by Google Translate] [CS50 knjižnica]
[Nate Hardison] [Harvard University]
[To je CS50. CS50.TV]
Knjižnica CS50 je koristno orodje, ki smo jih namestili na napravi
da bi bilo lažje za vas, da napišete programe, ki opozorijo uporabniki za vnos.
V tem video bomo potegnite zaveso in pogledati, kaj točno je v CS50 knjižnici.
>> V videu o knjižnicah C, govorimo o tem, kako vključiti # glav datotek
v knjižnici v izvorno kodo,
in potem se povežete z binarno datoteko knjižnice v fazi povezuje
za urejanje procesa.
V glavi datoteke določite vmesnik za knjižnico.
To pomeni, da so podrobnosti vseh virov, ki jih ima knjižnica na voljo za uporabo,
kot funkcijo izjav, konstant in podatkovnih tipov.
Binarni knjižnica datoteka vsebuje izvajanje knjižnici,
ki je sestavljen iz glave knjižnice, datoteke in knjižnice c. datotek izvorne kode.
>> Binarni Knjižnica datoteka ni zelo zanimivo gledati, saj je, no, v binarno.
Torej, vzemimo si na glavi datoteke za knjižnico namesto tega.
V tem primeru, obstaja samo ena datoteka z imenom glave cs50.h.
Mi smo ga namestili v uporabniku vključujejo imenik
skupaj z drugega sistema knjižničnih glavi datoteke.
>> Ena od prvih stvari, ki jih boste opazili, da cs50.h # vključuje header datoteke iz drugih knjižnic -
float, int meje, standard, in standardni lib.
Še enkrat, po načelu ne izumljanju kolesa,
smo zgradili CS0 knjižnico z orodji, da druge predvidene za nas.
>> Naslednja stvar, ki jo boste videli v knjižnici je, da določite novo vrsto imenovano "string".
Ta linija res samo ustvarja alias char za vrsto *,
tako da ne čudežno podelilo novo vrsto niz z atributi
pogosto povezana s niza objektov v drugih jezikih,
kot dolžino.
Razlog, da smo to storili je, da varuje nove programerje od krvavih podrobnosti
kazalcev, dokler ne bodo pripravljeni.
>> Naslednji del glave datoteke je izjava o funkcijah
da CS50 knjižnica zagotavlja skupaj z dokumentacijo.
Bodite pozorni na stopnjo podrobnosti v pripombah tukaj.
To je super pomembno, da ljudje vedo, kako uporabljati te funkcije.
Izjavljamo, ta pa deluje, da uporabnik in vračanja znakov, dvojice, plovci ints,
dolgo hrepeni, in godala uporabo lastnega niza tip.
V skladu z načelom skrivanje informacij,
smo dal našo definicijo v ločen izvedbeni spisu. C - cs50.c--
ki se nahaja v imeniku uporabniškega vira.
Pripravili smo to datoteko, tako da si lahko ogledate na to,
iz nje naučili, in jih prevesti na različnih strojih, če želite,
čeprav menimo, da je bolje, da delajo na napravo za ta razred.
Kakorkoli že, pa si oglejte v tem.
>> Naloge GetChar, GetDouble, GetFloat, GetInt, in GetLongLong
Vsi so zgrajene na vrhu GetString funkcije.
Izkazalo se je, da vsi sledijo v bistvu isti vzorec.
Uporabljajo while zanko, da uporabnik za eno vrstico vhoda.
Vrnejo posebno vrednost, če uporabnik vhodi prazno vrstico.
So poskušali razčleniti uporabnika prispevek kot ustreznega tipa,
bilo char, dvojni, float, itd
In potem se bodisi vrnejo rezultat, če je bil vstopni uspešno razčleniti
ali pa reprompt uporabnika.
>> Na visoki ravni, ni nič zapleteno tukaj.
Morda ste napisal podobno strukturiranih kodo se v preteklosti.
Morda je najbolj skrivnosten usmerjen del je sscanf klic, ki razčleni uporabnika prispevek.
Sscanf je del družine format vhodnega konverzije.
Živi v io.h standarda, njegova naloga je, da razčleniti niz C,
v skladu z določeno obliko, skladiščenje razčlembi rezultate spremenljivka
ki jih klicatelja.
Ker so vhodne funkcije za konverzijo formata, so zelo koristne, pogosto uporabljenih funkcij
ki niso zelo intuitiven na prvi,
bomo ogledali, kako sscanf deluje.
>> Prvi argument je sscanf char * - kazalec na znak.
Za funkcija deluje pravilno,
da znak mora biti prvi znak niza C,
zaključi z ničelno \ 0 značaja.
To je niz razčleniti
Drugi argument, da je sscanf formatni niz
običajno sprejet kot konstanten,
in morda boste opazili niz, kot je ta pred uporabo printf.
Znak za odstotek v obliki niza nakazuje določilo pretvorbe.
Znak takoj po znak za odstotek,
označuje tip C, da želimo sscanf pretvoriti.
V GetInt, boste videli, da je% d in% d.
To pomeni, da bo sscanf poskusite decimalno notr - je% d - in char - za% c.
Za vsako določilo pretvorbe v obliki niza,
sscanf pričakuje ustrezno utemeljitev kasneje v spisek argumentov.
To trditev je treba opozoriti, da ustrezno tipkano mesto
v kateri hrani rezultat pretvorbe.
>> Tipičen način za to je, da ustvarite spremenljivko na stack pred klicem sscanf
Za vsak element, ki ga želite razčleniti iz niza
in nato uporabite naslov operaterja - Ta znak -, da prenese kazalcev
teh spremenljivk na razpisu sscanf.
Vidite lahko, da je v GetInt delamo točno to.
Tik pred klicem sscanf izjavljamo, int n imenom in char klicev C na kupu,
in se peljemo navodila o njih v razpisu sscanf.
Prenos teh spremenljivk na stack je prednost pred uporabo dodeljenih prostora
na kup z knjižnične funkcije malloc, ker ste se izognili dodatni obremenitvi na malloc razpisa,
in vam ni treba skrbeti za uhajanje pomnilnika.
Znaki niso predpono znak za odstotek ne pozove konverzijo.
Namesto tega preprosto dodate v formatu specifikacijo.
>> Na primer, če je format niz v GetInt bilo% d namesto tega
sscanf bi si za črko a sledi notr,
in medtem ko bi poskušal spremeniti int, da ne bi naredil ničesar drugega z A.
Edina izjema pri tem je presledek.
Bele presledke v obliki niza ujemata vsak znesek prostorom -
celo sploh ne.
Torej, to je, zakaj je komentar omenja možnosti z vodilnimi in / ali pike, presledke.
Torej, v tem trenutku izgleda, naš poziv sscanf poskusite razčleniti uporabnikov vhodni niz
s preverjanjem za morebitne vodilnih presledkov,
sledi notr, da se bo spreobrnilo in shrani v int spremenljivko n
sledilo nekaj višini presledki, in sledi znak
shranjeni v char spremenljivko c.
>> Kaj vrnjene vrednosti?
Sscanf bo razčleniti vhodne linije od začetka do konca,
ustavi, ko pride do konca ali če znak v vhodni
se ne ujema z obliko značaj ali če ne more narediti spremembo.
To je vrnjena vrednost se uporablja izpostaviti, ko se je ustavila.
Če se je ustavil, ker je dosegel konec vhodnega niza
Pred kakršnim koli spremembam in pred tem, da se ujemajo del formatu niza,
Nato se vrne posebno stalno EOF.
V nasprotnem primeru vrne število uspešnih konverzij
ki je lahko 0, 1 ali 2, odkar smo prosili za dve konverzije.
V našem primeru želimo zagotoviti, da si ga vnesli v notr pa samo notr.
>> Torej, želimo, da se vrnete sscanf 1. Oglejte si, zakaj?
Če sscanf vrne 0, potem pa so bile narejene nobene pretvorbe,
Tako si tipkal nekaj drugega kot notr na začetku vnosa.
Če sscanf vrne 2, nato pa uporabnik ni pravilno ga vnesite v na začetku vnosa,
vendar so nato vnesli v nekaterih lastnostih niso presledkov kasneje
od% c pretvorba uspelo.
To pa je precej dolgotrajen razlaga za 1 klic funkcije.
Kakorkoli že, če želite več informacij o sscanf in njene brate in sestre,
check out man strani, Google, ali oboje.
Obstaja veliko možnosti formatni niz
in ti lahko prihrani veliko ročnega dela, ko poskušajo razčleniti nize v C.
>> Končni funkcijo v knjižnici, ki si je GetString.
Izkazalo se je, da GetString je zapleteno funkcijo pravilno napisati,
čeprav se zdi, kot nekaj tako preprostega, skupno nalogo.
Zakaj je to tako?
No, pa pomislite, kako bomo za shranjevanje črto, da uporabnik vnese palcev
Ker Niz je zaporedje znakov,
mi bi želeli, da jo shranite v matriko na sklad,
vendar pa bi morali vedeti, kako dolgo zaporedje se bo, ko se bo prijavil.
Prav tako, če želimo, da jo položite na kup,
moramo opraviti, da knjižnične funkcije malloc število bajtov, ki jo želimo rezerve,
ampak to je nemogoče.
Ne vemo, koliko znakov bo uporabnik vnesli v
preden si dejansko ne jih vnašate.
>> Naivna rešitev tega problema je, da samo rezervirajo velik kos prostora, recimo,
Blok 1000 znakov za vnos uporabnika,
ob predpostavki, da si ne bi nikoli vnesite v nizu tako dolgo.
To je slaba ideja iz dveh razlogov.
Prvič, ob predpostavki, da uporabniki običajno ne vnesite v kito tako dolgo,
bi lahko odpadki veliko pomnilnika.
V sodobnih strojev, to ne bi bilo problem, če to
v enem ali dveh osamljenih primerih,
ampak, če jemljete uporabnika prispevek v zanki in skladiščenje za poznejšo uporabo,
lahko hitro sesati tone pomnilnika.
Poleg tega, če program, ki ga pišete, je za manjše računalnika -
naprave, kot so pametni ali kaj drugega z omejenim pomnilnikom -
Ta rešitev bo povzročilo težave veliko hitreje.
Druga, bolj tehten razlog za to je, ne da zapusti svoj program ranljive
s tem, kar se imenuje buffer overflow napad.
V načrtovanje, varovalni pomnilnik se uporablja za začasno shranjevanje vhodnih in izhodnih podatkov,
ki v tem primeru je naša 1000-char blok.
Buffer overflow zgodi, ko se podatki pisni mimo konca bloka.
>> Na primer, če si v resnici počne vrsto pri več kot 1000 znakov.
Morda ste doživeli to nesreči pri programiranju z nizi.
Če imate niz 10 ints, da te nič ne ustavi, da bi poskusila brati ali pisati
15. int.
Ni prevajalnika, opozoril ali napak.
Program le blunders naravnost in dostopi spomin
če misli, da bo 15. int, in to lahko prepiše vaše druge spremenljivke.
V najslabšem primeru lahko prepišete nekatere notranje vašega programa
nadzorne mehanizme, zaradi česar vaš program za dejansko izvedbo različnih navodil
kot ste želeli.
>> No, to ni skupna, da to stori po naključju,
ampak to je precej običajna praksa, da slabi ljudje uporabljajo za prekinitev programov
in dal zlonamerne kode na računalnikov drugih ljudi.
Zato se ne moremo preprosto uporabite našo naivno rešitev.
Potrebujemo način za preprečevanje naše programe od tega, da občutljive
na napad buffer overflow.
Če želite to narediti, se moramo prepričati, da lahko naše varovalni rastejo kot beremo
več vnos od uporabnika.
Rešitev? Mi uporabljamo varovalo kopice dodeljena.
Ker lahko velikost jo s Resize realloc funkcijo,
in smo spremljali dve števili - indeks naslednjo prazno režo v varovalnem
in dolžino ali zmogljivost pomnilnika.
Beremo v številu znakov od uporabnika 1 hkrati z uporabo fgetc funkcijo.
The trditvijo fgetc funkcija traja - stdin - je sklicevanje na standardni niz vnosa,
ki je preconnected vhod kanal, ki se uporablja za prenos uporabnika prispevek
iz terminala v program.
>> Kadarkoli uporabnik vnese v nov lik, preverimo, če je indeks
v naslednjem prosti reži plus 1 je večja od zmogljivosti pomnilnika.
Presega 1 prihaja, ker če je naslednji prosti indeks 5,
potem je naše medpomnilnik dolžina 6 zahvaljujoč 0 indeksiranje.
Če smo zmanjka prostora v varovalnem, nato pa bomo poskušali njegovo velikost,
je podvojilo, tako da smo zmanjšali število krat, da velikost
če uporabnik tipka v zelo dolgo vrvico.
Če je niz dobila predolga ali če zmanjka pomnilnika kopice,
smo osvoboditi našo pufer in povratni null.
>> Končno smo dodajte char v pufru.
Ko bo uporabnik vnese ali vrniti, signalizacijski novo vrstico,
ali poseben znak - nadzor d - ki signalizira konec vnosa,
naredimo pregled, da vidim, če je uporabnik dejansko vnesli v karkoli.
Če ne, se vrnemo null.
V nasprotnem primeru, saj je naš varovalni je verjetno večji, kot smo potrebovali,
V najslabšem primeru je skoraj dvakrat večji, kot smo potrebovali
saj smo dvakrat vsakič, ko spremenite velikost,
naredimo novo kopijo niza s samo količino prostora, ki ga potrebujemo.
Mi dodamo dodatno 1 do malloc klicu,
tako da je prostor zaradi posebnega značaja null terminatorja - za \ 0,
ki smo jih dodajte v nizu, ko smo kopirali v ostalih likov,
z strncpy namesto strcpy
tako da določite, koliko znakov želimo kopirati.
Strcpy kopije, dokler ne zadene \ 0.
Potem smo osvoboditi našo spomin in vrne izvod klicatelja.
>> Kdo je vedel tako enostaven navidezno funkcija se lahko tako zapletena?
Zdaj veš, kaj se dogaja v CS50 knjižnici.
>> Moje ime je Nate Hardison, in to je CS50.
[CS50.TV]