[Powered by Google Translate] [CS50 Biblioteka]
[Nate Hardison] [Universiteti i Harvardit]
[Kjo është CS50. CS50.TV]
Biblioteka CS50 është një mjet i dobishëm që kemi instaluar në aplikim
për ta bërë të lehtë për ju për të shkruar programe që përdoruesit të shpejtë për input.
Në këtë video, ne do të tërheq mbrapsht perde dhe të shikojmë se çfarë saktësisht është në bibliotekë CS50.
>> Në video në bibliotekat C, ne flasim rreth asaj se si ju të përfshijë # headers fotografi
i bibliotekës në kodin tuaj burim,
dhe pastaj ju lidhje me një file binar bibliotekës gjatë fazës lidh
e procesit të kolazhin.
Fotografi header specifikojë ndërfaqen e bibliotekës.
Kjo është, ato detaje të gjitha burimeve që biblioteka ka në dispozicion për ju për të përdorur,
si deklarimeve funksion, konstantet, dhe lloje të të dhënave.
File binar Biblioteka përmban zbatimin e bibliotekës,
e cila është hartuar nga dosjet e bibliotekës header dhe të bibliotekës. kod burim c fotografi.
>> File binar Biblioteka nuk është shumë interesante për të parë që ajo është, mirë, në binar.
Pra, le të marrin një vështrim në dosjet header për bibliotekën vend.
Në këtë rast, ka vetëm një file header quajtur cs50.h.
Ne kemi instaluar atë në përdorues të përfshijë në dosjen
së bashku me fotografi bibliotekat e tjera të sistemit header.
>> Një nga gjërat e para që ju do të vëreni është se cs50.h # përfshin fotografi header nga bibliotekat e tjera -
noton, kufijtë, bool standarde, dhe standarde lib.
Përsëri, ndjekur parimin e mos Reinventing timon,
ne kemi ndërtuar bibliotekën CS0 duke përdorur mjetet që të tjera të parashikuara për ne.
>> Gjë tjetër që ju do të shihni në bibliotekë është se ne të përcaktojë një lloj të ri të quajtur "string".
Kjo linjë të vërtetë vetëm krijon një pseudonim për llojin char *,
kështu që nuk ka magjike mbushë lloj të ri string me atributet
lidhur zakonisht me objekte string në gjuhë të tjera,
të tilla si gjatësi.
Arsyeja që ne kemi bërë këtë është që të mbrojë programuesit të reja nga detajet gjakosur
i pointers derisa ata janë të gatshëm.
>> Pjesa tjetër e file header është deklarimi i funksioneve
se CS50 Biblioteka ofron së bashku me dokumentacionin.
Njoftim nivelin e detaje në komente këtu.
Kjo është super i rëndësishëm në mënyrë që njerëzit të dinë se si të përdorin këto funksione.
Ne deklarojmë, nga ana tjetër, funksionon me të shpejtë e përdoruesit dhe chars kthim, dyshe, gjithandej, ints,
gjatë dëshiron, dhe vargjet, duke përdorur llojin e vet tonë string.
Duke ndjekur parimin e fshehur informacionit,
ne kemi vënë përkufizimin tonë në një skedar të veçantë zbatimit të c -. cs50.c--
vendosur në directory burim përdoruesit.
Ne kemi dhënë atë fotografi në mënyrë që ju mund të marrë një vështrim në atë,
të mësojnë prej saj, dhe recompile atë në makina të ndryshme në qoftë se ju dëshironi,
edhe pse ne mendojmë se është më mirë për të punuar në aplikim për këtë klasë.
Gjithsesi, le të marrin një vështrim në atë tani.
>> Funksionet GetChar, GetDouble, GetFloat, GetInt, dhe GetLongLong
janë ndërtuar të gjitha në krye të funksionit getString.
Ajo rezulton se të gjithë ata ndjekin në thelb të njëjtin model.
Ata përdorin një lak, ndërsa të menjëhershëm të përdoruesit për një linjë të dhëna.
Ata kthehen një vlerë të veçantë në qoftë se përdoruesi inputeve një vijë e zbrazët.
Ata përpiqen të kuptoj kontributin e përdoruesit si lloji të përshtatshëm,
të jetë ajo një char, një dopio, një noton, etj
Dhe pastaj ata ose të kthehen rezultatin nëse input u parsed sukses
ose ata reprompt përdorues.
>> Në një nivel të lartë, nuk ka asgjë të vërtetë e ndërlikuar këtu.
Ju mund të keni shkruar kodin ngjashme strukturuar veten në të kaluarën.
Ndoshta pjesa më e fshehtë-looking është thirrja që sscanf parses input të përdoruesit.
Sscanf është pjesë e familjes format input konvertimit.
Ajo jeton në io.h standarde, dhe puna e tij është të kuptoj një varg C,
sipas një format të veçantë, ruajtja e rezultateve të kuptoj në të ndryshueshme
dhënë nga telefonuesi.
Që nga funksionet format input konvertimit janë shumë të dobishme, funksionet e përdorur gjerësisht
që nuk janë super intuitive në fillim,
ne do të shkojnë mbi atë se si punon sscanf.
>> Argumenti i parë për sscanf është një char * - një tregues për një karakter.
Për funksioni për të punuar si duhet,
se karakteri duhet të jetë karakteri i parë i një varg C,
ndërprerë me karakter \ null 0.
Ky është vargu të kuptoj
Argumenti i dytë për sscanf është një format string,
kaluar në mënyrë tipike në si një konstante string,
dhe ju mund të keni parë një varg si kjo para kur duke përdorur printf.
Një shenjë qind në vargun format tregon një specifier konvertimit.
Karakteri menjëherë pas një shenjë për qind,
tregon llojin C se ne duam sscanf për të kthyer në.
Në GetInt, ju shihni se ka një d% dhe c%.
Kjo do të thotë se do të përpiqet të sscanf një int decimal d -% - dhe një char - C%.
Për çdo specifier konvertimit në formatin vargut,
sscanf pret një argument korrespondon më vonë në listën e saj argument.
Se argumenti duhet të vënë në një vend të duhur typed
në të cilat për të ruajtur rezultatin e konvertimit.
>> Mënyra tipike e bërë këtë është të krijojë një ndryshore në rafte para thirrjes sscanf
për çdo send që ju doni të kuptoj nga vargu
dhe pastaj të përdorin operatorin e adresave - e simbol - të kalojë pointers
këtyre variablave të thirrjes sscanf.
Ju mund të shihni se në GetInt bëjmë pikërisht këtë.
Drejtë para thirrjes sscanf, ne deklarojmë një int n quajtur dhe një char c thirrje në rafte,
dhe ne të kalojë pointers të tyre në thirrjen sscanf.
Vënë këto variabla në rafte është e preferuar mbi përdorimin e hapësirës caktuar
në tog me malloc, që ju të shmangur lart e thirrjes malloc,
dhe ju nuk keni për t'u shqetësuar për rrjedhjen e kujtesës.
Personazhet nuk prefixed nga një shenjë për qind nuk shpejtë konvertimit.
Përkundrazi ata vetëm të shtoni në specifikimet format.
>> Për shembull, nëse string format në GetInt ishte një d% në vend,
sscanf do të shikojmë për një letër e ndjekur nga një int,
dhe ndërsa kjo do të përpiqet për të kthyer int, ajo nuk do të bëjë asgjë tjetër me një.
Përjashtimi i vetëm për këtë është hapësira të bardha.
White karaktere hapësirë ​​në vargun formatin përputhen me ndonjë sasi e whitespace -
edhe asnjë në të gjitha.
Pra, kjo është arsyeja pse komenti përmend ndoshta me kryesorë dhe / ose zvarritës whitespace.
Pra, në këtë pikë ajo duket si thirrjen tonë sscanf do të përpiqet të kuptoj vargun e përdoruesit input
duke kontrolluar për whitespace mundshme kryesor,
ndjekur nga një int që do të konvertohet dhe ruajtur në n ndryshueshme int
pasuar nga disa shuma e whitespace, dhe e ndjekur nga një karakter
ruhen në c char ndryshueshme.
>> Po në lidhje me vlerën e kthimit?
Sscanf do analizimi linjë input nga fillimi në fund,
ndalimin e kur ajo arrin në fund, ose kur një karakter në input
nuk përputhet me një karakter format ose kur ajo nuk mund të bëjë një konvertim.
Vlera është e kthimit është përdorur për të vetëm kur ajo u ndal.
Në qoftë se ajo u ndal, sepse ajo arriti në fund të vargut të dhëna
përpara se të bëjnë ndonjë conversions dhe para dështuar në ndeshjen pjesë të string format,
pastaj EOF veçantë konstante është kthyer.
Përndryshe, ai kthehet numrin e konvertimeve të suksesshme,
cila mund të jetë 0, 1, ose 2, që ne kam kërkuar për dy konvertimet.
Në rastin tonë, ne duam të sigurohemi që përdoruesi typed në një int dhe vetëm një Int.
>> Pra, ne duam sscanf të kthehen 1. Shih pse?
Nëse sscanf kthye 0, atëherë nuk ka konvertimet janë bërë,
në mënyrë që përdoruesit shtypur diçka tjetër se një int në fillim të input.
Nëse sscanf kthen 2, atëherë përdoruesi nuk duhet të shkruani atë në në fillim të input,
por ato shtypen më pas në disa karakter jo-whitespace pas
që nga% c konvertimit sukses.
Wow, kjo është krejt një shpjegim të gjatë për një thirrje të funksionit.
Gjithsesi, në qoftë se ju doni më shumë informacion mbi sscanf dhe vëllezërit e motrat e saj,
shikoni faqet e njeri, Google, ose të dyja.
Ka shumë opsione string format,
dhe këto mund të ju kursejnë një shumë të punës manual kur duke u përpjekur të kuptoj vargjet në C.
>> Funksioni përfundimtar në bibliotekë për të parë në është getString.
Ajo rezulton se getString është një funksion i ndërlikuar për të shkruar si duhet,
edhe pse kjo duket si një detyrë të tillë të thjeshtë, të përbashkët.
Pse është ky rast?
E pra, le të mendojmë rreth asaj se si ne jemi duke shkuar për të ruajtur vijën që përdoruesi lloje in
Që një varg është një sekuencë e karaktere,
ne mund të dëshironi të ruani atë në një grup në rafte,
por ne do të duhet të dini se sa kohë array do të jetë kur ne e deklarojnë atë.
Gjithashtu, në qoftë se ne duam të vënë atë në mur,
ne kemi nevojë për të kaluar në malloc numrin e bytes ne duam të rezervave,
por kjo është e pamundur.
Ne nuk kemi asnjë ide se sa chars përdoruesit do të shkruani në
para se përdoruesi të vërtetë nuk shkruani ato.
>> Një zgjidhje naive për këtë problem është që të rezervoj vetëm një copë të madhe të hapësirës, ​​të themi,
një bllok prej 1000 karaktere për kontributin e përdoruesit,
duke supozuar që përdoruesit kurrë nuk do të shkruani në një varg që gjatë.
Kjo është një ide e keqe për dy arsye.
Së pari, duke supozuar që përdoruesit zakonisht nuk shkruani vargjet aq gjatë,
ju mund të humbim një shumë të kujtesës.
Në makinat moderne, kjo nuk mund të jetë një çështje, nëse ju bëni këtë
në një ose dy raste të izoluara,
por në qoftë se ju jeni duke marrë të dhëna përdoruesi në një lak dhe ruajtjen për përdorim të mëvonshëm,
ju mund të shpejt thith deri një ton të kujtesës.
Përveç kësaj, në qoftë se ju jeni me shkrim programi është për një kompjuter më të vogël -
një pajisje si një smartphone apo diçka tjetër me kujtesë të kufizuar -
kjo zgjidhje do të shkaktojë probleme shumë më të shpejtë.
E dyta, arsyeja më serioz që të mos e bëjnë këtë është se ajo lë programin tuaj të pambrojtur
në atë që quhet një tampon del nga shtrati sulm.
Në programimin, një tampon është memorie përdoret për të ruajtur përkohësisht të dhëna ose të prodhimit të dhënave,
e cila në këtë rast është bllok 1000-char tonë.
Një tampon del nga shtrati ndodh kur të dhënat është shkruar kaluara në fund të bllokut.
>> Për shembull, në qoftë se një përdorues të vërtetë e bën lloji në më shumë se 1000 karaktere.
Ju mund të keni përjetuar këtë aksidentalisht kur programimit me vargjeve.
Nëse ju keni një koleksion prej 10 ints, asgjë nuk ju ndalon të duke u përpjekur për të lexuar ose shkruar
int 15.
Nuk ka paralajmërime ose përpiluesit gabime.
Programi vetëm gabimet drejt përpara dhe accesses kujtesës
ku ajo mendon se do të jetë int 15, dhe kjo mund të prishësh variablave tuaja të tjera.
Në rastin më të keq, ju mund të prishësh disa brendshëm programit tuaj
mekanizmat e kontrollit, duke shkaktuar programin tuaj të vërtetë të ekzekutojë udhëzimet ndryshme
se ju qëllim.
>> Tani, kjo nuk është e zakonshme për të bërë këtë aksidentalisht,
por kjo është një teknikë mjaft e zakonshme që liq përdorni për të thyer programe
dhe të vënë të dëmshme në kompjuterë të njerëzve të tjerë.
Prandaj, ne nuk mund të përdorni vetëm zgjidhje tonë naiv.
Ne kemi nevojë për një mënyrë për të parandaluar programet tona nga të qenit të pambrojtur
për një sulm del nga shtrati tampon.
Për ta bërë këtë, ne duhet të sigurohemi që tampon tonë mund të rritet si lexojmë
input më shumë nga përdoruesit.
Zgjidhje? Ne përdorim një tampon ndarë tog.
Që ne mund të ndrysho atë duke përdorur Resize funksionin realloc,
dhe ne të mbajtur gjurmët e dy numrave - indeksi i ardhshëm slot bosh në tampon
dhe gjatësia ose kapaciteti i tampon.
Ne lexojmë në karaktere nga përdoruesit në një kohë duke përdorur funksionin fgetc.
Argumenti funksioni fgetc merr - STDIN - është një referencë për vargun standarde input,
cila është një kanal preconnected input se është përdorur për të transferuar futjen e përdoruesit
nga terminali tek programit.
>> Kurdo që përdoruesi lloje në një karakter të ri, ne kontrolloni për të parë nëse indeksi
e çarë e ardhshëm të lirë plus 1 është më i madh se kapaciteti i buffer.
The +1 vjen në, sepse në qoftë se indeksi i ardhshëm lirë është 5,
atëherë gjatësia Buffer sonë duhet të jetë 6 falë 0 indeksimit.
Në qoftë se ne kemi të drejtuar nga hapësira në tampon, atëherë ne përpjekje për të resize atë,
dyfishuar atë mënyrë që ne të shkurtuar në numrin e herë që ne resize
në qoftë se përdoruesi është shtypur në një varg të gjatë me të vërtetë.
Nëse vargu ka marrë shumë kohë ose në qoftë se ne të drejtuar nga e kujtesës tog me ta,
ne liruar tampon tonë dhe NULL kthimit.
>> Së fundi, ne append char në tampon.
Pasi hitet përdorues të hyjë ose të kthehen, duke sinjalizuar një linjë të re,
ose speciale char - kontrollit d - i cili sinjalizon një fund të kontributit,
ne bëjmë një kontroll për të parë në qoftë se përdoruesi shtypur në të vërtetë në asgjë në të gjitha.
Nëse jo, do të kthehemi null.
Përndryshe, sepse tampon tonë është ndoshta më e madhe se ne kemi nevojë,
në rastin më të keq është pothuajse dy herë më i madh sa ne kemi nevojë
pasi ne çdo herë kemi dyfishtë resize,
kemi bërë një kopje të re të vargut duke përdorur vetëm sasi e hapësirës që ne kemi nevojë.
Ne shtoni një shtesë 1 të thirrjes malloc,
kështu që nuk ka hapësirë ​​për karakterin e veçantë null terminator - e \ 0,
të cilat ne append në vargun dikur ne kopje në pjesën tjetër të karaktereve,
strncpy përdorur në vend të strcpy
kështu që ne mund të përcaktojë saktësisht se sa chars ne duam të kopje.
Strcpy kopjon deri sa ajo godet një \ 0.
Pastaj ne liruar tampon tonë dhe kthehen kopje të thirrësit.
>> Kush e dinte tillë thjeshtë në dukje funksioni mund të jetë i komplikuar kështu?
Tani ju e dini se çfarë shkon në bibliotekë CS50.
>> Emri im është Nate Hardison, dhe kjo është CS50.
[CS50.TV]