[Powered by Google Translate] [PJESA 5: PAK rehatshme]
[Nate Hardison, Universiteti i Harvardit]
[Kjo është CS50.] [CS50.TV]
Pra, të mirëpritur mbrapa, djema.
Mirë se vini në nenin 5.
Në këtë pikë, ka përfunduar quiz 0 dhe duke parë se si ju keni bërë,
shpresojmë se ju ndiheni me të vërtetë e mirë, sepse unë kam qenë shumë i impresionuar nga rezultatet në këtë seksion.
Për shikuesit tanë online, ne kemi pasur disa pyetje
rreth dy problemet e fundit në grupin problemit - ose në quiz, në vend.
Pra, ne jemi duke shkuar për të shkuar mbi ata me të vërtetë shpejt në mënyrë që të gjithë e sheh se çfarë ka ndodhur
dhe si për të shkuar nëpërmjet zgjidhjes aktuale në vend se vetëm shikimin zgjidhje vetë.
Ne jemi duke shkuar për të shkuar mbi dy të fundit problemet e vërtetë shpejt, 32 dhe 33.
Vetëm, përsëri, në mënyrë që shikuesit online mund të shihni këtë.
>> Nëse ju të kthehet për problemin tuaj 32, e cila është në faqen 13,
13 nga 16, 32 Problemi është mbi të gjitha këmbime.
Kjo ishte e gjitha rreth shkëmbejnë dy integers.
Është problem që kishim shkuar mbi disa herë në leksion.
Dhe këtu, ajo që ne kemi qenë duke kërkuar që ju të bëni është një gjurmë të shpejtë kujtesës.
Për të plotësuar në vlerat e variablave si ata janë në rafte
si kodi kalon nëpër këtë funksion swap.
Në veçanti, ajo që ne jemi duke kërkuar në - Jam duke shkuar për të vënë këtë iPad poshtë -
në veçanti, atë që ne jemi duke kërkuar në është kjo linjë numëruar 6 të drejtë këtu.
Dhe kjo është numëruar 6 për vetëm vazhdimësia me problemin e mëparshëm.
Ajo që ne duam të bëjmë është shfaqur apo emërtim gjendjen e kujtesës
si ajo është në kohën kur ne të ekzekutuar këtë numër linjës 6,
e cila është në mënyrë efektive një kthim nga funksioni tonë swap drejtë këtu.
Nëse ne lëvizni poshtë këtu, pamë se adresat e çdo gjë në memorie është dhënë për ne.
Kjo është shumë e rëndësishme, ne do të kthehemi në të vetëm në një moment.
Dhe pastaj këtu poshtë në fund, kemi pasur një diagram pak memorie që ne jemi duke shkuar për t'iu referuar.
Unë kam bërë këtë në fakt jashtë në iPad tim.
Kështu që unë jam duke shkuar për alternative mbrapa me radhë dhe në mes të iPad dhe këtë kod vetëm për referencë.
>> Le të fillojë. Së pari, le të përqëndrohet në të parë disa linjave të kryesore të drejtë këtu.
Për të filluar, ne jemi duke shkuar për të nisja x dhe y në 1 me 2.
Pra, ne kemi dy variablave numër i plotë, ata të dy do të vendosen në rafte.
Ne jemi duke shkuar për të vënë një 1 dhe një 2 në to.
Pra, nëse unë rrokullisje mbi të iPad tim, me shpresë, le të shohim -
Apple mirroring TV, dhe aty ne do të shkojmë. Rregull.
Pra, nëse unë rrokullisje mbi të iPad tim,
Unë dua të nisja x dhe y në 1 me 2.
Ne e bëjmë se thjesht duke shkruar një 1 në kutinë e shënuar x
dhe një 2 në kutinë shënuar y. Mjaft e thjeshtë.
Pra, tani le të kthehemi në laptopë, shikoni se çfarë ndodh më pas.
Pra, kjo linjë tjetër është ajo ku gjërat ndërlikuar.
Ne kalojnë adresën e x dhe y adresën e si parametrat a dhe b në funksion swap.
Adresa e x dhe adresa e y janë gjëra që ne nuk mund të llogarisim
pa iu referuar këtyre plumb tregon drejtë këtu poshtë.
Dhe për fat të mirë, para dy pika plumb na tregoni saktësisht se çfarë janë përgjigjet.
Adresa e x në memorie është 10, dhe adresa e y në memorie është 14.
Pra, ato janë vlerat që të merrni kaluar si a dhe b të lartë deri në funksionin tonë swap.
Pra, përsëri, switching back to diagramin tonë, unë mund të shkruaj një 10 në një
dhe një 14 në b.
Tani, kjo pikë është vendi ku ne të vazhdojë me swap.
Pra Flipping përsëri në laptop përsëri,
ne shohim se mënyra swap punon është që unë dereference parë një dyqan dhe rezultati në tmp.
Pra, operatori dereference thotë: "Hey. Treat përmbajtjen e ndryshueshme si një një adresë.
Shko tek çdo gjë është ruajtur në atë adresë, dhe ngarkesës atë. "
Çfarë ju ngarkesës nga variabli do të ruhen në ndryshore tonë tmp.
Flipping përsëri në iPad.
Nëse ne do të shkojmë për të adresuar 10, ne e dimë se adresa është 10 x varible
sepse na u tha nga pikëpamja jonë plumb se adresa e x në memorie është 10.
Kështu që ne mund të shkojnë atje, të marrë vlerën e saj, e cila është 1, siç shohim në iPad tonë,
dhe ngarkesës që në tmp.
Përsëri, kjo nuk është përmbajtjen përfundimtare.
Ne jemi duke shkuar për të ecin nëpër dhe ne do të merrni për shtetin tonë final të programit në fund.
Por tani, ne kemi vlerën 1 depozituara në tmp.
>> Dhe ka një pyetje të shpejtë gjatë këtu.
[Aleksandër] është operatori dereference - që është vetëm e drejta yll në frontin e ndryshueshme?
Po >>. Pra, operatori dereference, si ne rrokullisje prapa në laptopë tonë edhe një herë,
është ky yll e drejtë përpara.
Në këtë kuptim, ai është - ju ballafaqojnë atë me operatorin shumëzimit
që kërkon dy gjëra; operatori dereference është një operator unary.
Aplikohet vetëm për një vlerë në krahasim me një operator binar,
ku ju aplikoni për dy vlera të ndryshme.
Pra, kjo është ajo që ndodh në këtë linjë.
Ne ngarkuar vlerën 1 dhe ruajtur atë në ndryshore integer përkohshëm tonë.
Linja tjetër, ne të ruajtur përmbajtjen e B në -
ose, përkundrazi, kemi të ruajtur përmbajtjen që është treguar në b në vendin ku është treguar për të.
Nëse analizojmë këtë nga e djathta në të majtë, ne jemi duke shkuar për të b dereference,
ne jemi duke shkuar për të adresuar 14, ne jemi duke shkuar për të rrëmbyer integer që është atje,
dhe pastaj ne do të shkojnë në adresën 10,
dhe ne do të hedhin rezultatin e dereference tonë të b në atë hapësirë.
Flipping përsëri në iPad tonë, ku ne mund të bëjë këtë një pak më konkret,
ajo mund të ndihmojë në qoftë se unë shkruaj numrat në të gjitha adresat këtu.
Kështu që ne e dimë se në y, ne jemi në adresën 14, x është në adresën 10.
Kur ne të fillojë në b, b dereference ne, ne jemi duke shkuar për të rrëmbyer vlerën 2.
Ne jemi duke shkuar për të rrëmbyer këtë vlerë, sepse kjo është vlera që jeton në adresën 14.
Dhe ne jemi duke shkuar për të vënë atë në ndryshore që jeton në adresën 10,
që është e drejtë atje, që korrespondon me x tona ndryshueshme.
Kështu që ne mund të bëjmë pak overwriting këtu
ku ne të shpëtoj prej 1 tonë dhe në vend të kësaj ne kemi shkruar një 2.
Kështu që të gjithë është mirë dhe të mirë në botë, edhe pse ne kemi x overwritten tani.
Ne kemi ruajtur vlerën e vjetër x në ndryshore tonë tmp.
Kështu që ne mund të përfunduar swap me linjë tjetër.
Flipping kthehet në laptopë tonë.
Tani të gjitha që mbetet është për të marrë përmbajtjen nga variable të përkohshëm tonë integer
dhe ruajtur ato në ndryshore që jeton në adresën që po mban b.
Kështu që ne jemi duke shkuar për të në mënyrë efektive b dereference për të marrë qasje në të ndryshueshme
që është në adresën që b mban në të,
dhe ne jemi duke shkuar për sende vlerën që tmp po mban në të.
Flipping përsëri në iPad herë më shumë.
Unë mund të fshihet këtë vlerë këtu, 2,
dhe në vend të ne do të kopje të drejtën 1 në të.
Pastaj linjë tjetër që ekzekuton, natyrisht -
në qoftë se ne rrokullisje prapa në laptopë - kjo është 6 pikë,
e cila është pika në të cilën ne kemi dashur që të kemi diagramin tonë plotësuar tërësisht.
Pra Flipping përsëri në iPad herë më shumë, vetëm kështu që ju mund të shihni diagramin e kompletuar,
ju mund të shihni se ne kemi një 10 në një, një 14 në B, një 1 në tmp, një 2 në x dhe y në një 1.
A ka ndonjë pyetje në lidhje me këtë?
A ka kjo të bëjë më shumë kuptim, duke ecur nëpër atë?
Kuptim pak? Shpresojmë se jo. Rregull.
>> Pointers janë një subjekt shumë i ndërlikuar.
Një nga djemtë e ne punojmë me ka një thënie shumë të përbashkët:
"Për të kuptuar pointers, ju duhet së pari të kuptojnë pointers."
Të cilat unë mendoj se është shumë e vërtetë. Ajo ka marrë një kohë për të marrë të përdoret për të.
Tërhequr shumë foto, shumë e tërhequr diagramet kujtesës si ky janë shumë të dobishme,
dhe pasi ju ecni nëpër shembull pas shembull pas shembull,
ajo do të fillojë të bëjë kuptim pak më shumë dhe ndjenjë pak më shumë dhe një ndjenjë pak më shumë.
Së fundi, një ditë, ju do të keni të gjitha zotëruar plotësisht.
Çdo pyetje para se të lëvizin për në problemin e ardhshëm? Dakord.
Pra, rrokullisje prapa në laptopë.
Problemi tjetër që kemi është problemi numër 33 në dosje I / O.
Zoom në për këtë pak pak.
Problemi 33 - Po?
>> [Daniel] Unë vetëm kishte një pyetje të shpejtë. Kjo yll, ose yll,
ajo që quhet dereferencing kur ju përdorni një yll më parë.
Çfarë është kjo quhet kur ju përdorni ampersand para?
>> Me simbol para është adresa e operatorit-.
Pra, le të shkoni back up.
Oops. Unë jam në mënyrë të zoom kështu që unë nuk mund të vërtetë rrotull.
Nëse ne shikojmë në këtë kod të vërtetë shpejt drejtë këtu,
përsëri, e njëjta gjë ndodh.
Nëse ne shikojmë në këtë kod të drejtë këtu, në këtë linjë, ku ne bëjmë thirrje të bie në ujdi,
the simbol është vetëm duke thënë se "të marrë adresën në të cilën jeton ndryshueshme x."
Kur compiler tuaj harton kodin tuaj,
ajo ka që në fakt fizikisht shënuar nga një vend në kujtesën për të gjithë variablat tuaja të jetojnë.
Dhe kështu çfarë përpiluesit pastaj mund të bëni një herë se është përpiluar gjithçka,
ai e di, "Oh, kam vënë në adresën x 10. kam vënë në adresën y 14".
Kjo pastaj mund të plotësoni në këto vlera për ju.
Kështu që ju mund pastaj - kjo pastaj mund të kalojë këtë në dhe të kalojë në & Y si.
Këta njerëz të marrë adresën, por ata gjithashtu, kur ju të kalojë ato në funksion swap,
ky informacion lloji, kjo * int drejtë këtu, tregon përpilues,
"Mirë, ne jemi duke shkuar për të interpretuar këtë adresë si një adresë e një ndryshore integer."
Si një adresë të një int, e cila është e ndryshme nga adresa e një variable karakter
sepse një int merr, në një makinë 32-bit, merr 4 bytes e hapësirës,
ndërsa një karakter të vetëm merr 1 bajt hapësirë.
Kështu që është e rëndësishme të dini edhe atë që është - çfarë jeton, çfarë lloji të vlerës
është duke jetuar në adresën që u miratua in
Ose adresën që ju jeni që kanë të bëjnë me të.
Në këtë mënyrë, ju e dini se sa bytes i informacionit të vërtetë ngarkesës nga RAM tuaj.
Dhe pastaj, po, ky operator dereference, si ju janë kërkuar,
shkon dhe accesses informacion në një adresë të veçantë.
Pra, ajo thotë se, me këtë variabël një këtu, trajtojnë përmbajtjen e një si një adresë,
shkojnë në atë adresë, dhe tërheq jashtë, ngarkesës në procesor, ngarkesës në një regjistër
vlerat aktuale apo përmbajtjet që jetojnë në atë adresë.
Më pyetje? Këto janë pyetje të mira.
Kjo është një shumë e terminologjisë së re shumë.
Është gjithashtu lloj i shokuar, duke parë dhe dhe * në vende të ndryshme.
>> Dakord.
Pra, përsëri për problemin e 33, të paraqesë I / O.
Kjo ishte një nga ato probleme që unë mendoj se disa gjëra të ndodhur.
Një, kjo është një temë mjaft e re.
Ajo u paraqit shumë shpejt para quiz,
dhe atëherë unë mendoj se kjo ishte një lloj si një nga ato problemet e fjalës në matematikë
ku ata të ju jap një shumë informacion, por ju në fakt nuk do të përfundojnë që të përdorni një ton të saj.
Pjesa e parë e këtij problemi është e përshkruar atë një file CSV është.
Tani, një CSV, sipas përshkrimit, është një presje-të ndara vlerat skedar.
Arsyeja këto janë aspak interesante, dhe arsyeja ndonjëherë ju përdorni ato,
po, sepse, si shumë prej jush e kanë përdorur ndonjëherë gjëra si Excel?
Figura shumica prej jush kanë, ndoshta, ose do të përdorë në një pikë në jetën tuaj.
Ju do të përdorni diçka si Excel.
Në mënyrë për të marrë të dhënat nga një Excel spreadsheet ose të bëjë çdo lloj të përpunimit me të,
në qoftë se ju të kërkuar për të shkruar një program C ose program Python, Java programin,
për t'u marrë me të dhënat që ju keni ruajtur në atje,
një nga mënyrat më të zakonshme për të marrë atë jashtë është në një skedar CSV.
Dhe ju mund të hapur deri Excel dhe kur ju shkoni në 'Ruaje Si' dialog,
ju mund të merrni nga një file CSV aktuale.
>> Dobishëm për të dini se si të merren me këto gjëra.
Mënyra se si punon është se ajo është e ngjashme me - Unë do të thotë, kjo është në thelb imituar një spreadsheet,
ku, si ne shohim këtu, në pjesë shumë të la-më,
ne kemi të gjitha emrat e fundit.
Pra, ne kemi Malan, atëherë Hardison, dhe pastaj Bowden, MacWilliam, dhe pastaj Chan.
Të gjithë emrat e fundit. Dhe pastaj një presje ndan emrat e fundit nga emrat e parë.
David, Nate, Rob, Tommy, dhe Zamyla.
Unë gjithmonë përzierje deri Robby dhe Tom.
Dhe pastaj, në fund, kolona e tretë është adresa e-mail.
Pasi ju e kuptoni se, pjesa tjetër e programit është mjaft i hapur për të zbatuar.
Ajo që ne kemi bërë në mënyrë që të imitoj këtë strukturë të njëjtë në C programin tonë
po ne kemi përdorur një strukturë.
Ne do të fillojnë të luajnë me këto pak më të mirë.
Ne pamë ata për pak pare pak në grup Problem 3, kur ne u që kanë të bëjnë me fjalorë.
Por kjo struct stafi ruan një mbiemër, një emër i parë, dhe një email.
Ashtu si CSV dosjen tonë është ruajtur.
Pra, kjo është vetëm konvertimin nga një formë në një tjetër.
Ne kemi për të kthyer, në këtë rast, një struct stafit në një linjë,
një presje-të ndara line, ashtu si kjo.
Bën që të bëjnë kuptim? Ju djema kanë marrë të gjitha quiz,
kështu që unë imagjinoni ju keni të paktën pasur disa kohë për të menduar për këtë.
>> Në funksion qira, problemi na kërkon të marrë në - zoom në në këtë we'll pak pak -
marrë në një strukturë stafit, një struct stafi, me emrin s,
append dhe përmbajtjen e saj të staff.csv dosjen tonë.
Ajo rezulton se kjo është mjaft e lehtë për t'u përdorur.
Ne do lloj të luajnë rreth me këto funksione sot pak më shumë.
Por në këtë rast, funksioni fprintf është me të vërtetë kyç.
Pra, me fprintf, ne mund të shtypura, ashtu si ju djema kanë qenë duke përdorur printf termin këtë tërë.
Ju mund printf një vijë në një skedar.
Pra, në vend të vetëm duke bërë thirrje zakonshme printf ku ju jepni atë string format
dhe pastaj ju zëvendësojë të gjitha ndryshoret me argumentet e mëposhtme,
me fprintf, argumenti juaj i parë është vend file qe doni te shkruani.
Nëse ne do të shikojmë në këtë në aplikim, për shembull, njeriu fprintf,
ne mund të shohim dallimin në mes printf dhe fprintf.
Unë do të zoom në këtu pak.
Pra, me printf, ne t'i jepte një varg format, dhe pastaj argumentet pasuese
janë të gjitha variablat për zëvendësimin ose zëvendësimit në vargun tonë format.
Ndërsa me fprintf, argumenti i parë është me të vërtetë këtë file i quajtur * një lumë.
>> Lëviz përsëri mbi këtu për qira tonë,
ne kemi marrë tashmë * ynë fotografi lumë hapur për ne.
Kjo është ajo që kjo linjë të parë e bën, ajo hap dosjen staff.csv,
ajo hapet append atë në mënyrë, dhe të gjithë që e la për ne të bëjmë është
shkruani strukturën e stafit në dosjen.
Dhe, le të shohim, nuk dua të përdorni iPad?
Unë do të përdorin iPad. Ne kemi zbrazëti - le të vënë këtë në tryezë në mënyrë që unë mund të shkruaj pak më të mirë -
pavlefshëm me qira dhe ajo merr në një argument, një strukturë të quajtur stafit s.
Mori formatimin e teksteve tona, ne kemi marrë * fotografisë tonë quajtur file,
ne kemi linjë tonë fopen dhënë për ne,
dhe unë do të shkruani vetëm atë si pika pasi ajo është tashmë në pedia.
Dhe pastaj në linjë tonë të ardhshëm, ne jemi duke shkuar për të bërë një telefonatë të fprintf
dhe ne jemi duke shkuar për të kaluar në dosjen që ne duam të shkruar për të,
dhe pastaj string format tona, të cilat -
Unë do të le ju djema thoni se çfarë ajo duket si.
Si në lidhje me ju, Stella? A e dini se çfarë Pjesa e parë e vargut format duket si?
[Stella] Unë nuk jam i sigurt. >> Mos ngurroni të pyesni Jimmy.
A e dini, Jimmy?
[Jimmy] A do të jetë vetëm i fundit? Nuk e di. Unë nuk jam plotësisht i sigurt.
Mirë >>. Si rreth, bëri dikush të marrë kjo e saktë në provim?
Nr. rregull.
Ajo rezulton se këtu të gjithë ne duhet të bëni është të duam çdo pjesë e strukturës sonë stafit
të jenë të shtypura si një varg në dosjen tonë.
Ne vetëm përdorin zëvendësimin varg karakter tre herë të ndryshme, sepse ne kemi një emër fundit
ndjekur nga presje, atëherë emri i ndjekur nga një presje,
dhe pastaj në fund adresë e-mail e cila është ndjekur - e cila nuk është
përshtatshëm në ekran e mia - por kjo është pasuar nga një karakter newline.
Kështu që unë jam duke shkuar për të shkruar atë vetëm atje poshtë.
Dhe pastaj pas vargun tonë format,
ne vetëm kemi zëvendësime, të cilat ne qasje duke përdorur simbol dot
që pamë në grup Problem 3.
Ne mund të përdorim s.last, s.first dhe s.email
të zëvendësojë në ato tri vlerat në vargun tonë format.
Pra, si bëri që të shkojnë? Kuptim?
Po? Jo? Ndoshta? Rregull.
>> Gjëja e fundit që ne të bëjmë pasi të kemi të shtypura dhe pas ne kemi hapur dosjen tonë:
sa herë që ne kemi hapur një skedar, ne gjithmonë duhet të mbani mend për të mbyllur atë.
Sepse përndryshe ne do të përfundojë deri në rrjedhjen e kujtesës,
përdorur deri përshkrime file.
Pra, për ta mbyllur atë, e cila funksion nuk kemi përdorim? Daniel?
[Daniel] Shkrimi? Shkrimi >>, pikërisht.
Pra, pjesa e fundit e këtij problemi ishte që të duhet mbyllur dosjen, duke përdorur funksionin Shkrimi,
që vetëm duket si kjo.
Jo shumë të çmendur.
Cool.
Pra, kjo është problem i 33 në quiz.
Ne do të kemi patjetër fotografinë më I / O vjen deri.
Ne do të bëjmë një pak më shumë në leksionin sot, ose në seksionin sot,
sepse kjo është ajo që do të formojnë pjesën më të madhe të këtij pset ardhshme.
Le të lëvizin nga quiz në këtë pikë. Po?
>> [Charlotte]] Pse Shkrimi (file) në vend të Shkrimi (staff.csv)?
Ah >>. Sepse ajo rezulton nga se - kështu pyetja, e cila është një një i madh,
është arsyeja pse, kur kemi shkruar Shkrimi, po ne shkrim Shkrimi ndryshore (file) yll
në krahasim me emrin e file, staff.csv? Është e saktë? Po.
Pra, le të marrin një sy. Nëse unë kaloni përsëri në laptop tim,
dhe le të shohim në funksion Shkrimi.
Pra, funksioni Shkrimi mbyllet një lumë dhe ajo merr në treguesin në lumë që ne duam të mbyllur,
në krahasim me emrin aktual e file që ne duam të mbyllur.
Dhe kjo është për shkak se prapa skenave, kur ju bëni një telefonatë për fopen,
kur ju të hapur një skedar, ju jeni në të vërtetë alokimin e kujtesës për të ruajtur informacion në lidhje me dosjen.
Pra, ju keni treguesin file që ka informacion në lidhje me dosjen,
të tilla si ajo e hapur, madhësia e saj, ku ju jeni aktualisht në dosjen,
kështu që ju mund të bëni thirrje lexim dhe shkrim në atë vend të caktuar brenda file.
Ju deri në fund mbylljen treguesin në vend të mbylljes emrin e file.
>> Po? [Daniel] Pra, në mënyrë që të përdorin me qira, do të thonë - si e bën atë të marrë të dhëna përdorues?
A fprintf veprojnë si getString në kuptimin se ajo vetëm do të presin për të dhëna përdoruesi
dhe kërkoj nga ju që të shtypni këtë - apo të presë për ju për të tipit këto tri gjëra në?
Apo nuk keni nevojë të përdorni diçka për të zbatuar me qira?
Po >>. Pra, ne nuk jemi - pyetja është, si nuk kemi marrë të dhëna përdoruesi
në mënyrë që të zbatojnë me qira? Dhe ajo që ne kemi këtu është thirrësi i qira,
kaluar në këtë struct stafit me të gjitha të dhënave të ruajtura në struct tashmë.
Pra fprintf është në gjendje të shkruani vetëm që të dhënat direkt në dosje.
Nuk ka pritur për input të përdoruesit.
Ky përdorues është dhënë tashmë e kontributit duhet duke e vënë atë në këtë struct stafit.
Dhe gjëra, natyrisht, do të prishej në qoftë se ndonjë nga këto pointers ishin null,
kështu që lëviz mbrapa deri këtu dhe ne të shikojmë në struct tonë.
Ne kemi kaluar, string string pari, email string.
Ne tani e dimë se të gjithë ata me të vërtetë, nën kapuç, janë variabla char *.
Kjo mund ose nuk mund të jetë duke treguar null.
Ato mund të vënë në kujtesën mbi tok,
ndoshta kujtesës në rafte.
Ne të vërtetë nuk e di, por nëse ndonjë nga këto pointers janë null, ose të pavlefshme,
se ai patjetër do të rrëzimit funksionin tonë me qira.
Kjo ishte diçka që ishte lloj përtej fushës së provimit.
Ne nuk jemi të brengosur për këtë.
Madhe. Rregull. Pra, duke lëvizur më nga quiz.
>> Le të mbyllur këtë djalë, dhe ne do të shikojmë në pset 4.
Pra, nëse ju djema shikoni në spekulim pset, një herë ju mund të hyni në atë, cs50.net/quizzes,
ne jemi duke shkuar për të shkuar nëpër disa nga problemet seksionin sot.
Unë jam scrolling poshtë - seksioni i pyetjeve fillon në faqen e tretë të spec pset.
Dhe pjesa e parë ju pyet për të shkuar dhe të shikojnë të shkurtër në Përcjellin dhe tubave.
Cili ishte lloj i një të shkurtër cool, ju tregon disa të reja, truket ftohtë command line që ju mund të përdorni.
Dhe pastaj ne kemi marrë disa pyetje për ju si.
Kjo pyetje e parë në lidhje me lumenj, në të cilën shkruan printf by default,
ne lloj i preku vetëm pak një moment më parë.
Kjo fprintf se ne ishim vetëm duke diskutuar merr në një lumë * skedar si argument të saj.
Shkrimi merr në një lumë * skedar, si edhe,
dhe vlera kthimi i fopen ju jep një rrjedhë * skedar si.
Arsyeja që ne nuk e kemi parë ata që ishin para, kur ne kemi marrë me printf
është për shkak se ka një lumë printf default.
Dhe lumë parazgjedhur në të cilën ajo shkruan
ju do të gjeni lidhje në afat të shkurtër.
Pra, patjetër të marrë një vështrim në të.
>> Në seksionin e sotme, ne do të flasim pak në lidhje me GDB,
pasi që ju jeni më të njohur me të, praktika që ju të merrni më shumë me të,
më të mirë ju do të jetë në gjendje që në fakt të ndjekë bugs në kodin tuaj.
Kjo përshpejton procesin e debugging deri jashtëzakonshme.
Pra, duke përdorur printf, çdo herë që bëni që ju keni për të përpiluar kodin tuaj,
ju keni për të drejtuar atë përsëri, ndonjëherë ju duhet të lëvizin thirrjen printf rreth,
komentuar nga kodi, ajo merr vetëm një kohë.
Qëllimi ynë është që të përpiqen dhe të ju bindin se me GDB, ju mund të thelb
asgjë printf në çdo moment në kodin tuaj dhe ju kurrë nuk keni për të përpiluar atë.
Ju kurrë nuk duhet të fillojë dhe për të mbajtur guessing ku të printf ardhshëm.
Gjëja e parë që bëni është të kopjoni këtë linjë dhe për të marrë kodin seksion off e internetit.
Unë jam kopjimi këtë linjë të kodit që thotë se, "http://cdn.cs50.net wget".
Unë jam duke shkuar për të kopje atë.
Unë jam duke shkuar për të shkuar mbi të aparatit tim, zoom jashtë në mënyrë që ju mund të shihni atë që unë jam duke bërë,
pasting atë në atje, dhe kur unë hit Enter, kjo komandë wget fjalë për fjalë është një web të merrni.
Ajo do të tërheqë poshtë këtë fotografi off e internetit,
dhe ajo do të shpëtojë atë në dosjen aktuale.
Tani, nëse unë lista dosjen time aktuale që ju mund të shihni se unë kam marrë këtë skedar section5.zip drejtë në atje.
Mënyra për t'u marrë me atë djalë është që të hap zinxhirin atë,
të cilat ju mund të bëni në command line, ashtu si kjo.
Section5.zip.
Kjo do të unzip atë, të krijojnë dosje për mua,
fryj të gjithë përmbajtjen, ata vënë në atje.
Deri tani unë mund të shkoj në directory 5 seksionin tim duke përdorur komandën cd.
Qartë në ekran duke përdorur të qartë. Pra, qartë në ekran.
Tani unë kam marrë një terminal të mirë të pastër për t'u marrë me të.
>> Tani, nëse unë të listojnë të gjitha dosjet që unë shoh në këtë directory,
ju shihni se unë kam marrë katër fotografi: buggy1, buggy2, buggy3 dhe buggy4.
Unë kam marrë edhe dosjet përkatëse. E tyre c.
Ne nuk do të shohim në fotografi. C për tani.
Në vend të kësaj, ne jemi duke shkuar për t'i përdorur ato, kur ne e hapur deri GDB.
Ne kemi mbajtur rreth tyre në mënyrë që të kemi qasje në kodin burimor aktuale, kur ne jemi duke përdorur GDB,
por qëllimi i kësaj pjese të këtij neni është që të kallajis rreth me GDB
dhe të shohim se si ne mund ta përdorin atë për të kuptoj se çfarë po ndodh gabuar me secilin nga këto katër programe buggy.
Pra, ne jemi vetëm duke shkuar për të nëpër dhomë me të vërtetë shpejt,
dhe unë jam duke shkuar për të pyetur dikë për të drejtuar një nga programet Buggy,
dhe pastaj ne do të shkojnë si një grup përmes GDB, dhe ne do të shohim se çfarë mund të bëjmë për të rregulluar këto programe,
ose të paktën të identifikuar se çfarë po ndodh gabuar në secilën prej tyre.
Le të fillojë gjatë këtu me Danielin. Do të ju drejtuar buggy1? Le të shohim se çfarë ndodh.
[Daniel] Ajo thotë se ka një kërkesë faji. Po >>. Saktësisht.
Pra, nëse kam drejtuar buggy1, unë të marrë një gabim seg.
Në këtë pikë, unë mund të shkoni dhe e hapur deri buggy1.c,
përpiqen dhe të kuptoj se çfarë po ndodh gabuar,
por një nga gjërat më të urryer në lidhje me këtë gabim faji Seg
është se ajo nuk do të ju them se çfarë linjë të gjërave të programit në fakt shkoi keq dhe thyen.
Ju lloj duhet të shikoni në kodin
dhe të kuptoj se duke përdorur mend dhe kontrolloni ose printf për të parë se çfarë po ndodh gabuar.
Një nga gjërat coolest rreth gdb është se ajo është e vërtetë, të vërtetë e lehtë
të gjej linjën në të cilën crashes programin tuaj.
Është krejtësisht e vlefshme për të përdorin atë, edhe në qoftë vetëm për atë.
Pra, për të boot up GDB, unë lloji GDB, dhe atëherë unë jap atë në rrugën të ekzekutueshme që unë dua për të kandiduar.
Këtu unë jam i shtypur gdb ./buggy1.
Hit Enter. Më jep gjithë këtë informacion autorit,
dhe këtu poshtë ju do të shihni këtë linjë që thotë se, "leximi nga simbolet / home /
jharvard/section5/buggy1. "
Dhe në qoftë se të gjitha shkon mirë, ju do të shihni se të shtypura nga një mesazh që duket si kjo.
Ajo do të lexoni simbole, ajo do të thonë: "Unë jam i lexuar nga simbolet dosjen tuaj ekzekutues"
dhe pastaj ajo do të ketë këtë "bërë" mesazh mbi këtu.
Nëse ju shikoni ndonjë variant tjetër të kësaj, apo e shihni se nuk mund të gjejnë simbole
ose diçka të tillë, çka do të thotë është se ju thjesht nuk kanë përpiluar ekzekutueshme tuaj siç duhet.
Kur ne hartojnë programe për përdorimin me GDB, ne duhet të përdorin atë flamur të veçantë-g,
dhe që është bërë nga default në qoftë se ju hartojnë programet tuaja, vetëm duke shtypur bëjë
ose të bëjë buggy ose të bëjë të shërohen, ndonjë nga ata.
Por në qoftë se ju jeni hartimin dorë me tingëllimë, atëherë ju do të keni për të shkuar në dhe të përfshijë se-g flamurin.
>> Në këtë pikë, tani që ne kemi vëmendjen tonë të shpejtë GDB,
kjo është shumë e thjeshtë për të drejtuar programin.
Ne ose mund të shtypni të kandidojë, ose ne mund vetëm të shtypni r.
Komandat Shumica Gdb mund të jenë shkurtuar.
Zakonisht në vetëm një ose letra çift, e cila është shumë e bukur.
Saad Pra, nëse ju shkruani r dhe hit Enter, çfarë ndodh?
[Saad] kam marrë SIGSEGV, faji segmentimit, dhe atëherë e gjithë kjo kuptueshme.
Po >>.
Si ne po shohim në ekran të drejtë tani, dhe si Saad tha:
kur të shtypni të kandidojë apo R dhe hit Enter, ne ende të marrë fajin njëjtin seg.
Pra, duke përdorur gdb nuk e zgjidh problemin tonë.
Por kjo na jep disa gobbledygook, dhe kjo rezulton se ky gobbledygook
në fakt na tregon se ku ajo ndodh.
Për këtë analizimi pak, kjo pak i parë është funksion në të cilën gjithçka do të gabuar.
Nuk është kjo __ strcmp_sse4_2, dhe kjo na tregon se ajo që po ndodh në këtë dosje
quajtur sysdeps/i386, e gjithë kjo, përsëri, lloj i një rrëmujë - por linjës 254.
Kjo është lloj i vështirë për të kuptoj. Zakonisht kur ju shikoni gjëra si kjo,
që do të thotë se ajo e seg përgënjeshtrojnë në njërën nga biblioteka e sistemit.
Pra, diçka të bëjë me strcmp. Ju djema keni parë strcmp parë.
Jo shumë i çmendur, por kjo do të thotë se strcmp është e thyer ose se ka një problem me strcmp?
Çfarë mendoni ju, Aleksandrin?
[Aleksandër] A është kjo - është 254 linja? Dhe - jo binar, por kjo nuk është tavanet e tyre,
dhe pastaj ka një tjetër gjuhë për secilin funksion. Është se në atë funksion 254, ose -?
Kjo është linja >> 254. Ajo duket si në këtë dosje. S, kështu që është ndoshta kodin kuvendi.
>> Por, unë mendoj se gjëja më e ngutshme është, sepse ne kemi marrë një faj Seg,
dhe kjo duket si ajo vjen nga funksioni strcmp,
nënkupton kjo, atëherë, që strcmp është thyer?
Ajo nuk duhet, me shpresë. Pra, vetëm për shkak se ju keni një faj segmentimit
në një nga funksionet e sistemit, në mënyrë tipike që do të thotë se ju thjesht nuk e kanë quajtur atë të saktë.
Gjëja më e shpejtë për të bërë të kuptoj se çfarë po ndodh në të vërtetë
kur ju shikoni diçka çmendur si kjo, sa herë që ju të shihni një faj Seg,
veçanërisht në qoftë se ju keni një program që është përdorur më shumë se vetëm kryesor,
është që të përdorin një backtrace.
I shkurtoj backtrace duke shkruar BT, në krahasim me fjalën e plotë backtrace.
Por Charlotte, çfarë ndodh kur ju shkruani BT dhe hit Enter?
[Charlotte] Ajo tregon mua dy linja, 0 line dhe alineja 1.
Po >>. Pra linjë 0 dhe alineja 1.
Këto janë korniza aktuale rafte që ishin aktualisht në lojë kur programi juaj u rrëzua.
Duke filluar nga sistemi i larti, kornizë 0, dhe do të fund-më, e cila është kornizë 1.
Kornizë ynë i larti është kornizë strcmp.
Ju mund të mendoj për këtë si të ngjashme me këtë problem, ne ishim vetëm duke bërë në quiz me pointers,
ku ne kishim shkëmbim kornizë rafte në krye të rafte kornizë kryesore,
dhe kemi pasur variablave që swap u përdorur në krye të variablave që kryesore ishte përdorur.
Këtu përplasje ynë ka ndodhur në funksion tonë strcmp, e cila u quajt nga funksioni ynë kryesor,
backtrace dhe po na jep jo vetëm funksionet në të cilat gjërat dështuar,
Por është gjithashtu e duke na thënë se ku çdo gjë u quajt nga.
Pra, nëse unë lëviz mbi një pak më shumë në të djathtë,
ne mund të shohim se vërtet, ne kemi qenë në linjën 254 të këtij file strcmp-sse4.s.
Por thirrja u bë në linjë buggy1.c, 6.
Kështu që do të thotë që ne mund të bëjmë - është që ne mund të shkoni vetëm të shikoni dhe të shohim se çfarë po ndodh
në linjë buggy1.c, 6.
Përsëri, ka disa mënyra për ta bërë këtë. Njëra është për të dalë nga GDB
ose të ketë kodin tuaj të hapet në një dritare dhe referencë kryq.
Kjo, në vetvete, është shumë i dobishëm, sepse tani, nëse ju jeni në orarit të punës
dhe ju keni marrë një defekt seg dhe TF juaj e pyesin se ku çdo gjë ishte e thyer,
vetëm ju mund të thoni, "Oh, Shkarko 6. Unë nuk e di se çfarë po ndodh,
por diçka rreth 6 linjë është duke shkaktuar programin tim për të thyer ".
Mënyra të tjera për të bërë atë që është që ju mund të përdorni këtë komandë quajtur lista në GDB.
Ju gjithashtu mund të shkurtoj atë me l.
Pra, nëse ne e goditi l, çfarë nuk kemi marrë këtu?
Ne kemi marrë një bandë e tërë e gjëra të çuditshme.
Ky është kodi aktual kuvendi
që është në strcmp_sse4_2.
Kjo duket lloj të shokuar,
dhe arsyeja që ne jemi duke marrë kjo është për shkak se tani,
Gdb ka na në kuadër 0.
>> Pra, në çdo kohë ne shikojmë në variablave, në çdo kohë ne shikojmë në kodin burim,
ne jemi duke kërkuar në kodin burimor që ka të bëjë me kuadrin rafte ne jemi aktualisht in
Pra, në mënyrë që të merrni asgjë kuptimplotë, ne duhet të
të shkojë në një kornizë pirg që e bën më shumë kuptim.
Në këtë rast, korniza kryesore rafte do të kishte kuptim pak më shumë,
sepse kjo ishte në fakt kodin që kemi shkruar.
Jo kodin strcmp.
Mënyra se si ju mund të lëvizin në mes të kornizave, në këtë rast, sepse ne kemi dy,
ne kemi 0 dhe 1,
ju bëni që me lart dhe komandat poshtë.
Nëse unë shkojë deri një kornizë,
tani unë jam në kuadër rafte kryesore.
Unë mund të lëvizin poshtë për të shkuar mbrapa ku isha,
shkoni përsëri, të shkojnë poshtë përsëri, dhe të shkojnë përsëri.
Nëse ju ndonjëherë të bëni programin tuaj në GDB, ju merrni një aksident, ju merrni backtrace,
dhe ju të shihni se ajo është në një farë skedar që ju nuk e dini se çfarë po ndodh.
Ju provoni listë, kodi nuk duket të njohura për ju,
hidhini një sy në korniza tuaj dhe të kuptoj se ku jeni.
Ju ndoshta jeni në kuadër të gabuar rafte.
Ose të paktën ju jeni në një kornizë pirg që nuk është një që ju mund të vërtetë të korrigjoj.
Tani që ne jemi në kuadër rafte e duhur, ne jemi në kryesore,
tani ne mund të përdorni komandën listë të kuptoj se çfarë linjë ishte.
Dhe ju mund të shihni atë, por të shtypura atë për ne të drejtë këtu.
Por ne mund të goditur lista të gjithë të njëjtë, dhe lista na jep këtë kopje bukur
i kodit aktual burim që po ndodh në këtu.
>> Në veçanti, ne mund të shohim në linjë 6.
Ne mund të shohim se çfarë po ndodh këtu.
Dhe kjo duket si ne jemi duke bërë një krahasim string
mes vargut "CS50 shkëmbinj" dhe argv [1].
Diçka në lidhje me këtë u crashing.
Pra Missy, a keni ndonjë mendime mbi atë që mund të ndodh këtu?
[Missy] Unë nuk e di pse kjo është crashing. Ju >> nuk e di pse është e crashing?
Jimmy, çdo mendime?
[Jimmy] Unë nuk jam plotësisht i sigurt, por hera e fundit që kemi përdorur string krahasuar,
ose strcmp, kemi pasur si tre raste të ndryshme në bazë të saj.
Ne nuk kemi një ==, unë nuk mendoj se, e drejta në këtë linjë të parë.
Në vend të kësaj ajo ishte e ndarë në tri, dhe një ishte == 0,
njëri ishte <0, unë mendoj, dhe një ishte> 0.
Pra, ndoshta diçka si kjo? Po >>. Pra, nuk është kjo çështje
e po bëjmë krahasimin saktë?
Stella? Çdo mendime?
[Stella] Unë nuk jam i sigurt. Nuk jam i sigurt >>. Daniel? Mendime? Rregull.
Ajo rezulton se çfarë po ndodh këtu është kur ne u programin
dhe kemi marrë fajin Seg, kur ju drejtoi programin për herë të parë, Danieli,
keni jepte argumente command line?
[Daniel] nr nr >> Në këtë rast, ajo që është vlera e argv [1]?
>> Nuk ka asnjë vlerë. E drejta >>.
E pra, nuk ka asnjë vlerë string përshtatshme.
Por ka disa vlera. Cila është vlera që merr ruajtur në atje?
Një vlerë >> plehrash? >> Kjo është ose një vlerë plehrash ose, në këtë rast,
fundi i array argv përfundon gjithmonë me null.
Pra, çfarë në të vërtetë u ruajtur në atje është i pavlefshëm.
Mënyra të tjera për të zgjidhur këtë, në vend se duke menduar atë nëpërmjet,
është që të përpiqen shtypjen atë.
Kjo është ajo ku unë isha duke thënë se duke përdorur gdb është e madhe,
sepse ju mund të shtypura nga të gjitha variablave, të gjitha vlerat që ju dëshironi
duke përdorur këtë komandë dobishëm-Pispilluq p.
Pra, nëse unë lloji p dhe pastaj shtypni vlerën e një ndryshore ose emrin e një variable,
thonë, argc, unë shoh se argc është 1.
Në qoftë se unë dua të shtypura nga argv [0], unë mund ta bëjë këtë vetëm si kjo.
Dhe ashtu siç e pamë, argv [0] gjithmonë është emri i programit tuaj,
gjithmonë emri i ekzekutues.
Këtu ju shihni se e mori emrin e plotë rrugën.
Unë gjithashtu mund të shtypura nga argv [1] dhe shikoni se çfarë ndodh.
>> Këtu kemi marrë këtë lloj të vlerës së mistike.
Ne morëm këtë 0x0.
Kujtohet në fillim të mandatit, kur kemi biseduar në lidhje me numrat heksadecimal?
Apo se pyetja pak në fund të pset 0 rreth asaj se si për të përfaqësuar 50 në magji?
Mënyra kemi shkruar numrat magji në CS, vetëm për të mos ngatërruar veten
me numra dhjetore, është ne gjithmonë prefix ato me 0x.
Pra, kjo prefix 0x gjithmonë vetëm do të thotë të interpretuar numrin e mëposhtëm si një numër heksadecimal,
jo si një varg, jo si një numër decimal, jo si një numër binar.
Që nga numri 5-0 është një numër i vlefshëm në heksadecimal.
Dhe kjo është një numër në decimal, 50.
Pra, kjo është vetëm se si ne disambiguate.
Pra, 0x0 Mjetet 0 heksadecimal, e cila është gjithashtu decimal 0 binare, 0.
Është vetëm vlera 0.
Ajo rezulton se kjo është ajo që është null, në të vërtetë, në kujtesë.
Null është vetëm 0.
Këtu, elementi ruajtur në argv [1] është i pavlefshëm.
Pra, ne jemi duke u përpjekur për të krahasuar tonë "CS50 Rocks" string për një varg null.
Pra dereferencing null, duke u përpjekur për të hyrë në gjërat null,
ata janë zakonisht do të shkaktojë ndonjë lloj faji segmentimit ose gjëra të tjera të këqija të ndodhë.
Dhe kjo rezulton se strcmp nuk kontrolloni për të parë
ose nëse nuk e keni kaluar në një vlerë që është null.
Përkundrazi, ajo shkon vetëm përpara, përpiqet të bëjë gjë e saj,
dhe në qoftë se ajo seg gabimet, ajo seg gabimet, dhe kjo është problemi juaj. Ju duhet të shkoni të rregulluar atë.
Me të vërtetë shpejt, si mund ne të rregullojmë këtë problem? Charlotte?
[Charlotte] Ju mund të shikoni në qoftë se duke përdorur.
Pra, nëse argv [1] është i pavlefshëm, == 0, pastaj do të ktheheni 1, ose diçka [pakuptueshëm].
Po >>. Pra, kjo është një mënyrë e madhe për të bërë atë, si ne mund të kontrolloni për të parë,
vlera ne jemi gati për të kaluar në strcmp, argv [1], është ajo null?
Nëse kjo është null, atëherë ne mund të themi rregull, ndërpritet.
>> Një mënyrë më e zakonshme për të bërë këtë është që të përdorin vlera argc.
Ju mund të shihni të drejtë këtu në fillim të kryesore,
ne hequr atë testin e parë që ne bëjmë zakonisht kur ne përdorim argumente command line,
e cila është për të provuar nëse është apo jo vlera jonë argc është ajo që ne presim.
Në këtë rast, ne jemi duke pritur të paktën dy argumente,
emri i programit plus një tjetër.
Sepse ne jemi gati për të përdorur argumentin e dytë të drejtë këtu.
Pra, ka një lloj testi paraprakisht, para se të thirrjes sonë strcmp
se testet nëse janë apo jo argv është të paktën 2, do të bëjë të njëjtin lloj gjë.
Ne mund të shohim nëse që punon me drejtimin e programit përsëri.
Ju gjithmonë mund të rinisni programin tuaj brenda GDB, e cila është me të vërtetë bukur.
Ju mund të kandidojë, dhe kur ju të kalojë në argumentet për programin tuaj,
ju të kalojë ato në kur ju drejtuar thirrje, jo kur ju boot up GDB.
Në këtë mënyrë ju mund të mbani duke u thirrur në programin tuaj me argumente të ndryshme çdo herë.
Pra drejtuar, ose përsëri, unë mund të shtypni r, dhe le të shohim se çfarë ndodh në qoftë se ne e tipit "hello".
Ajo gjithmonë do të ju pyes nëse ju doni të filloni atë nga fillimi përsëri.
Zakonisht, ju do të duan të fillojnë atë nga fillimi përsëri.
Dhe në këtë pikë, ajo rifillon përsëri, ajo printon nga
programi që ne jemi drejtimin, buggy1, me argumentin hello,
dhe printime this out standarde, ajo thotë, "Ju merrni një D," fytyra trishtuar.
Por ne nuk seg faj. Ai tha se procesi i exited normalisht.
Kështu që duket goxha e mirë.
Nuk ka faj më të seg, kemi bërë atë të kaluarën,
kështu që duket si ajo ishte me të vërtetë bug seg faji se ne kemi qenë duke marrë.
Për fat të keq, kjo na tregon se ne jemi duke marrë një D.
>> Ne mund të shkojnë prapa dhe të shikojmë në kodin dhe të shohim se çfarë po ndodh atje
të kuptoj se çfarë ishte - pse u duke na thënë se ne kemi marrë një D.
Le të shohim, këtu është kjo printf thënë se ju mori një D.
Nëse ne shkruani listë, si ju mbani shtypur listë, ajo mban iterating poshtë nëpër programin tuaj,
kështu ajo do t'ju tregojë linjat e para të programit tuaj.
Atëherë ajo do t'ju tregojë linjat e ardhshme, dhe copë tjetër dhe copë tjetër.
Dhe ajo do të vazhdojë të përpiqet për të shkuar poshtë.
Dhe tani ne do të merrni për të "vijë numri 16 është jashtë rrezes."
Për shkak se ajo ka vetëm 15 rreshta.
Nëse ju merrni në këtë pikë dhe tuaj pyesin, "Çfarë të bëj?" ju mund të përdorni komandën ndihmë.
Përdorni ndihmë dhe pastaj jepni emrin e një komandë.
Dhe ju shihni Gdb na jep të gjitha llojet e stuff këtë.
Ajo thotë se, "Me asnjë argument, listat dhjetë rreshta më pas ose rreth liste mëparshëm.
Lista - liston dhjetë linjat e para - "
Pra, le të provoni duke përdorur minus listë.
Dhe se listat e 10 linjat e mëparshme, ju mund të luajnë rreth me listën pak.
Ju mund të bëni listën, listë -, ju mund të jap edhe lista një numër, si lista e 8,
dhe ajo do të rendisin 10 rreshta rreth linjës 8.
Dhe ju mund të shihni se çfarë po ndodh këtu është që ju keni marrë një të thjeshtë, nëse tjetër.
Nëse ju shkruani në shkëmbinj CS50, ajo kopje nga "Ju merrni një A."
Përndryshe ajo printon nga "Ju merrni një D."
Qyteti zhgënjim. Dakord. Po?
>> [Daniel] Pra, kur unë u përpoq duke bërë CS50 shkëmbinj pa thonjëza,
ai thotë se "Ju merrni një D."
I nevojshëm kuotat për të marrë atë për të punuar, pse është kjo?
Po >>. Ajo rezulton se kur - kjo është një tjetër gjë e mirë pak fun -
kur ju të drejtuar programin, në qoftë se ne e drejtuar atë dhe ne shkruani në CS50 shkëmbinj,
ashtu si Danieli u thënë se ai e bëri, dhe ju goditi Enter,
ajo ende thotë se ne kemi marrë një D.
Dhe pyetja është, pse është kjo?
Dhe kjo rezulton se edhe terminali ynë dhe Gdb kuptoj këto si dy argumente të veçanta.
Sepse kur ka një hapësirë, që është nënkuptuar si
Argumenti i parë përfundoi, argumenti tjetër është gati të fillojë.
Mënyra për të kombinuar ato në dy, ose keq, në një argument,
është që të përdorin kuotat.
Deri tani, në qoftë se ne kemi vënë atë në thonjëza dhe drejtuar atë përsëri, ne të merrni një A.
Pra, vetëm për radhitje, pa thonjëza, CS50 dhe shkëmbinj janë parsed si dy argumente të veçanta.
Me citate, kjo është parsed si një argument krejt.
>> Ne mund të shohim këtë me një breakpoint.
Deri tani ne kemi qenë në drejtimin e programit tonë, dhe kjo është running
deri ose ajo seg meta apo godet një gabim
ose deri sa ajo ka dalë dhe të gjithë ka qenë krejtësisht gjobë.
Kjo nuk është domosdoshmërisht gjëja më e dobishme, sepse ndonjëherë
ju keni një gabim në programin tuaj, por kjo nuk është shkaktuar një defekt segmentimit.
Kjo nuk është shkaktuar programin tuaj për të ndaluar ose diçka të tillë.
Mënyra për të marrë gdb për pushim programin tuaj në një pikë të veçantë
është për të vendosur një breakpoint.
Ju mund ta bëni këtë duke vendosur një breakpoint në një emër funksion
ose ju mund të vendosni një breakpoint në një linjë të veçantë të kodit.
Më pëlqen për të vendosur breakpoints në emrat funksion, sepse - e lehtë për të kujtuar,
dhe në qoftë se ju në të vërtetë të shkoni në dhe për të ndryshuar kodin tuaj burim deri pak,
atëherë breakpoint tuaj të vërtetë do të qëndrojnë në të njëjtin vend brenda kodin tuaj.
Ndërsa në qoftë se ju jeni duke përdorur numrat e linjës, dhe numrat e linjës të ndryshojë
sepse ju shtoni ose fshini ndonjë kod, atëherë pikat e ndalimit tuaja janë të gjithë të dehur totalisht deri.
Një nga gjërat më të zakonshme që bëj unë është vendosur një breakpoint në funksionin kryesor.
Shpesh unë do të boot up GDB, unë do të tipit B MAIN, hit Enter, dhe se do të vendosë një breakpoint
në funksion kryesor që vetëm thotë, "pauzë programin sa më shpejt që ju të filloni running"
Dhe në këtë mënyrë, kur kam drejtuar programin tim me, të themi, CS50 shkëmbinjve si dy argumente
dhe hit Enter, ajo merr me funksionin kryesor dhe ndalon të drejtën në linjë të parë,
drejtë para se ajo vlerëson funksionin strcmp.
>> Që unë jam ndaluar, tani unë mund të fillojë mucking rreth dhe duke parë se çfarë po ndodh
me të gjitha variablave të ndryshme që janë kaluar në programin tim.
Këtu unë mund të shtypura nga argc dhe të shohim se çfarë po ndodh.
Shih se argc është 3, sepse ai e mori 3 vlera të ndryshme në të.
Ajo e mori emrin e programit, ai e mori argumentin e parë dhe Argumenti i dytë.
Ne mund të shtypura nga ata që duke kërkuar në argv [0], argv [1], dhe argv [2].
Deri tani ju mund të shihni se pse kjo thirrje strcmp do të dështojnë,
sepse ju shihni se ai ka ndarë deri CS50 dhe shkëmbinjtë në dy argumente të veçanta.
Në këtë pikë, një herë ju keni goditur një breakpoint, ju mund të vazhdojë të hap nëpërmjet programit tuaj
rresht pas rreshti, në krahasim me fillimin e programit tuaj përsëri.
Pra, nëse ju nuk doni të filloni programin tuaj përsëri dhe vetëm të vazhdojë më nga këtu,
ju mund të përdorni komandën vazhdojnë dhe do të vazhdojnë të drejtuar programin në fund.
Ashtu si ajo e bëri këtu.
Megjithatë, në qoftë se unë rinisni programin, CS50 shkëmbinj, ajo godet breakpoint time përsëri,
dhe këtë herë, në qoftë se unë nuk dua të vetëm të shkojnë të gjithë rrugën nëpër pjesën tjetër të programit,
Unë mund të përdorni komandën e ardhshëm, i cili edhe unë shkurtoj me n.
Dhe kjo do të hap përmes linjës programit nga linjë.
Kështu që ju mund të shikojnë si gjëra të ekzekutuar, si ndryshimi i variablave, si gjërat të merrni përditësuar.
E cila është shumë e bukur.
Gjë tjetër është e ftohtë sesa përsëritur komandën njëjta pa pushim,
në qoftë se ju vetëm hit Enter - kështu që këtu ju shihni unë nuk kam shtypur në asgjë -
në qoftë se unë vetëm goditi Enter, ai do të përsërisë komandën e mëparshme,
ose komandën mëparshme Gdb se unë vetëm vënë in
Unë mund të mbani goditur Enter dhe ajo do të mbajë shkelën përmes linjës sime kodit nga linjë.
Unë do të ju inkurajoj që të shkoni djema shikoni programe të tjera buggy si.
Ne nuk kemi kohë për të marrë nëpër të gjitha prej tyre sot në seksion.
Kodi burimor është atje, kështu që ju mund të lloj të shohim se çfarë po ndodh
prapa skenave në qoftë se ju merrni mbërthyer me të vërtetë,
por në shumë pak, vetëm praktikë booting up GDB,
drejtimin e programit deri sa prishet për ju,
marrjen e backtrace, duke parafytyruar se çfarë të funksionojë përplasje ishte në,
çfarë ajo ishte në linjë, shtypje nga disa vlera të ndryshueshme,
vetëm kështu që ju të merrni një të ndjehen për atë, sepse kjo do të ndihmojë me të vërtetë që ju të shkojnë përpara.
Në këtë pikë, ne jemi duke shkuar për të lënë jashtë GDB, të cilat ju mund të përdorni lë ose vetëm q.
Nëse programi juaj është në mes të rrjedhshëm ende, dhe kjo nuk ka dalë,
ajo gjithmonë do të ju pyes, "Jeni te sigurte qe doni me të vërtetë të lë?"
Ju vetëm mund të goditur po.
>> Tani ne do të shikojmë në problemin e ardhshëm ne kemi, që është programi cat.
Nëse keni shikuar të shkurtër në Përcjellin dhe tuba, ju do të shihni se Tommy përdor këtë program
që në thelb shtyp të gjithë prodhimin e një file në ekran.
Pra, nëse unë të drejtuar cat, kjo është në fakt një ndërtuar në program për aplikim,
dhe në qoftë se ju keni Macs që ju mund ta bëni këtë në Mac tuaj shumë, nëse keni hapur terminal.
Dhe ne - macja, le të themi, cp.c, dhe hit Enter.
Çfarë kjo e bëri, në qoftë se ne lëvizni lart pak dhe të shohim se ku ne u linjë,
ose ku ne u komandën cat, ajo fjalë për fjalë të shtypura vetëm nga përmbajtjen e cp.c në ekranin tonë.
Ne mund të kandidojë atë përsëri dhe ju mund të vënë në fotografi të shumta së bashku.
Kështu që ju mund të bëni cp.c mace, dhe pastaj ne mund të lidh file cat.c,
që është një program që ne jemi gati për të shkruar,
dhe ajo do të shtypura dy fotografi për të kthyer prapa në ekranin tonë.
Pra, nëse ne lëvizni lart pak, ne shohim se kur ne u këtë cp.c mace, cat.c,
Së pari, ai printuar nga CP dosjen, dhe pastaj poshtë, ajo printohet dosjen cat.c drejtë këtu poshtë.
Ne jemi duke shkuar për të përdorur këtë për të marrë vetëm këmbët tona lagësht.
Luajnë rreth me shtypjen e thjeshtë të terminalit, shih se si funksionon.
Në qoftë se ju djema të hapur deri me Gedit cat.c, hit Enter,
ju mund të shihni programin që ne jemi gati për të shkruar.
Ne kemi përfshirë këtë pjatë bojler të bukur, kështu që ne nuk duhet të kalojnë kohë shtypja gjithë jashtë atë.
Ne gjithashtu kontrolloni numrin e argumenteve kaloi in
Ne të shtypura nga një mesazh të bukur përdorimit.
>> Kjo është lloj i gjë që, përsëri, ashtu si ne kemi qenë duke folur rreth,
kjo është pothuajse si memorie të muskujve.
Vetëm mos harroni të vazhdojmë të bëjmë të njëjtën lloj të stuff
dhe gjithmonë shtypje nga disa lloj mesazhi dobishme
mënyrë që njerëzit të dinë se si për të drejtuar programin tuaj.
Me mace, kjo është shumë e thjeshtë, ne jemi vetëm duke shkuar për të shkuar nëpër të gjitha argumentet të ndryshme
që janë kaluar në programin tonë, dhe ne jemi duke shkuar për të shtypur
Përmbajtja e tyre jashtë në ekran në një kohë.
Në mënyrë që të shtypura fotografi nga të ekranit, ne jemi duke shkuar për të bërë diçka shumë të ngjashme
me atë që ne e bëmë në fund të quiz.
Në fund të quiz, që punësojnë program, ne kishim për të hapur një skedar,
dhe pastaj na u desh për të shkruar për të.
Në këtë rast, ne jemi duke shkuar për të hapur një skedar, dhe ne jemi duke shkuar për të lexuar nga ai vend.
Atëherë ne jemi duke shkuar për të shkruar, në vend të në një skedar, ne jemi duke shkuar për të shtypur në ekran.
Pra, shtypje në ekran që ju keni bërë të gjitha para me printf.
Kështu që nuk është shumë e çmendur.
Por duke lexuar një skedar është lloj i pazakontë.
Ne do të shkoni nëpër atë pak pak në një kohë.
Në qoftë se ju djema shkoni përsëri në këtë problem të fundit në quiz tuaj, problemit 33,
rreshtin e parë që ne jemi duke shkuar për të bërë këtu, duke hapur dosjen, është shumë e ngjashme me atë që ne e bëmë atje.
Pra Stella, çfarë bën që duken si të linjës, kur ne të hapur një skedë?
[Stella] * Capital Foto, file - >> Okay. >> - Është e barabartë me fopen. Yup >>.
E cila në këtë rast është? Është në komentin.
>> Është në komentin? argv [i] dhe r?
Pikërisht >>. Drejtë në. Pra, Stella është krejtësisht e drejtë.
Kjo është ajo që duket si linjë.
Ne jemi duke shkuar për të marrë një ndryshore lumë file, ruani atë në një * Foto, kështu që të gjitha shkronja kapitale,
Foto, *, dhe emri i këtij variablit do të jenë file.
Ne mund të telefononi atë çfarë na pëlqen. Ne mund të telefononi atë first_file, ose file_i, çfarëdo që ne do të donim.
Dhe pastaj emrin e file u miratua në në rreshtin e komandave në këtë program.
Kështu që është ruajtur në argv [i], dhe pastaj ne jemi duke shkuar për të hapur këtë file në mënyrë të lexuar.
Tani që ne kemi hapur dosjen, çfarë është gjëja që ne gjithmonë duhet të mbani mend për të bërë
sa herë që ne kemi hapur një skedar? Afër atë.
Pra Missy, sa nuk kemi mbyllur një skedë?
[Missy] Shkrimi (file) >> Shkrimi (file). Saktësisht.
Madhe. Rregull. Nëse ne shikojmë në këtë të bëni koment drejtë këtu,
ai thotë se, "Open argv [i] dhe printoni përmbajtjen e saj të stdout."
>> Nga standardi është një emër i pazakontë. Syswrite është vetëm mënyra jonë për të thënë
ne duam të shtypura atë në terminal, ne duam të shtypura atë në lumë standarde prodhimit.
Ne fakt mund të shpëtoj nga ky komenti të drejtë këtu.
Unë jam duke shkuar për të kopjoni dhe ngjisni atë atë që kjo është ajo që ne e bëmë.
Në këtë pikë, tani ne kemi për të lexuar pak nga pak e fotografisë.
Ne kemi diskutuar disa mënyra leximit të dosjeve.
Të cilat ato janë të preferuarat tuaja deri tani?
Cili mënyra keni parë ose nuk ju kujtohet, për të lexuar fotografi?
[Daniel] fread? Fread >>? Kështu fread është një. Jimmy, ju e dini ndonjë të tjerët?
[Jimmy] nr >> Okay. Jo. Charlotte? Alexander? Ndonjë të tjerët? Rregull.
Pra, ato të tjera janë fgetc, është ai që ne do të përdorim një shumë.
Ka gjithashtu fscanf, ju djema shikoni një model këtu?
Ata të gjithë fillojnë me f. Asgjë të bëjë me një skedar.
Ka fread, fgetc, fscanf. Këto janë të gjitha funksionet e leximit.
Për të shkruar kemi fwrite, ne kemi fputc vend të fgetc.
Ne gjithashtu kemi fprintf si e pamë në quiz.
Që kjo është një problem që përfshin lexuar nga një skedar,
ne jemi duke shkuar për të përdorur një nga këto tri funksione.
Ne nuk jemi duke shkuar për të përdorur këto funksione këtu poshtë.
Këto funksione janë gjetur të gjitha në bibliotekën standarde I / O.
Pra, nëse ju shikoni në krye të këtij programi,
ju mund të shihni se ne kemi përfshirë tashmë file header për bibliotekën standarde I / O.
Në qoftë se ne duam të kuptoj se cilat një që ne duam të përdorim,
ne gjithmonë mund të hapë faqet e njeri.
Pra, ne mund të shtypni stdio njeri
dhe të lexoni të gjitha në lidhje me kontributin stdio dhe funksionet e prodhimit në C.
Dhe ne mund të shohim tashmë oh, po. Është përmendur fgetc, ajo përmendet fputc.
Kështu që ju mund të Stërvitja poshtë pak dhe shikoni në, të themi, fgetc
dhe të kërkoni në faqen e saj njeri.
Ju mund të shihni se ajo shkon së bashku me një bandë e tërë e funksioneve të tjera:
fgetc, fgets, getc, getchar, merr, ungetc, dhe kontributin e tij të karaktereve dhe vargjet.
Pra, kjo është se si ne lexojmë në karaktere dhe vargjet nga dosjet nga input standard,
cila është në thelb nga perdoruesit.
Dhe kjo është se si ne bëjmë atë në C. aktuale
Pra, kjo nuk është duke përdorur getString dhe funksionet GetChar
që kemi përdorur nga biblioteka CS50.
Ne jemi duke shkuar për të bërë këtë problem në disa mënyra
kështu që ju mund të shihni dy mënyra të ndryshme për të bërë atë.
Dy fread funksion që Danieli përmendur dhe fgetc janë mënyra të mira për të bërë atë.
Unë mendoj se fgetc është pak më e lehtë, sepse ai ka vetëm, siç e shihni,
një argument, * FILE që ne jemi duke u përpjekur për të lexuar karakter nga,
dhe vlera e tij e kthimit është një int.
Dhe kjo është pak konfuze, apo jo?
>> Sepse ne jemi duke marrë një karakter, kështu që pse nuk e ky kthim një char?
Ju djema keni ndonjë ide se pse kjo nuk mund të kthehen një char?
[Përgjigjet Missy, i pakuptueshëm] >> yeah. Pra Missy është krejtësisht e drejtë.
Nëse kjo është ASCII, atëherë ky numër të plotë mund të jetë plotësisht në një char aktuale.
Mund të jetë një simbol ASCII, dhe kjo është e drejtë.
Kjo është pikërisht ajo që po ndodh.
Ne jemi duke përdorur një int thjesht sepse ajo ka më shumë copa.
Kjo është më e madhe se një char; char ynë i vetëm ka 8 bit, se 1 bajt për makinat 32-bit tonë.
Dhe një int ka vlerë të gjitha 4 bytes 'e hapësirës.
Dhe kjo rezulton se rruga fgetc punon,
nëse lëvizni poshtë në përmbledhje tonë në këtë faqe burrë pak,
shkoni të gjithë rrugën poshtë. Ajo rezulton se ata përdorin këtë vlerë të veçantë të quajtur EOF.
Kjo është një konstante të veçantë si vlerë e kthimit të funksionit fgetc
sa herë që ju goditi në fund të file ose nëse ju merrni një gabim.
Dhe kjo rezulton se për të bërë këto krahasime me EOF siç duhet,
ju dëshironi të keni atë sasi shtesë e informacionit që ju keni në një int
në krahasim me duke përdorur një ndryshore char.
Edhe pse fgetc është në mënyrë efektive duke marrë një karakter nga një skedar,
ju doni të mbani mend se ajo është kthyer diçka që është e tipit int për ju.
Kjo tha, ajo është mjaft e lehtë për t'u përdorur.
Ajo do të na japin një karakter, kështu që të gjithë ne duhet të bëni është të mbani duke i kërkuar dosjen,
"Ma jep karakter tjetër, më jep karakter tjetër, më jep karakter tjetër,"
deri sa të kemi në fund të file.
Dhe se do të tërheqë në një karakter në një kohë nga dosjen tonë,
dhe pastaj ne mund të bëjmë çdo gjë që ne donim me të.
Ne mund të ruajë atë, ne mund të shtoni atë në një varg, ne mund të shtypura atë.
A ndonjë nga se.
>> Zooming nga mbrapa dhe duke shkuar prapa në programin tonë cat.c,
në qoftë se ne jemi duke shkuar për të përdorur fgetc,
se si mund të afrohemi këtë linjë tjetër të kodit?
Ne jemi duke shkuar për të përdorur - fread do të bëjë diçka pak të ndryshme.
Dhe këtë herë, ne jemi vetëm duke shkuar për të përdorur fgetc për të marrë një karakter në një kohë.
Të procesit të një file të tërë, çfarë mund të kemi të bëjmë?
Sa shumë karaktere janë atje në një dosje?
Nuk janë një shumë. Pra, ju ndoshta dëshironi të merrni një
dhe pastaj të marrë një tjetër dhe për të marrë një tjetër dhe për të marrë një tjetër.
Çfarë lloj algorithm mendoni se ne mund të kemi për të përdorur këtu?
Çfarë lloji të -? [Aleksandër] A për lak? Pikërisht >>.
Disa lloj lak.
Një për lak është në të vërtetë e madhe, në këtë rast.
Dhe si ju janë duke thënë, kjo tingëllon si ju doni një lak mbi të gjithë dosjen,
duke marrë një karakter në një kohë.
Çdo sugjerime në atë që mund të duken si?
[Alexander, i pakuptueshëm]
Mirë >>, vetëm më tregoni në gjuhën angleze se çfarë jeni duke u përpjekur për të bërë? [Alexander, i pakuptueshëm]
Pra, në këtë rast, kjo tingëllon si ne jemi vetëm duke u përpjekur për të lak mbi të gjithë dosjen.
[Aleksandër] Pra, i > -?
I guess madhësinë e file, apo jo? Madhësia - we'll shkruani vetëm atë si kjo.
Madhësia e dosjes për momentin, i + +.
Pra, rezulton se në mënyrë që ju të bëni këtë duke përdorur fgetc, dhe kjo është e re,
është se nuk ka asnjë mënyrë e lehtë për të merrni vetëm madhësinë e një file
me këtë "sizeof" llojin e ndërtuar që ju keni parë më parë.
Kur ne përdorim atë funksion fgetc, ne jemi futur disa lloj
re, Sintaksa shokuar me këtë për lak, ku në vend të duke përdorur vetëm një counter themelore
për të shkuar karakter nga karakteri, ne jemi duke shkuar për të tërhequr një karakter në një kohë,
një karakter në një kohë, dhe mënyrën se si ne e dimë se ne jemi në fund
nuk është kur ne kemi numëruar një numër të caktuar të karaktereve,
por kur personazhi ne tërhiqet nga se fundi i veçantë i karakterit file.
Pra, ne mund ta bëni këtë duke - Unë e quaj këtë ch, dhe ne jemi duke shkuar për të nisja atë
me thirrjen tonë të parë për të marrë karakterin parë nga file.
Pra, këtë pjesë të drejtë këtu, kjo do të marrë një karakter nga e dosjes
dhe ruajtur atë në ch ndryshueshme.
Ne jemi duke shkuar për të mbajtur të bërë këtë deri sa të kemi në fund të skedarit,
që ne bëjmë nga testimi për karakterin jo të barabartë me atë karakter të veçantë EOF.
Dhe pastaj në vend që të bëjnë ch + +, i cili vetëm do të rritje e vlerës,
kështu që nëse ne lexojmë një nga një të dosjes, një kapital A, thonë,
ch + + do na japin b, dhe pastaj ne do të merrni dhe pastaj c d.
Kjo nuk është e qartë se çfarë duam. Ajo që ne duam këtu
në këtë pak e fundit është që ne duam të marrë karakter tjetër nga dosja.
>> Pra, si mund të kemi marrë karakter tjetër nga dosja?
Si nuk kemi marrë karakterin parë nga file?
[Student] fgetfile? Fgetc >>, ose, më vjen keq, ju ishit krejtësisht e drejtë.
Unë misspelled atë të drejtë atje. Pra, vërtet.
Këtu në vend të bërë ch + +,
ne jemi vetëm duke shkuar për të thirrur fgetc (file) përsëri
dhe ruajtur rezultatin në variabël të njëjtën tonë ch.
[Pyetja Student, pakuptueshëm]
Kjo është ajo ku >> këta dosjen * janë të veçantë.
Mënyra se si ata punojnë është se ata - kur ju së pari të hapur - kur ju së pari të bëni atë telefonatë fopen,
e * Foto efektivisht shërben si një tregues në fillim të file.
Dhe pastaj çdo herë që ju e quani fgetc, ajo lëviz një karakter nëpër dosje.
Pra, kur ju telefononi këtë, ju jeni bën rritjen treguesin e fotografisë me një karakter.
Dhe kur ju fgetc përsëri, ju jeni duke lëvizur atë një karakter
dhe një tjetër karakter dhe një tjetër karakter dhe një tjetër karakter.
[Pyetja Student, pakuptueshëm] >> Dhe that's - yeah.
Kjo është lloj i këtij magji nën kapuç.
Ju vetëm i mbajnë bën rritjen përmes.
Në këtë pikë, ju jeni në gjendje që në fakt të punojnë me një karakter.
Pra, si mund të kemi shkruar këtë jashtë në ekran, tani?
Ne mund të përdorni të njëjtën gjë që kemi përdorur printf parë.
Se ne kemi qenë duke përdorur të gjitha semestër.
Ne mund të telefononi printf,
dhe ne mund të kalojë në karakter vetëm si kjo.
Një tjetër mënyrë për të bërë atë është vend se duke përdorur printf dhe të kesh për të bërë këtë varg format,
ne gjithashtu mund të përdorni një nga funksionet e tjera.
Ne mund të përdorim fputc, i cili shtyp një karakter në ekran,
përveç nëse ne shikojmë në fputc - më lejoni të zoom out pak.
Ne e shohim se çfarë është e bukur është ajo merr në të karakterit që ne lexojmë duke përdorur fgetc,
por atëherë ne kemi për të dhënë atë një lumë për të shkruar për të.
Ne gjithashtu mund të përdorni funksionin e putchar, e cila do të vënë direkt në jashtë standardit.
Pra, ka një bandë e tërë e opcioneve të ndryshme që ne mund të përdorni për printim.
Ata janë të gjithë në bibliotekën standarde I / O.
Sa herë që ju doni të shtypura - kështu printf, by default, do të shtypura me standardin veçantë nga lumë,
cila është se Syswrite.
Pra, ne vetëm mund të referohen asaj si lloj i kësaj vlere magjike, syswrite këtu.
Oops. Vendos pikëpresje jashtë.
>> Kjo është një shumë e informacionit të ri, i shokuar në këtu.
Një shumë e kjo është shumë idiomatike, në kuptimin se ky është kodi
që është shkruar në këtë mënyrë vetëm për shkak se ajo është e pastër për të lexuar, të lehtë për të lexuar.
Ka shumë mënyra të ndryshme për ta bërë atë shumë funksione të ndryshme ju mund të përdorni,
por ne priren për të vetëm të ndiqni këto modele të njëjta pa pushim.
Pra, mos u habitni nëse ju shikoni kodin si kjo vijnë përsëri dhe përsëri.
Dakord. Në këtë pikë, ne kemi nevojë për të thyer për ditë.
Faleminderit për të ardhur. Faleminderit për të shikuar nëse ju jeni online. Dhe ne do të shohim se javën e ardhshme.
[CS50.TV]