[Powered by Google Translate] [CS50 Library]
[Nate Hardison] [Harvard University]
[To je CS50. CS50.TV]
Knižnica CS50 je užitočný nástroj, ktorý sme nainštalovali na spotrebiči
aby to pre vás jednoduchšie písať programy, ktoré vyzve používateľa pre vstup.
V tomto videu, budeme zatiahnite oponu a pozrieť sa na to, čo presne je v CS50 knižnici.
>> Vo videu na knižnice C, hovoríme o tom, ako si # include hlavičke súbory
z knižnice vo vašom zdrojovom kóde,
a potom prepojiť s binárnym súboru knižnice počas linkovanie fázy
z procesu kompilácie.
Hlavičkové súbory špecifikáciu rozhrania v knižnici.
To znamená, že detail všetkých zdrojov, ktoré má knižnica k dispozícii pre vás na použitie,
ako deklarácia funkcie, konštanty a dátové typy.
Binárny súbor knižnice obsahuje implementáciu knižnice,
, Ktorý je zostavený z knižnice hlavičkové súbory a knižnice. C súbory zdrojových kódov.
>> Binárny súbor s knižnicou nie je moc zaujímavé pozrieť sa na to, pretože, no, v binárnom formáte.
Takže, poďme sa pozrieť na hlavičkových súborov pre knižnicu miesto.
V tomto prípade je to iba jeden hlavičkový súbor nazvaný cs50.h.
Sme inštalovali v užívateľskej obsahovať adresár
spolu s hlavičkovým inom systéme knižníc súborov.
>> Jedna z prvých vecí, ktoré si všimnete, je skutočnosť, že cs50.h # obsahuje hlavičkové súbory z iných knižníc -
float, limity, štandardné bool a štandardné lib.
Opäť, podľa zásady, že nie je objavovanie Ameriky,
sme postavili CS0 knižnice pomocou nástrojov, ktoré ostatní stanovené pre nás.
>> Ďalšia vec, ktorú uvidíte v knižnici je, že my môžeme definovať nový typ nazvaný "string".
Táto linka naozaj len vytvára alias char * typ,
takže to nie je magicky naplniť nový typ reťazca s atribútmi
obyčajne spojené s fazuľovými objekty v iných jazykoch,
ako je dĺžka.
Dôvod, prečo sme urobili to je ochrániť nové programátorov z krvavých detailov
ukazovateľov, kým nebudú pripravení.
>> Ďalšia časť hlavičky súboru je deklarácia funkcií
že CS50 knižnica poskytuje spoločne s dokumentáciou.
Všimnite si, že úroveň podrobností v komentároch tu.
To je super dôležité, aby ľudia vedeli, ako používať tieto funkcie.
Prehlasujeme, v poradí, funguje vyzvať užívateľa a návrate znakov, dvojlôžkové, pláva, Ints,
dlho túži, a reťazce, s použitím vlastnej typ reťazca.
V súlade so zásadou skrývanie informácií,
sme dali naše definície v samostatnom súbore implementácie písaná v C -. cs50.c--
sa nachádza v adresári užívateľa zdroje.
Sme za predpokladu, že súbor, takže môžete sa pozrieť na to,
sa z nej poučiť, a prekompilovať to na rôznych strojoch, ak si prajete,
aj keď si myslíme, že je lepšie pracovať na zariadenia tejto triedy.
Každopádne, poďme sa pozrieť na to teraz.
>> Funkcia getchar, GetDouble, GetFloat, GetInt, a GetLongLong
sú postavené na vrchole GetString funkcie.
Ukazuje sa, že všetci riadiť v podstate rovnaký vzor.
Oni používajú slučky while vyzvať užívateľa na jeden riadok vstupu.
Oni sa vráti osobitnú hodnotu, pokiaľ užívateľ vstupy prázdnym riadkom.
Snaží sa analyzovať vstup užívateľa ako vhodný typ,
či už je to char, double, float, atď
A potom buď vrátiť výsledok, ak vstup bol úspešne analyzovaný
alebo sa reprompt užívateľa.
>> Na vysokej úrovni, nie je nič naozaj zložité tu.
Možno ste napísal podobne štruktúrovaná kód sami v minulosti.
Snáď najviac mystický vyzerajúci časť je sscanf volanie, ktoré analyzuje vstup užívateľa.
Sscanf je súčasťou konverzie vstupného formátu rodiny.
Žije v io.h štandardné, a jeho úlohou je analyzovať reťazec C,
podľa určitého formátu, ukladanie rozobrať výsledky v premennej
poskytuje volajúcim.
Vzhľadom k tomu, vstupné funkcie pre konverziu formátov sú veľmi užitočné, široko používané funkcie
že nie sú Super intuitívne najprv,
pôjdeme nad tým, ako sscanf funguje.
>> Prvý argument sscanf je char * - ukazovateľ na znak.
Pre funkcie pracovať správne,
že postava by mala byť prvý znak reťazca C,
ukončená s nulovým \ 0 znak.
Toto je reťazec, ktorý má analyzovať
Druhý argument sscanf je formátovací reťazec,
zvyčajne odovzdaná ako reťazcová konštanta,
a ste mohli vidieť reťazec, ako je tento pred pri použití printf.
Znak percenta vo formátovacom reťazci označuje konverzie špecifikátory.
Charakter bezprostredne po znak percenta,
označuje typ C, ktoré chceme sscanf previesť na.
V GetInt, uvidíte, že tam je% d, a% c
To znamená, že sscanf bude snažiť desatinnou int -% d - a char - je% c
Pre každý typ konverzie v parametri reťazec formáte,
sscanf očakáva zodpovedajúce tvrdenie, neskôr v jeho zozname argumentov.
Tento argument musí smerovať k zodpovedajúcim zadaný mieste
do ktorého sa ukladajú výsledok konverzie.
>> Typický spôsob, ako to urobiť, je vytvoriť premennú na zásobníku pred volaním sscanf
pre každú položku, ktorú chcete analyzovať z reťazca
a potom použite adresu operátora - ampersand - prejsť odkazy
týchto premenných do hovoru sscanf.
Môžete vidieť, že v GetInt robíme presne to.
Tesne pred volanie sscanf, sme deklarovať int s názvom n a char volanie C na zásobníku,
a míňame ukazovatele na ne do hovoru sscanf.
Uvedenie týchto premenných na zásobníku je prednostné cez používanie priestor pridelený
na halde s malloc, pretože sa vyhnete réžii malloc volanie,
a nemusíte sa starať o úniku pamäte.
Znaky nie sú predponou znakom percent nepobízejí konverziu.
Skôr sa len pridať k špecifikácii formátu.
>> Napríklad, v prípade, že reťazec formátu v GetInt boli% d miesto,
sscanf vyzerať za písmenom a nasleduje int,
a keď sa pokúsi previesť int, to by nebolo nič iného s A.
Jedinou výnimkou je medzera.
Biele medzery vo formátovacom reťazci nájdené žiadne množstvo medzerou -
dokonca žiadny vôbec.
Takže, to je dôvod, prečo komentár spomína prípadne s prednými a / alebo koncové medzery.
Takže, bude v tomto bode to vyzerá ako naša sscanf hovoru pokúsi analyzovať užívateľa vstupný reťazec
a kontrolovať prípadné vedúci medzerou,
nasleduje int, ktorá bude premenená a uložené v int premennej n
nasleduje nejakého množstva medzery, a nasleduje znak
uložený v premennej char c
>> Čo návratové hodnoty?
Sscanf bude analyzovať vstupné riadku od začiatku do konca,
zastavenie pri dosiahnutí konca alebo keď znak na vstupe
nezodpovedá formátu charakter, alebo ak nie je možné uskutočniť prevod.
Je to návrat hodnota sa používa vyčleniť, keď sa zastavil.
Ak sa zastavil, pretože na konci vstupného reťazca
pred vykonaním akejkoľvek konverzie a pred tým, že zápas časť formátovací reťazec,
potom špeciálna konštanta EOF je vrátená.
V opačnom prípade vráti počet úspešných konverzií,
, Ktoré by mohli byť 0, 1 alebo 2, pretože sme požiadaní o dve konverzie.
V našom prípade chceme, aby sa ubezpečil, že užívateľ napísané v int a iba na int.
>> Takže, chceme sscanf vrátiť 1. Pozrite sa, prečo?
Ak sscanf vrátil 0, potom žiadne prevody boli vykonané,
takže užívateľ napísal niečo iné ako int na začiatku vstupu.
Ak sscanf vráti 2, potom užívateľ sa riadne napíšte ju na začiatku vstupu,
ale oni potom písali v nejakom non-prázdny znak potom
od% c prevod úspešný.
Wow, to je docela zdĺhavý vysvetlenie jednom volanie funkcie.
Každopádne, ak chcete viac informácií o sscanf a jeho súrodenci,
pozrite sa na manuálové stránky, Google, alebo oboje.
Existuje veľa možností formátovacích reťazcov,
a tie vám môže ušetriť veľa manuálnej práce, keď sa snažia analyzovať reťazca v jazyku C.
>> Konečná funkcie v knižnici je pozrieť sa na GetString.
Ukazuje sa, že GetString je zložité funkcie písať správne,
aj keď sa to zdá ako taký jednoduchý, spoločnému úlohy.
Prečo je tomu tak?
No, poďme si o tom, ako budeme ukladať riadok, ktorý užívateľ zadá v
Vzhľadom k tomu, reťazec je postupnosť znakov,
by sme mohli chcieť uložiť ho do poľa na zásobníku,
ale potrebovali by sme vedieť, ako dlho pole bude, keď sme vyhlásiť ju.
Rovnako tak, ak chceme, aby to na hromadu,
musíme prejsť malloc počet bajtov chceme rezervy,
ale to je nemožné.
Nemáme potuchy, koľko znakov bude užívateľ písať,
predtým, než používateľ skutočne nemá písať.
>> Naivné riešenie tohto problému je len rezervovať veľký kus priestoru, povedzme,
blok 1000 znakov pre vstup užívateľa,
za predpokladu, že užívateľ by nikdy zadať reťazec, ktorý dlho.
To je zlý nápad to z dvoch dôvodov.
Po prvé, za predpokladu, že používatelia zvyčajne nemajú písať v reťazcoch tak dlho,
môžete odpad veľa pamäte.
Na moderných strojoch, mohlo by to byť problém, ak to
v jednom alebo dvoch ojedinelých prípadoch,
ale ak užívate vstup užívateľa do slučky a skladovanie pre neskoršie použitie,
môžete rýchlo vysať veľa pamäte.
Navyše, ak sa program píšete je pre menšie počítače -
zariadenia, ako je smartphone, alebo niečo iné s obmedzenou pamäťou -
toto riešenie bude spôsobovať problémy oveľa rýchlejšie.
Druhý, vážnejší dôvod to urobiť, je, že opustí svoj program zraniteľné
na to, čo sa nazýva pretečeniu vyrovnávacej pamäte útok.
V programovaní, vyrovnávacia pamäť je pamäť slúži na dočasné ukladanie vstupných alebo výstupných dát,
čo v tomto prípade je naša 1000-char blok.
Pretečeniu dochádza pri zápise dát za koncom bloku.
>> Napríklad, ak užívateľ skutočne robí typ vo viac ako 1000 znakov.
Možno ste to zažil náhodne pri programovaní s poľami.
Ak máte rad 10 ints, nič nezastaví vás z pokusu o čítanie alebo zápis
15. int.
Nie sú žiadne upozornenie kompilátora alebo chyby.
Program len prechmatov rovno a pristupuje pamäte
kde si myslí, že 15. int bude, a to môže prepísať svoje ďalšie premenné.
V najhoršom prípade môžete prepísať niektoré z vašich programu vnútornej
kontrolné mechanizmy, čo váš program, aby skutočne vykonať rôzne inštrukcie
, Ako ste zamýšľali.
>> Teraz, to nie je bežné, aby to náhodou,
ale je to celkom obyčajná technika, že protivníci používajú rozbiť programy
a dal škodlivého kódu na počítači iných ľudí.
Preto je možné nielen použiť náš naivné riešenie.
Potrebujeme spôsob, ako zabrániť naše programy od bytia zraniteľné
k pretečeniu vyrovnávacej pamäte útoku.
Ak to chcete urobiť, musíme sa uistiť, že naša vyrovnávacej pamäte môže rásť, ako sme si
viac vstup od užívateľa.
Riešenie? Používame haldy pridelenej vyrovnávacej pamäte.
Vzhľadom k tomu, môžeme zmeniť jeho veľkosť pomocou zmeniť veľkosť realloc funkciu,
a sledujeme z dvoch čísel - index ďalšieho prázdneho slotu vo vyrovnávacej pamäti
a dĺžka alebo kapacita pufri.
Čítame v znakov z užívateľského jeden po druhom pomocou fgetc funkciu.
The argument fgetc funkcie má - stdin - je odkaz na štandardný vstupný reťazec,
ktorý je preconnected vstupný kanál, ktorý sa používa pre prenos vstup užívateľa
z terminálu do programu.
>> Kedykoľvek užívateľ zadá do nového charakteru, môžeme skontrolovať, či index
ďalšieho voľného slotu plus 1 je väčší, než je kapacita vyrovnávacej pamäte.
The 1 prichádza v, pretože v prípade, že ďalší voľný index je 5,
potom naše vyrovnávacej pamäte dĺžka musí byť 6 vďaka 0 indexovanie.
Ak sme došli priestoru vo vyrovnávacej pamäti, potom sa snažíme zmeniť jeho veľkosť,
zdvojnásobenie to tak, že sa znížiť na to, koľkokrát sme veľkosť
v prípade, že používateľ je písanie v naozaj dlhé reťazce.
Ak reťazec dostal príliš dlho, alebo keď narazíme z haldy pamäte,
sme oslobodiť naše vyrovnávacej pamäte a vráti hodnotu NULL.
>> Nakoniec, pridáme char do vyrovnávacej pamäte.
Akonáhle užívateľ stlačí Enter alebo Return, čo signalizuje nový riadok,
alebo špeciálny znak - kontrolný d - čo signalizuje koniec vstupu,
robíme Skontrolujte, či užívateľ skutočne zadali vôbec nič.
Ak nie, vrátime null.
V opačnom prípade, pretože náš vyrovnávacej pamäte je pravdepodobne väčšia, než potrebujeme,
v najhoršom prípade je to takmer dvakrát tak veľká ako je potrebné
pretože sme dvakrát zakaždým, keď sme zmeniť veľkosť,
urobíme novú kópiu reťazca, iba pomocou množstvo priestoru, ktorý potrebujeme.
Sme pridať ďalšie 1 k malloc volanie,
tak, že je priestor pre špeciálne nulový znak terminátora - za \ 0,
ktoré pridáme do reťazca, akonáhle budeme kopírovať vo zvyšku postáv,
pomocou strncpy miesto strcpy
takže môžeme presne určiť, koľko znakov chceme kopírovať.
Strcpy kopíruje, kým nenarazí na \ 0.
Potom sme oslobodiť naše vyrovnávacej pamäte a vráti kópiu volajúcemu.
>> Kto vedel, že taký jednoduchý vyzerajúce funkcie by mala byť tak zložité?
Teraz už viete, čo ide do CS50 knižnice.
>> Moje meno je Nate Hardison, a to je CS50.
[CS50.TV]