DOUG LLOYD: Okej. Så nu ska vi ta itu med en riktigt stort ämne, funktioner. Hittills under, alla program som vi har skrivit har skrivits inne i huvud. De är ganska enkla program. Du behöver inte ha alla dessa grenar och saker som händer. Vi kan bara passa alla insidan av huvud- och det får inte hemskt överväldigande. Men som kursen pågår och när du börjar att utveckla program självständigt, är de förmodligen kommer att börja få en mycket mer än 10 eller 15 linjer. Du kan få hundratals eller tusentals eller tiotusentals rader kod. Och det är verkligen inte den galna en tanke. Som sådan, är det förmodligen inte en bra idé att hålla allt inne i huvud. Det kan bli lite svårt att hitta vad du letar efter om du gör det. Lyckligtvis, även om C, och ganska mycket varannan programmeringsspråk som kan arbeta med, gör oss att skriva funktioner. Och jag ska bara ta en snabb åt sidan här nämna att funktioner är ett område i datavetenskap. Och du kommer att se många fler av dem på olika punkter under kursens gång och om du fortsätter på. Där det finns en hel del synonymer för samma ord. Så vi kallar funktioner. Men du kan också höra dem kallade förfaranden, eller metoder, i synnerhet om du har någonsin gjort någon objektorienterad programmering before-- och oroa dig inte Om du inte har, inte en stor Deal-- men i revision orienterade språk ofta kallas metoder. Ibland är kallade subrutiner. Men de verkligen refererar alla till samma grundidé. Låt oss se vad den idén är. Vad är en funktion? Väl en funktion är verkligen inget mer än en svart låda. En svart låda som har en uppsättning av noll eller flera ingångar och en enda utgång. Så till exempel, detta kan vara en funktion. Detta är en funktion som kallas funk. Och det krävs tre ingångar a, b och c. Och inuti den svarta lådan, vi vet inte exakt vad det gör, men den behandlar ingångarna på något sätt och då det ger en enda utgång, i detta fall, z. Nu för att göra det lite mindre abstrakt, vi kan säga att vi kanske ha en funktion som kallas lägg som tar tre ingångar a, b, och c och bearbetar utsignalen på något sätt inuti den svarta lådan att producera en enda utsignal. Så i detta fall, om lägg tar 3, 6, och 7. Någonstans inuti lägga funktion, vi skulle förvänta sig att läggas samman för att framställa produkten, som är tre plus 6 plus 7 eller 16. På samma sätt har du en funktion som kallas mult som tar två ingångar, a och b, bearbetar dem på något sätt en sådan att utsignalen från funktionen är produkten av de två insignalerna. De två ingångarna multipliceras med varandra. 4 och 5 får passera in i mult, något händer, utgången vi förväntar oss är 20. Varför kallar vi det en svart låda? Tja, om vi inte skriver fungerar själva, som Vi har gjort en hel del så långt CS50. Vi har sett utskrifts f, till exempel, som är en funktion som vi inte skriva oss, men vi använder hela tiden. Om vi ​​inte skriver funktionerna själva, vi egentligen inte behöver veta hur det är faktiskt genomförs under huven. Så till exempel den svarta lådan I bara visade dig för multiplikation, Multipla a, kan b vara defined-- och detta är bara några pseudocode-- kunde vara definieras som produktion gånger b. Det vettigt, eller hur. Om vi ​​har en funktion som kallas mult som tar två ingångar. Vi förväntar oss att produktionen skulle vara de två ingångarna multipliceras med varandra, a gånger b. Men mult kan också vara genomförs så här, vi har en räknarvariabeln att få ställa inuti mult till 0. Och då är vi upprepa denna process b gånger lägga till en till disk. Till exempel, om vi multiplicerar 3a genom 5b, vi kunde säga satt mot 0, upprepa fem gånger, tillsätt 3 till disken. Så vi börjar på 0 och sedan vi detta fem gånger 3, 6, 9, 12, 15. Det är samma resultat. Vi fortfarande få 3 gånger 5 bara genomförandet är annorlunda. Det är vad vi menar när vi säger en svart låda. Det betyder bara att vi bryr mig egentligen inte hur det genomförs under huven så länge som utgången är vad vi förväntar oss. I själva verket är att en del av avtalet att använda funktioner, särskilt funktioner som andra skriver. Beteendet kommer alltid vara typiskt, oförutsägbar baserat på namnet på funktionen. Och det är därför det är verkligen viktigt när du skriver funktioner eller när andra människor skriver funktioner som du kan använda, att dessa funktioner har tydliga, relativt tydliga namn, och är väl dokumenterade. Som säkerligen är fallet för funktion som utskrifts f. Så varför använder vi funktioner? Väl som jag sa tidigare, om vi skriver all vår kod inuti viktigaste sakerna kan bli riktigt besvärligt och mycket komplicerat. Funktioner tillåter oss förmågan att organisera saker och bryta upp ett mycket komplicerat problem i mycket mer hanterbara underdelar. Funktioner tillåter oss också till förenkla kodningsprocessen. Det är mycket lättare att felsöka en 10 linjefunktion kontra en 100 linje funktion eller en 1000 linjefunktion. Om vi ​​har bara att felsöka små bitar åt gången, eller skriva små bitar på tiden, det gör att erfarenhet av programmering mycket bättre. Lita på mig om det. Till sist, om vi skriver funktioner vi kan återanvända de olika delarna. Funktioner kan återvinnas. De kan användas i ett program eller en annan. Du har redan skrivit funktionen, allt du behöver göra är att berätta att programmet var man kan hitta denna funktion. Vi har återvinning och användning print f i över 40 år. Men det var bara skrivit en gång. Ganska bra, eller hur. Okej. Så fungerar är stora. Vi vet att. Nu börja skriva dem. Låt oss börja få dem i våra program. För att göra detta, den första vi gör är deklarera funktionen. När du deklarerar en funktion vad du i princip göra säger kompilatorn, hej, bara så ni vet, Jag kommer att skriva en funktion senare och här är vad det kommer att se ut. Anledningen till detta är eftersom kompilatorer kan göra några konstiga saker om de ser en uppsättning av symboler att de inte är bekanta med. Så vi bara ge kompilatorn en heads up, jag skapar en funktion och det kommer att göra detta. Funktionsdeklarationer i allmänhet om så du organiserar din kod på ett sätt att andra kommer att kunna förstå och dra nytta av, du vanligtvis vill sätta alla av dina funktionsdeklarationer högst upp på din kod, höger innan du börjar skriva på även. Och enkelt, det finns en mycket standardformulär att varje funktion Förklaringen överensstämmer. De alla ganska mycket ser ut så här. Det finns tre delar till en funktion deklaration, returtyp, namn, och argumentlistan. Nu returtypen är vilken typ av variabel funktionen kommer utgång. Så till exempel, om vi tänker tillbaka minut sedan till att multiplicera två nummer funktion, vad förväntar vi oss om vi multiplicera ett heltal med ett heltal utgången kommer att vara förmodligen ett heltal, rätt. Multiplicerat två heltal tillsammans, får du ett heltal. Så returtyp av att funktion skulle vara int. Namn är vad du vill att ringa din funktion. Detta är förmodligen den minst viktiga del av funktionsdeklarationen, när det gäller funktionalitet. Men är faktiskt förmodligen en av de viktigaste delarna av funktionsdeklarationen när det gäller att veta vad funktionen faktiskt gör. Om du namnger din funktion f eller g eller h eller mystik eller nåt sånt, du förmodligen kommer att få lite löst upp försöker komma ihåg vad dessa funktioner gör. Så det är viktigt att ge din funktionens meningsfulla namn. Slutligen är argumentlistan kommaseparerad lista av alla ingångarna till din funktion, vilka vardera har en typ och ett namn. Så inte bara har du att ange vilken typ av variabel funktionen att mata ut, du också vill ange vilken typ och typer av variabler i Funktionen kommer att acceptera som insatsvaror. Så låt oss göra ett exempel här. Låt oss bara ta en titt på en mer konkret en. Så här är ett exempel på en funktion deklaration för en funktion som skulle lägga till två heltal tillsammans. Summan av två heltal kommer att vara ett heltal också, eftersom vi bara diskuteras. Och så returtypen, här i grönt, skulle vara int. Som bara berättar att lägga till två Ints kommer att, vid slutet av dagen, utgång, eller spotta tillbaka ut till oss, ett heltal. Med tanke på vad den här funktionen gör vi vill ge det ett lämpligt namn. Lägg till två Ints verkar lämpligt, med tanke på vi tar två heltal som insatsvaror och förhoppningsvis lägga samman dem. Det kan vara lite av en besvärlig namn och ärligt talat denna funktion är förmodligen inte nödvändigt eftersom vi har tillsats operatör, om du minns från vår diskussion om operatörer, tidigare. Men låt oss bara säga skull Argumentet att denna funktion är användbar och så vi kallar man lägga två Ints. Slutligen tar denna funktion två ingångar. Var och en av vilka är ett heltal. Så vi har denna kommatecken separerad lista av insatsvaror. Nu är vi i allmänhet vill namnge en av dem så att de kan användas inom funktionen. Namnen är inte särskilt viktig. I det här fallet har vi inte nödvändigtvis har någon mening knutna till dem. Så vi kan bara kalla dem a och b. Det är helt bra. Men om du hittar själv i en situation där namnen på variablerna kan faktiskt vara viktigt, kanske du vill kalla dem något annat än a och b att ge dem något mer symboliskt meningsfullt. Men i detta fall, gör vi inte riktigt vet något annat om funktionen. Vi vill bara lägga till två heltal. Så vi ska bara ringa de heltal a och b. Det är ett exempel. Varför tar du inte en sekund att tänka på detta, hur skulle du skriver en funktion deklaration för en funktion som multiplicerar två flyttal? Minns du vad en flyttal är? Vad skulle denna funktion deklaration ser ut? Jag rekommenderar verkligen du pausa videon här och ta hur mycket tid du behöver. Tänk på vad detta funktionsdeklarationen skulle vara? Vad skulle returtypen vara? Vad skulle ett meningsfullt namn vara? Vad skulle ingångarna vara? Så varför inte göra en paus i videon här och skriva upp en funktion deklaration för en funktion som skulle föröka två flyttal tillsammans. Förhoppningsvis du pausade videon. Så låt oss ta en titt på ett exempel av en möjlig förklaring. Float Mult två realer flyta x, float y. Produkten från två flyttal, som minns är hur vi representera reella tal eller siffror med decimalvärden i c, kommer att bli ett flyttal. När du multiplicerar en decimal av en decimal, du förmodligen kommer att få en decimal. Du vill ge det en relevant namn. Multiplicera två realer verkar bra. Men du kan verkligen kalla det Mult två flottörer eller Mult flottörer. Något liknande, så länge som det gav några verkliga innebörden av vad denna svarta lådan skulle göra. Och återigen, i det här fallet har vi inte verkar ha någon mening fäst till namnen på de variabler vi passerar i, så vi bara kalla dem x och y. Nu om du kallar dem något annars, det är helt bra. I själva verket, om du gjorde denna förklaring i stället med användning av dubbel istället av flyter, om ni minns att dubbel är en annan sätt att mer precist ange reella tal eller flyttal variabler. Det är helt bra också. Antingen en av dem skulle vara bra. I själva verket finns det flera olika kombinationer sätt att förklara denna funktion. Men dessa är två ganska bra. Vi har förklarat en funktion, det är bra. Vi har berättat kompilatorn vad det är, vad vi ska göra. Nu ska vi faktiskt skriver denna funktion. Låt oss ge det en definition, så att insidan den svarta lådan förutsägbart beteende som händer. I själva verket är vi multiplicera två real siffror tillsammans, eller lägga till nummer tillsammans, eller göra vad det är att vi bad vår funktion att göra. Så i själva verket, låt oss försöka definiera multiplicera två realer som vi just talade om en sekund sedan. Nu i början av en funktionsdefinition ser nästan exakt samma som en funktion deklaration. Jag har dem båda här. På toppen är funktionsdeklarationen, typ, namn, kommaseparerad argument listan, semikolon. Semikolon indikerar att som är en funktion deklaration. Början av funktionen definition ser nästan exakt samma, typ, namn, kommaseparerad argumentlistan, ingen semikolon, öppna klammerparentes. Den öppna klammerparentes, precis som vi har gjort med huvud, innebär att vi nu börjar definiera vad som händer inuti den svarta lådan som Vi har valt att kalla Mult två reals. Här är ett sätt att genomföra det. Vi skulle kunna säga, vi kunde deklarera en ny variabel av typen float kallas produkt och tilldela variabel till värdet x gånger y. Och sedan tillbaka produkten. Vad betyder avkastning menar här. Väl avkastning är vägen Vi visar att det är hur vi passerar utgången backa ur. Så tillbaka något, är densamma som, detta är utsignalen från den svarta lådan. Så det är hur du gör det. Här är ett annat sätt att genomföra det. Vi kunde bara tillbaka x gånger y. x är ett flöte. y är ett flöte. Så x gånger y är också en flottör. Vi behöver inte ens till skapa en annan variabel. Så det är ett annat sätt att genomföra exakt samma svarta lådan. Ta nu en stund, pausa videon igen, och försöka definiera lägga till två Ints, vilket är den andra funktionen som vi talade om för en stund sedan. Även här har jag lagt funktionen deklarationen, och så semikolon, och ett öppet klammerparentes och ett stängt lockigt stag för att ange var vi kommer att fylla i innehållet i lägga till två Ints, så att vi definierar den speciella beteende i den svarta lådan. Så pausa videon. Och ta så mycket tid som du måste försöka definiera en implementering av lägga till två ints, såsom att när funktionen utmatar ett värde, den gör det, i själva verket, retur summan av de två ingångarna. Så precis som det tidigare exemplet, det finns flera olika sätt att du skulle kunna genomföra lägga till två Ints. Här är en. Här inne i orange har jag bara hade några comments-- Jag har just lagt några kommentarer för att indikera vad som händer på varje kodrad. Så jag deklarerar en variabel kallas summan av typen int. Jag säger summan är lika med ett plus b. Det är där vi faktiskt gör arbetet att lägga a och b tillsammans. Och jag återvänder summa. Och det är vettigt eftersom Summan är en variabel av typen int. Och vad är den datatyp som detta Funktionen säger mig att det kommer att produktionen? Int. Så jag åter summa som är en heltalsvariabel. Och det är vettigt med tanke på vad vi har deklareras och definierat vår funktion att göra. Nu kan du också definiera funktionen på detta sätt, int summa motsvarar en plus b-- hoppa över den först step-- och sedan tillbaka summan. Nu kan du också genomfört det här sättet, som jag starkt rekommenderar inte. Detta är dåligt stil för en sak och verkligen dålig design, men den gör det, i själva verket, arbete. Om du tar den här koden, som är int lägg dålig adderaren punkt c, och använda den. Det faktiskt tillför två heltal tillsammans. Det är en mycket dålig implementering av denna speciella beteende. Men det fungerar. Det är bara här för att illustrera den punkt som vi egentligen inte bry sig om vad som händer inuti den svarta lådan, så länge eftersom det har utgång som vi förväntar oss. Detta är ett dåligt utformade svart låda. Men i slutet av dagen, gör det fortfarande utgång summan av ett plus b. Okej. Så vi har förklarat funktioner. Och vi har definierat funktionen. Så det är riktigt bra. Nu börjar använda funktionerna att vi har deklarerats och vi har definierat. Om du vill ringa ett function-- det faktiskt ganska easy-- allt du behöver göra är ge det lämpliga argument, argument datatyp att det förväntar sig och sedan tilldela retur värdet av denna funktion och this-- vändning mig-- tilldela returvärdet för denna funktion till något av rätt typ. Så låt oss ta en titt på detta i praktiken i en fil kallas adderare 1 dot c, som Jag har i min CS50 IDE. Så här är adderare 1 dot c. I början ser jag har min omfattar pund inkluderar, standard IO, och CS50 dot h. Och då jag har min funktionsdeklarationen. Det är där jag är berättar kompilatorn jag kommer att skriva en Funktionen kallas lägga till två Ints. Det kommer att mata ut en heltalstyp variabel. Det är vad den här delen är rätt här. Och då jag har två ingångar till en och B, som var och en är ett heltal. Inuti huvud, ber jag användaren ingång genom att säga, ge mig ett heltal. Och de uppmanas att glömma int, vilket är en funktion som ingår i CS50 biblioteket. Och det får lagras i x, en heltalsvariabel. Då kan vi få dem till ett annat heltal. Vi får ett annat heltal och lagra det i y. Och sedan, här på ledningen 28, är där vi gör vår funktionsanrop. Vi säger, int z jämlikar tillsätt 2 Ints x kommatecken y. Ser du varför detta är vettigt? x är ett heltal typ variabel och y är ett heltal typ variabel. Så det är bra. Det vettigt med vad vår funktion deklaration på rad 17 ser ut. Den kommaseparerad ingångslista Parlamentet förväntar sig två heltal, a och b. I så fall kan vi ringa dem vad vi vill. Det förväntar sig bara två heltal. Och x är ett heltal och y är ett heltal. Som fungerar. Och vi vet att funktionen går att mata ut en heltal också. Och så vi lagrar utmatning av funktionen, lägga till två ints, i ett heltal typ variabel, som vi kallar z. Och då kan vi säga, summan av procent i och procent i är procent i. x, y och z respektive fylla i de procent i talet. Vad är definitionen av lägga till två Ints ser ut? Det är ganska enkelt. Det är en av de vi bara såg en sekund sedan, int summa motsvarar en plus b returbelopp. Fungerar det? Låt oss spara filen. Och sedan ner här på min terminal Jag kommer att göra adderaren 1, och rensar jag min skärm. Jag kommer att zooma in eftersom jag vet det är lite svårt att se. Så vi sammanställa det här programmet som adderare 1. Så vi kan göra punkt snedstreck adderare 1. Ge mig ett heltal, 10. Ge mig en annan heltal, 20. Summan av 10 och 20 är 30. Så vi gjorde ett lyckat anrop funktion. Du kan köra funktionen igen, negativ 10, är ​​17 summan av -10 och 17 7. Den här funktionen fungerar. Den har beteendet att vi förväntar oss att. Och så har vi gjort en lyckad funktion, definition, förklaring, och ett lyckat anrop funktion. Par diverse punkter om funktioner innan vi avslutar det här avsnittet. Minns från vår diskussion om datatyper, tidigare, som fungerar kan ibland ta några ingångar. Om så är fallet, vi förklara funktion såsom att ha en tomrumsargumentlistan. Minns du vad vanligaste funktion vi har sett hittills som tar ett tomrum argumentlistan är? Det huvudsakliga. Minns också att funktionen ibland faktiskt inte har en utgång. I så fall, deklarerar vi funktionen ha en typ void avkastning. Låt oss avsluta detta avsnitt att ta itu med en praxis problem. Så här är problemet anges. Jag vill att du ska skriva en funktion kallas giltiga triangel. Vad den här funktionen ska göra är att ta tre reella tal som representerar längden på tre sidor av en triangel som dess parametrar, eller dess argument, eller dess inputs-- annan uppsättning synonymer som du kan stöta på. Denna funktion bör antingen utgång sant eller falskt beroende på om dessa tre längder är kapabla att göra en triangel. Kommer du ihåg datatyp som vi används för att ange sant eller falskt? Nu hur gör du genomföra detta? Tja vet att det finns ett par av reglerna om trianglar som är faktiskt bra att veta. En triangel kan bara ha sidor med positiv längd. Det känns logiskt. Du förmodligen säger, duh. Den andra saken att notera är dock att summan av längderna av varje två sidor av triangeln måste vara större än den längden på den tredje sidan. Det är faktiskt sant. Du kan inte ha en triangel av sidorna 1, 2 och 4, till exempel på grund 1 plus 2 inte är större än fyra. Så de är de regler som bestämma om tre eller inte ingångar kan tänkas bilda en triangel. Så ta ett par minuter och deklarera och sedan definiera denna funktion kallas giltiga triangel, så att det faktiskt har beteendet som anges här. Det kommer ut sant om dessa tre sidor är i stånd att innefattande en triangel, och i annat fall false Redo att se hur du gjorde? Här är en implementering giltig triangel. Det är inte den enda. Yours kan variera något. Men detta gör, i själva verket har det beteende som vi förväntar oss. Vi förklarar vår funktion vid högst upp, bool giltigt triangel flyta x float y flyta z. Så återigen, denna funktion tar tre reella tal som dess argument, flytande punkt värde variabler, och matar ut en sant eller falskt värde, vilket är en Boolean, återkallelse. Så det är därför returtypen är bool. Då kan vi definiera funktionen. Första vi gör är kontrollera att att alla sidorna är positiva. Om x är mindre än eller lika till 0, eller om y är lika med 0, eller om z är mindre än eller lika med 0, som inte kan möjligen vara en triangel. De har inte positiva sidor. Och så att vi kan återvända falskt i den situationen. Därefter kontrollerar vi att se till att att varje par av ingångar är större än det tredje en. Så om x plus y är mindre än eller lika med z, eller om x plus z är mindre än eller lika med y, eller om y plus z är mindre än eller lika med x, som också kan inte vara ett giltigt triangel. Så vi return false igen. Förutsatt vi passerade båda kontrollerna Men då kan vi return true. Eftersom dessa tre sidor är kapabla att returning-- att skapa en giltig triangel. Och det är allt. Du har nu förklarat och definieras. Och du kanske kan nu använda och kalla den här funktionen. Bra jobbat. Jag är Doug Lloyd. Detta är CS50.