[Powered by Google Translate] [CS50 Knjižnica]
[Nate Hardison] [Sveučilište Harvard]
[Ovo je CS50. CS50.TV]
The CS50 knjižnica je koristan alat koji smo instalirali na aparatu
kako bi ga lakše za vas da pisati programe koji redak korisnicima za ulaz.
U ovom video, mi ćemo povući zastor i pogledati što je točno u CS50 knjižnici.
>> U videu o C knjižnicama, govorimo o tome kako se # include zaglavlja datoteka
od knjižnice u svoj izvorni kod,
i onda povezati s binarnim knjižnica datoteku tijekom povezivanja fazi
od kompilacijski procesa.
Datoteke zaglavlja odrediti sučelje knjižnice.
To jest, oni detaljno sve resurse koje knjižnica ima na raspolaganju za korištenje,
kao funkcija deklaracijama, konstante, i vrstama podataka.
Binarni knjižnica datoteka sadrži provedbu knjižnici,
koji je sastavljen iz knjižnice header datoteka i knjižnice. C izvorni kod datoteke.
>> Binarni knjižnica datoteka nije jako zanimljivo pogledati jer je, dobro, u binarnom.
Dakle, neka je pogledati zaglavlja datoteka za knjižnicu umjesto.
U tom slučaju, postoji samo jedna datoteka zaglavlja zove cs50.h.
Mi smo ga instalirali u korisnika uključuju imenik
zajedno s drugim sustavom knjižnica zaglavlja datoteka.
>> Jedna od prvih stvari koje ćete primijetiti je da cs50.h # uključuje zaglavlje datoteke iz drugih knjižnica -
float, granice, standardni bool, i standardni lib.
Opet, nakon načelo nije Reinventing točak,
smo izgradili CS0 knjižnicu koristeći alate koje druge predviđene za nas.
>> Sljedeća stvar koju ćete vidjeti u knjižnici je da ćemo definirati novu vrstu pod nazivom "string".
Ova linija stvarno samo stvara alias za char * tip,
tako da ne magično prožeti novi string tip s atributima
obično povezana s gudačkim objekata u drugim jezicima,
kao duljine.
Razlog što smo učinili to je štit novih programera iz krvavih pojedinosti
od pokazivača dok oni spremni.
>> Sljedeći dio datoteke zaglavlja je deklaracija funkcije
da CS50 knjižnica pruža zajedno s dokumentacijom.
Obavijest razinu detalja u komentarima ovdje.
To je super važno da ljudi znaju kako koristiti ove funkcije.
Izjavljujemo, pak, djeluje na brz korisnik i povrat znakovi, parovi, lebdi, Ints,
dugo čezne, i gudače, koristeći vlastitu string tip.
Nakon načela informacijskog skrivanja,
mi smo stavili našu definiciju u odvojeni c provedbe datoteku -. cs50.c--
nalazi u korisničkom direktoriju izvor.
Osigurali smo tu datoteku, tako da možete pogledati na njega,
učiti iz nje, a to rekompiliranje na različitim strojevima, ako želite,
iako mislim da je bolje da rade na aparatu za ovu klasu.
U svakom slučaju, neka je pogledati sada.
>> Funkcije getchar, GetDouble, GetFloat, GetInt, i GetLongLong
su sve sagrađen na vrhu GetString funkcije.
Ispada da su svi oni slijede u suštini isti uzorak.
Oni koriste while petlja za brz korisnik za jedan redak unosa.
Vraćaju posebnu vrijednost ako korisnik ulazi praznu liniju.
Oni pokušavaju analizirati korisnikov ulaz kao odgovarajućeg tipa,
bilo char, double, float, itd.
A onda su ili vratiti rezultat, ako je ulazni uspješno je analizirano
ili oni reprompt korisnika.
>> Na visokoj razini, ne postoji ništa stvarno lukav ovdje.
Možda su pisali na sličan način strukturiran kôd sebe u prošlosti.
Možda najviše zagonetna izgleda dio je sscanf poziv da analizira korisnikov ulaz.
Sscanf je dio pretvorbe ulazne formatu obitelji.
Ona živi u standardnom io.h, a njegov posao je da izdvoji jedan C string,
prema određenom formatu, spremanje izdvoji rezultate u varijablu
osigurava pozivatelja.
Budući da su ulazni format pretvorbe funkcije su vrlo korisni, naširoko koriste funkcije
da nisu super intuitivno na prvi,
ćemo ići preko kako sscanf radi.
>> Prvi argument da sscanf je char * - pointer na karakter.
Za funkciju da rade ispravno,
taj lik bi trebao biti prvi znak u nizu C,
prestaje s nulte \ 0 karaktera.
To je niz analizirati
Drugi argument za sscanf je format string,
obično prošao u kao string konstante,
a možda ste vidjeli niz ovako prije kada koristite printf.
Posto znak u format string označava pretvorbe specifikator.
Lik je odmah nakon znak za postotak,
ukazuje C-tipa koji želimo sscanf pretvoriti.
U GetInt, vidjet ćete da je% d i% c.
To znači da sscanf će pokušati decimalni int -% d - i char - The% c.
Za svaki pretvorbe specifikator u format string,
sscanf očekuje odgovarajući argument kasnije u popis argumenata.
Taj se argument mora ukazati na odgovarajući način upisali lokaciji
u kojem se pohraniti rezultat pretvorbe.
>> Tipičan način za to je stvoriti varijablu na stog prije sscanf poziva
za svaku stavku koju želite analizirati iz niza
, a zatim koristiti adresu operator - znak za struju - proći pokazivače
onim varijablama do sscanf poziva.
Možete vidjeti da je u GetInt radimo upravo to.
Neposredno prije sscanf poziva, mi proglasi int n zove i char poziva C na stog,
i prolazimo upućuje na njih u sscanf poziva.
Stavljanje ove varijable na stog se preferira nad korištenjem prostora predviđenog
na hrpi s malloc, budući da se izbjegne opterećenje od malloc poziva,
a vi ne morate brinuti o curi memorije.
Likovi nisu prefiksom strane posto znaka ne potaknuti pretvorbu.
Umjesto toga oni samo dodati formatu specifikaciji.
>> Na primjer, ako je format string u GetInt su% d umjesto toga,
sscanf će tražiti pismu je potom int,
i dok to će pokušati pretvoriti int, to ne bi ništa drugo od A.
Jedina iznimka je razmak.
Bijeli prostor likovi u format string odgovara bilo koji iznos od whitespace -
čak uopće.
Dakle, to je razlog zašto komentar spominje eventualno s vodećim i / ili prateći praznine.
Dakle, u ovom trenutku to izgleda kao naše sscanf poziv će pokušati analizirati korisnikovo ulaznog niza
provjerom za moguću vodećih razmakom,
Slijedi int koja će biti pretvorena i pohranjen u varijablu int n
slijedi neki iznos razmakom, a nakon čega slijedi lik
pohranjena u char varijable c.
>> Što o povratku vrijednosti?
Sscanf će analizirati liniju ulaznog od početka do kraja,
zaustavljanje kada dođe do kraja ili kad lik na ulazu
ne odgovara lik formata ili kada to ne može napraviti konverziju.
To je povratna vrijednost se koristi za izdvojiti kada je zaustavljen.
Ako je zaustavljen, jer je do kraja ulaznog niza
prije donošenja bilo kakve pretvorbe i prije nego što nije slagala dio format string,
zatim posebna konstanta EOF vraća.
Inače, ona vraća broj uspješnih pretvorbi,
koji može biti 0, 1, ili 2, jer smo tražili dvije konverzije.
U našem slučaju, želimo biti sigurni da je korisnik upisao u int i samo int.
>> Dakle, želimo sscanf vratiti jedan. Pogledajte zašto?
Ako sscanf vratio 0, onda nema obraćenja su,
tako da korisnik unese nešto drugo nego int na početku ulaza.
Ako sscanf vraća 2, tada je korisnik ispravno uspjeli upisati na početku ulaza,
ali su se tada upisali u neki ne-razmak karaktera poslije
od% c pretvorbe uspio.
Wow, to je prilično dugotrajan objašnjenje za jednu funkcija poziva.
U svakom slučaju, ako želite više informacija o sscanf i njegovih braće i sestara,
check out man stranice, Google, ili oboje.
Postoji puno format string mogućnosti,
a to može uštedjeti puno manualnog rada kada pokušavate analizirati konce u C.
>> Konačna funkcija u knjižnici pogledati je GetString.
Ispada da GetString je lukav funkcija pisati ispravno,
iako se čini kao takav jednostavan, zajednički zadatak.
Zašto je to tako?
Pa, neka je razmišljati o tome kako ćemo za pohranu liniju da korisnik upiše u.
Budući da je niz slijed znakova,
mogli bismo ga želite pohraniti u niz na stog,
ali mi bi trebao znati koliko dugo polje će biti kada smo ga proglasiti.
Isto tako, ako želimo da ga stavi na hrpu,
moramo proći da malloc broj bajtova želimo rezerve,
ali to je nemoguće.
Mi nemamo pojma koliko znakova će korisnik upisati u
prije nego što korisnik zapravo ne ih upisati.
>> Naivna rješenje za ovaj problem je da se samo rezervirati veliki komad prostora, recimo,
blok 1000 znakova za korisnika ulaz,
pod pretpostavkom da je korisnik nikada ne bi upišite u nizu koji je dugo.
To je loša ideja zbog dva razloga.
Prvo, pod pretpostavkom da je korisnik obično ne upisati žice koja je dugo,
mogli trošiti puno memorije.
Na modernim strojevima, to ne može biti problem ako ste to učinili
u jednoj ili dvije izoliranim slučajevima,
ali ako uzimate korisnika ulaz u petlji i spremanje za kasniju uporabu,
možete brzo usisati tonu memorije.
Osim toga, ako se program pišete je za manji računalo -
uređaja poput smartphone ili nešto drugo s ograničenom memorije -
ovo rješenje će uzrokovati probleme puno brže.
Druga, ozbiljnija razlog da ne učiniti to je da to ostavlja svoj program ranjiva
na ono što se zove napad buffer overflow.
U programiranju, tampon je memorija se koristi za privremeno spremanje ulaza ili izlaza podataka,
koja je u ovom slučaju naša 1000-char blok.
Buffer overflow nastaje kada se podaci pisani prošlosti kraju bloka.
>> Na primjer, ako korisnik zapravo tip u više od 1000 znakova.
Možda ste to doživjeli slučajno programiranje s polja.
Ako imate niz od 10 Ints, ništa vas ne prestaje s pokušavao čitati ili pisati
15. Int.
Nema prevodilac upozorenja ili pogreške.
Program samo zabluda ravno i pristupi memorije
gdje da misli da je 15. int će biti, a to se može prepisati svoje druge varijable.
U najgorem slučaju, možete prepisati neke od svoga programa unutarnje
kontrolni mehanizmi, uzrokujući svoj program zapravo izvršiti različite upute
nego što ste mislili.
>> Sada, to nije uobičajeno za to slučajno,
ali to je prilično uobičajena tehnika da loši momci koristiti za break programe
i staviti malicioznog koda na tuđim računalima.
Stoga, ne možemo koristiti našu naivnu rješenje.
Moramo način da se spriječi naše programe od toga da bude ranjiva
u napadu tampon preljeva.
Da biste to učinili, moramo biti sigurni da naš tampon može rasti kao što smo pročitali
više ulaz od korisnika.
Rješenje? Mi koristimo tampon hrpa dodijeljen.
Budući da možemo promijeniti veličinu ga pomoću promjenu veličine realloc funkciju,
i mi pratiti dva broja - indeks sljedeći prazni utor u međuspremniku
i duljine ili kapacitet pufera.
Čitamo u znakovi od korisnika jednog u vrijeme pomoću fgetc funkciju.
The argument fgetc funkcija traje - STDIN - je referenca na standardnom ulaznog niza,
koji je preconnected ulazni kanal koji se koristi za prijenos korisnikov ulaz
iz terminala na programu.
>> Kada korisnik upiše u novi lik, možemo provjeriti da li je indeks
od sljedećeg slobodnog utora plus 1 je veći od kapaciteta spremnika.
Oznake +1 dolazi u jer ako sljedeći slobodni indeks 5,
onda naše međupohrane dužina mora biti šest zahvaljujući 0 indeksiranje.
Ako smo ponestane prostora u spremniku, onda ćemo ga pokušati promijeniti veličinu,
ga udvostručenje tako da smo smanjiti broj puta da smo veličinu
ako je korisnik upisivanjem u jako dugom nizu.
Ako string je stečen predugo ili ako mi ponestane hrpa memorije,
smo oslobodili našu tampon i povratak null.
>> Konačno, mi dodati char na tampon.
Nakon pogotka korisnika ući ili vratiti, signalizirajući novu liniju,
ili posebna char - kontrola d - koji signalizira kraj ulaza,
mi ček vidjeti ako korisnik zapravo upisali u bilo uopće.
Ako ne, mi vratiti null.
Inače, jer je naša tampon je vjerojatno veći nego što nam je potrebno,
u najgorem slučaju to je gotovo dvostruko veća trebamo
jer mi dvaput svaki put smo promijenili veličinu,
ćemo napraviti novu kopiju niza pomoću samo količinu prostora da trebamo.
Mi dodati dodatni 1 do malloc poziva,
tako da postoji prostor za posebnu null terminator karaktera - na \ 0,
koje smo dodati na string jednom smo kopirali u ostatku likova,
pomoću strncpy umjesto strcpy
tako da možemo odrediti koliko točno znakovi želimo kopirati.
Strcpy kopira sve dok se ne udari \ 0.
Tada smo oslobodili našu tampon i vratiti primjerak pozivatelju.
>> Tko je znao kao jednostavan izgledom funkcija mogla biti tako komplicirano?
Sad znate što ide u CS50 knjižnici.
>> Moje ime je Nate Hardison, a ovo je CS50.
[CS50.TV]