[Powered by Google Translate] [Review] [Quiz 0] [Lexi Ross, Tommy MacWilliam, Lucas Freitas, Joseph Ong] [Universitato Harvard] [Jen CS50.] [CS50.TV] Hej, ĉiuj. Bonvenon al la revizio kunsido por Quiz 0, kiu okazas ĉi merkredo. Kion ni faros ĉi tiu nokto, mi estas kun 3 aliaj TFs, kaj kune ni tuj iru tra revizio de kion ni faris en la kurso ĝis nun. Oni ne tuj estos 100% kompleta, sed ĝi devus doni al vi pli bonan ideon tion, kion vi jam havas malsupren kaj kion vi ankoraŭ bezonas studi antaŭ merkredo. Kaj bonvolu levi vian manon kun demandoj kiel ni iras kune, sed memoru, ke ni ankaux havas iom da tempo al la fino- se ni finos pri kelkaj minutoj al libera-fari ĝeneralajn demandojn, tiel subteni ke en menso, kaj tial ni tuj komencos komence kun Semajno 0. [Kvizo 0 Review!] [Parto 0] [Lexi Ross] Sed antaŭ ol ni faras tion let parolu pri la aranĝon de la kvizo. [Logistics] [Quiz okazas merkrede 10/10 en loko de prelego] [(Vidu http://cdn.cs50.net/2012/fall/quizzes/0/about0.pdf por detaloj)] Estas merkrede, oktobro 10-a. Tio estas tio merkredo, kaj se vi iros al oriento URL tie, kiu estas ankaŭ atingebla de CS50.net-tie estas ligilo al ĝi- vi povas vidi informojn pri kien iri bazita sur via lasta nomo aŭ lernejo afiliación tiel kiel rakontas pri ĝuste kion la kvizo kovros kaj la tipoj de demandoj kiujn vi ricevos. Konsideru ke vi ankaŭ havas ŝancon por revizii por la kvizo en transeco, tiel viaj TFs devus iri super iu praktiko problemoj, kaj tio estas alia bona ŝanco por vidi kie vi ankoraŭ bezonas studi ĉe la kvizo. Ni komencu komence kun Bitoj 'n' Bytes. Memoru iom estas nur 0 aŭ 1, kaj bajto estas kolekto de 8 el tiuj bitoj. Ni rigardu ĉi tiu kolekto de bitoj ĉi tie. Ni devus kapabli kalkuli kiom da bitoj estas. Kie ni kalkulu tie estas nur 8 el ili, ok 0 aŭ 1 unuoj. Kaj ĉar ne estas 8 bitoj, jen 1 bajto, kaj ni konverti ĝin al deksesuma. Deksesuma estas bazo 16, kaj ĝi estas bela facile konverti numeron en duuma, kiu estas kiu tiu estas, al nombro en deksesuma. Ĉiuj ni estas ni rigardas grupoj de 4, kaj ni konverti ilin al la konvena deksesuma cifero. Ni komencu per la dekstra plej grupo de 4, do 0011. Tio tuj estos unu 1 kaj unu 2, do kune kiu faras 3. Kaj tiam ni rigardu la alia bloko de 4. 1101. Tio tuj estos unu 1, unu 4, kaj unu 8. Kune ke tuj estos 13, kiu faras D. Kaj ni memoru, ke en deksesuma ni ne nur iri 0 tra 9. Ni iru 0 tra F, do post 9, 10 korespondas al A, 11 al B, kaj tiel plu kie F estas la 15. Jen 13 estas D, tiel por konverti ĝin al dekuma ĉiuj ni estas ni efektive trakti ĉiu pozicio kiel povo de 2. Tio estas unu 1, unu 2, nula 4s, nula 8s, unu 16, kaj tiel plu, kaj estas iom malfacile kalkuli en la kapo, sed se ni iros al la venonta slide ni povas vidi la respondon al tio. Esence ni iras trans de dekstre al maldekstre, kaj ni multiplikante ĉiu cifero por la responda potenco de 2. Kaj memoru, por deksesuma ni signifi tiuj nombroj kun 0x komence tial ni ne konfuzu ĝin kun dekuma nombro. Daŭrigante on, ĉi tiu estas Askio Tabelo, kaj kion ni uzas ASCII por estas mapaj de karakteroj por nombraj valoroj. Memoru en la ĉifriko pset ni faris vastan uzon de la ASCII Tabelo por uzi diversajn metodojn de ĉifriko, Cezaro kaj la Vigenère, por konverti malsamaj literoj en ĉenon laŭ la ŝlosilo donita de la uzanto. Ni rigardu iom de ASCII math. Rigardante 'P' + 1, en karaktero formo kiu estus Q, kaj memoru, ke '5 '≠ 5. Kaj kiel precize devus ni konverti inter tiuj 2 formojn? Ne vere tro peza. Por akiri 5 ni subtrahi '0 ' ĉar estas 5 lokoj inter la '0 'kaj la '5'. Por iri la alia vojo ni simple aldonu la 0, do ĝi estas speco de kiel regula aritmetiko. Nur memoras ke kiam io estas citaĵoj ĉirkaŭ ĝi temas pri karaktero kaj tiel respondas al valoro en la ASCII tablo. Enirante en pli ĝenerala komputikaj temoj. Ni lernis kio algoritmo estas kaj kiel ni uzas programado apliki algoritmoj. Kelkaj ekzemploj de algoritmoj estas iu vere simpla kiel kontrolanta ĉu nombro estas para aŭ nepara. Por memori ni mod la nombro de 2 kaj kontroli, ĉu la rezulto estas 0. Se jes, ĝi estas vespero. Se ne, ĝi estas nepara. Kaj tio estas ekzemplo de vere baza algoritmo. Iom iom de pli implikitaj estas duuma serĉo, kiuj ni iros pli malfrue en la revizio kunsido. Kaj programado estas la termino kiun ni uzas por preni algoritmo kaj konvertado al kodi la komputilo povas legi. 2 Ekzemploj de programado estas Scratch, kiu estas kion ni faris en Semajno 0. Eĉ kvankam ni ne vere tajpi el la kodo ĝi estas vojo de apliko ĉi tiu algoritmo, kiu estas presi la numeroj 1-10, kaj tie ni fari same en la C programlingvo. Ĉi tiuj estas funkcie ekvivalentaj, ĝuste skribita en malsamaj lingvoj aŭ sintakso. Ni tiam lernis pri bulea esprimoj, kaj bulea estas valoro kiu estas ĉu vera aŭ malvera, kaj tie ofte bulea esprimoj iras ene de kondiĉoj, do se (x ≤ 5), bone, ni jam starigis x = 5, tiel ke kondiĉo tuj taksi al vera. Kaj se ĝi estas vera, kio ajn kodo estas sub la kondiĉo tuj estos taksitaj de la komputilo, por ke kordoj tuj estos presita al la normo eligo, kaj la termino kondiĉo referencas al kio ajn ene de la krampoj de la se aserto. Memoru ĉiuj operatoroj. Memoru ke estas && kaj | | kiam ni provas kombini 2 aŭ pli kondiĉoj, == Ne = por kontroli ĉu 2 aĵoj estas egalaj. Memoru ke = estas por atribuo dum == estas bulea operatoro. ≤, ≥, kaj poste la fina 2 estas mem-klarigan. Ĝenerala revizio de bulea logiko tie. Kaj bulea esprimoj estas ankaŭ grava en cikloj, kiuj ni transiru nun. Ni lernis pri 3 tipoj de cikloj ĝis nun en CS50, por, dum, kaj faru tempon. Kaj estas grave scii ke dum por pli celoj ni povas reale uzi ajnan tipon de buklo ĝenerale estas certaj tipoj de celoj aŭ komuna ŝablonoj en programado kiu specife vokas unu el tiuj cikloj kiuj faras ĝin la plej efika aŭ eleganta por kodi ĝin en tiu vojo. Ni transiru kion ĉiu el tiuj cikloj inklinas uzi por plej ofte. En a por buklo ni ĝenerale jam scias kiom da fojoj ni volas persisti. Tio estas kion ni metis en la kondiĉo. Ĉar, i = 0, i <10, ekzemple. Ni jam scias, ke ni volas fari ion 10-foje. Nun, dum tempo buklo, ĝenerale ni ne nepre scias, kiom da fojoj ni volas ke la buklo kuri. Sed ni scias ian kondiĉo, ke ni volas ke ĝi ĉiam esti vera aŭ ĉiam esti malvera. Ekzemple, dum estas metita. Diru, ke estas bulea variablo. Dum tio estas vera ni volas ke la kodo por taksi, do iom pli etendebla, iomete pli ĝenerala ol por ciklo, sed neniu por buklo povas ankaŭ esti konvertita al tempo buklo. Fine, do dum bukloj, kiu povas esti la trickiest kompreni tuj, estas ofte uzata, kiam ni volas taksi la kodo unua antaŭ la unua fojo ni kontrolu la kondiĉo. Komuna uzo kazo por fari dum buklo estas kiam oni volas akiri uzanto enigo, kaj vi scias, ke vi volas demandi al la uzanto por enigo almenaŭ unufoje, sed se ili ne donos al vi bonan eniron tuj vi volas teni petante ilin ĝis ili donos al vi la bonan enigo. Tio estas la plej komuna uzo de ĉu dum ciklo, kaj ni rigardu la efektiva strukturo de ĉi tiuj cikloj. Ili tipe ĉiam emas sekvi tiujn mastrojn. Sur la por buklo ene vi havas 3 komponantoj: inicialización, tipe iu kiel int i = 0 kie i estas la vendotablo, kondiĉo, kie ni volas diri kuri ĉi por buklo dum ĉi tiu kondiĉo ankoraŭ tenas, kiel i <10, kaj tiam fine, ŝanĝo, kiu estas kiel ni pliigo la vendotablo variablo en ĉiu punkto en la ciklo. Komuna afero vidi tie estas nur mi + +, kio signifas pliigo i per 1 ĉiufoje. Vi povus ankaŭ fari ion kiel i + = 2, kio signifas aldoni 2 al mi ĉiufoje vi iros tra la ciklo. Kaj tiam la fari ĉi nur aludas al iu kodo kiu vere kuras kiel parto de la ciklo. Kaj por momento buklo, ĉifoje ni efektive havas la inicialización ekster la buklo, tiel ekzemple, ni diras, ke ni provas fari la saman tipon de buklo kiel mi ĵus priskribis. Ni dirus int i = 0 antaŭ la buklo komencas. Tiam ni povus diri dum i <10 fari tion, do la sama bloko de kodo kiel antaŭe, kaj ĉi-foje la ĝisdatigo parto de la kodo, ekzemple, mi + +, reale iras ene de la ciklo. Kaj fine, por fari dum ĝi estas simila al la dum ciklo, sed ni devas memori ke la kodo taksos unufoje antaŭ la kondiĉo estas kontrolita, do ĝi faras multe pli sentita se vi rigardas ĝin en ordo de supro al malsupro. En fari dum buklo la kodo taksas antaŭ vi eĉ rigardi la dum kondiĉo, dum kelka tempo buklo, ĝi kontrolas unue. Deklaroj kaj variabloj. Kiam ni volas krei novan variablon ni unue volas pravalorizi ĝin. Ekzemple, int trinkejo inicializa la variablo trinkejo, sed ne doni valoron, do kio estas trinkejo valoro nun? Ni ne scias. Ĝi povus esti iu rubo valoro kiu estis antaŭe konservitaj en memoro tie, kaj ni ne volas uzi tiun variablon ĝis ni vere donas valoron, do ni deklaras ĝin ĉi tie. Tiam ni pravalorizi ĝin esti 42-sube. Nun, kompreneble, ni scias ĉi tiu povas esti farita en unu linio, int trinkejo = 42. Sed nur por esti klara la multnombraj paŝoj kiuj okazadas, la deklaro kaj la inicialización okazas aparte tie. Ĝi okazas en unu paŝo, kaj la sekva, int baz = trinkejo + 1, tiu deklaracio sube, ke pliigoj baz, do fine de ĉi tiu kodo bloko se ni devis presi la valoro de baz estus 44 ĉar ni deklaras kaj pravalorizi ĝin al esti 1> trinkejo, kaj poste ni pliigo ĝin refoje kun la + +. Ni iris super ĉi bela mallonge, sed estas bone havi ĝeneralan kompreno de kio fadenoj kaj eventoj. Ni ĉefe faris tion en Scratch, tiel vi povas pensi pri fadenoj kiel multnombraj sekvencoj de kodo kurante al la sama tempo. En realeco, ĝi probable ne ruliĝas samtempe, sed ia abstrakte oni povas pensi pri ĝi en tiu vojo. En Scratch, ekzemple, ni havis la multnombraj sprites. Ĝi povus ekzekuti malsamajn kodo samtempe. Unu povus promeni dum la alia diras ion en alia parto de la ekrano. Eventoj estas alia maniero de disigi ekster la logiko inter malsamaj elementoj de via kodo, kaj en Scratch ni povis simuli okazaĵoj uzante la Broadcast, kaj tio efektive Kiam mi Ricevu, ne Kiam mi Aŭskultu, sed esence estas maniero por transdoni informon de unu sprite al alia. Ekzemple, vi eble volas transdoni ludo finiĝis, kaj kiam alia sprite ricevas ludo finiĝis, respondas en certa maniero. Estas grava modelo por kompreni por programado. Nur, por transiri la baza Semajno 0, kion ni iris trans ĝis nun, ni rigardu tiun simplan C programon. La teksto estu iom malgranda el ĉi tie, sed mi tuj iros vere rapida. Ni inkludante 2 header files ĉe la supro, cs50.h kaj stdio.h. Ni tiam difini konstanta nomata limo por esti 100. Ni tiam apliki nia ĉefa funkcio. Ekde ni ne uzas komandlinio argumentoj tie ni bezonas meti void kiel la argumentojn por ĉefa. Ni vidas int supre ĉefa. Tio estas la reveno tipo, do reveni 0 je la fundo. Kaj ni uzas CS50 biblioteko funkcio get int demandi al la uzanto por enigo, kaj ni konservas ĝin en ĉi variablo x, do ni deklari x supre, kaj ni pravalorizi ĝin kun x = GetInt. Ni tiam kontrolu vidi se la uzanto donis al ni bonajn enigo. Se estas ≥ limo ni volas reveni eraro kodo de 1 kaj presi erarmesagxon. Kaj fine, se la uzanto donis al ni bonajn enigo ni iras al akordi la numeron kaj presi tiun rezulton. Nur por certigi ke tiuj ĉiuj sukceson hejmen vi povas vidi la etiketoj de malsamaj partoj de la kodo tie. Mi menciis konstanto, header files. Ho, int x. Certiĝu memori ke estas loka variablo. Tio kontrastas ĝin el fonto malloka variablo, kiu ni parolos pri iom poste en la revizio kunsido, kaj ni alvokas la biblioteko funkcio printf, do se ni ne inkludis la stdio.h kapdosiero ni ne povos nomi printf. Kaj mi kredas, la sago ke got detrancxis tie indikante la% d, kiu estas formatado ĉenon en printf. Ĝi diras presi ĉi variablo kiel nombro,% d. Kaj tio estas por Semajno 0. Nun Lucas tio daŭros. Hej, knaboj. Mia nomo estas Lucas. Mi estas sophomore en la pli bona domo campus, Mather, kaj mi tuj parolos iom pri Semajno 1 kaj 2.1. [Semajno 1 kaj 2,1!] [Lucas Freitas] Kiel Lexi estis diranta, kiam ni komencis traduki vian kodon de Scratch al C unu el la aĵoj kiuj ni rimarkis, ke vi ne povas simple skribi vian kodon kaj ruli ĝin uzante verda flago plu. Vere, vi devas uzi iujn paŝojn por fari viajn C programon fariĝu ruleblan dosieron. Esence, kion vi faras, kiam vi skribas programo estas ke vi traduki vian ideon al lingvo kiun kompililon povas kompreni, do kiam vi skribas programon en C kion vi faras vere skribi ion, ke via tradukilo tuj komprenas, kaj tiam la tradukilo tuj traduki tiu kodo en ion, ke via komputilo komprenos. Kaj la afero estas, via komputilo estas vere tre stulta. Via komputilo povas nur kompreni _0s_ kaj _1s_, do fakte en la unua komputiloj homoj ĝenerale planita uzante _0s_ kaj _1s_, sed ne plu, dank 'al Dio. Ni ne devas parkeri la sekvencoj por _0s_ kaj _1s_ por a por buklo aŭ por tempo loop kaj tiel plu. Tial ni havas tradukilo. Kia tradukilo faras estas esence tradukas la C-kodo, en nia kazo, al lingvo ke via komputilo komprenos, kio estas la objekto kodo, kaj la tradukilon, ke ni uzas nomas clang, do ĉi tiu estas vere la simbolo por clang. Kiam vi havas vian programon, vi devas fari 2 aĵoj. Unue, vi devas kompili vian programon, kaj tiam vi tuj kuri via programo. Por traduki via programo vi havas multajn eblojn por tion fari. La unua estas fari clang program.c en kiu programo estas la nomo de via programo. En ĉi tiu kazo vi povas vidi ili estas nur diras "Hej, kompili mia programo." Vi ne diras "mi volas ke tiu nomo por mia programo" aŭ io. La dua eblo, donas nomon al via programo. Vi povas diri clang-o kaj tiam la nomo kiun vi volas la ruleblan dosieron por esti nomata kiel kaj poste program.c. Kaj vi povas ankaŭ fari fari programon, kaj vidu, kiel en la unuaj 2 kazoj Mi metis. C, kaj en la tria mi nur havas programojn? Yeah, vi vere ne devas meti. C kiam vi uzas fari. Alie la tradukilo estas vere tuj krias al vi. Kaj ankaŭ, mi ne scias se vi infanoj memoras, sed multe da fojoj ni ankaŭ uzas-lcs50 aŭ-lm. Tio estas nomata kunligi. Ĝi simple rakontas la tradukilo, ke vi uzos tiujn bibliotekoj dekstra tie, do se vi volas uzi cs50.h vi vere devas tajpi clang program.c-lcs50. Se vi ne faras tion, la tradukilo ne tuj scias ke vi uzas tiujn funkciojn en cs50.h. Kaj kiam vi volas kuri via programo vi havas 2 eblojn. Se vi faris clang program.c vi ne donis nomon al via programo. Vi devas kuri ĝin uzante. / A.out. A.out estas normo nomo kiu clang donas via programo, se vi ne donas al ĝi nomon. Alie vi faros. / Programo se vi donis nomon al via programo, kaj ankaŭ se vi faris fari programon la nomo de programo tuj akiri Jam tuj plani la sama nomo kiel la c dosiero. Tiam ni parolis pri datumtipoj kaj datumojn. Esence datumtipoj estas la sama afero kiel iom skatoloj uzas stoki valorojn, tiel datumtipoj estas fakte ĝuste kiel Pokémons. Ili venas en ĉiuj grandecoj kaj tipoj. Mi ne scias se tiu analogio havas sencon. La datumoj grandeco fakte dependas de la maŝino arkitekturo. Ĉiuj datumoj grandecoj ke mi iros por montri ĉi tie estas fakte por 32-bita maŝino, kiu estas la kazo de nia aparaton, sed se vi vere kodigo Mac aŭ en Vindozo ankaŭ probable vi tuj havos 64-bita maŝino, do memori ke la datumoj grandecoj ke mi iros por montri ĉi tie estas por la 32-bita maŝino. La unua, kiun ni vidis estis int, kiu estas sufiĉe simpla. Vi uzas int stoki entjero. Ni vidis ankaŭ la karaktero, la signo. Se vi volas uzi leteron aŭ iom simbolo vi probable tuj uzi char. A char havas 1 bajto, kio signifas 8 bitoj, kiel Lexi diris. Esence ni havas ASCII Tabelo kiu havas 256 eblaj kombinoj de _0s_ kaj _1s_, kaj kiam vi tajpi babilas tuj traduki la karaktero kiu enigas vin numero kiu vi havas en la ASCII tablo, kiel Lexi diris. Ni havas ankaŭ la kaleŝego, kiun ni uzas por stoki decimalaj numeroj. Se vi volas elekti 3.14, ekzemple, vi tuj uzi kaleŝego aŭ duobla kiu havas pli precizeco. Al kaleŝego havas 4 bitokoj. Duobla havas 8 bajtoj, do la sola diferenco estas la precizeco. Ni ankaŭ havas longan kiu uzas por entjeroj, kaj vi povas vidi por 32-bita maŝino an int kaj longan havas la saman grandecon, do ĝi ne vere havas sencon uzi longan en 32-bita maŝino. Sed se vi uzas Mac kaj 64-bita maŝino, reale longan havas grandecon 8, tiel vere dependas de la arkitekturo. Por la 32-bita maŝino ne havas sencon uzi longan vere. Kaj poste longa longa, aliflanke, havas 8 bajtoj, tial estas tre bona se vi volas havi pli longa entjero. Kaj fine, ni havas ĉenon, kiu estas vere char *, kiu estas puntero al char. Estas tre facile kredi ke la grandeco de la kordo tuj estos kiel la nombro da karakteroj, ke vi havas tie, sed fakte la char * sin havas la grandecon de puntero al char, kiu estas 4 bitokoj. La grandeco de char * estas 4 bitokoj. Ne gravas se vi havas malgrandan vorton aŭ leteron aŭ nenion. Ĝi tuj estos 4 bitokoj. Ni ankaŭ lernis iomete pri malplenigita, tiel kiel vi povas vidi, se vi havas, ekzemple, programo kiu diras int x = 3 kaj do printf ("% d", x / 2) do you guys scias kio okazas al presi sur ekrano? Iu? >> [Studentoj] 2. 1. >> 1, yeah. Kiam vi faras 3/2 ĝi ​​tuj akiri 1,5, sed ekde ni uzas entjero ĝi tuj ignori la dekuma parto, kaj vi tuj havos 1. Se vi ne volas ke tio okazas, kion vi povas fari, ekzemple, estas deklari kaleŝego y = x. Tiam x kiu kutimis esti 3 nun tuj estos 3,000 en y. Kaj tiam vi povas presi la y / 2. Fakte, mi devus havi 2. tien. Oni faros 3.00/2.00, kaj vi tuj akiri 1,5. Kaj ni havas ĉi .2 f simple peti 2 dekuma unuoj en la dekuma parto. Se vi havas .3 f ĝi tuj devos vere 1,500. Se ĝi estas 2 tio tuj estos 1,50. Ni ankaŭ havas ĉi kazo tie. Se vi faras kaleŝego x = 3.14 kaj tiam vi printf x vi ricevos 3.14. Kaj se vi faros x = la int de x, kio signifas trakti x kiel int kaj vi presi x nun vi havos 3.00. Ĉu tio havas sencon? Ĉar vi unue trakti x kiel entjero, do vi ignorante la dekuma parto, kaj tiam vi presi x. Kaj fine, vi povas ankaŭ fari tion, int x = 65, kaj poste vi deklaras char c = x, kaj poste, se vi presas la c vi efektive ricevos A, do esence kion vi faras ĉi tie estas traduki la entjero en la karaktero, samkiel la ASCII Tabelo faras. Ni ankaŭ parolis pri matematikaj operatoroj. La plimulto de ili estas sufiĉe simpla, tial +, -, *, /, kaj ankaŭ ni parolis pri mod, kiu estas la resto de divido de 2 nombroj. Se vi havas 10% 3, ekzemple, ĝi signifas dividi 10 per 3, kaj kio estas la resto? Ĝi okazas al esti 1, do ĝi estas vere tre utila por multaj el la programoj. Por Vigenère kaj Cezaro mi sufiĉe certas ke vi ĉiuj infanoj uzas mod. Pri matematikaj operatoroj, esti tre zorgema kiam kombinante * kaj /. Ekzemple, se vi faras (3/2) * 2 kion vi intencas akiri? [Studentoj] 2. Yeah, 2, ĉar 3/2 estas tuj estos 1,5, sed cxar vi faras operaciojn inter 2 entjeroj vi fakte ĝuste tuj konsideri 1, kaj tiam 1 * 2 tuj estos 2, do estus tre, tre zorgema farinte aritmetiko kun entjeroj ĉar vi eble akiri ke 2 = 3, en tiu kazo. Kaj ankaŭ estus tre singarda pri prioritaton. Vi devus kutimas uzi krampojn por esti certa, ke vi scias kion vi faras. Kelkaj utilaj ŝparvojoj, kompreneble, estas mi + + aŭ mi + = 1 aŭ uzante + =. Tio estas la sama afero kiel faras mi = mi + 1. Vi ankaŭ povas fari i - aŭ mi - = 1, kiu estas la sama afero kiel i = i -1, io you guys uzi multon in por cikloj, almenaŭ. Ankaŭ, por *, se vi uzas * = kaj se vi faros, ekzemple, i * = 2 estas la samo kiel dirante i = i * 2, kaj la sama afero por divido. Se vi faras i / = 2 ĝi estas la sama afero kiel i = i / 2. Nun pri funkcioj. You guys lernis ke funkcioj estas tre bona strategio por savi kodo dum vi programado, do se vi volas fari la saman taskon en kodo denove kaj denove, probable vi volas uzi funkcio nur tiel vi ne devas kopii kaj almeti la kodo denove kaj denove. Fakte, ĉefa estas funkcio, kaj kiam mi montras al vi la formaton de funkcio vi tuj vidos, ke tio estas bela evidenta. Ni ankaŭ uzas funkcioj de kelkaj bibliotekoj, ekzemple, printf, GetIn, kiu estas el la CS50 biblioteko, kaj aliaj funkcioj kiel toupper. Ĉiuj el tiuj funkcioj estas vere implementado en aliaj bibliotekoj, kaj kiam vi metis tiujn tether dosieroj en la komenco de via programo Via diro povas bonvole doni al mi la kodo por tiuj funkcioj do mi ne devas apliki ilin per mi mem? Kaj vi povas ankaŭ skribi viajn proprajn funkciojn, do kiam vi komencos programado vi rimarkas ke bibliotekoj ne havas ĉiujn funkciojn kiujn vi bezonas. Por la lasta pset, ekzemple, ni skribis desegni, scramble, kaj lookup, kaj ĝi estas tre, tre grava por povi skribi funkciojn ĉar ili estas utilaj, kaj ni uzas ilin la tutan tempon en programado, kaj ĝi ŝparas multe da kodo. La formato de funkcio estas ĉi tiu. Ni havas reveno tipo en la komenco. Kio estas la reveno tipo? Estas nur kiam via funkcio tuj revenos. Se vi havas funkcion, ekzemple, faktorialo, kiu iras al kalkuli faktorialo de entjero, probable tuj revenos entjero ankaŭ. Tiam la reveno tipo tuj estos int. Printf reale havas reveno tipo void ĉar vi ne reveni nenion. Vi nur presi aĵojn al la ekrano kaj lasi la funkcio poste. Tiam vi havas la nomon de la funkcio kiun vi povas elekti. Vi devus esti iom prudenta, kiel ne elektas nomon kiel xyz aŭ kiel x2f. Provu konsistigas nomo kiu havas sencon. Ekzemple, se ĝi estas faktorialo, diru faktorialo. Se estas funkcio kiu tuj desegni ion, nomu ĝin desegni. Kaj tiam ni havas la parametroj, kiuj estas ankaŭ nomita argumentoj, kiuj estas kiel la rimedojn por ke via funkcio bezonas de via kodo por realigi lian taskon. Se vi volas kalkuli la faktorialon de nombro probable vi bezonas havi kelkajn kalkuli faktorialo. Unu el la argumentoj, ke vi havos estas la nombro mem. Kaj tiam ĝi tuj fari ion kaj redoni la valoron je la fino krom se ĝi estas malplena funkcio. Ni vidu ekzemplon. Se mi volas skribi funkcio kiu resumas ĉiujn numerojn en tabelo de entjeroj, unue, la reveno tipo tuj estos int ĉar mi havas aron de entjeroj. Kaj poste mi iros al havi la funkcio nomo kiel sumArray, kaj tiam tuj prenos la tabelo mem, por int nums, kaj tiam la longo de la tabelo do mi scias, kiom da ciferoj Mi devas resumi. Tiam mi devas pravalorizi variablo nomata sumo, ekzemple, al 0, kaj ĉiufoje mi vidas ero en la tabelo mi aldonu ĝin al sumo, do mi faris por buklo. Samkiel Lexi diris, vi faru int i = 0, i 0 tiam ĝi estas pozitiva. Se ĝi estas = al 0 tiam ĝi estas 0, kaj se estas <0 tiam ĝi estas negativa. Kaj la aliaj unu faras se, alie se, alian. La diferenco inter la du estas, ke ĉi tiu estas vere tuj kontroli ĉu> 0, <0 aŭ = 0 tri fojojn, do se vi havas la numeron 2, ekzemple, ĝi tuj venas tie kaj diru if (x> 0), kaj ĝi tuj diri jes, do mi presi pozitiva. Sed kvankam mi scias ke ĝi estas> 0 kaj ĝi ne iras al esti 0 aŭ <0 Mi ankoraŭ volas fari estas 0, estas <0, do mi vere iras ene de IFS ke mi ne devis ĉar mi jam scias ke ĝi ne iras por kontentigi iun el ĉi tiuj kondiĉoj. Mi povas uzi la se, alie se, alie komunikaĵo. Ĝi esence diras se x = 0 mi presi la pozitiva. Se ĝi ne estas, mi tuj ankaŭ testi tion ĉi. Se ĝi estas 2 ne mi faros tion. Esence, se mi havis x = 2 vi dirus if (x> 0), jes, do presi ĉi. Nun ke mi scias, ke ĝi estas> 0 kaj ke ĝi kontentigis la unua se Mi eĉ ne tuj kuri ĉi tiu kodo. La kodo kuras pli rapide, fakte, 3 fojojn pli rapide se vi uzas ĉi. Ni ankaŭ lernis pri kaj kaj aŭ. Mi ne tuj iros tra ĉi ĉar Lexi jam parolis pri ili. Estas nur la && kaj | | operatoro. La sola afero, mi diras estas singardi kiam oni havas 3 kondiĉojn. Uzu krampoj ĉar ĝi estas tre konfuza kiam vi havas kondiĉo kaj alia aŭ alia. Uzu krampoj nur por esti certa ke via kondiĉoj sencon ĉar en tiu kazo, ekzemple, vi povas imagi ke povus esti la unua kondiĉo kaj unu aŭ la alia aŭ la 2 kondiĉoj kombinis en kaj aŭ la tria, tiel simple zorgu. Kaj fine, ni parolis pri ŝaltiloj. Al ŝaltilo estas tre utila kiam vi havas variablo. Diru, ke vi havas variablo kiel n kiu povas esti 0, 1, aŭ 2, kaj por ĉiu el tiuj kazoj vi tuj realigi taskon. Vi povas diri ŝanĝi la variablo, kaj ĝi indikas, ke la valoro tiam estas kiel value1 Mi faros tion, kaj tiam mi rompos, kio signifas ke mi ne tuj rigardi iun de la aliaj kazoj ĉar ni jam kontenta tiu kazo kaj tiam value2 kaj tiel plu, kaj mi ankaŭ povas havi defaŭlta ŝaltilon. Tio signifas, se ĝi ne kontentigas iun el la kazoj kiujn mi havis ke mi tuj faru ion alian, sed tio estas laŭvola. Tio estas ĉio por mi. Nun ni havas Tommy. Bone, ĉi tiu tuj estos Semajno 3-ish. Ĉi tiuj estas kelkaj el la temoj ni povas kovri, kripto, atingo, tabeloj, kaj tiel plu. Nur rapidan vorto sur kripto. Ni ne tuj martelo ĉi hejmo. Ni faris tion en pset 2, sed por la kvizo certigi vi scias la diferenco inter la cezaro kodita kaj la Vigenère, kiel ambaŭ el tiuj koditaj laboro kaj kio estas kiel por ĉifri kaj deĉifri teksto uzante tiujn 2 ĉifroj. Memoru, la cezaro kodita simple turnas ĉiu karaktero de la sama kvanto, certigante vin mod per la nombro de literoj en la alfabeto. Kaj la Vigenère, aliflanke, turnas ĉiu karaktero per malsama kvanto, do anstataŭ diri ĉiun karakteron turnita per 3 Vigenère rotará ĉiu karaktero per malsama kvanto depende iuj ŝlosilvorto kie ĉiu litero en la ŝlosilvorto reprezentas iun malsama kvanto turni la klara teksto de. Ni unue diskuto pri variablo medion. Estas 2 malsamaj tipoj de variabloj. Ni havas lokajn variablojn, kaj ĉi tiuj tuj esti difinita eksteren de ĉefa aŭ ekster iu funkcio aŭ bloko, kaj ĉi tiuj estos atingebla ie ajn en via programo. Se vi havas funkcion kaj en tiu funkcio estas dum buklo la granda tutmonda variablo estas atingebla ĉie. Loka variablo, aliflanke, estas scoped al la loko kie ĝi estas difinita. Se vi havas funkcion tie, ekzemple, ni havas ĉi tiun funkcion g, kaj ene de g estas variablo tie nomis y, kaj tio signifas ke ĉi tiu estas loka variablo. Kvankam ĉi variablo y estas nomata kaj ĉi variablo estas nomita y tiuj 2 funkcioj Ne havas ideon kion ĉiu alia loka variabloj estas. Aliflanke, tien ni diras int x = 5, kaj ĉi tiu estas ekster la medio de ajna funkcio. Estas ekstere la medio de ĉefa, do ĉi tiu estas malloka variablo. Tio signifas ke ene de tiuj 2 funkciojn kiam mi diras x - aŭ x + + Mi konsentas la sama x per ĉi y kaj y ĉi estas malsamaj variabloj. Tio estas la diferenco inter malloka variablo kaj loka variablo. Koncerne dezajno raportas, foje ĝi estas probable bona ideo teni variabloj lokaj kiam ajn vi eble povas ekde havi faskon de tutmonda variabloj povas akiri vere malklara. Se vi havas aron da funkcioj ĉiuj modifante la saman aferon vi eble forgesi kion se tiu funkcio hazarde modifas ĉi tutmonda, kaj tiu alia funkcio ne scias pri tio, kaj ĝi oni multe konfuza kiel vi ricevas pli kodo. Subtenante variabloj lokaj kiam ajn vi eble povas estas nur bona dezajno. Arrays, memoru, estas simple listoj de eroj de la sama tipo. Ene de CI ne povas havi liston kiel 1, 2.0, saluton. Ni tute ne povas fari tion. Kiam ni deklaras tabelo en C ĉiuj elementoj devas esti de la sama tipo. Jen mi havas aron de 3 entjeroj. Jen mi havas la longon de la tabelo, sed se mi simple deklarante ĝin en multaj lingvoj kie mi precizigi kion ĉiuj eroj estas ne teknike bezonas tiun 3. La tradukilo estas sufiĉe inteligenta por elkompreni kiel granda la tabelo devas esti. Nun, kiam mi volas aŭ aro de la valoro de tabelo ĉi tiu estas la sintakson por fari tion. Tio efektive modifas la dua ero de la tabelo ĉar, memoru, kalkulado komenciĝas je 0, ne 1. Se mi volas legi tiun valoron mi povas diri ion kiel int x = array [1]. Aŭ se mi volas meti tiun valoron, kiel mi faras ĉi tie, Mi povas diri tabelo [1] = 4. Tiu epoko alirante elementoj laŭ iliaj indekso aŭ ilia pozicio aŭ kie ili estas en la tabelo, kaj tio de kantoj startas je 0. Ni povas ankaŭ havi tabeloj de tabeloj, kaj ĉi nomiĝas _multi_-dimensia tabelo. Kiam ni havas multi-dimensia tabelo tio signifas ke ni povas havi iun kiel vicoj kaj kolumnoj, kaj ĉi tiu estas nur unu vojo de bildiganta tiu aŭ pensi pri ĝi. Kiam mi havas multi-dimensia tabelo kiu signifu mi tuj komencos bezoni pli ol 1 indekso ĉar se mi havas krado nur diras kion vico vi estas en ĝi ne donas al ni nombro. Tio vere nur tuj donos al ni liston de nombroj. Diru Mi havas ĉi tabelo tie. Mi havas tabelo nomis krado, kaj mi diris ke estas 2 vicoj kaj 3 kolumnoj, kaj tiel ĉi tiu estas unu formo de bildiganta ĝin. Kiam mi diras, ke mi volas ricevi la elemento en [1] [2] tio signifas, ke pro tiuj estas vicoj unua kaj tiam kolumnoj Mi tuj salti al remi 1 pro tio mi diris 1. Tiam mi tuj venos ĉi tien por kolumno 2, kaj mi iros por ricevi la valoron 6. Sencon? Multi-dimensia arrays, memoru, estas teknike nur tabelo de tabeloj. Ni povas havi tabeloj de tabeloj de tabeloj. Ni povas gardi tuj, sed vere oni maniero pensi kiel tiu estas metita ekstere kaj kio okazas estas bildigi ĝin en krado ŝatas tion. Kiam ni pasis arrays al funkcioj, ili tuj konduti iom malsame ol kiam ni pasas regula variabloj al funkcioj kiel pasas la int aŭ kaleŝego. Kiam ni pasis en int aŭ char nek iu ajn el ĉi tiuj aliaj datumtipoj ni simple prenis rigardi se la funkcio modifas la valoro de tiu variablo kiu ŝanĝo ne tuj propagi supren al la nomante funkcio. Kun tabelo, aliflanke, tio okazos. Se mi pasas en tabelo por iu funkcio kaj tiu funkcio ŝanĝas kelkajn el la elementoj, kiam mi revenos supren al la funkcio kiu nomis ĝin mia tabelo nun tuj estos malsama, kaj la vortaro por tiu Estas tabeloj estas pasitaj por referenco, kiel ni vidos poste. Ĉi tiu estas rilatanta al kiel punteros laboro, kie ĉi tiuj bazaj datumtipoj, aliflanke, estas transdonata de valoro. Ni povas pensi ke kiel fari kopion de iu variablo kaj tiam pasante en la kopio. Ne gravas kion ni faras kun tiu variablo. La nomi funkcio ne konscii ke tio estis ŝanĝita. Arrays estas malmulta malsamaj en tiu rilate. Ekzemple, kiel ni ĵus vidis, ĉefa estas simple funkcio kiu povas preni en 2 argumentojn. La unua argumento al la ĉefa funkcio estas argc, aŭ la nombro de argumentoj, kaj la dua argumento nomiĝas argv, kaj tiuj estas la realaj valoroj de tiuj argumentoj. Diru Mi havas programon nomata this.c, kaj mi diras fari tion, kaj mi iros por kuri ĉi ĉe la komandlinio. Nun pasi en iuj argumentoj al mia programo nomata ĉi, Mi povus diri iun kiel. / Tiu estas cs 50. Jen kion ni imagas Davido fari ĉiutage ĉe la stacio. Sed nun la ĉefa funkcio ene de tiu programo havas tiujn valorojn, tiel argc estas 4. Ĝi povus esti iom konfuza ĉar vere ni nur pasante en estas cs 50. Tio estas nur 3. Sed memoru ke la unua ero de argv aŭ la unua argumento estas la nomo de la funkcio mem. Do tio signifas ke ni havas 4 aĵoj ĉi tie, kaj la unua elemento tuj estos. / ĉi. Kaj tiu estos reprezentita kiel linio. Tiam la ceteraj eroj estas kion ni tajpis en laux la nomo de la programo. Do ĝuste kiel la rando, kiel ni probable vidis en pset 2, memoru ke la ŝnuro estas 50 ≠ la entjero 50. Do ni ne povas diri ion kiel, 'int x = argv 3.' Tio simple ne tuj havas sencon, ĉar ĉi estas ĉeno, kaj ĉi tiu estas entjero. Do se vi volas konverti inter la 2, memoru, ni iras al havas tiun magian funkcio nomita atoi. Kiu prenas ĉenon kaj redonas la entjero reprezentis ene de tiu linio. Por ke estas facila eraro fari en la kvizo, nur pensante ke tio estos aŭtomate esti la ĝusta tipo. Sed ĝuste scias ke ĉi tiuj ĉiam estos kordoj eĉ se la kordo nur enhavas entjero aŭ karaktero aŭ kaleŝego. Do nun ni parolu pri rula tempo. Kiam ni havas ĉiujn tiujn algoritmoj kiuj faras cxion cxi freneza aferojn, ĝi iĝas vere utila por demandi la demandon, "Kiel longe vi prenas?" Ni reprezentas ke kun iu nomita asimptota skribmaniero. Do tio signifas ke - nu, diru ni donos niajn algoritmo iuj vere, vere, vere granda enigo. Ni volas demandi al la demando "Kiom longe ĝi tuj prenos? Kiom da ŝtupoj oni bezonas nian algoritmon por kuri kiel funkcio de la grandeco de la eniga? " Do la unua maniero ni povas priskribi kuri horo estas kun granda O. Kaj jen estas nia plej malbona-kazo kurado tempo. Do, se ni volas ordigi tabelo, kaj ni donos niajn algoritmo tabelo jen en malsuprenira ordon kiam devus esti en kreska ordo, ke okazas al esti la plej malbona kazo. Ĉi tiu estas nia supera baro en la maksimuma longeco de tempo nia algoritmo prenos. Aliflanke, ĉi Ω tuj priskribi plej kazo rula tempo. Do, se ni donas jam ordo tabelo al ordiga algoritmo, kiom da tempo oni bezonas ordigi ĝin? Kaj jen, do, priskribas suba baro sur rula tempo. Do jen estas nur iuj vortoj kiuj priskribas iujn komunajn kurante foje. Ĉi tiuj estas en suprenira ordo. La plej rapida rula tempo ni havas estas nomita konstanto. Tio signifas ne gravas kiom da eroj ni donos niajn algoritmo, kiel ajn granda nia tabelo estas, ordigi ĝin aŭ farante ajn ni faras al la tabelo estos ĉiam preni la sama kvanto de tempo. Do ni povas reprezenti ke nur kun 1, kiu estas konstanto. Ni ankaŭ rigardis logaritma tempo de ekzekuto. Do iu kiel duuma serĉo estas logaritma, kie ni tranĉis la problemo en duono ĉiufoje kaj tiam aĵoj simple akiri pli alta de tie. Kaj se vi iam verkas ho de ajna faktorialo algoritmo, vi probable ne devus konsideri tion kiel vian laboron. Kiam oni komparas kurante fojoj ĝi estas grave konsideri tion. Do, se mi havas algoritmon tio O (n), kaj iu alia estas algoritmo de O (2n) tiuj estas fakte asimptote ekvivalento. Do, se ni imagi n esti granda nombro kiel dekunu milionoj: do kiam ni komparas dekunu milionoj al iu kiel dekunu miliardoj + 3, subite ke +3 ne vere faras grandan diferencon plu. Tial ni tuj komencos konsideri tion al esti ekvivalento. Do aliaj similaj konstantaj tie, tie estas 2 × ĉi, aŭ aldonante 3, tiuj estas nur konstantaj, kaj ĉi tiuj tuj faligi supren. Tial do ĉiu 3 de tiuj run horoj estas la sama kiel diri ke ili estas O (n). Simile, se ni havas 2 aliajn run tempoj, diru O (n ³ + 2n ²), ni povas aldoni + N, + 7, kaj tiam ni havi alia tempo de ekzekuto tio estas nur O (n ³). denove, tio estas la sama afero ĉar tiuj - tiuj ne estas la sama. Tio estas la sama aĵoj, sorry. Do tio estas la sama ĉar ĉi n ³ tuj regi ĉi 2n ². Kio ne estas la sama afero estas se ni kuros tempoj kiel O (n ³) kaj O (n ²) ĉar ĉi n ³ estas multe pli granda ol tiu n ². Do, se ni havas eksponentoj, subite ĉi komencas gravas, sed kiam ni simple pritraktas faktoroj kiel ni estas ĉi tie, tiam ne iras al gravas ĉar estas ĝuste tuj forlasi. Ni rigardu kelkajn el la algoritmoj ni vidis ĝis nun kaj paroli pri siaj tempo de ekzekuto. La unua maniero de serĉi numeron en listo, kiun ni vidis, estis lineara serĉo. Kaj la efektivigo de lineara serĉo is super simpla. Ni nur havas liston, kaj ni iras al rigardi ĉiu unuopa elemento en la listo ĝis ni trovos la nombro ni serĉas. Do tio signifas ke en la plej malbona kazo, ĉi O (n). Kaj la plej malbona kazo tie povus esti se la ero estas la lasta elemento, tiam uzanta lineara serĉo, ni devas en ĉiu sola ero ĝis ni atingos la lasta por scii ke estis vere en la listo. Ni ne povas simple forlasi duonvoje, kaj diros: "Estas probable ne ekzistas." Kun lineara serĉo ni devas rigardi la tutan aferon. La plej kazo kurado tempo, aliflanke, estas konstanta ĉar en la plej bona kazo la elemento ni serĉas estas nur la unua en la listo. Do ĝi estas tuj prenos al ni precize 1 paŝo, kiel ajn granda la listo estas se ni serĉas la unua elemento ĉiufoje. Do kiam vi serĉi, memoru, ĝi ne postulas, ke nia listo povas ordo. Ĉar ni simple tuj serĉos sur cxiu unuopa elemento, kaj ĝi ne vere gravas kiu ordo tiuj eroj estas in Pli inteligenta serĉo algoritmo estas io kiel duuma serĉo. Memoru, la apliko de duuma serĉo estas kiam vi iras al teni rigardante la mezo de la listo. Kaj ĉar ni rigardas la mezo, ni postulas, ke la listo estas ordigita alie ni ne scias kie la meza estas, kaj ni devas pli la tuta listo trovi ĝin, kaj poste en tiu punkto ni simple perdi tempon. Do, se ni havas ordo listo kaj ni trovos la mezo, ni tuj kompari la mezo al la elemento ni serĉas. Se ĝi estas tro alta, tiam ni povas forgesi la dekstra duono ĉar ni scias, ke se nia ero estas jam tro alta kaj ĉiu al la rajto de tiu elemento estas eĉ pli alten, tiam ni ne bezonas rigardi tie plu. Kie aliflanke, se nia ero estas tro malalta, ni scias ĉion maldekstren de tiu elemento estas ankaŭ tro malalta, do ĝi ne vere havas sencon por rigardi tie, ĉu. Tiel, kun ĉiu paŝo kaj ĉiufoje ni rigardas la mezpunkto de la listo, ni iras al tranĉi nia problemo en duono ĉar subite ni scias tuta aro da nombroj, ke ne povas esti tiu, ni serĉas. En _pseudocode_ ĉi tio aspektas io tiamaniere, kaj ĉar ni tranĉante la listo en duono ĉiu sola fojo, nia plej malbona-kazo tempo de ekzekuto saltas de lineara al logaritma. Tiel subite ni havas logo-en paŝojn por trovi elementon en lerta. La plej kazo kurado tempo, tamen, estas ankoraŭ konstanta ĉar nun, ni simple diri, ke la elemento ni serĉas estas ĉiam la ĝusta mezo de la originala listo. Do ni povas kreski nia listo tiel grandaj kiel ni volas, sed se la elemento ni serĉas estas en la mezo, tiam ĝi estas nur tuj porti nin 1 paŝo. Do jen kial ni estas O (log n) kaj Ω (1) aŭ konstanto. Ni efektive kuris duuma serĉu per tiu listo. Do diru ke ni serĉas la elemento 164. La unua afero tuj fari estas trovi la mezpunkto de tiu listo. Simple tiel okazas ke la mezpunkto tuj falos en inter tiuj 2 nombroj, do ni nur arbitre diras, ĉiufoje kiam la mezpunkto falas inter 2 nombroj, ni nur ĉirkaŭ supren. Ni nur bezonas certigi ni faros ĉi ĉiu paŝo de la vojo. Do ni tuj ĉirkaŭprenis, kaj ni tuj diru, ke 161 estas la mezo de nia listo. Do 161 <164, kaj ĉiu ero al la maldekstra de 161 Ankaŭ <164, do ni scias ke ĝi ne iras por helpi nin en ĉiuj komenci transrigardante tie ĉar la elemento oni serĉas ne povas esti tie. Do kion ni povas fari estas ni povas simple forgesu pri tiu tuta maldekstra duono de la listo, kaj nun nur konsideri de la rajto de la 161 antaŭen. Do denove, ĉi tiu estas la mezpunkto; ni nur ĉirkaŭ supren. Nun 175 estas tro granda. Do ni scias ne iras por helpi nin rigardi tie aŭ ĉi tie, do ni povas simple ĵeti ke for, kaj eventuale ni batis la 164. Demandojn sur duuma serĉo? Ni movi sur la esplorrigardo tra jam-ordo listo al reale preni listo de nombroj en iu ajn ordo kaj farante ke lerta en suprenira ordo. La unua algoritmo ni rigardis nomis bobelo varon. Kaj ĉi tio estus pli simpla de la algoritmoj ni vidis. Bobelo speco diras ke kiam ajna 2 eroj ene de la listo estas maloportune, signifo estas pli alta numero al la maldekstra de malsupera numeron, tiam ni tuj interŝanĝi ilin, ĉar tio signifas ke la listo estos "Pli ordo" ol estis antaŭe. Kaj ni nur daŭros tiu procezo denove kaj denove kaj denove ĝis fine la elementoj ia bobelo al lia ĝentila situo kaj ni havas ordo listo. La tempo de ekzekuto de ĉi tiu tuj estos O (n ²). Kial? Nu, ĉar en la plej malbona kazo, ni iras preni ĉiu ero, kaj nin tuj finos kompari ĝin al ĉiu alia ero en la listo. Sed en la plej bona kazo, ni havas jam ordo listo, bobelo speco de nur tuj iros tra unufoje, diri "Nope. Mi ne faris ajnan svopoj, do mi faris." Do ni havas plej kazo rula tempo de Ω (n). Ni kuras bobelo speco sur listo. Aŭ unua, ni nur rigardas iujn _pseudocode_ vere rapide. Ni volas ke ni volas konservi trako de, en ĉiu ripeto de la ciklo, teni spuri de ĉu ni ŝanĝis ajna elementoj. Do la kialo estas, ni tuj haltos kiam ni ne interŝanĝis ajna elementoj. Do je la komenco de nia ciklo ni ne interŝanĝis nenion, do ni diros, ke estas falsaj. Nun, ni tuj iru tra la listo kaj kompari elemento i al elemento i + 1 kaj se ĝi estas la kazo, ke estas pli granda numero al la maldekstra de pli malgranda nombro, tiam ni ĵus tuj interŝanĝi ilin. Kaj poste ni iras al memori, ke ni interŝanĝis ero. Tio signifas ke ni devas iri tra la listo almenaŭ ankoraŭ 1 horo ĉar la kondiĉo, en kiu ni haltis estas kiam la tuta listo estas jam ordo, signifo ni ne faris ajnan svopoj. Tial do, nia kondiĉo cxi tie estas 'dum iuj elementoj estis svopitaj.' Do nun ni simple rigardi tiun kurante sur listo. Mi havas la liston 5,0,1,6,4. Bobelo speco tuj komenci la tuta vojo al la maldekstra, kaj ĝi tuj kompari la i elementoj, do 0 al mi + 1, kio estas ero 1. Oni intencis diri, bone 5> 0, sed nun 5 estas maldekstre, do mi bezonas interŝanĝi la 5 kaj la 0. Kiam mi interŝanĝi ilin, subite I get this malsamaj listo. Nun 5> 1, do ni tuj interŝanĝi ilin. 5 ne> 6, do ni ne bezonas fari ion tie. Sed 6> 4, do ni bezonas interŝanĝi. Denove, ni bezonas kuri tra la tuta listo por eventuale eltrovi ke tiuj estas el ordon; ni interŝanĝi ilin, kaj je ĉi tiu punkto ni devas kuri tra la listo ankoraŭ 1 horo certigi ke ĉiu estas en lia ordono, kaj je ĉi tiu punkto bobelo varo finita. Malsama algoritmo por preni iujn elementojn kaj ordigi ilin estas elekto varon. La ideo malantaŭ selektado varo estas, ke ni tuj konstruos al ordo parton de la listo 1 ero samtempe. Kaj la vojon ni tuj faros kiu estas por la konstruo de la maldekstra segmento de la listo. Kaj esence, ĉiu - sur ĉiu paŝo, ni iras preni la plej malgranda ero ni forlasis kiu ne estis ordo ankoraŭ, kaj ni iras al movi gxin en tiu ordo segmento. Tio signifas ke ni bezonas senĉese trovi la minimuma unsorted elemento kaj tiam preni tiun minimuman elementon kaj interŝanĝi ĝin kun kion ajn forlasis-plej ero kiu ne ordo. La tempo de ekzekuto de ĉi tiu tuj estos O (n ²) ĉar en la plej malbona kazo ni bezonas kompari ĉiun elementon al ĉiu alia ero. Ĉar ni diras ke se ni starti je la maldekstra duono de la listo, ni bezonas iri tra la tuta dekstra segmento por trovi la plej malgranda ero. Kaj tiam, denove, ni devas iri super la tuta dekstra segmento kaj teni tuj super tiu super kaj denove kaj denove. Tio okazas al esti n ². Ni tuj bezonas por buklo ene de alia por buklo kio sugestas n ². En la plej bona kazo penso, diru ni donu al ĝi jam ordo listo; ni efektive ne faras pli bone ol n ². Ĉar elekto varo havas neniun manieron de scii ke la minimuma ero estas nur la unu mi okazi esti rigardante. Ĝi ankoraŭ bezonas certigi ke ĉi tio estas vere la minimumo. Kaj la sola maniero certigi, ke ĝi estas la minimumo, uzante tiun algoritmon, estas serĉi en ĉiu sola ero denove. Do vere, se vi donas ĝin - se vi donos elekton speco jam ordo listo, ĝi ne faros estas pli bona ol doni ĝin listo kiu ne ordo ankoraŭ. Parenteze, se hazarde estas la kazo, ke io estas O (iu) kaj la omega de io, oni povas simple diri pli koncize, ke ĝi estas θ de iu. Do se vi vidas ke venu ie, ke estas kio ke ĝuste signifas. Se io estas theta de n ², ĝi estas kaj granda O (n ²) kaj Ω (n ²). Do bona kazo kaj plej malbona kazo, ĝi ne faras diferencon, la algoritmo tuj faros la samon ĉiufoje. Do ĉi tiu estas kion _pseudocode_ por selektado speco povus aspekti. Ni esence intencas diri ke mi volas persisti super la listo de maldekstre al dekstre, kaj je ĉiu ripeto de la ciklo, mi iros por movi la minimuma ero en ĉi ordo parton de la listo. Kaj iam mi movi ion tie, mi neniam devas rigardi tiun elementon denove. Ĉar kiam mi interŝanĝi ero en la maldekstra segmento de la listo, ĝi estas ordo ĉar ni faras ĉion en suprenira ordon uzante minimumoj. Do ni diris, estas bone, ni estas en la pozicio i, kaj ni devas rigardi ĉiujn elementojn al la dekstra de i por trovi la minimumo. Do tio signifas ke ni volas rigardi el i + 1 al la fino de la listo. Kaj nun, se la elemento kiu ni aktuale rigardante estas malpli ol nia minimuma ĝis nun, kiu, memoru, ni ekde la minimuma ekstere al nur esti kion ajn elementon ni aktuale ĉe; Mi supozas ke estas la minimumo. Se mi trovos elemento kiu estas pli malgranda ol tiu, tiam mi intencis diri, estas bone, bone, mi trovis novan minimumo. Mi tuj memori kie tiu minimumo estis. Do nun, unu fojon mi iris tra tiu rajto unsorted segmento, Mi povas diri mi iros por interŝanĝi la minimuma elemento kun la elemento kiu estas en pozicio i. Tio okazas por konstrui mian liston, mia ordo parton de la listo de maldekstre al dekstre, kaj ni ne cxiam bezonas rigardi ero denove iam estas en tiu parto. Iam ni interŝanĝis ĝin. Do ni kuros selektado speco sur tiu listo. La blua elemento tie tuj estos la i, kaj la ruĝa elemento tuj estos la minimuma elemento. Do mi startas la tuta vojo al la maldekstra de la listo, do ĉe 5. Nun ni bezonas trovi la minimuman unsorted elemento. Do ni diru 0 <5, tiel 0 estas mia nova minimumo. Sed mi ne povas halti tie, ĉar kvankam ni povas agnoski, ke 0 estas la plej malgranda, ni bezonas kuri tra ĉiu alia ero de la listo por certiĝi. Do 1 estas pli grandaj, 6 estas pli granda, 4 estas granda. Tio signifas, ke post rigardi ĉiujn tiujn elementojn, mi determinis 0 estas la plej malgranda. Do mi iros por interŝanĝi la 5 kaj la 0. Iam mi interŝanĝi ke, mi iros akiri novan liston, kaj mi scias ke mi neniam devas rigardi ke 0 denove ĉar unufoje mi interŝanĝis ĝin, mi ordo kaj ni faris. Nun nur tiel okazas, ke la blua elemento estas denove la 5, kaj ni bezonas rigardi la 1, la 6 kaj la 4 determini ke 1 estas la plej malgranda minimuma elemento, do ni devos interŝanĝi la 1 kaj la 5. Denove, ni bezonas rigardi - kompari la 5 al la 6 kaj la 4, kaj ni tuj interŝanĝi la 4 kaj la 5, kaj fine, kompari tiuj 2 nombroj kaj interŝanĝi ilin ĝis ni atingos nian ordo listo. Demandojn sur selektado speco? Okay. Ni movi al la lasta temo ĉi tie, kaj tiu estas rekursio. Rekursio, memoru, estas ĉi vere meta afero kie funkcio ree nomas sin. Do en iu momento, dum nia fuction estas ree sin nomas, tie devas esti iu punkto en kiu ni haltas nomante nin mem. Ĉar se ni ne faros tion, tiam ni ĵus tuj daŭre fari tion por ĉiam, kaj nia programo estas simple ne tuj finiĝi. Ni nomas tiun ĉi kondiĉon la bazo kazo. Kaj la bazo kazo diras, anstataŭ nomi funkcio denove, Mi nur tuj revenos iun valoron. Do iam ni revenis valoro, ni haltis nomante nin, kaj la resto de la alvokoj ni faris ĝis nun ankaŭ povas reveni. La malo de la bazo kazo estas la rekursiaj kazo. Kaj jen estas, kiam ni volas fari alian alvokon al la funkcio kiun ni aktuale in Kaj ni probable, kvankam ne ĉiam, volas uzi malsamajn argumentojn. Do, se ni havas funkcion nomis f, kaj f ĵus nomis prenu 1 argumento, kaj ni simple observu nomante f (1), f (1), f (1), kaj ĝi nur tiel okazas ke la argumento 1 falas en rekursie kazo, ni ankoraŭ neniam tuj halti. Eĉ se ni havas bazon kazo, ni bezonas certigi ke eventuale ni iras por bati tiu bazo kazo. Ni ne nur konservi restante en ĉi rekursie kazo. Ĝenerale, kiam ni vokas nin, ni probable tuj havos malsamajn argumento ĉiufoje. Jen vere simpla rikura funkcio. Do tiu estos komputi la faktorialo de nombro. Supren top tie ni havas nian bazon kazo. En la kazo ke n ≤ 1, ni ne tuj voki faktorialo denove. Ni tuj halti; ni nur tuj revenos iun valoron. Se ĉi tio ne estas vera, tiam ni tuj batis nia rekursie kazo. Rimarku tie ni ne nur nomi faktorialo (n), ĉar tio ne estus tre utila. Ni tuj voki faktorialo de io alia. Kaj tial vi povas vidi, eventuale se ni pasi faktorialo (5) aŭ iu, ni iras por voki faktorialo (4) kaj tiel plu, kaj eventuale ni iras por bati tiun bazon kazo. Do tiu aspektas bone. Ni vidu kio okazas kiam ni efektive kuri ĉi. Ĉi tiu estas la pilo, kaj diru, ke ĉefa tuj nomas tiun funkcion kun argumento (4). Do iam faktorialo vidas kaj = 4, faktorialo nomos sin. Nun, subite, ni havas faktorialo (3). Do tiuj funkcioj tuj teni kreskantan ĝis fine ni batis nian bazon kazo. Je ĉi tiu punkto, la reveno valoro de ĉi tiu estas la reveno (nx la reveno valoro de ĉi tiu), la reveno valoron de tio estas nx la reveno valoro de ĉi. Eventuale ni bezonas bati iu nombro. Ĉe la supro tie, ni diru reveno 1. Tio signifas, ke iam ni revenos tiu numero, ni povas popo ĉi fronte al la pilo. Do ĉi faktorialo (1) estas farita. Kiam 1 revenas, ĉi faktorialo (1) revenas, ĉi tiu reveno al 1. La reveno valoro de tio, memoru, estis nx la reveno valoro de ĉi. Tiel subite, ĉi ulo scias ke mi volas reveni 2. Do memoru, revenu valoron de tio estas simple nx la reveno valoro ĝis ĉi tie. Do nun ni povas diri 3 x 2, kaj fine, jen ni povas diri ĉi tiu estas nur tuj estos 4 x 3 x 2. Kaj fojo ĉi revenas, ni preni malsupren al sola entjero ene de ĉefa. Demandojn sur rekursio? Bone. Do tie estas pli da tempo por demandoj al la fino, sed nun Jozef kovros la ceteraj temoj. [Jozef Ong] Bone. Do nun ni jam parolis pri recursions, ni parolu iomete pri kio kunfandi varo estas. Kunfandi varo estas esence alia formo de ordigi liston de nombroj. Kaj kiel ĝi funkcias estas, kun merge speco vi havas liston, kaj kion ni faras estas ni diras, ni fendi ĉi en 2 duonoj. Ni unue kuri kunfandi speco denove sur la maldekstra duono, tiam ni kuros kunfandi speco sur la dekstran duonon, kaj kiu donas al ni nun 2 duonoj kiuj ordo, kaj nun ni iras kombini tiujn duonoj kune. Estas iom malfacile por vidi sen ekzemplo, do ni iros tra la moviĝoj kaj vidu kio okazas. Do vi komencu per tiu listo, ni fendi ĝin en 2 duonoj. Ni kuras kunfandi speco en la maldekstra duono unua. Do jen la maldekstra duono, kaj nun ni kuras ilin tra tiu listo denove kiu prenas eniris merge varo, kaj poste ni rigardos, denove, ĉe la maldekstra flanko de ĉi tiu listo kaj ni kuras kunfandi speco sur ĝi. Nun, ni preni malsupren al listo de 2 nombroj, kaj nun la maldekstra duono estas nur 1 ero longa, kaj ni ne povas fendi liston tio nur 1 elemento en duono, do ni nur diros, iam ni havos 50, kiu estas nur 1 elemento, ĝi estas jam ordo. Iam ni faris kun tio, ni povas vidi, ke ni povas movi sur la dekstra duono de tiu listo, kaj 3 estas ankaŭ ordo, do nun, ke ambaŭ duonoj de ĉi tiu listo estas ordo ni povas aliĝi al tiuj nombroj reen kune. Do ni rigardu 50 kaj 3, 3 estas pli malgranda ol 50, do ĝi iras en unua kaj tiam 50 envenas Nun, ke tio faris, ni reiru al tiu listo kaj varo pravas duono. 42 estas ĝia propra nombro, do ĝi estas jam ordo. Do nun ni komparas tiujn 2 kaj 3 estas pli malgranda ol 42, tiel ke gets metis en la komenco, nun 42 gets metis en, kaj 50 gets enmetita tien Nun, ke tio ordo, ni iru la tuta vojo reen al la supro, 1337 kaj 15. Nu, ni nun rigardu la maldekstra duono de ĉi tiu listo; 1337 estas per si mem tiel ĝi estas ordo kaj sama kun 15. Do nun ni kombini tiujn 2 numeroj ordigi tiu originala listo, 15 <1337, do ĝi iras en la komenco, tiam 1337 iras in Kaj nun ni ordo ambaŭ duonoj de la originala listo supren supro. Kaj ĉiuj ni devas fari estas kombini tiujn. Ni rigardu la unuaj 2 numerojn de ĉi tiu listo, 3 <15, do ĝi iras en la varo tabelo unua. 15 <42, tia iras in Nun, 42 <1337, kiu iras in 50 <1337, do ĝi iras in Kaj rimarki, ke ni simple prenis 2 numeroj ekstere de tiu listo. Do ni ne nur alternante inter la 2 listojn. Ni nur rigardante la komenco, kaj ni preni la elemento jen malgranda kaj tiam metante gxin en nia tabelo. Nun ni kuniĝis ĉiuj duonoj kaj ni faris. Demandojn pri kunfandi speco? Jes? [Studenta] Se estas dividi en malsamaj grupoj, kial ne simple dividas ĝin unufoje kaj vi havas 3 kaj 2 en grupo? [Resto de demando ininteligibles] La kialo - do la demando estas, kial ni ne nur kunfandi ilin en tiu unua paŝo post ni havas ilin? La kialo povas fari tion, komenci ĉe la maldekstra plej elementojn de ambaŭ flankoj, kaj poste prenu la plej malgranda kaj metis ĝin en, estas, ke ni scias, ke tiuj individuaj listoj en ordo ordonojn. Do, se mi rigardas la maldekstra plej elementojn de ambaŭ duonoj, Mi scias ili tuj estos la plej malgranda eroj de tiuj listoj. Do mi povas meti ilin en la plej malgranda ero makuloj de tiu granda listo. Aliflanke, se mi rigardas tiujn 2 lertaj en la dua nivelo tien, 50, 3, 42, 1337 kaj 15, tiuj ne estas ordo. Do, se mi rigardas 50 kaj 1337, mi tuj metos 50 en mian liston unua. Sed tio ne vere havas sencon, ĉar 3 estas la plej malgranda ero de cxiuj el tiuj. Do la sola kialo ni povas fari ĉi kombinante paŝo estas ĉar nia lertaj jam ordo. Tial ni devas preni malsupren la tuta vojo al la fundo ĉar kiam ni havas nur unu nombro, vi scias ke sola nombro en kaj de sin jam ekzistas ordo listo. Demandojn? Ne? Komplekseco? Nu, vi povas vidi, ke ĉe ĉiu paŝo ekzistas fino nombroj, kaj ni povas dividi liston en duono logo n fojoj, kio estas kie ni atingos ĉi n × log n komplekseco. Kaj vi vidos la plej bona kazo por merge varo estas n logo n, kaj ĝi nur tiel pasas ke la plej malbona kazo, aŭ la Ω tie, estas ankaŭ n log n. Ion por teni en la menso. Movante en, ni iru antauxen al iuj super baza dosiero mi / O. Se vi rigardis Scramble, vi rimarkos ni havis ian sistemon kie vi povus skribi al log-dosiero, se vi legis tra la kodon. Ni vidos kiel vi eble fari tion. Nu, ni havas fprintf, kiun vi povas pensi pri kiel ĝuste printf, sed ĝuste presi al dosiero anstataŭ, kaj tie la f je la komenco. Tiu speco de kodo tien, kio faras estas, kiel vi eble vidis en Scramble, iras tra viaj 2-dimensia tabelo impreso el linion post linio, kion la nombroj estas. En ĉi tiu kazo, printf presas al viaj terminalo aŭ kion ni nomas la norma eligo de sekcio. Kaj nun, en ĉi tiu kazo, ĉiuj ni devas fari estas anstataŭi printf kun fprintf, sciigi kion dosiero kiun vi volas presi al, kaj en tiu kazo nur presas gxin al tiu dosiero anstataŭ presi gxin al via fina stacio. Nu, tiam tiu petegas la demando: Kie ni preni ĉi tia dosiero de, ĉu ne? Ni pasis ensaluti por ĉi fprintf fuction sed ni tute ne sciis kie venis. Nu, frue en la kodo, kion ni havis estis ĉi parton de kodo super ĉi tie, kiu esence diras ke malferma dosiero vokas log.txt. Kion ni faru post tio estas ni devas certigi ke la dosiero estas efektive malfermis sukcese. Do eble malsukcesos por multnombraj kialoj; vi ne havas sufiĉan spacon en via komputilo, ekzemple. Do ĝi estas ĉiam grava antaux vi faros neniun operacioj kun la dosiero ke ni kontrolu ĉu tiu dosiero estis malfermita sukcese. Do kio ke, jen argumento por fopen, nu, ni povas malfermi dosieron en multaj manieroj. Kion ni povas fari estas, ni povas pasi ĝin w, kiu signifas nuligi la dosieron se eliroj jam, Ni povas pasi al, kiu aldonas al la fino de la dosiero anstataŭ supera ĝin, aŭ ni povas specifi r, kio signifas, ni malfermu la dosieron kiel nurlega. Do se la programo provas fari ajnan ŝanĝojn al la dosiero, krias al ili kaj ne lasu ilin fari tion. Fine, iam ni faris kun la dosiero, farita fari operaciojn sur ĝi, ni bezonas por certigi ni fermas la dosiero. Kaj tial ĉe la fino de via programo, vi tuj pasi ilin denove ĉi tiu dosiero, kiun vi malfermis, kaj ĝuste fermi ĝin. Do ĉi tiu estas io grava, ke vi devas certigi vin fari. Do memoras vi povas malfermi dosieron, tiam vi povas skribi al la dosiero, fari operacioj en la dosiero, sed tiam vi devas fermi la dosieron ĉe la fino. Demandojn pri la bazaj dosiero / S? Jes? [Studenta demando, nekomprenebla] Ĝuste ĉi tie. La demando estas, kiel tio ĉi log.txt dosiero aperos? Nu, se vi simple donu log.txt, kredas ĝin en la sama dosierujo kiel la ruleblan. Do se you're - >> [Studenta demando, nekomprenebla] Jes. En la sama dosierujo, aŭ en la sama dosierujo, kiel vi nomas ĝin. Nun memoro, stako, kaj amaso. Do kiel estas memoro metitaj en la komputilo? Nu, vi povas imagi memoro kiel speco de ĉi tiu bloko tie. Kaj en memoro ni havas, kion nomas la havaĵon pusxis tien, kaj la pilo jen tie malsupre. Kaj la amaso kreskas malsupren kaj la pilo kreskas supren. Do kiel Tommy menciita - ho, nu, kaj ni havas ĉi tiujn aliaj 4 segmentoj kiujn mi ricevos por en dua - Kiel Tommy diris antaŭe, vi scias, kiel liaj funkcioj nomas sin kaj nomas unu la alian? Ili konstruos ĉi speco de pilo kadro. Nu, se ĉefa alvokoj foo, foo gets surmetis la stako. Foo nomas trinkejo, trinkejo akiri la surmetis la pilo, kaj ke gets surmetis la pilo poste. Kaj dum ili revenas, ili ĉiu get demetis la stako. Kion ĉiu el tiuj lokoj kaj memoro tenas? Nu, la supro, kiu estas la teksto segmento, enhavas la programon mem. Do la maŝino kodo, jen tie, kiam oni kompilas via programo. Tuj poste, neniu inicializado tutmonda variabloj. Do vi havas mallokajn variablojn en via programo, kaj vi diros kiel, a = 5, ke gets metis en tiu segmento, kaj ĝuste sub tiu, vi havas uninitialized tutmonda datumoj, kiuj estas simple int a, sed vi ne diras ke estas egala al nenio. Realigi tiuj estas tutmonda variabloj, do ili estas ekster ĉefa. Do tio signifas ajna tutmonda variabloj kiuj estas deklaritaj, sed ne estas inicializado. Do kio estas en la havaĵo? Memoro atribuitaj uzante malloc, kiun ni ricevos en en iomete. Kaj fine, kun la pilo vi havas lokajn variablojn kaj iu ajn funkciojn vi povus nomi en iu ajn el siaj parametroj. La lasta afero, vi ne vere devas scii kion la medio variabloj fari, sed kiam ajn vi kuros programo, estas iu asociita, kiel ĉi tiu estas la salutnomo de la persono kiu kuris la programo. Kaj tiu tuj estos speco de malsupre. En terminoj de memoro adresojn, kiuj estas deksesuma valoroj, la valoroj ĉe la supro komencas je 0, kaj ili iru la tuta vojo ĝis la fundo. En ĉi tiu kazo, se vi estas en la 32-bita sistemo, la adreso malsupre tuj estos 0x, sekvita de af, ĉar tio estas 32 bitoj, kiu estas 8 bajtoj, kaj en ĉi tiu kazo 8 bajtoj respondas al 8 deksesumaj ciferoj. Do ĉi tie vi havos, kiel, 0xffffff, kaj tie vi havos 0. Do kio estas punteros? Kelkaj el vi eble ne estus kovrita tion en sekcio antaŭe. sed ni ne transiru en konferenco, do puntero estas nur datumtipo kiu tendencas, anstataŭ ia valoro kiel 50, stokas la adreso de iu loko en memoro. Kiel tiu memoro [nekompreneblaj]. Do ĉi-kaze, kion ni estas, ni havas puntero al entjero aŭ int *, kaj ĝi enhavas tiun deksesuma adreso de 0xDEADBEEF. Do kion ni havas estas, nun, ĉi puntero punktoj en iu loko en memoro, kaj tio estas nur, la valoro 50 estas en ĉi tiu memoro loko. Sur iuj 32-bita sistemoj, sur ĉiuj 32-bita sistemoj, punteros levu 32 bitoj aŭ 4 bitokoj. Sed, ekzemple, sur 64-bita sistemo, punteros estas 64 bitoj. Por ke io vi volas teni en la menso. Ktp finon-bitoj, puntero estas fino bitoj longa. Punteros estas ia malfacile digestas sen ekstra aĵoj, do ni iru tra ekzemplo de dinamika memoro atribuo. Kio dinamika memoro atribuo faras por vi, aŭ kion ni nomas malloc, ĝi ebligas atribui ian datumoj ekster la aro. Do tiu datumo estas ia pli permanenta por la daŭro de la programo. Ĉar kiel vi scias, se vi rakontos x ene de funkcio, kaj tiu funkcio redonas, vi jam ne havas aliron al la datumoj kiuj estis stokitaj en x. Kio punteros ni faras estas ili ni stoki memoro aŭ vendejo valoroj en malsama segmento de memoro, nome la amaso. Nun unufoje ni revenos el funkcio, tiel longe, kiel ni havas puntero al tiu loko en memoro, tiam kion ni povas fari estas ni povas simple rigardi la valoroj tie. Ni rigardu ekzemplon: Ĉi tiu estas nia memoro aranĝo denove. Kaj ni havas la saman funkcion, ĉefa. Kion faras estas - estas bone, tiel simpla, ĉu ne? - Int x = 5, tio estas nur variablo en la pilo en ĉefa. Aliflanke, ni nun deklari puntero kiu nomas la funkcion giveMeThreeInts. Kaj tial nun ni iru en tiu funkcio kaj ni kreu novan pilon kadro por ĝi. Tamen, en ĉi tiu pilo kadro, ni deklaras int * temp, kiu en mallocs 3 entjeroj por ni. Do grandeco de int donos al ni, kiom da bitokoj ĉi int estas, kaj malloc donas al ni, ke multaj bajtoj de spaco sur la monteto. Do ĉi-kaze, ni kreis sufiĉan spacon por 3 entjeroj, kaj la amaso estas maniero tie supre, kio estas kial mi desegnis ĝin pli alte. Iam ni faris, ni revenu ĉi tien, vi nur bezonas 3 ints revenis, kaj denove la adreso, en ĉi tiu kazo super kie tiu memoro estas. Kaj ni starigis pointer = ŝaltilon, kaj tie ni havas nur alia puntero. Sed kion tiu funkcio redonas estas plata tie kaj malaperas. Do temp malaperas, sed ni ankoraŭ subtenas la adreso de kie tiuj 3 entjeroj estas ene de elektra reto. Do en tiu aro, la punteros estas scoped loke por la plata kadro, sed la memoro al kiu aludas estas en la havaĵo. Ĉu tio havas sencon? [Studenta] Ĉu vi povas ripeti tion? >> [Joseph] Jes. Do se mi reiros malmulta, vi vidos ke temp asignitaj iuj memoro sur la havaĵon tie supre. Kaj post tiu funkcio, giveMeThreeInts revenas, ĉi pilo tie tuj malaperos. Kaj per ĝi iun el la variabloj, en ĉi tiu kazo, ĉi puntero kiu atribuitaj en plata kadro. Kiu tuj malaperas, sed kiam ni revenis temp kaj ni starigis pointer = temp, pointer afero nun tuj notas la sama memoro de situo kiel temp estis. Do nun, eĉ se ni perdos temp, ke lokaj pointer, ni ankoraŭ konservas la memoron adreso de kio indikante ene de tiu variablo puntero. Demandoj? Tio povas esti speco de konfuza temo, se vi ne estus transirinta en sekcio. Ni povas, via TF definitive transiru ĝin kaj certe ni povas respondi demandojn fine de la recenzo kunsido por ĉi tio. Sed ĉi tiu estas speco de kompleksa temo, kaj mi havas pli ekzemploj kiuj tuj aperas kiu helpos klarigi kion punteros reale estas. En ĉi tiu kazo, punteros estas ekvivalentaj al arrays, do mi povas simple uzi tiun puntero kiel la sama afero kiel int tabelo. Do mi indeksado en 0, kaj ŝanĝi la unua entjero al 1, ŝanĝi la dua entjera al 2, kaj la 3a entjero al 3. Do pli en punteros. Nu, memoru Binky. En ĉi tiu kazo ni destinis puntero, aŭ ni deklaris pointer, sed komence, kiam mi ĵus deklarita pointer, ĝi ne indikante ie ajn en memoro. Estas nur rubo valoroj ene de ĝi. Do mi ne havas ideon kie ĉi puntero estas indikante. Ĝi havas adreson kiu estas nur plenigita kun 0-aj kaj 1-oj kie estis komence deklaris. Mi ne povas fari ion kun tiu ĝis mi nomas malloc sur ĝi kaj tiam donas al mi iom spaco sur la havaĵon, kie mi povas meti valoroj ene. Tiam denove, mi ne scias kio estas ene de ĉi memoro. Do la unua afero Mi devas fari estas kontroli ĉu la sistemo havis sufiĉan memoron doni al mi reen 1 entjero en la unua loko, kio estas kial mi faras ĉi kontroli. Se puntero estas nula, tio signifas ke ĝi ne havas sufiĉan spacon aŭ iu alia eraro, do mi devas eliri el mia programo.  Sed se ĝi faris sukcesos, mi nun povas uzi tiun puntero kaj kion * puntero faras estas sekvas kie la adreso estas al kie tiu valoro estas, kaj starigos ĝin egala al 1. Do ĉi tie, ni kontrolas se tiu memoro ekzistis. Iam vi scias ĝi ekzistas, vi povas meti en ĝin kio valoro vi volas meti en ĝin; en ĉi tiu kazo 1. Iam ni el tio, vi bezonas liberigi ke puntero ĉar ni bezonas reiri al la sistemo kiu memoro kiun vi petis en la unua loko. Ĉar la komputilo ne scias kiam ni el tio. En ĉi tiu kazo ni eksplicite diri ĝin, bone, ni faris kun tiu memoro. Se iu alia procezo bezonas ĝin, iu alia programo bezonas ĝin, bonvolu iri antaŭen kaj preni ĝin. Kion ni povas ankaŭ fari estas ni povas nur atingi la adreson de lokaj variabloj en la aro. Do int x estas interne la plata kadro de ĉefa. Kaj kiam ni uzas-signo, oriento kaj operatoro, kio faras estas prenas x, kaj x estas nur iuj datumoj en memoro, sed ĝi havas adreson. Ĝi estas lokita ie. Do per voko & x, kio estas tiu faras estas ĝi donas al ni la adreson de x. Por fari tion, ni faras puntero punkto al kie x estas en memoro. Nun ni simple iu kiel * x, ni ricevos 5 dorso. La stelo estas nomata dereferencing ĝin. Vi sekvu la adreson kaj vi ricevos la valoron de tio stokita tie. Demandojn? Jes? [Studenta] Se vi ne faras la 3-pinta afero, ĉu tio ankoraŭ kompili? Jes. Se vi ne faras la 3-puntero afero, ĝi estas ankoraŭ tuj kompili, sed mi montros al vi kio okazas en dua, kaj sen fari tion, tion ni nomas memoro fugo. Vi ne doni la sistemo apogi lian memoron, do post momento la programo tuj amasigos memoro kiun ĝi ne uzas, kaj nenio alia povas uzi ĝin. Se vi iam vidis Firefox kun 1,5 milionoj kilobajtoj en via komputilo, en la tasko direktisto, jen kio okazas. Vi havas memoron fugo en la programo kiu ili ne manipulas. Do kiel faras puntero aritmetiko laboro? Nu, pointer aritmetiko estas ia kiel indeksado en tabelo. En ĉi tiu kazo, mi havas pointer, kaj kion mi faras estas mi faras puntero punkton al la unua ero de tiu tabelo de 3 entjeroj ke mi destinis. Do nun tio, kion mi faru, stelo puntero nur ŝanĝas la unua ero en la listo. Stelo puntero +1 points tie. Do puntero estas tie, pointer +1 estas tie, pointer +2 estas super tie. Do ĝuste aldonante 1 estas la sama afero kiel movanta laŭ tiu tabelo. Kion ni faras estas, kiam ni faras puntero +1 vi ricevas la adreson ĉi tie, kaj por ricevi la valoron en ĉi tie, vi metu stelon en de la tuta esprimo al dereference ĝin. Do, en tiu kazo, mi opcio la unua loko en ĉi tiu tabelo al 1, dua loko al 2, kaj tria loko al 3. Tiam kion mi faras sur jen Mi presi nian puntero +1, kiu nur donas al mi 2. Nun mi pliigante pointer, do puntero egalas puntero +1, kiu movas ĝin antaŭen. Kaj tial nun, se mi presi puntero +1, +1 puntero nun 3, kiu en ĉi tiu kazo presas el 3. Kaj por liberigi iun, la puntero ke mi donu ĝin devas esti montrante al la komenco de la tabelo kiun mi reiris de malloc. Do, en ĉi tiu kazo, se mi estus nomi 3 dekstra tie, ĉi tiu ne estus bone, ĉar ĝi estas en la mezo de la tabelo. Mi devas subtrahi por atingi la originalan situo la komenca unua loko antaŭ ol mi povos liberigi ĝin. Do, jen pli implikitaj ekzemplo. En ĉi tiu kazo, ni atribui 7 gravuloj en karaktero tabelo. Kaj en ĉi tiu kazo kion ni faras estas ni looping super la unuaj 6 el ili, kaj ni opcio ilin al Z. Do, por int i = 0, i> 6, i + +, Do, pointer + i estos nur al ni, en ĉi tiu kazo, pointer, pointer +1, pointer +2, +3 pointer, kaj tiel plu kaj tiel plu en la ciklo. Kio okazas fari estas alvenas tiu adreso, dereferences ĝin akiri la valoron, kaj ŝanĝoj kiuj valoron al Z. Tiam fine memori ĉi estas ĉeno, ĉu ne? Ĉiuj kordoj devas finiĝi per la nula finanta karaktero. Do, kion mi faras estas en montrilo 6 Mi metis la nula Terminator karaktero in Kaj nun kion mi esence fari super tie apliki printf por kordoj, ĉu ne? Do, kiam tio printf nun kiam ĝi atingis la finon de ĉeno? Kiam batas la nula finanta karaktero. Do, en tiu kazo, mia originala puntero punktoj al la komenco de ĉi tabelo. Mi presis la unuan karakteron eksteren. Mi movi ĝin super unu. Mi presi tiu karaktero eksteren. Mi movi ĝin. Kaj mi konservos fari ĉi ĝis mi atingis la finon. Kaj nun la fino * puntero volo dereference ĉi kaj akiri la nula finanta karaktero dorso. Kaj tial mia dum buklo kuras nur kiam tiu valoro ne estas la nula finanta karaktero. Do, nun mi eliri el ĉi tiu ciklo. Kaj tial, se mi subtrahi 6 de ĉi pointer, Mi reiros tuta vojo al la komenco. Memoru, mi faras ĉi tion ĉar mi devas iri al la komenco por liberigi ĝin. Do, mi scias, ke estis tre. Ĉu estas demandoj? Bonvolu, jes? [Studenta demando ininteligibles] Ĉu vi povas diri ke pli laŭte? Pardonu. [Studenta] Sur la lasta slide ĝuste antaŭ vi liberigis la puntero, kie vi estis efektive ŝanĝanta la valoro de la puntero? [Joseph] Do, ĉi tie. >> [Studenta] Ho, bone. [Joseph] Do, mi havas puntero minus minus, dekstra, kiu movas la afero reen, kaj tiam mi liberigi ĝin, ĉar ĉi puntero devas indikis la komencon de la tabelo. [Studenta] Sed tio ne estus necesa estis vi haltis post tiu linio. [Joseph] Do, se mi ĉesis post ĉi tio, ĉi tiu devus esti konsiderata memoro fugo, ĉar mi ne ruli la libera. [Studenta] I [nekompreneblaj] post la unuaj tri linioj kie vi havis puntero +1 [nekompreneblaj]. [Joseph] Uh-huh. Do, kio estas la demando tie? Pardonu. Ne, ne. Iru, iru, bonvolu. [Studenta] Do, vi ne ŝanĝi la valoron de punteros. Vi ne devis fari puntero minus minus. [Joseph] Jes, ĝuste. Do, kiam mi faras puntero +1 kaj puntero +2, Mi ne faras puntero egalas puntero +1. Do, la puntero nur restas montrante al la komenco de la tabelo. Estas nur kiam mi faras pli pli ke ĝi fiksas la valoron reen interne de la puntero, ke ĝi efektive movas ĉi kune. Bone. Pli demandoj? Denove, se ĉi tiu estas speco de blindiga, ĉi estos kovrita en kunsido. Demandu vian instruadon ulo pri tio, kaj ni povas respondi demandojn je la fino. Kaj kutime ni ne ŝatas fari tion minus afero. Tiu devas postuli min konservanta trako de kiom mi ofseto en la tabelo. Do, ĝenerale, ĉi tiu estas nur por klarigi kiel puntero aritmetiko verkoj. Sed kion ni kutime deziras fari estas ni ŝatas krei kopion de la puntero, kaj tiam ni uzas tiun kopion kiam ni movi ĉirkaŭ en la kordo. Do, en tiuj kazo vi uzas la kopio por presi la tutan ĉenon, sed ni ne devas fari kiel puntero minus 6 aŭ konservi trako de kiom ni kopiis en tio, nur ĉar ni scias ke nia originala punkto ankoraŭ montris la komenco de la listo kaj cxio, kion ni ŝanĝita estis ĉi kopio. Do, ĝenerale, aliigi kopiojn de via originala puntero. Ne provu ordigi de kiel - ne batu ŝanĝi originalojn. Provante ŝanĝi nur kopiojn de via originala. Do, vi rimarkos, kiam ni pasas la kordo en printf vi ne devas meti stelon antaŭ ĝi kiel ni faris kun ĉiuj aliaj dereferences, ĉu ne? Do, se vi presi la tutan ĉenon% s atendas estas adreso, kaj en ĉi tiu kazo puntero aŭ en ĉi tiu kazo kiel aron da karakteroj. Karakterojn, char * s, kaj tabeloj estas la sama afero. Pointer estas signoj, kaj karaktero tabeloj estas la sama afero. Kaj tiel, ĉiuj ni devas fari estas pasi en puntero. Ni ne devas pasi en kiel * puntero aŭ io kiel tio. Do, tabeloj kaj punteros estas la sama afero. Kiam vi faras iun kiel x [y] super tie por tabelo, kio ĝi estas fari sub la kapuĉo estas ĝi estas jene bone, estas karaktero tabelo, do ĝi estas puntero. Kaj tiel x estas la sama afero, kaj tiel kion faras estas aldonas y al x, kiu estas la sama afero kiel movanta antaŭen en memoro ke multe. Kaj nun x + y donas al ni ian adreson, kaj ni dereference la adreso aŭ sekvu la sagon al kie tiu loko en memoro estas kaj ni preni la valoron el tiu loko en memoro. Do, tiel tiuj du estas ekzakte la sama afero. Estas nur sintaksa sukero. Ili faras la samon. Ili estas nur malsamaj syntactics por ĉiu alia. Do, kio povas iri malbone kun indikoj? Kiel, tre. Okay. Do, malbona aĵoj. Kelkaj malbonaj aĵoj vi povas fari ne kontrolanta se via malloc alvoko revenas nula, ĉu ne? En ĉi tiu kazo, mi petas la sistemo por doni al mi - kio estas tiu numero? Kiel 2 miliardoj fojoj 4, ĉar la grandeco de entjero estas 4 bitokoj. Mi petas tion kiel la 8 miliardoj bajtoj. Kompreneble mia komputilo ne tuj povos doni al mi ke multe memoro dorso. Kaj ni ne kontrolu se ĉi tiu estas nula, do kiam ni provas dereference ĝin tie - sekvi la sago al kie tuj - ni ne havas tiun memoron. Jen kion ni nomas dereferencing nula puntero. Kaj ĉi esence faligas vin segfault. Tiu estas unu el la manieroj vi povas segfault. Aliaj malbonaj aĵoj vi povas fari - ho bone. Tio estis dereferencing nula puntero. Okay. Aliaj malbonaj aĵoj - nu, fiksi, ke vi simple metas ĉekon tien ke kontrolas ĉu la puntero estas nula kaj eliri el la programo se ĝi okazas ke malloc revenas nula puntero. Tio estas la xkcd komika. Homoj komprenas ĝin nun. Ordigi de. Do, memoro. Kaj mi iris sur ĉi. Ni alvokas malloc en buklo, sed ĉiufoje ni nomas malloc ni perdas spuro de kie ĉi tiu puntero estas indikante, ĉar ni clobbering ĝin. Do, la komenca alvokon al malloc donas al mi memoron pri tie. Mia puntero punteros al ĉi tio. Nun, mi ne liberigi ĝin, do nun mi vokas malloc denove. Nun notas super tie. Nun mia memoro notas super tie. Atentigante pri tie. Atentigante pri tie. Sed mi miskalkulis la adresoj de la tuta memoro super tie ke mi destinis. Kaj tial mi nun ne havas referencon ilin plu. Do, mi ne povas liberigi ilin ekster tiu ciklo. Kaj tiel por fiksi ion kiel ĉi tiu, se vi forgesu libera memoro kaj vi ricevos tiun memoron fugo, Vi devas liberigi la memoron ene de ĉi buklo iam vi el tio. Nu, jen kio okazas. Mi scias multe pri vi malamas ĉi. Sed nun - yay! Vi ricevas kiel 44.000 kilobajtoj. Do, vi liberigi ĝin ĉe la fino de la ciklo, kaj ke tuj ĝuste liberigi la memoron ĉiufoje. Esence, via programo ne havas memoron fugo plu. Kaj nun io alia vi povas fari estas liberigi iun memoro kiun vi petis dufoje. En ĉi tiu kazo, vi malloc ion, vi ŝanĝu ĝian valoron. Vi liberigi ĝin iam ĉar vi diris ke vi estis faritaj per ĝi. Sed tiam ni liberigis ĝin denove. Tio estas iu kiu estas sufiĉe malbona. Oni ne tuj komence segfault, sed post momento kion ĉi tio estas duobla liberigante ĉi koruptas vian amaso strukturo, kaj vi lernos iom pli pri ĉi tio se vi elektos preni klaso kiel CS61. Sed esence post momento via komputilo tuj get konfuzita pri kio memoro lokoj estas kie kaj kie ĝi estas stokita - kie datumoj stokitaj en memoro. Kaj tiel liberigante puntero dufoje estas malbona afero, kiun vi ne volas fari. Aliajn aĵojn kiuj povas iri malbone ne uzante sizeof. Do, en tiu kazo vi malloc 8 bajtoj, kaj tio estas la sama afero kiel du entjeroj, ĉu ne? Do, jen perfekte sekura, sed estas ĝi? Nu, kiel Lucas parolis pri diversaj arkitekturoj, entjeroj estas de malsamaj longoj. Do, en la aparaton kiun vi uzas, entjeroj estas proksimume 4 bajtoj, sed sur iu alia sistemo ili estu 8 bajtoj aŭ ili povus esti 16 bajtoj. Do, se mi nur uzas tiun numeron sur ĉi tie, tiu programo povus labori en la aparaton, sed ne iras destini sufiĉan memoron pri kelkaj aliaj sistemo. En ĉi tiu kazo, ĉi tio estas kion la sizeof operatoro estas uzata por. Kiam ni nomas sizeof (int), kio estas tiu faras estas  ĝi donas al ni la grandeco de entjero en la sistemo, ke la programo kuras. Do, en ĉi tiu kazo, sizeof (int) revenos 4 en iun kiel la aparaton, kaj nun tiu volo 4 * 2, kiu estas 8, kio estas ĝuste la sumo de spaco necesa por du entjeroj. Sur malsama sistemo, se int estas kiel 16 bitokoj aŭ 8 bajtoj, ĝi estas ĵus tuj revenos sufiĉe bitokoj stoki tiu kvanto. Kaj fine, structs. Do, se vi volas stoki Sudoku tabulo en memoro, kiom eble ni faru tion? Vi povus pensi kiel variablo por la unua afero, variablo por la dua afero, variablo por la tria afero, variablo por la kvara afero - malbona, ĉu? Do, unu plibonigo vi povas fari supre sur ĉi estas fari 9 x 9 tabelo. Ke estas bone, sed kio se vi volas asociigi aliaj aĵoj kun la Sudoku tabulo ŝati kion la malfacileco de la tabulo estas, aŭ, ekzemple, kion via partituro estas, aŭ kiom da tempo ĝi estos prenita vin solvi ĉi tiu forumaro? Nu, kion vi povas fari estas vi povas krei struct. Kion mi esence dirante estas mi difinanta tiu strukturo super ĉi tie, kaj mi difinanta Sudoku tabulo kiu konsistas de tabulo kiu estas 9 x 9. Kaj kion ĝi havas ĝin havas punteros al la nomo de la nivelo. Ĝi ankaŭ havas x kaj y, kiuj estas la koordinatoj de kie mi estas nun. Ĝi ankaŭ tempo dediĉita [nekompreneblaj], kaj ĝi havas la tuta nombro de movoj mi inputted ĝis nun. Kaj tiel en tiu ĉi kazo, mi povas kolekti tutan faskon da datumoj en nur unu strukturo anstataŭ havi ĝin kiel flugante ĉirkaŭ en kiel malsamaj variabloj ke mi ne povas vere kontroli kiu faras. Kaj tion permesas al ni havas nur belaj sintakson por ia referenco malsamaj aĵoj interne de ĉi struct. Mi povas nur fari board.board, kaj mi alvenas la Sudoku tabulo dorso. Board.level, mi alvenas kiel malmola estas. Board.x kaj board.y donu al mi la koordinatoj de kie mi povus esti en la estraro. Kaj tiel mi konsentas kion ni nomas kampojn en la struct. Ĉi tiu difinas sudokuBoard, kiu estas tipo, kiun mi havas. Kaj nun ni estas ĉi tie. Mi havas variablo nomita "estraro" de tipo sudokuBoard. Kaj tial mi nun povas aliri ĉiujn kampojn kiuj konsistigas tiun strukturon super tie. Demandojn pri structs? Jes? [Studenta] Por int x, y, vi deklaris ambaŭ en unu linio? >> [Joseph] Uh-huh. [Studenta] Do, vi povus simple fari tion kun ĉiuj el ili? Kiel en x, y komo fojoj ke entute? [Joseph] Jes, vi povus definitive fari tion, sed la kialo mi metis x kaj y en la sama linio - kaj la demando estas kial ni povas nur fari tion en la sama linio? Kial ni ne simple metu ĉiuj tiuj sur la sama linio estas x kaj y estas rilatanta al ĉiu alia, kaj ĉi tiu estas nur stile pli ĝentila, iusence, ĉar ĝi estas kolektante du aferoj en la sama linio kiu kiel ia rilatas al la sama afero. Kaj mi nur fendi tiuj aparte. Estas nur stilo afero. Ĝi funkcie faras ne diferenco kion. Ajna alia demandojn sur structs? Vi povas difini Pokédex kun struct. Al Pokémon havas numeron kaj ĝi havas literon, posedanto, tipo. Kaj tiam se vi havas tabelo de Pokémon, vi povas konsistigas Pokédex, ĉu ne? Konsentite, cool. Do, la demandoj sur structs. Tiuj estas rilataj al structs. Fine, GDB. Kion GDB lasu vin fari? Ĝi permesas elpurigi via programo. Kaj se vi ne uzas GDB, mi rekomendas rigardi la mallonga kaj nur irante super kio GDB estas, kiel vi laboras kun ĝi, kiel vi povus uzi ĝin, kaj provi ĝin sur programo. Kaj tiel kion GDB permesas fari estas tio lasas paŭzo la [nekompreneblaj] vian programon kaj praktika linio. Ekzemple, mi volas paŭzi ekzekuto ĉe kiel linio 3 de mia programo, kaj kiam mi estas en la linio 3 Mi povas presi ĉiujn valorojn kiuj estas tie. Kaj tiel kion ni nomas kiel deteni en linio estas ni nomas tion metante Haltpunkto en tiu linio kaj poste ni povas presi la variabloj ĉe la stato de la programo en tiu tempo. Ni povas tiam el tie treti tra la programo linio-per-linio. Kaj tiam ni povas rigardi la stato de la pilo de la epoko. Kaj tiel en ordo uzi GDB, kion ni faras estas ni nomas clang sur la C-dosiero, sed ni devas pasi ĝin la-ggdb flago. Kaj unufoje ni faris kun ni nur kuri gdb en la rezultanta eliro dosiero. Kaj tiel vi havos iujn kiel maso de teksto kiel ĉi tiu, sed vere ĉiuj vi devas fari estas entajpi komandojn en la komenco. Rompi ĉefa metas Haltpunkto ĉe ĉefa. Listo 400 listas la linioj de kodo ĉirkaŭ linio 400. Kaj tiel en tiu ĉi kazo vi povas simple rigardi sin kaj diros, ho, Mi volas agordi Haltpunkto ĉe linio 397, kiu estas tiu linio, kaj tiam via programo kuras en tiun paŝon kaj ĝi tuj rompos. Ĝi tuj paŭzo tie, kaj vi povas presi, ekzemple, valoro de malaltaj aŭ altaj. Kaj tiel estas plenmano da ordonoj vi bezonas scii, kaj ĉi Bildoprezento iros en la retejo, do se vi volas nur referenci tiuj aŭ kiel meti ilin sur vian cheat littukoj, bonvolu. Cool. Tio estis Quiz Review 0, kaj ni batas ĉirkaŭ se vi havas demandojn. Bone.  [Aplaŭdo] [CS50.TV]