[Powered by Google Translate] [5. szakasz - További Comfortable] [Rob Bowden - Harvard University] [Ez CS50. - CS50.TV] Mint mondtam az én e-mail, van egy csomó dolog, amit használni más, mint a készüléket ténylegesen a probléma készletek. Javasoljuk, hogy csinálnád a készüléket csak azért, mert akkor könnyebben tudnak segíteni , és tudjuk, hogyan mindent fog működni. De egy példa arra, ahol meg tudod csinálni a dolgokat, ha, mondjuk, ha nem fér hozzá egy készülék vagy szeretne dolgozni a Science Center alagsorában - amely valójában ezek a készülék is - ha azt szeretnénk, hogy bárhol dolgozni. Egy példa láttad / hallott SSH? SSH alapvetően, mint csatlakozni a valamit. Igazából, most én SSHed a készülékbe. Soha nem dolgozik közvetlenül a készülékbe. Itt van a készülék, és ha megnézi itt lent látod ezt az IP címet. Soha nem dolgoznak a készüléken; Mindig jön át egy iTerm2 ablakhoz / terminál ablakot. Tudod SSH e IP-címet, ssh jharvard@192.168.129.128. Emlékszem, ez a szám nagyon könnyen, mert ez egy ilyen szép mintát. De ez meg fogja kérdezni tőlem a jelszót, és most én vagyok a készüléket. Alapvetően ezen a ponton, ha megnyitotta a terminál a készülék belsejét is, ezt a felületet, de akkor használni, pontosan ugyanaz mivel a felület Én használ ide, de most te SSHed. Nem kell SSH a készüléket. Egy példa a másik hely, amit lehetett SSH Most biztos vagyok benne, akkor alapértelmezés szerint - Oh. Bigger. Minden akkor kell alapértelmezett FAS beszámoló a FAS szervereket. Számomra, szeretném, hogy SSH rbowden@nice.fas.harvard.edu. Meg fog kérni, hogy az első alkalommal, és azt mondod: igen. A jelszó csak lesz a FAS jelszót. És így most, én SSHed a szép szerverek, és meg tudom csinálni, amit akarok itt. Sok osztályok lehet venni, mint például a 124, kell majd töltesz cucc ide hogy ténylegesen be a probléma készletek. De azt mondják, hogy nem férnek hozzá a készüléket. Akkor meg tudod csinálni a dolgokat, mint itt, azt fogja mondani - Ez csak a mi szakasza kérdésekre. Azt fogja kérni, hogy ezt a készüléket. Ehelyett én csak csinálni a kiszolgálón. Megyek unzip ezt. A probléma az lesz, hogy te vagy használt használ valami ilyesmit gedit vagy bármi a készülék belsejét. Ugye nem megy, hogy, hogy a FAS kiszolgálón. Ez az egész csak lesz ennek szöveges felület. Szóval akkor vagy az egyik, próbálja megtanulni egy szövegszerkesztőbe, hogy azok rendelkeznek. Ezek Nano. Nano általában nagyon könnyen használható. Használhatja a nyilakat, és írja be a szokásos módon. Szóval ez nem nehéz. Ha azt szeretnénk, hogy valóban képzelet segítségével Emacs, amit talán nem kellett volna megnyitni, mert nem is tudom, hogyan zárja Emacs. Ellenőrző X, Control C? Igen. Vagy használhatja Vim, ami az, amit használ. És ezek a lehetőségek. Ha nem akarom, akkor is, ha megnézi manual.cs50.net-- Oh. Egy PC segítségével SSH segítségével PuTTY, amely fogsz kell letölteni külön-külön. Egy Mac, akkor csak alapértelmezésben használat Terminal, vagy letölthető iTerm2, ami olyan, mint egy szép, díszes Terminal. Ha megy manual.cs50.net látni fog egy linket Notepad + +, ami az, amit tud használni a PC-n. Ez lehetővé teszi, SFTP honnan Notepad + +, ami alapvetően SSH. Mi ez engedi tennie, szerkesztheti a fájlokat a helyi, majd, amikor csak akarja, hogy megmentse őket, akkor mentés nice.fas, ahol lehet majd futtatni őket. És a megfelelője a Mac lesz TextWrangler. Így lehetővé teszi, hogy nem ugyanaz a dolog. Ez lehetővé teszi a fájlok szerkesztéséhez helyi és mentse őket nice.fas, ahol lehet majd futtatni őket. Szóval, ha valaha megragadt nélküli készüléket, akkor ezeket a lehetőségeket hogy még mindig nem a probléma készletek. Az egyik probléma az lesz, hogy nem fogod, hogy a CS50 könyvtár mert nice.fas nem alapértelmezés szerint van, hogy. Akkor vagy le a CS50 könyvtár - Azt hiszem, nem kell, hogy ezen a ponton. Akkor vagy le a CS50 könyvtárat, és másolja át nice.fas, vagy azt hiszem, ezen a ponton nem használja többé egyébként. Vagy ha igen, akkor az időt, hogy a helyébe Az implementáció a funkciók CS50 könyvtárban egyébként. Tehát nem kell, hogy sok korlátozást. És ennyi. Megyek vissza a készülék most, és mi mindent megteszünk a készülékbe. Keresi a mi szakaszán kérdések az elején, mint mondtam az én e-mail, meg kell beszélni egy rövid akkor kellett volna nézni. Megvan az átirányító & csövek és e három kérdésre. Mely patak nem úgy működik, mint printf levelet alapértelmezés szerint? Szóval stream. Mi az a patak? A patak alapvetően mintha ez csak néhány - Ez még csak nem is a forrás 1 és 0. A patak ez kér itt szabványos ki. És így szabvány meg egy patak, hogy amikor írsz rá, úgy tűnik a képernyőn. Szabványos ki, a patak, ez azt jelenti, hogy csak annyit írj 1 és 0 rá, és a másik végét a szabványos ki csak olvas az patak. Ez csak egy húr a 1 és 0. Írhat a folyamok vagy tudod olvasni patakok attól függően, hogy mi a patak valójában. A másik két alapértelmezett stream standard és standard hiba. Standard az, amikor te getString, ez vár rád a bemenő dolgokat. Tehát ez vár rád, ez valójában vár szabvány, amely valójában mit kapunk, ha beírja a billentyűzeten. Maga írja a szabványos be Standard hiba alapvetően egyenértékű a szabványos ki, de szakosodott, hogy ha nyomtatni standard hiba, kéne, hogy csak nyomtatni hibaüzeneteket e így különbséget tenni a normál üzenet kerül a képernyőre versus hibaüzenetek attól függően, hogy mentek a standard, vagy standard hibája. Fájlok is. Szabványos ki, standard, és a standard hiba csak különleges patakok, de tényleg bármilyen fájlt, ha megnyit egy fájlt, ez lesz a patak bájt ahol csak olvasni, hogy a patak. Te, a legtöbb, akkor gondolj egy fájlt patak bájt. Szóval mit patakok nem írnak, hogy alapértelmezés szerint? Szabványos ki. Mi a különbség a> és >>? Volt valaki nézze meg a videót előre? Oké. > Lesz, hogyan átirányítás a fájlokat, és >> nem fogja átirányítani kimenetet kép, de ez inkább fog hozzáfűzni a fájl. Például, mondjuk én véletlenül dict itt, és az egyetlen anyag belseje dict jelentése macska, macska, kutya, hal, kutya. Egy parancs, hogy van a parancssorban is macska, ami csak nyomdába, mi van a fájlban. Tehát amikor azt mondom macska dict, ez nyomdába macska, macska, kutya, hal, kutya. Ez minden macska nem. Ez azt jelenti, hogy a nyomtatott szabványos ki macska, macska, kutya, hal, kutya. Ha azt szeretnénk, hogy ahelyett, hogy az átirányítást egy fájlra, tudom használni>, és átirányítja azt amit a fájl. Hívom a file. Tehát most ha én ls, meglátom, van egy új fájlt nevű fájlt. És ha én nyisd ki, ez megy, hogy pontosan milyen macskát helyezni a parancssorban. Tehát most ha megteszem újra, akkor fogja átirányítani a kimenetet fájlba, és megyek, hogy pontosan ugyanolyan dolog. Szóval technikailag, teljesen nyíltságot felülírhatják amink volt. És majd meglátjuk, ha tudom megváltoztatni dict, Kivettem kutya. Most, ha macska dict fájlba újra megyünk, hogy az új verzió kutya eltávolították. Tehát teljesen felülírja azt. Ehelyett, ha az általunk használt >>, ez lesz hozzáfűzni fájlt. Most, fájl megnyitásakor, látjuk már csak ugyanaz a dolog nyomtatott kétszer mert ott egyszer, akkor csatolni kell az eredeti. Szóval, ez az, amit> és >> csinálni. Vajon a következő egy kérdezze - Ez nem kérdez rá. A másik, hogy van-e <, ami ha> átirányítja a szabványos ki, te 2>, ez átirányítása standard hibája. Tehát, ha valami elment standard hiba, akkor nem kap helyezett txt2. De észre, ha én 2>, akkor még mindig nyomtatás Hello, Rob! a parancssorba mert én csak átirányításával standard hiba, nem vagyok átirányítása szabványos ki. Standard hiba és standard out különböző. Ha akarta, hogy ténylegesen írni a standard hiba, akkor tudtam változtatni, hogy ez fprintf az stderr. Szóval printf alapértelmezés szerint kiírja a szabványos ki. Ha azt szeretnénk, hogy nyomtatni standard hiba manuálisan, akkor azt kell használni fprintf és meghatározza, hogy mit akarok nyomtatni. Ha ehelyett tettem fprintf stdout, akkor ez lényegében egyenértékű a printf. De fprintf a standard hiba. Tehát most, ha én irányítani ezt figyelembe txt2, Hello, Rob! még mindig egyre nyomtatva a parancssorban mivel ez kezd nyomtatni a szabványos hiba, és én csak átirányítása szabványos ki. Ha most átirányítás standard hiba, most már nem kap nyomtatott, és txt2 lesz Hello, Rob! Tehát most, akkor nyomtassa ki a tényleges hibák standard hiba és nyomtassa ki a rendszeres üzeneteket a szabványos ki. És így, amikor futtatja a programot, futtathatja azt. / Hello ilyen típusú, a 2> úgy, hogy a program fog futni rendesen, de minden hibaüzeneteket kapsz akkor megtekintéséhez később a error log, olyan hibákat, majd nézze meg később, és a hibák fájl bármilyen hiba történt. Kérdései vannak? Az utolsó egy cső, amit lehet gondolni, mint vevő a szabványos ki egy parancsot , és ezzel a szabvány a következő parancsot. Egy példa itt echo egy parancssori dolog hogy csak megy, echo, amit tettem, mint érvelését. Nem fogom idézetek. Echo bla, bla, bla éppen nyomdába bla, bla, bla. Előtt, amikor azt mondtam, el kellett halasztania Rob egy txt fájlba mert én csak átirányítani txt fájlokat, ahelyett, / ha én echo Rob majd a cső be. / hello, amely szintén nem ugyanaz a típusú dolog. Ezt figyelembe a parancs kimenete, echo Rob, és használja, mint a bemenet. / hello. Azt hiszem, hogy ez egy elsőnek echo Rob fájlba majd viszi be. / hello, hogy a fájl az éppen kimeneten. De azon az ideiglenes fájlt ki a képet. Kérdések az? A következő kérdés az lesz, hogy vonják ezt. Mit csővezeték használja, hogy megtalálja a számos egyedi nevek nevű fájlt names.txt? A parancsok fogunk használni kívánt itt egyedi, így uniq, majd a wc. Meg tudod csinálni ember uniq, hogy ténylegesen nézni, hogy ez mit jelent, és ez csak úgy, hogy kiszűrje szomszédos megfelelő sorokat a bemenet. És a férfi wc fog nyomtatni az új sor, szó, és a byte számít minden fájlt. És az utolsó fogunk használni kívánt egyfajta, ami majd csak egyfajta vonalak txt fájl. Ha azt, hogy néhány txt fájl, names.txt, és ez Rob, Tommy, Joseph, Tommy, Joseph, RJ, Rob, hogy mit akarok itt találja a számos egyedi nevek ebben a fájlban. Szóval, mi legyen a válasz lenni? >> [Hallgató] 4. >> Igen. Meg kell 4 óta Rob, Tommy, Joseph, RJ az egyetlen egyedi nevek ebben a fájlban. Az első lépés, ha csak nem szóból on names.txt, ez tényleg mond el mindent. Ez valójában nyomtatás - Lássuk, férfi wc - újsor, szavak és Bájtszám. Ha csak érdekel a sorok, akkor én is csak csináld wc-l names.txt. Szóval ez az 1. lépést. De én nem akarok wc-l names.txt mert names.txt csak tartalmazza mindazokat a neveket, és azt akarom, hogy kiszűrje a nem egyedi is. Szóval, ha én uniq names.txt, hogy nem egészen add nekem, amit akarok mert a duplikált nevek még mindig ott vannak. Miért van ez? Miért uniq nem azt teszi, amit akarok? [Hallgató] A másolatok nem [hallható] >> Igen. Ne feledje, a man oldalt a uniq mondja szűrő szomszédos illeszkedő sorokat. Ők nem szomszédos, így nem fogja kiszűrni őket. Ha rendezni őket először, egyfajta names.txt megy, hogy az összes ismétlődő sorok együtt. Tehát most sort names.txt hogy. Fogom használni kívánt, hogy mivel a bemeneti uniq, ami | uniq. Ez ad nekem Joseph, RJ, Rob, Tommy, és szeretném használni, hogy a bemeneti wc-l, amely fog adni nekem 4. Mint azt mondja itt, mit csővezeték használ? Meg tudod csinálni egy csomó dolgot, mint egy sor parancs ha használja a kimenet egyik parancs a bemenet a következő parancsot. Meg tudod csinálni egy csomó dolgot, sok okos dolgot. Kérdései vannak? Oké. Ennyi csövek és átirányítása. Most megy a tényleges dolgokat, a kódolási dolgokat. Belül a PDF, látni fogod ezt a parancsot, és akkor szeretné futtatni ezt a parancsot a készülékben. wget a parancs csak arra, hogy valamit az interneten, alapjában véve, így wget és URL. Ha ment az URL a böngészőben, akkor letölteni ezt a fájlt. Én csak kattintott rá, így a letöltött fájlt nekem. De írásban wget e dolog belsejében a terminál csak megy letöltéséhez be terminál. Én section5.zip, és akkor szeretnénk unzip section5.zip, amely majd kapsz egy mappát nevű 5. pontjának, ami megy, hogy az összes fájlt fogunk használni ma benne. Mivel ezek a programok "fájlneveket sugallják, ők egy kicsit bugos, így a küldetése, hogy kitaláljuk, miért használ gdb. Mindenki azt nekik Letöltött / tudják, hogyan kell kérni őket Letöltött be a készülék? Oké. Futás ./buggy1, azt fogja mondani Segmentation fault (core dump), amely minden alkalommal, amikor kap egy segfault, ez egy rossz dolog. Milyen körülmények között nem kapja segfault? [Hallgató] Dereferencing egy null pointer. >> Igen. Annak érdekében, hogy csak egy példa. Dereferencing null pointer fogsz kapni a segfault. Milyen segfault azt jelenti, amit megható memória nem kell érjen. Tehát dereferencing null pointer hozzáér cím 0, és lényegében az összes számítógép manapság azt mondják, hogy a 0 címet a memória nem kell érjen. Szóval ezért dereferencing null pointer eredményez segfault. Ha történetesen nem inicializálja a mutatót, akkor egy szemét érték, és így, amikor megpróbál dereference azt minden valószínűség amit megható memória ez a semmi közepén. Ha történetesen szerencsés, és a szemetet érték történt, hogy pont valahol a verem, vagy valami, majd amikor dereference hogy pointer, amelyek még nem inicializált, semmi baj. De ha ez mutat, mondjuk, valahol a stack és a heap, vagy ez mutat csak valahol, hogy nem használja a program még akkor már megható memória nem kell érjen, és segfault. Amikor leír egy rekurzív függvény, és ez recurses túl sokszor és a stack nő túl nagy, és a köteget ütközik a dolgok hogy nem kell az ütközést, te megható memória nem kell megható, így segfault. Ez az, amit egy segfault van. Ez is ugyanebből az okból, hogy ha van egy string, mint - menjünk vissza az előző programhoz. In hello.c--Én csak megy, hogy valami mást. char * s = "hello world!"; Ha valaki használja a * s = vagy valami s [0] = 'X'; úgyhogy győződjön hello,. / hello, miért azt segfault? Miért ez a segfault? Mit vársz történni? Ha én tettem printf ("% s \ n", s), mit vársz a nyomtatandó? [Hallgató] X hello. >> Igen. A probléma az, hogy amikor nyilvánítja egy string, mint ez, s egy mutató, hogy fog menni a stack, és mi s mutat ez a szöveg, amely tartalmazza a csak olvasható memória. Tehát csak a neve, csak olvasható memória, akkor az ötlet hogy ha megpróbál változtatni, mi van a csak olvasható memória, csinál valamit, amit nem kellene ezzel a memória és segfault. Ez valójában egy nagy különbség char * s és char s []. Szóval char s [], most ez a sztring fog tenni a stack, és a verem, nem csak olvasható, ami azt jelenti, hogy ez működik tökéletesen. És igen. Ne feledje, hogy amikor én char * s = "hello world!", S maga a verem de s rámutat arra, hogy valahol máshol, és hogy valahol máshol történik, hogy csak olvasható. De char s [] csak valami a verem. Szóval ez egy másik példa a segfault történik. Láttuk, hogy ./buggy1 eredményezett segfault. Elméletileg, nem kell nézni buggy1.c azonnal. Ehelyett, akkor nézd meg a gdb. Figyelje meg, hogy amikor megkapja Segmentation fault (core dump), Önnek ezt a fájlt ide nevezett mag. Ha ls-l, látni fogjuk, hogy a mag általában elég nagy fájlt. Ez a bájtok száma a fájl, így úgy néz ki, ez 250-valami kilobyte. Ennek az az oka, hogy amit az veremkiíratást valójában amikor a program lefagy, az állam a memória a program Csak kap illesztenie ezt a fájlt. Ez lesz dömpingelt figyelembe, hogy a fájl. Ez a program, miközben azt is fut, történt, hogy egy memóriahasználat mintegy 250 kilobyte, és így ez az, amit kaptam dömpingelt ebbe a fájlba. Most nézd meg ezt a fájlt, ha nem teszünk gdb buggy1 mag. Mi csak ezt gdb buggy1, és hogy majd csak elindul gdb rendszeresen, használja buggy1 mint a bemeneti fájl. De ha gdb buggy1 mag, akkor ez kifejezetten fog indítani gdb megnézi, hogy a core fájlt. És mondja buggy1 eszközök gdb tudja, hogy core fájlt származik buggy1 program. Szóval gdb buggy1 mag fog azonnal hoz nekünk , ahol a programot történt megszüntetésére. Látunk itt Program szüntetni jel 11-Segmentation fault. Mi történik, ha egy sor szerelvény, amely valószínűleg nem nagyon hasznos. De ha beírja bt vagy backtrace, ez lesz a függvény hogy megadja nekünk a lista a jelenlegi verem kereteket. Szóval backtrace. Úgy néz ki, már csak két verem kereteket. Az első fő stack frame, a második pedig a verem keret ezt a funkciót, hogy mi történik, hogy legyen, amely úgy néz ki, mint mi csak a szerelvény kód. Akkor menjünk vissza a fő funkciója, és erre tehetünk keret 1, és azt hiszem, mi is ezt le, de én szinte soha nem le - vagy felfelé. Igen. Fel és le. Up hozza létre egy verem keret megállapításáról hozza le egy verem keret. Én inkább nem használni. Csak kifejezetten mondom 1. keret, amely a megy a keret jelölése 1. Keret 1 fog hozni minket fő stack frame, és azt mondja, itt a sorban a kódot, történetesen a. Ha volna még egy pár sornyi kódot, azt mondhatjuk, lista, és ez fog adni nekünk minden sornyi kódot körül. A vonal amit segfaulted at 6 volt: if (strcmp ("CS50 sziklák", argv [1]) == 0). Ha nem egyértelmű még, akkor kap egyenesen az itt csak a gondolkodás, hogy miért segfaulted. De vehetjük, hogy egy lépéssel tovább, és azt mondják: "Miért argv [1] segfault?" Nézzük print argv [1], és úgy néz ki ez az 0x0, ami a null mutató. Mi strcmping CS50 sziklák és null, és hogy fog segfault. És miért argv [1] null? [Hallgató] Mivel nem adja meg semmilyen parancssori argumentumok. Igen. Mi nem adja meg semmilyen parancssori argumentumok. Tehát ./buggy1 csak megy, hogy argv [0] lesz ./buggy1. Ez nem megy, hogy egy argv [1], hogy fog segfault. De ha ehelyett én csak CS50, ez fog mondani Kapsz egy D mert ez az, amit kéne csinálni. Nézve buggy1.c, ez állítólag print "Kapsz egy D" - Ha az argv [1] A nem "CS50 sziklákat", "Kapsz egy D", más "Kapsz egy A!" Szóval, ha azt szeretné, hogy A, szükségünk van erre összehasonlítani, mint igaz, ami azt jelenti, hogy összehasonlítja 0-ra. Szóval, argv [1] kell "CS50 sziklák". Ha azt akarod, hogy a parancssorban, akkor kell használni, \, hogy elkerülje a helyet. Szóval CS50 \ sziklák és kapsz egy A! Ha nem teszed a backslash, miért ez nem működik? [Hallgató] Ez két különböző érveket. >> Igen. Argv [1] lesz CS50, és argv [2] lesz sziklák. Oké. Most ./buggy2 fog segfault újra. Ahelyett, hogy kinyitotta a core fájlt, akkor csak megnyitja buggy2 közvetlenül, így gdb buggy2. Most, ha csak fut a program, akkor ez fog mondani Program vett jelet SIGSEGV, amely a segfault jel, és ez az, ahol az történt, hogy megtörténjen. Keresi a mi backtrace, azt látjuk, hogy mi volt a funkció oh_no, amely által hívott függvény Dinky, amit hívott függvény Muci, amit hívott fő. Azt is látni az érveket, hogy ezeket a funkciókat. Az az érv, hogy takaros és Muci 1. volt. Ha sorolja a funkciót oh_no, azt látjuk, hogy oh_no éppen csinál char ** s = NULL; * S = "BOOM"; Miért, hogy nem? [Hallgató] Nem lehet feloldani a null pointer? >> Igen. Ez csak azt mondom, s NULL, függetlenül attól, hogy ez történik, hogy egy char **, amely, attól függően, hogy hogyan értelmezzük azt, lehet, hogy a mutató egy mutató egy string vagy egy sor húrok. Ez s NULL, tehát * s dereferencing egy null pointer, és így ez fog zuhanni. Ez az egyik leggyorsabb módon lehet esetleg segfault. Ez csak nyilvánító null pointer és azonnal segfaulting. Ez az, amit oh_no csinál. Ha felmegyünk egy keret, akkor fogunk bejutni a funkció hívott oh_no. Azt kell csinálni, hogy le. Ha nem adja meg a parancsot, és csak nyomja meg újra az Enter, akkor csak ismételje meg az előző parancsot, hogy futott. Mi vagyunk a keretben 1. Lista ez a keret, azt látjuk, itt a mi funkció. A találati lista újra, vagy meg tudod csinálni listát 20 és kiírja tovább. A funkció Dinky mondja, ha i = 1, akkor megy a oh_no funkció más megy a feszes funkciót. És tudjuk, i = 1, mert megtörténhet, hogy ide hogy Dinky hívták azzal az érvvel 1. Vagy csak nem nyomtatni i és azt fogja mondani i 1 lehet. Jelenleg is takaros, és ha elmegyünk egy másik frame, tudjuk, mi a végén Muci. Up. Most vagyunk Muci. Felsorolása ezt a funkciót - a lista előtti 1/2 vágott le engem - úgy indult, mint ha én 0, akkor fogjuk hívni oh_no, különben hívja takaros. Tudjuk, hogy voltam 1, ezért úgynevezett takaros. És most újra itt vagyunk a fő, és fontosabb éppen lesz int i = rand ()% 3; Ez csak megy, hogy ön egy véletlen számot, amely vagy 0, 1, vagy 2. Meg fog hívni Muci ezzel a számmal, és vissza fog térni 0. Nézi most ezt, Csak séta a program kézi nélkül fut, hogy azonnal, akkor be egy töréspontot a fő, ami azt jelenti, hogy amikor a program futtatásához A program fut, amíg eléri a töréspontot. Így fut a program, akkor fog futni, és akkor majd nyomja meg a fő funkciója, és leáll. Most bent vagyunk a fő, és a lépést vagy mellette fog hozni minket a következő sort. Meg tudod csinálni, vagy a következő lépést. Következő slágere, most már van állítva rand ()% 3, így tudjuk nyomtatni az i értékét, és azt fogja mondani, i 1 lehet. Most nem számít, hogy az általunk használt vagy következő lépés. Azt hiszem, ez számít az előző, de azt szeretnénk használni a következő. Ha az általunk használt lépésben, belépünk a funkció, ami azt jelenti, nézd meg a tényleges dolog ez történik belül Muci. Ha az általunk használt mellett, akkor az azt jelenti, megy át a függvény és csak megy a következő sort a mi fő funkciója. Itt ezen a vonalon, voltam, ahol azt mondta, rand ()% 3; ha mégis lépést, akkor menj be a végrehajtását rand és nézd meg, mi történik ott, és én végig a rand függvény. De nem érdekel a rand függvényt. Csak azt akarom, hogy ugorjon a következő sort a fő, ezért használja a következő. De most már nem érdekel a Muci funkciót, ezért szeretném, hogy belépjünk ezt. Most vagyok Muci. Az első sort fog mondani, ha (i == 0), én egy lépést, azt látjuk, hogy a végén a takaros. Ha lista dolgokat, azt látjuk, hogy ellenőrzött i = 0. i nem egyenlő 0-val, így elment a más feltételt, amely a fog hívni takaros (i). Lehet, hogy összezavarodnak. Ha csak nézd meg ezeket a sorokat közvetlenül, akkor hiszem, ha (i == 0), oké, aztán tett egy lépést, és most én vagyok a takaros (i), azt gondolhatja, hogy azt jelenti i = 0, vagy ilyesmi. Nem, csak azt jelenti, hogy tudja, akkor ragaszkodni közvetlenül a hálózati takaros (i). Mert én nem 0, a következő lépés nem fog véget a mást. Különben nem egy sort, hogy fog megállni. Ez csak fog menni a következő sorra, hogy ténylegesen végre, ami takaros (i). Lépve Dinky (i), azt látjuk, hogy (i == 1). Tudjuk, i = 1, így amikor belépünk, tudjuk, mi lesz a vége fel oh_no mert i = 1 meghívja a függvényt oh_no, amelyek segítségével belép, amely a fog beállítani char ** s = NULL és azonnal "BOOM". És akkor tényleg nézi most végrehajtásának buggy2, ezt, az i csak most egy véletlen szám - 0, 1, vagy 2 - hívás Muci, amelyek, ha i értéke 0 szólít oh_no, különben arra kéri Dinky, ami jön ide. Ha én 1, hívás oh_no, különben hívja feszes, ami jön ide, ha i = 2, hívja oh_no. Nem is hiszem, hogy van egy módja - Látja valaki egy módja annak, hogy ezt a programot, amely nem segfault? Mert hacsak nem én vagyok hiányzik valami, ha én értéke 0, akkor azonnal segfault, mást elmész egy függvény, amely, ha én az 1 ha segfault, mást elmész egy függvény, ahol ha az i 2-t segfault. Tehát nem számít, mit teszel, segfault. Azt hiszem, az egyik módja a rögzítés lenne, ahelyett, hogy char ** s = NULL, akkor malloc helyet adott string. Megtehetjük malloc (sizeof) - sizeof mi? [Hallgató] (char) * 5? >> Vajon ez úgy tűnik, nem igaz? Én feltételezve, hogy ez működni fog, ha én valóban futott, de ez nem az, amit én keresek. Nézd típusának s. Adjunk hozzá int *, így int * x. Én megtenném malloc (sizeof (int)). Vagy ha akartam egy sor 5, megtenném (sizeof (int) * 5); Mit tegyek, ha egy int **? Mit tettem volna malloc? [Hallgató] mérete a mutatót. >> Igen. (Sizeof (int *)); Ugyanaz itt lent. Azt akarom, (sizeof (char *)); Ez fog kiosztani hely a mutató, amely rámutat, hogy "BOOM". Nem kell kiosztani hely "BOOM" maga mert ez alapvetően megegyezik azzal, amit korábban mondtam A char * x = "BOOM". "BOOM" már létezik. Előfordul, hogy létezik a csak olvasható régió memória. De ez már létezik, ami ezt a kódsort, ha s egy char **, akkor * s egy char * és te ha ezt char * hogy pont a "BOOM". Ha akartam másolni "BOOM" be s, akkor azt kell, hogy fordítsanak helyet s. Megteszek * s = malloc (sizeof (char) * 5); Miért 5? Miért nem 4? Úgy néz ki, mint a "boom" a 4 karakter. >> [Hallgató] A null karakter. Igen. Minden a húrok lesz szüksége a null karakter. Most már meg tudom csinálni valami hasonlót strcat - Mi a szerepe a másoláshoz karakterlánc? [Hallgató] cpy? >> Strcpy. man strcpy. Szóval strcpy vagy strncpy. strncpy egy kicsit biztonságosabb, mert megadhatja, hogy pontosan hány karakter, de itt ez nem számít, mert tudjuk. Szóval strcpy és nézz az érvek. Az első érv az úti célunk. A második érv a forrás. Fogunk másolni úti célunk * s mutató "BOOM". Miért is akarod, hogy ezt a strcpy ahelyett, hogy csak amit azelőtt A * s = "BOOM"? Van egy ok, amiért érdemes ezt tenni, de mi az, hogy oka? [Hallgató] Ha szeretne valamit változtatni a "BOOM". >> Igen. Most már meg tudom csinálni valami hasonlót s [0] = 'X'; mert s rámutat arra, hogy a halom, és hely a heap hogy s mutat egy mutató több helyet a heap, amely tárolja "BOOM". Szóval ezt a példányt a "boom" van tárolva a kupac. Van technikailag két példányban a "boom" a mi program. Itt az első, hogy ez csak az ebben az "BOOM" string állandó, , a második példányt a "BOOM" strcpy létrehozta a másolatát "BOOM". De a másolatot a "boom" alatt tárolja a halom, és a kupac nyugodtan változtatni. A kupac nem csak olvasható, így azt jelenti, hogy s [0] nem hagyom, hogy módosítsa az értéket a "BOOM". Ez engedem, hogy változtatni ezeket a karaktereket. Kérdései vannak? Oké. Továbblépve a buggy3, menjünk gdb buggy3. Mi csak futtatni, és látjuk, kapunk egy segfault. Ha backtrace, már csak két funkciója van. Ha felmegyünk a mi fő funkciója, azt látjuk, hogy mi segfaulted most ezt a sort. Tehát csak nézi most ezt a vonalat, for (int vonal = 0; fgets ez a cucc nem egyenlő NULL; vonal + +). Korábbi frame hívták _IO_fgets. Látni fogod, hogy sok beépített C függvények, hogy ha kap a segfault, nem lesz igazán rejtélyes függvény nevek mint ez _IO_fgets. De hogy fog ehhez az fgets hívást. Valahol belül itt vagyunk segfaulting. Ha megnézzük az érvek fgets tudunk nyomtatni puffer. Nézzünk kinyomtatni - Oh, nem. Nyomtatás nem fog működni pontosan úgy, ahogy azt jónak látja. Nézzük meg az aktuális program. Buffer egy karakter tömb. Ez egy karakter tömb 128 karakter. Tehát amikor azt mondom nyomtatási puffer, ez fog nyomtatni e 128 karakter, ami azt hiszem, mi várható. Mit kerestem a kinyomtatni címe puffer, de ez nem igazán mondani sokat. Szóval, amikor azt történetesen mondom ide x puffer, azt mutatja nekem 0xbffff090, amely, ha emlékszel a korábbi vagy néhány pont Oxbffff inkább egy stack-szerű régióban. A stack hajlamos kezdeni valahol majdnem 0xc000. Csak az látja ezt a címet, tudom, hogy puffer történik a verem. Újraindítása a program fut, feláll, tompítása láttuk volt ez karaktersor hogy elég sok értelmetlen. Aztán nyomtatás fájl, mit jelent a fájl néz ki? [Hallgató] Null. >> Igen. Fájl olyan típusú FILE *, így a mutató, és az érték e mutató null. Szóval fgets fog próbálni, hogy olvassa el, hogy a mutató közvetett módon, hanem azért, hogy elérje az adott mutató, meg dereference azt. Vagy, hogy hozzáférhessen mit kell mutasson, akkor dereferences azt. Szóval ez dereferencing egy null pointer és segfaultol. Tudtam volna újra ott. Ha szünet a mi fő szempont és fuss, az első sorban a kód char * filename = "nonexistent.txt"; Ez kell adnia egy elég nagy tipp, hogy miért ezt a programot nem sikerül. Beírás mellett elvezet a következő sorba, ahol én megnyitni ezt a fájlt, és aztán rögtön bejutni a vonal, ahol valaha megütöttem a következő, hogy fog segfault. Valaki akar kidobni egy ok, amiért lehet segfaulting? [Hallgató] fájl nem létezik. >> Igen. Ezt állítólag egy csipetnyi hogy ha te a file megnyitásakor ellenőrizni kell, hogy a fájl valóban létezik. Tehát itt, "nonexistent.txt"; Amikor fopen fájlnév olvasatra, akkor majd meg kell mondani, if (fájl == NULL), és azt mondják printf ("A fájl nem létezik!" vagy - ami még jobb - filename); return 1; Így most nézze meg, ha ez NULL mielőtt ténylegesen folytatja és próbál olvasni a fájlt. Mi lehet a remake nem csak hogy lássa, hogy működik. Akartam, hogy egy új vonal. Tehát most nonexistent.txt nem létezik. Mindig ellenőrizze, hogy ez a fajta dolog. Mindig ellenőrizze, hogy ha fopen NULL. Mindig győződjön meg róla, hogy a malloc nem tér vissza NULL, vagy máshol segfault. Most buggy4.c. Futás. Azt hiszem ez a vár input esetleg végtelen hurok. Igen, ez végtelen hurok. Szóval buggy4. Úgy néz ki, mi vagyunk végtelen hurok. Mi lehet törni a főbb, futtassa a programot. A gdb, amíg a rövidítés használata egyértelmű vagy speciális rövidítéseket nyújtanak az Ön számára, akkor használd n használata mellett ahelyett, hogy írja ki a következő módon. És most, hogy már hit n egyszer, én is csak Enter, hogy folytassam következő ahelyett, hogy megüt n Enter, Enter n, n az Enter billentyűt. Úgy néz ki, mint én vagyok valamilyen for ciklus, ami beállítás array [i]-0-ra. Úgy néz ki, én soha kitörésre ezt hurok. Ha nyomtatni i, tehát én 2, akkor én megyek legközelebb. Én nyomtatni i, i = 3, akkor én megyek legközelebb. Majd nyomtassa i és i 3 lehet. Ezután nyomtassa i, i 4 lehet. Igazából, print sizeof (array), így a mérete tömb 20. De úgy néz ki, van néhány különleges gdb parancsot megy, amíg valami nem történik. Ez olyan, mint amelyben a feltétel értéke a változó. De nem emlékszem, hogy mi ez. Tehát ha tartani fog - Mit mondott? Mit hoztál fel? [Hallgató] Vajon megjelenítéséhez adhatok - >> Igen. Így jelenik meg tudok segíteni. Ha csak megjeleníti én, akkor tegye fel itt, mi az értéke i így nem kell nyomtassa ki minden alkalommal. Ha csak menj következő, látjuk 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5. Valami megy borzasztóan rossz, és én éppen visszaáll 0-ra. Keresi buggy4.c, azt látjuk, minden, ami történik, int array [5]; for (i = 0; i <= sizeof (array); i + +) array [i] = 0; Mit látunk, hogy baj van? Mint egy tipp, mikor csinál a gdb buggy4 - Nézzük main, run - Én print sizeof (array), hogy lássam, mi a feltétel, ahol kéne végre kitörni. Hol vagyok? Mondtam futni? Én nem nyilvánítja még. Szóval nyomtatása sizeof (array), és ez 20, ami várhatóan mióta tömb mérete 5 és ez 5-egészek, így az egész dolog, legyen az 5 * sizeof (int) bájt, ahol a sizeof (int) általában 4 legyen. Szóval sizeof (array) 20. Mit kell ez? [Hallgató] Osztva sizeof (int). >> Igen / sizeof (int). Úgy tűnik, még mindig van egy kis problémánk. Azt hiszem, ez kéne legyen < mivel ez nagyjából mindig <és soha <=. Most úgy gondolja, hogy miért ez a ténylegesen megszakadt. Tudja valaki, hogy kitalálja, miért én vissza 0-át minden iteráció a hurok? Az egyetlen dolog, belsejében van, ami történik, hogy array [i] van állítva 0-ra. Szóval valahogy, ezt a kódsort okoz mi int i kell beállítani 0-ra. [Hallgató] Lehet, hogy azért, mert ez nyomós emlékére ezen részének i ha azt hiszi, hogy a következő elem tömb? >> [Bowden] Igen. Mikor megyünk vége után a tömb, valahogy ezt a helyet, hogy mi van nyomós nyomós értéke i. És ha megnézzük a buggy4, törés fő, futás, hadd nyomtassa ki a címét i. Úgy néz ki, hogy ez bffff124. Most nyomtassa ki a címét array [0]. 110. Mi a helyzet a [1]? 114. [2], 118. 11c, 120. array [5] bfff124. Szóval array [5] is ugyanazt a címet, mint én, ami azt jelenti, hogy az array [5] i. Ha ugyanaz a címe, ezek ugyanaz a dolog. Tehát, ha mi meg array [5], 0 állítunk i 0-ra. És ha úgy gondolja, erről szempontjából a verem, int i nyilvánították először, ami azt jelenti, hogy lesz egy kis hely a veremben. Aztán array [5] osztják, így aztán 20 byte osztják a verem. Tehát én lesz kiosztott első, majd a 20 byte kap különítettek el. Tehát én történik, mielőtt a tömb, és mert az út, mint mondtam a múlt héten, ahol ez technikailag a verem lefelé növekszik, amikor index egy tömb, mi garantálja, hogy a 0. pozícióját a tömbben mindig történik, mielőtt az első helyét a tömbben. Ez a fajta, hogyan húzta a múlt héten. Figyelje meg, hogy az alján van a 0 címet, és a tetején van címe max. A verem mindig növekszik meg. Mondjuk kiosztani i. Mi osztja integer i, ami azt jelenti, mondjuk, ide integer i gets különítettek el. Aztán osztja meg sor 5 egész számok, ami azt jelenti, hogy az alatta, mivel a verem növekszik meg, az 5 egészek kap különítettek el. De mivel, hogyan tömbök működik, mi garantálja, hogy az első helyen a tömbben mindig van egy címet kevesebb, mint a második dolog a tömbben. Szóval array 0 helyzetbe mindig történik először memóriában, mivel a tömb 1. pozícióban kell történnie azt követően, hogy a és a tömb 2. pozíció meg kell történnie azt követően, hogy a ami azt jelenti, hogy a tömb 0 helyzetbe fog történni, valahol itt lent, array pozíció 1 történne felett mert feljebb azt jelenti, magasabb cím, mivel a maximális cím itt. Szóval array [0] itt lent, array [1] itt, array [2] itt, array [3] itt. Figyeljük meg, hogy mielőtt kiosztott integer i egészen itt, ahogy haladunk tovább és tovább a tömb, mi egyre közelebb és közelebb a mi integer i. Ez csak azért történik, hogy a array [5], amely az egyik álláspont túl tömb, pontosan hol történt integer i kell felosztani. Szóval ez az a pont, ahol történetesen üti a hely a stack amit kiutalt integer i, és mi beállítás, hogy 0-ra. Ez az, hogy hogyan működik. Kérdései vannak? Igen. [Hallgató] Nem baj. Oké. [Hallgató] Hogyan kerüljük ilyen fajta hibákat? Ezek a fajta hibákat? Ne használja, mint a C programozási nyelv. Használjon olyan nyelv, amely tömb határain ellenőrzés. Amíg te vagy óvatos, akkor csak meg kell kerülni, hogy az elmúlt határait a tömb. [Hallgató] Szóval itt, amikor elmentünk az elmúlt határait a tömb - [Bowden] Ez az, ahol a dolgok kezdenek rosszra. >> [Hallgató] Ó, oké. Amíg marad a lefoglalt memória a tömb, akkor minden rendben. De a C nem tesz hibaellenőrzés. Ha megteszem array [1000], akkor szívesen, csak módosítani bármi történjék is - Ez megy az elején a tömb, akkor megy 1000 pozíciók után, és beállítja azt a 0-ra. Ez nem csinál semmi ellenőrzésére, hogy ó, ez nem ténylegesen 1000 dolgok benne. 1000-módon túl mit kell a változó, mivel a Java vagy valami kapsz array tilos index vagy indexet a határokat kivétel. Ezért nagyon sok magasabb szintű nyelvben ezek a dolgok ahol ha megy túl a tömb, akkor nem úgy, hogy nem lehet megváltoztatni a dolgokat alulról Ön majd a dolgok sokkal rosszabb, mint csak arra, hogy kivételt mondván, hogy túlment a végén a tömb. [Hallgató] És így kell már csak megváltozott a <=, hogy csak > [Bowden] Igen. Meg kell > [Hallgató] Rendben. További kérdések? Oké. [Hallgató] Van egy kérdésem. >> Igen. [Hallgató] Mi a tényleges tömb változó? [Bowden] Mint mi a tömb? Array maga is szimbólum. Ez csak a címe a kezdete a 20 byte, hogy mi hivatkozik. Azt hiszem, hogy ez egy mutató, de ez egy állandó mutató. Amint dolgok összeállított, a változó tömb nem létezik többé. [Hallgató] Szóval hogyan találja a mérete tömb? Méret tömb méretére utal az, hogy a mondat, hogy ez a jel utal. Amikor ilyet printf ("% p \ n", array); hadd futtatni. Amit csak én csináltam rosszul? Array "array" bejelentett itt. Oh, itt. Zengés okos, és ez történik észre, hogy én nyilvánította a tömb 5 elem de én indexelni helyére 1000. Meg lehet csinálni, mert ezek csak állandók. Ez csak megy eddig észre, hogy én megyek határain túl a tömb. Ám mielőtt észre, amikor már én hibásak, nem tudja esetleg hány értéket tudtam vállalni, így nem tudja megállapítani, hogy túlmutat a végén a tömb. Ez csak csenget, hogy okos. De most, hogy buggy4. Szóval, mit csinálok rosszul? Értelemszerűen nyilvánító könyvtári funkció "printf". Megyek szeretnénk # include . Oké. Most futó buggy4. Nyomtatása az érték a tömb, mint én itt, a nyomtatás, mint egy pointer Plakátok valami, ami úgy néz ki, mint ez - bfb8805c - ami némi címe ez a stack-ish régióban. Array maga olyan, mint egy mutató, de ez nem a tényleges mutató, mivel a rendszeres mutatót tudunk változtatni. Array mindössze néhány állandó. A 20 blokkok memória kezdődik címen 0xbfb8805c. Szóval bfb8805c át ezt a címet +20- vagy azt hiszem, -20 - minden a memória kiosztott ezt a tömböt. Array, a változó maga nem tárolja sehol. Amikor összeállítása, a fordító - kézzel hullám rajta - de a fordító csak használja, ha tudja, tömb legyen. Tudja, ha ez a tömb kezdődik, , és így mindig csak a dolgok tekintetében kompenzáció ebből elején. Nem kell egy változót magát képviselje tömb. De ha valami ilyesmit int * p = array, most p egy mutató, amely rámutat arra, hogy a tömb, és most p ténylegesen létezik a verem. Szabad vagyok változtatni p. Meg tudom csinálni p = malloc. Így az eredetileg mutatott tömb, most azt hangsúlyozza, hogy egy kis helyet a kupac. Nem tudom array = malloc. Ha csenget okos, akkor kiabálj velem rögtön a denevér. Igazából, biztos vagyok benne, gcc tenne ilyet is. Szóval array típusú "int [5]" nem átruházható. Nem lehet rendelni valamit egy tömb típusú mert a tömb csak egy konstans. Ez a szimbólum, amely találat a 20 bájt. Nem tudom megváltoztatni. [Hallgató] És hol van a méret a tömb tárolják? [Bowden] Ez nem tárolja sehol. Ez az, amikor ez összeállításánál. Szóval, hol van a méret tömb tárolják? Csak akkor használhatja a sizeof (array) belsejében a funkció, hogy a tömb nyilvánította magát. Szóval, ha nem néhány funkció, ize, és én (int array []) printf ("% d \ n", sizeof (array)); majd ide hívom ize (array); belül ez a funkció - mondjuk futtatni. Ez csenget, hogy okos újra. Ez azt mondja, hogy a tömb sizeof függvény paraméter visszatér mérete "int *". Ez lenne a hiba, ha ez nem az, amit akartam, hogy megtörténjen. Nézzük ténylegesen kikapcsol Werror. Figyelmeztetés. Figyelmeztetések rendben vannak. Ez továbbra is fordítani, amíg van egy figyelmeztetést. . / A.out fog nyomtatni 4. A figyelmeztetés, hogy a keletkezett egyértelműen jelzi, hogy mit rontottam el. Ez az int tömb éppen nyomdába sizeof (int *). Még ha tettem array [5] itt, ez még mindig csak a nyomdába sizeof (int *). Szóval, amint át be egy függvény közötti különbségtétel tömbök és mutatók nem létezik. Ez történik, hogy egy tömb, amely nyilvánította a stack, de amint átadjuk ezt az értéket, hogy 0xbf bla, bla, bla be ezt a funkciót, akkor ez a mutató, hogy a tömb a verem. Tehát ez azt jelenti, hogy sizeof kizárólag a funkció, hogy a tömb nyilvánították, ami azt jelenti, hogy amikor összeállításakor ezt a funkciót, amikor csenget megy keresztül ez a funkció, látja tömb int tömb méret 5. Akkor lát sizeof (array). Nos, ez 20. Ez tulajdonképpen hogyan sizeof alapvetően működik, szinte minden esetben. Sizeof nem egy függvény, ez az üzemben. Nem hívja a sizeof funkciót. Sizeof (int), a fordító csak lefordítani, hogy 4-re. Megvan? Oké. [Hallgató] Akkor mi a különbség a sizeof (array), a fő és az ize? Ez azért van, mert azt mondja sizeof (array), mely típusú int * mivel a tömb idelent nem típusú int *, ez egy int tömb. [Hallgató] Szóval ha már a paramétert array [] helyett int * array, lenne ez azt jelenti, hogy még mindig megváltoztathatja array, mert most ez a mutató? [Bowden] Tetszik ez? >> [Hallgató] Igen. Meg tudod változtatni tömb a funkciót most? [Bowden] Lehet változtatni tömb mindkét esetben. Mindkét esetben nyugodtan mondani array [4] = 0. [Hallgató] De lehet, hogy array pont valami mást? [Bowden] Oh. Igen. Mindkét esetben - >> [hallgató] Igen. [Bowden] közötti különbségtétel array [] és int * tömb, nincs. Ön is kap némi többdimenziós tömb itt néhány kényelmes szintaxist, de ez még mindig csak egy mutató. Ez azt jelenti, hogy szabad vagyok megtenni array = malloc (sizeof (int)), és most pont valahol máshol. De ugyanúgy, mint, hogy ez működik, örökké és mindig, megváltoztassák ezt a tömb azáltal, hogy mutasson valami másra nem változtatja meg ezt a tömböt ide, mert ez egy példányát az érv, ez nem egy mutatót ezt az érvet. És valóban, ahogy több jelzés, hogy ez pontosan ugyanaz - már látta, mi Nyomtatásra array nyomatok - mi lenne, ha kinyomtatja a címét a tömb vagy címe címét a tömb hogy akár e? Nézzük figyelmen kívül hagyják ezt. Oké. Ez rendben van. Ez már fut. / A.out. Nyomtatás tömb, majd a nyomtatás címét a tömb, az ugyanaz a dolog. Array egyszerűen nem létezik. Tudja, amikor nyomtat tömb, akkor kinyomtatja a szimbólum, amely utal a 20 bájt. Nyomtatása címét a tömb, nos, tömb nem létezik. Ez nincs címe, így csak kiírja a címét a 20 bájt. Amint összeállítására le, mint a lefordított buggy4. / A.out, tömb nem létezik. Mutatók létezik. Arrays nem. A blokkok memória képviselő a tömb továbbra is fennállnak, hanem a változó tömb és a változók az ilyen típusú nem léteznek. Ezek olyanok, mint a főbb különbségek a tömbök és mutatók kerülnek, amint csinál függvényhívásokat, nincs különbség. De belsejében a függvény a tömb maga kijelentette, sizeof másképp működik mert te nyomtat a méret a blokkok helyett a méret a típus, és nem lehet megváltoztatni, mert ez egy szimbólum. Nyomtatás a dolog és címét a dolog kinyomtatja ugyanaz a dolog. És ez nagyjából azt. [Hallgató] tudnád mondani, hogy még egyszer? Én lehet, hogy kimaradt valami. Nyomtatási sor és címe tömb kinyomtatja ugyanaz a dolog, mivel ha nyomtat egy mutatót versus címét a mutatót, az egyetlen dolog, kiírja a címét, amit mutat, A többi kiírja a címét a mutató a verem. Meg lehet változtatni a pointer, akkor nem lehet megváltoztatni egy tömb szimbólum. És sizeof mutató nyomdába méretét, hogy a mutató típus. Így int * p sizeof (p) fog nyomtatni 4, de int array [5] print sizeof (array) fog nyomtatni 20. [Hallgató] Szóval int array [5] kiírja 20? >> Igen. Ezért belsejében buggy4 mikor szokott lenni sizeof (array) ez csinál i <20, ami nem az, amit akartunk. Szeretnénk, i <5. >> [Hallgató] Oké. [Bowden], majd amint elkezd halad a funkciók, ha volt int * p = array; belül ezt a funkciót, akkor alapvetően a P és a tömb pontosan ugyanolyan módon, kivéve a sizeof problémát, és a változó probléma. De p [0] = 1, ugyanaz, mint mondás array [0] = 1; És amint mondjuk foo (array), vagy foo (p); belsejében a foo függvény, ez ugyanaz a hívás kétszer. Nincs különbség a két hívás között. Mindenki jó e? Oké. Van 10 perc. Megpróbáljuk átvészelni ezt a Hacker Typer program, ezt a weboldalt, amely kijött elmúlt évben, vagy ilyesmi. Ez csak kéne lenni, mint te írja véletlenszerűen és kiírja - Bármi fájlt, ez történik van-e töltve, amit úgy néz ki, mint te gépelés. Úgy néz ki, mint valami operációs rendszer kódját. Ez az, amit szeretnénk megvalósítani. Meg kell egy bináris futtatható nevű hacker_typer hogy vesz egy érv a fájlt "hacker típus." Futás a végrehajtható kell tisztítania a képernyőn majd nyomtassa ki az egyik karakter a recirkulált-fájlban minden alkalommal, amikor a felhasználó megnyomja a gombot. Tehát bármilyen gombot megnyomja, meg kell dobni, és helyette nyomtatni egy karaktert a fájlból ez az érv. Én elég sokat mondani, hogy mi a dolgokat fogunk tudni vannak. De mi szeretnénk, hogy nézd meg a termios könyvtár. Én még soha nem használta ezt a könyvtár egész életemben, ezért nagyon minimális célokra. De ez lesz a könyvtár tudjuk használni, hogy dobja el a karaktert eléred ha gépelés a szabványos be Szóval hacker_typer.c, és fogunk szeretnénk # include . Keresi a man oldal termios - Én találgatás, hogy a terminál operációs rendszer, vagy valami - Nem tudom, hogyan kell olvasni. Nézi most ezt, azt mondja, hogy ezeket 2 kép, úgyhogy csinálni. Az első dolog az első, azt akarom, hogy egyetlen érv, amely a fájl kellene nyitni. Szóval, mit szeretnél csinálni? Hogyan lehet ellenőrizni, hogy van egy érv? [Hallgató] Ha argc egyenlő azt. >> [Bowden] Igen. Tehát, ha (argc! = 2) printf ("Használat:% s [file megnyitása]"). Tehát most, ha futtatni ezt anélkül, hogy a második érv - ó, szükségem van az új vonal - látni fogod azt mondja használat:. / hacker_typer, majd a második érv kell a fájlt akarok megnyitni. Most mit tegyek? Azt akarom, hogy olvassa el ezt a fájlt. Hogyan kell olvasni egy fájlt? [Hallgató] You nyissa meg először. >> Igen. Szóval fopen. Mit jelent a fopen néz ki? [Hallgató] fájlnév. >> [Bowden] fájlnév lesz argv [1]. [Hallgató] És akkor mit akar kezdeni vele, így a - >> [Bowden] Igen. Szóval, ha nem emlékszik, akkor csak nem férfi fopen, ahol ez lesz a const char * path ahol a path fájlnév, const char * módban. Ha történetesen nem emlékszem, milyen állapotban van, akkor keresni módban. Belül man oldalak, a perjel karakter, amit segítségével keresni dolgokat. Szóval írja / mode keresni módba. n és N, amit segítségével körbe a keresési mérkőzések. Itt azt mondja az érvet módot mutat egy string kezdve az alábbi szekvenciák. Szóval r, Open szöveges fájlt olvasásra. Ez az, amit mi akarunk. Az olvasás, és azt akarom, hogy a tárolni. A dolog lesz a FILE *. Most mit akarok csinálni? Adj egy percet. Oké. Most mit akarok csinálni? [Hallgató] Ellenőrizze ha ez NULL. >> [Bowden] Igen. Minden alkalommal, amikor megnyit egy fájlt, győződjön meg arról, hogy te sikeresen tudja nyitni azt. Most azt akarom, hogy termios dolgokat, ahol szeretnék először olvastam a jelenlegi beállítások és mentse a valami, akkor én akarom megváltoztatni a beállításokat eldobni minden olyan képességgel, hogy én írja, majd szeretnék frissíteni ezeket a beállításokat. És akkor a végén a program, azt akarom, hogy állítsa vissza az eredeti beállításokat. Tehát a struct lesz típusú termios, és megyek, hogy szeretne két ilyen. Az első lesz a current_settings, , és akkor ők lesznek az én hacker_settings. Először fogok menteni szeretné a jelenlegi beállításokat, akkor megyek a frissíteni kívánt hacker_settings, majd így a végén az én program, szeretnék visszaállítani az aktuális beállításokat. Szóval aktuális beállítások mentése, az is, hogy működik, akkor ember termios. Látjuk, hogy itt van ez a tcsetattr int, int tcgetattr. Elmegyek egy termios struct annak mutató. Az, hogy ez fog kinézni jelentése - I've már elfelejtette, mi a függvény neve. Másolja és illessze be. Szóval tcgetattr, akkor én szeretnék átadni a struct, hogy én vagyok megtakarítás az információt, ami lesz current_settings, és az első argumentum a fájl leíró a dolog, szeretnék menteni a tulajdonságait. Mi a fájl leíró olyan, mint minden alkalommal, amikor megnyit egy fájlt, akkor kap egy fájl leíró. Amikor fopen argv [1], hogy kap egy fájl leíró, ahol Ön hivatkozó ha el szeretnénk olvasni, vagy írni. Ez nem az a fájl leíró szeretnék használni itt. Három fájlleíró van alapértelmezés szerint, amelyek a standard, standard ki, és a standard hiba. Alapértelmezés szerint, azt hiszem, standard értéke 0, standard out 1, és a standard hiba 2 lehet. Szóval mit akarok változtatni a beállításait? Szeretném megváltoztatni a beállításokat, amikor elütöttem egy karaktert, Azt akarom, hogy dobja el, hogy a karakter nyomtatás helyett a képernyőn. Mi stream - standard, standard ki, vagy standard hiba - reagál a dolgokat, amikor azt írja a billentyűzet? >> [Hallgató] Standard in >> Igen. Szóval lehet csinálni akár 0 vagy tehetek stdin. Kezdek a current_settings standard be Most azt akarom, hogy frissíteni ezeket a beállításokat, Tehát először fogok másolni hacker_settings mi a current_settings vannak. És milyen struktúrákat munka akkor csak másolja. Ez átmásolja az összes területen, ahogy az elvárható. Most azt akarom, hogy frissíteni néhány területen. Keresi termios, meg kellett volna, hogy olvassa el a sok e csak hogy lássa, mit szeretne keresni, de a zászlók fogsz szeretnénk keresni a visszhang, így ECHO Echo input karakter. Először is szeretnék beállítani - I've már elfelejtette, milyen területeken vannak. Ez az, amit a struct néz ki. Szóval bemeneti üzemmódok úgy gondolom, szeretnénk változtatni. Majd nézd meg a megoldást, hogy győződjön meg arról, hogy az, amit mi szeretnénk változtatni. Meg akarja változtatni lflag elkerülése érdekében szüksége, hogy nézze át ezeket. Meg akarja változtatni a helyi módok. Meg kellett volna, hogy olvassa el ezt az egész dolgot, hogy megértsük, ahol minden tartozik hogy meg akarjuk változtatni. De ez benne a helyi módok hová megyünk akar változtatni. Szóval hacker_settings.cc_lmode, amit a neve. c_lflag. Ez az, ahol bejutni bitenkénti operátorok. Mi vagyunk a fajta az, de megyünk át rajta gyorsan. Ez az, ahol bejutni bitenkénti operátorok, Azt hiszem, ha azt mondtam, egyszer régen, hogy amikor elkezd foglalkozó zászlókkal, fogsz használni bitenkénti operátor sokat. Minden bit a zászló megfelel valamilyen magatartás. Tehát itt, ez a zászló egy csomó különböző dolgot, ahol mindegyik jelent valami mást. De amit akarok éppen kikapcsolni a bit, amely megfelel az ECHO. Tehát kapcsold ki tudom & = ¬ ECHO. Igazából, azt hiszem, ez olyan, mint techo vagy ilyesmi. Én csak megy ellenőrizze újra. Én termios azt. Ez csak ECHO. ECHO lesz egy kicsit. ¬ ECHO fog minden olyan bit értéke 1, ami azt jelenti, az összes zászló van állítva true kivéve az ECHO kicsit. Ezzel véget a helyi zászlók ezzel, az azt jelenti, hogy valamennyi lobogó alatt hajózó jelenleg true továbbra is kell beállítani, hogy igaz. Ha az én ECHO flag értéke true, akkor ez szükségszerűen false az ECHO zászlót. Szóval ezt a kódsort, csak kikapcsolja a ECHO zászlót. A másik sornyi kódot, én csak másolja őket az érdeke az idő, majd magyarázni. A megoldás, mondta 0. Ez talán jobb, hogy kifejezetten mondani stdin. Figyeljük meg, hogy én is csinál ECHO | icanon itt. Icanon jelentése valamit külön, ami azt jelenti, kanonikus mód. Mi kanonikus mód azt jelenti, általában amikor gépelés ki a parancssorban, szabvány nem dolgozza fel semmit, amíg bejön újsor. Szóval, ha nem getString, beír egy csomó dolgot, akkor bejön újsor. Ez az, amikor ez küldött szabványos be Ez az alapértelmezett. Amikor kikapcsolja kanonikus mód, most már minden egyes karakter megnyomásakor az, amit kap feldolgozásra, mely általában olyan rossz, mert lassan feldolgozni ezeket a dolgokat, ezért is jó, hogy puffer be egész sorokat. De azt akarom, minden egyes karakter kell feldolgozni mert én nem akarom, hogy várjon rám a hit újsor előtt dolgozza fel az összes karakter voltam gépelni. Ez kikapcsolja egyházjogi módot. Ez a cucc csak azt jelenti, amikor valójában dolgozza karakter. Ez azt jelenti, feldolgozzák azokat, azonnal, amint én gépelési őket feldolgozni. És ez az a funkció, amely frissíti a beállításokat a szabvány, és TCSA eszközök csinálni most. A többi opció várjon, amíg minden, ami jelenleg a patak kerül feldolgozásra. Ez nem igazán számít. Csak most megváltoztatni a beállításokat, hogy bármi jelenleg hacker_typer_settings. Azt hiszem nevezte hacker_settings, úgyhogy változtatni. Változás mindent hacker_settings. Most, a végén a program megyünk vissza akar térni hogy milyen jelenleg belül normal_settings, ami megy, hogy csak kinézni & normal_settings. Megjegyzés Én nem változtak sem az én normal_settings mivel eredetileg szerzés ez. Aztán, hogy csak megváltoztatni őket vissza, én át őket a végén. Ez volt a frissítés. Oké. Most belseje itt én csak elmagyarázni a kód a kamat az idő. Ez nem olyan sok kódot. Látjuk azt olvassuk egy karaktert a fájlból. Úgy hívják, hogy f. Most már férfi fgetc, de hogyan fgetc fog dolgozni éppen ez megy vissza a karakter, hogy csak olvasni, vagy EOF, amely megfelel az a fájl végére, vagy valamilyen hiba történik. Mi hurok, továbbra is olvasni egy karaktert a fájl, amíg mi már elfogyott karakterek olvasni. És miközben csinálunk, hogy várunk egyetlen karaktert a standard be Minden egyes alkalommal, amikor írja be valamit a parancssorban, hogy olvas egy karaktert a standard be Aztán putchar éppen megy, hogy a char olvasunk fel ide a fájlt a szabványos ki. Tudod férfi putchar, de ez csak üzembe a standard ki, ez kinyomtatná a karaktert. Te is tedd printf ("% c", c); Same ötlet. Ez fog csinálni a nagy részét a munkánkat. Az utolsó dolog, fogunk akarok csak fclose a fájlt. Ha nem fclose, ez a memóriavesztés. Azt akarjuk, hogy a fájl fclose amit eredetileg nyitott, és úgy gondolom, hogy ez az. Ha ezt teszik, hogy már megvan a problémákat. Lássuk. Mit nem panaszkodnak? A várt "int", hanem az érvelés típusú "struct _IO_FILE * '. Majd meglátjuk, ha ez működik. Csak engedélyezett C99. Augh. Oké, hogy hacker_typer. Most még több hasznos leírásokat. Így használja a be nem jelentett azonosító "normal_settings". Én nem nevezném normal_settings. Hívtam current_settings. Szóval változtatni az egésznek. Most tompított érv. Én ezt 0 most. Oké. . / Hacker_typer cp.c. Én is nem törli a képernyőt az elején. De nézd vissza az utolsó probléma állítva látni, hogyan törölje a képernyőt. Ez csak néhány karaktert nyomtat míg ez csinál, amit akarok. Oké. És gondoltam, hogy ez miért szükséges, hogy 0 helyett stdin, amelyet be kell # define 0, ez panaszkodik, hogy - Előtt, amikor azt mondtam, hogy van fájlleíró, de akkor is a FILE * Egy fájl-leíró csak egy egész szám, mivel a FILE * van egy csomó cucc társul hozzá. Az ok, azt kell mondani, 0 helyett stdin az, hogy stdin egy FILE *, amely rámutat a dolog, hogy a hivatkozó fájl leíró 0. Tehát akár itt, amikor én fopen (argv [1], kapok egy FILE * vissza. De valahol, hogy a FILE * a dolog megfelelő fájl leíró adott fájlt. Ha megnézzük a man oldalt nyitott, így azt hiszem, neked kell csinálni man 3 nyitott - nope - man 2 nyitott - igen. Ha megnézzük az oldal nyitott, nyílt, mint egy alacsonyabb szintű fopen, és ez visszatérés az aktuális fájl leíró. fopen csinál egy csomó dolgot a tetején nyitott, amely visszatérés helyett csak azt a fájlt leíró vissza egész FILE * pointer belül, ami a mi kis fájl leíró. Tehát szabvány hivatkozik a FILE * dolog, mivel a 0 jelenti, hogy csak a fájl leíró szabvány is. Kérdései vannak? [Nevet] Blew ezen keresztül. Rendben van. Végeztünk. [Nevet] [CS50.TV]