[Powered by Google Translate] [CS50 Library]
[Nate Hardison] [Harvard Egyetem]
[Ez CS50. CS50.TV]
A CS50 könyvtár egy hasznos eszköz, hogy már telepített a készülékre
annak érdekében, hogy könnyebben programokat írhassanak, hogy a prompt felhasználók bemenet.
Ebben a videóban, akkor húzza vissza a függönyt, és nézd meg, mi is pontosan a CS50 könyvtárban.
>> A videó a C könyvtárak, beszélünk arról, hogy hogyan # include fejléc fájlokat
A könyvtár a forráskódot,
és akkor összekapcsolni egy bináris könyvtárfájlt alatt összekötő szakasz
A fordítási folyamat.
A fejléc fájlokat adja meg a felület a könyvtár.
Ez azt jelenti, hogy minden részlet a források, hogy a könyvtár áll rendelkezésre, hogy használd,
mint funkció nyilatkozatok, állandók, és adattípusok.
A bináris könyvtár fájl tartalmazza a végrehajtását a könyvtár,
amely össze a könyvtár header fájlokat és a könyvtár. c forráskód fájlokat.
>> A bináris könyvtár fájl nem nagyon érdekes, hogy nézd meg, mivel ez, nos, a bináris.
Nos, vessünk egy pillantást a header fájlokat a könyvtár helyett.
Ebben az esetben csak egy header file neve cs50.h.
Már telepítettem a felhasználói include könyvtárban
együtt a másik rendszer könyvtárak header fájlokat.
>> Az egyik első dolog, észre fogod venni, hogy az magában foglalja a cs50.h # header fájlokat más könyvtárak -
úszó, korlátok, standard bool, és a standard lib.
Ismét elvét követve nem újra feltalálja a kereket,
hoztuk létre a könyvtárat CS0 eszközök használatával, hogy a többi biztosított számunkra.
>> A következő dolog, látni fogod, a könyvtárban, hogy mi határozza meg egy új típusú úgynevezett "string."
Ez a vonal tényleg csak létrehoz egy fedőnevet a char * típusú,
így nem mágikusan beivódnak az új karakterlánc típusú attribútumok
gyakran társul húr tárgyakat más nyelveken,
mint a hossza.
Azért tettem ezt, hogy megvédje új programozók a véres részletek
mutatókat amíg készen.
>> A következő rész a fejléc fájl a nyilatkozatot a funkciók
hogy a CS50 könyvtár együtt dokumentációt.
Figyeljük meg a részletezettség szintjét a megjegyzések itt.
Ez szuper fontos, hogy az emberek tudják, hogyan kell használni ezeket a funkciókat.
Kijelentjük, viszont működik, hogy figyelmezteti a felhasználót és a visszatérő karakter, kétágyas, úszók, ints,
Hosszú vágyik, és a vonósok, a saját string típusú.
Elvét követve az információ rejtőzik,
mi valósult meg a meghatározást egy külön. c végrehajtás fájl - cs50.c--
található, a felhasználói forrás könyvtárba.
Már feltéve, hogy a fájl így vessen egy pillantást rá,
tanulni, és újrafordítani azt különböző gépeken, ha szeretné,
még ha azt gondoljuk, hogy jobb dolgozni a készüléket ebben az osztályban.
Mindegy, vessünk egy pillantást a most.
>> A funkciók GetChar, GetDouble, getFloat, getInt és GetLongLong
mind épül a getString funkciót.
Kiderül, hogy mindannyian követik lényegében ugyanazt a mintát.
Ezek használata while kérje a felhasználótól egy sor bemenet.
Ők vissza különleges értéket, ha a felhasználó be egy üres sort.
Azt próbálja meg értelmezni a felhasználó bemenet a megfelelő típust,
legyen az char, egy kétágyas, egy úszó, stb
És akkor sem tér vissza az eredmény, ha a bemeneti sikeresen értelmezhető
vagy azok reprompt a felhasználó.
>> Egy magas szintű, semmi sem igazán trükkös itt.
Lehet, hogy írt hasonlóan szerkesztett kódot magad a múltban.
Talán a leginkább titokzatos kinézetű része a sscanf hívást, hogy elemzi a felhasználó bemenet.
Sscanf része a bemeneti formátum konverziós család.
Él standard io.h, és a feladata, hogy elemezze a C string,
szerint egy adott formában, tárolja a feldolgozási eredményeket változó
által a hívó.
Mivel a bemeneti formátum konverziós funkció nagyon hasznos, széles körben használt funkcióit
, amelyek nem szuper intuitív először,
megyünk át, hogyan sscanf működik.
>> Az első érv, hogy sscanf egy char * - a mutató egy karaktert.
A funkció működik megfelelően,
hogy a karakter legyen az első karaktere a C string,
leállt a null \ 0 karakter.
Ez a string értelmezni
A második érv, hogy sscanf egy formátum string,
jellegzetesen telt, mint egy string állandó,
és lehet, hogy láttam egy string, mint ez előtt használatakor printf.
A százalék jel a format string jelez az átalakítás meghatározása.
A karakter követő egy százalék jelet,
jelzi, C típusú, hogy szeretnénk sscanf konvertálni.
A getInt, látod, hogy van egy% d és% c.
Ez azt jelenti, hogy sscanf megpróbál decimális int - a% d - és a char - a% c.
Minden átalakító meghatározása az a formátum string,
sscanf elvárja a megfelelő érvet később a paraméterek listája.
Ez az érv kell mutatnia egy megfelelően tipizált location
amelyben tárolni az eredményét a konverzió.
>> A tipikus módja ennek az, hogy hozzon létre egy változót a verem előtt sscanf hívás
minden kívánt elemet értelmezni a húr
majd a cím operátor - a jelet - át mutatók
e változók a sscanf hívást.
Láthatjuk, hogy a getInt mi pontosan ezt.
Jobb előtt sscanf hívást, akkor állapítsa int hívott n, és egy char c hívás a verem,
és mi át mutatókat őket a sscanf hívást.
Elhelyezés ezek a változók a verem előnyösebb, mint a térben elkülönített
A heap a malloc, mert így elkerülhető a felső a malloc hívás
és nem kell aggódnod szivárgó memóriát.
Karakterek nem előtaggal a százalék jel nem kér konverziót.
Inkább csak hozzá a formátum specifikáció.
>> Például, ha a formátum karakterláncot getInt volt egy% d helyette,
sscanf nézne ki a levelet egy, majd egy int,
és bár ez megpróbálja átalakítani a int, hogy nem csinál semmi mást az a.
Az egyetlen kivétel ez alól whitespace.
White space karaktereket a format string meccsek bármilyen összegű whitespace -
még egyáltalán.
Szóval, ezért a kommentár említi esetleg vezető-és / vagy záró szóközöket.
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
ellenőrzésével lehetséges vezető szóközök,
követ int, hogy lesz átváltani, és tárolni az int változó n
majd bizonyos mennyiségű whitespace, és utána egy karakter
tárolt char változó c.
>> Mi a helyzet a visszatérési érték?
Sscanf fogja elemezni a beviteli sor az elejétől a végéig,
megállás, amikor az eléri a vég, vagy ha egy karakter a bemenő
nem felel meg a formátum karaktert, vagy ha nem tudja, hogy egy konverzió.
Ez a visszatérési értéket használja azonosítottam, amikor megállt.
Ha megállt, mert elérte a végét a bemeneti karakterlánc
mielőtt bármilyen konverziók előtt nem, hogy megfeleljen része a format string,
akkor a speciális konstans EOF vissza.
Ellenkező esetben, visszatér a sikeres konverziók,
amely lehet 0, 1, vagy 2, hiszen már kért két konverziót.
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.
>> Szóval, mi szeretnénk sscanf vissza 1. Nézze meg, miért?
Ha sscanf vissza 0, akkor nincs konverzió történt,
így a felhasználó beírt valami más, mint egy int elején a bemenet.
Ha sscanf visszatér 2, akkor a felhasználó nem megfelelően gépelje be az elején a bemeneti,
de aztán beírt néhány nem szóköz-karaktere utána
mivel a% c konverzió sikerült.
Wow, ez elég hosszú magyarázatot egy függvényhívás.
Egyébként, ha többet szeretne tudni sscanf és testvérek,
nézd meg a man oldalakat, a Google, vagy mindkettő.
Sok format string lehetőségek,
és ezek mentheti meg egy csomó manuális munka, amikor megpróbálják értelmezni húrok C.
>> Az utolsó funkció a könyvtárban, hogy nézd meg getString.
Kiderül, hogy getString egy trükkös funkció írni megfelelően,
bár úgy tűnik, mint egy ilyen egyszerű, közös feladat.
Miért van ez így?
Hát, gondolom, arról, hogy hogyan fogjuk tárolni a sort, hogy a felhasználói típusokat be
Mivel a string sorozata karakter,
talán szeretnénk tárolni egy tömbben a stack,
de azt kell tudni, hogy milyen hosszú a tömb lesz, amikor nyilvánítja.
Hasonlóképpen, ha azt akarjuk, hogy azt a halom,
kell átadni a malloc bájtok számát szeretnénk tartalékba,
ez azonban nem lehetséges.
Fogalmunk sincs, hogy hány karakter a felhasználó írja
mielőtt a felhasználó valóban nem írja őket.
>> A naiv megoldás erre a problémára az, hogy csak fenn egy nagy darab helyet, mondjuk,
egy blokk az 1000 karakter a felhasználó bemenet,
feltételezve, hogy a felhasználó soha nem írjon be egy string, amely hosszú.
Ez egy rossz ötlet, két okból.
Először is, feltételezve, hogy a felhasználók általában nem írja be a vonósok, hogy a hosszú,
akkor hulladék rengeteg memória.
A modern gépek, ez nem lehet probléma, ha ezt
egy vagy két egyedi esettől,
de ha veszed felhasználói input egy hurok és tárolását későbbi használatra,
gyorsan szopni egy csomó memória.
Továbbá, ha a programot írsz Az egy kisebb számítógép -
Egy eszköz, mint egy okostelefon, vagy valami más korlátozott memória -
ez a megoldás problémát fog okozni sokkal gyorsabb.
A második, komolyabb ok arra, hogy nem ez az, hogy nem hagy a program sebezhető
hogy az úgynevezett puffer túlcsordulást támadást.
A programozás, a puffer memória átmeneti tárolására bemeneti vagy kimeneti adatokat,
amely ebben az esetben a mi 1000-char blokk.
Puffer túlcsordulás akkor beszélünk, ha az adatok írása múlt az a mondat végén.
>> Például, ha a felhasználó valójában mire típus több, mint 1000 karakter.
Lehet, hogy tapasztalta ezt véletlenül programozás a tömbök.
Ha van egy sor 10 ints, semmi nem gátolja Önt próbál írni vagy olvasni
15. int.
Nincsenek fordító figyelmeztetések vagy hibák.
A program csak a baklövéseket egyenesen előre, és hozzáfér a memória
ha úgy gondolja, a 15. int lesz, és ez felülírja a többi változót.
A legrosszabb esetben, akkor felülírhatja néhány program belső
ellenőrzési mechanizmusok, így a program, hogy ténylegesen végrehajtani különböző utasítások
, mint ahogy tervezte.
>> Nos, ez nem gyakori, hogy ezt véletlenül,
de ez egy meglehetősen gyakori módszer, hogy a rossz fiúk használják megtörni programok
és tedd rosszindulatú kódot mások számítógépeken.
Ezért nem lehet csak használni a naiv megoldást.
Szükségünk van egy módja annak, hogy megakadályozzák a programok veszélyeztetett
a buffer overflow támadást.
Ehhez meg kell, hogy megbizonyosodjon arról, hogy a puffer képes növekedni, mint olvasunk
több bemenet a felhasználó elől.
A megoldás? Az általunk használt halom lefoglalt pufferbe.
Mivel tudjuk átméretezni használatával az átméretezés a realloc funkció
és mi nyomon követheti a két szám - az index a következő üres helyet a puffer
és a hosszát vagy a puffer kapacitását.
Azt olvassuk a karakter a felhasználó egyesével a fgetc funkciót.
Az érvelés a fgetc függvény - stdin - utalás a standard input string,
amely egy preconnected bemeneti csatorna átviteléhez használt a felhasználó által megadott
A terminál a programhoz.
>> Amikor a felhasználó beír egy új karaktert, akkor nézze meg, ha az index
A következő szabad, valamint 1 nyílás nagyobb, mint a kapacitása a puffer.
A +1 jön, mert ha a következő szabad index 5,
akkor a puffer hosszúnak kell lennie 6 hála 0 indexelés.
Ha már elfogy a hely a pufferben, akkor próbálja átméretezni azt,
megduplázásával úgy, hogy vágjuk le, hogy hányszor, hogy átméretezni
ha a felhasználó beírja egy nagyon hosszú string.
Ha a string ütött túl hosszú, vagy ha elfogy a heap memória,
mi szabadítani a puffer és vissza null.
>> Végül, fűzze hozzá a karakter a pufferbe.
Ha a felhasználó látogatottság be vagy vissza-, jelző-egy új sort,
vagy a speciális char - control d - amely jelzi véget bemenet,
mi egy csekket, hogy ha a felhasználó ténylegesen beírt semmit.
Ha nem, akkor vissza null.
Ellenkező esetben, mert a puffer valószínűleg nagyobb, mint amire szükségünk van,
a legrosszabb esetben ez majdnem kétszer akkora, mint van szükségünk
hiszen dupla valahányszor átméretezni,
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.
Mi hozzá egy extra 1 a malloc hívás
úgy, hogy van hely a különleges null terminátor jelleg - a \ 0,
amelyhez csatolja a string amint másolni a többi karakter,
felhasználásával strncpy helyett strcpy
annak érdekében, hogy tudjuk meg, hogy pontosan hány karakter akarunk másolni.
Strcpy másolja, amíg eléri a \ 0.
Akkor szabad a puffer és a példányt visszaadja a hívónak.
>> Ki tudta, hogy egy ilyen egyszerű látszó funkció lehet olyan bonyolult?
Most már tudod, mi kerül a CS50 könyvtárba.
>> A nevem Nate Hardison, és ez CS50.
[CS50.TV]