[Powered by Google Translate] [CS50 Library]
[Nate Hardison] [Harvard University]
[Ito ay CS50. CS50.TV]
Ang CS50 library ay isang kapaki-pakinabang na tool na aming na-install sa appliance
upang gawing mas madali para sa iyo upang sumulat ng mga programa na prompt mga gumagamit para sa input.
Sa video na ito, makikita namin hilahin ang kurtina at tingnan kung ano ang eksaktong ay sa CS50 library.
>> Sa video sa mga aklatan sa C, makipag-usap namin tungkol sa kung paano mo # include file header
ng library sa iyong source code,
at pagkatapos ay i-link mo sa isang binary file ng library sa panahon ng phase ang pag-link
ng compilation proseso.
Ang mga file header tukuyin ang interface ng library.
Iyon ay, sila detalye ng lahat ng mga mapagkukunan na library ay magagamit para sa iyo upang gamitin ang,
tulad ng mga function na pagdeklara, constants, at mga uri ng data.
Ang binary file ng library ay naglalaman ang pagpapatupad ng library,
na inipon mula sa mga file ng header sa library at ang library. c source code file.
>> Ang binary file ng library ay hindi lubhang kawili-wili upang tingnan dahil, well, sa binary.
Kaya, sabihin tingnan ang mga file ng header para sa library sa halip.
Sa kasong ito, mayroon lamang isang header ng file na tinatawag na cs50.h.
Namin na-install ang mga ito sa gumagamit ang direktoryo
kasama ang sa iba pang mga sistema ng aklatan 'file ng header.
>> Isa ng ang unang bagay na mapapansin mo ay cs50.h # ang mga file ng header mula sa iba pang mga aklatan -
Float, mga limitasyon, karaniwang bool, at karaniwang Lib.
Muli, ng pagsunod sa mga prinsipyo ng hindi reinventing ang wheel,
na binuo namin ang CS0 library na gamit ang mga tool na ang ibang para sa amin.
>> Ang susunod na bagay na makikita mo sa library na namin tukuyin ang isang bagong uri ng tinatawag na "string."
Linyang ito ay talagang lamang lumilikha ng isang alias para sa magpasinda * uri,
kaya hindi ito ay magically humitik ang bagong uri ng string na may mga katangian
karaniwang nauugnay sa mga bagay ng string sa iba pang mga wika,
tulad ng haba.
Ang dahilan kung bakit namin nagawa mo na ito sa kalasag ang mga bagong programmer mula sa madugo detalye
ng mga payo hanggang sila ay handa.
>> Ang susunod na bahagi ng file ng header ay ang deklarasyon ng function
na ang CS50 library nagbibigay kasama ang dokumentasyon.
Pansinin ang antas ng detalye sa ang mga komento dito.
Ito ay sobrang mahalaga upang ang mga taong kilala kung paano gamitin ang mga function.
Idedeklara namin, sa pagliko, function upang i-prompt ng gumagamit at return char, Doubles, kamay, ints,
mahaba na longs, at mga string, gamit ang ating sariling uri ng string.
Ng pagsunod sa mga prinsipyo ng impormasyon nagtatago,
ilagay namin ang aming kahulugan sa isang hiwalay na file na c pagpapatupad - cs50.c--
na matatagpuan sa direktoryo ng pinagmulan ng user.
Nagbigay kami ng mga file na sa gayon maaari mong tingnan ito,
matuto mula sa ito, at mag-recompile ito sa ibang machine kung nais mo,
kahit na sa tingin namin ito ay mas mahusay na upang gumana sa appliance para sa uri.
Pa Rin, sabihin tingnan ito ngayon.
>> Ang mga function ng GetChar, GetDouble, GetFloat, GetInt, at GetLongLong
ay itinayo sa tuktok ng GetString function na.
Ito lumiliko out na lahat ng mga ito ay sundin ang mahalagang parehong pattern.
Gamitin ito ay may habang loop upang i-prompt ang user para sa isang linya ng input.
Ibalik ang mga ito ng espesyal na halaga kung ang user input ang isang walang laman na linya.
Tinangka nilang upang i-parse ang input ng user bilang ang naaangkop na uri,
maging ito ng isang pansamantalang trabaho, may double, isang Float, atbp.
At pagkatapos ay ibalik ang resulta kung input ay matagumpay na na-parse
o reprompt sila ang gumagamit.
>> Sa isang mataas na antas, wala talagang nakakalito dito.
Maaari mong nakasulat na katulad nakabalangkas na code ang iyong sarili sa nakaraan.
Marahil ang pinaka mukhang misteriyoso-bahagi ang sscanf tawag na Pina-parse ang input ng user.
Sscanf ay bahagi ng conversion sa format ng input pamilya.
Nakatira sa karaniwang io.h, at ang trabaho nito ay upang i-parse ng C string,
ayon sa isang partikular na format, itinatago ang mga resulta ng parse sa variable
ibinigay ng tumatawag.
Dahil ang format ng input function ng conversion ay masyadong kapaki-pakinabang, malawakang ginagamit function
na hindi sobrang intuitive sa una,
kami sa kung paano sscanf gumagana.
>> Ang unang argumento sa sscanf ay isang pansamantalang trabaho * - isang pointer sa isang character.
Para sa function upang gumana nang maayos,
character na dapat ay ang unang character ng isang string ng C,
winakasan na may null \ 0 karakter.
Ito ay ang string upang i-parse
Ang pangalawang argumento sa sscanf ay isang format string,
karaniwang naipasa in bilang isang string ng pare-pareho,
at maaaring nakakita ka ng isang string tulad nito bago kapag gumagamit ng printf.
Isang porsiyento mag-sign in ang string ng format ay nagpapahiwatig isang conversion specifier.
Agad ang character na ang pagsunod sa isang porsiyento sign,
nagpapahiwatig C uri na gusto naming sscanf i-convert.
Sa Sa GetInt, makita na may% d at% c.
Nangangahulugan ito na sscanf ay subukang ng decimal int -% d - at isang pansamantalang trabaho -% c.
Para sa bawat conversion specifier sa string ng format,
sscanf inaasahan ang isang naaayong argumento sa ibang pagkakataon sa listahan ng argumento.
Argument na dapat ituro sa isang naaangkop na-type na lokasyon
kung saan-imbak ang resulta ng conversion.
>> Ang tipikal na paraan ng paggawa nito ay upang lumikha ng isang variable sa stack bago ang sscanf tawag
para sa bawat item na gusto mong i-parse mula sa string
at pagkatapos ay gamitin ang address ng operator - ang ampersand - upang pumasa sa mga payo
sa mga variable sa tawag sscanf.
Maaari mong makita na sa GetInt gawin namin ang eksaktong ito.
Bago mismo ang tawag ng sscanf, aming ipinapahayag ng isang int tinatawag n at magpasinda c tawag sa stack,
at pumasa kami ng mga payo sa kanila sa tawag ng sscanf.
Paglalagay ng mga variable na ito sa stack ay ginustong sa paglipas ng paggamit ng espasyo inilalaan
sa magbunton sa malloc, dahil mong maiwasan ang overhead ng tawag ng malloc,
at hindi mo na kailangang mag-alala tungkol sa tagas memory.
Character hindi prefix sa pamamagitan ng pag-sign ng porsiyento hindi prompt ng conversion.
Sa halip lang nila idagdag sa detalye ng format.
>> Halimbawa, kung ang string ng format sa GetInt ay% d sa halip,
ay tumingin ng sscanf para sa titik na sinusundan ng isang int,
at habang ito ay subukang i-convert ang int, hindi ito ay gawin ang anumang bagay na may isang.
Ang tanging mga pagbubukod na ito ay whitespace.
Puting espasyo character sa string ng format na tumugma sa anumang mga halaga ng whitespace -
kahit wala sa lahat.
Kaya, na ang dahilan kung bakit ang komento ang pagbanggit posibleng sa mga nangungunang at / o sumusunod whitespace.
Kaya, sa puntong ito mukhang aming sscanf tawag ay subukang i-parse ang input string ang user
sa pamamagitan ng check para sa posibleng nangungunang whitespace,
sinundan sa pamamagitan ng isang int na mako-convert at naka-imbak sa int variable n
sinusundan ng ilang halaga ng whitespace, at sinusundan ng isang character
naka-imbak sa magpasinda variable c.
>> Paano ang tungkol sa mga halaga ng return?
Sscanf ay parse ang linya ng input mula simula hanggang matapos,
pagtigil kapag umabot sa dulo o kapag isang character sa input
ay hindi tumutugma sa isang format ng character o kapag hindi ito gumawa ng conversion.
Ito ang return halaga ay ginagamit sa solong kapag ito tumigil.
Kung huminto ito, dahil naabot na ninyo ang dulo ng input string
bago gumawa ng anumang mga conversion at bago bagsak upang tumugma sa bahagi ng string ng format,
pagkatapos ay ang mga espesyal na pare-pareho ang EOF ay ibinalik.
Kung hindi man, nagbabalik ang bilang ng mga matagumpay na conversion,
na maaaring 0, 1, o 2, dahil tatanungin namin ang para sa dalawang mga conversion.
Sa aming kaso, nais naming tiyakin na ang gumagamit na nai-type sa isang int at lamang sa isang int.
>> Kaya, gusto naming sscanf upang bumalik 1. Makita kung bakit?
Kung sscanf ibinalik 0, pagkatapos ay walang mga conversion ay ginawa,
kaya ang user-type ng isang bagay maliban sa isang int sa simula ng input.
Kung nagbabalik ng sscanf 2, ang user ay maayos type ito sa sa simula ng input,
ngunit pagkatapos nila na nai-type sa ilang di-whitespace character na pagkatapos
simula ng% c conversion nagtagumpay.
Wow, na medyo isang napakahabang paliwanag para sa isang function na tawag.
Pa rin, kung nais mo ng karagdagang impormasyon sa sscanf at ang kapatid,
tingnan ang mga pahina ng tao, Google, o pareho.
Mayroong maraming ng mga pagpipilian sa format string,
at ang mga ito ay maaaring i-save ka ng maraming trabahong pangkamay kapag sinusubukang upang i-parse ang mga string sa C.
>> Ang huling function sa library upang tumingin sa GetString.
Ito lumiliko out na ang GetString ay isang mahirap imaneho function na magsulat ng maayos,
kahit na ito tila tulad ng isang simple, karaniwang gawain.
Bakit ito ang kaso?
Well, sabihin isipin ang tungkol sa kung paano namin upang iimbak ang linya na gumagamit ang mga uri.
Dahil string ay isang pagkakasunud-sunod ng mga karakter,
maaari naming gusto upang mag-imbak ang mga ito sa isang array sa stack,
ngunit kailangan naming malaman kung gaano katagal array ay pagpunta sa kapag ipinapahayag namin ito.
Gayundin, kung gusto naming ilagay ang mga ito sa magbunton,
kailangan namin upang pumasa sa malloc ang bilang ng mga byte gusto naming reserve,
ngunit ito ay imposible.
Wala kaming ideya kung gaano karaming karakter ang user ay type sa
bago ang user na aktwal na ay ilagay ang mga ito.
>> Isang musmos na solusyon sa problemang ito ay upang lamang magreserba ng malaking tipak ng puwang, sabihin nating,
isang bloke ng 1000 karakter para sa input ng user,
ipagpalagay na ang gumagamit ay hindi kailanman ay type sa isang string na mahaba.
Ito ay isang masamang ideya para sa dalawang mga kadahilanan.
Una, ipagpalagay na ang mga gumagamit karaniwang hindi type sa mga string na mahaba,
maaari mong i-aaksaya ng maraming memorya.
Sa mga modernong machine, ito ay maaaring hindi isang isyu kung gagawin mo ito
sa isa o dalawang mga nakahiwalay na mga pangyayari,
ngunit kung ikaw ay pagkuha ng input ng user sa isang loop at pag-imbak para sa hinaharap na paggamit,
maaari mong mabilis sipsipin up ng isang tonelada ng memorya.
Bukod pa rito, kung ang programa ay sumusulat para sa isang mas maliit na computer na -
aparato tulad ng isang smartphone o ibang bagay na may limitadong memorya -
solusyong ito ay magdulot ng mga problema ng maraming mas mabilis.
Ang ikalawang, mas malubhang dahilan upang hindi gawin ito na umalis iyong programa mahina
sa kung ano ang tinatawag na isang buffer overflow atake.
Sa programming, ang buffer ng memorya na ginagamit upang pansamantalang mag-imbak ng data ng input o output,
na sa kasong ito ay aming 1000 magpasinda block.
Isang buffer overflow nangyayari kapag ang data ay nakasulat nakaraan dulo ng bloke.
>> Halimbawa, kung ang isang gumagamit ay aktwal na ginagawa uri sa higit sa 1000 na karakter.
Maaari mong naranasan ito aksidenteng kapag mga programa na may array.
Kung mayroon kang isang hanay ng mga 10 ints, walang hinto mula sa sinusubukang basahin o sumulat
ika-15 int.
Walang mga tagatala babala o error.
Ang programa blunders tuwid magpatuloy at access ang memorya
kung saan sa tingin nito ay ang ika-15 int, at maaari itong patungan ng iyong iba pang mga variable.
Sa pinakamasama kaso, maaari mong patungan ang ilan ng mga panloob na iyong programa
mekanismo ng kontrol, na nagiging sanhi ng iyong programa sa aktwal na isakatuparan ang iba't ibang mga tagubilin
kaysa sa nilayon mo.
>> Ngayon, ito ay hindi karaniwang gawin ito aksidenteng,
ngunit ito ay medyo karaniwang diskarte na ang mga masamang guys gamitin upang masira ang mga programa
at ilagay ang nakakahamak na code sa ibang mga tao computer.
Samakatuwid, hindi lamang namin maaaring gamitin ang aming musmos na solusyon.
Kailangan namin ng isang paraan upang maiwasan ang aming mga programa mula sa pagiging mahina
sa isang atake ng buffer overflow.
Upang gawin ito, kailangan namin upang matiyak na ang aming buffer palaguin bilang nabasa na namin
karagdagang input mula sa user.
Ang solusyon? Ginagamit namin ang isang magbunton inilalaan buffer.
Dahil maaari naming palitan ang laki nito gamit ang resize function na ang realloc,
at panatilihin namin track ng dalawang numero - index ng susunod na walang laman na slot sa buffer
at ang haba o kapasidad ng buffer.
Basahin namin sa mga karakter mula sa gumagamit ng isa sa bawat pagkakataon gamit ang fgetc function na.
Ang argument ang fgetc function na tumatagal - stdin - ay isang reference sa karaniwang input string,
na isang preconnected channel input na ginagamit upang ilipat ang input ng user
mula sa terminal sa programa.
>> Tuwing ang mga uri ng user sa isang bagong character, suriin namin upang makita kung ang index
ng susunod na libreng puwang ng plus 1 ay mas mataas kaysa sa kapasidad ng buffer.
Ang +1 ay dahil kung ang susunod na libreng index ay 5,
ang haba ng aming buffer ay dapat na 6 salamat sa 0 pag-i-index.
Kung kami maubusan ng espasyo sa buffer, pagkatapos ay tinatangka naming palitan ang laki nito,
pagdodoble ito kaya na namin cut sa dami ng beses na na naming baguhin ang laki
kung ang gumagamit ay nagta-type sa isang talagang mahabang string.
Kung ang string na nakuha ng masyadong mahaba o kung patakbuhin namin ng magbunton memory,
magbakante namin ang aming buffer at return null.
>> Panghuli, maglagay namin ang magpasinda sa buffer.
Sa sandaling ang mga hit user ay pumasok o bumalik, pagbibigay ng senyas ng isang bagong linya,
o espesyal na magpasinda - kontrol d - na signal ng isang dulo ng input,
ginagawa namin ng isang tseke upang makita kung ang user na aktwal na nai-type sa anumang bagay sa lahat.
Kung hindi, bumalik namin null.
Kung hindi man, dahil ang aming buffer ay malamang na mas malaki kaysa sa kailangan namin,
sa pinakamalala kaso halos dalawang beses bilang malaking bilang kailangan namin
dahil double namin ang bawat oras na baguhin ang laki namin,
gumawa kami ng isang bagong kopya ng string na gamit lamang ang halaga ng puwang na kailangan namin.
Idagdag namin ng dagdag na 1 sa tawag malloc,
kaya na may puwang para sa mga espesyal na character null Terminator - ang \ 0,
kung saan ikabit ang naming ang string sa sandaling kopyahin namin sa natitirang bahagi ng ang mga character na,
gamit strncpy sa halip na strcpy
upang maaari naming tukuyin eksakto kung gaano karaming karakter ang gusto naming kopyahin.
Strcpy kinokopya hanggang ito hit sa isang \ 0.
Pagkatapos namin magbakante aming buffer at ibalik ang kopya sa tumatawag.
>> Sino alam sa isang simpleng-tila function na ma-kumplikado?
Ngayon alam mo kung ano ang napupunta sa CS50 library.
>> Ang pangalan ko ay Nate Hardison, at ito ay CS50.
[CS50.TV]