>> [MUSIK SPELA]
DOUG LLOYD: Okej.
Typ av en konstig fråga, eller hur?
Magiska tal.
Vad doe han menar när han är talar om magiska tal?
Tja, en del av programmen att vi har skrivit i CS50
hittills har haft några konstiga siffror slags kastat i dem.
Kanske skäl gör vi inte helt förstå just nu.
Till exempel i Mario problemet, vi capped höjden av pyramiden vid 23.
Vi uttryckligen sa att du kan inte gå högre än 23.
>> Men vad betyder 23 detta?
Tja, om du läser spec noga, du
kanske har sett att Anledningen till att vi utjämnade vid 23
beror på att standardhöjden av ett terminalfönster är 24.
Och så om vi har pyramid vara längre än så,
det kan göra detta konstig sak där den rinner av skärmen.
Och du vet, vad gör det innebär i sammanhanget, eller hur?
>> Är innebörden av 23 omedelbart uppenbara till någon som tittar på ditt program
och kanske har en annan storlek terminalfönster?
Antagligen inte.
Det verkar som, OK.
Tja, varför är det bara mindre än 23?
I allmänhet är det slags en dålig vana faktiskt
att skriva konstanter i din kod.
På så sätt, när du faktiskt gör skriva en konstant i koden,
det är ibland kallas att använda Magic Numbers, som är något
vi i allmänhet vill försöka undvika.
>> Till exempel, låt oss ta en titt på detta enkla funktion här.
Uppenbarligen finns det inga uppgifter typ i C kallas kort eller däck.
Så bara bära med mig.
Det är en liten bit av pseudo blandas i här.
Detta är en funktion som kallas hantera kort som tydligen
tar ett däck som sin parameter, och vilja utgång till mig ett enda kort.
>> Och jag gör något här där jag ha en slinga som går från 0 till 52,
och jag hantera ett kort.
Tja, vi har en magisk Antalet här till höger.
Ser du vad det magiska numret är?
Eller ännu viktigare, gör du se vad problemet är här?
Särskilt om detta är bara en funktion
i en egen fil i ett mapp som innehåller
ett gäng olika filer, av vilka var
gör en annan sak att en kortlek.
Kanske blandar dem, eller behandlar en hand av fem kort i stället för ett enda kort.
>> Ser du vad Problemet kan vara här?
Ser du det magiska talet Jag har injicerat i koden?
Det är 52, rätt.
>> Precis, intuitivt förmodligen vet, OK.
Som en vanlig kortlek med kort innehåller 52 kort.
Men i vårt program, det är bara typ av flyter runt där.
Det är som helt plötsligt finns det en 52.
>> Ett sätt att lösa detta problem är att göra detta.
Vi är mycket tydligt nu ropar däck storlek som 52.
Det ger det lite mer intuitiv det vill säga när i för slingan
senare vi då säga att jag är mindre än däck storlek.
Det verkar bara bättre än att säga 52.
Nu är detta inte faktiskt åtgärda problemet.
Det ger en viss symbolisk betyder att den konstanta.
Men den gör slags faktiskt införa ett annat problem
som kanske inte omedelbart uppenbara.
Även om denna variabel deklareras globally--
minns du vad det betyder när vi förklarar
en variabel globalt kontra lokalt?
Även om vi deklarerar en variabel globalt, tänk om det finns
en annan funktion i vår svit av funktioner
som handlar med kort manipulation som oavsiktligt ändrar däck storlek,
eller det ökar den genom 1 eller minskar det med en.
Det skulle kunna innebära problem, eller hur?
Speciellt om vi har att göra med en uppsättning kort där blandar hela däck
krävs.
Om däck storlek minskas genom en till exempel till 51,
vi faktiskt inte blanda alla korten möjligen.
Vi lämnar en av dem.
Och det värdet kan kanske vara förutses eller utnyttjas av en dålig skådespelare.
>> C ger vad som kallas en preprocessor direktivet, som
kallas också ett makro för skapa symboliska konstanter.
Och i själva verket har du redan sett ett direktiv preprocessor,
även om du inte har hört det kallas det med #include.
Det är ett annat exempel på ett makro eller preprocessor direktivet.
>> Sättet att skapa symboliska konstanter, eller ge ett namn till en konstant
så att det har mer vilket innebär, är följande.
#define, namn, ersättare.
Verkligen viktigt undan här verkligen snabbt.
Inte sätta ett semikolon på I slutet av dina #defines.
Så det är #define, namn, ersättare.
>> När ditt program kompileras, vad som egentligen händer
är kompilatorn om kommer att gå igenom din kod
och ersätta alla förekomster av ordet "namn" med vad du
sätta som ersättning.
Analogt, om #include är typ av liknande kopiera och klistra in,
då #define är typ av liknande sök och ersätt,
Om du någonsin använt den funktionen i en ordbehandlingsprogram, till exempel.
>> Så till exempel, om jag #define pi som 3.14159265,
om du är bättre matematiskt lutande och du plötsligt
se 3.14159265 flygande runt i din kod,
vet du förmodligen att det talar om pi.
Men kanske kan vi ge det en lite mer symbolisk innebörd.
Och vi kan i stället säga #define pi som munfull siffror
att jag inte kommer att hålla läsa om och om igen.
>> Och vad som kommer att hända sedan på kompilering är när programmet är
sammanställs, den första som kommer att hända är att det kommer att gå igenom
och det kommer att ersätta varje gång Det ser kapitalet P, kapital I,
Det kommer bokstavligen ersätta det med 3,14 och så vidare, så att man
behöver inte skriva in det varje tid medan programmet fortfarande
har den funktionalitet som du förväntar sig, eftersom du arbetar
med manipulering, multiplicera, dela, vad det än är med pi.
>> Du är inte begränsad till denna ersättning för endast siffror.
Till exempel kan jag #define kursen som strängen CS50.
I detta fall, när den Programmet sammanställs,
#define kommer att gå igenom kod, byt varje gång
det ser "kurs" med strängen CS50.
>> Du kommer att märka här också att jag ofta
#define alla mina definierade symbolisk konstanter, så att säga,
är alltid med stora bokstäver.
Det är en konvention.
Det är inte nödvändigt.
Anledningen allmänhet människor kommer att använda alla huvudstäder när de #defining
bara för att göra det riktigt klart att just denna del av min kod
är en definierad konstant.
Om det var gemener, är det möjligt att det skulle kunna förväxlas med en variabel.
Och det är förmodligen inte en bra sak att göra.
>> Så denna speciella lösning är mycket bättre
än någon av de tidigare.
Om jag först #define däck storlek 52, då nu min användning av 52, eller däck storlek här,
är mycket mer intuitivt och mycket säkrare.
Du kan inte manipulera en konstant.
Du kan inte säga 52 plus plus.
Det kommer inte att konvertera det till 53.
Du kan inte ändra 52 till något.
>> Du kan ändra en variabel vars värde är 52,
som var den första fix vi hade tidigare.
Och du kan öka denna variabel till 53.
Men du kan inte säga 52 plus plus och har som plötsligt vända 52 till 53.
52 är alltid 52.
Och så du inte kan oavsiktligt ändra däck storlek här genom att manipulera det,
>> En annan bra sida Effekten av detta är dock
som är du medveten om att inte alla länder runt om i världen
Använd en kortlek storlek 52?
Till exempel är det verkligen vanligt i Tyskland använder en kortlek storlek 32,
där de remsor ut några av de lägre valör.
Och i detta fall, jag ville port min svit
funktioner som hanterar kort manipulation till Tyskland.
Jag kunde i första hand vi visade, måste gå och ersätta
alla instanser av 52 i min kod med 32.
>> Men här, om jag #define däck storlek som 32 högst upp på min kod,
om jag behöver ändra det, jag kan bara gå och ändra på det en sak.
Kompilera min kod, och alla plötsligt fortplantar sig genom.
I själva verket kan vi ändra däck storlek något värde vi vill.
>> Kan jag intressera dig i en omgång däck size pickup?
>> Jag är Doug Lloyd.
Och detta är CS50.