[Powered by Google Translate] [ODDÍL 5: méně komfortní]
[Nate Hardison, Harvard University]
[To je CS50.] [CS50.TV]
Tak vítej zpět, kluci.
Vítejte v sekci 5.
V tomto bodě, mít dokončil kvíz 0 a když byla svědkem, jak jsi udělal,
doufejme, že budete cítit opravdu dobře, protože jsem byl velmi zaujatý skóre v této sekci.
Pro naše on-line diváky, měli jsme pár otázek
o posledních dvou problémů na problém souboru - nebo na testu, ale.
Takže jsme jít přes ty opravdu rychle, takže každý vidí, co se stalo
a jak projít skutečné řešení, spíše než jen prohlížení řešení sám.
Budeme jít za posledních pár problémů opravdu rychle, 32 a 33.
Jen opět, může tak, že on-line diváci vidět.
>> Pokud se obrátíte na vašeho problému 32, který je na straně 13,
13 z 16, problém 32 je o swapů.
Bylo to všechno o výměně dvě celá čísla.
Je to problém, který jsme si už za pár časů v přednášce.
A tady, co jsme se ptali vás udělat, je rychle paměťová stopa.
Chcete-li vyplnit v hodnotách proměnných tak, jak jsou ve frontě
jako kód prochází tímto odkládací funkci.
Zejména, co se díváme na - Jdu dát tuto iPad dolů -
zejména, co se díváme na to je řada číslovány 6 právě zde.
A to očíslovány 6 jen za kontinuitu s předchozím problémem.
To, co chceme udělat, je zobrazit nebo označit stav paměti
jak je to v době, kdy se provedení tohoto řádku číslo 6,
který je účinně návratu z naší odkládací funkci tady.
Pokud bychom posunout dolů tady, jsme viděli, že adresy vše v paměti byla poskytnuta pro nás.
To je velmi klíčový, budeme se k ní vrátí za chvíli.
A pak tady dole na dně, jsme měli trochu paměti diagram, který budeme odkazovat.
Jsem vlastně udělal se na mé IPAD.
Takže budu střídat tam a zpět mezi iPad a tento kód jen pro referenci.
>> Pojďme začít. Za prvé, pojďme zaměřit na prvních pár řádků hlavního tady.
Chcete-li začít, budeme inicializovat x na 1 a Y 2.
Takže máme dvě celočíselné proměnné, oni oba bude umístěn na zásobníku.
Budeme dát 1 a 2 v nich.
Takže když jsem otočit k mému iPad, doufejme, uvidíme -
Apple TV zrcadlení, a tam jdeme. Dobře.
Takže když jsem otočit k mému iPad,
Chci inicializovat x na 1 a Y 2.
Děláme to jednoduše tím, že píše 1 do pole označeného x
a 2 v poli označeny y. Poměrně jednoduché.
Takže teď se vraťme k notebooku, uvidíme, co se bude dít dál.
Takže to další řádek je místo, kde se věci složitější.
Míjíme adresu X a adresu y jako parametry a a b na odkládací funkci.
Adresa x a adresou y jsou věci, které nemůžeme vypočítat
aniž by odkázal na tyto bodech tady dole.
A naštěstí, první dvě odrážky nám přesně to, co jsou odpovědi.
Adresa x v paměti je 10, a adresa y v paměti je 14.
Takže to jsou hodnoty, které se dostanou předána jako a, b až nahoru v naší virtuální funkce.
Takže znovu, přepnutí zpět do našeho schématu, mohu napsat 10 v
a 14 v b..
Nyní, tento bod je místo, kde budeme pokračovat s swapu.
Tak obracející zpět k přenosnému počítači znovu,
vidíme, že způsob, jakým funguje, je odkládací jsem se poprvé dereference a obchod výsledkem tmp.
Takže dereference operátor říká, "Hey. Dopřejte obsah proměnné jako adresa.
Přejít na vše, co je uloženo na této adrese, a tak jej nahraje. "
Co načíst z proměnné se bude uložen do našeho tmp proměnné.
Přehodit zpět na iPad.
Pokud půjdeme řešit 10, víme, že adresa 10 je proměnná x
protože nám bylo řečeno, náš odrážky, že adresa x v paměti je 10.
Takže můžeme jít tam, získat hodnotu toho, který je 1, jak je vidíme na naší iPad,
a nahrát to do tmp.
Opět, toto není konečné obsah.
Budeme procházet a my Vás budeme do našeho konečného stavu programu na konci.
Ale teď, máme hodnotu 1 uložené v tmp.
>> A je tu rychlý dotaz tady.
[Alexander] Je dereference provozovatel - to je jen hvězda přímo před proměnné?
Ano >>. Takže dereference provozovatel, jak jsme otočit zpět do našeho notebooku znovu,
Je to hvězda přímo před hotelem.
V tomto smyslu, to je - kontrastovat s operátorem násobení
které vyžaduje dvě věci, přičemž dereference operátor je unární operátor.
Jen aplikován na jedné hodnoty na rozdíl od binárního operátoru,
kde se vztahují na dvou různých hodnot.
Takže to je to, co se děje v tomto řádku.
Naložili jsme hodnotu 1 a uloženy do naší dočasné celočíselné proměnné.
Na další řádek, uložíme obsah B do -
nebo spíše, uložíme obsah, který b ukazuje na do místa, kde se ukazuje.
Analyzujeme-li tento zprava doleva, budeme dereference b,
budeme řešit 14, budeme chytit celé číslo, které je tam,
a pak jsme se jít na adresu 10,
a budeme házet výsledek naší dereference z B do tohoto prostoru.
Přehodit zpět k našemu iPad, kde můžeme udělat to trochu konkrétnější,
to by mohlo pomoci, když napíšu čísla na všechny adresy zde.
Takže víme, že v y, jsme na adrese 14, x je na adrese 10.
Když začneme u b, jsme dereference b, budeme chytit hodnotu 2.
Budeme se chytit tuto hodnotu, protože to je hodnota, která žije na adrese 14.
A budeme dávat to do proměnné, která žije na adrese 10,
který je tady, odpovídající našim proměnné x.
Takže můžeme udělat trochu přepsání zde
kde jsme se zbavit našeho 1 a místo toho jsme napsat 2.
Takže všechno je v pořádku a dobře na světě, i když máme přepisováno X nyní.
Máme uloženy x starou hodnotu v našem tmp proměnné.
Takže můžeme dokončit swapu s dalším řádkem.
Přehodit zpět k našemu notebooku.
Nyní vše, co zbývá, je, aby se obsah z našeho dočasného celočíselné proměnné
a uložit je do proměnné, která žije na adresu, která b drží.
Takže budeme účinně dereference b získat přístup k proměnné
, který je na adrese, b drží v něm,
a budeme se nacpat hodnotu, která tmp drží do něj.
Přehodit zpět na iPad ještě jednou.
Mohu vymazat tuto hodnotu zde, 2,
a místo toho budeme kopírovat 1 právo do něj.
Pak další řádek, který provádí, samozřejmě -
pokud bychom otočit zpět do notebooku - je to bod 6,
což je bod, ve kterém jsme chtěli, aby naše schéma zcela vyplněny.
Tak mizerný zpět na iPad ještě jednou, jen tak můžete vidět dokončenou diagram,
můžete vidět, že máme 10 v, 14 v B, 1 ve tmp, 2 v X, a 1 v y.
Jsou nějaké otázky ohledně tohoto?
Dává to větší smysl, když šel přes něj?
Udělejte menší smysl? Doufejme, že ne. Dobře.
>> Ukazatele jsou velmi ošidné téma.
Jeden z kluků, se kterými spolupracujeme má velmi časté rčení:
"Abychom pochopili ukazatele, musíte nejprve pochopit ukazatele."
Což myslím, že je to pravda. To dělá to chvíli trvat zvyknout si na to.
Kreslení spoustu obrázků, losování paměťových diagramů, jako je tento jsou velmi užitečné,
a poté, co projdete například po například po příkladu,
to začnu dělat něco větší smysl a trochu víc rozum a trochu větší smysl.
A konečně, jeden den, budete mít vše úplně zvládl.
Jakékoliv otázky dříve než přejdeme k dalšímu problému? Dobrá.
Takže otočit zpět do notebooku.
Další problém, který máme, je problém číslo 33 na soubor I / O.
Zvětšení na tomto trochu.
Problém 33 - Ano?
>> [Daniel] jsem měl rychlou otázku. Tato hvězda, nebo hvězdička,
je to tzv. dereferencing při použití hvězdičku před.
Jak se to jmenuje, když použijete ampersand předtím?
>> Znak ampersand dříve, než je adresa-provozovatele.
Takže pojďme se posunout zpět.
Chybička se vloudila. Jsem v režimu zoom, takže nemůžu opravdu scroll.
Podíváme-li se na tento kód opravdu rychle přímo zde,
znovu, to samé se děje.
Podíváme-li se na tento kód přímo tady, na tomto řádku, kde děláme volání vyměnit,
ampersand jen říká "dostat adresu, na které proměnné x životy."
Když váš kompilátor kompiluje kód,
má skutečně fyzicky vytýčit místo v paměti pro všechny vaše proměnných žijí.
A tak to, co může kompilátor pak dělat, když je to sestavují všechno,
to ví, "Oh, jsem dal x na adrese 10. jsem dal Y na adrese 14."
To pak může vyplnit tyto hodnoty pro vás.
Takže si pak můžete - to pak předat to v průchodu a & y v i.
Tihle kluci si adresu, ale také, když je předávat do odkládací funkce,
tento typ informací, to int * tady, říká kompilátoru,
"Dobře, budeme se výkladu tuto adresu jako adresu celočíselné proměnné."
Jako adresu int, která je odlišná od adresy proměnné znak
protože int zabírá, na 32-bit stroje, zabírá 4 bajty prostoru,
vzhledem k tomu, postava pouze přebírá 1 bajt prostoru.
Takže je to důležité vědět i to, co je - to, co žije, jaký typ hodnoty
žije na adresu, kterou dostal prošla dovnitř
Nebo adresu, kterou co do činění.
Tak, víte, kolik bytů informací skutečně načíst z paměti RAM.
A pak, ano, to dereference operátor, jako vy jste se ptal,
jde a přistupuje k informacím na konkrétní adresu.
Tak to říká, s tímto proměnnou zde, léčit obsah jako adresa,
přejít na tuto adresu, a vytáhnout, vložte do procesoru, zatížení do registru
skutečné hodnoty nebo obsah, které žijí na této adrese.
Nějaké další otázky? To jsou dobré otázky.
Je to hodně nové terminologie příliš.
Je to také trochu funky, vidět a a * na různých místech.
>> Dobrá.
Takže zpět k problému 33, soubor I / O.
To byl jeden z těch problémů, které si myslím, že pár věcí se stalo.
Jeden, že je to docela nové téma.
To byl předložen brzy před kvízu,
a pak jsem, že to bylo něco jako jeden z těch slovních úloh v matematice
kde vám spoustu informací, ale ve skutečnosti nechcete skončit museli použít spoustu ní.
První část tohoto problému popisuje, co soubor CSV je.
Nyní, CSV souboru, podle popisu, je oddělený čárkami hodnoty souboru.
Důvodem jsou vůbec zajímavé, a důvod, proč se někdy použít,
je, protože, jak mnozí z vás někdy používají věci, jako je Excel?
Obrázek většina z vás, pravděpodobně bude nebo použití při určitém okamžiku svého života.
Budete používat něco jako Excel.
S cílem získat data z tabulky aplikace Excel nebo dělat nějaký druh zpracování s ním,
pokud byste chtěli napsat program v jazyce C nebo Python program, Java programu,
vypořádat se s daty jste uložili tam,
jedním z nejčastějších způsobů, jak dostat to je v souboru CSV.
A můžete otevřít Excel a když jdete na "Uložit jako" dialog,
se můžete dostat ven skutečný soubor CSV.
>> Handy vědět, jak se vypořádat s těmito věcmi.
Funguje to tak, že je to podobné - myslím, že to v podstatě napodobování tabulky,
kde, jak vidíme zde, ve velmi nejvíce nalevo kus,
máme všechny poslední názvy.
Takže máme Malan, pak Hardison, a pak Bowden, MacWilliam, a pak Chan.
Všechny poslední jména. A pak čárka odděluje příjmení z křestních jmen.
David, Nate, Rob, Tommy, a Zamyla.
Vždycky jsem smíchat Robby a Toma.
A pak, konečně, třetí sloupec e-mailové adresy.
Jakmile pochopíte, že zbytek programu je poměrně jednoduché implementovat.
Co jsme udělali, aby se napodobit stejný strukturu v našem programu C
je, že jsme použili strukturu.
Začneme hrát s nimi trochu více stejně.
Viděli jsme je na první trochu v problému sadě 3, když jsme byli zabývající se slovníky.
Ale tento personál struct ukládá příjmení, křestní jméno, a e-mail.
Stejně jako náš soubor CSV byl skladování.
Takže je to jen konverze z jednoho formátu do druhého.
Máme převést, v tomto případě, je personál struct do linky,
oddělený čárkami line, stejně jako to.
Dává to smysl? Vy všichni vzít kvíz,
tak jsem si představit, že máte alespoň nějaký čas na přemýšlení o tom.
>> V pronájmu funkci, problém nás žádá, abychom se v - Dáme snímku v tomto trochu -
se v personálu struktury, personálu struct, s jméno s,
a připojit jeho obsah do našeho souboru staff.csv.
Ukazuje se, že je to docela jednoduché použití.
Budeme trochu pohrát s těmito funkcemi trochu více dnes.
Avšak v tomto případě, fprintf funkce je skutečně klíčem.
Takže s fprintf, můžeme tisknout, stejně jako vy byly pomocí printf celý tento termín.
Můžete printf řádek do souboru.
Takže místo toho, aby prostě dělat obvyklé printf hovor, kde si dát formátovací řetězec
a pak nahradit všechny proměnné s následujícími argumenty,
s fprintf, vaše první argument je místo toho soubor, který chcete napsat.
Pokud bychom se podívali na to v zařízení, například, člověk fprintf,
můžeme vidět rozdíl mezi printf a fprintf.
Budu přiblížit tady trochu.
Takže s printf, dáme formátovací řetězec, a pak následující argumenty
jsou všechny proměnné pro výměnu nebo nahrazení do našeho formátu řetězce.
Vzhledem k tomu, s fprintf, první argument je skutečně tento soubor * nazývá potok.
>> Přesun zpět sem do našeho pronájmu,
jsme již dostali náš soubor * otevřený stream pro nás.
To je to, co tento první linka dělá, že otevře soubor staff.csv,
se otevře v režimu append, a vše, co zbylo pro nás udělat, je
napsat zaměstnanců strukturu do souboru.
A uvidíme, nechci používat iPad?
Budu používat iPad. Máme za neplatné - pojďme dát to na stůl, takže můžu napsat trochu lépe -
neplatnost kol a trvá do jednoho argumentu, má personál strukturu nazvanou s.
Mám naše rovnátka, máme náš soubor * s názvem souboru,
máme fopen linku které jste nám poskytli,
a já budu jen psát jako tečky, protože je již v pedia.
A pak na naše další řádek, budeme-li volat do fprintf
a budeme procházet v souboru, který chceme tisknout,
a pak se naše formátovací řetězec, který -
Nechám jste mi říct, jak to vypadá.
Jak o vás, Stella? Víte, co první část formátovacího řetězce vypadá?
[Stella] Nejsem si jistý. >> Nebojte se zeptat na Jimmyho.
Víte, Jimmy?
[Jimmy] Bylo by to prostě být poslední? Nevím. Nejsem si úplně jistý.
Dobře >>. Jak o tom, to někdo si to správně na zkoušku?
Ne pořádku.
Ukazuje se, že tady všechno, co musíme udělat, je chceme každou část našeho personálu struktury
které mají být vytištěny jako řetězec do našeho souboru.
Právě jsme použít řetězec substituční znaku tři různé časy, protože máme příjmení
následuje čárka, pak jméno následovaný čárkou,
a pak konečně adresa, která následuje - což není
montáž na mé obrazovce - ale je to následuje znakem nového řádku.
Takže budu psát to jen tam.
A pak po naší formátovací řetězec,
prostě mají náhrady, které jsme přístup pomocí tečkové notace
kterou jsme viděli v problému sadě 3.
Můžeme použít s.last, s.first, a s.email
nahradit v těchto tří hodnot do našeho formátovacího řetězce.
Tak jak to šlo? Smysl?
Ano? Ne? Možná? Dobře.
>> Poslední věc, že ​​my poté, co jsme vytisknout a poté, co jsme otevřeli naši soubor:
když jsme otevřeli soubor, musíme vždy pamatovat na jeho zavření.
Protože jinak skončíme úniku paměti,
použití se deskriptory souborů.
Takže zavřete jej, které funkce budeme používat? Daniel?
[Daniel] fclose? >> Fclose, přesně.
Takže poslední část tohoto problému bylo řádně zavřete soubor, pomocí fclose funkce,
který právě vypadá.
Není příliš šílené.
Cool.
Tak to je problém 33 o testu.
Budeme mít určitě větší soubor I / O přijít.
Uděláme trochu víc v přednášce dnes, nebo v sekci dnes,
protože to je to, co se děje tvořit část této nadcházející PSet.
Pojďme dál od testu v tomto bodě. Ano?
>> [Charlotte]] Proč fclose (soubor) místo fclose (staff.csv)?
>> Ah. Vzhledem k tomu, že se ukáže, že - tak otázka, která je veliký,
je důvod, proč, když píšeme fclose, píšeme fclose (soubor) star proměnnou
na rozdíl od názvu souboru, staff.csv? Je to správně? Jo.
Takže pojďme se podívat. Pokud bych přejít zpět na mém notebooku,
a pojďme se podívat na fclose funkci.
Takže fclose funkce uzavírá proud a trvá na ukazatel na proudu, který chceme uzavřít,
na rozdíl od skutečného názvu souboru, který chceme uzavřít.
A to je proto, že v zákulisí, když uděláte volání fopen,
když si otevřete soubor, jste vlastně přidělování paměti pro ukládání informací o souboru.
Takže máte ukazatel souboru, který obsahuje informace o souboru,
jako je to otevřené, jeho velikost, kde se v současné době v souboru,
takže si můžete udělat čtení a psaní volání daného místa v souboru.
Můžete skončit uzavřením ukazatel namísto uzavření název souboru.
>> Ano? [Daniel] Tak aby bylo možné používat pronájem, řekli byste - jak to dostat uživatelský vstup?
Má fprintf chovat jako GetString v tom smyslu, že to bude jen čekat na vstup od uživatele
a požádat, abyste zadejte tento - nebo počkat na zadání tyto tři věci?
Nebo potřebujete použít něco realizovat pronájem?
Jo >>. Takže nejsme - otázka byla, jak se dostat vstup od uživatele
za účelem provedení nájem? A to, co tu máme, je volající o pronájmu,
prošla v tomto pracovníků struct se všemi z dat uložených v struct již.
Takže fprintf je schopen jen napsat, že data přímo do souboru.
Není třeba čekat na vstup od uživatele.
Tento uživatel je již dána vstup řádně vložením do tohoto zaměstnance struct.
A věci, samozřejmě, by rozbít, pokud některý z těchto ukazatelů byly null,
tak jsme se posunout zpět a my podívat na naši struct.
Máme řetězec naposledy, string první, string email.
Nyní víme, že všichni ti, opravdu, pod kapotou, jsou char * proměnné.
To může nebo nemusí být nasměrována na null.
Mohou směřovat do paměti na haldě,
Možná paměť na zásobníku.
My opravdu nevíme, ale pokud některý z těchto ukazatelů jsou null, nebo neplatné,
že to určitě havárii naše půjčovna funkci.
To bylo něco, co bylo trochu nad rámec zkoušky.
Nejsme starosti, že.
Great. Dobře. Takže se přesunul od kvízu.
>> Pojďme zavřít toho chlapa, a budeme se dívat na PSet 4.
Takže pokud jste se podívat na spec PSet, jakmile k němu máte přístup, cs50.net/quizzes,
jsme jít přes několik sekcí problémů dnes.
Já rolování dolů - část otázek začíná na třetí straně PSet spec.
A první část vás požádá jít a dívat se na krátký na přesměrování a potrubí.
Což bylo docela v pohodě krátký, zobrazí několik nových cool triky příkazového řádku, které můžete použít.
A pak máme několik otázek pro vás stejně.
Tato první otázka proudy, které printf píše ve výchozím nastavení,
jsme trochu dotkli jen trochu před chvílí.
To fprintf, že jsme právě diskutovali bere v proudu souboru * jako jeho argument.
fclose bere v proudu souboru * i,
a návratová hodnota funkce fopen vám souboru * proud stejně.
Důvod, proč jsme neviděli ty předtím, když jsme se zabýval printf
Je tomu tak proto printf má výchozí proud.
A výchozí proud, na které se píše
zjistíte informace o v krátké.
Takže určitě se na něj podívat.
>> V dnešní části budeme mluvit trochu o GDB,
protože čím více jste obeznámeni s tím, že více praxe získáte s ní,
lépe schopný budete skutečně stopovat chyby ve vašem vlastním kódu.
To urychluje proces ladění nahoru ohromně.
Takže pomocí printf, pokaždé, když to, že budete muset rekompilovat kód,
budete muset spustit znovu, někdy budete muset přesunout printf hovor kolem,
komentář mimo kód, zabere to jen chvilku.
Naším cílem je pokusit se přesvědčit, že s GDB, můžete v podstatě
printf něco na libovolném místě v kódu a už nikdy nebudete muset překompilovat ho.
Už nikdy nebudete muset začít a udržet hádat, kde printf další.
První věc, kterou musíte udělat, je zkopírovat tento řádek a získat část kódu pryč webu.
Jsem kopírování tento řádek kódu, který říká, "wget ​​http://cdn.cs50.net".
Budu ho kopírovat.
Chystám se jít na moji spotřebiče, oddálení, takže můžete vidět, co dělám,
vložit to tam, a když jsem stiskněte klávesu Enter, tato wget příkaz doslova je web dostat.
Bude to bourat tento soubor pryč na internetu,
a bude to uložit do aktuálního adresáře.
Nyní, když jsem seznam svou aktuální adresář můžete vidět, že jsem dostal tuto section5.zip file přímo tam.
Způsob, jak se s tím vypořádat chlap je rozbalit ho,
které můžete udělat v příkazovém řádku, stejně jako to.
Section5.zip.
To bude rozbalte jej, vytvořte složku pro mě,
nafouknout veškerý obsah, dal je tam.
Takže teď můžu jít do mého sekce 5 adresáře pomocí příkazu cd.
Zrušte obrazovku pomocí jasné. Takže vyčistit obrazovku.
Teď mám pěkný čistý terminál řešit.
>> Nyní, když jsem vypsat všechny soubory, které vidím v tomto adresáři,
vidíte, že mám čtyři soubory: buggy1, buggy2, buggy3, a buggy4.
Já jsem také dostal své odpovídající. C soubory.
Nebudeme se dívat na. Soubory C pro tuto chvíli.
Místo toho, budeme používat je, když jsme se otevřít GDB.
Jsme drželi je asi tak, že máme přístup k aktuální zdrojový kód, když jsme pomocí GDB,
ale cílem této části sekce je pohrát si s GDB
a uvidíte, jak můžeme použít zjistit, co se děje špatně s každou z těchto čtyř kočárku programů.
Takže jsme jen tak po pokoji opravdu rychle,
a budu se zeptat někoho spustit jednu z kočárku programů,
a pak půjdeme jako skupina prostřednictvím GDB, a uvidíme, co můžeme udělat pro to opravit tyto programy,
nebo alespoň zjistit, co se děje špatně v každé z nich.
Pojďme začít znovu tady s Danielem. Spustíme buggy1? Pojďme se podívat, co se stane.
[Daniel] To říká, že je to chyba aplikace. Jo >>. Přesně tak.
Takže, když spustím buggy1, dostanu seg poruchu.
V tomto bodě, jsem mohl jít a otevřít buggy1.c,
vyzkoušet a zjistit, co se děje špatně,
ale jeden z nejvíce nepříjemnými věcí na tomto seg poruchy chybě
je to, že nemůžu říct o tom, co řada z programových věcí skutečně pokazilo a zlomil.
Tak nějak se podívat na kód
a zjistit pomocí odhad a kontrolu nebo printf vidět, co se děje špatně.
Jedna z nejlepších věcí, o GDB je, že je to opravdu, ale opravdu jednoduché
přijít na to, řádek, ve kterém váš program zhroutí.
Je to naprosto stojí za to ji používat, i když jen na to.
Takže nastartovat GDB, jsem typ GDB, a pak jsem jí dávají cestu k spustitelného souboru, který chci spustit.
Tady píšu gdb ./buggy1.
Stiskněte Enter. Dává mi to všechno informace o autorských právech,
a tady uvidíte tento řádek, který říká, "Čtení symbolů z / home /
jharvard/section5/buggy1. "
A pokud vše půjde dobře, uvidíte, že vytisknout zprávu, která vypadá takto.
Bude to číst symboly, bude to říkat "Já čtu symboly z vašeho spustitelného souboru,"
a pak to bude mít tento "Hotovo" zpráva tady.
Pokud vidíte jiný variantu tohoto, nebo vidíte, že se nepodařilo najít symboly
nebo něco takového, co to znamená, je to, že jste právě nejsou sestaveny na spustitelný správně.
Když jsme kompilovat programy pro použití s ​​GDB, musíme použít tuto speciální g vlajkou,
a že se to dělá ve výchozím nastavení, pokud si zkompilovat vaše programy, pouhým zadáním, aby
nebo si kočárek nebo se zotavit, každý z nich.
Ale pokud jste kompilace ručně s Clang, pak budete muset jít a patří to-g vlajkou.
>> V tomto bodě, teď, když máme GDB řádku,
je to docela jednoduché spustit program.
Můžeme buď zadat běh, nebo můžeme jen typ R.
Většina gdb příkazy mohou být zkráceny.
Obvykle jen na jedné nebo několika písmen, což je docela pěkné.
Takže Saad, pokud zadáte r a stiskněte klávesu Enter, co se stane?
[Saad] Mám SIGSEGV, Segmentation fault, a pak to všechno hatmatilka.
Jo >>.
Stejně jako vidíme na obrazovce právě teď, a jako Saad řekl,
když napíšeme běh nebo r a stiskněte klávesu Enter, stále se stejnou seg poruchu.
Takže pomocí GDB nevyřeší náš problém.
Ale to nám dává určité hatmatilka, a ukázalo se, že to hatmatilka
vlastně nám říká, kde se to děje.
Chcete-li analyzovat tento trochu, tento první bit je funkce, v níž všechno špatně.
Tam je to __ strcmp_sse4_2, a to nám říká, že se to děje v tomto souboru
volal sysdeps/i386, to vše opět trochu nepořádek - ale linka 254.
To je trochu těžké analyzovat. Obvykle, když vidíte věci, jako je tento,
to znamená, že je to seg chybující v jednom z knihovny systému.
Takže něco do činění s strcmp. Vy jste viděl strcmp dříve.
Není příliš bláznivé, ale znamená to, že strcmp je rozbité, nebo že je tu problém s strcmp?
Co si myslíte, Alexander?
[Alexander] Je to - je 254 linka? A - není binární, ale není to jejich stropy,
a pak je tu jiný jazyk pro každou funkci. Je to 254 v této funkci, nebo -?
>> Je to linka 254. Vypadá to, že v tomto souboru. S., tak to je kód assembleru pravděpodobně.
>> Ale myslím, že naléhavější věc je, protože jsme dostali seg poruchu,
a vypadá to, že to přichází z strcmp funkce,
to neznamená, pak, je špatně, že strcmp?
To by nemělo, snad. Takže jen proto, že máte segmentation fault
v jedné z funkcí systému, obvykle to znamená, že jste právě Nevolal správně.
Nejrychlejší věc udělat, aby se zjistit, co se vlastně děje
když vidíte něco šíleného, ​​jako to, když vidíte seg poruchu,
zvláště pokud máte program, který je pomocí více než jen hlavní,
je použít backtrace.
I zkrátit backtrace psaním BT, jak protichůdný k plnému backtrace slovo.
Ale Charlotte, co se stane, když zadáte BT a stiskněte klávesu Enter?
[Charlotte] Ukazuje mi dva řádky, řádek 0 a 1. řádek.
Jo >>. Takže řádek 0 a 1. řádek.
Jedná se o skutečné zásobníku snímky, které se v současné době ve hře, když váš program havaroval.
Počínaje nejvyšší rámu, rámu 0, a bude nejspodnější, která je rám 1.
Naše nejvyšší rám je strcmp rámu.
Můžete myslet na to, jak podobný k tomuto problému jsme dělali jen to, na testu s ukazateli,
kde jsme vyměnit zásobník rám na horní části hlavního zásobníku rámu,
a my jsme museli proměnné tak, že prohodí se pomocí na vrcholu proměnných, že hlavní je používat.
Zde naše pád se stalo v našem strcmp funkce, které se říkalo o naší hlavní funkcí,
a backtrace nám dává nejen funkce, ve kterých věci selhala,
ale je to také nám říká, kde bylo vše jen z.
Takže pokud jsem projděte trochu více vpravo,
můžeme vidět, že jo, my jsme byli na lince 254 tohoto strcmp-sse4.s souboru.
Ale hovor byl dělán na buggy1.c, řádek 6.
Takže to znamená, že můžeme udělat - je, že jsme si prostě jít podívat a zjistit, co se děje
na buggy1.c, řádek 6.
Opět, existuje několik způsobů, jak to udělat. Jedním z nich je ukončení z GDB
nebo mít váš kód otevře v jiném okně a cross reference.
To samo o sobě, je docela užitečné, protože teď, když jste na úředních hodin
a máte seg poruchu a vaše TF se divila, kde všechno bylo porušení,
stačí říct, "Oh, linka 6. Nevím, co se děje,
ale něco řádku 6 je příčinou můj program přerušit. "
Jiný způsob, jak to udělat, je, můžete použít tento příkaz s názvem seznam v GDB.
Můžete také zkrátit s l.
Takže pokud jsme narazili l, co jsme se sem dostali?
Dostáváme spoustu podivné věci.
To je skutečná sestava kód
že je v strcmp_sse4_2.
To vypadá druh funky,
a důvod, proč jsme stále je to proto, že právě teď,
GDB má nás v rámu 0.
>> Takže kdykoliv se podíváme na proměnné, kdykoli se podíváme na zdrojový kód,
díváme zdrojového kódu, který se vztahuje k zásobníku rámu jsme právě nacházíte
Tak, aby si něco smysluplného, ​​musíme
přejít na zásobníku rámu, který dává větší smysl.
V tomto případě by hlavní zásobník rám, aby trochu větší smysl,
protože to byl vlastně kód, který jsme napsali.
Není strcmp kód.
Jak se můžete pohybovat mezi snímky, v tomto případě, protože máme dvě,
máme 0 a 1,
děláte, že se nahoru a dolů příkazů.
Pokud bych posunout o jeden snímek,
teď jsem v hlavním zásobníku rámu.
Mohu se pohybovat dolů jít tam, kde jsem byl,
jít znovu, jít zase dolů, a jít znovu.
Pokud jste někdy dělat program v GDB, dostanete havárii, získáte backtrace,
a zjistíte, že je to v nějakém souboru, který neví, co se děje.
Můžete zkusit seznamu, kód nevypadá znáte,
podívejte se na seznam snímků a zjistit, kde jste.
Pravděpodobně jste ve špatném rámce fronty.
Nebo alespoň, že jsi v zásobníku rámu, který není ten, který si můžete opravdu ladit.
Teď, když jsme v příslušné rámce fronty, jsme v hlavním,
Nyní můžeme použít příkaz list zjistit, co byla linka.
A vidíte to, to vytiskl pro nás tady.
Ale můžeme zasáhnout seznam všech stejné, a seznam nám dává toto pěkné výtisk
skutečného zdrojového kódu, co se děje tady.
>> Zejména, můžeme se podívat na řádku 6.
Můžeme vidět, co se děje tady.
A vypadá to, že děláme porovnání řetězců
mezi řetězci "CS50 skal" a argv [1].
Něco o tom padal.
Takže Missy, máte nějaké myšlenky na to, co by mohlo být to tu děje?
[Missy] Já nevím, proč to shazovat. >> Nevíte proč to shazovat?
Jimmy, nějaké myšlenky?
[Jimmy] Nejsem si úplně jistý, ale v poslední době jsme použili řetězec porovnání,
nebo strcmp, měli jsme jako tři různé případy podle ní.
Neměli jsme k ==, nemyslím si, že přímo v té první linii.
Místo toho byl rozdělen do tří a jedna == 0,
jeden byl <0, myslím, a jeden byl> 0.
Takže možná něco takového? Jo >>. Takže tam je to problém
z děláme srovnání správně?
Stella? Jakékoliv myšlenky?
[Stella] Nejsem si jistý. >> Nejsem si jistý. Daniel? Myšlenky? Dobře.
Ukázalo se, že to, co se děje tady, je, když jsme běželi program
a my jsme dostali seg poruchu, při spuštění programu poprvé, Daniel,
jste jej žádné argumenty příkazového řádku?
[Daniel] No >> č. V tomto případě, co je hodnota argv [1]?
>> Není žádná hodnota. Právo >>.
No, není vhodné řetězcová hodnota.
Ale tam je nějaká hodnota. Jaká je hodnota, která je uložena v tam?
>> Odpadky hodnota? >> Je to buď odpadky hodnota nebo, v tomto případě,
konec pole argv je vždy ukončen s null.
Takže, co vlastně dostal v nich uloženy, je null.
Další způsob, jak vyřešit tento, spíše než myšlení přes,
je pokusit vytisknout to.
To je místo, kde jsem si říkal, že používání GDB je skvělé,
protože si můžete vytisknout všechny proměnné, všechny hodnoty, které chcete
pomocí tohoto handy-dandy p příkazu.
Takže pokud jsem typ p a pak jsem zadejte hodnotu proměnné nebo název proměnné,
říkají, argc, vidím, že argc je 1.
Pokud chci vytisknout argv [0], mohu tak učinit jen tak.
A jak jsme viděli, argv [0] je vždy název programu,
vždy název spustitelného souboru.
Zde můžete vidět, že má úplný název.
Mohu také vytisknout argv [1], a uvidíme, co se stane.
>> Zde jsme dostali tento druh mystické hodnoty.
Máme tuto 0x0.
Nezapomeňte na začátku semestru, kdy jsme mluvili o hexadecimální čísla?
Nebo že malá otázka na konci PSet 0 o tom, jak reprezentovat 50 v hex?
Způsob, jakým píšeme hex čísla v CS, jen neplést sami
s desetinnými čísly, je, že jsme vždy prefix jim 0x.
Tak tohle 0x prefix vždy jen rozumí interpretovat následující číslo jako hexadecimální číslo,
ne jako řetězec, ne jako desetinné číslo, ne jako binární číslo.
Protože počet 5-0 je platné číslo v šestnáctkové soustavě.
A to je číslo v desítkové soustavě, 50.
Takže to je to, jak jsme disambiguate.
Takže 0x0 prostředky hexadecimální 0, což je také desetinné 0, binární 0.
Je to jen hodnota 0.
Ukazuje se, že to je to, co je null, vlastně, v paměti.
Null je jen 0.
Zde se prvek uložen v argv [1] je nulový.
Takže se snažíme tyto naše "CS50 skály" řetězec nulový řetězec.
Takže dereferencing null, pokusu o přístup k věci na null,
ty jsou obvykle bude způsobovat nějaké segmentation fault nebo jiné špatné věci se dějí.
A ukázalo se, že strcmp nekontroluje vidět
zda jste prošel v hodnotě, která je null.
Spíše, to jen jde dopředu, snaží se dělat svou věc,
a pokud seg chyby, to seg chyby, a je to tvůj problém. Musíš jít opravit.
Opravdu rychle, může jak tento problém vyřešit? Charlotte?
[Charlotte] můžete zkontrolovat pomocí, pokud.
Takže pokud argv [1] je null, == 0, pak se vraťte 1, nebo něco [nesrozumitelné].
Jo >>. Takže to je jedna skvělý způsob, jak to udělat, jak můžeme zkontrolovat,
hodnota se chystáme projít do strcmp, argv [1], je null?
Pokud je to null, pak můžeme říci, v pořádku, potratit.
>> Běžnější způsob, jak to udělat, je použít argc hodnotu.
Můžete vidět přímo zde na začátku main,
Vynechali jsme, že první test, který jsme obvykle dělat, když budeme používat argumenty příkazového řádku,
který je otestovat, zda není naše argc hodnota je to, co očekáváme.
V tomto případě, čekáme nejméně dva argumenty,
název programu plus jeden další.
Protože se chystáme použít druhý argument tady.
Takže má nějaký zkoušky předem, před naším strcmp hovoru
že testy též argv je nejméně 2, by také udělat stejný druh věci.
Můžeme zjistit, jestli to funguje, spuštěním programu znovu.
Vždy se můžete restartovat program do GDB, což je opravdu pěkné.
Můžete spustit, a při předání v argumentech do vašeho programu,
předáte je, když říkáte spuštění, ne při startu GDB.
Tímto způsobem můžete mít vyvolání programu s různými argumenty pokaždé.
Tak běžte, nebo znovu, můžu Type R, a uvidíme, co se stane, když napíšeme "ahoj".
To bude vždy zeptá, zda chcete spustit znovu od začátku.
Obvykle si chcete spustit znovu od začátku.
A v tomto bodě, to restartuje to znovu, to vytiskne
program, který jsme běh, buggy1, s argumentem ahoj,
a vytiskne tento standard ven, říká, "Dostanete D," smutný obličej.
Ale my jsme to seg chyba. To říkal, že proces ukončen normálně.
Takže to vypadá docela dobře.
Žádné další seg chyba, jsme to minulost,
takže to vypadá, že je skutečně seg chyba chyba, že jsme se dostat.
Bohužel, to nám říká, že jsme stále na D.
>> Můžeme se vrátit a podívat se na kód a vidět, co se tam děje
zjistit, co bylo - proč se to nám říká, že máme D.
Pojďme se podívat, zde byla tato printf říká, že máš D.
Pokud napíšeme seznam, jak si udržet psaní seznamu, udržuje iterace se prostřednictvím svého programu,
tak to vám ukážu několik prvních řádků programu.
Pak vám ukážu několik dalších řádků, a další kus a další kus.
A to bude dál snažit jít dolů.
A teď se dostaneme "linku číslo 16 je mimo rozsah."
Vzhledem k tomu, že má jen 15 řádků.
Pokud se dostanete do tohoto bodu, a vaše přemýšlel, "Co mám dělat?" můžete použít příkaz help.
Použijte nápovědu a pak to jméno příkazu.
A vidíte GDB nám dává všechny takovéhle věci.
To říká: "S žádným argumentem, uvádí dalších deset linek po nebo kolem předchozího seznamu.
Seznam - uvádí deset řádky před - "
Tak pojďme zkusit pomocí seznamu mínus.
A, který uvádí, že 10 řádků předchozí, můžete pohrát se seznamem trochu.
Můžete to udělat seznam, seznam -, můžete si dokonce dát vypsat číslo, jako je seznam 8,
a to bude seznam 10 řádků po řádku 8.
A vidíte, co se tady děje je máš jednoduché, pokud jiný.
Pokud zadáte CS50 skalách, vypíše "Získáte A."
Jinak to vytiskne "Dostanete D."
Bummer město. Dobrá. Ano?
>> [Daniel] Takže když jsem se snažil dělat CS50 kameny bez uvozovek,
říká, že "Dostanete D."
Potřeboval jsem uvozovky se dostat do práce, proč to je?
Jo >>. Ukazuje se, že když - to je další trochu legrace lahůdku -
při spuštění programu, pokud bychom jej spustit a my zadejte CS50 skalách,
stejně jako Daniel byl řekl, že ano, a stisknete klávesu Enter,
stále říká, že jsme si D.
A otázka je, proč to je?
A ukázalo se, že jak naše terminál a GDB analyzovat tyto jako dvě samostatné argumenty.
Vzhledem k tomu, když je prostor, který je vyjádřen
První argument skončila, další argument je asi začít.
Způsob zkombinovat ty do dvou, nebo líto, do jednoho argumentu,
je použít uvozovky.
Takže teď, když dáme do uvozovek a spusťte jej znovu, dostaneme A.
Takže jen shrnout, žádné citace, CS50 a skály analyzovat jako dvě samostatné argumenty.
S citacemi, je to analyzovat jako jeden argument úplně.
>> Vidíme to s zarážka.
Zatím jsme byli běží náš program, a to byl spuštěn
dokud buď seg závady nebo narazí na chybu
nebo dokud byl ukončen a veškeré byla úplně v pohodě.
To není nutně nejužitečnější věc, protože někdy
Máte chybu v programu, ale to není způsobení segmentation fault.
Není to způsobuje váš program zastavit nebo něco podobného.
Způsob, jak dostat GDB pozastavit váš program na určitém místě
je nastavit zarážku.
Můžete buď provést nastavením zarážka na název funkce
nebo můžete nastavit zarážku na konkrétní řádek kódu.
Líbí se mi nastavit zarážky na názvy funkcí, protože - snadno zapamatovatelné,
a pokud si skutečně jít a změnit zdrojový kód do trochu,
pak se vaše breakpoint bude skutečně zůstat na stejném místě ve vašem kódu.
Vzhledem k tomu, pokud používáte čísla řádků, a čísla řádků změní
protože přidáte nebo odstraníte nějaký kód, pak se vaše zarážky jsou úplně posral.
Jedním z nejčastějších věcí, které jsem udělat, je nastavit zarážku na hlavní funkci.
Často jsem si nastartovat gdb, budu psát B Hlavní, stiskněte klávesu Enter, a které vám nastavit zarážku
na hlavní funkcí, kterou právě říká, "Pozastavení programu, jakmile začnou,"
a to tak, když jsem spustit svůj program, řekněme, CS50 skály jako dva argumenty
a stiskněte klávesu Enter, se dostane do hlavní funkce a zastaví se na prvním řádku,
těsně před vyhodnocuje strcmp funkce.
>> Vzhledem k tomu, jsem se zastavil, teď můžu začít odtěžení kolem a viděl, co se děje
se všemi různými proměnnými, které jsou předávány do mého programu.
Zde mohu vytisknout argc a vidět, co se děje.
Vidět, že argc je 3, protože je to má 3 různé hodnoty v něm.
Je to tu na název programu, je to má první argument a druhý argument.
Můžeme tisknout ty z pohledu na argv [0], argv [1], a argv [2].
Takže nyní můžete vidět, proč tato výzva strcmp bude k nezdaru,
protože vidíte, že se rozdělil CS50 a skály do dvou samostatných argumentů.
V tomto okamžiku, jakmile jste hit zarážku, můžete pokračovat ke kroku prostřednictvím programu
řádek po řádku, na rozdíl od spuštění programu znovu.
Takže pokud nechcete začít svůj program znovu a prostě pokračovat dále,
můžete použít příkaz continue a pokračovat bude spusťte program až do konce.
Stejně jako to udělal tady.
Nicméně, když jsem restartovat program, CS50 skály, zasáhne můj zarážku znovu,
a tentokrát, když nechci prostě jít celou cestu přes zbytek programu,
Mohu použít následující příkaz, který jsem také zkratka s n.
A to bude krok prostřednictvím programu řádek po řádku.
, Takže můžete sledovat, jak se věci vykonávat, jako změnit proměnné, jak se věci se aktualizace.
Což je docela pěkné.
Druhá super věc je, spíše než opakovat stejný příkaz znovu a znovu a znovu,
pokud jste prostě zmáčknout Enter - tak tady vidíte, já jsem napsal v ničem -
když jsem prostě zmáčknout Enter, bude opakovat předchozí příkaz,
nebo předchozí GDB příkaz, který jsem dal dovnitř
Můžu mít stisknutí klávesy Enter a nechám krokování můj kód řádek po řádku.
Chtěl bych povzbudit vy jít podívat na další buggy programy stejně.
Nemáme čas se dostat přes všechny z nich dnes v oddíle.
Zdrojový kód je tam, takže můžete trochu vidět, co se děje
v zákulisí, pokud vám opravdu přilepená,
ale přinejmenším, jen cvičit bootování gdb,
spuštění programu, dokud se zlomí na vás,
získání backtrace, přijít na to, jakou funkci pád byl,
jaký postoj to bylo na, tisk na některé hodnoty proměnných,
jen tak budete mít pocit, pro to, protože to bude opravdu pomůže do budoucna.
V tomto bodě, budeme ukončit z GDB, které udělat pomocí skončit, nebo jen q.
Pokud váš program je uprostřed běhu stále, a to není ukončen,
bude to vždy zeptat, "Jste si jisti, že opravdu chcete skončit?"
Můžete stačí kliknout ano.
>> Nyní budeme dívat na další problém, který máme, což je kočka program.
Pokud se budete dívat z krátkodobého o přesměrování a potrubí, uvidíte, že Tommy používá tento program
že v podstatě vytiskne všechny výstup souboru na obrazovku.
Takže pokud jsem běžet kočku, tohle je vlastně vestavěný program spotřebiče,
a pokud budete mít Macintoshe, můžete to udělat na počítači Mac taky, pokud si otevřete terminál.
A my - kočka, řekněme, cp.c, a stiskněte klávesu Enter.
Co to udělali, kdybychom posunout nahoru trochu a podívejte se, kde jsme spustili linku,
nebo tam, kde jsme běželi příkazu cat, doslova jen vytisknout obsah cp.c naší obrazovce.
Můžeme spustit znovu a vy můžete dát do více souborů dohromady.
Takže si můžete udělat kočičí cp.c, a pak můžeme také zřetězit cat.c soubor,
což je program, chystáme psát,
a to bude tisknout na obě soubory zpět k sobě do našeho obrazovce.
Takže pokud budeme pohybovat nahoru trochu, vidíme, že když jsme běželi tuto kočka cp.c, cat.c,
Nejprve vytisknout ven cp soubor, a pak pod ním, to vytiskne se na cat.c soubor tady dole.
Budeme používat toto jen dostat naše nohy mokré.
Pohrajte si s jednoduchým potiskem na terminálu, viz, jak to funguje.
Pokud jste otevření s gedit cat.c, Enter,
můžete vidět program, že jsme o tom psát.
Jsme součástí toto pěkné kotle desku, takže nemusíte trávit čas psát všechny ty ven.
Jsme také zkontrolovat počet argumentů předaných palců
Jsme vytisknout pěkné zprávu o použití.
>> To je jedna z těch věcí, které opět, stejně jako jsme se bavili,
je to skoro jako svalové paměti.
Jen pamatujte, že dělají stejný druh věcí
a vždy vytisknout nějaký užitečných zprávy
tak, aby lidé věděli, jak spustit svůj program.
S kočkou, je to docela jednoduché, my jsme jen jít přes všechny různé argumenty
, které byly předány do našeho programu, a budeme tisknout
jejich obsah na obrazovku po jednom.
Chcete-li tisknout soubory na obrazovku, budeme dělat něco velmi podobného
na to, co jsme na konci testu.
Na konci kvízu, že najmout programu, museli jsme otevřít soubor,
a pak jsme museli tisknout.
V tomto případě, budeme otevřít soubor, a budeme číst z něj místo.
Pak budeme tisknout, místo do souboru, budeme tisknout na obrazovku.
Takže tisku na obrazovku, kterou jste všichni udělal předtím s printf.
Takže to není příliš bláznivé.
Ale čtení souboru je trochu divný.
Projdeme to trochu v čase.
Pokud jste se vrátit k poslednímu problému na kvíz, problém 33,
první řádek, že budeme dělat tady, otevření souboru, je velmi podobný tomu, co jsme dělali tam.
Takže Stella, co dělá, že řádka vypadá takto, když jsme se otevřít soubor?
[Stella] Capital FILE *, soubor - >> Dobře. >> - Je roven fopen. Jo >>.
Což je v tomto případě? Je to v komentáři.
>> Je to v komentáři? argv [i] a r?
Přesně >>. Právo na. Takže Stella je naprosto pravdu.
To je to, co řádek vypadá.
Budeme si soubor proud proměnné, uložte je do souboru *, takže všechny čepice,
FILE, *, a jméno této proměnné bude soubor.
Jsme mohli nazvat, co se nám líbí. Mohli bychom říkat first_file, nebo file_i, co jsme chtěli.
A pak název souboru byl přijat v na příkazovém řádku k tomuto programu.
Tak to jsou uloženy v argv [i,] a pak budeme tento soubor otevřít v režimu pro čtení.
Nyní, když jsme otevřeli soubor, co je ta věc, že ​​musíme vždy pamatovat na to
když jsme otevřeli soubor? Zavřete jej.
Tak Missy, jak jsme zavření souboru?
[Missy] fclose (soubor) >> fclose (soubor). Přesně tak.
Great. Dobře. Podíváme-li se na to, aby to komentář tady,
říká, "Open argv [i] a vytisknout obsah na standardní výstup."
>> Standardní out je divné jméno. Stdout je jen náš způsob, jak říct
chceme tisknout do terminálu, chceme vytisknout na standardní výstupní proud.
Můžeme skutečně zbavit tento komentář tady.
Budu zkopírovat a vložit jej protože to je to, co jsme udělali.
V tomto bodě, teď máme číst soubor kousek po kousku.
Jsme diskutovali několik způsobů čtení souborů.
Které z nich jsou vaše oblíbené tak daleko?
Jakými způsoby jste viděli, nebo si pamatovat, číst?
[Daniel] fread? >> Fread? Takže fread je jeden. Jimmy, víte nějaké další?
[Jimmy] No >> Dobře. Ne. Charlotte? Alexander? Nějaké další? Dobře.
Takže ty ostatní jsou fgetc, je ten, který budeme používat hodně.
K dispozici je také fscanf; vy vidět vzor zde?
Všichni začínají s f. Cokoliv, co dělat se souborem.
Tam je fread, fgetc, fscanf. Toto jsou všechny čtecích funkcí.
Pro psaní máme fwrite, máme fputc místo fgetc.
Máme také fprintf jako jsme viděli na kvíz.
Jelikož se jedná o problém, který se týká čtení ze souboru,
budeme používat jeden z těchto tří funkcí.
Nebudeme používat tyto funkce tady dole.
Tyto funkce jsou všechny nalezené ve standardním I / O knihovny.
Takže když se podíváte na horní části tohoto programu,
můžete vidět, že jsme již zahrnuty hlavičkový soubor pro standardní I / O knihovny.
Chceme-li zjistit, který z nich chceme použít,
můžeme vždy otevřít manuálové stránky.
Takže můžeme psát man stdio
a přečtěte si vše o stdio vstupních a výstupních funkcí v C
A už můžeme vidět oh, podívej. Je to zmínit fgetc, to zmínit fputc.
Takže můžete vrtat se trochu a podívejte se na, řekněme, fgetc
a podívejte se na jeho manuálové stránce.
Můžete vidět, že to jde ruku v ruce s celou partou dalších funkcí:
fgetc, fgets, getc, getchar, dostane, ungetc, a jeho vstup znaků a řetězců.
Tak to je, jak čteme ve znacích a řetězce ze souboru ze standardního vstupu,
který je v podstatě od uživatele.
A to je, jak to děláme ve skutečném C.
Takže to nepoužívá GetString a getchar funkcí
že jsme použili z CS50 knihovny.
Budeme dělat tento problém v několika způsoby
takže můžete vidět dva různé způsoby, jak dělat to.
Oba fread funkce, které Daniel zmínil a fgetc jsou dobré způsoby, jak to udělat.
Myslím, že fgetc je trochu jednodušší, protože je to jen má, jak vidíte,
jeden argument, soubor *, že se snažíme číst znak z,
a jeho návratová hodnota je int.
A to je trochu matoucí, že jo?
>> Protože jsme stále charakter, tak proč není tento návrat char?
Vy máte nějaké nápady, proč je toto nemusí vrátit char?
[Missy odpovědi, nesrozumitelné] >> Jo. Takže Missy je naprostou pravdu.
Pokud je to ASCII, pak celé číslo může být mapována na skutečné char.
Mohlo by to být ASCII znak, a to je pravda.
To je přesně to, co se děje.
Používáme int prostě proto, že má více bitů.
Je to větší než char; naše char má pouze 8 bitů, které 1 byte na našich 32-bitových strojích.
A int má hodnotu všech 4 bytů "prostoru.
A ukázalo se, že způsob, jakým fgetc funguje,
pokud bychom posunout dolů v našem přehledu v této manuálové stránce trochu,
rolovat celou cestu dolů. Ukazuje se, že použití tohoto zvláštního hodnotu s názvem EOF.
Je to zvláštní konstantu jako návratová hodnota funkce fgetc
když narazí na konec souboru, nebo pokud se vyskytne chyba.
A ukázalo se, že k tomu tyto srovnání s EOF správně,
Chcete-li mít extra množství informací, které máte v int
na rozdíl od použití char proměnné.
I když fgetc je skutečně dostat znak ze souboru,
si chcete zapamatovat, že se vrací něco, co je typu int na vás.
To znamená, že je to docela snadné.
Je nám dá charakter, takže vše, co musíte udělat, je pořád ptají soubor,
"Dej mi další znak, dej mi další znak, dej mi další znak,"
dokud se na konec souboru.
A to bude tahat v jednom znaku v době od našeho souboru,
a pak můžeme dělat, co chceme s ní.
Můžeme uložit, můžeme přidat na řetězec, můžeme ji vytisknout.
Dělat nic z toho.
>> Zvětšení zpátky a jít zpátky do našeho cat.c programu,
pokud budeme používat fgetc,
jak bychom mohli přistupovat k tomuto další řádek kódu?
Budeme používat - fread bude dělat něco trochu jiného.
A tentokrát, jsme jen tak použít fgetc dostat jeden znak v čase.
Chcete-li zpracovat celý soubor, možná to, co máme dělat?
Kolik znaků je tam v souboru?
Existuje mnoho. Takže budete pravděpodobně chtít, aby si jeden
a pak se další a získat další a získat další.
Jaký druh algoritmu si myslíš, že možná budeme muset použít tu?
Jaký typ -? [Alexander] pro smyčce? Přesně >>.
Nějaký typ smyčky.
Pro smyčky, je ve skutečnosti velký, v tomto případě.
A jak jsi říkal, že to zní jako chcete smyčku přes celý soubor,
dostat po znacích.
Nějaké návrhy na to, co by mohla vypadat?
[Alexander, nesrozumitelným]
Dobře >>, jen mi řekni, v angličtině to, co se snažíte udělat? [Alexander, nesrozumitelným]
Takže v tomto případě, to zní, jako bychom jen snažíte smyčky přes celý soubor.
[Alexander] Tak i > Velikost -?
Myslím, že velikost souboru, ne? Velikost - Dáme jen napsat to takhle.
Velikost souboru pro bytí času, i + +.
Tak to dopadá, že způsob, jakým to uděláte pomocí fgetc, a to je nové,
je to, že neexistuje žádný jednoduchý způsob, jak jen dostat velikost souboru
s tímto "sizeof" typu konstrukce, které jste předtím neviděli.
Když použijeme tuto fgetc funkci, jsme zavádí nějaký
nové, funky syntax to pro smyčce, kde namísto použití jen základní počítadlo
jít znak po znaku, budeme tahat jeden znak v době,
jeden znak v době, a způsob, jakým my víme, že jsme na konci
není, když jsme napočítali určitý počet znaků,
ale když postava se vytáhnout, je, že zvláštní konec souboru znak.
Tak jsme to udělat - já ji nazývám tuto ch, a budeme ji inicializovat
s naší první výzvy, aby si první znak z souboru.
Takže této části přímo zde, to dostane znak z souboru
a uložit jej do proměnné ch.
Budeme to dělat tak dlouho, dokud se dostaneme na konec souboru,
které děláme při testování na charakteru nesmí je rovna k této zvláštní povaze OSZ.
A pak místo toho, aby dělal ch + +, který by jen zvyšovat hodnotu,
takže pokud čteme o A ven spisu, kapitál, řekněme,
ch + + by nám b, a pak bychom si C a pak d.
To zjevně není to, co chceme. To, co chceme zde
v tomto posledním bitu je chceme získat další znak ze souboru.
>> Tak jak bychom mohli získat další znak ze souboru?
Jak se dostat na první znak ze souboru?
[Student] fgetfile? >> Fgetc, nebo, je mi líto, že jsi naprostou pravdu.
I chybně to tam. Tak jo.
Zde místo provádění ch + +,
jsme jen tak zavolat fgetc (soubor) znovu
a uložit výsledek v naší stejném ch proměnné.
[Student otázka, nesrozumitelným]
>> To je místo, kde tito lidé soubor * jsou zvláštní.
Způsob jejich práce je, že - při prvním otevření - při prvním dělat, že fopen volání,
FILE * účinně slouží jako ukazatel na začátek souboru.
A pak pokaždé, když volání fgetc, to se pohybuje jeden znak v souboru.
Takže pokaždé, když říkáš, že jste zvyšování ukazatel souboru o jeden znak.
A když fgetc znovu, se stěhujete to jiný charakter
a jiný charakter a jiný charakter a jiný znak.
[Student otázka, nesrozumitelné] >> A to je - ano.
Je to druh této magie pod kapotou.
Stačí držet zvyšování prostřednictvím.
V tomto bodě, jste schopni skutečně pracovat s charakterem.
Tak jak bychom mohli vytisknout na obrazovku, teď?
Můžeme použít stejný printf věc, kterou jsme použili předtím.
To jsme byli s využitím všech semestr.
Můžeme zavolat printf,
a můžeme předat v charakteru, stejně jako to.
Dalším způsobem, jak to udělat, je spíše než pomocí printf a mají co do činění tento formát řetězce,
můžeme také použít jeden z dalších funkcí.
Můžeme použít fputc, která tiskne znak na obrazovce,
s výjimkou, pokud se podíváme na fputc - dovolte mi vzdálíte trochu.
Vidíme to, co je pěkné, je to má v povaze, že čteme s použitím fgetc,
ale pak musíme dát jí proud se bude tisknout.
Můžeme také použít putchar funkci, která bude klást přímo na standardní výstup.
Takže tam jsou celá parta různých možností, které můžeme použít pro tisk.
Všichni jsou ve standardním I / O knihovny.
Kdykoliv budete chtít vytisknout - to printf, ve výchozím nastavení, bude tisknout na speciální normy ven proudu,
který je, že stdout.
Takže můžeme jen odkazovat se na to jako druh tohoto kouzelného hodnoty, stdout zde.
Chybička se vloudila. Dejte středník mimo.
>> To je hodně nových, funky informací zde.
Mnoho z toho je velmi idiomatická, v tom smyslu, že je to kód
, který je psán tato cesta jen proto, že je to čistý číst, snadno čitelný.
Existuje mnoho různých způsobů, jak to udělat, mnoho různých funkcí, které můžete použít,
ale máme tendenci postupujte podle následujících stejné vzorce znovu a znovu.
Takže nebuďte překvapeni, když uvidíte kód, jako to přichází znovu a znovu.
Dobrá. V tomto bodě, musíme zlomit na den.
Díky, že jste přišli. Díky za sledování, pokud jste on-line. A uvidíme se příští týden.
[CS50.TV]