[Powered by Google Translate] [Sehemu ya 5 - Zaidi Starehe] [Rob Bowden - Chuo Kikuu cha Harvard] [Hii ni CS50. - CS50.TV] Kama nilivyosema katika barua pepe yangu, kuna mambo mengi unaweza kutumia nyingine kuliko appliance kwa kweli kufanya seti tatizo. Tunapendekeza ya kufanya hivyo katika appliance sababu tu basi tunaweza kwa urahisi zaidi kukusaidia na tunajua jinsi kila kitu ni kwenda kufanya kazi. Lakini kama mfano mmoja wa ambapo unaweza kufanya mambo kama, kusema, wewe hawana kwa appliance au unataka kazi katika basement Center Sayansi - ambayo kwa kweli wana appliance pia - kama unataka kufanya kazi mahali popote. Mfano mmoja ni umeona / sikia SSH? SSH kimsingi ni kama tu kuungana na kitu. Kweli, sasa hivi mimi nina SSHed katika appliance. Mimi kamwe kazi moja kwa moja katika appliance. Hapa ni appliance, na kama wewe kuangalia chini hapa unaweza kuona hii anwani ya IP. Mimi kamwe kazi katika appliance yenyewe; Mimi daima kuja juu na dirisha iTerm2 dirisha / terminal. Unaweza SSH kwa anwani hiyo IP, ssh jharvard@192.168.129.128. Nakumbuka kwamba idadi urahisi sana kwa sababu ni mfano kama nice. Lakini hilo kuuliza mimi kwa password yangu, na sasa mimi niko katika appliance. Kimsingi, katika hatua hii, kama wewe ni kufungua terminal ndani ya appliance yenyewe, interface hii, hata hivyo ungependa kutumia hiyo, ni sawa kama interface mimi nina kutumia zaidi ya hapa lakini sasa uko SSHed. Huna kwa SSH kwa appliance. Mfano mmoja wa mahali pengine unaweza SSH kwa ni nina uhakika pretty una by default - Oh. Kubwa. Wote wa unapaswa kuwa na akaunti FAS default kwenye seva FAS. Kwa maana mimi, napenda SSH kwa rbowden@nice.fas.harvard.edu. Ni kwenda kuuliza kwamba mara ya kwanza, na wewe kusema ndiyo. Password yangu ni kwenda tu kuwa FAS yangu password. Na hivyo sasa, mimi nina SSHed servrar nzuri, na mimi siwezi kufanya kitu chochote nataka hapa. mengi ya madarasa unaweza kuchukua, kama 124, ni kwenda na wewe upload stuff kwa hapa kwa kweli kuwasilisha tatizo seti yako. Lakini kusema huna upatikanaji wa appliance yako. Basi unaweza kufanya mambo, kama hapa, atasema - Hii ni sehemu yetu ya maswali. Ni kuuliza wewe kufanya hivyo katika appliance. Badala yake mimi itabidi kufanya hivyo kwenye seva. Mimi naenda unzip kwamba. tatizo ni kwenda kuwa kuwa wewe ni kutumika kwa kutumia kitu kama gedit au chochote ndani ya appliance. Wewe hutaenda kuwa na kwamba katika server FAS. Ni wote kwenda tu kuwa hii interface textual. Hivyo unaweza aidha moja, kujaribu kujifunza mhariri Nakala kwamba hawana wana. Wao wana Nano. Nano ni kawaida pretty rahisi kutumia. Unaweza kutumia mishale yako na aina ya kawaida. Basi hiyo ni si ngumu. Kama unataka kupata kweli dhana unaweza kutumia Emacs, ambayo mimi pengine haipaswi kuwa kufunguliwa kwa sababu mimi si hata kujua jinsi ya kuifunga Emacs. Document X, Udhibiti C? Yeah. Au unaweza kutumia VIM, ambayo ni nini mimi kutumia. Na hivyo wale ni chaguzi yako. Kama hutaki kufanya hivyo, unaweza pia, kama ukiangalia manual.cs50.net-- Oh. Juu ya PC, unaweza kutumia SSH putty, ambayo wewe ni kwenda na download tofauti. Mac, unaweza tu na default Terminal matumizi au unaweza kushusha iTerm2, ambayo ni kama Terminal nice, dhana. Kama wewe kwenda manual.cs50.net utaona zilizounganishwa na Notepad + +, ambayo ni nini unaweza kutumia PC. Ni inakuwezesha SFTP kutoka Notepad + +, ambayo kimsingi ni SSH. Nini hii basi wewe kufanya ni kuhariri faili yako ndani ya nchi, na kisha kila unataka kuwaokoa, itakuwa ila kwa nice.fas, ambapo unaweza kisha kukimbia nao. Na sawa juu ya Mac ni kwenda kuwa TextWrangler. Hivyo inakuwezesha kufanya kitu kimoja. Ni inakuwezesha kuhariri faili ndani ya nchi na kuwaokoa nice.fas, ambapo unaweza kisha kukimbia nao. Hivyo kama wewe ni milele kukwama bila appliance, una chaguzi hizi bado kufanya tatizo seti yako. Tatizo moja ni itakuwa kwamba wewe si kwenda kuwa na maktaba CS50 kwa sababu nice.fas haina na default kuwa na kwamba. Unaweza ama download maktaba CS50 - Sidhani mimi haja ya kuwa katika hatua hii. Unaweza ama download maktaba CS50 na nakala yake juu ya nice.fas, au nadhani katika hatua hii sisi si kutumia tena anyway. Au kama sisi kufanya, unaweza kwa muda kuwa badala yake pamoja na utekelezaji wa majukumu katika maktaba CS50 anyway. Ili isiwe kwamba mengi ya kizuizi. Na kwamba ni kwamba. Nitakwenda nyuma appliance sasa, tutaweza kufanya kila kitu katika appliance. Kuangalia sehemu yetu ya maswali, mwanzoni, kama nilivyosema katika barua pepe yangu, sisi kuwa na majadiliano kuhusu moja mfupi walipaswa kukesha. Tuna imetuma Mabomba & na maswali haya matatu. Ambayo mkondo gani kazi kama printf kuandika na default? Hivyo mkondo. Nini ni mkondo? mkondo ni kimsingi kama ni baadhi tu - Si hata chanzo cha 1s na sekunde 0. mkondo ni kuuliza kwa hapa ni kiwango nje. Na hivyo kiwango nje ni mkondo kwamba wakati wewe kuandika hayo, inaonekana kwenye screen. Nje ya kiwango, na mkondo, ina maana wewe andika tu 1s na sekunde 0 kwa hiyo, na mwisho mwingine wa nje ya kiwango tu anayesoma kutoka mkondo huo. Ni kamba tu ya 1s na sekunde 0. Unaweza kuandika kwa mito au unaweza kusoma kutoka katika mikondo kutegemea na nini mkondo kweli ni. wengine wawili default mito ni ya kiwango katika upotofu na kiwango. Darasa katika wakati wowote ni huna GetString, ni kusubiri kwa wewe stuff pembejeo. Hivyo ni kusubiri kwa ajili yenu, ni kweli kusubiri juu ya kiwango katika, ambayo ni kweli nini kupata pale unapoandika kwenye keyboard. Wewe ni kuandika katika kiwango in Kosa la kimsingi ni sawa na nje ya kiwango, lakini ni maalumu katika kwamba wakati magazeti ya hitilafu ya kiwango, wewe ni walidhani tu magazeti ujumbe wa makosa kwa kuwa hivyo unaweza kutofautisha kati ya ujumbe wa mara kwa mara kuchapishwa kwa screen dhidi ya makosa ujumbe kutegemea kama walikwenda kwa kiwango nje au kosa standard. Files pia. Darasa la nje, kiwango katika, na makosa ya hali ni tu maalum ya mito, lakini kwa kweli faili yoyote, wakati wa kufungua faili, inakuwa mkondo ya ka ambapo unaweza kusoma tu kutoka mkondo huo. Wewe, kwa sehemu kubwa, unaweza kufikiria tu ya faili kama mkondo wa bytes. Basi nini mito gani wao kuandika na default? Darasa la nje. Nini tofauti kati ya> na >>? Je mtu yeyote kuangalia video ya zamani? Sawa. > Ni kwenda kuwa jinsi redirect katika files, na >> pia kwenda kwingine pato katika files, lakini ni badala ya kwenda append na faili. Kwa mfano, hebu kusema mimi kutokea kwa kuwa Dict haki hapa, na mambo tu ndani ya Dict ni paka, paka, mbwa, samaki, mbwa. Amri moja kuwa una mstari amri ni paka, ambayo ni kwenda tu na magazeti nini katika faili. Hivyo wakati mimi kusema paka Dict, ni kwenda magazeti paka, paka, mbwa, samaki, mbwa. Hiyo paka wote gani. Hiyo ina maana kwamba ni kuchapishwa kwa kiwango nje paka, paka, mbwa mbwa, samaki,. Kama mimi badala wanataka redirect kwamba faili, naweza kutumia> na REDIRECT kwa chochote faili ni. Mimi nitakuita faili faili. Hivyo sasa kama mimi ls, mimi utaona nina faili mpya iitwayo faili. Na kama mimi kufungua it up, itakuja kuwa na nini hasa paka kuweka katika mstari amri. Hivyo sasa kama mimi kufanya hivyo tena, basi ni kwenda kwingine pato katika faili, na mimi naenda kuwa sawa exact kitu. Basi kitaalam, kabisa overrode nini tulikuwa. Na tutaweza kuona kama mimi kubadili Dict, mimi alichukua nje mbwa. Sasa kama sisi paka Dict katika faili tena, tunakwenda na toleo mpya na mbwa kuondolewa. Hivyo kabisa yanapewa kipaumbele hilo. Badala yake, kama sisi kutumia >>, ni kwenda append faili. Sasa, kufungua faili, tunaona tuna tu kitu kimoja kuchapishwa mara mbili sababu ilikuwa huko mara moja, kisha sisi umeongezewa awali. Hivyo kwamba ni nini> na >> kufanya. Je moja ijayo kuuliza - Haina kuuliza kuhusu hilo. nyingine moja kwamba tuna ni <, ambayo kama> redirects nje ya kiwango, kufanya 2>, hiyo imetuma makosa ya hali. Hivyo kama kitu akaenda makosa ya hali, ingekuwa si kupata kuweka ndani ya txt2. Lakini taarifa kama mimi kufanya 2>, basi ni bado uchapishaji Hello, Rob! kwa mstari amri kwa sababu mimi nina tu imetuma makosa ya hali, mimi nina haielekezi kiwango nje. Kiwango makosa na nje ya kiwango ni tofauti. Kama alitaka kweli kuandika makosa ya hali, basi mimi naweza kubadili hili kuwa fprintf kwa stderr. Hivyo printf, kwa default, prints kwa nje standard. Kama mimi nataka magazeti kwa makosa ya hali manually, basi nina kutumia fprintf na bayana nini nataka magazeti kwa. Kama badala sikuwa stdout fprintf, basi, kwamba kimsingi ni sawa na printf. Lakini kwa kosa fprintf standard. Hivyo sasa, ikiwa mimi redirect hii katika txt2, Hello, Rob! bado kupata kuchapishwa katika mstari amri tangu ni kupata kuchapishwa kwa makosa ya hali na mimi nina tu imetuma kiwango nje. Kama mimi sasa redirect makosa ya hali, sasa hawakuwa kupata kuchapishwa, na txt2 ni kwenda kuwa Hello, Rob! Hivyo sasa, unaweza print yako makosa halisi kwa makosa ya hali na magazeti yako ujumbe wa mara kwa mara nje ya kiwango. Na hivyo wakati wewe kuendesha programu yako, unaweza kukimbia kama /. Hujambo aina hii na 2> hivyo kwamba programu yako ni kwenda kukimbia kwa kawaida, lakini ujumbe wa makosa yoyote kwamba kupata unaweza kuangalia baadaye katika upotofu logi yako, hivyo makosa, na kisha kuangalia baadaye na makosa yako faili itakuwa na makosa yoyote yaliyotokea. Maswali? moja ya mwisho ni bomba, ambayo unaweza kufikiria kama kuchukua kiwango kutoka amri moja na kuifanya ya kiwango katika amri ya pili. mfano hapa ni mwangwi ni mstari amri kitu kwamba ni kwenda tu echo chochote mimi kuweka kama hoja yake. Mimi sitaweza quotes. Echo blah, blah, blah ni kwenda tu na magazeti blah, blah, blah. Kabla ya hapo, mimi nina alisema alikuwa na kuweka ndani ya Rob faili txt sababu naweza tu redirect files txt, badala yake, / kama mimi echo Rob na kisha bomba ndani / hello, ambayo pia kufanya aina moja ya kitu.. Hii ni kuchukua pato la amri hii, echo Rob, na kutumia kama pembejeo kwa /. hello. Unaweza kufikiria kama kwanza redirect echo Rob katika faili na kisha kuyaingiza katika faili. / hujambo kwamba mara tu outputted. Lakini itachukua muda faili nje ya picha. Maswali juu ya hilo? Swali la pili ni kwenda kuhusisha hii. Nini bomba unaweza kutumia ili kupata idadi ya majina ya kipekee katika faili inayoitwa names.txt? amri tunakwenda wanataka kutumia hapa ni ya kipekee, hivyo uniq, na kisha WC. Unaweza kufanya mtu uniq kwa kweli kuangalia nini kwamba gani, na ni kwenda tu kwa chujio mistari karibu vinavyolingana kutoka pembejeo. Na mtu WC ni kwenda magazeti newline, neno, na makosa Byte kwa kila faili. Na moja ya mwisho tunakwenda wanataka kutumia ni aina ya, ambayo ni kwenda tu aina ya mistari ya faili txt. Kama mimi kufanya baadhi ya faili txt, names.txt, na ni Rob, Tommy, Joseph, Tommy, Joseph, RJ, Rob, nini nataka kufanya hapa ni kupata idadi ya majina ya kipekee katika faili hii. Hivyo kile lazima jibu kuwa? >> [Mwanafunzi] 4. >> Yeah. Ni lazima 4 tangu Rob, Tommy, Joseph, RJ ni pekee tu majina katika faili hii. hatua ya kwanza, kama mimi tu kufanya neno juu ya kuhesabu names.txt, hii ni kweli akiniambia kila kitu. Hii ni kweli uchapishaji - basi s kuona, mtu WC - newlines, maneno na kuhesabu Byte. Kama mimi tu huduma ya juu mistari, naweza tu kufanya WC-l names.txt. Basi hiyo ni hatua ya 1. Lakini mimi sitaki names.txt WC-l kwa sababu tu ina names.txt majina yote, na mimi nataka kuchuja wale yoyote yasiyo ya kipekee. Hivyo kama mimi kufanya uniq names.txt, kwamba hana kabisa nipe nini nataka kwa sababu majina duplicated bado kuna. Kwa nini? Kwa nini uniq si kufanya nipendavyo? [Mwanafunzi] marudio si [inaudible] >> Yeah. Kumbuka ukurasa mtu kwa uniq anasema mistari chujio vinavyolingana karibu. Hawako karibu, hivyo itakuwa si kuchuja yao. Kama mimi aina yao ya kwanza, aina names.txt ni kwenda kuweka mistari yote duplicate pamoja. Hivyo sasa ni kwamba aina names.txt. Mimi nina kwenda kutaka kutumia kama pembejeo kwa uniq, ambayo ni | uniq. Anipaye Joseph, RJ, Rob, Tommy, na mimi nataka kuwa matumizi kama pembejeo kwa WC-l, ambayo ni kwenda nipe 4. Kama inavyosema hapa, nini bomba unaweza kutumia? Unaweza kufanya mambo mengi kama vile kutumia mfululizo wa amri ambapo matumizi pato kutoka amri moja kama mchango wa amri ya pili. Unaweza kufanya mambo mengi, mengi ya mambo wajanja. Maswali? Sawa. Hiyo ni kwa ajili ya mabomba na redirection. Sasa tunaenda kwenye mambo halisi, stuff coding. Ndani ya hii PDF, utaona amri hii, na wewe utakuwa unataka kukimbia amri hii katika appliance yako. wget ni amri kwa ajili tu ya kupata kitu kutoka mtandao, kimsingi, hivyo wget na hii URL. Kama wewe akaenda URL hiki katika kivinjari chako, ingekuwa download kwamba faili. Mimi tu clicked juu yake, hivyo ni kupakuliwa faili kwa ajili yangu. Lakini kuandika wget ya kitu ndani ya terminal ni kwenda tu kwa kushusha ni ndani ya terminal yako. Nina section5.zip, na utasikia wanataka unzip section5.zip, ambayo ni kwenda kukupa folder aitwaye section5, ambayo ni kwenda wote wa files tunakwenda kutumia leo ndani yake. Kama faili programu hizi 'majina kupendekeza, wao uko Buggy kidogo, hivyo lengo lako ni kwa takwimu kwa nini kutumia gdb. Je, kila mtu kuwa wao kupakuliwa / kujua jinsi ya kupata yao kupakuliwa katika appliance zao? Sawa. Mbio ./buggy1, itakuwa kusema Mkato kosa (msingi kutupwa), ambayo wakati wowote kupata segfault, ni kitu mbaya. Chini ya mazingira gani unayoipata segfault? [Mwanafunzi] Dereferencing pointer null. >> Yeah. Hivyo kwamba ni mfano mmoja. Dereferencing pointer null utaenda kupata segfault. Nini segfault njia ni wewe ni kugusa kumbukumbu unapaswa kuwa kugusa. Hivyo dereferencing pointer null ni kugusa anuani 0, na kimsingi, kila kompyuta siku hizi wanasema kwamba anuani 0 ni kumbukumbu unapaswa kuwa kugusa. Hivyo ndiyo sababu dereferencing matokeo pointer null katika segfault. Wakati wewe kutokea si initialize pointer, basi ina thamani ya takataka, na hivyo wakati wewe kujaribu dereference hivyo, katika uwezekano wote wewe ni kugusa kumbukumbu kwamba katika katikati ya pa. Kama kutokea kwa kupata bahati na thamani ya takataka kilichotokea kwa uhakika na mahali fulani kwenye stack au kitu, basi wakati wewe dereference kwamba pointer, ambayo wewe si initialized, hakuna kitu kwenda vibaya. Lakini kama ni akizungumzia, kusema, mahali fulani kati ya stack na chungu, au ni akizungumzia tu mahali fulani kwamba haijawahi kutumika kwa mpango wako bado, basi wewe ni kugusa kumbukumbu unapaswa kuwa kugusa na wewe segfault. Wakati kuandika kazi ya kujirudia na recurses mara nyingi sana na stack yenu inakua kubwa mno na collides stack katika mambo kwamba ni lazima kuwa colliding na, wewe ni kugusa kumbukumbu unapaswa kuwa na kugusa, hivyo segfault. Hiyo ni nini segfault ni. Ni sababu hiyo hiyo pia kwamba kama una kamba kama - hebu kwenda nyuma ya mpango uliopita. Katika hello.c-I'm just kwenda kufanya kitu kingine. Char * s = "hello dunia!"; Kama mimi kutumia * s = kitu au s [0] = 'X'; hivyo kufanya hello, /. hello, kwa nini kuwa segfault? Kwa nini hii segfault? Gani, unatarajia nini? Kama mimi printf ("% s \ n", s); gani, unatarajia kuchapishwa? [Mwanafunzi] X hello. >> Yeah. Tatizo ni kwamba wakati wewe kutangaza string kama hii, s ni pointer kwamba kinaendelea kwenda stack, na kile ambacho ni akizungumzia ni hii kamba ambayo ni zilizomo katika kumbukumbu kusoma tu. Hivyo tu kwa jina, kumbukumbu kusoma tu, unapaswa kupata wazo kwamba kama wewe kujaribu kubadili nini katika kumbukumbu kusoma tu, wewe ni kufanya kitu unapaswa kufanya na kumbukumbu na wewe segfault. Hii ni kweli tofauti kubwa kati ya Char * s na Char s []. Hivyo Char s [], sasa string hii ni kwenda kuwekwa katika stack, na stack si kusoma tu, ambayo ina maana kwamba hii lazima kazi kikamilifu faini. Na inakuwa hivyo. Kumbuka kwamba wakati mimi kufanya Char * s = "hello dunia!", S yenyewe ni juu ya stack lakini s pointi mahali pengine, na kwamba mahali pengine hufanyika kuwa kusoma tu. Lakini Char s [] ni kitu tu juu ya stack. Basi hiyo ni mfano mwingine wa segfault kinachotokea. Tuliona kwamba ./buggy1 ilisababisha segfault. Katika nadharia, unapaswa kuangalia buggy1.c mara moja. Badala yake, tutaweza kuangalia ni kwa njia ya gdb. Taarifa kwamba wakati wewe kupata Mkato kosa (msingi kutupwa), kupata faili hii juu ya msingi hapa kuitwa. Kama sisi ls-l, tutaweza kuona msingi kwamba ni kawaida faili pretty kubwa. Hii ni idadi ya ka ya SVG, hivyo inaonekana kama ni 250-kitu kilobytes. Sababu hii ni kwamba kile dampo msingi kweli ni ni wakati mpango wako shambulio, hali ya kumbukumbu ya mpango wako tu anapata kunakiliwa na pasted katika faili hii. Ni anapata kutupwa kwenye faili hilo. Mpango huu, wakati ni mbio, kilichotokea kuwa na matumizi ya kumbukumbu ya kilobytes karibu 250, na hivyo kwamba ni nini got kutupwa kwenye faili hii. Sasa unaweza kuangalia faili kwamba kama sisi kufanya gdb buggy1 msingi. Tunaweza tu kufanya gdb buggy1, na kwamba itakuwa tu kuanzisha gdb mara kwa mara, kutumia buggy1 kama pembejeo faili wake. Lakini kama wewe kufanya gdb buggy1 msingi, basi ni hasa kwenda kuanza up gdb kwa kuangalia faili kwamba msingi. Na wewe kusema buggy1 njia gdb anajua kwamba kwamba faili msingi linatokana na mpango buggy1. Hivyo gdb buggy1 msingi ni kwenda mara moja kutuletea kwa mpango ambapo kilichotokea kusitisha. Tunaona hapa Programu terminated pamoja na ishara ya 11, Mkato kosa. Sisi kutokea kwa kuona mistari ya kanisa, ambayo pengine ni hayasaidii sana. Lakini kama wewe aina bt au backtrace, ambayo inaenda kuwa kazi kwamba inatupa orodha ya muafaka wetu wa sasa stack. Hivyo backtrace. Inaonekana kama sisi tu muafaka stack mbili. kwanza ni stack yetu kuu frame, na pili ni sura stack kwa kazi hii ya kuwa sisi kutokea kwa kuwa katika, ambayo inaonekana kama sisi tu code kanisa kwa ajili ya. Basi hebu kwenda nyuma katika kazi yetu kuu, na kwa kufanya hivyo tunaweza kufanya sura 1, na nadhani tunaweza pia kufanya chini, lakini mimi kamwe karibu kufanya chini - au juu. Yeah. Juu na chini. Hadi huleta you up moja stack frame, chini huleta wewe chini frame stack. Mimi huwa kamwe kutumia. Mimi tu kusema hasa sura 1, ambayo ni kwenda frame labeled 1. Frame 1 anaenda kutufanya frame kuu stack, na anasema haki hapa mstari wa kanuni sisi kutokea kwa kuwa katika. Kama sisi alitaka mistari michache zaidi ya kificho, tunaweza kusema orodha, na kwamba kinaendelea kutupa mistari yote ya maadili ya kuzunguka. mstari sisi segfaulted saa ilikuwa 6: kama (strcmp ("CS50 miamba", argv [1]) == 0). Kama si dhahiri bado, unaweza kupata moja kwa moja kutoka hapa tu kwa kufikiri kwa nini segfaulted. Lakini tunaweza kuchukua hatua moja zaidi na kusema, "Kwanini argv [1] segfault?" Magazeti Hebu argv [1], na inaonekana kama 0x0 ni, ambayo ni pointer null. Sisi ni strcmping miamba CS50 na null, na ili kwenda segfault. Na kwa nini ni argv [1] null? [Mwanafunzi] sababu sisi hakutoa ni hoja amri yoyote-line. Yeah. Sisi hatukukubaliana ni hoja amri yoyote-line. Hivyo ./buggy1 ni kwenda tu kuwa argv [0] kuwa ./buggy1. Ni si kwenda kuwa na argv [1], ili kwenda segfault. Lakini kama, badala yake, mimi kufanya tu CS50, ni kwenda kusema Unaweza kupata D kwa sababu hiyo ni nini ni zinatakiwa kufanya. Kuangalia buggy1.c, ni walidhani magazeti "Unaweza kupata D" - Kama argv [1] ni si "CS50 miamba", "Unaweza kupata D", mwingine "Unaweza kupata!" Hivyo kama tunataka, tunahitaji hii kulinganisha kama kweli, ambayo ina maana kwamba inalinganishwa na 0. Hivyo argv [1] inahitaji "kuwa CS50 miamba". Kama unataka kufanya hivyo juu ya mstari amri, unahitaji kutumia \ kutoroka nafasi. Hivyo CS50 \ miamba na Wewe kupata A! Kama huwezi kufanya backslash, kwa nini hii si kazi? [Mwanafunzi] Ni hoja mbili tofauti. >> Yeah. Argv [1] ni kwenda kuwa CS50, na argv [2] ni kwenda kuwa miamba. Sawa. Sasa ./buggy2 ni kwenda segfault tena. Badala ya kufungua faili kwa msingi wake, tutaweza tu kufungua buggy2 moja kwa moja, hivyo gdb buggy2. Sasa kama sisi tu kuendesha programu yetu, basi ni kwenda kusema Programu ya kupokea signal SIGSEGV, ambayo ni segfault signal, na hii ni mahali ambapo ilivyotokea kutokea. Kuangalia backtrace yetu, tunaona kwamba tulikuwa katika oh_no kazi, ambalo alikuwa amepewa na Dinky kazi, ambayo aliitwa na binky kazi, ambalo alikuwa amepewa na kuu. Tunaweza pia kuona hoja kwa kazi hizi. hoja kwa Dinky na binky alikuwa 1. Kama sisi orodha oh_no kazi, tunaona kwamba oh_no ni kufanya tu Char ** s = null; * S = "BOOM"; Kwa nini kuwa kushindwa? [Mwanafunzi] Huwezi dereference pointer null? >> Yeah. Hii ni kusema tu s ni null, bila kujali kama kwamba hutokea kwa kuwa ** Char, ambayo, kulingana na jinsi kutafsiri, inaweza kuwa pointer pointer string au safu ya masharti. Ni s ni null, hivyo * s dereferencing pointer null, na hivyo hii ni kwenda kwa ajali. Hii ni moja ya njia ya haraka unaweza uwezekano segfault. Ni tu kutangaza pointer null na mara segfaulting. Hiyo ni nini oh_no ni kufanya. Kama Tunakwenda frame moja, basi sisi ni kwenda kupata ndani ya kazi ambayo inaitwa oh_no. Mimi haja ya kufanya kwamba chini. Kama huna kuingia amri na wewe tu hit Enter tena, itakuwa rudia tu amri ya awali kwamba wewe mbio. Sisi ni katika sura ya 1. Kuorodhesha frame hii, tunaona hapa ni kazi yetu. Unaweza hit orodha tena, au unaweza kufanya orodha 20 na orodha itakuwa ni zaidi. Dinky kazi anasema kama i ni 1, kisha kwenda kufanya kazi oh_no, mwingine kwenda kazi slinky. Na tunajua i ni 1 kwa sababu sisi kutokea kwa kuona hapa Dinky kwamba aliitwa na hoja 1. Au unaweza tu wala magazeti i na matokeo yake watasema i ni 1. Sisi ni sasa katika Dinky, na kama sisi kwenda mwingine frame, tunajua kuishia katika binky. Up. Sasa tuko katika binky. Kuorodhesha kazi hii - orodha kutoka kabla ya nusu kunikatilia mbali - ilianza kama kama i ni 0, kisha tunakwenda kuiita oh_no, mwingine piga Dinky. Tunajua i alikuwa 1, hivyo kuitwa Dinky. Na sasa tuko nyuma katika kuu, na kuu ni kwenda tu kuwa int i = rand ()% 3; Hiyo ni kwenda tu kukupa namba random kwamba ni aidha 0, 1, au 2. Ni kwenda kuwaita binky na idadi hiyo, nayo atarudi 0. Kuangalia hii, tu kutembea kupitia mpango manually bila ya mbio mara moja, ungependa kuweka uhakika wa mapumziko katika kuu, ambayo ina maana kwamba wakati sisi kuendesha programu ya mpango wako anaendesha hadi hits hatua ya mapumziko. Hivyo mbio mpango, itakuwa kukimbia na basi itakuwa hit kazi kuu na kuacha kuendesha. Sasa tuko ndani ya kuu, na hatua au ijayo anaenda kututoa kwa line ya pili ya code. Unaweza kufanya hatua au ijayo. Kupiga ijayo, sasa i umeanzishwa kwa rand ()% 3, ili tuweze kuchapa thamani ya i, na matokeo yake watasema i ni 1. Sasa ni gani jambo kama sisi kutumia ijayo au hatua. Mimi nadhani ni mattered katika moja ya awali, lakini sisi wanataka kutumia ijayo. Kama sisi kutumia hatua, sisi hatua katika kazi, ambayo ina maana ya kuangalia kitu halisi kwamba kinajitokeza ndani ya binky. Kama sisi kutumia ijayo, basi ina maana kwenda juu ya kazi na kwenda tu kwa line ya pili ya kificho katika kazi yetu kuu. Haki hapa kwenye mstari huu, nilikuwa katika ambapo alisema rand ()% 3; kama mimi hatua, ingekuwa kwenda katika utekelezaji wa rand na kuangalia nini kinatokea pale, na mimi nilikuwa hatua kupitia kazi rand. Lakini mimi sijali kuhusu kazi rand. Mimi nataka tu kwenda line ya pili ya kificho katika kuu, hivyo mimi kutumia ijayo. Lakini sasa mimi kufanya huduma kuhusu kazi binky, hivyo nataka hatua katika hilo. Sasa mimi nina katika binky. mstari wa kwanza wa code ni kwenda kusema kama (i == 0), mimi kuchukua hatua, tunaona sisi kuishia katika Dinky. Kama sisi orodha ya mambo, tunaona kwamba ni checked ni i = 0. i si sawa na 0, hivyo alikwenda kwa hali kingine, ambayo ni kwenda kuwaita Dinky (i). Unaweza kupata kuchanganyikiwa. Kama wewe tu kuangalia mistari haya moja kwa moja, unaweza kufikiri kama (i == 0), sawa, basi mimi alichukua hatua na sasa mimi nina katika Dinky (i), unaweza kufikiri kwamba lazima maana i = 0 au kitu. No Ni tu ina maana kwamba anajua unaweza fimbo moja kwa moja kwa Dinky line (i). Sababu i si 0, hatua inayofuata ni si kwenda mwisho katika mwingine. Mwingine si line ni kwenda kuacha katika. Ni tu kwenda kwenda line ijayo inaweza kweli nitafanya, ambayo ni Dinky (i). Kukanyaga katika Dinky (i), sisi kuona kama (i == 1). Sisi tunajua i = 1, hivyo wakati sisi hatua, tunajua tunakwenda kuishia katika oh_no kwa sababu i = 1 wito oh_no kazi, ambayo unaweza kujipenyeza katika, ambayo ni kwenda kuweka Char ** s = kwa null na mara moja "BOOM". Na kisha kwa kweli kuangalia utekelezaji wa buggy2, hii, i ni kupata tu idadi random - 0, 1, au 2 - wito binky, ambayo kama i ni 0 ni wito oh_no, mwingine ni wito Dinky, ambayo huja hapa juu. Kama i ni 1, wito oh_no, mwingine piga slinky, ambayo kuja hapa, kama i ni 2, piga oh_no. Mimi wala hata kufikiri kuna njia - Je, mtu yeyote kuona njia ya kufanya programu hii ambayo si segfault? Kwa sababu isipokuwa mimi kukosa kitu, kama i ni 0, utasikia mara segfault, mwingine wewe kwenda kufanya kazi ambayo kama i ni 1 wewe segfault, mwingine wewe kwenda kufanya kazi ambapo kama i ni 2 wewe segfault. Hivyo hakuna jambo gani wewe, wewe segfault. Nadhani njia moja ya fixing itakuwa badala ya kufanya Char ** s = null, unaweza malloc nafasi kwa kamba hiyo. Tunaweza kufanya malloc (sizeof) - sizeof nini? [Mwanafunzi] (Char) * 5? >> Je, hii wanaonekana haki? Mimi nina kuchukua hii kazi kama mimi kweli mbio, lakini si nini nina kuangalia kwa. Angalia katika aina ya s. Hebu kuongeza * int, hivyo int * x. Napenda kufanya malloc (sizeof (int)). Au kama nilitaka safu ya 5, napenda kufanya (sizeof (int) * 5); Nini kama mimi na ** int? Gani Mimi malloc? [Mwanafunzi] Ukubwa wa pointer. >> Yeah. (Sizeof (int *)); Same kitu chini hapa. Mimi nataka (sizeof (Char *)); Hii ni kwenda kutenga nafasi kwa pointer kwamba anaonyesha "BOOM". Sihitaji kutenga nafasi kwa ajili ya "BOOM" yenyewe kwa sababu hii ni kimsingi sawa na kile alisema kabla ya ya Char * x = "BOOM". "BOOM" tayari upo. Hufanyika kwa kuwepo katika kanda kusoma tu ya kumbukumbu. Lakini tayari ipo, ambayo ina maana hii mstari wa kanuni, ikiwa ni s ** Char, kisha * s ni * Char na wewe ni kuweka hii * Char na kumweka kwa "BOOM". Kama nilitaka kunakili "BOOM" ndani, basi mimi ingekuwa haja ya kutenga nafasi kwa s. Nitafanya * s = malloc (sizeof (Char) * 5); Mbona 5? Mbona si 4? Inaonekana kama "BOOM" ni 4 wahusika. >> [Mwanafunzi] tabia null. Yeah. Yote ya masharti yako ni kwenda haja ya tabia null. Sasa siwezi kufanya kitu kama strcat - Ni nini kazi kwa kuiga kamba? [Mwanafunzi] cpy? >> Strcpy. mtu strcpy. Hivyo strcpy au strncpy. strncpy ni kidogo salama tangu unaweza specify hasa jinsi wengi wahusika, lakini hapa haijalishi sababu tunajua. Hivyo strcpy na kuangalia katika hoja. Hoja ya kwanza ni ya marudio yetu. Hoja ya pili ni chanzo chetu. Sisi ni kwenda na nakala katika marudio * wetu s pointer "BOOM". Kwa nini wapate unataka kufanya hii na strcpy badala ya kile tu tulikuwa kabla ya ya * s = "BOOM"? Kuna sababu unaweza kutaka kufanya hivyo, lakini nini ni sababu ya kwamba? [Mwanafunzi] Kama unataka kubadilisha kitu katika "BOOM". >> Yeah. Sasa siwezi kufanya kitu kama s [0] = 'X'; kwa sababu ya pointi chungu na kwamba nafasi kwenye chungu kwamba s ni akizungumzia ni pointer nafasi zaidi juu ya chungu, ambayo ni hifadhi ya "BOOM". Hivyo nakala hii ya "BOOM" ni kuwa kuhifadhiwa katika lundo. Kuna nakala mbili za kitaalam "BOOM" katika programu yetu. Kuna mmoja tu kwanza hiyo aliyopewa na hii mara kwa mara "BOOM" kamba, na nakala ya pili ya "BOOM", strcpy umba nakala ya "BOOM". Lakini nakala ya "BOOM" ni kuwa kuhifadhiwa kwenye chungu, na chungu wewe ni bure kubadilika. chungu si kusoma tu, hivyo hiyo ina maana kwamba s [0] ni kwenda basi unaweza kubadilisha thamani ya "BOOM". Ni kwenda basi wewe kubadili tabia hizo. Maswali? Sawa. Kuhamia kwenye buggy3, hebu gdb buggy3. Sisi tu kukimbia na sisi kuona sisi kupata segfault. Kama sisi backtrace, kuna mbili tu kazi. Kama sisi kwenda juu katika kazi yetu kuu, sisi kuona kwamba sisi segfaulted katika mstari huu. Hivyo tu kuangalia mstari huu, kwa ajili ya (int line = 0; fgets mambo haya haina sawa null; mstari + +). Frame wetu uliopita aliitwa _IO_fgets. Utaona kwamba mengi na kujengwa katika utendaji C, kwamba wakati wewe kupata segfault, kutakuwa kweli cryptic kazi majina kama hii _IO_fgets. Lakini ambayo inaenda yanahusiana na wito huu fgets. Mahali fulani ndani ya hapa, sisi ni segfaulting. Kama sisi kuangalia hoja kwa fgets, tunaweza magazeti buffer. Hebu magazeti kama - Oh, hakuna. Print si kwenda kufanya kazi hasa kama mimi unataka kwa. Hebu tuangalie mpango halisi. Buffer ni safu tabia. Ni safu tabia ya wahusika 128. Hivyo wakati mimi kusema magazeti buffer, ni kwenda magazeti wahusika wale 128, ambayo mimi nadhani ni mambo yanayotarajiwa. Nini nilikuwa kutafuta ni magazeti anuani ya buffer, lakini kwamba si kweli niambie sana. Hivyo wakati mimi kutokea kwa kusema hapa juu x buffer, inaonyesha mimi 0xbffff090, ambayo, kama wewe kumbuka kutoka mapema au fulani, Oxbffff huelekea kuwa kanda stack-ish. stack huelekea kuanza mahali fulani tu chini ya 0xc000. Tu kwa kuona anuani hii, najua kwamba buffer kinachojitokeza stack. Kuanzisha tena mpango wangu, kukimbia, juu, buffer tuliona ilikuwa hii mlolongo wa wahusika kwamba ni kiasi pretty maana. Kisha uchapishaji faili, nini faili kuangalia kama? [Mwanafunzi] Batili. >> Yeah. File ni ya aina * JALADA, hivyo ni pointer, na thamani ya pointer kwamba ni null. Hivyo fgets ni kwenda kujaribu kusoma kutoka pointer kwamba katika njia ya moja kwa moja, lakini ili kupata kwamba pointer, ina dereference yake. Au, ili kupata kile ni lazima akizungumzia, ni dereferences yake. Hivyo ni dereferencing pointer null na segfaults yake. Ningeweza imeweza kuanzisha pale. Kama sisi kuvunja katika hatua zetu kuu na kukimbia, mstari wa kwanza wa code ni Char * filename = "nonexistent.txt"; Kwamba lazima kutoa pretty kubwa ladha kama kwa sababu programu hii inashindwa. Typing ijayo inanileta kwa mstari unaofuata, ambapo mimi kufungua faili hii, na kisha mimi mara moja kupata katika line yetu, ambapo mara moja mimi hit ijayo, ni kwenda segfault. Je, mtu yeyote unataka kutupa nje sababu sisi tupate kuwa segfaulting? [Mwanafunzi] Picha haipo. >> Yeah. Hii ni walidhani kuwa dokezo kwamba wakati wowote wewe ni kufungua faili unahitaji kuangalia kwamba faili kweli lipo. Hivyo hapa, "nonexistent.txt"; Wakati sisi fopen filename kwa ajili ya kusoma, sisi basi haja ya kusema kama (faili == null) na kusema printf ("Picha haipo!" au - bado bora - filename); kurudi 1; Hivyo sasa sisi kuangalia kuona kama ni null kabla ya kuendelea na kweli kujaribu kusoma kutoka faili hilo. Tunaweza remake tu kuona kwamba matendo hayo. Mimi lengo ni pamoja na mstari mpya. Hivyo sasa nonexistent.txt haipo. Unapaswa daima kuangalia kwa aina hii ya kitu. Unapaswa daima kuangalia kuona kama fopen anarudi null. Unapaswa daima kuangalia kuhakikisha kwamba malloc haina kurudi null, au mwingine segfault. Sasa buggy4.c. Mbio. Mimi guessing hii ni kusubiri kwa ajili ya pembejeo au looping uwezekano usio. Ndiyo, ni usio looping. Hivyo buggy4. Inaonekana kama sisi ni usio looping. Tunaweza kuvunja saa kuu, kuendesha programu yetu. Katika gdb, kwa muda mrefu kama wewe kutumia abbreviation ni suala la utata au maalum vifupisho kwamba wao kutoa kwa ajili yenu, basi unaweza kutumia n kutumia ijayo badala ya kuwa na aina nje karibu njia yote. Na kwa kuwa sasa nimepata hit n mara moja, siwezi tu hit Enter kuendelea ijayo badala ya kuwa na hit n Ingiza, n Ingiza, n Ingiza. Inaonekana kama mimi niko katika baadhi ya aina ya kwa kitanzi ambacho kuweka safu [i] kwa 0. Inaonekana kama mimi kamwe kuvunja nje ya hili kwa kitanzi. Kama mimi magazeti i, hivyo i ni 2, kisha nitakwenda ijayo. Mimi itabidi magazeti i, i ni 3, kisha nitakwenda ijayo. Mimi itabidi magazeti i na i ni 3. Next, magazeti i, i ni 4. Kweli, magazeti sizeof (safu), hivyo ukubwa wa safu ni 20. Lakini inaonekana kama kuna baadhi maalum gdb amri kwa ajili ya kwenda mpaka kitu kinachotokea. Ni kama kuweka hali juu ya thamani ya kutofautiana. Lakini sikumbuki ni nini. Hivyo kama sisi kuendelea - Nini walikuwa wewe kusema? Nini kuleta? [Mwanafunzi] Je kuonyesha i kuongeza - >> Yeah. Hivyo kuonyesha i inaweza kusaidia. Kama sisi tu kuonyesha i, itakuwa kuweka hapa nini thamani ya i ni hivyo mimi hawana magazeti ni nje kila wakati. Kama sisi tu kuendelea ijayo, tunaona 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5. Kitu ni kwenda vibaya sana, na i ni kuwa upya kwa 0. Kuangalia buggy4.c, tunaona yote ambayo hufanyika ni int safu [5]; kwa ajili ya (i = 0; i <= sizeof (safu); i + +) safu [i] = 0; Nini sisi kuona kwamba ni makosa hapa? Kama dokezo, wakati mimi nilikuwa kufanya gdb buggy4 - hebu kuvunja kuu, kukimbia - Sikuweza magazeti sizeof (safu) tu kuona nini hali ni ambapo mimi lazima hatimaye kuvunja nje. Ambapo Mimi ni nani? Je, mimi kukimbia? Sikuweza kutangaza bado. Hivyo magazeti sizeof (safu) na kwamba 20, ambayo inatarajiwa tangu safu yangu ni ya kawaida 5 na ni ya integers 5, hivyo suala zima lazima 5 * sizeof (int) ka, ambapo sizeof (int) huelekea kuwa 4. Hivyo sizeof (safu) ni 20. Nini hii? [Mwanafunzi] Kugawanywa na sizeof (int). >> Yeah, / sizeof (int). Inaonekana kama bado kuna tatizo hapa. Nadhani hii lazima tu kuwa < tangu ni kiasi pretty daima > [Bowden] Ndiyo. Wakati sisi ni kwenda nje ya mwisho wa safu yetu, namna fulani kwamba nafasi ya kuwa sisi ni kuu ni kuu thamani ya i. Na hivyo kama sisi kuangalia ndani buggy4, kuvunja kuu, kukimbia, hebu magazeti anuani ya i. Inaonekana kama ni bffff124. Sasa hebu magazeti anuani ya safu [0]. 110. Je kuhusu [1]? 114. [2], 118. 11c, 120. safu [5] ni bfff124. Hivyo safu [5] ina anuani hiyo kama i, ambayo ina maana kwamba safu [5] ni i. Kama wana anuani hiyo, wao ni kitu kimoja. Hivyo wakati sisi kuweka safu [5] kwa 0, sisi ni kuweka i kwa 0. Na kama wewe kufikiri juu ya hili katika suala la stack, int i ni alitangaza kwanza, ambayo ina maana i anapata baadhi nafasi kwenye stack. Kisha safu [5] ni zilizotengwa, hivyo basi ka 20 zinatolewa kwa stack. Hivyo i anapata zilizotengwa kwanza, basi ka hizi 20 kupata zilizotengwa. Hivyo i kinachotokea haki kabla ya safu, na kwa sababu ya njia, kama nilivyosema wiki iliyopita, ambapo kitaalam stack hukua chini, wakati wewe index katika safu, sisi ni uhakika kwamba nafasi 0 katika safu daima hufanyika kabla ya nafasi ya kwanza katika safu. Hii ni aina ya jinsi mimi akauchomoa wiki iliyopita. Ona kwamba chini tuna anuani 0 na saa ya juu tuna anuani Max. stack daima ni kukua chini. Hebu sema sisi kutenga i. Sisi kutenga integer i, ambayo ina maana wacha tu kusema hapa juu integer i anapata zilizotengwa. Kisha sisi kutenga safu yetu ya integers 5, ambayo ina maana kwamba chini ya kwamba, tangu stack ni kuongezeka chini, integers wale 5 kupata zilizotengwa. Lakini kwa sababu ya jinsi arrays kazi, sisi ni uhakika kwamba nafasi ya kwanza katika safu daima ina anuani chini ya Jambo la pili katika safu. Hivyo safu nafasi 0 daima ina kutokea kwanza katika kumbukumbu, ambapo safu msimamo 1 kitokee baada ya kuwa na safu msimamo 2 kitokee baada ya kuwa, ambayo ina maana kwamba nafasi safu 0 kingetokea mahali fulani hapa chini, safu msimamo 1 kingetokea hapo juu kwamba sababu ukienda juu ina maana anwani ya juu tangu anuani upeo ni hapa juu. Hivyo safu [0] chini hapa, safu [1] hadi hapa, safu [2] hadi hapa, safu [3] hadi hapa. Angalia jinsi kabla sisi zilizotengwa integer i wote njia ya juu hapa, kama sisi hoja zaidi na zaidi katika safu yetu, sisi ni kupata karibu na karibu na integer yetu i. Ni hivyo tu hutokea kwamba safu [5], ambayo ni moja nafasi zaidi ya safu yetu, ni hasa ambapo integer i kilichotokea kuwa zilizotengwa. Basi hiyo ni mahali ambapo sisi kutokea kwa kuwa kupiga nafasi kwenye stack zilizotengwa kwa ajili ya integer i, na sisi ni kuweka kwamba kwa 0. Hiyo ni jinsi ya kuwa kazi. Maswali? Yeah. [Mwanafunzi] Kamwe akili. Sawa. [Mwanafunzi] Jinsi gani unaweza kuepuka hayo aina ya makosa? Hizi aina ya makosa? Usitumie C kama programu lugha yako. Kutumia lugha ambayo ina mipaka safu kuangalia. Muda mrefu kama wewe ni makini, wewe tu haja ya kuepuka kwenda nyuma mipaka ya safu yako. [Mwanafunzi] Basi hapa wakati sisi akaenda nyuma mipaka ya safu yako - [Bowden] Hiyo ambapo mambo kuanza kwenda vibaya. >> [Mwanafunzi] Oh, okay. Muda mrefu kama wewe kukaa ndani ya kumbukumbu zilizotengwa kwa ajili ya safu yako, wewe ni faini. Lakini C gani hakuna kuangalia makosa. Kama mimi kufanya safu [1000], ni furaha tu kurekebisha chochote kinachotokea - Unaendelea na mwanzo wa safu, basi huenda nafasi 1000 baada na huiweka kwa 0. Haina kufanya yoyote ya kuangalia kwamba oh, hii si kweli kuwa mambo 1000 ndani yake. 1000 ni njia zaidi ya kile mimi lazima kubadilisha, ambapo Java au kitu utapata safu nje ya mipaka index au index nje ya ubaguzi mipaka. Hiyo ni kwa nini mengi ya lugha za ngazi za juu kuwa na mambo haya ambapo kama kwenda zaidi ya mipaka ya safu, wewe kushindwa hivyo kwamba huwezi kubadili mambo kutoka chini ya wewe na kisha mambo kwenda mbaya zaidi kuliko kupata tu isipokuwa akisema kwamba alikwenda ng'ambo ya mwisho wa safu. [Mwanafunzi] Na hivyo tusingeli tu iliyopita <= tu > [Bowden] Yeah. Ni lazima kuwa > [Mwanafunzi] Haki. Zaidi maswali? Sawa. [Mwanafunzi] nina swali. >> Yeah. [Mwanafunzi] Nini halisi safu variable? [Bowden] Kama kile ni safu? Array yenyewe ni ishara. Ni haki ya anuani ya kuanza ya ka 20 kwamba sisi ni referencing. Unaweza kufikiria kama pointer, lakini ni pointer mara kwa mara. Haraka kama mambo kupata compiled, safu variable haipo tena. [Mwanafunzi] Hivyo jinsi gani kupata ukubwa wa safu? Ukubwa wa safu inahusu ukubwa wa block kwamba ishara kwamba inahusu. Wakati mimi kufanya kitu kama printf ("% p \ n", safu); hebu kukimbia. Nini mimi tu kufanya makosa? 'Safu' Array alitangaza hapa. Oh, hapa juu. Clang ni wajanja, na hutokea kwa taarifa kwamba mimi alitangaza safu kama vipengele 5 lakini nina Indexing katika nafasi 1000. Ni anaweza kufanya hivyo kwa sababu hizi ni baadhi tu ya constants. Ni inaweza tu kwenda mbali katika noticing kwamba mimi nina kwenda zaidi ya mipaka ya safu. Lakini taarifa kabla ya wakati tulikuwa i kuwa sio sahihi, haiwezi uwezekano kuamua jinsi wengi maadili i inaweza kuchukua, hivyo hawezi kuamua kwamba i alikuwa anaenda ng'ambo ya mwisho wa safu. Hiyo tu Clang kuwa wajanja. Lakini sasa kufanya buggy4. Hivyo kile kingine mimi kufanya makosa? Implicitly kutangaza maktaba kazi 'printf'. Mimi naenda wanataka # pamoja . Sawa. Sasa mbio buggy4. Uchapishaji thamani ya safu kama mimi hapa, uchapishaji ni kama pointer prints kitu ambacho inaonekana kama hii - bfb8805c - ambayo ni baadhi anuani kwamba katika mkoa stack-ish. Array yenyewe ni kama pointer, lakini si pointer halisi, tangu pointer mara kwa mara tunaweza kubadilisha. Array ni baadhi tu ya mara kwa mara. Vitalu 20 ya kumbukumbu ya kuanza saa 0xbfb8805c anuani. Hivyo bfb8805c kupitia anuani hii +20--au mimi nadhani -20 - yote ni ya kumbukumbu zilizotengwa kwa ajili ya safu hii. Array, variable yenyewe si kuhifadhiwa mahali popote. Wakati wewe ni kuandaa, compiler - mkono wimbi saa yake - lakini compiler tu kutumia ambapo anajua kuwa safu. Ni anajua ambapo safu kwamba kuanza, na hivyo inaweza daima tu kufanya mambo katika suala la offsets tangu mwanzo kwamba. Haina haja ya variable yenyewe kuwakilisha safu. Lakini wakati mimi kufanya kitu kama int safu * p =; sasa p ni pointer ambayo inaelekeza kwamba safu, na sasa p kweli gani zipo juu ya stack. Mimi nina uhuru wa kubadilisha p. Naweza kufanya p = malloc. Hivyo awali alisema kwa safu; sasa inaelekeza katika nafasi baadhi ya chungu. Mimi siwezi kufanya safu = malloc. Kama Clang ni wajanja, itakuwa yell saa yangu haki mbali bat. Kweli, mimi nina uhakika pretty GCC bila kufanya hii pia. Hivyo safu aina ya 'int [5]' si assignable. Huwezi hawawajui kitu aina safu kwa sababu ni safu tu mara kwa mara. Ni ishara ambayo marejeo wale ka 20. Siwezi kuibadilisha. [Mwanafunzi] Na pale ambapo ni kawaida ya safu kuhifadhiwa? [Bowden] Ni si kuhifadhiwa mahali popote. Ni wakati ni kuandaa. Hivyo ambapo ni kawaida ya safu kuhifadhiwa? Unaweza tu kutumia sizeof (safu) ndani ya kazi kwamba safu ya kutangazwa yenyewe. Hivyo kama mimi kufanya baadhi ya kazi, foo, na mimi kufanya (int safu []) printf ("% d \ n", sizeof (safu)); na kisha chini hapa mimi wito foo (safu); ndani ya kazi hii - wacha kukimbia. Hii ni Clang kuwa wajanja tena. Ni akiniambia kwamba sizeof kwenye safu parameter kazi atarudi ukubwa wa '* int'. Hii itakuwa kosa kama si nini nilitaka kutokea. Hebu kweli kugeuka mbali Werror. Onyo. Maonyo ni faini. Itakuwa bado kukusanya muda mrefu kama ina onyo. . / A.out ni kwenda magazeti 4. onyo kwamba alikuwa yanayotokana ni kiashiria wazi ya nini potoka. Hii safu int ni kwenda tu na magazeti sizeof (int *). Hata kama mimi kuweka safu [5] katika hapa, ni bado tu kwenda magazeti sizeof (int *). Hivyo kwa haraka kama wewe kupita ndani ya kazi, tofauti kati ya arrays na kuyatumia haipo. Hii hutokea kwa kuwa safu kwamba ilitangazwa siku ya stack, lakini kwa haraka kama sisi kupita kwamba thamani, kwamba 0xbf blah, blah, blah katika kazi hii, kisha pointer hii inaelekeza kwamba safu ya stack. Hivyo hiyo ina maana kwamba sizeof tu inatumika katika kazi kwamba safu ilitangazwa, ambayo ina maana kwamba wakati wewe ni kuandaa kazi hii, wakati Clang huenda kwa njia ya kazi hii, anaona safu safu int ya kawaida 5. Hivyo basi anaona sizeof (safu). Naam, hiyo ni 20. Hiyo ni kweli jinsi sizeof kimsingi kazi kwa karibu kesi zote. Sizeof si kazi; ni operator. Huwezi kuwaita kazi sizeof. Sizeof (int), compiler tu kutafsiri kwamba kwa 4. Got it? Sawa. [Mwanafunzi] Basi ni nini tofauti kati ya sizeof (safu) katika kuu na katika foo? Hii ni kwa sababu sisi ni kusema sizeof (safu), ambayo ni ya aina * int, ambapo safu chini hapa ni si ya aina * int, ni safu int. [Mwanafunzi] Hivyo kama wewe alikuwa parameter katika safu [] badala ya safu int *, ingekuwa kwamba maana kwamba unaweza bado kubadili safu kwa sababu sasa ni pointer? [Bowden] Kama hili? >> [Mwanafunzi] Yeah. Je, unaweza kubadili safu ndani ya kazi sasa? [Bowden] Unaweza kubadilisha safu katika kesi zote. Katika wote wa kesi hizi ni huru kusema safu [4] = 0. [Mwanafunzi] Lakini unaweza kufanya safu uhakika na kitu kingine? [Bowden] Oh. Yeah. Katika kesi aidha - >> [mwanafunzi] Yeah. [Bowden] tofauti kati ya safu [] na int safu *, hapana. Unaweza pia kupata baadhi ya safu multidimensional katika hapa kwa syntax baadhi urahisi, lakini bado tu pointer. Hii ina maana kwamba mimi ni huru kufanya safu = malloc (sizeof (int)); na sasa kumweka mahali pengine. Lakini tu kama jinsi hii matendo milele na daima, kubadilisha hii safu kwa kufanya hivyo uhakika na kitu kingine haibadiliki hii safu chini hapa kwa sababu ni nakala ya hoja, si pointer hoja kwamba. Na kweli, kama dalili zaidi kwamba ni sawa - sisi tayari kuona nini prints safu uchapishaji - nini kama sisi magazeti anuani ya safu au anuani ya anuani ya safu aidha ya wale? Hebu kupuuza hii moja. Sawa. Hii ni faini. Ni sasa mbio. / A.out. Uchapishaji safu, basi uchapishaji anuani ya safu, ni kitu kimoja. Array tu haipo. Ni anajua wakati wewe ni uchapishaji safu, wewe ni uchapishaji ishara kwamba inahusu ka wale 20. Uchapishaji anuani ya safu, vizuri, safu haipo. Haina anuani, hivyo tu Prints anuani ya ka wale 20. Haraka kama wewe kukusanya chini, kama katika buggy4 yako compiled /. A.out, safu haipo. Kuyatumia zipo. Arrays hawana. vitalu ya kumbukumbu anayewakilisha safu bado zipo, lakini safu kutofautiana na vigezo ya aina ya kwamba hazipo. Wale ni kama tofauti kubwa kati ya arrays na kuyatumia ni haraka kama wewe kufanya wito kazi, hakuna tofauti. Lakini ndani ya kazi ambayo safu yenyewe ni alitangaza, sizeof kazi tofauti tangu wewe ni uchapishaji ukubwa wa vitalu badala ya ukubwa wa aina, na huwezi kubadilisha ni kwa sababu ni ishara. Uchapishaji kitu na anuani ya kitu Prints kitu kimoja. Na kwamba ni pretty kiasi. [Mwanafunzi] Unaweza kusema kwamba muda zaidi? Nipate kuwa amekosa kitu. Uchapishaji safu na anuani ya safu Prints kitu kimoja, lakini kama wewe magazeti pointer dhidi anuani ya pointer, jambo moja Prints anuani ya nini wewe akizungumzia, nyingine Prints anuani ya pointer juu ya stack. Unaweza kubadilisha pointer; huwezi kubadilisha ishara safu. Na sizeof pointer ni kwenda magazeti ukubwa wa aina hiyo pointer. Hivyo int * p sizeof (p) ataenda magazeti 4, lakini int safu [5] magazeti sizeof (safu) ataenda magazeti 20. [Mwanafunzi] Basi int safu [5] itakuwa magazeti 20? >> Ndiyo. Hiyo ndiyo sababu ndani ya buggy4 wakati kutumika kuwa sizeof (safu) hii alikuwa akifanya i <20, ambayo si kile tunachotaka. Tunataka i <5. >> [Mwanafunzi] Sawa. [Bowden] Na kisha kwa haraka kama wewe kuanza kupita katika utendaji, kama tulivyofanya int * p = array; ndani ya kazi hii, tunaweza kutumia kimsingi p na safu katika hasa njia ile ile, isipokuwa kwa ajili ya tatizo sizeof na tatizo kubadilisha. Lakini p [0] = 1; ni sawa na kusema safu [0] = 1; Na kwa haraka kama sisi kusema foo (safu); au foo (p); ndani ya kazi ya foo, huu ni mwito huo mara mbili. Hakuna tofauti kati ya simu hizi mbili. Kila mtu mzuri juu ya hilo? Sawa. Tuna dakika 10. Tutajaribu kupata kupitia mpango huu typer Hacker, tovuti hii, ambayo alikuja nje mwaka jana au kitu. Ni tu walidhani kuwa kama wewe aina nasibu na Prints nje - Chochote faili hutokea kwa kuwa kubeba ni nini inaonekana kama wewe ni kuandika. Inaonekana kama baadhi ya aina ya maadili ya mfumo wa uendeshaji. Hiyo ni nini tunataka kutekeleza. Unapaswa kuwa executable binary aitwaye hacker_typer kwamba inachukua katika hoja moja, faili na "aina hacker." Mbio executable lazima wazi screen na kisha magazeti nje moja tabia kutoka faili kupita katika kila wakati mtumiaji presses muhimu. Hivyo kila ufunguo waandishi, ni lazima kutupa mbali na badala yake magazeti tabia kutoka faili kwamba ni hoja. Mimi itabidi pretty much kukuambia nini mambo ya sisi ni kwenda haja ya kujua ni. Lakini tunataka kuangalia nje ya maktaba termios. Sijawahi kutumika hii maktaba katika maisha yangu yote, hivyo ina madhumuni ya chini sana. Lakini hii ni kwenda kuwa maktaba tunaweza kutumia kutupa mbali tabia hit wakati wewe ni kuandika katika kiwango in Hivyo hacker_typer.c, na sisi ni kwenda wanataka # pamoja . Kuangalia ukurasa mtu kwa termios - I'm guessing terminal ni OS au kitu - Sijui jinsi ya kusoma. Kuangalia hii, inasema kwa pamoja na hizi files 2, hivyo tutaweza kufanya hivyo. Jambo la kwanza kwanza, tunataka kuchukua katika hoja moja, ambayo ni faili sisi inapaswa kufungua. Basi nini nataka kufanya? Je, mimi kuangalia kuona nina hoja moja? [Mwanafunzi] Kama argc sawa yake. >> [Bowden] Yeah. Hivyo kama (argc = 2)! Printf ("matumizi:% s [faili kufungua]"). Hivyo sasa kama mimi hii kukimbia bila kutoa hoja ya pili - oh, nahitaji mstari mpya - utaona anasema matumizi: / hacker_typer,. na kisha hoja ya pili lazima faili mimi wanataka kufungua. Sasa nini mimi? Mimi nataka kusoma kutoka faili hii. Je, mimi kusoma kutoka faili? [Mwanafunzi] Wewe kufungua kwanza. >> Yeah. Hivyo fopen. Je fopen kuangalia kama? [Mwanafunzi] Filename. >> [Bowden] Filename ni kwenda kuwa argv [1]. [Mwanafunzi] Na hapo nini unataka kufanya na hayo, hivyo - >> [Bowden] Yeah. Hivyo kama hukuzikumbuka, unaweza tu kufanya mtu fopen, ambapo ni kwenda kuwa const Char * njia ambapo njia ni filename, const Char * mode. Kama kutokea kwa si unakumbuka kile mode ni, basi unaweza kuangalia kwa mode. Ndani ya mtu kurasa, tabia slash ni nini unaweza kutumia ili kutafuta mambo. Hivyo ninapoandika / mode kutafuta mode. n na N ni nini unaweza kutumia mzunguko kupitia mechi ya utafutaji. Hapa inasema pointi mode hoja kwa kamba mwanzo na mmoja wa Mwandamano zifuatazo. Hivyo r, Open Nakala faili kwa ajili ya kusoma. Hiyo ni nini tunataka kufanya. Kwa kusoma, na mimi nataka kuhifadhi kwamba. kitu kinaenda kuwa * FILE. Sasa nini nataka kufanya? Nipe pili. Sawa. Sasa nini nataka kufanya? [Mwanafunzi] Angalia kama ni null. >> [Bowden] Yeah. Yoyote wakati wa kufungua faili, kuhakikisha kwamba wewe ni mafanikio na uwezo wa kufungua hiyo. Sasa nataka kufanya kwamba stuff termios ambapo nataka kwanza kusoma yangu mazingira ya sasa ya na wale kuokoa katika kitu, kisha Mimi nataka kubadili mipangilio yangu kutupilia mbali tabia yoyote kwamba mimi aina, na kisha Mimi nataka kusasisha mipangilio hizo. Na kisha mwisho wa mpango, nataka kubadili nyuma mipangilio yangu ya awali. Hivyo struct ni kwenda kuwa ya termios aina, na mimi nina kwenda kutaka mbili ya wale. moja ya kwanza ni kwenda kuwa current_settings yangu, na kisha wao wanaenda kuwa hacker_settings yangu. Kwanza, mimi naenda wanataka kuokoa yangu mazingira ya sasa, basi mimi nina kwenda kutaka update hacker_settings, na kisha njia mwisho wa mpango wangu, nataka kurudia mazingira ya sasa. Hivyo kuokoa mazingira ya sasa, njia ya kwamba kazi, termios mtu sisi. Sisi tunaona kwamba tuna hii tcsetattr int, int tcgetattr. Mimi kupita katika struct termios na pointer wake. njia hii itakuwa kuangalia ni - I've tayari wamesahau nini kazi iliitwa. Nakala na kuweka. Hivyo tcgetattr, kisha Mimi nataka kupita katika struct kwamba mimi nina kuokoa habari katika, ambayo ni kwenda kuwa current_settings, na hoja ya kwanza ni descriptor faili kwa ajili ya jambo nataka kuokoa sifa ya. Nini descriptor faili ni ni kama yoyote wakati wa kufungua faili, anapata descriptor faili. Wakati mimi fopen argv [1], anapata descriptor faili ambayo wewe ni referencing kila unataka kusoma wala kuandika na hiyo. Hiyo si descriptor faili nataka kutumia hapa. Kuna tatu faili descriptors una by default, ambayo ni ya kiwango katika, kiwango nje, na hitilafu ya kiwango. By default, nadhani ni ya kiwango katika ni 0, kiwango nje ni 1, na makosa ya hali ni 2. Basi je, nataka kubadili mipangilio ya? Nataka mabadiliko ya mazingira ya wakati mimi hit tabia, Mimi nataka kutupa kwamba tabia mbali badala ya uchapishaji kwa screen. Nini mkondo - kiwango katika, nje ya kiwango, au kosa kiwango - anaitikia kwa mambo wakati ninapoandika katika keyboard? >> [Mwanafunzi] darasa in >> Yeah. Hivyo siwezi ama kufanya 0 au siwezi kufanya stdin. Nina kupata current_settings ya kiwango in Sasa nataka kusasisha mipangilio hizo, hivyo kwanza mimi itabidi nakala katika hacker_settings nini current_settings yangu ni. Na jinsi structs kazi itakuwa ni nakala tu. Hii nakala zote za mashamba, kama ungependa kutarajia. Sasa nataka update baadhi ya mashamba. Kuangalia termios, ungependa kuwa na kusoma kwa njia ya kura ya hii tu kuona nini ungependa unataka kuangalia kwa, lakini bendera utaenda unataka kuangalia kwa ni mwangwi, hivyo ECHO Echo pembejeo wahusika. Kwanza nataka kuweka - I've tayari wamesahau nini mashamba ni. Hii ni nini struct inaonekana kama. Hivyo pembejeo modes nadhani tunataka kubadili. Tutaangalia ufumbuzi kuhakikisha kwamba ni nini tunataka kubadili. Tunataka kubadili lflag ili kuzuia wanaohitaji kuangalia njia zote hizi. Tunataka kubadili modes mitaa. Ungependa kuwa na kusoma kwa jambo hili zima kuelewa ambapo kila kitu ni mali kwamba tunataka mabadiliko. Lakini ni ndani ya modes mitaa ambapo tunakwenda wanataka mabadiliko hayo. Hivyo hacker_settings.cc_lmode ni nini ni wito. c_lflag. Hii ni wapi tunapata ndani ya waendeshaji bitwise. Sisi ni aina ya nje ya muda, lakini tutaweza kwenda kupitia haraka ni halisi. Hii ni wapi tunapata ndani ya waendeshaji bitwise, ambapo mimi nadhani alisema mmoja wa muda mrefu uliopita kwamba wakati wowote kuanza kushughulika na bendera, utaenda kutumia bitwise operator mengi. Kila kidogo katika bendera sambamba na aina fulani ya tabia. Hivyo hapa, bendera hii ina rundo la vitu mbalimbali, ambapo wote maana kitu tofauti. Lakini nini nataka kufanya ni tu kugeuka mbali kidogo ambayo inalingana na ECHO. Hivyo kugeuka kuwa mbali mimi kufanya & = ¬ ECHO. Kweli, nadhani ni kama tECHO au kitu. Mimi tu kwenda kuangalia tena. Naweza termios yake. Ni tu ECHO. ECHO ni kwenda kuwa kidogo moja. ¬ ECHO ni kwenda kwa maana ya bits wote ni kuweka 1, ambayo ina maana bendera wote ni kuweka kweli isipokuwa kwa kidogo ECHO. Kwa kumaliza wangu bendera ya ndani na hii, ina maana bendera zote kwamba sasa kuweka kweli Bado utakuwa kuweka kweli. Kama ECHO bendera yangu ni kuweka kweli, basi hii ni lazima kuweka uongo juu ya bendera ya ECHO. Hivyo hii mstari wa kanuni tu anarudi mbali bendera ECHO. mistari nyingine ya kificho, na mimi itabidi nakala kwa maslahi ya muda na kisha kueleza wao. Katika ufumbuzi, alisema 0. Ni pengine bora kwa uwazi kusema stdin. Ona kwamba mimi nina pia kufanya ECHO | ICANON hapa. ICANON inahusu kitu tofauti, ambayo ina maana mode kisheria. Nini kisheria mode njia ni kawaida wakati wewe ni kuandika nje ya mstari amri, kiwango katika mchakato haina chochote mpaka hit newline. Hivyo wakati wa kufanya GetString, unapoandika rundo la vitu, wewe hit newline. Hiyo ni wakati ni alimtuma kiwango in Hiyo ni default. Wakati mimi kugeuka mbali mode kisheria, sasa kila tabia moja vyombo vya habari ni nini anapata kusindika, ambayo ni kawaida aina ya mbaya kwa sababu ni mwepesi wa mchakato mambo haya, ambayo ni kwa nini ni vizuri buffer ndani mistari nzima. Lakini Mimi nataka kila tabia kuwa processed tangu mimi sitaki kusubiri kwa mimi hit newline kabla michakato ya wahusika wote nimekuwa kuandika. Hii anarudi mbali mode kisheria. Mambo haya tu ina maana wakati ni kweli michakato wahusika. Hii ina maana mchakato wao mara moja; haraka kama mimi kuandika yao, mchakato wao. Na hii ni kazi ambayo ni uppdatering mipangilio yangu kwa kiwango katika, na TCSA njia kufanya hivyo hivi sasa. chaguzi nyingine ni kusubiri hadi hapo kila kitu sasa ni juu ya mkondo ni processed. Hiyo haina kweli jambo. Haki tu sasa kubadili mipangilio yangu kuwa chochote kwa sasa katika hacker_typer_settings. Mimi nadhani kuitwa ni hacker_settings, hivyo hebu mabadiliko hayo. Kubadili kila kitu kwa hacker_settings. Sasa mwisho wa programu yetu sisi ni kwenda kutaka revert kwa nini kwa sasa ndani ya normal_settings, ambayo ni kwenda kuangalia tu kama & normal_settings. Taarifa mimi si iliyopita yoyote ya normal_settings yangu tangu awali ya kupata. Kisha kubadili tu nyuma yao, mimi kupita yao nyuma mwishoni. Hii ilikuwa update. Sawa. Sasa ndani ya hapa mimi itabidi kueleza code katika maslahi ya muda. Siyo kwamba code sana. Tunaona tunasoma tabia kutoka faili. Tuliihisabia f. Sasa unaweza mtu fgetc, lakini jinsi fgetc ni kwenda kufanya kazi ni tu ni kwenda na kurudi tabia ya kuwa wewe tu kusoma au EOF, ambazo zinahusiana na mwisho wa faili au baadhi likitokea kosa. Sisi ni looping, kuendelea kusoma tabia moja kutoka faili, mpaka tumekuwa kukimbia nje ya wahusika kusoma. Na wakati sisi ni kufanya hivyo, sisi kusubiri juu ya tabia moja kutoka kiwango in Kila wakati unapoandika kitu katika mstari amri, hiyo ni ya kusoma katika tabia kutoka kiwango in Kisha putchar ni kwenda tu kuweka Char tunasoma juu hapa kutoka faili nje ya kiwango. Unaweza mtu putchar, lakini ni kuweka tu kwa kiwango nje, ni uchapishaji kwamba tabia. Unaweza pia tu kufanya printf ("% c", c); Same wazo. Hiyo kwenda kufanya wingi wa kazi yetu. Jambo la mwisho tunakwenda wanataka kufanya ni tu fclose faili wetu. Kama huna fclose, hiyo leak kumbukumbu. Tunataka fclose faili sisi awali kufunguliwa, na nadhani hiyo ni yake. Kama sisi kufanya huo, mimi tayari got matatizo. Hebu angalia. Ni nini kulalamika kuhusu? Inatarajiwa 'int' lakini hoja ni ya aina ya 'struct _IO_FILE *'. Tutaweza kuona kama kwamba kazi. Kuruhusiwa tu katika C99. Augh. Okay, kufanya hacker_typer. Sasa sisi kupata maelezo muhimu zaidi. Hivyo matumizi ya kitambulisho Undeclared 'normal_settings'. Sikuweza kuiita normal_settings. Mimi kuitwa ni current_settings. Basi hebu mabadiliko yote. Sasa kupita hoja. Mimi itabidi kufanya hili 0 kwa sasa. Sawa. . / Hacker_typer cp.c. Mimi pia hakuwa wazi screen mwanzoni. Lakini unaweza kuangalia nyuma kwa kuweka mwisho tatizo kuona jinsi wewe wazi screen. Ni tu uchapishaji wahusika baadhi wakati hii ni kufanya nini nataka kufanya. Sawa. Na kufikiri kuhusu nini hii zinahitajika kuwa 0 badala ya stdin, ambayo inapaswa # define 0, hii ni kulalamika kwamba - Kabla ya wakati mimi alisema kwamba kuna faili descriptors lakini basi wewe pia kuwa JALADA yako *, descriptor faili ni tu integer moja, ambapo * JALADA ana rundo zima ya mambo yanayohusiana na hayo. sababu tunahitaji kusema 0 badala ya stdin ni kwamba ni stdin * JALADA ambayo inaelekeza kwamba ni jambo referencing faili descriptor 0. Hivyo hata hapa wakati mimi kufanya fopen (argv [1], nina kupata * JALADA nyuma. Lakini mahali fulani katika kwamba * JALADA ni kitu sambamba na descriptor faili kwa ajili ya faili hilo. Kama ukiangalia ukurasa mtu kwa ajili ya wazi, hivyo nadhani itabidi kufanya mtu 3 wazi - nope - mtu 2 wazi - yeah. Kama ukiangalia ukurasa kwa wazi, wazi ni kama fopen chini ya ngazi, na ni kurudi halisi faili descriptor. fopen gani rundo la stuff juu ya wazi, ambayo badala ya kurudi tu kwamba faili descriptor anarudi JALADA zima * pointer ndani ambayo ni faili wetu descriptor kidogo. Hivyo kiwango katika inahusu kitu * JALADA, ambapo 0 inahusu tu kiwango faili descriptor katika yenyewe. Maswali? [Atacheka] akapiga kupitia njia hiyo. Wote haki. Sisi ni kosa. [Atacheka] [CS50.TV]