[Powered by Google Translate] [Neni 5 - më të rehatshme]
[Rob Bowden - Universiteti i Harvardit]
[Kjo është CS50. - CS50.TV]
>> Ashtu si thashë në email tim, ka shumë gjëra që ju mund të përdorni
përveç aparatit që në fakt të bërë grupe problem.
Ne ju rekomandojmë që ju bëni atë në aplikim vetëm sepse atëherë ne mund të ju ndihmojë më lehtë
dhe ne e dimë se si çdo gjë është duke shkuar për të punuar.
Por si një shembull se ku ju mund të bëni gjëra nëse, të themi, ju nuk keni qasje
në një aplikim ose ju dëshironi të punoni në bodrum Qendra Shkencore -
e cila në fakt ata kanë aplikim shumë -
në qoftë se ju dëshironi të punoni kudo.
Një shembull është i keni parë / dëgjuar SSH?
SSH është në thelb vetëm si të lidheni me diçka.
Në fakt, tani unë jam SSHed në aplikim.
Unë kurrë nuk punojnë direkt në aplikim.
Këtu është aplikim, dhe nëse ju shikoni këtu poshtë shihni ju këtë adresë IP.
Unë kurrë nuk punojnë në aplikim vetë;
Unë gjithmonë të vijë mbi të një dritare dritare iTerm2 / terminal.
Ju mund të SSH në atë adresë IP, ssh jharvard@192.168.129.128.
Mbaj mend se numri shumë të lehtë për shkak se ajo është e tillë një model bukur.
Por që do të pyesni mua për fjalëkalimin tim, dhe tani unë jam në aplikim.
Në thelb, në këtë pikë, në qoftë se keni hapur një terminal brenda vetë pajisjes,
kjo interface, megjithatë ju do të përdorin atë, është saktësisht e njëjtë
si unë jam duke përdorur ndërfaqe gjatë këtu, por tani ju jeni SSHed.
Ju nuk keni për të SSH në pajisjen.
Një shembull i një vend tjetër ju mund të SSH për të është që unë jam goxha i sigurt që ju keni nga default -
Oh. Madhe.
Të gjithë ju duhet të ketë nga llogaritë FAS si parazgjedhje në serverat FAS.
Për mua, unë do të SSH rbowden@nice.fas.harvard.edu.
Kjo do të ju pyes se herë të parë, dhe ju them po.
Fjalëkalimi im është vetëm do të jetë fjalëkalimi im FAS.
Dhe kështu tani, unë jam SSHed në serverat e bukur, dhe unë mund të bëjë asgjë që unë dua këtu.
Një shumë e klasave ju mund të merrni, si 124, do të keni ngarkoni gjëra këtu
që në fakt paraqesin grupe tuaja problem.
Por thonë se ju nuk keni qasje në pajisjen tuaj.
Atëherë ju mund të bëni gjëra, si në këtu do të thonë -
Kjo është vetëm pjesë e pyetjeve tona.
Kjo do të ju pyes për të bërë këtë në aplikim.
Në vend të kësaj unë do vetëm të bëjë atë në server.
Unë jam duke shkuar për të unzip atë.
Problemi do të jetë se ju jeni përdorur për të përdorur diçka si Gedit
ose çfarëdo brendësi të pajisjes.
Ju nuk jeni do të ketë që në server FAS.
Kjo është e gjitha vetëm do të jetë në këtë ndërfaqe tekstuale.
Kështu që ju mund të ose një, do të përpiqen për të mësuar një editor teksti që ata kanë.
Ata kanë Nanon.
Nano është zakonisht shumë e lehtë për t'u përdorur.
Ju mund të përdorni shigjetat tuaja dhe shkruani normalisht.
Kështu që nuk është e vështirë.
Në qoftë se ju doni të merrni të vërtetë dashuroj ju mund të përdorni Emacs,
që unë ndoshta nuk duhet të ketë hapur, sepse unë nuk e di edhe se si për të mbyllur Emacs.
Kontrolli X, Kontrollit C? Po.
Ose ju mund të përdorni vim, e cila është ajo që unë e përdor.
Dhe kështu ata janë mundësitë tuaja.
Nëse ju nuk doni të bëni këtë, ju gjithashtu mund të, nëse ju shikoni në manual.cs50.net--
Oh.
Në një PC, ju mund të përdorni SSH stuko,
që ju jeni do të duhet të shkarkoni veç e veç.
Në një Mac, ju mund të përdorni vetëm duke terminalin e prezgjedhur, ose ju mund të shkarkoni iTerm2,
e cila është si një Terminal bukur, zbukuruar.
Nëse ju shkoni në manual.cs50.net ju do të shihni një lidhje në Notepad + +,
e cila është ajo që ju mund të përdorni në një PC.
Kjo ju lejon të SFTP nga Notepad + +, e cila është në thelb SSH.
Çfarë kjo do të ju lejojnë të bëni është të redaktoni fotografi tuaja në vend,
dhe pastaj kur ju doni të ruani ato, ajo do të ruajtur nice.fas,
ku ju mund të pastaj të drejtuar ata.
Dhe ekuivalente në një Mac do të jetë TextWrangler.
Pra, kjo ju lejon të bëni të njëjtën gjë.
Kjo ju lejon të redaktoni fotografi në nivel lokal dhe ruani ato në nice.fas,
ku ju mund të pastaj të drejtuar ata.
Pra, nëse ju jeni të mbërthyer ndonjëherë pa një aplikim, ju keni këto opsione
për të ende bëjnë grupe tuaja problem.
Një problem do të jetë që ju nuk do të ketë bibliotekën CS50
sepse nice.fas nuk kanë se by default.
Ju mund ta shkarkoni bibliotekën CS50 -
Unë nuk mendoj se kam nevojë që në këtë pikë.
Ju mund ta shkarkoni bibliotekën CS50 dhe kopje atë mbi të nice.fas,
ose unë mendoj se në këtë pikë ne nuk e përdorin atë më anyway.
Ose në qoftë se ne bëjmë, ju mund të për herë të zëvendësojë atë me
e implementimit të funksioneve në bibliotekë CS50 anyway.
Kështu që nuk duhet të jetë se shumë nga një kufizim.
Dhe kjo është se.
>> Unë do të shkoj përsëri në aplikim tani, ne do të bëjmë gjithçka në aplikim.
Kërkoni në seksionin tonë të pyetjeve, në fillim, siç thashë në email tim
ne duhet të flasim për një të shkurtër keni qenë dashur të shikojnë.
Ne kemi Përcjellin & tuba dhe këto tre pyetje.
>> Në të cilën nuk funksionon si lumë printf shkruani by default?
Pra lumë. Çfarë është një lumë?
Një lumë është në thelb si ajo është vetëm disa -
Kjo nuk është edhe një burim i 1s dhe 0s.
Lumë është e kërkuar për këtu është jashtë standardeve.
Dhe jashtë në mënyrë standarde është një rrjedhë se kur ju shkruani në të,
duket në ekran.
Nga standardi, me rrymë, do të thotë që ju të shkruani vetëm 1s dhe 0s për atë,
dhe në fund të tjera të jashtë standardit vetëm lexon nga ai lumë.
Kjo është vetëm një varg i 1s dhe 0s.
Ju mund të shkruani për rrjedhat ose ju mund të lexohet nga rrjedhat
në varësi të asaj lumë të vërtetë është.
Të tjera dy lumenj default janë standard në gabim dhe standarde.
Standard në është kur ju bëni getString, është duke pritur për ju për gjëra të dhëna.
Pra, kjo duke pritur për ju, kjo është në fakt duke pritur në standard në,
e cila është me të vërtetë ajo që ju merrni kur ju shtypni në tastierë.
Ju jeni të shtypni në standardin in
Gabim standarde është në thelb ekuivalente me jashtë standardit,
por është e specializuar në atë që, kur keni shkruar gabim të standardit,
ju jeni menduar të shtypura vetëm mesazhet e gabimit për këtë
kështu që ju mund të dallojnë në mes të mesazheve të rregullta të shtypura në ekran
kundrejt mesazhet e gabimit në varësi të nëse ata shkuan jashtë standardit apo gabimi standard.
Fotografi shumë.
Nga standardi, standard në, dhe gabimi standarde janë vetëm lumenj të veçanta,
por me të vërtetë ndonjë file, kur ju hapni një skedar, ajo bëhet një lumë bytes
ku ju mund vetëm të lexohet nga ai lumë.
Ju, për pjesën më të madhe, vetëm mund të mendojnë për një fotografi si një rrjedhë e bytes.
Pra streams për çfarë shkruajnë ata që by default? Nga standardi.
>> Çfarë është dallimi në mes> dhe >>?
A e dikush të shikuar këtë video paraprakisht? Rregull.
> Do të jetë si ju përcjellim në fotografi,
dhe >> është gjithashtu do të përcjellim në dalje fotografi,
por ajo në vend që do të append në dosjen.
Për shembull, le të thonë se unë të ndodhë që të ketë Dict drejtë këtu,
dhe sende të vetëm brenda Dict është mace mace, qen, peshk, qen.
Një komandë që ju keni në command line është mace,
e cila është vetëm do të shtypura atë që është në një skedar.
Kështu që kur unë them Dict mace, ajo do të shtypura, mace mace, qen, qen, peshk. Kjo është e gjitha cat bën.
Që do të thotë se ai printuar në standard, nga mace mace, qen qen, peshk,.
Në qoftë se unë dua të përcjellim në vend që në një skedar, unë mund të përdorni> dhe përcjellim atë në çfarëdo file është.
Unë do të thërrasë të fotografisë.
Deri tani, nëse unë ls, unë do të shihni se unë kam një skedar të ri të quajtur file.
Dhe në qoftë se unë të hapur atë, ajo do të ketë pikërisht ajo macja vënë në rreshtin e komandave.
Kështu që tani, nëse unë ta bëjë këtë përsëri, atëherë ajo do të përcjellim në dalje në dosje,
dhe unë jam i do të ketë të njëjtën gjë e saktë.
Pra teknikisht, ajo tërësisht overrode atë që kemi pasur.
Dhe ne do të shohim nëse unë ndryshoj Dict, I mori qenin.
Tani në qoftë se ne cat dict në dosjen përsëri, ne jemi duke shkuar për ketë versionin e ri me qen hequr.
Pra, ajo tërësisht refuzon atë.
Në vend të kësaj, në qoftë se ne përdorim >>, ajo do të append fotografi.
Tani, duke hapur dosjen, ne shohim kemi vetëm të njëjtën gjë dy herë shtypura
sepse ajo ishte atje një herë, atëherë ne bashkangjitur në origjinal.
Atë mënyrë që të> dhe >> bëni.
A të kërkojë një tjetër - Ajo nuk pyet për atë.
>> Një tjetër që ne kemi është <, i cili në qoftë se> përcjellëse jashtë standardeve,
<Do të përcjellim standardet in
Le të shohim nëse ne kemi një shembull.
Unë mund të shkruaj një të shpejtë të vërtetë.
Le të marrin ndonjë skedar, hello.c.
Fotografi relativisht i thjeshtë.
Unë jam vetëm duke marrë një varg dhe pastaj shtypjen "Hello" çfarëdo string Unë sapo hyri ishte.
Kështu që bëni përshëndetje dhe pastaj. / Hello.
Tani ajo është bërë mua për të hyrë në diçka,
që do të thotë se është duke pritur për gjëra për të hyrë në standardin in
Kështu që unë dua çdo gjë që hyn në standardin in Ne jemi vetëm do të them Hello, Rob!
Pastaj ai e shtypjes për standarde nga Hello, Rob!
Nëse unë bëj. / Përshëndetje dhe pastaj përcjellëse,
tani për tani ju mund të përcjellim nga një skedar.
Pra, nëse kam vënë në disa dosje, txt, dhe kam vënë Rob,
në qoftë se unë të drejtuar përshëndetje dhe pastaj përcjellëse txt file ne. / hello, ajo do të them Hello, Rob! menjëherë.
Kur ajo të parë merr në getString dhe është duke pritur në standarde në,
standarde në nuk është më duke pritur në tastierë për të dhëna për të marrë hyrë.
Në vend të kësaj, ne kemi ridrejtuar standarde për të lexuar nga txt file.
Dhe kështu ajo do të lexohet nga txt file, e cila është vetëm Rob linjë,
dhe pastaj ajo do të shtypura Hello, Rob!
Dhe nëse kam kërkuar, unë mund të bëj. / Përshëndetje <txt
dhe pastaj standarde se kjo shtypje, e cila është Hello, Rob!,
Unë mund të përcjellim se në dosjen e vet.
Unë vetëm do të thërrasë skedarin hello - jo, unë nuk do të, për shkak se është ekzekutues - txt2.
Tani, txt2 do të ketë prodhimin e. / Përshëndetje <txt, i cili do të jetë Përshëndetje, Rob!
>> Pyetje?
>> Rregull. Kështu atëherë këtu kemi tubacionin.
Tuba janë njësia e fundit e redirection.
>> Oh. I guess një njësi më shumë nga redirection është në qoftë se në vend të> ju bëni 2>,
që është Përcjellin gabim standarde.
Kështu që nëse diçka shkoi gabim standarde, nuk do të ketë vënë në txt2.
Por vëreni nëse i bëj 2>, atëherë ajo është ende shtypjen Hello, Rob! në command line
sepse unë jam vetëm Përcjellin gabim standarde, unë nuk jam Përcjellin standardin jashtë.
Gabim standarde dhe jashtë standarde janë të ndryshme.
Në qoftë se ju të kërkuar për të shkruar për të vërtetë gabimi standart,
atëherë unë mund të ndryshojë kjo të jetë fprintf të stderr.
Pra printf, by default, shtyp të jashtë standardeve.
Nëse unë dua të shtypura të gabimit standarde dorë, atëherë unë duhet të përdorni fprintf
dhe të përcaktojë se çfarë unë dua të shtypura të.
Nëse në vend të kësaj kam bërë syswrite fprintf, atëherë kjo është në thelb ekuivalente me printf.
Por fprintf të gabimit standard.
Deri tani, në qoftë se unë të përcjellim këtë në txt2, Hello, Rob! është ende duke u shtypur në command line
pasi ajo është duke u shtypur të gabimit standarde dhe unë jam vetëm Përcjellin standardin jashtë.
Nëse unë tani përcjellim gabim standarde, tani ajo nuk ka marrë të shtypura, dhe txt2 do të jetë Hello, Rob!
Deri tani, ju mund të shtypura gabimet tuaja aktuale të gabimit standarde
dhe të shtypura mesazhet tuaja të rregullta për jashtë standardit.
Dhe kështu që kur ju drejtuar programin tuaj, ju mund të kandidojë atë si. / Përshëndetje kjo lloj me 2>
në mënyrë që programi juaj do të kandidojë normalisht,
por çdo mesazhet e gabimit që ju të merrni ju mund të kontrolloni më vonë në log tuaj gabim,
kështu gabime, dhe pastaj të shohim më vonë dhe file gabime juaj do të ketë ndonjë gabim që ka ndodhur.
>> Pyetje?
>> E fundit është tub, të cilat ju mund të mendoni si të marrë standardin nga një komandë
dhe duke e bërë atë standard në të komandës ardhshëm.
Një shembull këtu është Echo është një linjë komande gjë
që është vetëm do të bëjnë jehonë çdo gjë që unë vënë si argument të saj. Unë nuk do të vënë kuotat.
Echo blah, blah, blah është vetëm do të shtypura blah, blah, blah.
Më parë, kur kam thënë unë kam për të vënë Rob në një skedar txt
sepse unë vetëm mund të përcjellim fotografi txt, në vend, / në qoftë se unë jehonë Rob
dhe pastaj atë në tub. / hello, që do të bëjë të njëjtin lloj gjë.
Kjo po e prodhimit të kësaj komande, jehonë Rob,
dhe duke e përdorur atë si input për të. / hello.
Ju mund të mendoni për atë si përcjellëse e parë e jehonës Rob në një skedar
dhe pastaj në input. / Përshëndetje këtë dosje që u outputted vetëm.
Por ajo merr file të përkohshëm nga foto.
>> Pyetjet për këtë?
>> Pyetja tjetër do të përfshijë këtë.
Çfarë mund të tubacionit që ju përdorni për të gjetur numrin e emrave unike në një skedar të quajtur names.txt?
The Komandat ne do të dëshironi të përdorni këtu janë unike, kështu uniq, dhe pastaj WC.
Ju mund të bëni uniq njeri që në fakt shohim se çfarë bën,
dhe kjo vetëm do të filtruar linja ngjitur përputhen nga input.
Dhe njeriu WC do të shtypura newline fjalë,, dhe akuza bajt për çdo dosje.
Dhe e fundit ne do të dëshironi të përdorni është lloj,
e cila është vetëm do të zgjidhë rreshta të txt file.
Nëse unë bëjë disa fotografi txt, names.txt, dhe kjo është Rob, Tommy, Jozefi, Tommy, Jozefi, RJ, Rob,
ajo që unë dua të bëj këtu është të gjeni numrin e emrave unik në këtë file.
Pra, çfarë duhet të jetë përgjigja? >> [Student] 4. Po >>.
Ajo duhet të jetë 4 prej Rob, Tommy, Jozefi, RJ janë emrat e vetme unike në këtë file.
Hapi i parë, në qoftë se unë vetëm të bëjë numërimin e fjalës në names.txt,
Kjo është në fakt më thënë gjithçka.
Kjo është në fakt shtypje - le të shohim, njeriu WC - newlines, fjalët, dhe numërimin e bajt.
Nëse unë vetëm kujdesen për linjat, atëherë unë mund të bëjë vetëm wc-l names.txt.
Pra, kjo është hap 1.
Por unë nuk dua të WC-l names.txt sepse vetëm names.txt përmban të gjitha emrat,
dhe unë dua për të filtruar nga ndonjë jo-unike ato.
Pra, nëse unë bëj names.txt uniq, që nuk mjaft më jep atë që unë dua
sepse emrat dyfishta janë ende atje.
Pse është kjo? Pse nuk është bërë uniq atë që unë dua?
[Student] nuk janë kopje identike [padëgjueshme] >> Yeah.
Kujtohet njeri per faqe uniq thotë linjat filtër ngjitur përputhen.
Ato nuk jeni ngjitur, kështu që nuk do të filtruar ato.
Nëse unë të zgjidhur ato së pari, names.txt lloj do të vënë të gjitha linjat e kopjuar bashku.
Kështu që tani names.txt lloj është se.
Unë jam do të duan të përdorin atë si input për uniq, e cila është | uniq.
Kjo më jep Jozefin, RJ, Rob, Tommy,
dhe unë dua të përdorin atë si input për wc-l,
e cila do të më jepni 4.
Si ajo thotë se këtu, çfarë tubacioni mund të përdorni?
Ju mund të bëni një shumë të gjëra të tilla si duke përdorur një seri e komandave
ku ju përdorni të prodhimit nga një komandë si input në komandën e ardhshëm.
Ju mund të bëni një shumë të gjëra, shumë gjëra të zgjuar.
>> Pyetje?
Rregull.
Kjo është ajo për tuba dhe redirection.
>> Tani ne do të shkojmë për të stuff stuff aktuale, coding.
Brenda kësaj PDF, ju do të shihni këtë komandë,
dhe ju do të doni për të drejtuar këtë komandë në aplikim tuaj.
wget është komanda për vetëm duke marrë diçka nga interneti, në thelb,
kështu wget dhe kjo URL.
Në qoftë se ju shkoi në këtë URL në shfletuesin tuaj, ajo do të shkarkoni këtë fotografi.
Unë vetëm klikuar mbi të, kështu që ajo shkarkuar skedarin për mua.
Por shkrim wget e kësaj gjëje në brendësi të terminalit
është vetëm do të shkarkoni atë në terminalin tuaj.
Unë kam section5.zip, dhe ju do të dëshironi të unzip section5.zip,
e cila do të ju jap një dosje të quajtur section5,
e cila do të ketë të gjitha dosjet që ne do të jeni duke përdorur sot në brendësi të saj.
Si emra këto programe "fotografi sugjerojnë, ata janë një buggy pak,
kështu që misioni juaj është që të kuptoj se pse duke përdorur gdb.
A të gjithë ata kanë shkarkuar / e di se si për të marrë ato shkarkuar
në aplikim të tyre? Rregull.
>> Drejtimin ./buggy1, kjo do të thotë fajin segmentimit (core hedhur),
që çdo herë që të merrni një segfault, kjo është një gjë e keqe.
Në çfarë rrethanash mund të merrni një segfault?
[Student] Dereferencing një tregues null. Po >>. Kështu që është një shembull.
Dereferencing një tregues null ju jeni do të merrni një segfault.
Çfarë do të thotë një segfault është që ju jeni duke prekur kujtesën që ju nuk duhet të jetë prekur.
Pra dereferencing një tregues zero është prekur adresën 0,
dhe në thelb, të gjithë kompjuterët në ditët e sotme thonë se adresa është 0 kujtesës që ju nuk duhet të jetë prekur.
Pra, kjo është arsyeja pse një dereferencing rezultate null pointer në një segfault.
Kur ju ndodh që të mos nisja një tregues, atëherë ajo ka një vlerë plehrash,
dhe kështu kur ju përpiqeni të dereference atë, në të gjitha gjasat ju jeni prekur kujtesën
që është në mes të askund.
Nëse ju ndodh që të merrni me fat dhe vlera e plehrave
ndodhur për pikë në diku në rafte apo diçka,
atëherë kur ju dereference se treguesin që ju nuk e keni initialized,
asgjë nuk do të shkojnë keq.
Por në qoftë se ajo është treguar për të, thonë, diku në mes të rafte dhe të tog,
ose ajo është vënë vetëm për diku që nuk ka qenë e përdorur nga programi juaj ende,
atëherë ju jeni prekur kujtesën që ju nuk duhet të jetë prekur dhe ju segfault.
Kur ju shkruani një funksion gjithkund rekursive dhe kjo recurses shumë herë
dhe rafte juaj rritet shumë e madhe dhe përplaset rafte në gjërat
se ajo nuk duhet të përplasen me të, ju jeni prekur kujtesën që ju nuk duhet të jetë prekur,
kështu që ju segfault.
Kjo është ajo që një segfault është.
>> Kjo është edhe arsyeja njëjtë se në qoftë se ju keni një varg si -
le të kthehemi në programin e mëparshëm.
Në hello.c--Jam vetëm do të bëjë diçka tjetër.
char * s = "Hello World!";
Nëse unë përdorni * s = diçka ose s [0] = 'X';
prandaj sigurohuni hello,. / hello, pse se segfault?
Pse kjo segfault?
Çfarë do të presin që të ndodhë?
Nëse unë e bëri printf ("% s \ n", s); çfarë do të presin që të jenë të shtypura?
[Student] X hello. Po >>.
Problemi është se kur ju të deklarojë një varg si kjo,
s është një tregues që do të shkojë në rafte,
dhe çfarë s është treguar është ky varg që përmbahet në read-only kujtesës.
Pra, vetëm nga emri, read-only kujtesës, ju duhet të merrni ide
se në qoftë se ju provoni për të ndryshuar atë që është në read-only kujtesës,
ju jeni duke bërë diçka që ju nuk duhet të jetë bërë me kujtesën dhe ju segfault.
Kjo është në fakt një dallim i madh në mes të char * ve dhe char S [].
Pra, char s [], tani ky varg do të jetë vënë në rafte,
dhe rafte nuk është read-only, që do të thotë se kjo duhet të punojnë të përkryer gjobë.
Dhe kjo e bën.
Mos harroni se kur bëj char * s = "Hello World!", S vetvete është në rafte
por s pikë për diku tjetër, dhe se diku tjetër ndodh të jetë read-only.
Por char s [] është vetëm diçka në rafte.
Pra, kjo është një tjetër shembull i një segfault ndodh.
>> Ne pamë se ./buggy1 rezultoi në një segfault.
Në teori, ju nuk duhet të shikoni në buggy1.c menjëherë.
Në vend të kësaj, ne do të shikojmë në atë nëpërmjet GDB.
Vini re se kur ju merrni faj segmentimit (core hedhur),
ju merrni këtë skedë mbi thelbin e quajtur këtu.
Nëse ne ls-l, ne do të shohim se thelbi është zakonisht një file goxha i madh.
Ky është numri i bytes të file, kështu që duket si ajo e 250-diçka kilobytes.
Arsyeja për këtë është se çfarë në fakt është thelbi hale
është kur crashes programin tuaj, shteti i kujtim të programit tuaj
vetëm merr kopjohet dhe të ngjit në këtë file.
Ajo merr hedhur në atë dosje.
Ky program, ndërsa ajo ishte duke ecur, ka ndodhur që të ketë një përdorim memorie prej rreth 250 kilobytes,
dhe kështu kjo është ajo që u hedhur në këtë file.
Tani ju mund të shikoni në atë dosje në qoftë se ne bëjmë Gdb thelbin buggy1.
Ne vetëm mund të bëjmë gdb buggy1, dhe se do të fillojë vetëm deri gdb rregullisht,
buggy1 përdorur si file saj input.
Por në qoftë se ju bëni Gdb thelbin buggy1, atëherë kjo është në mënyrë specifike do të fillojnë deri gdb
duke shikuar në atë dosje core.
Dhe ju thënë buggy1 gdb do të thotë që e di se dosja kryesor vjen nga programi buggy1.
Pra gdb buggy1 core do të na sjellë menjëherë
ku programi ka ndodhur të përfundojë.
Ne shohim këtu Programi i ndërprerë me sinjal 11, faji segmentimit.
Ne të ndodhë për të parë një linjë e asamblesë, e cila ndoshta nuk është shumë e dobishme.
Por në qoftë se ju shkruani ose backtrace BT, që do të jetë funksioni
që na jep listën e kornizave tona rafte aktuale.
Pra backtrace. Ajo duket si ne kemi vetëm dy korniza rafte.
E para është korniza kryesore tonë rafte,
dhe e dyta është korniza rafte për këtë funksion që ne të ndodhë të jetë në,
e cila duket si ne kemi vetëm kodin kuvendit për të.
Pra, le të kthehemi në funksion tonë kryesor,
dhe për të bërë që ne mund të bëjmë kornizë 1, dhe unë mendoj se ne mund të bëjmë poshtë,
por unë kurrë nuk pothuajse të bëni poshtë - ose lart. Po.
Lart dhe poshtë. Deri ju sjell deri një kornizë rafte, poshtë ju sjell poshtë një kornizë rafte.
Unë kurrë nuk kanë tendencë për të përdorur këtë.
Unë vetëm të them konkretisht kornizë 1, e cila është të shkoni në kuadër emërtuar 1.
Frame 1 do të na çojë në kuadër rafte kryesore,
dhe ai thotë se këtu linjë e kodit ne të ndodhë të jetë në.
Nëse ne dëshirojmë linjat një çift shumë të kodit, ne mund të themi listë,
dhe kjo do të na japë të gjitha linjat e kodit rreth saj.
Vija ne segfaulted në ishte 6:
në qoftë se (strcmp ("CS50 shkëmbinj", argv [1]) == 0).
Nëse kjo nuk është e qartë ende, ju mund të merrni atë të drejtë nga këtu vetëm duke menduar pse ajo segfaulted.
Por ne mund të marrë atë një hap më tej dhe të thonë: "Pse do argv [1] segfault?"
Print le argv [1], dhe kjo duket si ajo e 0x0, e cila është tregues null.
Ne jemi strcmping CS50 gurë dhe të pavlefshme, dhe kështu që do të segfault.
Dhe pse është argv [1] null?
[Student] Sepse ne nuk jepte asnjë komandë-line argumente.
Po. Ne nuk japim asnjë komandë-line argumente.
Pra ./buggy1 është vetëm do të ketë argv [0] ./buggy1 jetë.
Kjo nuk do të ketë një argv [1], në mënyrë që do të segfault.
Por në qoftë se, në vend të kësaj, unë bëj vetëm CS50, kjo do të thotë që ju të merrni një D
sepse kjo është ajo që është menduar për të bërë.
Kërkuar në buggy1.c, ajo është menduar për të shtypur "Ju merrni një D" -
Nëse argv [1] nuk është "CS50 gurë", "Ju merrni një d", tjetër "Ju merrni një A!"
Pra, nëse ne duam një A, ne kemi nevojë për të krahasuar këtë si të vërtetë,
që do të thotë se ajo krahasohet me 0.
Pra, argv [1] duhet të jenë "CS50 shkëmbinj".
Nëse ju doni të bëni që në rreshtin e komandave, ju duhet të përdorni \ për të shpëtuar hapësirë.
Pra CS50 \ shkëmbinj dhe ju merrni një A!
Nëse ju nuk bëni backslash, pse nuk është kjo punë?
[Student] Kjo është dy argumente të ndryshme. Po >>.
Argv [1] do të jetë CS50, dhe argv [2] do të jetë shkëmbinj. Rregull.
>> Tani ./buggy2 do të segfault përsëri.
Në vend të hapjes me dosjen e tij kryesor, ne vetëm do të hapur deri buggy2 direkt,
kështu GDB buggy2.
Tani në qoftë se ne vetëm të drejtuar programin tonë, atëherë ajo do të thotë Programi ka marrë sinjal SIGSEGV,
cila është segfault sinjal, dhe ky është vendi ku ajo ndodhi të ndodhë.
Kërkim në backtrace tonë, shohim se ne kemi qenë në oh_no funksion,
e cila u quajt nga hollë funksion, e cila u quajt nga Binky funksion,
e cila u quajt nga kryesore.
Ne gjithashtu mund të shihni argumentet për këto funksione.
Argumenti për hollë dhe Binky ishte 1.
Nëse ne lista oh_no funksion, ne shohim se oh_no është vetëm duke bërë char ** S = NULL;
* S = "BOOM";
Pse do që të dështojnë?
[Student] Ju nuk mund të dereference në treguesin null? Po >>.
Kjo është vetëm duke thënë s është NULL, pavarësisht nëse kjo ndodh të jetë një char **,
të cilat, në varësi se si ju interpretoni atë, ajo mund të jetë një tregues për një tregues për një varg
ose një grup i vargjet.
Kjo është s është NULL, kështu që * s është një tregues dereferencing null,
dhe kështu që kjo do të rrëzuar.
Kjo është një nga mënyrat e shpejtë që ju ndoshta mund të segfault.
Kjo është vetëm një tregues shpalljen e pavlefshme dhe menjëherë segfaulting.
Kjo është ajo që oh_no është duke bërë.
Nëse ne do të shkojmë deri në një kornizë, atëherë ne jemi duke shkuar për të marrë në funksion që quhet oh_no.
Unë kam nevojë për të bërë këtë poshtë.
Nëse ju nuk hyjnë në një komandë dhe ju vetëm hit Enter përsëri,
ai thjesht do të përsërisë komandën e mëparshme që ju u zhvillua.
Ne jemi në kuadër 1.
Renditur këtë kuadër, ne shohim këtu është funksioni ynë.
Ju mund të goditur listën përsëri, ose ju mund të bëni listën e 20 dhe kjo listë do më shumë.
The hollë Funksioni thotë se në qoftë se unë është 1, atëherë shkoni në funksion oh_no,
tjetër të shkojë në funksion slinky.
Dhe ne e dimë se i është 1 sepse ne të ndodhë të shohim deri këtu
që u quajt hollë me argumentin 1.
Ose ju mund vetëm të shtypura nuk i dhe kjo do të thotë unë është 1.
Ne jemi aktualisht në hollë, dhe në qoftë se ne do të shkojmë deri në një kornizë, ne e dimë që ne do të përfundojë deri në Binky.
Deri. Tani ne jemi në Binky.
Renditur këtë funksion - lista para gjysmë prerë me jashtë -
ai filloi si në qoftë se unë është 0, atëherë ne jemi duke shkuar për të thirrur atë oh_no, tjetër thirrje hollë.
Ne e dimë se i ishte 1, kështu që ai e quajti hollë.
Dhe tani ne jemi kthyer në kryesore, dhe kryesore është vetëm do të jetë int i = rand ()% 3;
Kjo është vetëm do të ju jap një numër të rastit që është ose 0, 1, ose 2.
Ajo do të thërrasë Binky me atë numër, dhe ajo do të kthehet 0.
Duke kërkuar në këtë,
vetëm në këmbë përmes programit dorë pa drejtimin atë menjëherë,
ju do të caktojë një pikë pushim në kryesor, që do të thotë se kur ne të drejtuar programin
programi juaj shkon deri ajo hits një pikë pushim.
Pra drejtimin e programit, ajo do të kandidojë dhe pastaj ajo do të goditur funksionin kryesor dhe të ndaluar drejtimin.
Tani ne jemi në brendësi të kryesor, dhe hapi i ardhshëm është ose do të na sjellë në linjë tjetër të kodit.
Ju mund të bëni hapin apo tjetër.
Goditur tjetër, tani i është caktuar që të rand ()% 3, kështu që ne mund të shtypura vlerën e I,
dhe kjo do të thotë unë është 1.
Tani ajo ka rëndësi nëse ne përdorim tjetër ose hap.
Unë mendoj se rëndësi në një të kaluar, por ne do të dëshironi të përdorni ardhshëm.
Nëse ne përdorim hap, ne hap në funksion, që do të thotë vështrim në gjë e vërtetë
që po ndodh brenda Binky.
Nëse ne përdorim tjetër, atëherë kjo do të thotë të shkojë mbi funksionin
dhe vetëm të shkojnë në vijën e ardhshme të kodit në funksion tonë kryesore.
Të drejtë këtu në këtë linjë, unë kam qenë në ku ai tha rand ()% 3;
në qoftë se kam bërë hap, ajo do të shkojë në zbatimin e rand
dhe të shohim se çfarë po ndodh atje, dhe unë mund të hap nëpërmjet funksionit rand.
Por unë nuk e kujdesit në lidhje me funksionin e rand.
Unë vetëm dua të shkojë në rreshtin tjetër të kodit në kryesore, kështu që unë të përdorni të ardhshëm.
Por tani unë bëj kujdes në lidhje me funksionin Binky, kështu që unë dua që të hap në atë.
Tani unë jam në Binky.
Rreshtin e parë të kodit do të thotë në qoftë se (i == 0), kam marrë një hap,
ne shohim ne fund deri në hollë.
Nëse gjërat ne lista, ne shohim se ajo është e kontrolluar i = 0.
Unë nuk është e barabartë me 0, kështu që ai shkoi në gjendjen tjetër,
cila do te thirrje avdall (I).
Ju mund të merrni hutuar.
Nëse ju vetëm shikoni në këto linja direkt, ju mund të mendoni se në qoftë se (i == 0),
në rregull, atëherë unë mori një hap dhe tani unë jam në hollë (i),
ju mund të mendoni se duhet të thotë i = 0 ose diçka.
Nr Kjo thjesht do të thotë se ai e di se mund të rrinë direkt në linjë hollë (i).
Sepse unë nuk është 0, hapi tjetër nuk do të përfundojë në tjetër.
Tjetër nuk është një vijë ajo do të ndalet në.
Është vetëm do të shkojnë në vijën e ardhshëm ajo mund të ekzekutojë në fakt, i cili është i hollë (i).
Shkallaret në avdall (I), ne shih nëse (I == 1).
Ne e dimë i = 1, kështu që kur ne hap, ne e dimë që ne jemi duke shkuar për t'i dhënë fund deri në oh_no
sepse i = 1 quan oh_no funksion, të cilat ju mund të futemi në,
e cila do të vendosë char ** s = Për të pavlefshme dhe menjëherë "BOOM".
Dhe pastaj në të vërtetë duke kërkuar në zbatimin e buggy2,
këtë, i është vetëm duke marrë një numër të rastësishme - 0, 1, ose 2 - thirrja Binky,
të cilat nëse i është 0 ajo e quan oh_no, tjetër ajo e quan hollë, e cila vjen deri këtu.
Në qoftë se i është 1, thirrje oh_no, tjetër thirrje slinky, që vjen deri këtu,
në qoftë se i është 2, thirrje oh_no.
Unë nuk mendoj se edhe ka një mënyrë -
A ka dikush parë një mënyrë për të bërë këtë një program që nuk do segfault?
Sepse nëse unë jam i humbur diçka, në qoftë se i është 0, ju menjëherë do të segfault,
tjetër që ju të shkoni në një funksion që është në qoftë se unë ju segfault 1,
tjetër që ju të shkoni në një funksion ku është në qoftë se unë ju segfault 2.
Pra, pa marrë parasysh atë që ju bëni, ju segfault.
>> I guess një mënyrë për të ndreqim ajo do të jetë në vend të bërë char ** S = NULL,
ju mund të malloc hapësirë ​​për atë varg.
Ne mund të bëjmë malloc (sizeof) - sizeof çfarë?
[Student] (char) * 5? A ka kjo të duket >> drejtë?
Unë jam duke supozuar se kjo do të funksionojë në qoftë se unë në fakt u zhvillua atë, por kjo nuk është ajo që unë jam duke kërkuar për të.
Shikoni në llojin e s. Le të shtoni * int, int * x kështu.
Unë do të bëjë malloc (sizeof (int)).
Ose në qoftë se unë të kërkuar një grup prej 5, unë do të bëj (sizeof (int) * 5);
Çka nëse unë kam një int **?
Çfarë do që unë malloc?
[Studenti] Madhësia e pointer. Po >>. (Sizeof (int *));
E njëjta gjë këtu poshtë.
Unë dua (sizeof (char *));
Kjo do të ndajë hapësirën për treguesin që tregon për "bum".
Unë nuk kam nevojë për të ndarë hapësirën për "bum" vetë
sepse kjo është në thelb ekuivalente me atë që kam thënë më parë
i char * x = "BOOM".
"BOOM" tashmë ekziston. Kjo ndodh për të ekzistojnë në rajonin e read-only kujtesës.
Por ajo tashmë ekziston, që do të thotë këtë linjë të kodit, në qoftë se s është një char **,
pastaj * s * char është një dhe ju jeni të vendosur këtë char * për pikë në "bum".
Nëse kam kërkuar për të kopje "bum" në ve, atëherë unë do të duhet të ndajë hapësirë ​​për s.
Unë do të bëj * s = malloc (sizeof (char) * 5);
Pse 5?
Pse nuk 4? Ajo duket si "bum" është 4 karaktere. >> [Student] Karakteri null.
Po. Të gjitha vargjet tuaja do të duhet karakterin null.
Tani unë mund të bëjë diçka si strcat - Cili është funksioni për kopjim një varg?
[Student] PKJ-ja? Strcpy >>.
strcpy njeri.
Pra strcpy ose strncpy.
strncpy është pak të sigurt që ju mund të përcaktojë saktësisht se sa shumë karaktere,
por këtu nuk ka rëndësi, sepse ne e dimë.
Pra strcpy dhe do të shikojnë në argumente.
Argumenti i parë është destinacioni ynë.
Argumenti i dytë është burimi ynë.
Ne jemi duke shkuar për të kopjuar në * tonë destinacion s treguesin "BOOM".
Pse mund të ju doni të bëni këtë me një strcpy në vend të vetëm atë që kemi pasur më parë
nga * S = "BOOM"?
Ka një arsye që ju mund të dëshironi të bëni këtë, por çfarë është kjo arsye?
[Student] Nëse ju doni të ndryshojë diçka në "bum". Po >>.
Tani unë mund të bëjë diçka si s [0] = 'X';
sepse pika s të tog dhe këtë hapësirë ​​në grumbull që s është treguar
është një tregues për më shumë hapësirë ​​në tog, e cila është ruajtja "bum".
Kështu që kjo kopje e "bum" është duke u ruajtur në tog.
Nuk janë teknikisht dy kopje të "bum" në programin tonë.
Ka pari që është dhënë vetëm nga kjo konstante "bum" string,
dhe kopja e dytë e "bum", strcpy krijuar kopje të "bum".
Por kopje e "bum" është duke u ruajtur në grumbull, dhe tog ju jeni të lirë për të ndryshuar.
Tog nuk është read-only, kështu që do të thotë se s [0]
do të ju lejojnë të ndryshojë vlerën e "bum".
Kjo do të ju lejojnë të ndryshojë ato karaktere.
>> Pyetje?
Rregull.
>> Lëvizja për buggy3, buggy3 Gdb le.
Ne vetëm drejtuar atë dhe ne e shohim ne të merrni një segfault.
Nëse ne backtrace, ka vetëm dy funksione.
Nëse ne do të shkojmë deri në funksionin tonë kryesor, ne shohim se ne segfaulted në këtë linjë.
Pra, vetëm duke kërkuar në këtë linjë, për (i int = 0; linjë fgets kjo stuff nuk null barabartë;
Linja + +).
Kornizë tona mëparshme u quajt _IO_fgets.
Ju do të shihni se shumë me ndërtuar në funksionet C,
se kur ju merrni segfault, nuk do të jetë me të vërtetë emrat e fshehta funksion
si kjo _IO_fgets.
Por kjo do të lidhen me këtë thirrje fgets.
Diku brenda këtu, ne jemi segfaulting.
Nëse ne shikojmë në argumente të fgets, ne mund të shtypura tampon.
Le të shtypura si një - Oh, jo.
Shtyp nuk do të punojë pikërisht si unë dua që ajo të.
Le të shikojmë në programin aktual.
Buffer është një grup karakter. Është një grup karakterin e 128 karaktereve.
Kështu që kur unë them tampon të shtypura, ajo do të shtypura ato 128 karaktere,
e cila unë mendoj se është ajo që pritet.
Ajo që unë isha duke kërkuar për të është shtypur adresën e tampon,
por kjo nuk ka të vërtetë më thoni shumë.
Pra, kur Unë të ndodhë për të thënë deri këtu tampon x, ajo tregon mua 0xbffff090,
të cilat, në qoftë se ju mbani mend nga herët ose disa pika, Oxbffff tenton të jetë një pirg-ish rajonit.
Rafte tenton të fillojë diku vetëm nën 0xc000.
Vetëm duke parë këtë adresë, unë e di se tampon po ndodh në rafte.
Rifillimi programin tim, e drejtuar, deri, tampon pamë ishte kjo sekuence e karaktere
që janë shumë e shumë të pakuptimta.
Pastaj shtypjen fotografi, e çfarë do të duken si fotografi?
[Student] null. Po >>.
File është një nga FILE * tipit, kështu që është një tregues,
dhe vlera e atij tregues është i pavlefshëm.
Pra fgets do të përpiqen për të lexuar nga ajo treguesin në një mënyrë të tërthortë,
por në mënyrë për të hyrë në këtë tregues, ajo ka për të dereference atë.
Ose, në mënyrë për të hyrë në atë që duhet të jetë treguar për të, ajo dereferences atë.
Pra, kjo është një tregues null dereferencing dhe ajo segfaults.
Unë mund të ketë rifilluar atë atje.
Nëse ne të thyer në pikën tonë kryesore dhe të drejtuar,
rreshtin e parë të kodit është char * filename = "nonexistent.txt";
Që duhet të japë një aluzion goxha i madh se pse ky program dështon.
Typing tjetër sjell mua në linjë tjetër, kur kam hapur këtë skedar,
dhe pastaj unë menjëherë të marrë në linjë tonë, ku dikur kam goditur tjetër, ajo do të segfault.
A ka dikush duan të hedhin një arsye pse ne mund të segfaulting?
[Student] File nuk ekziston. Po >>.
Kjo është menduar të jetë një aluzion
se sa herë ju jeni të hapur një skedar ju duhet të kontrolloni se file në fakt ekziston.
Kështu që këtu, "nonexistent.txt";
Kur ne filename fopen për lexim, ne atëherë duhet të them
në qoftë se (== NULL fotografi) dhe thonë printf ("File nuk ekziston!"
ose - më mirë akoma - filename); kthim 1;
Deri tani ne kontrolloni për të parë nëse ajo është NULL
para se të vërtetë duke vazhduar dhe duke u përpjekur për të lexuar nga ajo dosje.
Ne mund të ribëjë atë vetëm për të parë se që punon.
Unë për qëllim të përfshijë një linjë të re.
Deri tani nonexistent.txt nuk ekziston.
Ju duhet të kontrolloni gjithmonë për këtë lloj gjë.
Ju gjithmonë duhet të kontrolloni për të parë nëse fopen kthen null.
Ju duhet të kontrolloni gjithmonë për t'u siguruar se nuk ka kthim malloc NULL,
ose tjetër ju segfault.
>> Tani buggy4.c.
Running. Unë jam guessing kjo është duke pritur për të dhëna ose looping ndoshta pafund.
Po, kjo është looping pafund.
Pra buggy4. Ajo duket si ne jemi looping pafund.
Ne mund të shpërthejë në kryesore, të drejtuar programin tonë.
Në GDB, për aq kohë sa ju përdorni shkurtesa është qartë
ose shkurtesat e veçanta që ata ofrojnë për ju,
atëherë ju mund të përdorni për të përdorur n ardhshëm në vend që të shkruani nga tjetër gjatë gjithë rrugës.
Dhe tani që unë kam goditur n herë, unë mund vetëm të goditur Enter për të do të mbajë ardhshëm
në vend që të goditur n Enter, n Enter, n Enter.
Ajo duket si unë jam në një lloj për lak që është vendosjen array [i] me 0.
Ajo duket si unë kurrë nuk jam thyer nga kjo për lak.
Nëse unë të shtypura i, kështu që i është 2, atëherë unë do të shkoj e ardhshëm.
Unë do të shtypura unë, është 3, atëherë unë do të shkoj e ardhshëm.
Unë do të shtypura dhe unë i është 3. Tjetra, shkruar unë, është 4.
Në fakt, të shtypura sizeof (array), kështu që madhësia e array është 20.
Por duket sikur ka disa komanda të veçanta gdb për të shkuar derisa diçka ndodh.
Është si një kusht për vendosjen e vlerës së ndryshueshme. Por unë nuk e mbani mend se çfarë është ajo.
Pra, nëse ne do të mbajë -
Çfarë po thua? Çfarë keni sjellë deri?
[Student] A i shfaqur add - >> yeah. Kështu që unë mund të të ndihmojë shfaqur.
Nëse ne vetëm i ekranit, ajo do të vënë këtu atë që unë është vlera e
kështu që unë nuk duhet të shtypura it out çdo kohë.
Nëse ne vetëm mbajtur shkon tej, ne shih 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5.
Diçka po shkon tmerrësisht keq, dhe unë po vë në 0.
Kërkuar në buggy4.c, ne shohim të gjitha që ndodh është int array [5];
për (i = 0; I <= sizeof (array); I + +)
array [i] = 0;
Çfarë ne shohim se është e gabuar këtu?
Si një aluzion, kur unë isha duke bërë gdb buggy4 - le të thyejnë kryesore, drejtuar -
Unë kam shkruar sizeof (array) vetëm për të parë se çfarë kushti është vendi ku unë duhet në fund shpërthen.
Ku jam unë? Nuk kam drejtuar?
Unë nuk e kanë deklaruar ende.
Pra, të shtypura sizeof (array) dhe kjo është 20,
e cila pritet që array im është i madhësisë 5 dhe kjo është 5 yje të integers,
kështu që gjëja e tërë duhet të jetë 5 * sizeof (int), ku bytes sizeof (int) ka tendencë të jetë 4.
Pra, sizeof (array) është 20.
Çfarë duhet të jetë kjo?
[Student] Ndarë nga sizeof (int). >> Yeah, / sizeof (int).
Ajo duket sikur nuk ka ende një problem këtu. Unë mendoj se kjo duhet të jetë vetëm <
pasi kjo është shumë e shumë të gjithmonë <asnjëherë dhe <=.
Tani le të mendojmë se pse ky fakt ishte thyer.
Does anyone kanë supozime pse ishte i rivendosur në 0 nëpër çdo ripërsëritje e lak?
E vetmja gjë brenda e këtu se po ndodh është se array [i] është duke u vendosur në 0.
Kështu disi, kjo linjë e kodit është duke shkaktuar int tonë i të vendosur për të 0.
[Student] Mund të jetë për shkak se ajo është thelbësore kujtimin e kësaj pjese të I
kur ajo mendon se është elementi tjetër të grup? >> [Bowden] Po.
Kur ne jemi duke shkuar përtej fund të array tonë,
disi se hapësira që ne jemi mbizotërues është thelbësore në vlerën e i.
Dhe kështu nëse ne shikojmë në buggy4, thyejnë kryesor, afat,
le të shtypura në adresën e i.
Ajo duket si kjo është bffff124.
Tani le të shtypur adresën e array [0]. 110.
Po në lidhje me [1]? 114.
[2], 118.
11c, 120. array [5] është bfff124.
Pra, array [5] ka të njëjtën adresë si unë, që do të thotë se array [5] është i.
Në qoftë se ata kanë të njëjtën adresë, ata janë e njëjta gjë.
Pra, kur ne kemi vendosur koleksion [5] në 0, ne jemi të vendosur për të i 0.
Dhe në qoftë se ju mendoni rreth kësaj në aspektin e rafte,
int i është shpallur të parë, që do të thotë i merr disa hapësirë ​​në rafte.
Pastaj array [5] është ndarë, kështu që pas 20 bytes janë ndarë në rafte.
Pra, i merr ndahen parë, atëherë këto 20 bytes merrni ndarë.
Kështu që i ndodh e drejtë para array,
dhe për shkak të rrugës, si i tha javën e kaluar, ku teknikisht rafte rritet poshtë,
kur ju indeksi në një grup, ne jemi të garantuar se qëndrimi 0 në rrjet
ndodh gjithmonë përpara vendin e parë në grup.
Kjo është lloj i si unë tërhoqi atë javën e kaluar.
Vini re se në fund ne kemi adresën dhe 0 në krye kemi Max adresave.
Rafte është gjithmonë në rritje poshtë.
Le të themi se i ndajë.
Ne ndajë integer i, që do të thotë le të them vetëm deri këtu integer i merr ndarë.
Pastaj ne ndajë koleksion tonë prej 5 integers, që do të thotë se nën cilat,
pasi rafte po rritet poshtë, ato 5 integers merrni ndarë.
Por për shkak të asaj se si punojnë vargjeve, ne jemi të garantuar se pozita e parë në grup
gjithmonë ka një adresë më pak se gjëja e dytë në grup.
Pra, pozita array 0 gjithmonë duhet të ndodhë e parë në kujtesë,
ndërsa pozita array 1 duhet të ndodhë pas kësaj
dhe pozita array 2 duhet të ndodhë pas kësaj,
që do të thotë se pozicioni array 0 do të ndodhë diku poshtë këtu,
Pozita array 1 do të ndodhë më lart se
sepse do të thotë duke shkuar deri adresa larta që adresa maksimale është deri këtu.
Pra, array [0] këtu poshtë, array [1] deri këtu, array [2] deri këtu, array [3] deri këtu.
Vini re se si para se të ndahen integer i të gjithë rrugën deri këtu,
si ne shkojmë më tej dhe më tej në grup tonë, ne jemi duke marrë më afër dhe më afër numër të plotë tonë i.
Kjo ndodh pikërisht kështu që Array [5], që është një pozicion përtej array tonë,
është pikërisht aty ku integer i ka ndodhur që të ndahen.
Pra, kjo është pika ku ne të ndodhë të jetë goditur hapësirë ​​në rafte
që është ndarë për integer i, dhe ne jemi të vendosur që të 0.
>> Kjo është se si funksionon. Pyetje? Po.
[Student] Never mind. Rregull.
[Student] Si mund të ju shmangur këto lloj gabime?
Këto lloj gabime? Mos përdorni C, si gjuhën tuaj programimit.
Përdorni një gjuhë që ka kufijtë array kontrolluar.
Për sa kohë që ju jeni të kujdesshëm, ju vetëm duhet për të shmangur duke shkuar kaluar kufijtë e array tuaj.
[Student] Pra, këtu, kur kemi shkuar kaluar kufijtë e array tuaj -
[Bowden] Kjo është ajo ku gjërat fillojnë të shkojnë keq. >> [Student] Oh, në rregull.
Për sa kohë që ju të qëndroni brenda kujtesës ndarë për grup tuaj, ju jeni të mirë.
Por C nuk i bën kontrollin gabimi. Nëse unë bëj koleksion [1000], ajo me kënaqësi do të ndryshojë çfarëdo që të ndodhë vetëm -
Ai shkon në fillim të array, atëherë ajo shkon 1000 poste pas dhe vendos atë në 0.
Ajo nuk ka të bëjë asnjë kontrolluar se oh, kjo nuk ka të vërtetë kanë gjërat në atë 1000.
1000 është rruga përtej asaj që unë duhet të ndryshuar,
kurse Java apo diçka që ju do të merrni rrjet nga indeksi kufijtë
ose indeksin jashtë caqeve përjashtim.
Kjo është arsyeja pse shumë gjuhë të nivelit të lartë kanë këto gjëra
ku në qoftë se ju shkoni përtej kufijve të vektorit, ju nuk
kështu që ju nuk mund të ndryshojë gjërat nga poshtë jush
dhe pastaj gjërat shkojnë shumë më keq se vetëm duke u një përjashtim
duke thënë se ju shkoi përtej përfundimit të vektorit.
[Student] Dhe kështu duhet të kemi ndryshuar vetëm <= të vetëm <? >> [Bowden] Yeah.
Ajo duhet të jetë <sizeof (array) / sizeof (int);
prej sizeof (array) është 20, por ne duam vetëm 5. >> [Student] E drejta.
Më shumë pyetje? Rregull.
>> [Student] Unë kam një pyetje. Po >>.
[Student] Çfarë është e ndryshueshme aktuale array?
[Bowden] Ashtu si çfarë është grup?
Array vetvete është një simbol.
Ajo është vetëm adresa e fillimit të 20 bytes se ne jemi referenca.
Ju mund të mendoni për atë si një tregues, por kjo është një tregues konstant.
Sa më shpejt që të merrni gjëra të hartuar, array ndryshueshme nuk ekziston më.
[Student] Pra, si e bën atë të gjetur madhësinë e grup?
Madhësia e array referohet madhësinë e atij bllokut se ky simbol i referohet.
Kur unë bëj diçka si printf ("% f \ n", array);
le të drejtuar atë.
Çfarë unë vetëm bëj gabim?
'Array' Array deklaruar këtu.
Oh, deri këtu.
Tingëllimë është zgjuar, dhe kjo ndodh të konstatoj se unë e shpalli si grup 5 elemente
por unë jam në pozitë indeksimin 1000.
Ajo mund ta bëjë këtë për shkak se këto janë vetëm konstante.
Ajo vetëm mund të shkojnë aq larg në vërejtur që unë jam duke shkuar përtej kufijve të vektorit.
Por, para se të vini re, kur ne kishim të jetë i gabuar,
ajo nuk mund të përcaktojë se sa vlerat që unë mund të marrë në,
kështu që nuk mund të përcaktojë se i ishte duke shkuar përtej përfundimit të vektorit.
Kjo është vetëm tingëllimë qenë zgjuar.
>> Por tani të bëjë buggy4. Pra, çfarë tjetër po bëj keq?
Implicite deklaruar Funksioni Biblioteka "printf '.
Unë jam duke shkuar për të duan të përfshijnë # .
Rregull. Tani drejtimin buggy4.
Shtypjen e vlerës së array si kam bërë këtu, shtypjen atë si një tregues
printime diçka që duket si ky - bfb8805c - e cila është disa adresa
që është në rajonin e ish-rafte.
Array vetë është si një tregues, por kjo nuk është një akrep aktuale,
pasi një tregues rregullt ne mund të ndryshojmë.
Array është vetëm disa konstante. Të 20 blloqet e kujtesës fillojë në 0xbfb8805c adresave.
Pra bfb8805c nëpërmjet këtë adresë +20--ose I guess -20 -
është e gjitha e kujtesës ndarë për këtë koleksion.
Array, e ndryshueshme në vetvete nuk është ruajtur kudo.
Kur ju jeni hartimin, përpiluesit - Vala dorë në atë -
por përpilues do të përdorin vetëm kur ai e di array të jetë.
Ai e di se ku fillon array,
dhe kështu ajo gjithmonë mund të bëjë vetëm gjërat në drejtim të offsets nga ajo fillimi.
Ajo nuk ka nevojë për një ndryshore vetë për të përfaqësuar grup.
Por kur bëj diçka si int * p = array, tani p është një tregues që tregon në atë grup,
dhe tani p fakt nuk ekziston në rafte.
Unë jam i lirë të ndryshojë p. Unë mund të bëj p = malloc.
Pra, ajo fillimisht vuri në grup, tani ajo tregon për një hapësirë ​​në tog.
Unë nuk mund ta bëjë array malloc =.
Nëse tingëllimë është i mençur, ai do të bërtas në mua të drejtën off bat.
Në fakt, unë jam goxha i sigurt gcc do të bëjë këtë shumë.
Pra, lloji array 'int [5]' nuk është tjetërsohet.
Ju nuk mund të caktojë një lloj diçka për të array
sepse array është vetëm një konstante.
Ajo është një simbol i cili referencat ato 20 bytes. Unë nuk mund ta ndryshojë atë.
>> [Student] Dhe ku është madhësia e array ruajtur?
[Bowden] Kjo nuk është ruajtur kudo. Kjo është kur është e përpilimit.
Pra, ku është madhësia e array ruajtur?
Ju mund të përdorni vetëm sizeof (array) brenda funksionit që array është deklaruar vetë.
Pra, nëse unë bëj një funksion, foo, dhe unë bëj (int array [])
printf ("% d \ n", sizeof (array));
dhe pastaj këtu poshtë unë e quaj foo (array);
brenda këtij funksioni - le të drejtuar atë.
Kjo është tingëllimë të qenit zgjuar përsëri.
Është thënë se në sizeof funksion parametër array
do të kthehen madhësinë e '* int'.
Kjo do të jetë një gabim, nëse kjo nuk është ajo që kam kërkuar të ndodhë.
Le të vërtetë të kthehet off Werror.
Paralajmërim. Paralajmërimet janë të mirë.
Ajo do të vazhdojë të përpilojë për aq kohë sa ajo ka një paralajmërim.
. / A.out do të shtypura 4.
Paralajmërimi që u gjeneruar është një tregues i qartë i çfarë shkoi keq.
Ky grup int është vetëm do të shtypura sizeof (int *).
Edhe në qoftë se kam vënë array [5] në këtu, ai është ende vetëm do të shtypura sizeof (int *).
Pra, sa më shpejt që ju të kalojë atë në një funksion, dallimi midis vargjeve dhe pointers
është që nuk ekzistojnë.
Kjo ndodh të jetë një grup që ishte shpallur në rafte,
por sa më shpejt që ne të kalojë atë vlerë që 0xbf blah, blah, blah në këtë funksion,
atëherë ky tregues tregon për atë grup në rafte.
Kështu që do të thotë se sizeof vlen vetëm në funksion që array ishte deklaruar,
që do të thotë se kur ju jeni hartimin e këtij funksioni,
kur tingëllimë shkon përmes këtij funksioni, ai e sheh array është një grup int i madhësisë 5.
Kështu atëherë ajo sheh sizeof (array). E pra, kjo është 20.
Kjo është në fakt si sizeof thelb punon për pothuajse të gjitha rastet.
Sizeof nuk është një funksion, është një operator.
Ju nuk telefononi funksionin sizeof.
Sizeof (int), përpiluesit vetëm do të përkthehet se për 4.
Got it? Rregull.
>> [Student] Pra, çfarë është dallimi në mes sizeof (array) në kryesore dhe në foo?
Kjo është për shkak se ne jemi duke thënë sizeof (array), e cila është e tipit int *,
ndërsa array poshtë këtu nuk është e tipit int *, është një grup int.
>> [Student] Pra, nëse keni pasur parametër në grup [] në vend të array int *,
do të thotë që ju ende mund të ndryshojë grup sepse tani kjo është një akrep?
[Bowden] Ashtu si kjo? >> [Student] Yeah. Ju mund të ndryshojë koleksion brenda funksionit tani?
[Bowden] Ju mund të ndryshojë rrjet në të dy rastet.
Në të dyja këto raste ju jeni të lirë për të thënë array [4] = 0.
[Student] Por ju mund të bëni pikë array për diçka tjetër?
[Bowden] Oh. Po. Në secilin rast - >> [Student] Yeah.
[Bowden] Dallimi ndërmjet array [] dhe një grup int *, nuk ka asnjë.
Ju gjithashtu mund të merrni disa grup shumëdimensionale në këtu
për disa sintaksë të përshtatshëm, por është ende vetëm një tregues.
Kjo do të thotë se unë jam i lirë të bëj koleksion = malloc (sizeof (int)); dhe tani pikë diku tjetër.
Por ashtu si si ky punon përgjithmonë dhe gjithmonë,
ndryshuar këtë koleksion duke e bërë atë të tregojnë për diçka tjetër
nuk e ndryshojnë këtë koleksion këtu poshtë, sepse kjo është një kopje e argumentit,
kjo nuk është një tregues për atë argument.
Dhe në fakt, ashtu si tregues më shumë se ajo është saktësisht e njëjtë -
ne tashmë pamë se çfarë printime array shtypi -
çka nëse kemi shkruar adresën e grup ose adresën e adresën e grup
për njërin prej atyre?
Le të injorojë këtë.
Rregull. Kjo është e mirë. Është tani running. A.out /.
Array shtypjen, atëherë shtypjen adresën e array, janë e njëjta gjë.
Array thjesht nuk ekziston.
Ai e di kur ju jeni shtypjen koleksion, ju jeni shtypjen simbol që i referohen këtyre 20 bytes.
Shtypi adresën e array, mirë, array nuk ekziston.
Ajo nuk ka një adresë, kështu që vetëm shtyp adresën e atyre 20 bytes.
Sa më shpejt që ju të përpilojnë poshtë, si në buggy4 tuaj hartuar. / A.out,
array është që nuk ekzistojnë.
Pointers ekzistojnë. Vargjeve nuk e bëjnë.
Blloqet e kujtesës që përfaqësojnë array ende ekzistojnë,
por array ndryshueshme dhe variablat e atij lloji nuk ekzistojnë.
Ata janë si dallimet kryesore midis vargjeve dhe pointers
janë sa më shpejt që ju të bëni thirrje funksion, nuk ka asnjë ndryshim.
Por brenda funksionit që array vetë është deklaruar, sizeof punon ndryshe
pasi ju jeni shtypjen madhësinë e blloqeve në vend të madhësisë të tipit,
dhe ju nuk mund të ndryshojë atë, sepse ajo është një simbol.
Shtypi gjë dhe adresën e gjë shtyp të njëjtën gjë.
Dhe kjo është shumë e shumë ajo.
[Student] A mund të themi se një herë më shumë?
Unë mund të ketë humbur diçka.
Array Printime dhe adresa e array shtyp të njëjtën gjë,
ndërsa nëse keni shkruar një tregues kundrejt adresën e akrep,
një gjë shtyp adresën e asaj që ju jeni duke treguar,
të tjera shtyp adresën e treguesin në rafte.
Ju mund të ndryshojë një tregues, ju nuk mund të ndryshojë një simbol array.
Dhe treguesin sizeof do të shtypur madhësinë e atij lloji akrep.
So int * sizeof p (p) do të shtypura 4,
por int array [5] print sizeof (array) do të shtypura 20.
[Student] Pra int array [5] do të shtypura 20? Po >>.
Kjo është arsyeja pse në brendësi të buggy4 kur ajo përdoret për të sizeof (array)
kjo ishte bërë i <20, e cila nuk është ajo që kemi dashur.
Ne duam I <5. >> [Student] Okay.
[Bowden] Dhe pastaj sa më shpejt që ju të filloni duke kaluar në funksionet,
në qoftë se ne e bëmë int * p = array;
brenda këtij funksioni, ne thelb mund të përdorni dhe p koleksion pikërisht në të njëjtën mënyrë,
përveç problemit sizeof dhe problemi ndryshon.
Por p [0] = 1; është njëlloj si të thuash array [0] = 1;
Dhe sa më shpejt që ne e themi foo (array), ose foo (p);
brenda funksionit foo, kjo është thirrja e njëjtë dy herë.
Nuk ka dallim në mes këtyre dy telefonatave.
>> Gjithkush e mirë për këtë? Rregull.
Ne kemi 10 minuta.
>> Ne do të përpiqemi për të marrë përmes këtij programi Typer Hacker,
Kjo faqe e internetit, e cila doli vitin e kaluar apo diçka.
Ajo është menduar vetëm për të të jetë si ju shkruani rastësisht dhe printime jashtë -
Çfarëdo fotografi ndodh të ketë ngarkuar është ajo që duket si ju jeni shtypur.
Ajo duket si një lloj të kodit të sistemit operativ.
Kjo është ajo që ne duam të zbatojë.
Ju duhet të keni një ekzekutueshme binary quajtur hacker_typer
që merr në një argument të vetëm, fotografi të "tipit hacker".
Drejtimin e ekzekutueshme duhet të qartë në ekran
dhe pastaj të shtypura nga një karakter nga dosja kaloi-në çdo herë që përdoruesi shtyn një kyç.
Pra, çfarëdo që të shtypni kyç, ajo duhet të hedhin larg dhe në vend të shtypur një karakter nga e dosjes
që është argumenti.
Unë do të shumë e shumë të ju tregojnë se çfarë gjëra ne do të duhet të dini janë.
Por ne duam të shikoni bibliotekën termios.
Unë kurrë nuk kam përdorur këtë bibliotekë në tërë jetën time, kështu që ajo ka qëllime shumë minimale.
Por kjo do të jetë biblioteka ne mund të përdorim për të hedhur larg karakterin që ju goditi
kur ju jeni të shtypni në standardin in
Pra hacker_typer.c, dhe ne jemi duke shkuar për të duan të përfshijnë # .
Looking në faqen njeri për termios - Jam guessing terminal ajo e OS ose diçka -
Unë nuk e di se si të lexuar atë.
Duke kërkuar në këtë, ai thotë se për të përfshirë këto 2 fotografi, kështu që ne do të bëjmë këtë.
>> Gjëja e parë e parë, ne duam të marrë në një argument të vetëm, i cili është fotografi ne duhet të hapur.
Pra, çfarë unë dua të bëj? Si mund të kontrolloni për të parë unë kam një argument të vetëm?
[Student] Nëse argc barabartë me atë. >> [Bowden] Yeah.
Pra, nëse (argc = 2!) Printf ("përdorimi:% s [fotografinë për të hapur]").
Kështu që tani, nëse unë të drejtuar këtë pa dhënë një argument të dytë - oh, kam nevojë për linjë të re -
ju do të shihni se përdorimi thotë:. / hacker_typer,
dhe pastaj Argumenti i dytë duhet të jetë dosja që unë dua të hapur.
Tani çfarë të bëj?
Unë dua për të lexuar nga kjo skedë. Si mund të lexohet nga një skedar?
[Student] Ju hapur atë më parë. Po >>.
Pra fopen. Çfarë do të duken si fopen?
[Student] Emri i dokumentit. >> [Bowden] Emri i dokumentit do të jetë argv [1].
[Student] Dhe atëherë ajo që ju doni të bëni me të, kështu që - >> [Bowden] Yeah.
Pra, nëse ju nuk e mbani mend, ju vetëm mund të bëni fopen njeri,
ku ajo do të jetë një rrugë e const char *, ku rruga është filename,
const char * Mode.
Nëse ju ndodh që të mos mbani mend se çfarë është mënyra, atëherë ju mund të shikoni për mode.
Brenda faqeve njeriu, karakteri slash është ajo që ju mund të përdorni për të kërkuar për gjërat.
Kështu që unë lloj / mënyrë për të kërkuar për mode.
n dhe N janë ato që ju mund të përdorni për të ciklit përmes ndeshjet e kërkimit.
Këtu ajo thotë se pikat analog argument për një varg
filluar me një nga sekuenca në vijim.
Pra r, file teksti Hapur për lexim. Kjo është ajo që ne duam të bëjmë.
Për të lexuar, dhe unë dua për të ruajtur atë.
Gjëja do të jetë një * FILE. Tani çfarë unë dua të bëj?
Më jepni një të dytë.
Rregull. Tani çfarë unë dua të bëj?
[Student] Kontrolloni nëse është e NULL. >> [Bowden] Yeah.
Çdo herë që ju të hapur një skedar, sigurohuni që ju jeni në gjendje për sukses për të hapur atë.
>> Tani unë dua të bëj gjëra që termios ku unë dua që së pari të lexoni vetitë e mia aktuale
dhe për të shpëtuar ata në diçka, atëherë unë dua të ndryshoj vetitë e mia
për të hedhur larg çdo karakter që unë lloji,
dhe pastaj unë dua të rinovuar këto settings.
Dhe pastaj në fund të programit, unë dua të ndryshojë përsëri në parametrat e mia origjinale.
Pra struct do të jetë e tipit termios, dhe unë jam duke shkuar për të duan dy nga ato.
I pari do të jetë current_settings mi,
dhe pastaj ata do të jenë hacker_settings mi.
Së pari, unë jam duke shkuar për të dëshironi të ruani vetitë e mia aktuale,
atëherë unë jam duke shkuar për të duan për të rinovuar hacker_settings,
dhe pastaj rruga në fund të programit tim, unë dua të kthehet në parametrat aktuale.
Pra, duke kursyer cilësimet aktuale, mënyra se si punon, ne termios njeri.
Ne shohim se ne kemi këtë tcsetattr int, int tcgetattr.
Unë të kalojë në një struct termios me treguesin e saj.
Në këtë mënyrë do të duket është - I've harruar tashmë se çfarë funksioni është quajtur.
Kopjoni dhe ngjisni atë.
Pra tcgetattr, atëherë unë dua të kalojë në struct që unë jam duke kursyer informacion në,
cila do të jetë current_settings,
dhe argumenti i parë është përshkrues skedar për gjë unë dua të të shpëtuar atributet e.
Çfarë përshkrues file është është si çdo kohë që ju të hapur një skedar, ajo merr një përshkrues skedar.
Kur unë fopen argv [1], ajo merr një përshkrues skedar që ju jeni referenca
sa herë që ju dëshironi të lexoni apo shkruani atë.
Kjo nuk është përshkrues skedar që unë dua të përdorni këtu.
Ka tre Përshkruesit e dokumentit që ju keni si parazgjedhje,
të cilat janë standarde në, jashtë standardeve, dhe gabimi standard.
By default, unë mendoj se është standard në është 0, nga standardi është 1, dhe gabimi standard është 2.
Pra, çfarë unë dua të ndryshojë parametrat e?
Unë dua të ndryshojë parametrat e sa herë që unë goditi një karakter,
Unë dua që ajo të hedhin atë karakterin larg në vend të shtypjes atë në ekran.
Çfarë lumë - standard në, jashtë standardeve, apo gabimeve standarde -
përgjigjet për gjëra kur unë lloji në tastierë? >> [Student] Standard in >> yeah.
Kështu që unë mund ta bëni 0 ose unë mund të bëjë STDIN.
Unë jam duke marrë current_settings e standardit in
>> Tani unë dua të rinovuar këto settings,
Pra, së pari unë do të kopjoni në hacker_settings atë current_settings mi janë.
Dhe si structs puna është se do të vetëm kopje.
Kjo kopje të gjitha fushat, si ju do të presim.
>> Tani unë dua të rinovuar disa prej fushave.
Kërkuar në termios, ju do të keni për të lexuar përmes një shumë të këtij
vetëm për të parë atë që ju do të dëshironi të shikoni për,
por flamujt që ju jeni do të dëshironi të shikoni për janë jehonë,
kështu ECHO karaktere input Echo.
Së pari unë dua të vendosur - I've harruar tashmë se çfarë fusha janë.
Kjo është ajo që duket si struct.
Pra modes input unë mendoj se ne duam të ndryshojmë.
Ne do të shikojmë në zgjidhje të bëni të sigurtë që është ajo që ne duam të ndryshojmë.
Ne duam të ndryshojmë lflag në mënyrë për të parandaluar që kanë nevojë për të kërkuar nëpër të gjitha këto.
Ne duam të ndryshojë modes lokale.
Ju do të keni për të lexuar nëpër këtë gjë për të kuptuar tërë ku çdo gjë i takon
që ne duam të ndryshojmë.
Por është brenda e modes lokale ku ne do të duan që kjo të ndryshojë.
Pra hacker_settings.cc_lmode është ajo që është quajtur.
c_lflag.
Kjo është ajo ku ne kemi marrë në operatorët bitwise.
Ne jemi lloj i jashtë kohe, por ne do të kalojnë nëpër të shpejtë të vërtetë.
Kjo është ajo ku ne kemi marrë në bitwise operatorëve,
ku unë mendoj se kam thënë një herë kohë më parë se sa herë që ju filloni që kanë të bëjnë me flamujt,
ju jeni do të jetë duke përdorur operatorit bitwise shumë.
Çdo pak në flamurin korrespondon me një lloj të sjelljes.
Kështu që këtu, ky flamur ka një bandë e gjëra të ndryshme, ku të gjithë prej tyre do të thotë diçka të ndryshme.
Por ajo që unë dua të bëj është vetëm të fikur pak që i korrespondon ECHO.
Mënyrë për ta kthyer atë jashtë të bëj & = ¬ ECHO.
Në fakt, unë mendoj se kjo është si tECHO apo diçka. Unë jam vetëm duke shkuar për të kontrolluar përsëri.
Unë mund termios atë. Është vetëm ECHO.
ECHO do të jetë pak e vetme.
¬ ECHO do të thotë të gjitha bit janë të vendosur të 1, që do të thotë të gjithë flamujt janë të vendosur të vërtetë
me përjashtim të pak ECHO.
Duke i dhënë fund flamujt e mia lokale me këtë, kjo do të thotë të gjitha flamujt që janë vendosur aktualisht në vërtetë
do të vazhdojë të jetë e vendosur për të vërtetë.
Nëse flamuri im ECHO është vendosur të vërtetë, atëherë kjo është vendosur domosdoshmërisht të rreme në flamurin ECHO.
Pra, kjo linjë e kodit vetëm fiket flamurin jehonë.
Linjat e tjera të kodit, unë vetëm do të kopjoni ato në interes të kohës dhe pastaj të shpjeguar ato.
Në zgjidhje, tha ai 0.
Kjo është ndoshta më mirë të them në mënyrë eksplicite STDIN.
>> Vini re se unë jam gjithashtu duke bërë jehonë | ICANON këtu.
ICANON referohet diçka të veçantë, që do të thotë regjim kanonike.
Çfarë do të thotë kanonike mode është zakonisht kur ju jeni shtypur nga command line,
standarde në proces nuk asgjë, derisa ju goditi newline.
Kështu që kur ju bëni getString, ju shtypni një bandë e gjëra, atëherë ju goditi newline.
Kjo është kur ajo është dërguar për standardin in
Kjo është paracaktuar.
Kur unë të fikur mënyrë kanonike, tani çdo karakter të vetme që ju shtypni
është ajo merr përpunohet, e cila zakonisht është lloj i keq, sepse kjo është e ngadaltë të procesit këto gjëra,
cila është arsyeja pse ajo është e mirë për të tampon atë në linja të tëra.
Por unë dua çdo karakter të jenë të përpunuara
pasi që unë nuk dua që ajo të prisni për mua për të goditur newline
para se ajo përpunon të gjitha karakteret unë kam qenë shtypur.
Kjo fiket mënyrë kanonike.
Kjo stuff thjesht do të thotë kur ai në fakt përpunon karaktere.
Kjo do të thotë procesin e tyre menjëherë, sa më shpejt që unë jam shtypja e tyre, procesin e tyre.
Dhe ky është funksion i cili është përditësimin vetitë e mia për standarde në,
dhe mjetet TCSA bëjë atë të drejtë tani.
Opsionet e tjera janë të prisni derisa çdo gjë që është aktualisht në lumë është i përpunuar.
Kjo nuk ka rëndësi.
Vetëm tani ndryshoj vetitë e mia që të jetë çdo gjë që është aktualisht në hacker_typer_settings.
I guess I quajtur atë hacker_settings, kështu që le të ndryshojë këtë.
Ndryshojë çdo gjë në hacker_settings.
>> Tani në fund të programit tonë ne do të duan të rikthehen
me atë që është aktualisht në brendësi të normal_settings,
e cila është vetëm do të duken si dhe normal_settings.
Njoftim Unë nuk kam ndryshuar asnjë nga normal_settings mi që fillimisht të marrë atë.
Pastaj të vetëm të ndryshojë ato përsëri, unë të kalojë ato përsëri në fund.
Kjo ishte update. Rregull.
>> Tani brenda këtu unë vetëm do të shpjegojë kodin në interes të kohës.
Kjo nuk është se kodi shumë.
Ne e shohim ne lexojmë një karakter nga file. Ne e thirrëm atë f.
Tani ju mund fgetc njeri, por si fgetc do të punojë
është vetëm ajo do të kthehet në karakter që ju vetëm lexuar ose EOF,
që korrespondon në fund të skedarit apo ndonjë gabim ndodh.
Ne jemi looping, duke vazhduar për të lexuar një karakter të vetme nga dosja,
deri sa ne kemi drejtuar nga personazhet për të lexuar.
Dhe, ndërsa ne jemi duke bërë këtë, ne presim për një karakter të vetëm nga standardi in
Çdo herë që ju shkruani diçka e vetme në command line,
që është lexuar në një karakter nga standardi in
Pastaj putchar është vetëm do të vënë char kemi lexuar deri këtu nga file të jashtë standardeve.
Ju mund putchar njeri, por kjo është vetëm për të vënë standarde nga, ajo shtypje atë karakter.
Ju gjithashtu mund të bëjë vetëm printf ("% c", c); njëjtën ide.
Kjo do të bëjë pjesa më e madhe e punës sonë.
>> Gjëja e fundit që ne do të dëshironi të bëni është vetëm Shkrimi dosjen tonë.
Nëse ju nuk Shkrimi, që është një rrjedhje kujtim.
Ne duam të Shkrimi file ne fillim u hap, dhe unë mendoj se kjo është ajo.
Nëse bëjmë këtë, unë tashmë kam probleme.
Le të shohim.
Çfarë e bëri atë të ankoheni?
Pritej 'int', por argumenti është i tipit 'struct _IO_FILE *'.
Ne do të shohim nëse që punon.
Lejohet vetëm në C99. Augh. Mirë, të bëjë hacker_typer.
Tani kemi përshkrime shumë të dobishme.
Pra, përdorimi i padeklaruar identifikues 'normal_settings'.
Unë nuk e quaj atë normal_settings. Unë e quajti atë current_settings.
Pra, le të ndryshojë të gjithë se.
Tani kalon argument.
Unë do të bëjë këtë tani për tani 0.
Rregull. . / Hacker_typer cp.c.
Unë gjithashtu nuk e qartë në ekran në fillim.
Por ju mund të shikoni përsëri në setin e fundit të problemit për të parë se si ju të qartë në ekran.
Është vetëm shtypjen e disa karaktere
ndërsa kjo është duke bërë atë që unë dua të bëj.
Rregull.
Dhe duke menduar se pse kjo duhet të jetë në vend të 0 STDIN,
të cilat duhet të përcaktojnë # 0,
kjo është ankuar se -
Para se kur kam thënë se nuk ka Përshkruesit fotografi, por pastaj ju gjithashtu keni tuaj * File,
një përshkrues fotografi është vetëm një numër i plotë vetme,
ndërsa një * FILE ka një bandë e tërë e gjëra që lidhen me të.
Arsyeja që ne duhet të them në vend të 0 STDIN
është se është një STDIN * Foto e cila tregon gjë që është referenca përshkrues skedar 0.
Pra, edhe deri këtu, kur unë bëj fopen (argv [1], unë jam duke marrë një * File prapa.
Por diku në atë * skedë është një gjë që korrespondon me descriptor skedar për atë dosje.
Nëse ju shikoni në faqen e njeriut për të hapur, kështu që unë mendoj se ju do të keni për të bërë man 3 e hapur - Jo -
njeri 2 i hapur - yeah.
Nëse ju shikoni në faqen e hapur, e hapur është si një fopen të ulët të nivelit,
dhe është kthyer përshkrues aktuale file.
fopen bën një bandë e stuff në krye të hapur,
e cila në vend që të kthehej vetëm se përshkrues skedar kthehet një skedar * treguesin e tërë
brenda së cilës është përshkrues pak jonë file.
Pra standarde në referohet gjë FILE *,
ndërsa 0 vetëm referohet standardeve të descriptor file në vetvete.
>> Pyetje?
[Qesh] shpërtheu nëpër atë.
Dakord. Ne jemi duke bërë. [Qesh]
>> [CS50.TV]