[Powered by Google Translate] [8 § - Mer Bekväm] [Rob Bowden - Harvarduniversitetet] [Detta är CS50. - CS50.TV] Dessa vecka avsnitt anteckningar kommer att vara ganska kort, så jag ska bara fortsätta prata, är ni kommer att fortsätta att ställa frågor, och vi ska försöka fylla så mycket tid som möjligt. Många tror att detta pset är inte nödvändigtvis svårt, men det är mycket lång. Den pset spec själv tar en timme att läsa. Vi ger dig en hel del av SQL kan du eventuellt behöver använda. Vi går igenom mycket av det, så det borde inte vara så illa. Har någon börjat eller färdiga? Det är den sista pset. Herregud. Vanligtvis finns det en JavaScript en efter detta, men kalender ändra saker gör allt 1 vecka kortare och vi inte längre har en JavaScript pset. Jag vet inte hur det påverkar om JavaScript kommer att visas på tentan eller Quiz 1. Jag antar att det kommer att vara något som du behöver veta på hög nivå saker om JavaScript, men jag tvivlar på att vi bara skulle ge dig rakt JavaScript-kod eftersom du inte har haft en pset i den. Men det kommer att vara saker för frågesport översyn nästa vecka. Del av frågorna. En hel del av det här är något dåligt formulerad, men vi kommer att diskutera varför. Till skillnad från C, PHP ett "dynamiskt skrivit" språk. Vad betyder det, frågar du? Tja, säga adjö till alla dessa röding, flyta, int, och andra sökord som du behöver använda När förklara variabler och funktioner i C. I PHP är en variabels typ bestäms av det värde som för närvarande är innehav. Så innan vi skriver denna kod i en fil som heter dynamic.php, PHP dynamiskt skrivs. Det är sant. Jag håller inte med att det innebär att vi säger adjö till röding, flyta, int, och andra sökord. Den exakta skillnaden mellan dynamiskt tryckte hand, som är statiskt skrivs, är det dynamiskt skrivit, alla dina typkontroll och sånt händer vid körning, medan statiskt skrivit det händer vid kompileringen. Ordet static i allmänhet tycks betyda saker kompileringen. Jag antar att det finns andra användningsområden för det, men i C när du deklarerar en statisk variabel, lagring fördelas vid kompileringen. Här dynamiskt skrivit betyder bara att - I C om du försöker lägga till en sträng och ett heltal, när du kompilerar den, det kommer att klaga eftersom det kommer att säga att du inte kan lägga en int och en pekare. Det är bara inte en giltig operation. Det är en annan sak som vi kommer till i en sekund. Men den sortens kontroll, att det klagar vid kompileringen, är statisk typkontroll. Det finns språk där man inte behöver säga röding, flyta, int, och alla dessa saker, men språket kan berätta från ramen för något vilken typ det ska vara, men det är fortfarande statiskt skrivit. Så om du tar 51, OCaml, behöver du aldrig använda någon av dessa typer, men det kommer fortfarande vid kompileringen säger att du inte kan göra detta eftersom du blandar en int och en sträng. Dynamiskt skrivit betyder bara att någon gång under körning du kommer att få ett klagomål. Om du också har använt Java tidigare i allmänhet nästan alla C-typ språk kommer att statiskt skrivit så C, C + +, Java, alla dessa är i allmänhet statiskt skrivs. I Java när du kompilerar något och du säger string s lika ny något som inte är en sträng, det kommer att klaga eftersom dessa typer bara inte matchar. Det kommer att klaga vid kompileringen. Men det har också några dynamisk tid saker som om du försöker kasta något en typ som är mer specifik än den nuvarande typ, det finns inget man kan göra vid kompileringen att kontrollera om den gjutna kommer att lyckas. Java har också några dynamisk typkontroll att så snart det kommer till att kodrad när det faktiskt är köra, det kommer att göra rösterna, kontrollera om det gjutna gällde i första hand, och om det inte var så att det kommer att klaga över att du har en ogiltig typ. Dynamisk typkontroll. Skriv detta i en fil som heter dynamic.php. Dynamic.php. Jag packa den formateringen. Vi har en variabel, vi satt det till heltal 7, då ska vi skriva ut det och s% - Åh, vi skriver den typ av den, så getType kommer att återvända typen av variabeln. Vi bara skriva ut typ om och om igen. Vi php.dynamic.php bara. Vi får se till att den ändras från heltal till sträng till Boolean som vi går igenom. I C finns ingen boolesk datatyp, finns det ingen sträng datatyp. Det finns char * och Boolean bara tenderar att vara int eller char eller något. I PHP dessa typer finns, och det är en av de stora fördelarna med PHP över C - att string verksamhet oändligt mycket lättare i PHP än C. De bara fungerar. Så vi kommer tillbaka hit. Vi körde dynamic.php. Detta talar PHP tolken, kallad php, att köra PHP-kod i dynamic.php. Om du har några fel i filen kommer tolken berätta! Tolken är detta en annan stor skillnad mellan PHP och C I C måste du kompilera något och sedan kör det kompilerade filen. I PHP du kompilera aldrig något. Så PHP tolken är i princip bara läser detta rad för rad. Det träffar var = 7 så träffar printf då den träffar var så den träffar printf och så vidare. Det är lite att sammanställa det gör, och det cachar resultatet så om du kör skriptet senare kan du göra några, men i grunden är det en rad för rad saker. Det betyder att många av de optimeringar som vi får i C, Liksom sammanställa, det är bara allmänt kompilatorn kan göra en hel del trick för dig. Det kan ta ut oanvända variabler, kan det göra alla dessa typer av saker, det kan göra svansen rekursion. I PHP du inte kommer att få denna fördel eftersom det bara kommer att börja köra rad för rad för rad, och den inte erkänner egentligen dessa saker lika lätt eftersom det inte är en stor sammanställning passerar över saken och sedan utförande; det är bara en rad i taget. Så det är tolken. Tillbaka till våra dynamiska skriva: pretty cool, va? Du definitivt inte kunde göra det i C! Nu, se om du kan lista ut vilken typ av vardera av följande värden. Se denna som referens. Så 3,50. Vilken typ tror du att det kommer att bli? Här är de typer som vi har. Vi har bools, heltal, flytande punkter, strängar, arrayer, objekt, och sedan resurser, vilket är typ av vaga. Jag tror det finns faktiskt ett exempel här. Sedan finns NULL. NULL är en speciell typ. Till skillnad från C där NULL är bara en pekare med adress 0, i PHP, är NULL sin egen typ där det enda giltiga sak av den typen är NULL. Detta är mycket mer användbart för felkontroll. I C där vi hade den här frågan där om du återvänder NULL, betyder det att du återvänder en NULL-pekare eller använda NULL för att beteckna fel eller alla som förvirring vi hade vid ett tillfälle. Här, återvänder NULL allmänhet betyder fel. En hel del saker återkommer också falskt för fel. Men poängen är NULL typen är det enda av NULL typen NULL. Då återuppringning är som du kan definiera några anonyma funktioner. Du behöver inte ge funktionen ett namn, men du kommer inte behöva ta itu med det här. Titta på de typer som de inte förväntar sig att vi ska veta, vad tror du den typ av 3,50 är? >> [Elev] Float. Ja. Så då här, vad tycker du vilken typ av detta är? >> [Elev] Array. Ja. Den första var flottören, är den andra en grupp. Observera att denna array är inte som en C array där du har index 0 har något värde, har index 1 visst värde. Här indexen är a, b och c och är 1, 2, och 3. I PHP är det ingen skillnad mellan en associativ array och bara en vanlig array som du skulle tänka på det i C. Det är just detta, och under huven en vanlig array är bara en associativ array där 0 kartor till ett värde på samma sätt en kartor till något värde. Av denna anledning kan PHP vara ganska dåligt för riktigt snabba kod / benchmarking saker eftersom C när du använder en array som du vet att komma en medlem är konstant tid. I PHP åtkomst till en ledamot är som vet hur mycket tid? Det är nog konstant om det hashar korrekt. Vem vet vad det egentligen gör under huven? Du måste verkligen titta på genomförandet för att se hur det kommer att ta itu med det. Så då fopen. Jag tror här låt oss bara PHP manuell fopen att titta på returtyp. Vi ser här kan du slå upp ganska mycket varje funktion i PHP manualen och detta är typ av mannen sidan av PHP. Avkastningen typ kommer att bli resurs. Det är därför jag såg det, eftersom vi inte riktigt definiera resurs. Idén om resurs i C du typ av har en fil * eller vad; i PHP resursen är din fil *. Det är vad du kommer att läsa ur, det är vad du kommer att skriva till. Det är oftast externa, så det är en resurs som du kan dra saker från och kasta saker. Och slutligen, vad är den typ av NULL? >> [Elev] NULL. Ja. Så det enda som är NULL NULL. NULL är NULL. Ett inslag i PHP typsystem (på gott och ont) är dess förmåga att jonglera typer. När du skriver en rad PHP-kod som kombinerar värden av olika slag, PHP kommer att försöka göra det enda förnuftiga. Prova var och en av följande rader PHP-kod. Vad skrivs ut? Är det vad du förväntade dig? Varför eller varför inte? Detta faktum om PHP är det som gör det vad vi kallar svagt skrivit. Svagt skrivit och starkt skrivit, det finns olika användningsområden för dessa villkor, men de flesta människor använder svagt skrivit och starkt skrivit att betyda något sådant där ("1" + 2), som fungerar. I C som inte skulle fungera. Ni kan föreställa er att detta inte fungerar. Många blandar ihop dynamisk typning och svag typning och statisk typning och stark skriva. Python är ett annat exempel på ett språk som dynamiskt är skrivit. Du kan kasta runt typer i variabler och det kommer att avgöra vid körning eventuella fel KONTROLLER. I Python det kommer att utföra detta och det kommer att se ("1" + 2); och detta kommer att misslyckas eftersom det står att du inte kan lägga till en sträng och ett heltal. I PHP, som är lika dynamiskt skrivit, kommer detta inte misslyckas. Svag typning har att göra med det faktum att den gör saker med olika typer som egentligen inte vettigt nödvändigtvis. Så ("1" + 2), jag kan tänka mig att vara strängen 12, kan jag tänka mig att det är strängen 3, Jag kan tänka mig att det är heltalet 3. Det är inte nödvändigtvis väl definierade, och vi förmodligen kommer att se här att när vi skriver ut ("1" + 2), det är förmodligen kommer att hamna olika än utskrift (1 + "2"). Och detta tenderar att vara, enligt min mening, till det sämre. Här kan vi prova dessa. En annan litet trick om PHP är att du inte behöver verkligen skriva filen. Det har kört detta kommando läget. Så php-r, då kan vi kasta in kommandot här: "Tryck ('1 '+ 2)," och jag kastar en ny rad. Denna tryckta 3. Det ser ut som det skrivs 3 och det är heltalet 3. Så nu ska vi prova tvärtom: "Print (1 + '2 '); Vi får 3, och det kommer också att bli heltal 3? Jag har ärligt talat ingen aning. Det ser ut som det är konsekvent. Det finns aldrig någon chans att det är strängen 12 eller nåt sånt eftersom PHP, till skillnad från JavaScript och Java också, har en separat operatör för sammanfogning. Sammanlänkning i PHP är prick. Så utskrift (1 '2 '.), Kommer att ge oss 12. Detta tenderar att leda till förvirring där människor försöker göra något liknande Str + = någon annan sak som de vill lägga till i slutet av sin sträng, och det kommer att misslyckas. Du måste göra str. = Så glöm inte sammanslagning i PHP är en punkt. Andra saker att prova: print ("CS" + 50); Jag har sagt att det inte finns något hopp om detta resulterar i CS50 eftersom sammanslagning är inte +. Vad tror du detta kommer att hamna? Jag har ärligt talat ingen aning. Det ser ut som det är bara 50. Det ser strängen, och jag slår vad om vi sätter 123CS - Den ser den första strängen, försöker den att läsa ett heltal från den eller ett nummer från den. I det här fallet ser 123CS. "Det inte är vettigt som ett heltal, så jag ska bara tänka på 123." Så 123 + 50 kommer att bli 173. Och här börjar läser detta som ett heltal. Det behöver inte se någonting, så det bara behandlar det som 0. Så 0 + 50 kommer att bli 50. Detta Jag antar kommer att göra något liknande. Jag tänker 99. Ja, eftersom det kommer att ta första - Så 99. Här (10/7), om detta var C, vad skulle det tillbaka? [Elev] 1. >> Ja, det skulle vara 1 eftersom 10/7 splittrar 2 heltal. Ett heltal dividerad med ett heltal kommer att returnera ett heltal. Det kan inte returnera 1 poäng vad det skulle vara, så det är bara att gå tillbaka 1. Här skriver (10/7), det kommer att faktiskt tolka det. Och detta innebär att om du verkligen vill göra heltal avrundning och sånt, du behöver göra utskrift (golv (10/7)); I C är det nog konstigt att man kan lita på heltal trunkering regelbundet, men i PHP kan du inte eftersom det kommer automatiskt att förvandla det till en flottör. Och sedan (7 + true), vad tror du att det kommer att bli? Jag gissar 8 om det kommer att tolka sant som 1. Det ser ut som det är 8. Så allt vi har gjort under de senaste 10 minuterna ska du absolut aldrig göra. Du kommer att se kod som gör detta. Det behöver inte vara så enkelt som detta. Du kunde ha 2 variabler och 1 variabel råkar vara en sträng och den andra variabeln råkar vara en int, och sedan lägga till dessa variabler tillsammans. Eftersom PHP är dynamiskt skrivit och det kommer inte att göra någon typ kontroll för dig och eftersom det är svagt skrivit och eftersom det kommer bara automatiskt kasta dessa saker tillsammans och allt bara fungerar, är det svårt att ens veta att denna variabel ska vara en sträng nu, så jag ska inte lägga till denna variabel, vilket är ett heltal. Bästa praxis är om en variabel är en sträng, hålla det som en sträng för evigt. Om en variabel är en int, hålla den som en int evigt. Om du vill ta itu med heltal och strängar, Du kan använda varsint - det är JavaScript. Intval. Jag gör det hela tiden. PHP och Javascript jag blandar ihop allting. Så intval kommer att returnera heltalsvärdet av en variabel. Om vi ​​passerar i "tryck (intval ('123 ')); du får 123. Intval själv kommer inte att göra kontrollen för oss att det är enbart ett heltal. PHP manualen, det finns bara så många funktioner tillgängliga, så här tror jag vad jag skulle använda är is_numeric först. Jag gissar att returneras falskt. Det är en annan sak som vi måste gå över är ===. Så is_numeric ('123df), skulle du inte tänka på det som is_numeric. I C du måste iterera över alla tecken och kontrollera om varje karaktär är siffran eller vad som helst. Här is_numeric kommer att göra det åt oss, och det är tillbaka falsk. Så när jag tryckt att skrivas ingenting, så här jag jämföra det att se, var du råkar vara falsk? Och så nu är det utskrift 1. Tydligen skriver 1 som gäller i stället för att skriva ut sant som sant. Jag undrar om jag gör print_r. Nej, det gör det fortfarande 1. Att gå tillbaka till === finns == fortfarande, och om du pratar med Tommy att han ska säga == är helt bra. Jag ska säga att == är fruktansvärt och du bör aldrig använda ==. Skillnaden är att == jämför saker där det kan vara sant, även om de inte är av samma typ, medan === jämför saker och Först kontrollerar är de av samma typ? Ja. Okej, nu ska jag se om de faktiskt jämföra vara lika. Du får konstiga saker som 10 är lika med - låt oss se vad det säger. Så ('10 '== 1 e1'); Detta returnerar true. Har någon några gissningar varför detta returnerar sant? Det handlar inte bara om det. Kanske är detta en ledtråd. Men om jag ändra det till en F - darn det! Jag håller med citationstecken. Anledningen till att citationstecken skriker på mig är att jag har lagt detta i citationstecken. Så jag kunde fly citattecken i här, men apostrof gör det lättare. Så ('10 '== 1 f1'); inte ut riktigt. ('10 '== 1 e1'); skriver sant. [Elev] Är det hex? >> Det är inte hex, men det är nära att det är som - 1E1, grundpotensform. Det erkänner 1E1 som en * 10 ^ 1 eller något annat. Det är lika heltal. Om vi ​​gör === då det kommer att vara falsk. Jag har faktiskt ingen aning om vi gör == vad om (10 och '10abc '); Okej. Så det är sant. Så precis som när du gjorde (10 + '10abc "), och det skulle vara 20, Här (10 == '10abc '); är sant. Ännu värre är saker som (falsk == NULL); är sant eller (falskt == 0); är sant, (falskt == []); Det finns konstiga fall - Det är en av de konstiga fall. Observera att (falskt == []); är sant. ('0 '== False), är sant. ('0 '== []); Är falskt. Så == är på intet sätt transitiva. en kan vara lika med b och en kan vara lika med c, men B inte kan vara lika med c.. Det är en styggelse för mig, och du bör alltid använda ===. [Elev] Kan vi göra! == Också? >> [Bowden] Ja. Motsvarande skulle vara! = Och! ==. Detta är faktiskt växte upp i pset spec där många funktioner tillbaka - PHP manualen är bra om det här. Det sätter en stor röd ruta, "Detta kommer att returnera false om det finns ett fel." Men återvänder 0 är en helt rimlig sak att återvända. Tänk om någon funktion som förväntas återgå ett heltal. Låt oss säga denna funktion är tänkt att räkna antalet rader i en fil eller något. Under normala omständigheter, passerar du den här funktionen en fil och det kommer att återvända ett heltal som representerar antalet rader. Så 0 är en helt rimligt antal om filen är bara tomt. Men om du passerar det en ogiltig fil och funktionen råkar returnera false om du klarar det en ogiltig fil? Om du bara gör == du inte skilja fallet mellan ogiltig fil och tom fil. Använd alltid ===. Det är alla dessa. I PHP är arrayen typ annorlunda än vad du är van vid i C. I själva verket kanske du redan har märkt detta ovan när du såg att det är av typen array. Fästet Syntaxen är nytt från och med PHP 5,4, som är den senaste versionen av PHP. Innan detta kan du alltid haft att skriva array ('a' -> 1, 'b' -> 2. Det var konstruktören för en matris. Nu PHP har äntligen kommit runt till trevliga syntax bara hakparenteser, vilket är bara så mycket bättre än matris. Men med tanke på PHP 5,4 är den nyaste versionen, du kan stöta platser som inte ens har PHP 5.3. Under sommaren körde vi i denna fråga där PHP 5,3 var vad vi hade på apparaten, men den server som vi utplacerade alla våra klass bok och lämna in och allt det där till var PHP 5,4. Att inte veta detta har vi utvecklat under 5,3, knuffade till 5,4, och nu helt plötsligt ingen av vår kod fungerar eftersom det råkade ha skett förändringar mellan 5,3 och 5,4 som inte är bakåtkompatibelt, och vi måste gå och fixa alla våra saker som inte fungerar för PHP 5,4. För denna klass, eftersom apparaten inte har PHP 5,4, Det är väl bra att använda hakparenteser. Men om du letar upp saker runt på Internet, om du letar upp någon form av matris saker, mest troligt att du kommer att se förtrollningen ut Array-konstruktorn syntax eftersom det har funnits sedan PHP föddes och offentlig fäste syntax har funnits under de senaste par månader eller när 5,4 kom runt. Så här gör du index. Precis som i C hur du skulle index med hakparenteser som $ array [0], $ array [1], $ array [2], du indexerar på samma sätt om du råkar ha din index är strängar. Så $ array ['a'] och $ array ['b']. $ Array [b]. Varför skulle detta vara fel? Det kommer förmodligen generera en varning men fortfarande fungerar. PHP tenderar att göra det. Det tenderar att bara, "jag ska varna dig om det här, men jag ska bara fortsätta "Och göra vad jag kan." Det kommer sannolikt att översätta detta till en sträng, men det är möjligt att någon gång i det förflutna någon sade definiera b för att vara "Hello World". Så nu B kan vara en konstant och $ array [b] faktiskt kommer att göra "Hello World". Jag tror på denna punkt, eller åtminstone våra PHP-inställningar, om du försöker index i en array och att nyckeln inte finns, kommer det att misslyckas. Jag tror inte att det bara kommer att varna dig. Eller åtminstone kan du ställa in den så att den inte bara varna dig, det bara rakt upp misslyckas. Sättet du kontrollera om det faktiskt är ett sådant index är isset. Så isset ($ array ['Hello World']) kommer att återvända falskt. isset ($ array ['b']) kommer att återvända sant. Du kan blanda dessa syntax. Jag är ganska säker på vad denna array skulle hamna är - Vi kan testa det. Åh, jag behöver PHPWord. Detta blandar syntax där du anger vad nyckeln är och du inte anger vad nyckeln är. Så 3 här är ett värde. Du har inte uttryckligen sagt vad dess nyckel kommer att bli. Vad tror du det nyckel kommer att bli? [Elev] 0. >> Jag gissar 0 bara för att det är den första vi har inte specificerats. Vi kan faktiskt göra ett par av dessa fall. Så print_r är ut rekursiv. Det kommer att skriva ut hela uppsättningen. Det skulle skriva ut subanordningarna i matrisen om det fanns några. Så print_r ($ array), php.test.php. Det ser ut som det gav den 0. Det är faktiskt något att tänka på här, men vi återkommer till det i en sekund. Men om jag råkar göra detta index 1? PHP skiljer inte mellan sträng index och heltal index, så på denna punkt har jag bara definierat ett index 1 och jag kan göra både $ array [1] och $ array ['1 '] och det kommer att vara samma index och samma nyckel. Så nu vad tror du 3 kommer att bli? >> [Elev] 2. >> [Bowden] Jag gissar 2. Ja. Det är 2. Tänk om vi gjorde detta är 10, är ​​detta 4? Vad tror du index 3 kommer att bli? Jag tänker 11. Min gissning vad PHP gör - och jag tror att jag har sett det här förut - är det håller bara reda på vad det högsta numeriska indexet den används hittills är. Det kommer aldrig att tilldela en sträng index 3. Det kommer alltid att vara ett numeriskt index. Så det håller reda på den högsta en det tilldelade hittills, vilket råkar vara 10, och det kommer att ge 11 till 3. Vad jag sa tidigare, märker hur det skriver denna array. Den skriver nyckeln 10, nyckel 4, 11, nyckel d.. Eller ens låta oss göra - Jag antar att jag inte satt en 0, men det är utskrift 1, 2, 3, 4. Vad händer om jag byter här? Eller låt oss faktiskt byta dessa 2. Nu skriver 2, 1, 3, 4. PHP: s arrayer är inte precis som din vanliga hashtabell. Det är helt rimligt att tänka på dem som hashtabeller 99% av tiden. Men i din hashtabeller finns det ingen känsla av ordning som saker in. Så snart som du sätter in i din hashtabell, antar det finns ingen länkad lista och du kan döma i en länkad lista som infördes först. Men här vi in ​​2 först och den vet när den skrivs ut denna array som 2 kommer först. Det skrivs inte ut det i bara någon ordning. Den tekniska datastruktur som det använder är en ordnad karta, så det kartlägger nycklar till värden och det minns i vilken ordning dessa nycklar infördes. I grunden är det vissa komplikationer där det är irriterande att faktiskt - Låt oss säga att du har en array 0, 1, 2, 3, 4, 5 och du vill ta ut index 2. Ett sätt att göra det, låt oss se vad som ser ut som. 0, 2, 1, 3, 4. Unset råkar nollställa både variabler och index array. Så unset ($ array [2]); Nu vad det kommer att se ut? 2 är bara borta, så det är väl bra. Mer irriterande är om du vill att saker faktiskt vara som en matris. Jag sätter slumptal. Nu märker jag index. Jag vill att det ska bara vara som en C array där det går från 0 till längd - 1 och jag kan iterera över den som sådan. Men så fort jag frånkoppla det andra indexet, vad var i index 3 inte blivit index 2. Istället tar bort just det indexet och nu går 0, 1, 3, 4. Det är helt rimligt. Det är bara irriterande och du måste göra saker som array skarv. Ja. [Elev] Vad skulle hända om du hade en for-slinga och du ville gå över alla element? När det slår 2, skulle det ge någonsin? Iterera över en array. Det finns 2 sätt att göra det. Du kan använda en vanlig for-slinga. Detta är en annan invecklade av PHP. De flesta språk, skulle jag säga, har någon form av längd eller len eller något indikerar längden på en array. I PHP är det räknas. Så räkna ($ array), $ i + +) Låt oss bara skriva ut ($ array [$ i]); Observera: Undefined offset: 2. Det kommer bara att misslyckas. Detta är anledningen till att, för det mesta, att du aldrig behöver iterera över en array som denna. Det kan vara en överdrift, men du behöver aldrig iterera över en array som denna eftersom PHP erbjuder sina foreach syntax där foreach ($ array som $ post). Nu om vi trycker ($ post), - we'll diskutera det i en andra - som fungerar alldeles utmärkt. Det sätt som foreach arbetar är det första argumentet är arrayen som du iteration över. Och det andra argumentet, objekt genom varje pass av for-slingan det kommer att ta på nästa sak i arrayen. Så kom ihåg matrisen har en beställning. Första gången genom for-slingan är posten kommer att bli 123 då blir det 12 då blir det 13 då blir det 23 då blir det 213. Saker och ting blir väldigt konstigt när du gör något som foreach. Låt oss se vad som händer eftersom du aldrig ska göra detta. Tänk om vi unset ($ array [1]); Som förmodligen var väntat. Du iteration över denna array, och varje gång du deaktivera det första indexet. Så för index 0, tar det första punkt på värde 0, så det kommer att bli 123. Men inuti for-slingan vi unset index 1, så det betyder 12 är borta. Så ut. PHP_EOL. PHP_EOL är bara nyrad, men det är tekniskt mer portabel eftersom nya rader i Windows skiljer sig från radbrytningar på Mac och UNIX. I Windows nyrad är \ r \ n, medan överallt annars tenderar bara vara \ n. PHP_EOL är konfigurerad så att den använder oavsett nyrad av ditt system. Så ut det. Låt oss inte print_r ($ array) i slutet. Jag hade ingen aning om att det skulle vara beteendet. Punkt tar fortfarande på värdet 12 även om vi nollställa 12 innan vi någonsin fick den från matrisen. Ta inte mitt ord på detta, men det ser ut som foreach skapar en kopia av matrisen och sedan posten tar på alla värden i den kopian. Så även om du ändrar arrayen inne i for-slingan, det kommer inte bry sig. Punkt tar på de ursprungliga värdena. Låt oss försöka deaktivera den. Tänk om det är $ array [1] = "Hej"; Även om vi sätter "Hej" i arrayen, tar posten aldrig på det värdet. Det finns en annan syntax för att foreach loopar där du sätter 2 variabler åtskilda av en pil. Denna första variabel kommer att vara nyckeln för detta värde, och denna andra variabel kommer att vara exakt samma objekt. Detta är ointressant här, men om vi går tillbaka till vår ursprungliga fråga om "a" -> 1, "B" -> 1, här om vi bara iterera för varje array som objekt är objektet kommer att bli 1 varje gång. Men om vi vill också veta nyckeln associerad med det objektet då vi gör som $ key -> $ objekt. Så nu kan vi göra utskrift ($ key. ':'. Nu är det iteration över och skriva varje knapp och dess tillhörande värde. En ytterligare sak vi kan göra i foreach loopar är att du kan se den här syntaxen. Et-tecken innan variabelnamn tenderar att vara hur PHP gör referenser. Där hänvisningar är mycket lika pekare, du inte har pekare, så att du aldrig ta itu med minnet direkt. Men du har referenser där 1 variabel avser samma sak som en annan variabel. Inuti här vi gör $ objekt. Låt oss gå tillbaka till 1, 10. Låt oss göra $ objekt + +, det finns fortfarande i PHP. Du kan fortfarande göra + +. php.test.php. Jag måste skriva ut det. print_r ($ matris); Vi trycker 2, 11. Om jag bara hade gjort foreach ($ array som $ post) då objektet blir värdet 1 första gången genom slingan. Det kommer att öka från 1 till 2 och vi är klara. Så då kommer det att gå igenom det andra passet av slingan och objektet är 10. Det steg post till 11, och sedan som bara kastas bort. Då vi print_r ($ array), och låt oss se till att detta bara är 1, 10. Så ökningen vi gjorde var förlorat. Men foreach ($ array som & $ post) Nu denna post är samma objekt som denna här. Det är samma sak. Så $ objekt + + är att ändra rad 0. I princip kan du också göra $ k -> $ objekt och du kan göra $ array [$ k] + +; Så ett annat sätt att göra det är vi fria att modifiera objekt, men det kommer inte att ändra vår ursprungliga arrayen. Men om vi använder k, som är vår nyckel, vi kan då bara index i vår array med denna nyckel och öka det. Denna mer direkt ändrar vår ursprungliga arrayen. Du kan även göra det om du av någon anledning ville möjlighet att ändra - Egentligen är detta helt rimligt. Du ville inte behöva skriva $ array [$ k] + +, du ville bara skriva $ objekt + + men du fortfarande ville säga if ($ k === "a") sedan öka objektet och sedan skriva ut vår array. Så nu vad vi förväntar oss print_r göra? Vilka värden ska skrivas? [Studerande] 2 och 10. >> [Bowden] Endast om nyckeln var "en" vi faktiskt ut som. Du har förmodligen mycket sällan, om någonsin, måste definiera funktioner i PHP, men du kan se något liknande där du definierar en funktion som funktion oavsett. Vanligtvis skulle du säga ($ foo, $ bar) och sedan definiera det vara vad som helst. Men om jag gör det, så betyder det att allt samtal oavsett, vad kallar baz, så det första argumentet som skickas till baz kan ändras. Låt oss göra $ foo + +; och insidan av här låt oss göra baz ($ post); Nu är vi kallar en funktion. Argumentet är tagen som referens, vilket innebär att om vi ändrar det vi ändrar det som antogs i. Och skriva det vi förväntar oss - om jag trasslat syntax - vi fick 2, 11, så det var faktiskt ökas. Märker vi behöver referenser i 2 platser. Vad händer om jag gjorde det här? Vad betyder det här? [Elev] Det kommer att förändras. >> Ja. Objektet är bara en kopia av värdet i arrayen. Så posten ändras till 2, men arrayen ['a'] kommer fortfarande att vara 1. Eller tänk om jag gör det? Nu objektet skickas som kopia till baz. Så kopian av argumentet kommer att ökas till 2, men själva objektet aldrig ökas till 2. Och punkt är samma sak som array fäste oavsett, så att matris aldrig ökas. Så båda dessa platser behöver det. PHP är oftast ganska smarta om detta. Du kanske tror att jag vill passera genom hänvisning - Detta var faktiskt en fråga om en av de psets. Det var en questions.txt sak där det stod, Varför vill du kanske passera denna struct genom hänvisning? Vad var svaret på det? [Eleven] Så du behöver inte kopiera något stort. >> Ja. En struktur kan vara godtyckligt stor, och när du passerar struct in som ett argument den behöver för att kopiera hela den struktur för att ge det till funktionen, medan om du passerar bara struct genom hänvisning då behöver bara kopiera en 4-byte adress som argument till funktionen. PHP är lite smartare än så. Om jag har någon funktion, och jag övergår till det en rad 1.000 saker, betyder att det kommer att behöva kopiera alla 1.000 av dessa saker att passera den i funktion? Det behöver inte göra det omedelbart. Om insidan av denna funktion aldrig ändrar foo, så om ($ foo === "Hej") return true.; Märker vi aldrig ändrat argumentet insidan av denna funktion, vilket innebär att allt antogs i så foo aldrig behöver kopieras eftersom det inte är att ändra den. Så hur PHP fungerar är argumenten skickas alltid med referens tills du prova faktiskt att ändra den. Nu om jag säger $ foo + +, det kommer nu att göra en kopia av den ursprungliga foo och ändra kopian. Detta sparar tid. Om du aldrig vidröra denna massiva array, du aldrig ändra det, det behöver inte göra kopian, medan om vi sätter bara denna ampersand det betyder att det inte ens kopiera den även om du ändrar det. Detta beteende kallas copy-on-write. Du ser det på andra ställen, speciellt om du tar en kurs operativsystem. Copy-on-write är en ganska vanlig mönster där du inte behöver göra en kopia av något om det inte är faktiskt förändras. Ja. [Eleven] Tänk om du hade ökningen inom test, så bara 1 del av 1.000 skulle behöva förändras? Jag är inte säker. Jag tror att det skulle kopiera det hela, men det är möjligt att det är smart nog att - Egentligen, vad jag tänker är föreställa hade vi en array som ser ut så här: $ matris2 = [ Då index "a" är en matris av [1 2 3 4], och index "b" är en matris med vad som helst. Jag behöver kommatecken mellan alla dessa. Föreställ finns kommatecken. Sedan "c" är värdet 3. Okej. Låt oss nu säga att vi gör $ Baz ($ matris2); där baz inte ta detta som referens. Så $ foo ['c'] + +; Detta är ett sådant exempel där vi passerar matris2 som ett argument och sedan modifierar ett specifikt index av uppsättningen genom att öka den. Jag har ärligt talat ingen aning om vad PHP kommer att göra. Det kan lätt göra en kopia av hela saken, men om det är smart, det kommer att göra en kopia av dessa tangenter där det kommer att ha sin distinkta värde men detta kan ändå peka till samma array 1,2,3,4 och detta kan fortfarande peka till samma array. Jag ska iPad den. Vi passerar i denna array där denna kille pekar på 3, den här killen pekar på [1,2,3,4], denna killen pekar på [34, ...] Nu när vi passerar den till baz, vi ändrar det. Om PHP är smart, det kan bara göra - Vi hade fortfarande att kopiera något minne, men om det var dessa enorma kapslade subsystem Vi behövde inte kopiera dem. Jag vet inte om det är vad den gör, men jag kan tänka mig att det gör det. Detta är också en ganska stor fördel av C över PHP. PHP gör livet så mycket lättare för en massa saker, men du typ av har absolut ingen aning om hur bra det kommer att fungera eftersom jag har ingen aning under huven när det gör dessa kopior av saker, Oh, är det kommer att bli en konstant tid kopia, det bara att byta 1 pekare, det kommer att bli en löjligt svår linjär kopia? Tänk om det inte kan hitta utrymme? Behöver den då att köra skräpsamling för att få lite mer utrymme? Och sophämtning kan ta godtyckligt lång. I C behöver du inte oroa dig för dessa saker. Varenda linje du skriver kan du ganska mycket resonera kring hur det kommer att utföra. Låt oss se tillbaka på dessa. Hur trevligt är det att du inte behöver ta itu med hash funktioner, länkade listor, eller något sånt? Sedan arbeta med hashtabeller är så lätt nu, här en rolig pussel att arbeta med. Öppna en fil som heter unique.php och i den skriver en PHP-program (Även känd som en "script"). Vi tenderar att kalla dem skript om de är korta saker som du kör på kommandoraden. I grund och botten, vilket språk som helst som du inte kompilera men du kommer att köra den körbara på kommandoraden, kan du kalla det körbara skript. Jag kunde lika gärna skriva en C-program som gör detta, men jag kallar det inte ett manus sedan jag först kompilera och kör den binära. Men denna PHP-program ska vi kalla ett skript. Eller om vi skrev det i Python eller Perl eller Node.js eller någon av dessa saker, vi skulle kalla dem alla skript eftersom du kör dem på kommandoraden men vi sammanställa dem inte. Vi kan göra det här ganska snabbt. Vi kommer inte att använda argv. Låt oss bara blåsa igenom det här. Kalla det unika, skriva ett program. Du kan anta att ingången kommer att innehålla ett ord per rad. Egentligen kommer argv vara ganska trivialt att använda. unique.php. Första sak först, vill vi att kontrollera om vi har passerat 1 kommandoraden argument. Precis som du förväntar argc och argv i C, har vi fortfarande de i PHP. Så om ($ argc! == 2) då jag inte kommer att behandla skriva ett meddelande eller något. Jag ska bara avsluta, felkod av 1. Jag kunde också återvända 1. Sällan i PHP är du på detta tillstånd där vi är på - Vanligtvis du är i en funktion som kallas en funktion som kallas en funktion som kallas en funktion. Och om något går fel och du bara vill lämna allt helt, utgång slutar strax programmet. Detta finns också i C. Om du är i en funktion i en funktion i en funktion i en funktion och du vill bara döda programmet kan du ringa avsluta och det kommer bara avsluta. Men i PHP är det ännu mer sällsynt att vi är på denna toppnivå. Vanligtvis är vi inne någon form av funktion, så vi kallar exit så att vi inte behöver återvända upp 1 sak som sedan inser att det finns ett fel så som returnerar upp om som erkänner det fanns ett fel. Vi vill inte ta itu med det, så avsluta (1); retur (1), i detta fall skulle vara likvärdiga. Vad vi vill öppna vi vill fopen. Argumenten kommer att se ganska lika. Vi vill fopen ($ argv [1], och vi vill öppna den för läsning. Som returnerar en resurs som vi ska ringa f.. Detta ser ganska lik hur C gör det utom vi inte har att säga FIL *. Istället säger vi bara $ f. Okej. Egentligen tror jag att detta även ger oss en vink om PHP-funktion som kallas fil. PHP-fil. Vad detta kommer att göra är att läsa en hel fil i en matris. Du behöver inte ens behöver fopen det. Det kommer att göra det åt dig. Så $ linjer = fil ($ argv [1]); Nu alla rader i filen är i rader. Nu vill vi sortera raderna. Hur kan vi sortera raderna? Vi sorterar raderna. Och nu kan vi skriva ut dem eller vad som helst. Förmodligen det enklaste sättet är foreach ($ linjer som $ rad) echo $ linje; [Elev] Skulle vi korsar ens linjer genom att referera något i slag? Det är där slaget skulle definieras som funktion sort (& $ array). När du ringer den funktion du inte passera genom referens. Det är den funktion som definierar det som att ta det som referens. Detta är faktiskt precis vad som gick fel när vi sätter allt till våra servrar när vi gick från 5,3 till 5,4. Fram till 5,4, detta var helt rimligt. En funktion förväntar sig inte att ta det som referens, men du kan skicka den som referens så om funktionen inte råkar ändra det, det är fortfarande ändras. Från och med 5,4, du är inte meningen att göra detta. Så nu är det enda sättet du passera genom hänvisning är om funktionen uttryckligen gör det. Om du inte vill att den ska ändra det, så måste du göra $ kopia = $ linjer och passera kopia. Så nu linjer kommer att bevaras och kopiera ändras. php.unique.php. Jag kanske har trasslat upp något. Oväntat "Sortera". Det kommer att vara något som gör detta åt oss. Det är inte ens där. Lägg märke till när man läser den manual som det första argumentet förväntas vara en array och det har tagit genom hänvisning. Varför är detta klagar till mig? Eftersom jag har denna funktion Sortera fortfarande här som jag inte vill. Okej, php.unique.php. Jag klarade inte det ett argument för att jag inte har en fil. Det är php.unique.php på test.php. Här är test.php alla skrivas ut i en sorterad fin ordning. Observera att sorterad ordning är lite konstigt för en kod fil eftersom alla våra tomma rader kommer att komma först sedan kommer att komma alla våra 1 nivå fördjupningar sedan kommer alla våra några försänkningar. Ja. >> [Elev] Så för källkoden inte antogs av referens? Är det gick allmänt värde? [Bowden] När du ringer en funktion, aldrig avgör om det antogs genom hänvisning. Det är funktionsdefinitionen som avgör om den antogs genom hänvisning. Och titta på funktionen definition av slag eller bara tittar på detta, det tar argument som referens. Så oavsett om du vill att den ska ta det med hänvisning tar det den som referens. Det ändrar arrayen på plats. Detta är helt enkelt inte tillåtet. Du är inte tillåtet att göra detta. >> [Elev] Åh, okej. [Bowden] Detta är typ kommer att ta linjer genom hänvisning och ändra det. Och återigen, om du inte vill att det ska göra det, kan du göra en kopia av slag. Även i detta fall, är kopia inte faktiskt en kopia av linjer. Den pekar bara samma sak tills det först blir modifierad, där det först gå att få ändras i sorteringsfunktionen, där, eftersom det är copy-on-write, nu en kopia av kopia kommer att göras. Du kan också göra detta. Det är den andra plats som du kan se ampersand. Du ser det i foreach loopar, ser du det i funktionsdeklarationer, och du ser det när bara tilldela variabler. Nu har vi åstadkommit något genom att göra detta eftersom kopiering och linjer är bokstavligen samma sak. Du kan använda linjer och kopiera omväxlande. Du kan göra unset ($ kopia), och som inte unset linjer, du förlorar bara din hänvisning till samma sak. Så från och med denna punkt, nu linjer är det enda sättet du kan komma rader. Frågor? Ja. [Elev] Helt off topic, men du behöver inte stänga PHP med - >> Du gör det inte. Okej. [Bowden] Jag skulle gå så långt som att säga att det är dålig praxis att stänga dem. Det är förmodligen en överdrift, speciellt i ett manus, men låt oss se vad som händer om jag gör detta. Det gjorde ingenting. Vad händer om jag ville - [suckar] Jag behöver skicka ett argument. Skjuta. Jag kallade det fel. Så php.unique.php med ett argument. Nu har jag inte ens behöver det här. Jag ska förmedla det ett giltigt argument. Denna tryckta vad det är utskrift. Jag skriver kopiera och kopiera finns inte. Så linjer. Det tryckta allt, och sedan märker allt detta skräp här nere, eftersom PHP allt som är utanför PHP-taggar är bara att skrivas ut ordagrant. Det är därför HTML, det är så skönt att jag kan göra div bla, bla, bla klass eller vad som helst, bla, bla, bla och sedan göra några PHP-kod och sedan göra slut div. Och nu skriver detta får jag min fina div uppe, allt som PHP tryckta, div nedtill. Katastrofalt när något sådant här händer, vilket är ganska vanligt, bara en herrelös nyrad på botten av filen. Du skulle inte tro att det skulle vara så stor av en affär tills man betänker det faktum att med webbläsare - Hur omdirigerar arbete eller i princip alla rubriker arbete, när du gör din anslutning till en webbplats och det skickar tillbaka alla dessa rubriker och saker Liksom svar 200 eller svar omdirigera eller vad som helst, rubriker är endast giltiga fram till den första byte data skickas. Du kan omdirigera tusentals gånger, men så snart som den första byten av data skickas du är inte tänkt att omdirigera igen. Om du har en herrelös nyrad på botten av en fil och låt oss säga att du använder den här funktionen och sedan vill - Låt oss säga att det är en annan fil som är index.php och du require_once något - Jag kan inte tänka ett bra exempel på det. Frågan händer när denna linje längst ner blir ekade. Du vill inte något att ha ekade ännu. Även om du inte tänker på någonting blir ekade, gjorde något får ekade och så nu du inte ska skicka fler rubriker och du kommer att få klagomål. Du bara behöver inte dessa avslutande taggar. Om du planerar att göra något med HTML - och det är helt rimligt att göra här nere div helst och sedan på denna punkt kan du eller kan du inte inkludera dem. Det spelar egentligen ingen roll. Men i PHP-skript är det ovanligt att stänga den. När allt är PHP, absolut allt, du egentligen inte behöver stänga den / du ska inte stänga den. Att handskas med strängar är mycket trevligare än i C. I PHP kan du ange en sträng med enkla eller dubbla citattecken. Med enkla citationstecken kan du inte använda "escape"-sekvenser. Ständigt fly, bla, bla, bla. Så printf är mycket sällsynt i PHP. Jag antar att jag skulle använda printf om jag ville göra ett slags sak - i pset 5 du använde sprintf eller vad som helst. Men du vill göra 001.jpg och 002.jpg. Så för sånt där jag vill faktiskt att formatera texten jag skulle använda printf. Men annars skulle jag bara använda strängsammanfogning. Jag har aldrig riktigt använda printf. Vi bara skilja detaljerna mellan enkla citationstecken och dubbla citat. Den största skillnaden är att enkla citattecken, kommer det att skrivas bokstavligt. Det finns ingen röding datatyp i PHP, till skillnad från C, så detta är likvärdig med detta. De är båda strängarna. Och det fina med enstaka citat strängar är jag kunde säga "Hej världen!" bla, bla, bla, $ $ Wooo. Vad händer när jag skriver ut det skriver ut det bokstavligen. Låt oss bli av med alla våra grejer. Så echo $ str1; Det tryckta bokstavligen alla dessa saker: dollartecken, omvänt snedstreck n, som man skulle kunna tro skulle vara radbrytningar - alla dessa saker det skrivs bokstavligen. Det enda du behöver för att fly är enkla citattecken eftersom det annars skulle tro det stänga enkla citattecken. Dubbla citattecken, helt annorlunda. Vi ser redan syntaxmarkering är cluing oss till vad som är på väg att gå fruktansvärt fel. php.unique. Odefinierad variabel: Wooo eftersom detta tolkas som en variabel som heter Wooo. Citattecken låter dig infoga variabler i - Låt oss säga $ name = "Rob"; Så echo "Hej, mitt namn är $ namn!"; Det erkänner detta som en variabel. När jag kör det - och jag kommer att sätta in en ny rad - Hej, jag heter Rob! och hej världen! Detta beror på att jag aldrig bort tryckningen av Wooo ovan. Det finns 1 ytterligare steg du kan göra. $ Array = [1, 2, 3]; Vad händer om jag vill skriva ut den första index array? Du gör $ array [0]. De syntaxmarkering är en ledtråd. Vad kommer detta att göra? php.unique. Hej, mitt namn är 1! vilket är inte vad jag ville. Syntaxmarkering ljög för mig. Låt oss försöka "a" -> 1, 'b' -> 2. Det är så jag skulle behöva skriva det. Oväntad enda citat (T_ENCAPSED bla, bla, bla, bla, bla). Tanken är att det inte är att erkänna detta som en del av gruppen. Det är inte erkänna detta som matris indexeras av bokstaven A. Du vill göra det omgiven av klammerparenteser, och nu allt som är i detta klammerparentes kommer interpoleras, vilket är det ord vi använder för magiskt sätta dessa variabler i de rätta ställena. Nu gör detta, php.unique och Hej, mitt namn 1! som väntat eller Hej, jag heter Rob! En sak som är ganska trevligt om enkla citattecken är att - Det finns en viss kostnad för interpolering. Om du använder citationstecken, måste tolken att gå över denna sträng, att se till att, "Åh, här är en variabel. Nu måste jag gå och hämta den variabeln och sätta in det här." Även om du inte använder några variabler, ingenting inuti dessa citationstecken måste interpoleras, men det kommer fortfarande att vara långsammare eftersom det måste gå över de dubbla citattecken letar efter saker som måste interpoleras. Så apostrof kan vara lite snabbare om ingenting behöver interpoleras, och jag brukar även använda enkla citattecken för "Hej, mitt namn är". $ Array ['a'] ändå. Det kommer att motsvara vad vi hade tidigare. Men det är en fråga om inställning. Om du använder PHP, du förmodligen inte bryr sig om skillnaden i hastighet. Det räcker inte att resonera dem till att börja med. Några definitiva frågor? Vi har faktiskt inte ens få igenom allt, men det här var tråkigt. Det sista som är ganska trevligt i PHP är när du arbetar med HTML, du kommer att använda den lite, så den fina genvägen syntaxen för att skriva ut en variabel. Utan att sätta PHP hit, detta kallas korta taggar. Officiellt som PHP 5,4, detta föråldrat. Du rekommenderas att sätta PHP. Detta stöds fortfarande, så korta taggar med