[Powered by Google Translate] [5 skirsnis - patogiau] [Rob Bowden - Harvardo universiteto] [Tai CS50. - CS50.TV] Kaip ir sakiau mano elektroninio pašto adresą, yra daug dalykų, kuriuos galite naudoti, išskyrus prietaisą, iš tikrųjų problemines rinkinius. Mes rekomenduojame jums padaryti tik todėl, kad jį į prietaisą, tada mes galime daugiau lengvai padėti jums ir mes žinome, kaip viskas vyksta į darbą. Bet kaip vienas iš pavyzdžių, kur jūs galite padaryti dalykų, jei, tarkim, jums nereikia turėti prieigą prietaisą arba norite dirbti mokslo centro rūsyje - kurios iš tikrųjų jie turi prietaisą taip pat - jei norite dirbti bet kur. Vienas pavyzdys yra matėte / girdėjote apie SSH? SSH yra iš esmės tik kaip prisijungti prie ko nors. Tiesą sakant, dabar aš SSHed į aparatą. Aš niekada tiesiai į prietaisą. Čia yra prietaisas, ir jei jums atrodo čia matote šį IP adresą. Aš niekada dirbti paties prietaiso; Aš visada ateis į iTerm2 lango / terminalo lange. Galite SSH šį IP adresą, ssh jharvard@192.168.129.128. Aš atsimenu, kad skaičius labai lengvai, nes jis toks gražus modelis. Bet tai bus paklausti manęs už savo slaptažodį, ir dabar aš į prietaisą. Iš esmės, šiuo metu, jei jūs atidarėte terminalo viduje paties prietaiso, šią sąsają, tačiau jūs ją naudoti, yra lygiai tokia pati kaip sąsaja aš čia, bet dabar jūs SSHed. Jūs neturite SSH prietaiso. Vienas iš pavyzdžių kitoje vietoje galėtum SSH, aš esu gana įsitikinęs, turite pagal nutylėjimą - Oh. Didesnis. Jums visiems turėtų būti pagal nutylėjimą FAS sąskaitų fas serverių. Už mane, aš norėčiau SSH į rbowden@nice.fas.harvard.edu. Ji ketina paprašyti, kad pirmą kartą, ir pasakyti "taip". Mano slaptažodis yra tiesiog bus mano FAS slaptažodį. Ir todėl dabar, aš SSHed gražūs serverių ir galiu daryti, ką noriu čia. Daug klasių, jums gali imtis, kaip 124, ketinate norite įkelti stuff čia faktiškai pateikti jūsų problema rinkinius. Bet pasakyti, kad jūs neturite prieigos prie įrenginio. Tada jūs galite padaryti dalykus, kaip čia jis pasakys - Tai tik mūsų skyriuje klausimų. Jis paklaus jūsų, tai padaryti prietaisą. Vietoj to, aš tiesiog padaryti jį serveryje. Aš einu, išpakuokite, kad. Problema bus, kad esate pripratę naudojant kažką panašaus į gedit ar kokia prietaiso viduje. Jūs esate nesiruošia turėti, kad kad ŪKS serveryje. Visa tai tiesiog bus tai tekstinė sąsaja. Taigi jums gali arba viena, pasistenkite išmokti teksto redaktoriumi, kad jie turi. Jie turi Nano. Nano yra paprastai gana paprasta naudotis. Galite naudoti savo strėles ir įveskite paprastai. Taigi, tai nėra sunku. Jei norite gauti tikrai išgalvotas galite naudoti emacs, aš tikriausiai neturėtų atvėrė, nes aš net nežinau kaip uždaryti Emacs. Kontrolė X valdymo C? Taip. Arba galite naudoti VIM, o tai, ką aš naudoju. Ir taip yra jūsų pasirinkimai. Jei nenorite to daryti, taip pat galite, jei peržvelgsite manual.cs50.net - Oh. Kompiuteriu, galite SSH naudojant glaistai, , kuriame jūs turite atsisiųsti atskirai. Apie Mac, galite tiesiog pagal nutylėjimą naudoti terminalo arba galite atsisiųsti iTerm2 kuris yra tarsi gražus, išgalvotas terminalo. Jeigu jūs einate į manual.cs50.net pamatysite nuorodą į užrašų knygelę + +, o tai, ką galite naudoti kompiuterio. Jis leidžia jums SFTP su Notepad + +, kuris yra iš esmės SSH. Ką tai leis jums padaryti redaguoti savo failus vietoje, ir tada, kai norite juos išsaugoti, tai padės sutaupyti nice.fas kur tada galite paleisti juos. Ir ant Mac ekvivalentas būti TextWrangler. Taigi ji leidžia jums padaryti tą patį. Jis leidžia jums redaguoti failus vietiniame ir įrašyti juos į nice.fas kur tada galite paleisti juos. Taigi, jei jūs kada nors pakimba be prietaiso, turite šias galimybes vis dar padaryti jūsų problema rinkinius. Viena problema bus, kad jūs nesiruošia turėti CS50 biblioteką nes nice.fas nėra pagal nutylėjimą, kad. Jūs galite atsisiųsti CS50 biblioteka - Nemanau, kad man reikia, kad šiuo metu. Jūs galite atsisiųsti CS50 biblioteką ir nukopijuokite jį į nice.fas ar aš manau, kad šiuo metu mes ne naudoti it anymore vistiek. Arba, jei mes darome, galite šiuo metu yra pakeisti jį su CS50 bibliotekos funkcijų diegimas vistiek. Kad neturėtų būti kad daug apribojimo. Ir tai, kad. Grįšiu prie prietaiso, mes padarysime viską, kad prietaiso. Žiūri mūsų skyriuje klausimų, pradžioje, kaip sakiau mano elektroninio pašto adresą, mes turime kalbėti apie vieną trumpą jums turėjo žiūrėti. Mes turime Skamb ir vamzdžiai, ir į šiuos tris klausimus. , Kuri srautas printf rašyti funkcijas, pavyzdžiui, pagal nutylėjimą? Taigi, srautas. Kas yra upelis? Srautas iš esmės, kaip tai tik keletas Tai net ne 1s ir 0s šaltinis. Srautas, jis klausia čia yra standartinis. Ir taigi standartinio iš srautas, kai jūs į jį rašyti, jis pasirodo ekrane. Standartinis išvada, srautą, tai reiškia, kad jūs tiesiog parašyti 1s ir 0s jai, Standartinis išvada kitas galas tiesiog skamba nuo to upelio. Tai tiesiog 1s ir 0s eilutę. Jūs galite rašyti srautų arba galite perskaityti iš srautų priklausomai nuo to, srautas iš tikrųjų yra. Kiti du numatytieji srautai yra standartinis ir standartinė paklaida. Standartas yra kai jūs GetString, laukia tavęs įvesti stuff. Taigi ji laukia jūsų, tai iš tikrųjų laukia standarto, yra tai, ką jūs gaunate, kai jūs įvedate į klaviatūrą. Įvedate į standartą in Standartinė paklaida yra iš esmės atitinka standartinio out, bet tai specializuojasi, kad kai spausdinate standartinė paklaida, jums turėjo tik spausdinimo klaida pranešimus , kad būtų galima atskirti reguliariai pranešimus, atspausdintus į ekraną palyginti su klaidų pranešimų, priklausomai nuo to, ar jie nuvyko į standartinį atsisakymą arba standartinė paklaida. Failus per. Standartinis out, standartinis, ir standartinė paklaida yra tik specialios srautai, bet tikrai bet kokį failą, kai atidarote failą, jis tampa baitų srautas kur Jūs galite tiesiog skaityti nuo to srauto. Jūs, didžiąja dalimi, gali tiesiog manau, kaip baitų srautą faile. Taigi, kas srautus jie parašyti pagal nutylėjimą? Standartinis išvada. Koks yra skirtumas tarp> ir >>? Ar kas nors peržiūrėti šį video įrašą iš anksto? Gerai. > Bus kaip jūs nukreipti į failus, ir >> taip pat ketina išvedimo į failus, bet tai, o ne pridėti prie bylos. Pavyzdžiui, tarkime, kad Aš atsitikti, kad dict čia, ir tik stuff viduje dict katės, katė, šuo, žuvis, šuo. Viena komanda, kad jūs turite į komandų eilutę yra katė, kuris yra tik ketinate spausdinti faile. Taigi, kai aš sakau, kačių dict, jis ketina spausdinti kačių, kačių, šunų, žuvis, šunį. Kad viskas katė daro. Tai reiškia, kad spausdinami standarto iš katė, katė, šuo, žuvis, šuo. Jei aš vietoj norite peradresuoti, kad į failą, aš galiu naudoti> ir nukreipti jį į ką failas yra. Aš kviesiu rinkmenoje. Taigi dabar, jei I ls, aš turiu naują failą pavadinimu failas. Ir jei aš jį atidaryti, ji ketina turėti, ką katė įdėti į komandų eilutę. Taigi dabar, jei aš tai padaryti dar kartą, tada jis vyksta nukreipti išvestį į failą, ir aš norėčiau turėti tą patį tiksliai dalykas. Taigi techniškai, ji visiškai svarbesnis, ką mes turėjome. Ir mes pamatyti, jei aš pakeisiu dict, aš paėmė šunį. Dabar, jei mes katė dict į failą dar kartą, mes ketiname turėti naują versiją su šuo ištrintas. Taigi tai paneigia. Vietoj to, jei mes naudojame >> ketinate pridėti failą. Dabar atidaryti failo, mes matome, mes turime tik du kartus tą patį spausdintą nes ten vieną kartą, tada mes pridėtas į originalą. Tam, kad tai, ką> ir >> padaryti. Ar kitą paklausti - Tai nereiškia, paklausti apie tai. Kita, kad mes turime yra <, kuri, jei> nukreipimus standartinį, jūs darote 2> kad nukreipti standartinė paklaida. Taigi, jei kažkas standartinė paklaida, tai nebūtų gauti įdėti į txt2. , Bet pastebėsite, jei aš 2>, tada jis vis dar spausdinti Sveiki, Rob! į komandų eilutę nes aš tik nukreipti standartinė paklaida, aš nenukreipiama standartą. Standartinė paklaida ir standartas iš yra skirtingi. Jeigu jūs norėjote, kad iš tikrųjų rašyti standartinė paklaida, tada galėčiau pakeisti, kad tai bus fprintf į išvestį. Iki printf, pagal nutylėjimą spausdina su standartine out. Jei aš noriu spausdinti standartinė paklaida rankiniu būdu, tada aš turiu naudoti fprintf ir nurodyti, ką norite spausdinti. Jei vietoj to aš fprintf STDOUT, tada, kad iš esmės atitinka printf. Bet fprintf standartinė paklaida. Taigi dabar, jei aš nukreipti į tai txt2, Sveiki, rob! vis dar gauti atspausdintas į komandų eilutę nes jis vis spausdinami standartinė paklaida ir aš tik nukreipti standartą. Jei aš dabar nukreipti standartinė paklaida, dabar ji negali gauti spausdinti, ir txt2 bus Sveiki, Rob! Taigi, dabar, jūs galite spausdinti savo faktines klaidas standartinė paklaida ir spausdinti savo nuolatinius pranešimus į standartinę out. Ir todėl, kai jūs paleisti savo programą, galite paleisti jį. / Apie šio tipo su 2> taip, kad jūsų programa vyksta normaliai važinėti, bet bet koks klaidos pranešimas, kad jūs gaunate jums gali patikrinti vėliau savo klaidų žurnalą, todėl klaidų, ir tada ieškoti vėliau ir savo klaidų byla turės kokių nors klaidų, kas nutiko. Turite klausimų? Naujausia yra vamzdis, kurį jūs galite galvoti, kaip standartą iš vienos komandos ir todėl standartas taikomas kitą komandą. Pavyzdys čia echo yra komandų eilutės dalykas kad yra tik ketina pakartoti, ką aš įdėti kaip savo argumentą. Aš ne įdėti kabučių. Echo, blah, blah, blah yra tik ketina spausdinti blah, blah, blah. Anksčiau, kai aš sakiau, aš turėjo įdėti Rob į txt failą , nes aš galiu tik nukreipti TXT failus, o ne / jei aš echo Rob ir tada vamzdis jį į / hello, kad bus taip pat padaryti tos pačios rūšies dalykas. Tai užtruko šią komandą galia, aidas Rob, ir naudoti jį kaip įvesties / hello. Jūs galite galvoti apie tai, kaip pirmasis peradresavimas ir echo Rob į failą ir tada įvesti į / Apie šio failo, kuris buvo tik išvedamas. Bet tai trunka laikiną bylą iš paveikslėlio. Turite klausimų apie tai? Kitas klausimas ketina įtraukti. Kas dujotiekis gali naudoti norėdami rasti unikalių pavadinimų failą pavadinimu names.txt? Komandos, mes ketiname norite naudoti, yra unikalus, todėl Uniq ir tada wc. Tai galite padaryti vyro Uniq kas, kad tai iš tikrųjų atrodo, ir tai tik ketina filtruoti gretimų atitikimo linijas įėjimo. Vyras wc ketina spausdinti naujos eilutės simbolį, žodį, ir kiekvieno failo baitų skaičius. Ir naujausia mes ketiname norite naudoti, yra tarsi kuris vyksta tiesiog rūšiuoti eilutes txt failą. , Jei aš padaryti šiek tiek txt failas, names.txt, ir tai Rob, Tommy, Juozapas, Tommy, Juozapas, RJ, Rob, ką aš noriu padaryti, čia yra rasti unikalių pavadinimai šiame faile. Taigi, kas jei atsakymas būtų? >> [Studentas] 4. >> Taip. Jis turi būti 4 nuo Rob, Tommy, Juozapo, RJ yra tik unikalūs pavadinimai šiame faile. Pirmas žingsnis, jei aš tiesiog padaryti Word count names.txt tai tikrai sakau man viską. Iš tikrųjų tai yra spausdinimas - pažiūrėkime, vyras wc - naujų eilučių, žodžių, ir baitų skaičius. Jeigu aš tik rūpi linijų, tada aš galiu tiesiog padaryti wc-l names.txt. Taip, kad 1 žingsnis. Bet aš nenoriu wc-l names.txt, nes names.txt tiesiog yra visi vardai, ir aš noriu filtruoti jokių Neunikalus. Taigi, jei aš UNIQ names.txt, kuris ne visai duoti man, ką aš noriu nes dubliuoti pavadinimai vis dar ten. Kodėl taip yra? Kodėl Uniq ne daryti ką noriu? [Studentas] dublikatai nėra [nesigirdi] >> Taip. Prisiminti man puslapius, UNIQ sako filtro gretimų atitinkančių eilučių. Jie nėra šalia, kad ji bus ne filtruoti juos. Jei aš rūšiuoti juos pirma, rūšiuoti names.txt ketina pateikti visus pasikartojančius eilutes kartu. Taigi dabar rūšiuoti names.txt kad. Aš ruošiuosi norite naudoti, kad įėjime Uniq, kuris yra | Uniq. , Kuri suteikia man Juozapą, RJ, Rob, Tommy, ir aš noriu naudoti, kad kaip indėlį į wc-l, ketina duoti man 4. , Kaip ji sako, čia, vamzdynas gali naudoti? Daug dalykų jūs galite padaryti, komandų serija, pavyzdžiui, naudojant kur jūs naudojate produkciją iš vienos komandos kaip įėjimo į kitą komandą. Jūs galite padaryti daug dalykų, daug protingų dalykų. Turite klausimų? Gerai. Štai ir viskas vamzdžių ir perorientavimas. Dabar mes pereiti prie faktinio dalykų, kodavimo stuff. Viduje šis PDF, pamatysite šią komandą, , ir jūs norite paleisti šią komandą savo prietaiso. wget komanda tiesiog gauti ką nors iš interneto, iš esmės, taip wget ir šį URL. Jei Jūs patekote į šį URL savo naršyklėje, ji būtų atsisiųsti šį failą. Aš tiesiog paspaudžia ant jo, todėl man atsisiųsti failą. Bet raštu wget šito daikto viduje terminalo yra tik ketina jį atsisiųsti į savo terminalą. Turiu section5.zip, ir jūs norite išpakuokite section5.zip kuris ketina suteikti jums aplanką, pavadintą section5 kuris vyksta, kad visi failai, mes ketiname naudoti šiandien viduje ji. Kaip šių programų failų pavadinimai rodo, kad jie šiek tiek Buggy, todėl jūsų tikslas yra išsiaiškinti, kodėl naudojant gdb. Ar visus juos parsisiųsti / žinoti, kaip juos gauti atsisiųsti į savo prietaiso? Gerai. Veikia ./buggy1, jis pasakys SEGMENTAVIMAS gedimą (Core dempingo kaina), bet kuriuo metu gausite segfault, tai yra blogas dalykas. Kokiomis aplinkybėmis jūs gaunate segfault? [Studentas] Dereferencing NULL pointeris. >> Taip. Taigi, kad yra vienas iš pavyzdžių. NULL pointeris Dereferencing jūs ketinate gauti segfault. Kas segfault priemones jūs liesdami atmintį, jums neturėtų būti neliesti. Taigi dereferencing NULL pointeris yra neliesti Adresas 0 ir iš esmės, šiandien pasakyti, kad visi kompiuteriai adresas 0 yra atminties, jums neturėtų būti neliesti. Štai kodėl dereferencing NULL pointeris rezultatų segfault. Kai jums atsitikti, kad negali inicijuoti rodyklę, tada ji turi šiukšlių vertę, ir taip, kai bandote dereference, greičiausiai jūs liesdami atmintį tai į niekur viduryje. Jei atsitiktų gauti pasisekė ir šiukšlių vertė atsitiko, kad rodytų į kažkur ant kamino ar kažką, tada, kai jums dereference kad žymeklį, kuriuos dar inicializuoti, nieko bus negerai. Bet jei ji nukreipta į, tarkim, kažkur tarp kamino ir krūvos, ar ji nukreipta tik kažkur, kad nebuvo buvo naudojami pagal savo programą dar, tada jūs liesdami atminties jums neturėtų būti neliesti ir jums segfault. Rašydami rekursinis funkciją ir ji recurses per daug kartų ir jūsų kamino auga per didelis ir kamino pataiko į dalykus kad ji neturėtų susidurti su, jūs liesdami atmintį, jums neturėtų būti neliesti, todėl jūs segfault. Kad yra ką segfault. Tai taip pat dėl ​​tos pačios priežasties, kad jei turite eilutę, pavyzdžiui, grįžkime su ankstesne programa. Hello.c-Aš tik ketina padaryti ką nors kita. char * s = "hello world!"; Jei aš naudoju * = kažkas ar s [0] = "X"; todėl įsitikinkite, labas,. / hello, kodėl, kad segfault? Kodėl taip segfault? Ką būtų galima tikėtis, kad taip atsitiktų? Jeigu aš printf ("% s \ n",-os), ką jūs tikėtis, kad bus spausdinami? [Studentas] X hello. >> Taip. Problema yra ta, kad, kai jūs deklaruoja panašaus į tai eilutę, s yra žymeklis, kad ketina eiti kamino, ir kas s nukreipta į ši eilutė, kuri yra tik skaitomos atminties. Taigi tik vardą, pavardę, tik skaitomos atminties, turėtumėte gauti idėja kad jei bandysite pakeisti tai, kas yra tik skaitomos atminties, jūs darote kažką, kad jums nereikėtų daryti su atmintim ir jums segfault. Iš tikrųjų tai yra didelis skirtumas tarp char * s ir char s []. Taigi char [], dabar ši eilutė bus įdėti į steką, kamino yra ne tik skaityti, o tai reiškia, kad tai turėtų veikti puikiai baudą. Ir ji tai daro. Atminkite, kad kai aš char * s = "hello world!", Pati yra kamino bet kažkur kitur, ir kad kažkur kitur būna, kad tik skaityti. Bet char [] yra tik kažkas kamino. Taigi, tai dar vienas pavyzdys, segfault vyksta. Mes matėme kad ./buggy1 lėmė segfault. Teoriškai neturėtų pažvelgti buggy1.c nedelsiant. Vietoj to, mes pažvelgti į jį per gdb. Atkreipkite dėmesį, kad, kai jūs gaunate SEGMENTAVIMAS kaltės (Core dempingo kaina), gausite šį failą per čia vadinama šerdies. Jei mes ls-l, mes pamatysime, kad esmė yra paprastai gana didelis failas. Tai bylos baitų skaičius, todėl atrodo, kad jis 250-kažkas kilobaitai. Taip yra todėl, kad tai, ką core dump iš tikrųjų yra yra tada, kai jūsų programos avarijos, atminties savo programą valstybės tiesiog gauna nukopijuoti ir įklijuoti į šį failą. Ji gauna dempingo kaina į šio failo. Ši programa, o ji buvo paleista, įvyko apie 250 kilobaitų atminties naudojimą, ir kad tai, ką gavo dempingo kaina į šį failą. Dabar jūs galite peržvelgti šio failo, jei mes gdb buggy1 branduolį. Mes galime tik daryti gdb buggy1, ir kad bus tiesiog paleidžiant gdb reguliariai, naudojant kaip savo įvesties failo buggy1. Bet jei jūs gdb buggy1 branduolį, tada jis konkrečiai ketina pradėti gdb žiūri šią pagrindinę bylą. Ir tu sakai, buggy1 reiškia gdb žino, kad pagrindinė byla ateina iš buggy1 programą. Taigi gdb buggy1 esmė yra nedelsiant atnešti mums kur programa atsitiko nutraukti. Čia mes matome, programa nutrauktas signalo 11, segmentavimo kaltės. Atsitiks pamatyti liniją susirinkimų, kurį tikriausiai nėra labai naudinga. Bet jei įvesite BT arba pėdsako, kad bus funkcija , kuri suteikia mums mūsų dabartinių kamino kadrų sąrašą. Taigi Backtrace. Atrodo, kad mes tik du kamino rėmus. Pirmasis mūsų pagrindinis kamino rėmas, , o antrasis yra kamino rėmas šią funkciją, kad mes atsitiktų būti, atrodo, kad mes tik surinkimo kodą. Taigi, grįžkime į mūsų pagrindinę funkciją, ir padaryti, kad mes galime padaryti 1 kadrą, ir manau, kad mes taip pat galime tai padaryti žemyn, bet aš beveik niekada daryti žemyn - arba iki. Taip. Aukštyn ir žemyn. Iki atneša jums vieną kamino rėmo, žemyn atneša jums žemyn kamino rėmo. Aš paprastai niekada naudoti, kad. Aš tiesiog konkrečiai pasakyti 1 kadrą, kuris yra eiti į rėmo, pažymėtą 1. Rėmelis 1 ketina atnešti mums į pagrindinį kamino rėmo, ir ji sako, čia kodo eilutę atsitiktų būti. Jei mes norėjome dar keletą eilučių kodo, mes galime pasakyti, sąrašą, ir kad ketina duoti mums visus kodo linijomis aplink jį. Linija segfaulted buvo 6: if (strcmp ("CS50 uolienos", argv [1]) == 0). Jei tai nėra akivaizdu dar galite gauti jį tiesiai iš čia, tiesiog galvoju, kodėl ji segfaulted. Tačiau mes galime imtis dar vieną žingsnį ir pasakyti: "Kodėl argv [1] segfault?" Leiskite spausdinimo argv [1], ir atrodo, tai 0x0, kuris yra niekinis rodyklė. Mes strcmping CS50 uolų ir NULL, ir todėl, kad vyksta segfault. Ir kodėl tai argv [1] null? [Studentas] Kadangi mes nesuteikė jai jokių komandų eilutės argumentus. Taip. Mes nesuteikė jai jokių komandų eilutės argumentus. Taigi ./buggy1 yra tik ketina argv [0] būti ./buggy1. Ji nesiruošia turėti argv [1], kad ketina segfault. Bet jei, vietoj to, aš tai tiesiog CS50, jis ketina pasakyti Jūs gaunate D nes tai, ką ji turėtų daryti. Žiūri buggy1.c, tai turėtų spausdinti "Jūs gaunate D" - Jei argv [1] nėra "CS50 uolienos", "Jūs gaunate D", kitaip "Jūs gaunate tai!" Taigi, jei norime, turime tai palyginti kaip tiesa, tai reiškia, kad ji lygina su 0. Taigi argv [1] turi būti "CS50 uolų". Jei norite padaryti, kad į komandų eilutę, jūs turite naudoti \ pabėgti erdvę. Taigi CS50 \ uolienos ir gausite A! Jei jums nereikia daryti "Backslash, kodėl tai neveikia? [Studentas] Tai du skirtingi argumentai. >> Taip. Argv [1] bus CS50, ir argv [2] bus uolienos. Gerai. Dabar ./buggy2 vėl ketina segfault. Vietoj atidaryti jį su savo pagrindine byla, mes tiesiog atverti buggy2 tiesiogiai taip gdb buggy2. Dabar, jei mes tiesiog paleisti programą, tada jis ketina pasakyti, kad programa gavo signalo SIGSEGV kuris yra segfault signalą, kur tai įvyko, kad taip atsitiktų. Žiūri mūsų pėdsako, mes matome, kad mes buvome funkciniam oh_no , kuris buvo vadinamas funkcijos Dinky, kuris buvo vadinamas funkcijos Binky, , kuris buvo vadinamas pagrindinis. Mes taip pat galime pamatyti argumentus šių funkcijų. Buvo argumentas Dinky ir Binky 1. Jei mes sąrašą funkcija oh_no, matome, kad oh_no tiesiog daro char ** S = NULL; * = "STRĖLĖ"; Kodėl tai nepavyksta? [Studentas] Jūs negalite dereference null žymeklį? >> Taip. Tai tiesiog pasakyti ai yra NULL, nepriklausomai nuo to, ar būna, kad char ** , kuri, priklausomai nuo to, kaip jūs jį interpretuoti, tai gali būti žymiklį į rodyklę į eilutę arba eilučių masyvas. Tai ai yra NULL, todėl * s dereferencing NULL pointeris, ir taip tai vyksta į avariją. Tai yra vienas iš greičiausių būdų, galite galbūt segfault. Tai tiesiog skelbiantis null žymiklį ir iš karto segfaulting. Štai ką oh_no daro. Jei mes einame po vieną kadrą, tada mes ketiname gauti į funkcija, kuri vadinama oh_no. Man reikia daryti, kad žemyn. Jei jūs neturite įvesti komandą, ir jūs tiesiog paspauskite "Enter" dar kartą, tai bus tik pakartoti ankstesnę komandą, kad jūs anksčiau. Mes esame Rėmelis 1. Listingavimas Ši rėmo, matome, čia yra mūsų funkcija. Jūs galite paspausti dar kartą, ar jūs galite padaryti sąrašą 20 ir ji bus sąraše daugiau. Ši funkcija Subtili sako, jei i 1, tai eikite į oh_no funkcija, kitur eiti lieso funkciją. Ir mes žinome, i 1, nes mes atsitiktų pamatyti čia kad Subtili buvo iškviestas argumentu, 1. Arba galite tiesiog spausdinti i ir jis pasakys, i 1. Mes šiuo metu Dinky, ir jei mes einame kito kadro, mes žinome, kad galų gale į Binky. Aukštyn. Dabar mes Binky. Listingavimas Ši funkciją - iš prieš pusę tuoj mane sąrašą prasidėjo taip, lyg i 0, tada mes ketiname jį vadiname oh_no, dar Subtili. Mes žinome, man buvo 1, todėl jis vadinamas Subtili. Ir dabar mes grįžome pagrindinis ir pagrindinis tiesiog bus int i = rand ()% 3; Kad yra tik ketina suteikti jums atsitiktinį skaičių, kuris yra arba 0, 1 arba 2. Ji ketina skambinti Binky su tuo numeriu, ir jis grįš 0. Žvelgiant į šią tiesiog vaikščioti per programą rankiniu būdu be paleisti jį iš karto, galėtumėte nustatyti pertraukos tašką Main, o tai reiškia, kad, kai mes paleisti programą jūsų programa veikia iki tol, kol ji hitai pertraukos tašką. Taigi, paleisti programą, ji veiks ir tada ji nukentėjo pagrindinė funkcija ir nustoti veikti. Dabar mes viduje pagrindinis, ir žingsnis ar kiti ketina vesti mus į kitą eilutę kodo. Jūs galite padaryti, žingsnis arba kitą. Pereis į kitą, dabar aš buvo rand ()% 3, taigi mes galime atspausdinti aš vertė, ir jis pasakys, i 1. Dabar ji, nepriklausomai nuo to, ar mes naudojame kitą arba ankstesnį žingsnį. Manau, kad svarbiau ankstesniojo, bet mes norime naudoti kitą. Jei mes naudojame žingsnį, mes žingsnis į funkciją, o tai reiškia pažvelgti į faktinį dalykas kad vyksta viduje Binky. Jei mes naudojame kitą, tai reiškia eiti per funkciją ir tiesiog eiti į kitą eilutę kodo Mūsų pagrindinė funkcija. Štai čia, šioje linijoje, man buvo, kur jis sakė, rand ()% 3; jei aš žingsnį, tai būtų eiti į rand įgyvendinimo ir pažvelgti į tai, kas vyksta ten, ir aš galėjau žingsnis per randas funkcija. Bet man nerūpi apie randas funkcija. Aš tik noriu eiti į kitą eilutę kodo pagrindinis, tad aš naudoju kitą. Bet dabar aš rūpintis apie Binky funkcija, todėl aš noriu dėti į. Dabar aš Binky. Pirmoje eilutėje kodas going to say if (i == 0), aš žengti žingsnį, matome mes galų gale dinky. Jei mes sąrašas dalykų, matome, kad jį patikrinti yra i = 0. i nėra lygus 0, todėl jis išvyko į kitas sąlyga, kuris ketina skambinti Dinky (i). Jums gali susipainioti. Jei jūs tiesiog pažvelgti į šias eilutes, jūs manote, if (i == 0) gerai, tada aš paėmė dar vieną žingsnį ir dabar aš Dinky (i), jūs manote, kad turėtų reikšti, i = 0 ar kažkas. Ne, tai tiesiog reiškia, kad jis žino, kad tai galima klijuoti tiesiai į linijos Dinky (i). Nes aš ne 0, kitas žingsnis yra nesiruošia baigti else. Dar yra ne linija, ji ketina sustoti. Tai dabar einu į kitą eilutę, ji iš tikrųjų gali vykdyti, kuri yra Subtili (i). Kovos į dinky (i), matome, if (i == 1). Mes žinome, i = 1, todėl, kai mes žingsnį, mes žinome, kad jūs ketinate baigti oh_no nes i = 1 iškviečia funkciją oh_no, kurį galite žengti į, kuris ketina nustatyti char ** s = NULL ir nedelsiant "STRĖLĖ". Ir tada iš tikrųjų žiūri į buggy2 įgyvendinimo, tai, aš tiesiog gauti atsitiktinių skaičių - 0, 1 arba 2 - Calling Binky jei i 0 ragina oh_no, dar ji vadina Subtili, kuris ateina čia. Jei i 1, skambinkite oh_no, dar lieso, kuris ateina čia, jei i 2, skambinkite oh_no. Aš net manau, kad yra būdas, Ar kas nors būdas padaryti programa, kad nebus segfault? Nes jei aš kažko trūksta, jei i 0, jūs iš karto segfault nors jums eiti į funkciją, kuri, jei i yra 1 Jūs segfault nors jums eiti prie funkcijos, kur, jei aš yra 2 segfault. Todėl nesvarbu, ką jūs darote, jūs segfault. Manau, vienas iš būdų nustatyti, kad būtų, o ne daryti char ** S = NULL, jums gali malloc vietos už tą eilutę. Mes galime padaryti malloc (sizeof) - sizeof ką? [Studentas] (char) * 5? >> Ar tai atrodo tiesa? Aš darant prielaidą, kad tai veiks, jei aš iš tikrųjų vyko, bet tai ne tai, ko aš ieškau. Pažvelgti s tipo. Pridėkime int *, todėl int * x. Noriu daryti malloc (sizeof (int)). Arba, jei aš norėjau iš 5 masyvo, aš norėčiau tai padaryti (sizeof (int) * 5); Ką daryti, jei int **? Ką aš malloc? [Studentas], tuomet rodyklė dydis. >> Taip. (Sizeof (int *)); Tas pats dalykas čia. Noriu (sizeof (char *)); Tai ketina skirti vietos žymeklis, kad rodo, kad "bumo". Man nereikia skirti vietos "bumo" pati , nes tai iš esmės atitinka tai, ką minėjau anksčiau char * x = "STRĖLĖ". "Bumo" jau egzistuoja. Taip atsitinka, kad egzistuoja tik skaityti atminties regione. Bet jis jau egzistuoja, o tai reiškia, šią kodo eilutę, jei s char ** * s char * ir jūs nustatote šį char * "boom". Jei aš norėjau kopijuoti "bumo" į S, tada man reikės skirti vietos s. Aš padarysiu * = malloc (sizeof (char) * 5); Kodėl 5? Kodėl gi ne 4? Atrodo, kad "STRĖLĖ" yra 4 simboliai. >> [Studentas] null charakterį. Taip. Savo stygos ketinate reikia nulinę pobūdžio. Dabar galiu padaryti kažką panašaus strcat - Kas yra funkcija kopijuoti eilutę? [Studentas] CPy? >> Strcpy. vyras strcpy. Taigi strcpy arba strncpy. strncpy yra šiek tiek saugiau, nes galite nurodyti tiksliai, kiek simbolių, bet čia nesvarbu, nes mes žinome. Taigi strcpy ir ieškoti argumentų,. Pirmasis argumentas yra mūsų tikslas. Antrasis argumentas yra mūsų šaltinis. Mes ketiname kopijuoti į mūsų paskirties * s rodyklė "STRĖLĖ". Kodėl jūs norite tai padaryti, o ne apie tai, ką mes turėjome strcpy prieš * S = "STRĖLĖ"? Yra priežastis, kodėl jūs galbūt norėsite tai padaryti, bet kas tai yra priežastis? [Studentas] Jei norite ką nors pakeisti "boom". >> Taip. Dabar galiu padaryti kažką panašaus s [0] = "X"; nes taškai, dėl krūvos į krūvą, ir ši vieta, kad yra nukreipta į yra rodyklė daugiau vietos krūvos, kuri yra saugoti "bumo". Taigi, šis "bumo" kopija yra saugomas krūvos. Yra techniškai dvi kopijas "bumo" mūsų programoje. Yra pirmasis, kad tik šio "BOOM" styginių konstantos, , o antroji kopija "bumo", strcpy sukūrė "bumo" kopiją. Bet kopija "bumo" yra saugomi krūvos, ir krūvos esate laisvai keisti. Krūvos yra ne tik skaityti, todėl tai reiškia, kad [0] ketina leisti jums pakeisti "bumo" vertę. Ji ketina leisti pakeisti šiuos simbolius. Turite klausimų? Gerai. Persikėlimas į buggy3, tegul gdb buggy3. Mes tiesiog paleiskite jį ir matome mes gauname segfault. Jei mes Backtrace, yra tik dvi funkcijos. Jei mes einame į mūsų pagrindinę funkciją, mes matome,, kad mes segfaulted šioje eilutėje. Taigi, tiesiog žiūri į šią eilutę, už (int linija = 0; "fgets ši medžiaga nėra lygi NULL; linija + +). Mūsų ankstesnis kadras buvo vadinamas _IO_fgets. Pamatysite, kad su built-in C funkcijų daug, , kad, kai jūs gaunate segfault, ten bus tikrai paslaptingas funkcijų pavadinimuose kaip tai _IO_fgets. Bet tai vyksta, susijusios su šio fgets skambučio. Kažkur viduje čia, mes segfaulting. Jei pažvelgsime į argumentų fgets, mes galime atspausdinti buferio. Leiskite spausdinti - O, ne. Spausdinti nesiruošia tiksliai taip, kaip aš noriu jį dirbti. Pažvelkime į faktinį programos. Buferis yra simbolių masyvas. Tai skaitmenu rinkinys 128 simbolių. Taigi, kai aš sakau, spausdinimo buferio, tai ketinate spausdinti tuos 128 simboliai, Manau, tai, ko tikimasi. Ką aš ieškojau spausdinti buferio adresą, bet tai nereiškia, tikrai pasakyti, man daug. Taigi, kai aš atsitiktų, tai čia x buferis, tai rodo man 0xbffff090, kuri, jei prisiminti, iš anksčiau ar tam tikru momentu, Oxbffff linkęs būti kamino ish regionas. Kamino linkęs pradėti kažkur tik pagal 0xc000. Tiesiog matyti šį adresą, aš žinau, kad buferis vyksta kamino. Perkrauti savo programą, paleisti,, buferio mes matėme šią ženklų seką yra gana daug prasmės. Tada spausdinimo failą, ką failas atrodo? [Studentas] null. >> Taip. Failas yra tipo FILE *, todėl yra rodyklė, ir tos rodyklė vertė yra tuščias. Taigi fgets ketiname bandyti skaityti iš tos rodyklė netiesioginiu būdu, tačiau, norint pasiekti, kad žymeklį, jis turi dereference jį. Arba tam, kad būtų pasiekti, ką ji turėtų būti nukreipta į, ji dereferences, kurių. Taigi tai dereferencing NULL pointeris ir IT segfaults. Aš galėčiau iš naujo paleiskite jį ten. Jei mes pertrauka mūsų pagrindinį punktą ir paleisti, pirmoje eilutėje kodas yra char * filename = "nonexistent.txt"; Tai turėtų duoti gana didelis užuominą, kodėl ši programa nepavyksta. Rašyti kitą iškelia mane į kitą eilutę, kur aš atidaryti šį failą, ir tada aš iš karto gauti į mūsų linijos, kur, kai aš paspauskite šalia, ji ketina į segfault. Ar kas nors nori išmesti priežastis, kodėl mes galime būti segfaulting? [Studentas] Failo neegzistuoja. >> Taip. Tai turėtų būti užuomina kad, kai jūs atidarote failą, kurį reikia patikrinti, kad byla iš tikrųjų egzistuoja. Taigi čia, "nonexistent.txt"; Kai mes fopen failo vardas skaityti, mes tada reikia pasakyti, if (failas == NULL) ir sako: printf ("Failas neegzistuoja!" arba - dar geriau - filename); return 1; Taigi dabar mes patikrinti, pamatyti, jei ji yra NULL prieš faktiškai tęsti ir bando skaityti iš šio failo. Mes galime perdaryti jį tik pamatyti, kad darbus. Siekiama įtraukti naują eilutę. Taigi dabar nonexistent.txt neegzistuoja. Jūs visada turėtumėte patikrinti, ar šis dalykas rūšiuoti. Jūs visada turėtumėte patikrinti, norėdami pamatyti, jei fopen grąžina NULL. Jūs visada turėtumėte patikrinti, įsitikinti, kad malloc negrįžta NULL, arba kita jums segfault. Dabar buggy4.c. Veikia. Spėju, kad šis laukia pirkimo arba galbūt begalinis Looping. Taip, tai begalinis Looping. Taigi buggy4. Atrodo, kad mes begalinis Looping. Mes galime sulaužyti pagrindinis, paleisti mūsų programą. Į gdb, kaip ilgai, kaip jūs naudojate santrumpa yra vienareikšmis arba specialios santrumpos, kad jie suteiks jums, tada galite naudoti n naudoti kitą vietoj to, kad įvesti kitą visą kelią. Ir dabar, kad aš hit n kartą, aš galiu tiesiog paspauskite Enter, kad nuolat vyksta šalia vietoj to, kad pasiektų n Įveskite n Įveskite n Įveskite. Atrodo, kad aš esu tam tikros rūšies for ciklas, kuriame masyvas [i] 0. Jis atrodo, kaip aš niekada išeities tai už linijos. Jei galiu atspausdinti aš, todėl aš yra 2, tada aš eiti toliau. Aš spausdinti i, i 3, tada aš eiti toliau. Aš spausdinti i ir i yra 3. Kitas, spausdinti i, i 4. Tiesą sakant, spausdinti sizeof (array), todėl masyvo dydis yra 20. Bet atrodo, kad yra keletas specialios gdb komanda vyksta kol kas nors atsitiks. Tai kaip nustatyti sąlygą kintamojo vertę. Bet aš nepamenu, kas tai yra. Taigi, jei mes nuolat vyksta - Ką tu sakai? Ką jums atnešti? [Studentas] Ar rodyti i Įdėti >> Taip. Taigi, rodyti, aš galiu padėti. Jei mes tiesiog i rodyti, jis bus įdėti čia ką i reikšmė yra todėl aš neturiu atspausdinti jį kiekvieną kartą. Jei mes tiesiog nuolat vyksta šalia, mes matome, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5. Kažkas vyksta siaubingai negerai, ir aš yra atstatyti į 0. Žiūri buggy4.c, mes matome, kas atsitinka, yra int masyvas [5]; (i = 0; i <= sizeof (array); + +) masyvas [i] = 0; Ką mes matome, kad negerai čia? Kaip užuominą,, kai darau gdb buggy4 - tegul pertrauka pagrindinis, paleisti - Aš spausdinimo sizeof (array) tik pamatyti, ką ši sąlyga yra, kur aš pagaliau išeiti. Kur aš esu? Ar galiu paleisti? Aš dar nedeklaravo. Taigi spausdinti sizeof (array), ir tai yra 20, kuri, kaip tikimasi, nes mano matrica yra dydis 5, ir tai iš 5 sveikųjų skaičių, todėl visą dalykas turi būti 5 * sizeof (int) baitų, sizeof (int) tendenciją būti 4. Taigi, sizeof (masyvas) yra 20. Ką tai turėtų būti? [Studentas] Padalinta iš sizeof (int). >> Taip, / sizeof (int). Atrodo, kad dar yra problema čia. Manau, kad tai turėtų būti tik < , nes tai beveik visada tarp > [Bowden] Taip. Kai mes einame už mūsų masyvo pabaigos, kažkaip, kad erdvė, kad mes privalomaisiais svarbesnio ï vertę. Ir todėl, jei mes žiūrime į buggy4, pertrauka Main, paleisti, galime spausdinti ï adresą. Atrodo, kad jis yra bffff124. Dabar galime spausdinti adresas masyvo [0]. 110. Ką apie [1]? 114. [2], 118. 11c, 120. masyvas [5] bfff124. Taigi masyvas [5] turi tą patį adresą, kaip aš, o tai reiškia, kad masyvas [5] yra i. , Jei jie turi tą patį adresą, jie yra tas pats dalykas. Taigi, kai mes masyvas [5], kad būtų 0, mes nustatome i 0. Ir jei jūs manote apie tai kamino, int i pirma yra paskelbtas, o tai reiškia, i gauna šiek tiek erdvės kamino. Tada masyvas [5] paskirstoma taip, tada 20 baitų skiriama kamino. Taigi, aš bus skiriama pirmą kartą, tada šie 20 baitų gauti skiriama. Taigi, aš nutinka prieš masyvo, ir dėl to, kaip, kaip aš praėjusią savaitę sakė, kur techniškai kamino auga žemyn, , kai į masyvo indeksas, mes garantuoti, kad 0. pozicija masyve visada vyksta prieš pirmąjį poziciją masyve. Tai yra natūra, kaip aš išsitraukė jį praėjusią savaitę. Atkreipkite dėmesį, kad apačioje turime Adresas 0 viršuje turime adresas Max. Kamino visada auga žemyn. Leiskite pasakyti, kad mes skirti i. Mes skirti sveikasis skaičius i, o tai reiškia, tegul tiesiog pasakyti, čia sveikasis skaičius i gauna skirta. Tada mes skirti mūsų 5 sveikųjų skaičių masyvas, tai reiškia, kad apačioje, kad, nuo kamino auga, tie 5 sveikieji skaičiai, gauti skiriama. Bet kadangi, kaip matricos dirbti, mes garantuojame, kad pirmoji vieta masyve visada yra adresas yra mažesnis nei antrojo masyvo dalykas. Taigi matrica pozicija 0 visada turi įvykti pirmoji atminties, kadangi masyvas 1 padėtis turi įvykti po to ir masyvo pozicija 2 turi įvykti po to, o tai reiškia, kad matrica pozicija 0 nutiktų, kažkur žemyn čia, masyvas 1 padėtis nutiktų, kas išdėstyta pirmiau, nes juda aukštyn reiškia didesnes adresus, nes didžiausia adresas yra čia. Taigi masyvas [0] Žemyn čia, masyvas [1] iki čia, masyvas [2] iki čia, masyvas [3] čia. Atkreipkite dėmesį, kaip prieš skyrėme sveikasis skaičius, aš visą kelią iki čia, kaip mes judėti toliau ir toliau į mūsų masyvas, mes vis arčiau ir arčiau mūsų sveikojo skaičiaus i. Jis tiesiog taip atsitinka masyvo, [5], kuri yra viena vieta už mūsų masyvas, yra tiksliai, kur sveikasis skaičius man teko būti skiriama. Taigi, kad yra vieta, kur mes atsitiktų būti pataikyti vietos kamino integer i kuri buvo skirta, ir mes nustatant, kad 0. Štai kaip tai veikia. Turite klausimų? Taip. [Studentas] Never mind. Gerai. [Studentas] Kaip išvengti šių klaidų rūšiuoti? Šių klaidų rūšiuoti? Nenaudokite savo programavimo kalbą C. Naudoti kalbą, kuri yra masyvo ribas kontrolės. Tol, kol jūs esate atsargus, jums tiesiog reikia, kad būtų išvengta vyksta praeityje jūsų masyvo ribų. [Studentas] Taigi čia, kai mes Eime praeityje jūsų masyvo ribų [Bowden] Štai kur ko pradėti going wrong. >> [Studentas] O, gerai. Tol, kol jūs likti per jūsų masyvo paskirtą atmintį, jūs gerai. Tačiau C nedaro klaidų. Jei aš masyvas [1000], tai mielai tiesiog pakeisti, kas beatsitiktų - Jis eina į masyvo pradžioje, tada jis eina 1000 pozicijas po ir nustatyta į 0. Jis nedaro jokių patikrinti, kad oh, tai ne iš tikrųjų turėti 1000 dalykų. 1000 yra būdas ne tik tai, ką aš turėtų būti pakeisti, kadangi Java arba kažkas jums gauti masyvas iš greitai indeksas arba indekso, išskyrus tam tikras ribas. Štai kodėl daug aukštesnio lygio kalbų šiuos dalykus kur, jei jūs einate už masyvo ribų, jums nepavyksta taip, kad jūs negalite pakeisti dalykų su Jumis ir tada viskas vyks daug blogiau nei tiesiog gauti išimtį suprantama, kad jūs nuėjo už masyvo pabaigos. [Studentas] Ir tokiu būdu mes ką tik pasikeitė <= tiesiog > [Bowden] Yeah. Ji turėtų būti > [Studentas] Teisė. Daugiau klausimų? Gerai. [Studentas] Turiu klausimą. >> Taip. [Studentas] Kas yra tikrasis masyvo kintamasis? [Bowden] Kaip, kas yra masyvas? Masyvas pati yra simbolis. Tai tik iš 20 baitų, kad mes nuorodų pradžios adresas. Jūs galite galvoti apie tai, kaip žymeklis, tačiau ji yra pastovi rodyklė. Kuo greičiau viskas susitvarko rengiami, kintamasis matrica neegzistuoja anymore. [Studentas] Taigi, kaip tai rasti masyvo dydį? Masyvo dydis reiškia to bloko dydžio, kad šis simbolis yra susijusi su. Kai aš kažką panašaus printf ("% p \ n", masyvas); tegul jį paleisti. Ką aš tiesiog padaryti neteisingai? Array "masyvas" pateikiamas čia. O, čia. Apsukite metalinis garsas yra protingas, ir tai atsitinka pastebėti, kad Aš paskelbiau kaip 5 elementų masyvo bet aš indeksavimo į poziciją 1000. Ji gali tai daryti, nes tai yra tik konstantos. Jis gali tik eiti taip toli pastebėti, kad aš ruošiuosi už masyvo ribų. , Bet pastebėsite, anksčiau, kai mes turėjo galiu būti neteisingas, tai niekaip negali nustatyti, kiek vertės galėčiau imtis, todėl ji negali nustatyti, kad aš buvau ketinate už masyvo pabaigos. Tai tiesiog Apsukite metalinis garsas yra protingas. Bet dabar buggy4. Taigi, ką dar aš darau blogai? Netiesiogiai skelbiantis bibliotekos funkcija printf ". Aš einu, kad nori # include . Gerai. Dabar veikia buggy4. Spausdinti masyvo vertę, kaip aš čia, spausdinimo jį kaip rodykle grafika kažkas, kad atrodo taip - bfb8805c - kai adresas tai kamino ish regione. Masyvas pati yra kaip žymeklis, bet tai nėra tikrasis rodyklė, nes reguliariai rodyklė, mes galime pakeisti. Masyvas yra tik keletas pastovus. 20 atminties blokai pradėti adresu 0xbfb8805c. Taigi bfb8805c per šiuo adresu +20- ar aš atspėti -20 - yra visi atminties, skirto šio masyvo. Masyvas, kintamasis savaime nėra saugomi bet kur. Kai jūs sudarymą, sudarytojas - į jį ranka banga - bet kompiliatorius tiesiog naudoti kur jis žino, masyvas. Ji žino, kur tas masyvas prasideda, ir todėl ji gali visada tiesiog daryti tai, ko Kompensacijų nuo tos pradžios. Ji nebūtinai turi kintamąjį pati atstovauti masyvo. Bet kai aš kažką panašaus int * p = masyvo; dabar p - rodyklė, kuri nurodo masyvo, ir dabar p tikrųjų egzistuoja kamino. Aš esu laisvai keisti psl. Galiu padaryti p = malloc. Taigi, jis iš pat pradžių atkreipė dėmesį į masyvą, dabar ji pažymi, kad šiek tiek erdvės krūvos. Aš negaliu to padaryti masyvai = malloc. Jei Apsukite metalinis garsas yra protingas, jis bus klykauti ne man Iškart. Tiesą sakant, aš esu gana įsitikinęs, gcc tai padaryti per. Taigi masyvas tipas 'int [5] "nėra jam priskiriamos pajamos. Jūs negalite priskirti kažką masyvo tipo nes masyvas yra tik konstanta. Tai yra simbolis, kuris nuorodos šie 20 baitų. Aš negaliu pakeisti. [Studentas] Ir kur yra saugomi masyvo dydis? [Bowden] Tai niekur nėra saugomi. Tai, kai jis sudarant. Taigi, kur yra saugomi masyvo dydis? Galite naudoti tik sizeof (masyvas) viduje funkciją, masyvas pasiskelbė. Taigi, jei aš galiu padaryti tam tikrą funkciją, foo, ir aš (int masyvas []) printf ("% d \ n", sizeof (array)); ir tada žemyn, čia aš vadinu foo (masyvas); šios funkcijos viduje - galime jį paleisti. Tai Apsukite metalinis garsas vėl yra protingas. Jis man sako, kad sizeof masyvo funkcijos parametras grįš dydis 'int *'. Tai būtų klaida, jei tai ne tai, ką norėjau, kad taip atsitiktų. Leiskite išjungti Werror. Įspėjimas. Įspėjimai gerai. Jis vis dar sudaryti tol, kol jis turi įspėjimą. . / A.out ketinate spausdinti 4. Įspėjimas, kuris buvo sukurtas aiškus rodiklis, kas nutiko. Šis int masyvas yra tik ketina spausdinti sizeof (int *). Net jei aš įdėti masyvas [5] čia, tai dar tik ketinate spausdinti sizeof (int *). Todėl, kai tik jums perduoti į funkciją, skirtumas tarp matricas ir rodyklės neegzistuoja. Panašu, kad tai masyvas, kuri buvo paskelbta kamino, bet kaip tik mes pereiname tą vertę, kad 0xbf blah, blah, blah į šią funkciją, rodyklė nurodo masyvo, kamino. Taigi, tai reiškia, kad sizeof taikoma tik funkciją, masyvas buvo paskelbta, , o tai reiškia, kad, kai jūs sudarant šią funkciją, Apsukite metalinis garsas eina per šią funkciją, jo manymu, masyvas int masyvas dydis 5. Taip, tada ji mato, sizeof (array). Na, tai 20. Kad iš tikrųjų, kaip sizeof iš esmės veikia beveik visais atvejais. Sizeof tai ne funkcija, tai operatorius. Jūs neturite skambinti sizeof funkciją. Sizeof (int), kompiliatorių bus tik išversti, kad iki 4. Got it? Gerai. [Studentas] Taigi, kas yra skirtumas tarp sizeof (array) pagrindinis ir foo? Tai yra todėl, kad mes sakome sizeof (array), kuris yra tipo int *, kadangi masyvas žemyn čia yra ne tipo int *, tai int masyvas. [Studentas] Taigi, jei jums turėjo parametrą masyvas [], o ne int * masyvas, reikštų, kad jūs vis dar gali pakeisti masyvas nes dabar rodyklė? [Bowden] Kaip tai? >> [Studentas] Yeah. Galite pakeisti masyvas per funkcija? [Bowden] Jūs galite pakeisti masyvo abiem atvejais. Abiem šiais atvejais esate laisvai pasakyti, masyvas [4] = 0. [Studentas] Bet jūs galite padaryti masyvo tašką į ką nors kita? [Bowden] Oh. Taip. Bet kuriuo atveju - >> [studentas] Yeah. [Bowden] Skirtumas tarp masyvas [] ir int * masyvas, nėra nė vieno. Taip pat galite gauti kai daugialypį masyvas čia dėl tam tikrų patogioje sintaksė, bet tai dar tik rodyklė. Tai reiškia, kad aš esu laisvai daryti, masyvas = malloc (sizeof (int)), o dabar atkreipti kažkur kitur. Bet tiesiog patinka, kaip tai veikia amžinai ir visada, keičiant šį masyvą todėl atkreipti dėmesį į ką nors kita nekeičia šio masyvo čia, nes tai argumentu, kopija, tai ne rodyklė į šį argumentą. Ir iš tikrųjų, kaip nuoroda, kad tai lygiai tas pats - mes jau pamatė, ką spausdinimo masyvo spaudinius - ką daryti, jei mes spausdinti iš masyvo adresą arba adresą masyvo adresą viena iš šių dviejų? Ignoruoti šį vieną. Gerai. Tai yra gerai. Dabar jis veikia / a.out. Spausdinimo masyvas, tada spausdinti masyvo adresą, yra tas pats dalykas. Masyvas tiesiog neegzistuoja. Ji žino, kai jūs spausdinate masyvas, jūs spausdinate simbolį, kuris reiškia, kad šių 20 baitų. Spausdinti masyvo adresą, gerai, masyvas neturi egzistuoti. Ji neturi adresą, taigi jis tiesiog spausdina šių 20 baitų adresą. Kuo greičiau jums sudaryti, kaip ir savo sukompiliuotą buggy4. / A.out matrica neegzistuoja. Pointeriai egzistuoja. Masyvai to padaryti negali. Atminties blokai, atstovaujantys masyvo vis dar egzistuoja, tačiau tokio tipo kintamasis masyvo ir kintamieji nėra. Tie, kurie, pavyzdžiui, pagrindinių skirtumų tarp matricas ir rodykles kuo greičiau padaryti funkcijų iškvietimų, nėra jokio skirtumo. Bet viduje funkciją, masyvo pati yra paskelbta, sizeof veikia skirtingai nes jūs spausdinate vietoj tipo dydžio blokų dydį, ir jūs negalite pakeisti jį, nes jis yra simbolis. Spausdinimas dalykas ir adresą dalykas spausdina tą patį. Ir kad gana daug. [Studentas] Ar galite pasakyti, kad dar kartą? Aš galėčiau ką nors praleido. Spausdinimo masyvas ir adresas masyvo spausdina tą patį, kadangi jei spausdinate Versus rodyklė adresas žymeklį, vienas dalykas, spausdina, ką jūs nukreipta į adresą, kitų spaudinių kamino rodyklė adresą. Galite pakeisti pelės žymeklį, jūs negalite pakeisti masyvo simbolį. Ir sizeof žymeklis ketinate spausdinti tos rodyklės tipo dydį. Taigi, int * p sizeof (p) ketinate spausdinti 4 bet int masyvas [5] Spausdinti sizeof (masyvas) ketinate spausdinti 20. [Studentas] int masyvas [5] bus atspausdinti 20? >> Taip. Štai kodėl viduje buggy4, kai ji naudojama sizeof (array) tai darė i <20, o tai yra ne tai, ką norėjo. Mes norime, I <5. >> [Studentas] Gerai. [Bowden] Ir tada, kai, kaip jums pradėti perduoti funkcijų, jei mes int * p = array; šios funkcijos viduje, mes iš esmės gali naudoti P ir masyvo lygiai tais pačiais būdais, išskyrus sizeof problemos ir besikeičiančios problema. Bet p [0] = 1; yra tas pats, kaip pasakyti masyvas [0] = 1; Ir kuo greičiau, kaip mes sakome, foo (masyvas), arba foo (p); viduje foo funkcija, tai yra tas pats skambutis du kartus. Yra skirtumas tarp šių dviejų skambučių. Kiekvienas gerai? Gerai. Mes turime 10 minučių. Mes pasistengsime gauti per šio Hacker typer programos, šioje svetainėje, kuris išėjo pernai ar kažką. Tai tiesiog turėtų būti kaip jūs įvedate atsitiktinai ir ji spausdina Nepriklausomai byla taip atsitinka, kad įdėjote, kas atrodo, kad jūs įvedėte. Atrodo, kad kažkoks operacinės sistemos kodas. Štai ką norime įgyvendinti. Jūs turite failus vykdomais pavadinimu hacker_typer kad mano vieną argumentą, failo "hacker tipo." Paleisti vykdomąjį turėtų išvalyti ekraną ir tada atsispausdinti iš praėjo rinkmenų, kiekvieną kartą, kai vartotojas paspaudžia klavišą, vieną simbolį. Taigi kokia raktas paspaudžiate, tai turėtų išmesti, o vietoj to atspausdinti simbolį iš failo tai yra argumentas. Aš gana daug pasakyti jums, ką yra tai, ką mes ketiname reikia žinoti. Bet mes norime patikrinti termios biblioteką. Aš niekada naudojamas šią biblioteką per visą savo gyvenimą, todėl ji turi labai nedaug tikslais. Bet tai bus biblioteka, mes galime naudoti išmesti simbolį, kurį nukentėjo kai jūs renkate į standartą in Taigi hacker_typer.c, ir mes ketiname norite # include . Žiūri žinyno puslapyje termios - I 'atspėti galinius OS ar kažką - Aš nežinau, kaip jį perskaityti. Žiūri į tai, ji sako, įtraukti šiuos 2 failus, kad mes tai padarysime. Pirmas dalykas, pirma, mes norime imtis vieną argumentą, kuris yra failas turėtume atidaryti. Taigi, ką aš noriu daryti? Kaip aš galiu patikrinti, turiu vieną argumentą? [Studentas] Jei argc lygus. >> [Bowden] Yeah. Taigi, jei (argc = 2!) Printf ("Naudojimas:% s [failą atidaryti]"). Taigi dabar, jei aš paleisti tai be suteikti antrą argumentą - O, aš turiu naują liniją - pamatysite, ji sako, naudojimas: / hacker_typer ir tada Antrasis argumentas turėtų būti aš noriu atidaryti failą. Dabar ką man daryti? Noriu skaityti šį failą. Kaip skaityti iš failo? [Studentas] Atidarote jį pirmiausia. >> Taip. Taigi, fopen. Ką fopen atrodyti? [Studentas] Failo vardas. >> [Bowden] Failo pavadinimas bus argv [1]. [Studentas] Ir tada tai, ką norite daryti su juo, kad - >> [Bowden] Taip. Taigi, jei tu negali prisiminti, jums gali tiesiog padaryti vyro fopen, kur jis bus const char * kelias, kur kelias failo vardas, const char * režimu. Jei atsitiktų, kad neprisimenu režimas, tada jūs galite pažvelgti veiksena. Brūkšnio simboliu viduje žinyno puslapių, yra tai, ką jūs galite naudoti norėdami ieškoti dalykų. Taigi, aš tipo / paieškos režimas režimo. N ir N yra tai, ką jūs galite naudoti paieškos rungtynių ciklą per. Štai jis sako, kad argumentas, režimas taškus į eilutę pradžioje su vieną iš šių sekų. Taigi, R, atviras teksto failą skaitymui. Kad tai, ką mes norime daryti. Skaityti, ir aš noriu laikyti, kad. Dalykas bus FILE *. Dabar, ką aš noriu padaryti? Duok man per sekundę. Gerai. Dabar, ką aš noriu padaryti? [Studentas] Patikrinkite, ar jis yra NULL. >> [Bowden] Yeah. Bet kuriuo metu galite atidaryti failą, įsitikinkite, kad jūs sėkmingai galėtų jį atidaryti. Dabar aš noriu padaryti, kad termios stuff, kur aš noriu pirmiausia perskaityti mano dabartinius nustatymus ir išgelbėti tuos, į kažką, tada aš noriu pasikeisti savo nustatymus mesti į simbolį, kuris I tipo, ir tada aš noriu atnaujinti šiuos parametrus. Ir tada programos pabaigoje, aš noriu pakeisti atgal į savo pradinius parametrus. Taigi struct bus tipo termios, ir aš norėčiau, kad nori du iš šių. Pirmasis vyksta būti mano current_settings, ir tada jie ketina būti mano hacker_settings. Pirma, aš ketinate norite išsaugoti savo dabartinius nustatymus, tada aš ruošiuosi norite atnaujinti hacker_settings ir tada mano programos pabaigos būdas, aš noriu grįžti prie esamais nustatymais. Taupo dabartinius nustatymus, taip, kad veikia, Mes vyras termios. Mes matome, kad turime šį int tcsetattr, int tcgetattr. Galiu perduoti termios struct pagal jo rodyklė. Kaip ši atrodys - I've jau pamiršote, ką funkcija buvo vadinama. Nukopijuokite ir įklijuokite jį. Taigi tcgetattr, tuomet aš noriu važiuoti, struct, kad aš taupymo informaciją, kuris vyksta būti current_settings, ir pirmasis argumentas yra failo deskriptorius dalykas, kurį noriu išsaugoti atributus. Kas failo deskriptorius, kaip ir bet kuriuo metu, kai atidarote failą, jis gauna failo deskriptorius. Kai aš fopen argv [1], ji pasireiškia failo deskriptorius, kurioje esate nuorodų jei norite skaityti arba rašyti į jį. Kad nėra failo deskriptorius, aš noriu naudoti čia. Yra trys failų deskriptoriai turite pagal nutylėjimą, standartas standartas atlikti, ir standartinė paklaida. Pagal nutylėjimą, aš manau, kad tai standartas yra 0, standartas iš 1, ir standartinė paklaida yra 2. Taigi, ką aš noriu pakeisti nustatymus? Noriu pakeisti parametrus, kai aš paspauskite simbolį, Noriu mesti tą simbolį karto, o ne spausdinti į ekraną. Kas srautas - standartinis, standartinės, arba kad standartinė paklaida - reaguoja į dalykų, kai aš tipo į klaviatūrą? >> [Studentas] Standartinis in >> Yeah. Taigi aš galiu padaryti arba 0 arba Galiu padaryti STDIN. Gaunu standartą current_settings, in Dabar aš noriu atnaujinti šiuos parametrus, todėl pirmiausia aš kopijuoti į hacker_settings ką mano current_settings yra. Ir kaip structs darbas tai tiesiog nukopijuoti. Kopijuoja visus laukus, kaip galima tikėtis. Dabar aš noriu atnaujinti, kai kurie laukai. Žiūri termios, jums reikės perskaityti daug šio tik pamatyti, ką jūs norėtumėte ieškoti, tačiau jūs ketinate norite ieškoti vėliavos echo, todėl Echo Echo įvesties ženklai. Pirmiausia noriu nustatyti - I've jau pamiršote, ką laukai yra. Tai, ką struct atrodo. Taigi įvesties režimai, aš manau, kad mes norime pakeisti. Mes pažvelgti į tirpalą, įsitikinti, kad tai, ką mes norime pakeisti. Mes norime pakeisti, siekiant užkirsti kelią, reikia ieškoti per visus šiuos lflag. Mes norime pakeisti vietos režimus. Jums reikės perskaityti visą šį dalyką suprasti, kur viskas priklauso kad mes norime pakeisti. Bet tai viduje vietinių rūšių, kur mes einame, kad nori pakeisti, kad. Taigi hacker_settings.cc_lmode yra tai, ką ji vadinama. c_lflag. Tai kur mes patekti į Bitinis operatorių. Mes rūšies Out Of Time, bet mes pereiti per jį nekilnojamojo greitai. Tai yra, kai mes gauname į Bitinis operatorių, ten, kur aš manau, vieną kartą seniai sakė, kad, kai paleidus, susijusius su vėliavomis, jūs ketinate naudoti Bitinis operacijų daug. Kiekviena vėliavos bitų atitinka kažkoks elgesio. Taigi čia, ši vėliava yra krūva įvairių dalykų, kai visi jie reiškia kažką kitą. Bet ką aš noriu padaryti, tai tiesiog išjungti grąžtą, kuris atitinka ECHO. Taip pasukti, kad ne aš & = ¬ ECHO. Tiesą sakant, aš manau, kad tai kaip techo ar kažką. Aš tik ketina patikrinti dar kartą. Galiu termios. Tai tiesiog ECHO. ECHO bus vienas tiek. ¬ ECHO ketina tai visi bitai yra nustatyti 1, o tai reiškia, visi vėliavas true išskyrus ECHO bitų. Baigti Mano vietos vėliava, tai reiškia, kad visų šalių vėliavomis, kurie šiuo metu nustatyta, kad tiesa vis dar bus true. Jei mano ECHO vėliava yra true, tada tai yra būtinai false ECHO vėliava. Taigi tiesiog išjungė šią kodo eilutę ECHO vėliava. Kitų eilučių kodo, aš tiesiog nukopijuokite juos laiko interesus ir tada juos paaiškinti. Tirpale, sakė jis 0. Tai turbūt geriau aiškiai pasakyti STDIN. Atkreipkite dėmesį, kad aš taip pat daro ECHO | ICANON čia. ICANON nurodo į kažką atskirą, o tai reiškia kanoninė režimą. Kas kanoninė režimas reiškia, paprastai, kai jūs įvedate į komandų eilutę, standartas netvarko nieko, kol paspausite naujos eilutės. Taigi, kai jūs GetString, įvedate dalykų krūva, tada paspausite naujos eilutės. Štai, kada ji buvo išsiųsta standarto in Tai yra numatytasis nustatymas. Kai aš išjungti kanoninė režimą, dabar kiekvienas, kai paspausite vieną simbolį yra tai, ką gauna tvarkomi, kuris paprastai yra natūra blogo, nes jis lėtai apdoroti šiuos dalykus, kuris yra, kodėl ji yra gera sušvelninti jį į visą linijų. Bet aš noriu, kiekvienas simbolis turi būti tvarkomi nes aš nenoriu laukti man, kad pasiektų naują eilutę , prieš tai apdoroja visus simbolius aš rašyti. Tai išjungia kanoninė režimą. Ši medžiaga tiesiog reiškia, kai jis iš tikrųjų apdoroja simbolių. Tai reiškia, apdoroti juos nedelsiant; kuo greičiau aš rašyti juos, apdoroti. Ir tai yra funkcija, kuri atnaujina savo nustatymus standartą, ir TCSA priemonė tai padaryti dabar. Kiti variantai laukti, kol visa tai, kas šiuo metu upelio yra tvarkomi. Kad tikrai ne klausimas. Tiesiog dabar pasikeisi savo nustatymus, kokia yra šiuo metu hacker_typer_settings. Spėju, kad pavadino jį hacker_settings, todėl galime pakeisti, kad. Pakeiskite viską hacker_settings. Dabar mūsų programos pabaigoje mes ketiname norite grįžti kas šiuo metu viduje normal_settings kuris vyksta tiesiog atrodyti ir normal_settings. Atkreipkite dėmesį, nepasikeitė bet mano normal_settings nuo pradžių gauti jį. Tada tiesiog pakeisti juos atgal, galiu perduoti juos atgal pabaigoje. Tai buvo atnaujinta. Gerai. Dabar viduje čia aš tik paaiškinti kodą laikui interesų. Tai nereiškia, kad daug kodas. Mes matome, mes skaityti iš bylos pobūdį. Mes pavadino jį f. Dabar galite vyras fgetc, bet kaip fgetc ketina dirbti yra tik jis ketina grįžti į simbolį, kad jūs tiesiog perskaityti ar eof kuris atitinka failą arba kai klaidos vyksta pabaigos. Mes kilpų, toliau skaityti vieną simbolį iš failo, kol mes pritrūksta simbolių skaitomas. Ir nors, ką mes darome, mes laukti vienas simbolis nuo standartinių in Kiekvieną kartą jūs tipo kažkas į komandų eilutę, , skaito simbolį nuo standartinių in Tada putchar yra tik ketina įdėti char mes skaitome čia failą su standartine out. Galite vyras putchar, bet tai tik pradėti standarto, tai spausdinant tą simbolį. Taip pat Jūs galite tiesiog padaryti printf ("% c", c); tą pačią idėją. Kad ketina padaryti didžiąją dalį mūsų darbo. Paskutinis dalykas, mes ketiname norite daryti yra tiesiog fclose mūsų failą. Jei jūs neturite fclose, Atminties nutekėjimas. Mes norime fclose failą, mes iš pradžių atidarytas, ir aš manau, kad viskas. Jei mes darome, kad aš jau turiu problemų. Pažiūrėkime. Ką ji skųstis? Tikimasi "int", bet argumentas yra tipas "struct _IO_FILE *". Mes pamatyti, jei tai veikia. Leidžiama tik C99. Augh. Gerai, kad hacker_typer. Dabar mes turime daugiau naudingų aprašymus. Taigi naudoti nedeklaruoto identifikatorius "normal_settings". Aš ne ją vadina normal_settings. Aš jį pavadino current_settings. Todėl galime pakeisti visa tai. Dabar artimųjų argumentą. Aš padaryti šį 0 dabar. Gerai. . / Hacker_typer cp.c. Aš taip pat nebuvo išvalyti ekraną pradžioje. , Bet jūs galite pažvelgti atgal į paskutinę problemą, pamatyti, kaip jūs išvalyti ekraną. Tai tiesiog spausdinti keletą simbolių o tai yra tai, ką aš noriu padaryti. Gerai. Ir galvoju apie tai, kodėl tai turėjo būti 0 vietoj standartinio įvesties, , kurios turėtų būti # define 0, tai skundžiasi, kad Anksčiau, kai aš sakė, kad yra failų deskriptoriai, bet tada jūs taip pat turite savo failą * failo deskriptorius yra tik vienas sveikasis skaičius, kadangi FILE * turi visa krūva daiktų su juo susijusios. Priežastis, kodėl mes turime pasakyti 0 vietoj stdin kad stdin FILE *, kurioje nurodoma dalykas, kad yra nuorodų failo deskriptorius 0. Taigi, net čia, kai aš fopen (argv [1], Gaunu failą *. Bet kažkur tame faile * yra dalykas, atitinkantis šio failo failo deskriptorius. Jei peržvelgsite žinyno puslapyje atvira, todėl manau, kad jūs turite padaryti atvirą man 3 - Ne - vyras 2 atviri - taip. Jei pažvelgti atviromis puslapyje, atviras kaip žemesnio lygio fopen, ir jis grąžina tikrasis failo deskriptorius. fopen veikia pagal atviro ant daiktų krūva, , o ne grąžinant tik, kad failo deskriptorius grąžina visa bylos * žymeklį kurio viduje yra mūsų mažai failo deskriptorius. Taigi standartinio nuoroda į failą * dalykas, o 0 reiškia, kad tik failo deskriptorius standarto savaime. Turite klausimų? [Juokiasi] išmetė per tą. Gerai. Baigsime. [Juokiasi] [CS50.TV]