[Powered by Google Translate] [5.pants - ērtāk] [Rob Bowden - Hārvarda] [Tas ir CS50. - CS50.TV] Tāpat kā es teicu manu e-pastu, ir lietas, ko var izmantot daudz izņemot ierīces, lai faktiski darīt problēmu kopas. Mēs iesakām darīt to ierīcē tikai tāpēc, tad mēs varam vieglāk jums palīdzēt un mēs zinām, kā viss iet uz darbu. Bet kā viens piemērs, kur jūs varat darīt lietas, ja, teiksim, jums nav piekļuves uz ierīcēm vai vēlaties strādāt Science Center pagrabā - kas faktiski viņi ir ierīci pārāk - ja jūs vēlaties strādāt jebkur. Viens piemērs ir esat redzējuši / dzirdējuši par SSH? SSH ir būtībā tāpat kā savienot ar kaut ko. Patiesībā, šobrīd es esmu SSHed ierīcē. Es nekad strādāt tieši ierīcē. Šeit ir ierīce, un ja paskatās uz leju šeit jūs redzat šo IP adresi. Es nekad strādāt pati ierīce; Es vienmēr nāk vairāk nekā uz iTerm2 loga / termināla logu. Jūs varat SSH uz šo IP adresi, ssh jharvard@192.168.129.128. Es atceros, ka vairāki ļoti viegli, jo tas ir tik jauki modelis. Bet, ka būs man jautā par manu paroli, un tagad es esmu iekārtā. Būtībā, šajā brīdī, ja jūs atvēra termināla iekšpusē pati ierīce, Šī saskarne, tomēr jūs varētu to izmantot, ir tieši tāds pats kā saskarne es esmu, izmantojot vairāk nekā šeit, bet tagad tu esi SSHed. Jums nav SSH pie ierīces. Viens piemērs citā vietā jūs varētu SSH ir es esmu diezgan pārliecināts, ka jums ir pēc noklusējuma - Oh. Lielāks. Jums visiem vajadzētu būt pēc noklusējuma FAS kontos LKS serveriem. Par mani, es būtu SSH rbowden@nice.fas.harvard.edu. Tas notiek, lai jums jautāt, ka pirmo reizi, un jūs sakāt: jā. Mana parole ir tikai būs mans FAS parole. Un tāpēc tagad, es esmu SSHed ar jauku serveriem, un es varu darīt kaut ko es gribu šeit. Klašu jūs varētu veikt, piemēram, 124 daudz, nāksies jums augšupielādēt stuff šeit faktiski iesniegt savu problēmu kopas. Bet saku jums nav piekļuves jūsu ierīci. Tad jūs varat darīt lietas, piemēram, šeit tā teikt - Tas ir tikai mūsu sadaļā jautājumiem. Tā lūgs jums to darīt iekārtā. Tā vietā es ņemšu tikai darīt to uz servera. Es esmu gatavojas unzip to. Problēma būs, ka jūs izmantot, lai, izmantojot kaut ko līdzīgu gedit vai kāds iekšpusē ierīces. Jūs neesat gatavojas būt, ka uz SKS serverī. Tas viss tikai būs šis tekstuāli saskarne. Lai jūs varētu vai nu viens, mēģināt uzzināt teksta redaktoru, kas viņiem ir. Viņi ir Nano. Nano parasti ir diezgan viegli izmantot. Jūs varat izmantot savu bultas un ierakstiet parasti. Tā ka nav grūti. Ja jūs vēlaties saņemt tiešām iedomātā jūs varat izmantot Emacs, ko es droši vien nebūtu atvērti, jo es pat nezinu, kā lai aizvērtu Emacs. Kontroles X Control C? Yeah. Vai jūs varat izmantot Spars, kas ir tas, ko es izmantot. Un tāpēc tie ir jūsu iespējas. Ja jūs nevēlaties to darīt, jūs varat arī, ja paskatās manual.cs50.net-- Oh. Datorā, jūs varat SSH izmantojot tepe, kas jums nāksies lejupielādēt atsevišķi. Uz Mac, jūs varat vienkārši noklusējuma izmantot Terminal vai jūs varat lejupielādēt iTerm2, kas ir kā jauka, fancy Terminal. Ja jūs iet uz manual.cs50.net jūs redzēsiet saiti uz Notepad + +, kas ir tas, ko jūs varat izmantot datorā. Tas ļauj jums SFTP no Notepad + +, kas būtībā ir SSH. Ko tas ļaus jums darīt, ir rediģēt failus lokāli, un tad, ja jūs vēlaties, lai saglabātu tos, tas ļaus ietaupīt līdz nice.fas, kur jūs varat palaist tos. Un uz Mac līdzvērtīgs būs TextWrangler. Tātad tas ļauj jums darīt to pašu. Tas ļauj jums rediģēt failus lokāli un saglabāt tos nice.fas, kur jūs varat palaist tos. Tātad, ja jūs esat kādreiz iestrēdzis bez ierīces, jums ir šīs iespējas lai vēl darīt savu problēmu kopas. Viena problēma būs, ka jūs neesat nāksies CS50 bibliotēka jo nice.fas nav pēc noklusējuma ir, ka. Jūs varat vai nu lejupielādēt CS50 bibliotēka - Es nedomāju, ka man vajag, ka šajā brīdī. Jūs varat vai nu lejupielādēt CS50 bibliotēku un kopēt to pa nice.fas, vai es domāju, šajā brīdī mēs neizmantojam to vairs vienalga. Vai, ja mēs, jūs varat pagaidām aizstāt to ar plānu ieviešanu par šajā CS50 bibliotēkas funkcijas vienalga. Tāpēc, ka nedrīkst būt, ka daudz ierobežojumu. Un tas, ka. Es iešu atpakaļ uz ierīces tagad, mēs darīsim visu, kas ir ierīces. Aplūkojot mūsu sadaļu jautājumiem, sākumā, tāpat kā es teicu manu e-pastu, Mums ir jārunā par vienu īsu jums bija paredzēts skatīties. Mums ir novirzot & Caurules un šiem trim jautājumiem. Uz kuru straume to funkcijas, piemēram printf rakstīt pēc noklusējuma? Tā straume. Kas ir plūsma? Plūsma ir būtībā tāpat tas ir tikai dažas - Tas nav pat avots 1s un 0s. Straume tas prasot šeit ir standarta out. Un tā standarts, kas ir plūsma, kas, ja jūs rakstīt uz to, tā parādās uz ekrāna. Standarts, kas, pēc straumi, tas nozīmē, ka jūs vienkārši uzrakstīt 1s un 0s uz to, un otrs gals standarta, kas tikai lasa no šīs plūsmas. Tas ir tikai virkne 1s un 0s. Jūs varat rakstīt uz plūsmām vai jūs varat izlasīt no plūsmām atkarībā no tā, kāda plūsma patiesībā ir. Pārējie divi Noklusējuma plūsmas ir standarta un standarta kļūda. Standarta ir, kad tu GetString, tas gaida, lai jūs varētu ievades sīkumi. Tātad, tas gaida jūs, tas ir faktiski gaida uz standarta, kas ir patiešām to, ko jūs saņemsiet, ja jūs tipa pie klaviatūras. Jūs rakstāt par standarta collas Standarta kļūda ir būtībā atbilst standarta out, bet tas ir specializējies ka tad, kad jūs drukāt ar standarta kļūdu, jūs vajadzēja tikai drukas kļūda ziņas, ka lai jūs varētu atšķirt regulāru ziņojumu iespiestas uz ekrāna pret kļūdu ziņojumiem atkarībā no tā, vai viņi devās uz standarta out vai standarta kļūda. Failus too. Standarts, kas, standarta, un standarta kļūda ir tikai īpašas strautiem, bet tiešām jebkuru failu, atverot failu, tas kļūst plūsmā baitu kur jūs varat vienkārši lasīt no šīs plūsmas. Tu, lai lielākā daļa, var tikai domāt par failu kā plūsmā baitu. Tātad, ko straumes viņi rakstīt pēc noklusējuma? Standarta out. Kāda ir atšķirība starp> un >> atšķirība? Vai kāds skatīties video iepriekš? Labi. > Būs kā jūs novirzīt vērā failus, un >> ir arī gatavojas novirzīt izejas uz failu, bet tas tā vietā gatavojas pievienot lietas materiāliem. Piemēram, pieņemsim, ka es notikt ir dict tieši šeit, un vienīgais sīkumi iekšā dict ir kaķis, kaķis, suns, zivs, suns. Viena komanda, kas jums ir pie komandrindas ir kaķis, kas ir tikai gatavojas drukāt, kas ir failā. Tātad, kad es saku kaķu dict, tas notiek, lai drukātu kaķis, kaķis, suns, zivs, suns. Tas ir viss, kaķis dara. Tas nozīmē, ka to iespiež uz standarta ārā kaķis, kaķis, suns, zivs, suns. Ja es tā vietā vēlas novirzīt kas uz failu, es varētu izmantot> un pārorientēt to, lai neatkarīgi fails. Es aicinu šo failu failu. Tāpēc tagad, ja I ls, es redzēsit man ir jaunu failu ar nosaukumu failu. Un, ja es to atvērtu, tas būs tieši tas, ko kaķis likt pie komandrindas. Tāpēc tagad, ja man tas atkal, tad tas būs novirzīt izejas uz failu, un es esmu nāksies to pašu precīzu lieta. Tātad tehniski, tas pilnīgi neievērot ierobežojumu dēļ, kas mums bija. Un mēs redzēsim, ja es mainīt dict, es izņēma suns. Tagad, ja mēs kaķis dict uz failu vēlreiz, mēs esam nāksies jauno versiju ar suni noņemts. Tātad tas pilnīgi ignorē to. Tā vietā, ja mēs izmantojam >>, tas būs pievienot failu. Tagad, atverot failu, mēs redzam mums ir tikai pašu drukāto divreiz jo tas bija tur vienreiz, tad mēs pievienots oriģināls. Tātad tas, ko> un >> darīt. Vai nākamais jautāt - Tas nav jautāt par to. Otrs, kas mums ir, ir <, kas, ja> novirza standarta out, jums 2>, kas ir novirzot standarta kļūda. Tātad, ja kaut kas devās uz standarta kļūdu, tas nav get nodot txt2. Bet paziņojums, ja man 2>, tad tas vēl drukāšanas Sveiki, Rob! uz komandrindas jo es esmu tikai novirzot standarta kļūda, es neesmu pārprofilējot standartu out. Standarta kļūdas un standarta ārā ir atšķirīgas. Ja jūs vēlētos, lai faktiski rakstīt standarta kļūdu, tad es varētu mainīt tas ir fprintf stderr. Tātad printf, pēc noklusējuma, izdrukas uz standarta out. Ja es gribu, lai izdrukātu standarta kļūdu manuāli, tad man ir izmantot fprintf un norāda, kāda es gribu, lai izdrukātu. Ja tā vietā es tomēr fprintf stdout, tad tas būtībā atbilst printf. Bet fprintf standarta kļūda. Tāpēc tagad, ja es novirzīt to vērā txt2, Sveiki, Rob! joprojām kļūst izdrukāts pie komandrindas jo tas kļūst iespiež uz standarta kļūda, un es esmu tikai pārprofilējot standartu out. Ja es tagad novirzīt standarta kļūda, tagad tā nav get uzdrukāts, un txt2 būs Sveiki, Rob! Tāpēc tagad, jūs varat izdrukāt savu faktisko kļūdas, lai standarta kļūda un izdrukāt regulāras ziņas standarta out. Un tā, kad jūs palaist savu programmu, jūs varat palaist to, kā / sveiki. Šāda veida saistībā ar 2> lai jūsu programma ir gatavojas palaist normāli, bet visas kļūdas ziņojumi, ka jums, jūs varat pārbaudīt vēlāk savu kļūdas žurnālā, tik kļūdas, un tad skatīties vēlāk un jūsu kļūdas fails būs kādas kļūdas, kas notika. Jautājumi? Pēdējais ir caurules, ko jūs varat iedomāties, kā veikt standarta ārā no vienas komandas un padarot to standartu par nākamo komandu. Piemērs šeit ir atbalss ir komandrindas lieta kas ir tikai gatavojas atkārtot kāds man kā tās argumentu. Es ne likts pēdiņas. Echo blah, blah, blah ir tikai gatavojas drukāt blah, blah, blah. Pirms tam, kad man teica, man bija likt Rob uz txt failā jo es varu tikai novirzīt txt failus, nevis, / ja es atkārtoju Rob un tad caurule to savos / sveiki, ka arī darīt to pašu veida lieta.. Tas ir ņemot izejas šo komandu, ECHO Rob, un izmanto to kā ievade. / sveiki. Jūs varat domāt par to kā pirmās novirzīt atbalss Rob failā un tad ieguldījums. / sveiki šo failu, kas bija tikai izvadīt. Bet tas aizņem pagaidu failu no attēla. Jautājumi par šo? Nākamais jautājums ir gatavojas iesaistīt šo. Ko cauruļvads jūs varētu izmantot, lai atrastu vairākas unikālas nosaukumus failu sauc names.txt? Komandas mēs spēsim vēlaties izmantot šeit ir unikāls, tāpēc Uniq, un tad wc. Jūs varat darīt vīrieti uniq faktiski apskatīt, kas tas dara, un tas ir tikai gatavojas, lai filtrētu blakus atbilstošas ​​līnijas no ieejas. Un cilvēks WC gatavojas drukāt newline, vārdu un baitu skaitu par katru failu. Un pēdējais, mēs esam gatavojas vēlaties izmantot, ir kārtot, kas gatavojas tikai sakārtot līnijas txt failu. Ja es veikt dažas txt failu, names.txt, un tas ir Rob, Tommy, Jāzeps, Tommy, Jāzeps, RJ, Rob, ko es gribu darīt, šeit ir atrast vairākas unikālas vārdi šajā failā. Tātad, kādi būtu atbilde būt? >> [Students] 4. >> Jā. Tas ir 4 jo Rob, Tommy, Jāzeps, RJ ir tikai unikāls vārdi šajā failā. Pirmais solis, ja es tikai darīt vārdu skaits par names.txt, tas ir faktiski stāsta man visu. Tas ir faktiski drukāšanas - pieņemsim redzēt, cilvēks wc - newlines, vārdiem un baitu skaits. Ja es tikai rūp līnijas, tad es varu tikai darīt WC-l names.txt. Tā ka ir solis 1. Bet es negribu, lai WC-l names.txt jo names.txt tikai satur visus vārdus, un es gribu, lai filtrēt nav unikālas ones. Tātad, ja man Uniq names.txt, ka nav gluži dod man to, ko es gribu jo dublēti nosaukumi ir joprojām. Kāpēc tā? Kāpēc uniq nedara to, ko es gribu? [Students] dublikāti nav [dzirdams] >> Jā. Atceros man lapu par Uniq saka filtrs blakus bet saderīgas līnijas. Viņi nav blakus, tāpēc tas nav filtrēt tos. Ja es šķirot tos vispirms kārtot names.txt gatavojas nodot visas dublēt rindas kopā. Tāpēc tagad kārtot names.txt tas ir. Es esmu gatavojas vēlaties izmantot šo kā ieguldījumu Uniq, kas ir | uniq. Tas dod man Jāzepu, RJ, Rob, Tommy, un es vēlos izmantot šo kā ieguldījumu wc-l, kas gatavojas sniegt man 4. Tāpat kā tas saka šeit, ko cauruļvads jūs varētu izmantot? Jūs varat darīt daudzas lietas, piemēram, izmantojot virkni komandu kur jūs izmantot izejas no vienas komandas kā ievadi uz nākamo komandu. Jūs varat darīt daudz lietas, daudz gudrs lietām. Jautājumi? Labi. Tas ir tas par caurulēm un pārorientācija. Tagad mēs ejam uz faktisko sīkumi, kodēšanas sīkumi. Iekšpusē šis PDF, jūs redzēsiet šo komandu, un jūs vēlaties palaist šo komandu savā ierīcē. wget ir komanda, lai tikai iegūtu kaut ko no interneta, būtībā, tāpēc wget un šis URL. Ja jūs devās uz šo URL savā pārlūkprogrammā, tas varētu lejupielādēt šo failu. Es tikko noklikšķinājuši par to, lai tā lejupielādēt failu par mani. Bet rakstot wget šī lieta iekšpusē termināla ir tikai gatavojas lejupielādēt to savā terminālā. Man ir section5.zip, un jūs vēlaties, lai unzip section5.zip, kas gatavojas sniegt jums mapi sauc section5, kas ir nāksies visus failus, mēs ejam, lai, izmantojot šodien iekšpusē no tā. Tā kā programmas "failu nosaukumi liecina, viņi mazliet buggy, lai jūsu uzdevums ir izdomāt, kāpēc, izmantojot gdb. Vai visi ir tos lejupielādēt / zina, kā iegūt tos lejupielādēt savā iekārtu? Labi. Darbojas ./buggy1, tā teikt segmentāciju vaina (core dempinga cenām), kas jebkurā laikā jūs saņemsiet segfault, tas slikti. Kādos apstākļos jūs saņemsiet segfault? [Students] dereferencing ar null rādītāju. >> Jā. Tāpēc, ka ir viens piemērs. Dereferencing Null rādītāju jūs gatavojas saņemt segfault. Kas segfault līdzekļus ir jūs pieskaras atmiņu jums nevajadzētu pieskarties. Tātad dereferencing Null rādītāju pieskaras adresi 0, un būtībā, visi datori mūsdienās saka, ka adrese 0 ir atmiņas jums nevajadzētu pieskarties. Tātad, tāpēc dereferencing Null rādītāju rezultātus segfault. Ja jums gadās ne inicializēt rādītāju, tad tas ir atkritumu vērtība, un tad, kad jūs mēģināt dereference tā, visticamāk, jūs esat pieskaras atmiņu kas ir vidū nekur. Ja jums gadās saņemt laimīgs un atkritumu vērtības noticis norādīt uz kaut uz skursteņa vai kaut ko, tad, kad tu dereference ka rādītāju, kas jums nav inicializēts, nekas iet greizi. Bet, ja tas ir norādot uz, teiksim, kaut kur starp kaudze un kaudze, vai tas ir norādot tikai kaut kas nav ticis izmantots ar savu programmu vēl, tad jūs pieskaroties atmiņu jums nevajadzētu pieskarties un tu segfault. Rakstot rekursīvo funkciju un tas recurses pārāk daudz reižu un jūsu kaudze aug pārāk liels un kaudzīti satiekas vērā lietas ka to nedrīkst sadurties ar, jūs pieskaras atmiņu jums nevajadzētu pieskarties, lai jūs segfault. Tas ir tas segfault ir. Tas ir arī pats iemesls, ka, ja jums ir virkne līdzīgu - iesim atpakaļ uz iepriekšējo programmu. Jo hello.c--I'm tikai gatavojas darīt kaut ko citu. char * s = "Hello World!"; Ja es izmantot * s = kaut vai s [0] = "X"; lai padarītu sveiki, / sveiki., kāpēc tas segfault? Kāpēc tas segfault? Ko jūs sagaidāt notikt? Ja man printf ("% s \ n", i); ko jūs sagaida, lai iespiež? [Students] X sveiki. >> Jā. Problēma ir tā, ka tad, kad jūs atzīt virkni kā šis, s ir rādītājs, ka gatavojas doties uz skursteņa, un ko s ir vērsta uz ir šī virkne, kas ir ietverts tikai lasīšanas atmiņas. Tik vienkārši ar nosaukumu, lasāmatmiņa, jums vajadzētu saņemt ideja ka, ja jūs mēģināt mainīt to, kas lasāms tikai atmiņa, jūs darāt kaut ko jūs nevar darīt ar atmiņu, un jūs segfault. Tas ir tiešām liela atšķirība starp char * s un char s []. Tātad char s [], tagad šī virkne būs jāliek uz skursteņa, un kaudze ir tikai lasāma, kas nozīmē, ka tas ir darbs perfekti labi. Un tā dara. Atcerieties, ka tad, kad es to char * s = "Hello World!", I pati uz skursteņa bet s norāda uz kaut ko citu, un ka kaut kur citur notiek, ir tikai lasāms. Bet char s [] ir tikai kaut uz skursteņa. Tātad tas ir vēl viens piemērs segfault notiek. Mēs redzējām, ka ./buggy1 izraisīja segfault. Teorētiski, jums nevajadzētu apskatīt buggy1.c nekavējoties. Tā vietā, mēs apskatīt to, izmantojot gdb. Ievērojiet, ka tad, kad jūs saņemsiet segmentāciju vaina (core dempinga cenām), Jūs saņemsiet šo failu nekā šeit sauc kodols. Ja mēs ls-l, mēs redzēsim, ka kodols ir parasti diezgan liels fails. Tas ir baitu skaits no failu, tāpēc izskatās, ka tas ir 250 kaut kilobaiti. Iemesls ir tas, kas pamatā izgāztuve patiesībā ir ir tad, kad jūsu programma avarē, valsts atmiņas par savu programmu vienkārši kļūst nokopēt un ielīmēt šo failu. Tas izpaužas aprakta šo failu. Šī programma, bet tā darbojas, noticis, ir atmiņas izmantošana aptuveni 250 kilobaitiem, un lai tas, ko saņēmu aprakta šo failu. Tagad jūs varat apskatīt šo failu, ja mēs GDB buggy1 kodols. Mēs varam vienkārši darīt gdb buggy1, un kas būs vienkārši uzsākt gdb regulāri, izmantojot buggy1 kā tās ieejas failu. Bet, ja jūs GDB buggy1 kodols, tad tas īpaši gatavojas uzsākt gdb ko meklē, ka kodols failu. Un tu saki buggy1 līdzekļi gdb zina, ka galvenais fails nāk no buggy1 programmas. Tātad gdb buggy1 kodols būs nekavējoties jāpārtrauc mums kur programma notika pārtraukt. Mēs redzam šeit programma beidzās ar 11 signālu, segmentācija defektu. Mēs gadās redzēt līniju montāžu, kas, iespējams, nav ļoti noderīga. Bet, ja jūs tipa BT vai Izcelsme, kas būs funkcija kas dod mums sarakstu ar mūsu pašreizējo kaudze rāmjiem. Tā Izcelsme. Izskatās, ka mēs tikai divi kaudze rāmji. Pirmais ir mūsu galvenais kaudze rāmi, un otrais ir kaudze rāmis šai funkcijai, ka mēs gadās būt, kas izskatās, ka mums ir tikai montāžas kodu. Tāpēc iesim atpakaļ uz mūsu galveno funkciju, un to darīt, mēs varam darīt rāmi 1, un es domāju, ka mēs varam arī darīt leju, bet es gandrīz nekad darīt leju - vai uz augšu. Yeah. Augšu un uz leju. Up parādīs jums uz augšu vienu kaudze rāmi, noteikti parādīs jums uz leju kaudze rāmi. Man ir tendence nekad izmantot. Es tikai konkrēti pateikt rāmi 1, kas ir doties uz rāmja nosaukumu 1. 1 kadrs ir gatavojas celt mūs galvenajā kaudze rāmi, un tas saka šeit līniju kodu mēs gadās būt. Ja mēs vēlējāmies vēl pāris koda rindiņas, mēs varam teikt sarakstu, un kas notiek, lai dotu mums visas līnijas koda ap to. Līnija mēs segfaulted pie bija 6: ja (strcmp ("CS50 klintis", argv [1]) == 0). Ja tas nav skaidrs vēl, jūs varat saņemt to tieši no šejienes, vienkārši domāju, kāpēc tā segfaulted. Bet mēs varam ņemt to vienu soli tālāk un saka, "Kāpēc būtu argv [1] segfault?" Let 's drukas argv [1], un izskatās, ka tas ir 0x0, kas ir null rādītājs. Mēs strcmping CS50 akmeņiem un Null, un lai notiek, lai segfault. Un kāpēc ir argv [1] Null? [Students] Jo mums nedeva nekādām komandrindas argumentus. Yeah. Mēs neesam tai būtu iespējams komandrindas argumentus. Tāpēc ./buggy1 ir tikai nāksies argv [0] būs ./buggy1. Tas nav gatavojas būt ARGV [1], lai dodas uz segfault. Bet, ja tā vietā, es tikai CS50, tas gatavojas teikt Jūs saņemsiet D jo tas, kas tas ir paredzēts darīt. Aplūkojot buggy1.c, tas ir paredzēts, lai drukātu "Jūs saņemsiet D" - Ja argv [1] nav "CS50 klintis", "Jūs saņemsiet D", kas cits "Jums!" Tātad, ja mēs gribam, mums ir nepieciešams šis lai salīdzinātu kā taisnība, kas nozīmē, ka to var salīdzināt ar 0. Tātad argv [1] jābūt "CS50 klintis". Ja jūs vēlaties darīt, ka uz komandrindas, jums ir nepieciešams izmantot \ izvairīties telpu. Tātad CS50 \ ieži un jūs iegūsiet A! Ja jums nav darīt to slīpsvītru, kāpēc tas nedarbojas? [Students] Tas ir divas dažādas argumentus. >> Jā. Argv [1] būs CS50, un argv [2] būs klintis. Labi. Tagad ./buggy2 gatavojas segfault vēlreiz. Tā vietā, atverot to ar savu galveno failu, mēs vienkārši atvērt buggy2 tieši, tā buggy2 gdb. Tagad, ja mēs vienkārši palaist savu programmu, tad tas būs teikt programma saņēma signālu SIGSEGV, kas ir segfault signālu, un tas ir, ja tas noticis, lai notikt. Skatoties uz mūsu Izcelsme, mēs redzam, ka mēs bijām funkciju oh_no, ko sauc par funkciju skaists, ko sauc par funkciju Binky, ko sauc par galveno. Mēs varam redzēt arī argumentus, lai šo funkciju. Arguments, lai skaists un Binky bija 1. Ja mēs saraksts funkciju oh_no, mēs redzam, ka oh_no ir tikai dara char ** s = null; * S = "bums"; Kāpēc tas neizdodas? [Students] Jūs nevarat dereference Null rādītāju? >> Jā. Tas ir vienkārši sakot s ir NULL, neatkarīgi, ja tas notiek, ir char **, kas, atkarībā no tā, kā jūs interpretēt to, tas varētu būt rādītājs, lai rādītāju uz virknes vai masīvs stīgas. Tas s ir NULL, tāpēc * s dereferencing Null rādītāju, un tā tas būs crash. Tas ir viens no ātrākajiem veidiem, kā jūs varat iespējams segfault. Tas ir tikai deklarējot null rādītāju un uzreiz segfaulting. Tas ko oh_no dara. Ja mēs ejam uz augšu vienu kadru, tad mēs spēsim nokļūt funkciju sauc oh_no. Man vajag to darīt uz leju. Ja jums nav ievadīt komandu, un jūs vienkārši hit Enter vēlreiz, tas būs tikai atkārtot iepriekšējo komandu, kuru vadīja. Mēs esam 1 rāmī. Uzskaitot šī rāmja, mēs redzam šeit ir mūsu funkcija. Jūs varat hit sarakstu atkal, vai jūs varat darīt sarakstu 20 un tas saraksts vairāk. Funkcija skaists saka, ja man ir 1, tad dodieties uz oh_no funkciju, cits iet uz slinky funkciju. Un mēs zinām, i ir 1, jo mēs gadās redzēt šeit kas skaists sauca ar argumentu 1. Vai jūs varat vienkārši izdrukāt i un tā teikt man ir 1. Mēs šobrīd skaists, un, ja mēs iet uz augšu citu rāmi, mēs zinām mēs galu galā Binky. Augšu. Tagad mēs esam Binky. Uzskaitot šo funkciju - saraksts, no pirms pusgada samazināt man off - tas sākās pie kā, ja es ir 0, tad mēs ejam, lai izsauktu to oh_no, cits zvana skaists. Mēs zinām man bija 1, tā to sauc skaists. Un tagad mēs esam atpakaļ galvenais, un galvenais ir tikai būs int i = rand ()% 3; Tas ir tikai gatavojas sniegt jums izlases numuru, kas ir vai nu 0, 1, 2 vai. Tas notiek, lai izsauktu Binky ar šo numuru, un tas atgriezīsies 0. Meklē tas, tikai ejot caur programmu manuāli bez rādīt to nekavējoties, Jūs noteikt lūzuma punkts pamatdarbā, kas nozīmē, ka tad, kad mēs palaist programmu jūsu programma darbojas līdz tas hits lūzuma punkts. Tātad darbojas programma, tas darbosies, un tad tas būs hit galveno funkciju un pārtraukt darboties. Tagad mēs esam iekšā galvenais, un soli vai blakus gatavojas mūs uz nākamo līniju kodu. Jūs varat izdarīt soli vai nākamo. Hitting nākamais, tagad man ir iestatīts uz rand ()% 3, lai mēs varētu drukāt vērtību i, un tā teikt man ir 1. Tagad tas nav jautājums, vai mēs izmantojam nākamo vai soli. Es domāju, tas vienaldzīgs no iepriekšējā, taču mēs vēlamies izmantot nākamo. Ja mēs izmantojam soli, mēs soli uz funkciju, kas nozīmē apskatīt faktisko lieta ka notiek iekšpusē Binky. Ja mēs izmantojam nākamo, tad tas nozīmē iet pa funkciju un dodieties uz nākamo rindiņu kodu mūsu galvenā funkcija. Tepat šajā līnijā, es biju kur tā teica rand ()% 3; ja man soli, tas varētu doties uz īstenošanas randu un apskatīt to, kas tur notiek, un es varētu soli pa randu funkciju. Bet es vienalga par randu funkciju. Es tikai gribu, lai pārietu uz nākamo līniju koda galvenais, lai varu izmantot nākamo. Bet tagad man rūp Binky funkciju, tāpēc es gribu, lai soli kas. Tagad es esmu Binky. Pirmā līnija koda gatavojas teikt, ja (i == 0), es soli, mēs redzam, mēs galu galā pie skaists. Ja mēs saraksts lietas, mēs redzam, ka tas pārbaudīts ir i = 0. Man nav vienāds ar 0, tāpēc devās uz citu nosacījumu, kas gatavojas aicināt Dinky (i). Jūs varētu saņemt sajaukt. Ja jūs paskatieties šo līniju tieši, jūs varētu domāt, ja (i == 0), labi, tad es spēra soli, un tagad es esmu pie Dinky (i), Jūs varētu domāt, ka ir nozīmē i = 0 vai kaut. Nē tikai nozīmē, ka tā zina, tā var pielipt tieši uz līnijas Dinky (i). Jo man nav 0, nākamais solis nav gatavojas pārtraukt pie cits. Cits nav līnija tas gatavojas apstāties pie. Tas ir tikai gatavojas doties uz nākamo līniju tā var reāli izpildīt, kas ir skaists (i). Pastiprināšanu Dinky (i), mēs redzam, ja (i == 1). Mēs zinām i = 1, tad, kad mēs soli, mēs zinām, mēs ejam, lai galu galā oh_no jo es = 1 izsauc funkciju oh_no, ko jūs varat soli, kas gatavojas noteikt char ** s = uz NULL un uzreiz "bums". Un tad faktiski meklē īstenošanas buggy2, Tas, es ir tikai kļūst izlases numuru - 0, 1, 2 vai - zvanot Binky, kas, ja es ir 0 tas aicina oh_no, cits tā aicina skaists, kas nāk šeit. Ja es ir 1, zvans oh_no, cits zvana Slinky, kas nāk šeit, ja es ir 2, zvanīt oh_no. Man nav pat domāju, ka ir veids, - Vai kāds redzētu veids, kā padarīt šo programmu, kas nav segfault? Jo ja es esmu trūkst kaut ko, ja es ir 0, jūs uzreiz segfault, arī jūs dodaties uz funkciju, kas, ja es ir 1 jums segfault, cits jums iet līdz funkcijai, kur, ja i ir 2 jums segfault. Līdz ar to nav svarīgi, ko jūs darāt, jūs segfault. Es domāju viens no veidiem, nosakot, ka būtu nevis darīt char ** s = null, Jūs varētu malloc vietu šajā virknē. Mēs varētu darīt malloc (sizeof) - sizeof ko? [Students] (char) * 5? >> Vai tas šķiet labi? Es esmu pieņemot, ka tas darbosies, ja es tiešām skrēja, bet tas nav tas, ko es esmu meklē. Paskaties veida s. Pieņemsim pievienot int *, lai int * x. Es varētu darīt malloc (sizeof (int)). Vai, ja es gribēju masīvs 5, es varētu darīt (sizeof (int) * 5); Ko darīt, ja man ir int **? Ko es malloc? [Students] lielums rādītāja. >> Jā. (Sizeof (int *)); Pats uz leju šeit. Es gribu (sizeof (char *)); Tas ir gatavojas piešķirt vietu rādītāja, kas norāda uz "bums". Man nav nepieciešams piešķirt telpu "bums" pati jo tas ir būtībā līdzvērtīgs tam, ko es teicu iepriekš char * x = "bums". "Bums" jau eksistē. Tas notiek ar pastāvēt tikai lasīšanas reģiona atmiņas. Bet tas jau pastāv, kas nozīmē šo koda rindu, ja s ir char **, tad * s ir char * un jūs nosakot šo char *, lai norādītu uz "bums". Ja es gribēju, lai kopētu "bums" uz s, tad es būtu nepieciešams, lai sadalītu telpu s. Es darīšu * s = malloc (sizeof (char) * 5); Kāpēc 5? Kāpēc ne 4? Tā izskatās "bums" ir 4 zīmes. >> [Students] null raksturs. Yeah. Visas jūsu stīgas būs nepieciešams null raksturs. Tagad es varu darīt kaut ko līdzīgu strcat - Kāda ir kopēšanas virkni funkciju? [Students] cpy? >> Strcpy. Vīrietis strcpy. Tātad strcpy vai strncpy. strncpy ir mazliet drošāk, jo jūs var precīzi norādīt, cik rakstzīmes, bet šeit tas nav svarīgi, jo mēs zinām. Tik strcpy un meklēt argumentus. Pirmais arguments ir mūsu galamērķis. Otrs arguments ir mūsu avots. Mēs ejam, lai kopētu mūsu mērķa * s rādītājs "bums". Kāpēc jūs varētu vēlēties to darīt ar strcpy nevis tikai to, ko mums bija pirms gada * s = "bums"? Ir iemesls, jūs varētu vēlēties to darīt, bet kas tas ir iemesls? [Students] Ja jūs vēlaties kaut ko mainīt "bums". >> Jā. Tagad es varu darīt kaut ko līdzīgu s [0] = "X"; jo s norāda uz kaudze un šī vieta uz kaudzes, ka s ir vērsta uz ir rādītājs uz lielāku vietu uz kaudzes, kas tiek glabāta "bums". Tātad šis "bums" kopija tiek saglabāta kaudzē. Ir tehniski divos eksemplāros "bums" mūsu programmā. Tur pirmais, kas ir tikai dota šī "bums" stīgu konstante, un otro kopiju "bums", strcpy radīja kopiju "bums". Bet par "bums" kopija tiek saglabāta uz kaudzes, un kaudze jūs esat brīvi mainīt. Kaudze ir tikai lasāma, lai tas nozīmē, ka s [0] gatavojas ļauj mainīt vērtību "bums". Tas notiek, lai jums mainīt šos simbolus. Jautājumi? Labi. Pārvietojas uz buggy3, pieņemsim GDB buggy3. Mēs vienkārši palaist to, un mēs redzam mēs segfault. Ja mēs Izcelsme, ir tikai divas funkcijas. Ja mēs ejam uz augšu mūsu galvenā funkcija, mēs redzam, ka mēs segfaulted šajā līnijā. Tik vienkārši apskatot šo līniju, uz (int līnija = 0; fgets šī stuff nav vienāds null; līnija + +). Mūsu iepriekšējais rāmis tika saukta _IO_fgets. Jūs redzēsiet, ka partija ar iebūvētu C funkciju, ka tad, kad jūs saņemsiet segfault, būs patiesi mistisks funkcijas vārdus Tāpat kā šī _IO_fgets. Bet kas notiek, lai ir saistīti ar šo fgets aicinājumu. Kaut kur iekšā šeit, mēs segfaulting. Ja mēs skatāmies uz argumentiem, lai fgets, mēs varam drukāt buferis. Pieņemsim drukāt kā - Ak, nē. Drukas nav dodas uz darbu tieši tā, kā es gribu to. Apskatīsim faktisko programmu. Buferis ir raksturs masīvs. Tas ir raksturs masīvs 128 zīmēm. Tātad, kad es saku drukas buferi, tas notiek, lai drukātu šos 128 rakstzīmēm, ko es domāju, ir, kas ir gaidāms. Ko es meklēju ir drukāt adresi bufera, bet tas nav īsti man pateikt daudz. Tātad, ja es notikt teikt šeit x buferis, tā rāda man 0xbffff090, kas, ja jūs atceraties no agrāk vai kādā brīdī, Oxbffff mēdz būt kaudze ish reģionā. Kaudze tendence sākt kaut nedaudz zem 0xc000. Tikai redzot šo adresi, es zinu, ka buferis notiek uz skursteņa. Restartēt savu programmu, palaist, uz augšu, bufera mēs redzējām, bija šo rakstzīmju secību ka ir diezgan daudz bezjēdzīgi. Tad drukāšanas failu, ko tas fails izskatās? [Students] Null. >> Jā. Fails ir tipa fails *, tāpēc tas ir rādītājs, un šī rādītāja vērtība ir nulle. Tāpēc fgets gatavojas, lai mēģinātu lasīt no šī rādītāja netiešā veidā, bet, lai piekļūtu šo rādītāju, tas ir dereference to. Vai, lai piekļūtu to, ko tā būtu vērsta uz, tā dereferences IT. Tātad tas ir dereferencing Null rādītāju un tā segmentācijas kļūdas. Es varētu būt atsākās to tur. Ja mēs pārkāpjam mūsu galvenais punkts un palaist, pirmajā rindā kods ir char * filename = "nonexistent.txt"; Ka vajadzētu dot diezgan liels mājienu par to, kāpēc šī programma neizdodas. Ierakstot blakus nes mani uz nākamo rindiņu, kur es atvērt šo failu, un tad es uzreiz nokļūt mūsu līnijā, kur reiz es hit nākamo, tas dodas uz segfault. Vai kāds vēlas mest ārā iemesls, kāpēc mēs varētu segfaulting? [Students] Fails nepastāv. >> Jā. Tas ir vajadzētu būt mājiens ka ikreiz, kad jūs atvērt failu, jums ir nepieciešams, lai pārbaudītu, ka fails tiešām pastāv. Tātad šeit, "nonexistent.txt"; Kad mēs fopen filename par lasījumā, mēs pēc tam jāpasaka ja (fails == NULL) un saka printf ("fails neeksistē!" vai - vēl labāk - filename), atgriešanās 1; Tāpēc tagad mēs pārbaudām, vai tas ir NULL Pirms faktiski turpina un mēģina nolasīt no šī faila. Mēs varam pārtaisīt to tikai, lai redzētu, ka šis darbi. Es paredzēts iekļaut jaunu līniju. Tāpēc tagad nonexistent.txt neeksistē. Jums vienmēr vajadzētu pārbaudīt šāda veida lieta. Jums vienmēr vajadzētu pārbaudīt, lai redzētu, vai fopen atgriež null. Jums vienmēr vajadzētu pārbaudīt, lai pārliecinātos, ka malloc neatgriežas null, vai arī jūs segfault. Tagad buggy4.c. Darboties. Es esmu guessing tas gaida ieejas vai iespējams bezgalīgs looping. Jā, tas ir bezgalīgs looping. Tā buggy4. Izskatās, ka mēs esam bezgalīgs looping. Mēs varam pārtraukumu galvenais, palaist mūsu programmu. Gdb, kamēr saīsinājums jūs izmantojat ir nepārprotams vai īpašas saīsinājumi, ko tie sniedz jums, tad jūs varat izmantot n izmantot nākamo vietā, lai tipa no nākamās visu ceļu. Un tagad, ka es esmu hit n reizi, es varu tikai hit Enter, lai saglabātu notiek nākamo tā vietā, lai hit n Enter, n Enter, n Enter. Izskatās, ka es esmu sava veida cilpa, kas ir kurā masīvs [i] uz 0. Izskatās, es nekad izkļūt no šī cilpa. Ja es drukāt i, tāpēc es ir 2, tad es iešu nākamo. Es izdrukāt es, es ir 3, tad es iešu nākamo. Es izdrukāt i un i ir 3. Nākamais, drukāt es, es ir 4. Patiesībā, drukas sizeof (masīvs), tāpēc no masīva izmērs ir 20. Bet izskatās, ka tur ir dažas īpašas gdb komanda dodas līdz kaut kas notiek. Tas ir tāpat kā nosakot nosacījums par vērtību mainīgā. Bet es neatceros, kas tas ir. Tātad, ja mēs tur notiek - Ko jūs sakāt? Ko jūs audzināt? [Students] Vai parādīt es pievienot - >> jā. Tāpēc displejs i var palīdzēt. Ja mēs vienkārši parādīt i, tas būs likts šeit kāda no i vērtība ir tāpēc man nav to izdrukāt katru reizi. Ja mēs tikai glabāt iet blakus, mēs redzam 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5. Kaut kas notiek briesmīgi nepareizi, un es tiek reset uz 0. Aplūkojot buggy4.c, mēs redzam visu, kas notiek, ir int masīvs [5]; (i = 0, i <= sizeof (masīvs), i + +) masīvs [i] = 0; Ko mēs redzam, ka ir nepareizi šeit? Kā mājienu, kad es to gdb buggy4 - pieņemsim pauze galvenais, palaist - Man drukas sizeof (masīvs), tikai lai redzētu, kas nosacījums ir, ja es būtu beidzot izlauzties. Kur es esmu? Vai es palaist? Man nav deklarējis vēl. Tātad izdrukāt sizeof (masīvs), un tas ir 20, kas gaidāms jo mans masīvs ir 5 lieluma un tas ir no 5 integers, tāpēc visa lieta ir 5 * sizeof (int) baiti, ja sizeof (int) mēdz būt 4. Tātad sizeof (masīvs) ir 20. Kas būtu tas būtu? [Students] dalīts ar sizeof (int). >> Jā, / sizeof (int). Izskatās, ka tur ir vēl problēma šeit. Es domāju, ka tas būtu vienkārši < jo tas ir diezgan daudz vienmēr > [Bowden] Jā. Kad mēs ejam tālāk beigās mūsu masīvs, kaut ka telpa, ka mēs primāri ir svarīgas vērtības i. Un tāpēc, ja mēs skatāmies uz buggy4, salauzt galvenais, skrien, pieņemsim drukāt adresi i. Izskatās, ka tas ir bffff124. Tagad drukāt adresi masīva [0]. 110. Kas par [1]? 114. [2], 118. 11c, 120. masīvs [5] ir bfff124. Tāpēc masīvs [5] ir tāda pati adrese kā man, kas nozīmē, ka masīva [5] ir i. Ja viņi ir viena adrese, tie ir tas pats. Tātad, kad mēs, kas masīvu [5] uz 0, mēs kurā es uz 0. Un, ja jūs domājat par šo ziņā kaudze, int i ir deklarēta pirmais, kas nozīmē, es izpaužas dažas vietas uz skursteņa. Tad masīvs [5] tiek piešķirta, lai tad 20 baiti tiek piešķirti uz skursteņa. Tāpēc es izpaužas piešķir vispirms, tad šie 20 baiti get piešķirts. Tāpēc es notiek tieši pirms masīvs, un tāpēc, ka tā, tāpat kā es teicu pagājušajā nedēļā, kad tehniski kaudze aug uz leju, kad tu indekss masīvs, mēs garantēta ka 0. pozīciju masīvā vienmēr notiek pirms pirmās pozīcijas masīva. Tas ir veids, kā es vērsa to pagājušajā nedēļā. Ievērojiet, ka apakšā mums ir adrese 0 un augšpusē mums ir adrese Max. Kaudze vienmēr pieaug leju. Teiksim mēs piešķirt i. Mēs piešķirt skaitlim i, kas nozīmē, pieņemsim tikai teikt, šeit skaitlim es izpaužas piešķirts. Tad mēs piešķirt mūsu klāstu 5 integers, kas nozīmē, ka zem ka, jo kaudze aug uz leju, šie 5 skaitļu get piešķirts. Bet tāpēc, ka kā bloki strādā, mēs esam garantēta ka pirmo pozīciju masīvā vienmēr ir ņemti mazāk nekā otrajā lieta masīvā. Tāpēc masīvs pozīcija 0 vienmēr ir jānotiek vispirms atmiņā, tā masīvs pozīcija 1 ir jānotiek pēc tam un masīvs pozīcija 2 ir noticis pēc tam, kas nozīmē, ka masīva pozīcija 0 notiktu kaut kur šeit lejā, masīvs stāvoklis 1 notiktu augstāk jo pārvietojas uz augšu nozīmē augstāku adreses jo maksimālais adrese ir šeit. Tāpēc masīvs [0] noteikti šeit, masīvs [1] šeit, masīvs [2] šeit, masīvs [3] šeit. Paziņojums, kā pirms mēs piešķirts skaitlis es visu ceļu augšup šeit, kā mēs virzāmies tālāk un tālāk mūsu masīvs, mēs kļūst tuvāk un tuvāk mūsu skaitlim i. Tas tikai tā notiek, ka masīvu [5], kas ir viena pozīcija ārpus mūsu masīvs, ir tieši tur, kur skaitlim es notika piešķīrums. Tātad tas ir punkts, kur mēs gadās būt hitting vietu uz skursteņa kas tika piešķirti skaitlim i, un mēs esam nosakot, ka uz 0. Tas ir kā tas darbojas. Jautājumi? Yeah. [Students] Nekad prātā. Labi. [Students] Kā jūs izvairītos šos veida kļūdas? Šie veida kļūdas? Neizmantojiet C kā savu programmēšanas valodu. Lietot valodu, kas ir masīva robežas pārbaudes. Kamēr jūs uzmanīgi, jums ir nepieciešams, lai izvairītos no vēršanās pagātnē jūsu masīvs robežas. [Students] Tātad šeit, kad mēs devāmies agrāk par jūsu masīvs robežas - [Bowden] Tas ir, ja lietas sāk iet greizi. >> [Students] Ak, labi. Kamēr jūs uzturēšanās laikā atmiņā atvēlēts jūsu masīvs, viss ir kārtībā. Bet C nav nekādu kļūdu pārbaudi. Ja man masīvs [1000], tas labprāt vienkārši mainīt arī notiktu - Tā iet uz sākuma masīvs, tad tas iet 1000 pozīcijas pēc un nosaka to uz 0. Tas nav jādara visas pārbaudes ka ak, tas nav reāli ir 1000 lietas tajā. 1000 ir veids, kā tikai to, kas man būtu mainās, bet Java vai kaut ko jūs saņemsiet masīvs no robežas indeksa vai indekss no robežas izņēmuma. Tieši tāpēc no augstāka līmeņa valodu daudz ir šīs lietas kur, ja jūs iet ārpus masīva robežām, jums neizdodas lai jūs nevarat mainīt lietas no zem jums un tad lietas iet daudz sliktāk nekā tikai iegūt izņēmumu saprotams, ka jums gāja pēc projekta beigām masīva. [Students] Un tā būtu mēs esam tikko mainīts <= tikai > [Bowden] Jā. Tas būtu > [Students] labi. Vēl jautājumi? Labi. [Students] Man ir jautājums. >> Jā. [Students] Kas ir faktiskais masīvs mainīgā? [Bowden] Tāpat kā to ir masīvs? Masīvs pati par sevi ir simbols. Tas ir tikai adrese sākuma 20 baitu ka mēs atsaucēm. Jūs varat domāt par to kā rādītājs, bet tas ir nemainīgs rādītājs. Tiklīdz lietas iegūt apkopota, mainīgais masīvs vairs neeksistē. [Students] Tātad, kā tas atrast izmēru masīva? Lielumu masīvs attiecas uz izmēru šajā blokā, ka simbols attiecas. Kad man kaut kas līdzīgs printf ("% p \ n", masīvs); pieņemsim palaist to. Ko es tikai darīt nepareizi? Bloks "masīvs" paziņoja šeit. Ak, šeit. Šķindēt ir gudrs, un tas notiek ar pamanīt, ka man paziņoja, ka masīvu kā 5 elementiem bet es esmu indeksāciju uz 1000 pozīcijā. To var darīt, jo tie ir tikai konstantes. To var tikai tik tālu, pamanījusi, ka es esmu gatavojas ārpus masīva robežām. Bet paziņojums pirms kad mums bija man būt nepareizi, tas nav iespējams noteikt, cik daudz vērtības es varētu uzņemties, tāpēc tas nevar noteikt, ka man bija iet pēc projekta beigām masīva. Tas ir tikai šķindēt ir gudrs. Bet tagad darīt buggy4. Tātad, ko vēl es daru nepareizi? Netieši atzīstot bibliotēkas funkcija "printf". Es esmu gatavojas vēlas # ietvert . Labi. Tagad darbojas buggy4. Drukāšanas vērtību masīva piemēram, I did šeit, drukājot to kā rādītājs izdrukas kaut kas izskatās šādi - bfb8805c - kas ir daži adrese kas ir ar kaudze ish reģionā. Masīvs pati ir kā rādītājs, bet tas nav faktiskā rādītājs, jo regulāri rādītāju mēs varam mainīt. Masīvs ir tikai daži nemainīgs. Tās 20 bloki atmiņas sākas pēc adreses 0xbfb8805c. Tātad bfb8805c caur šo adresi +20--vai es domāju -20 - viss no atmiņas piešķirti šī masīva. Masīvs, mainīgais pats netiek saglabāta jebkur. Kad esat apkopojot, kompilators - roku vilnis pie tā - bet kompilators tikai izmantot, ja tā zina masīvs būt. Tā zina, kur tas masīvs sākas, un tā tas vienmēr var vienkārši darīt lietas saistībā ar kompensācijām no šī sākuma. Tas nav nepieciešams mainīgo pati pārstāvēt masīvs. Bet, kad man kaut kas līdzīgs int * p = bloku; tagad p ir rādītājs, kas norāda uz šo masīvs, un tagad p tiešām eksistē uz skursteņa. Es esmu brīvi mainīt p. Es varu darīt p = malloc. Tātad tas sākotnēji norādīja uz masīvu, tagad tas norāda uz kādu vietu uz kaudzes. Es nevaru darīt masīva = malloc. Ja šķindēt ir gudrs, tas būs bļaut uz mani tiesības pie nūja. Patiesībā, es esmu diezgan pārliecināts, ka LSP varētu darīt pārāk. Tāpēc masīvs tipa "int [5]" nav nododamas. Jūs nevarat kaut ko masīva tipam jo masīvs ir tikai nemainīgs. Tas ir simbols, kas atsauces šie 20 baiti. Es nevaru mainīt. [Students] Un kur ir masīva izmēru uzglabāti? [Bowden] Tas nav uzglabāt jebkur. Tas ir tad, kad tas ir apkopojot. Tātad, kur ir no masīva izmērs uzglabāti? Jūs varat izmantot tikai sizeof (masīvs) iekšpusē funkciju ka masīvs ir deklarējusi. Tātad, ja man dažas funkcijas, foo, un man (int masīvs []) printf ("% d \ n", sizeof (masīvs)); un tad uz leju šeit es aicinu foo (masīvs); iekšpuses šo funkciju - pieņemsim palaist to. Tas ir šķindēt to gudrs vēlreiz. Tas stāsta man, ka sizeof uz masīvu funkcijas parametru atgriezīsies lielumu "int *". Tas būtu kļūda, ja tas nav tas, ko es gribēju, lai notikt. Pieņemsim faktiski izslēgt Werror. Brīdinājuma. Brīdinājumi ir labi. Tas joprojām apkopo kamēr tas ir brīdinājums. . / A.out gatavojas izdrukāt 4. Brīdinājuma kas tika radīts ir skaidrs rādītājs, kas nogāja greizi. Šī int masīvs ir tikai gatavojas, lai izdrukātu sizeof (int *). Pat ja man masīvs [5] šeit, tas joprojām tikai gatavojas drukāt sizeof (int *). Tā tiklīdz jūs iet to funkciju, atšķirība starp masīvu un norādes ir neeksistējošā. Tas notiek, ir masīvs, kas tika atzīts par steku, bet tiklīdz kā mums iet šo vērtību, kas 0xbf blah, blah, blah par šo funkciju, tad šis rādītājs norāda uz šo masīvs uz skursteņa. Tātad tas nozīmē, ka sizeof piemērojams tikai funkcijas, ka masīva tika atzīta, kas nozīmē, ka tad, kad jums ir apkopot šo funkciju, kad šķindēt iet cauri šo funkciju, tas redz masīvs ir int masīvs 5 lieluma. Tātad, tad tas redz sizeof (masīvs). Nu, tas ir 20. Tas ir tiešām kā sizeof būtībā strādā gandrīz visos gadījumos. Sizeof nav funkcija, tas ir operators. Jums nav izsauktu sizeof funkciju. Sizeof (int), kompilators būs tikai tulkot, ka līdz 4. Sanāca tā? Labi. [Students] Tātad, kāda ir starp sizeof (masīvs) starpība galvenais un foo? Tas ir tāpēc, ka mēs esam sakot sizeof (masīvs), kas ir tipa int *, tā kā masīvs noteikti šeit nav tipa int *, tas int masīvu. [Students] Tātad, ja jums bija parametru masīvā [], nevis int * masīvs, tas tas nozīmē, ka jūs varētu mainīt masīva, jo tagad tas ir rādītājs? [Bowden] Tāpat kā šī? >> [Students] Jā. Vai jūs varat nomainīt masīvs ietvaros funkciju tagad? [Bowden] Jūs varētu mainīt masīva abos gadījumos. Abos šajos gadījumos jums ir tiesības brīvi teikt masīvs [4] = 0. [Students] Bet jūs varat veikt masīvu punktu, lai kaut kas cits? [Bowden] Ak. Yeah. Jebkurā gadījumā - >> [students] Jā. [Bowden] starp masīvs [] un int * masīvs atšķirība, nav neviens. Jūs varat arī iegūt kādu daudzdimensiju masīvu šeit kādu ērtu sintaksi, bet tas joprojām tikai rādītājs. Tas nozīmē, ka es esmu brīvs darīt masīvs = malloc (sizeof (int)) un tagad norāda kaut kur citur. Bet tieši tāpat kā tas darbojas uz visiem laikiem, un vienmēr, mainot šo masīvu, padarot to norāda uz kaut ko citu nemaina šo masīvu noteikti šeit, jo tas ir kopija argumentu, tas nav rādītājs, lai šo argumentu. Un patiesībā, tāpat kā vairāk norādi, ka tas ir tieši tas pats - mēs jau redzējām to, ko drukāšanas masīvs izdrukas - Ko darīt, ja mēs drukāt masīva adresi vai adresi masīva adresi uz kādu no tiem? Pieņemsim ignorēt šo vienu. Labi. Tas ir labi. Tas tagad darbojas. / A.out. Drukāšanas masīvs, tad izdrukāt adresi masīva, ir tas pats. Masīvs vienkārši neeksistē. Tā zina, kad jūs drukāšanas masīvs, drukājat simbolu, attiecas uz tiem 20 baiti. Drukāšanas adresi masīvs, labi, masīvs neeksistē. Tas nav adreses, tāpēc tas tikai izdrukas adresi šiem 20 baiti. Tiklīdz jūs sastādīt leju, tāpat kā savu apkopojusi buggy4 / a.out., masīvs ir neeksistējošā. Norādes eksistē. Masīvi nav. No atmiņas bloki pārstāv masīvs joprojām pastāv, bet mainīgo masīvs un mainīgie šāda veida nav. Tie ir, piemēram, galvenās atšķirības starp masīvu un norādes tiek tiklīdz jūs veicat funkcija zvanus, nav atšķirības. Bet iekšpusē funkciju, ka masīva pati deklarē, sizeof darbojas atšķirīgi jo jūs drukāšanas lielumu, nevis no lieluma veida blokiem, un jūs nevarat mainīt to, jo tas ir simbols. Drukāšanas lieta un adresi lieta drukā to pašu. Un tas ir diezgan daudz to. [Students] Vai jūs teiktu, ka vēl vienu reizi? Es varētu būt kaut ko palaiduši garām. Drukāšanas masīvs un adrese masīva izdrukas pats, tā kā, ja jūs drukāt rādītāju salīdzinot adresi rādītāja, viena lieta izdrukas adresi, ko jūs norādot uz, otrs izdrukas adresi rādītāja uz skursteņa. Jūs varat mainīt rādītāju, jūs nevarat mainīt masīva simbolu. Un sizeof rādītājs gatavojas drukāt lielumu šī rādītāja veida. Tātad int * p sizeof (p) gatavojas izdrukāt 4, bet int masīvs [5] Izdrukas sizeof (masīvs) gatavojas drukāt 20. [Students] Tātad int masīvs [5] būs drukāt 20? >> Jā. Tieši tāpēc iekšpusē buggy4 ja to izmanto, lai sizeof (masīvs) Tas darīja i <20, kas ir tas, ko mēs vēlējāmies. Mēs vēlamies i <5. >> [Students] Labi. [Bowden] Un tad, tiklīdz jūs sākat iet pildāmo funkciju, ja mēs int * p = masīvs; iekšpuses šo funkciju, mēs varam būtībā izmantot p un masīvs tādos pašos veidos, izņemot sizeof problēmu un mainīgo problēma. Bet p [0] = 1; ir tāds pats kā sakot masīvs [0] = 1; Un tiklīdz mēs sakām foo (masīvs), vai foo (p); iekšpusē foo funkcija, tas ir tas pats zvans divreiz. Nav atšķirības starp šiem diviem zvaniem atšķirība. Ikvienam labi uz to? Labi. Mums ir 10 minūtes. Mēs cenšamies, lai iegūtu, izmantojot šo Hacker Typer programmu, Šī tīmekļa vietne, kas iznāca pagājušajā gadā, vai kaut ko. Tas ir tikai vajadzēja būt, piemēram, rakstot nejauši un tā izdrukā - Neatkarīgi failu tas notiek, ir ievietots ir tas, ko tas izskatās, ka jūs rakstāt. Tas izskatās kā sava veida operētājsistēmas kodu. Tas, ko mēs vēlamies īstenot. Jums ir jābūt binārā izpildāmā nosaukts hacker_typer kas notiek ar vienu argumentu, failu "hakeru stila." Darbojas izpildāmā būtu skaidrs ekrānu un pēc tam izdrukāt vienu rakstzīmi no ieskaitīts-in failu katru reizi, lietotājs nospiež taustiņu. Tātad, neatkarīgi taustiņu nospiežot, tai vajadzētu mest prom un tā vietā drukāt raksturs no faila kas ir arguments. Es diezgan daudz pateikt, ko lietas mēs spēsim jāzina ir. Bet mēs gribam, lai pārbaudītu termios bibliotēku. Es nekad neesmu izmantojis šo bibliotēku visu manu dzīvi, tāpēc tas ir ļoti minimāla mērķiem. Bet tas būs bibliotēkā, mēs varam izmantot, lai mest prom raksturs jums hit kad jūs rakstāt par standarta collas Tātad hacker_typer.c, un mēs esam gatavojas vēlaties # ietvert . Aplūkojot cilvēks lapā termios - I'm guessing tas ir gala OS vai kaut kas - Es nezinu, kā lai to izlasītu. Aplūkojot to, tas saka, lai iekļautu šos 2 failus, tāpēc mēs darīsim tā. Pirmā lieta, pirmkārt, mēs vēlamies veikt vienu argumentu, kas ir fails mums vajadzētu atvērt. Tātad, ko es gribu darīt? Kā es varu pārbaudīt, lai redzētu man ir viens arguments? [Students] Ja argc vienāds to. >> [Bowden] Jā. Tātad, ja (argc = 2!) Printf ("lietojums:% s [failu atvērt]"). Tāpēc tagad, ja man palaist šo bez piedāvājot otru argumentu - ak, man vajag jaunu līniju - jūs redzēsiet tā saka lietojums: / hacker_typer. un tad otrais arguments būtu failu es vēlos atvērt. Tagad ko man darīt? Es gribu lasīt no šī faila. Kā es varu lasīt no faila? [Students] Atverot tā pirmo reizi. >> Jā. Tā fopen. Kāda fopen izskatās? [Students] attēlu. >> [Bowden] Filename būs argv [1]. [Students] Un tad ko jūs vēlaties darīt ar to, tāpēc - >> [Bowden] Jā. Tātad, ja jums nav atcerēties, jūs varētu vienkārši darīt vīrieti fopen, ja tas būs const char * ceļš, kur ceļš ir filename, const char * režīmā. Ja jūs notikt ne atcerēties, ko režīms ir, tad jūs varat meklēt režīmā. Iekšpusē cilvēks lapas, slīpsvītra raksturs ir tas, ko jūs varat izmantot, lai meklētu lietas. Tāpēc es rakstīt / režīmu, lai meklētu režīmā. N un N ir tas, ko jūs varat izmantot, lai pārvietotos caur meklēšanas spēlēs. Te tā saka arguments režīma norāda uz virkni sākot ar vienu no šādiem sekvences. Tātad r, Atvērt teksta failu lasīšanai. Tas, ko mēs vēlamies darīt. Lasīšanai, un es vēlos, lai saglabātu to. Lieta būs fails *. Tagad to, ko es gribu darīt? Dodiet man otru. Labi. Tagad to, ko es gribu darīt? [Students] Pārbaudiet, vai tas ir NULL. >> [Bowden] Jā. Katru reizi, kad atverat failu, pārliecinieties, ka esat veiksmīgi var atvērt. Tagad es gribu darīt, ka termios sīkumi, kur es gribu, lai vispirms izlasīt manu pašreizējos iestatījumus un saglabāt tos uz kaut ko, tad es vēlos mainīt manus iestatījumus mest prom jebkuru raksturu, kas man tips, un tad es gribu, lai atjauninātu šos iestatījumus. Un tad beigās programmas, es vēlos mainīt atpakaļ uz manu sākotnējo uzstādījumu. Tāpēc struktūrai būs Tipa termios, un es esmu gatavojas vēlas divi no šiem. Pirmais būs mana current_settings, un tad viņi būs mana hacker_settings. Pirmkārt, es esmu gatavojas vēlaties, lai saglabātu manu pašreizējos iestatījumus, tad es esmu gatavojas vēlas atjaunināt hacker_settings, un tad kā beigās manā programmā, es gribu atgriezties pie pašreizējiem iestatījumiem. Tātad taupīšanas pašreizējos iestatījumus, kā tas darbojas, mums cilvēks termios. Mēs redzam, ka mums ir šis int tcsetattr, int tcgetattr. Es iet ar termios struct ar tās rādītājs. Kā tas izskatīsies, ir - I've jau aizmirsuši, ko funkcija sauca. Kopēt un ielīmēt. Tātad tcgetattr, tad es gribu iet uz struct ka es esmu ietaupot informāciju, kas būs current_settings, un pirmais arguments ir fails deskriptors lieta, ko es gribu, lai saglabātu atribūtus. Kāds fails deskriptors ir ir tāpat kā jebkurš reizi atverot failu, tā kļūst failu deskriptoru. Kad es fopen argv [1], tā kļūst failu deskriptoru, kas jums ir norādes ja jūs vēlaties lasīt vai rakstīt uz to. Tas nav failu deskriptors es vēlos izmantot šeit. Ir trīs failu deskriptori jums ir pēc noklusējuma, kas ir standarta, standarta ārā, un standarta kļūda. Pēc noklusējuma, es domāju, ka tas standarts ir 0, standarta out ir 1, un standarta kļūda ir 2. Tātad, ko vēlos mainīt uzstādījumus? Es vēlos mainīt iestatījumus, kad es hit raksturs, Es gribu, lai mest šo raksturu prom, nevis izdrukāt to uz ekrāna. Kas plūsma - standarta, standarta ārā, vai standarta kļūda - reaģē uz lietām, kad es tipa pie klaviatūras? >> [Students] Standarta iekšā >> Yeah. Lai es varētu vai nu darīt 0 vai es varu darīt stdin. Es saņemu current_settings par standarta collas Tagad es gribu, lai atjauninātu šos iestatījumus, tāpēc vispirms es ņemšu iekopēt hacker_settings ko mani current_settings ir. Un kā structs darbs tas būs tikai kopija. Tas kopijas visās jomās, kā jūs varētu gaidīt. Tagad es gribu, lai atjauninātu kādu no jomām. Aplūkojot termios, jums būtu izlasīt daudz šīs tikai, lai redzētu to, ko jūs vēlaties meklēt, bet karogi jūs gatavojas vēlaties meklēt ir atbalss, tāpēc ECHO Echo ievadi rakstzīmes. Vispirms es gribu noteikt - I've jau aizmirsuši, ko lauki ir. Tas ir tas, ko struktūrai izskatās. Tāpēc ievades režīmus es domāju, ka mēs gribam mainīt. Mēs apskatīt risinājums, lai pārliecinātos, ka tas, ko mēs gribam mainīt. Mēs vēlamies mainīt lflag lai novērstu nepieciešams izskatīt visus šos. Mēs vēlamies mainīt vietējo režīmus. Jums būtu izlasīt visu šo lietu, lai saprastu, kur viss pieder ka mēs gribam mainīt. Bet tas ir iekšā vietējo veidos, kur mēs ejam, vēlas to mainīt. Tātad hacker_settings.cc_lmode ir tas, ko tā sauc. c_lflag. Tas ir, ja mēs nokļūt Bitu līmeņa operatoriem. Mēs esam veida no laika, bet mēs iesim cauri to reālu ātri. Tas ir, ja mēs nokļūt Bitu līmeņa operatoriem, kur es domāju, ka es teicu vienu reizi sen, ka ikreiz, kad jūs sākat, kas nodarbojas ar karogiem, Jūs esat būs izmantojot Bitu līmeņa operatoram daudz. Katrs karoga mazliet atbilst sava veida uzvedību. Tātad šeit, šis karogs ir ķekars dažādas lietas, kur visi no tiem nozīmēt kaut ko citu. Bet ko es gribu darīt, ir tikai izslēgt mazliet, kas atbilst ECHO. Tātad, lai ieslēgtu, ka off man & = ¬ ECHO. Patiesībā, es domāju, ka tas ir tāpat kā techo vai kaut ko. Es esmu tikai gatavojas pārbaudīt vēlreiz. Es varu termios to. Tas ir tikai ECHO. ECHO būs viena mazliet. ¬ ECHO gatavojas nozīmē visi biti ir iestatīts uz 1, kas nozīmē, visi karogi ir noteikti patiess izņemot ECHO bit. Līdz beidzot manu vietējo karogus ar to, tas nozīmē visiem karogiem, kas šobrīd noteikti ir taisnība joprojām tiks iestatīts kā patiess. Ja mana ECHO karodziņš ir iestatīts uz patiess, tad tas ir obligāti iestatīts uz False uz ECHO karoga. Tāpēc šo kodu līniju vienkārši izslēdz ECHO karogu. Pārējās rindas kods, es ņemšu tikai kopēt tos interesēs laikā un pēc tam tos izskaidrot. Šķīdumā, viņš teica 0. Tas ir iespējams, labāk skaidri pateikt stdin. Ievērojiet, ka es esmu arī dara ECHO | ICANON šeit. ICANON atsaucas uz kaut ko atsevišķu, kas nozīmē kanonisko režīmā. Kas kanonisko režīms nozīmē ir parasti, kad jūs rakstāt no komandrindas, standarts nav procesa nekas, kamēr jūs hit newline. Tātad, ja jūs GetString, rakstot ķekars lietas, tad jums hit newline. Tas ir, kad tas ir nosūtīts uz standarta collas Tas ir noklusējuma. Kad es izslēgt kanonisko režīmu, tagad katru rakstzīmi, nospiežot ir tas, ko izpaužas apstrādāti, kas parasti ir sava veida slikti, jo tas ir lēns, lai apstrādātu šīs lietas, kas ir iemesls, kāpēc tas ir labi, lai buferis to visu līniju. Bet es gribu katru rakstzīmi jāapstrādā jo es negribu to gaidīt man, lai sasniegtu newline pirms tā apstrādā visus burtus es esmu rakstīt. Tas izslēdz kanonisko režīmā. Šī stuff tikai nozīmē, kad tas faktiski apstrādā rakstzīmes. Tas nozīmē, apstrādāt tos nekavējoties; tiklīdz es esmu ierakstot tos, tos apstrādāt. Un tas ir funkcija, kas atjaunina savus iestatījumus standarta, un TCSA līdzekļiem darīt to tieši tagad. Citas opcijas ir gaidīt, kamēr viss, kas pašlaik ir plūsma tiek apstrādāti. Tas nav īsti jautājums. Tikai tagad mainīt iestatījumus, lai būtu kāds ir pašlaik hacker_typer_settings. Es domāju, es to nosauca hacker_settings, tāpēc pieņemsim to mainīt. Mainīt visu, lai hacker_settings. Tagad beigās mūsu programmu, mēs esam gatavojas vēlaties atgriezties to, kas ir pašlaik iekšā normal_settings, kas gatavojas tikai izskatās & normal_settings. Paziņojums Es neesmu mainījies kāds no maniem normal_settings jo sākotnēji kļūst to. Tad vienkārši mainīt tos atpakaļ, es nodot tos atpakaļ beigās. Tas bija atjauninājums. Labi. Tagad iekšā šeit es ņemšu tikai izskaidrot kodu interesēs laiku. Tas nav tik daudz kodu. Mēs redzam lasām rakstzīmi no faila. Mēs sauc tā f. Tagad jūs varat Vīrietis fgetc, bet kā fgetc iet uz darbu ir tikai tas notiek, lai atgrieztos uz rakstzīmes, tikai lasīt vai EOF, kas atbilst beigām failu vai kādu kļūdas notiek. Mēs looping, turpina lasīt vienu rakstzīmi no lietas materiāliem, kamēr mēs esam palaist no rakstzīmes, lai lasītu. Un, kamēr mēs darām, ka mums jāgaida uz vienu rakstzīmi no standarta collas Katru reizi, rakstot kaut ko pie komandrindas, kas ir lasījumā raksturs no standarta iekšā Tad putchar ir tikai gatavojas nodot CHAR mēs lasīt šeit no failu standarta out. Jūs varat cilvēks putchar, bet tas ir tikai liekot uz standartu ārā, tas drukāšanas ka raksturu. Jūs varētu arī vienkārši darīt printf ("% c", c); pati ideja. Kas gatavojas darīt lielāko daļu no mūsu darba. Pēdējā lieta, mēs esam gatavojas vēlaties darīt, ir tikai fclose mūsu failu. Ja jums nav fclose, ka ir atmiņas noplūde. Mēs vēlamies, lai fclose failu mēs sākotnēji atklāja, un es domāju, ka tas arī viss. Ja mēs, kas, es jau saņēmu problēmas. Pieņemsim redzēt. Ko tas sūdzēties? Paredzams "int", bet arguments ir veids "struct _IO_FILE *". Redzēsim, vai tas darbojas. Atļauta tikai C99. Augh. Labi, padarīt hacker_typer. Tagad mēs iegūtu vairāk noderīgas aprakstus. Līdz ar to izmantot par nedeklarētu identifikators "normal_settings". Man nav to sauc normal_settings. Es to sauca current_settings. Tāpēc pieņemsim mainīt visu to. Tagad viņa arguments. Es ņemšu padara šo 0! Tagad. Labi. . / Hacker_typer cp.c. Es arī nav skaidrs ekrānu sākumā. Bet jūs varat atskatīties uz pēdējo problēmu kopumu, lai redzētu, kā jūs notīrītu ekrānu. Tas ir vienkārši izdrukāt dažas rakstzīmes kamēr tas dara to, ko es gribu darīt. Labi. Un domājot par to, kāpēc tas nepieciešams, lai ir 0 nevis stdin, kas būtu # define 0, tas sūdzas, ka - Pirms kad es teicu, ka tur ir failu deskriptori, bet tad jums ir arī jūsu failu *, fails deskriptors ir tikai viens skaitlis, tā FILE * ir viss stuff ķekars saistīti ar to. Iemesls mums teikt 0 vietā stdin ir tas, ka stdin ir Failu *, kas norāda uz to lieta, kas ir atsauces faila deskriptoru 0. Tātad pat šeit, kad es to fopen (argv [1], es saņemu failu * atpakaļ. Bet kaut kur, ka failu * ir lieta, kas atbilst faila deskriptoru par šo failu. Ja paskatās cilvēks lapā atvērt, tāpēc es domāju, ka jums ir jādara man 3 atvērtā - Nē - Man 2 atvērts - jā. Ja paskatās lapā atvērts, atklāts ir kā zemāka līmeņa fopen, un tas atgriežas faktisko failu deskriptoru. fopen dara ķekars sīkumi uz augšu vaļā, kas tā vietā atgriežoties tikai, ka fails deskriptors atgriež veselu failu * rādītāju iekšā kas ir mūsu mazā failu deskriptors. Tāpēc standarts attiecas uz failu * lieta, tā 0 attiecas uz tikai ar failu deskriptors standartu sevi. Jautājumi? [Smejas] Blew caur to. Labi. Mēs esam darīts. [Smejas] [CS50.TV]