>> [Musik spiller]
DOUG LLOYD: Okay.
Slags en mærkelig emne, ikke?
Magiske tal.
Hvad doe han mener, når han er taler om magiske tal?
Tja, nogle af de programmer, at vi har skrevet i CS50
hidtil har haft nogle underlige numre slags smidt i dem.
Måske grunde vi ikke helt forstår lige nu.
For eksempel i Mario problem, vi udjævnede højden af ​​pyramiden ved 23.
Vi udtrykkeligt sagde, at du kan ikke gå højere end 23.
>> Men hvad betyder 23 betyder?
Tja, hvis du læser spec omhyggeligt, du
måske har set, at Grunden til at vi udjævnede det ved 23
skyldes, at den standard højde af en terminal vindue er 24.
Og så hvis vi har den pyramide være højere end det,
det kunne gøre dette underlige ting hvor den løber ud af skærmen.
Og du ved, hvad betyder at betyde i sammenhæng, ikke?
>> Er meningen med 23 umiddelbart indlysende til nogen, der ser på dit program
og måske har en anden terminalvindue størrelse?
Sikkert ikke.
Det ser ud som, OK.
Tja, hvorfor er det lige under 23?
Generelt er det er sådan af en dårlig vane faktisk
at skrive konstanter ind i din kode.
Dermed når du rent faktisk gør skriver en konstant ind i din kode,
det er undertiden benævnt hjælp magiske tal, hvilket er noget
vi generelt ønsker at forsøge at undgå.
>> For eksempel, lad os tage et kig på dette enkle funktion her.
Selvfølgelig er der ingen data typen i C kaldes kort eller dæk.
Så bare bære over med mig.
Det er en lille smule pseudokode blandet i her.
Dette er en funktion kaldet behandle kort, der tilsyneladende
tager et dæk som parameter, og udsendes til mig et enkelt kort.
>> Og jeg gør noget her, hvor jeg har en løkke, der løber fra 0 til 52,
og jeg behandle et kort.
Tja, vi har en magisk nummer her, lige.
Kan du se, hvad det magiske nummer er?
Eller endnu vigtigere, gør du se, hvad problemet er her?
Især hvis det er blot én funktion
i sin egen fil i en mappe, der indeholder
en masse forskellige filer, som hver
gør en anden ting til et spil kort.
Måske blander dem, eller behandler en hånd fem kort i stedet for et enkelt kort.
>> Kan du se, hvad problem kunne være her?
Kan du se det magiske tal Jeg har sprøjtet ind i koden?
Det er 52, til højre.
>> Ligesom, intuitivt du sikkert ved, OK.
Ligesom en standard kortspil med kort indeholder 52 kort.
Men i vores program, det er bare slags flyder rundt derinde.
Det er ligesom lige pludselig er der en 52.
>> En måde at løse dette Problemet er at gøre dette.
Vi er meget eksplicit nu råber dæk størrelse som 52.
Det giver det lidt mere intuitiv hvilket betyder når i for-løkken
senere vi så sige, jeg er mindre end dæk størrelse.
Det virker bare bedre end at sige 52.
Nu er dette rent faktisk løse problemet.
Det giver nogle symbolske hvilket betyder, at den konstant.
Men det gør slags faktisk indføre et andet problem
der måske ikke være umiddelbart indlysende.
Selv om denne variabel erklæres globally--
Kan du huske, hvad det betyder, når vi erklærer
en variabel globalt versus lokalt?
Selv hvis vi erklærer en variabel globalt, hvad hvis der er
en anden funktion i vores suite af funktioner
at beskæftige sig med kort manipulation der uforvarende ændrer dæk størrelse,
eller det øger den ved 1 eller formindsker det med 1.
Det kunne stave problemer, ikke?
Især hvis vi har at gøre med et sæt af kort, hvor blander fuld dæk
er nødvendigt.
Hvis dækket størrelse mindskes med 1, for eksempel til 51,
Vi er faktisk ikke blander alle kortene evt.
Vi forlader en af ​​dem ud.
Og denne værdi kunne måske være forudsete eller udnyttes af en dårlig aktør.
>> C giver hvad der kaldes en præprocessor direktiv, som
kaldes også en makro til skabe symbolske konstanter.
Og i virkeligheden, har du allerede set en præprocessor direktiv,
selvom du ikke har hørt det kaldte det med #include.
Det er et andet eksempel på en makro eller præprocessor direktivet.
>> Den måde at skabe symbolske konstanter, eller give et navn til en konstant
således at det har mere betyder, er som følger.
#define, navn, udskiftning.
Virkelig vigtigt til side her virkelig hurtig.
Du må ikke sætte et semikolon på slutningen af ​​dine #defines.
Så det er #define, navn, udskiftning.
>> Når dit program er kompileret, hvad der faktisk sker
er compileren hvis vil at gå gennem din kode
og erstatte alle forekomster af ordet "navn" med hvad du
sætte som erstatning.
Analogt, hvis #include er sortering af ligner kopiere og indsætte,
derefter # define er sortering af lignende at finde og erstatte,
hvis du nogensinde har brugt denne funktion i et tekstbehandlingsprogram, for eksempel.
>> Altså for eksempel, hvis jeg # define pi som 3.14159265,
hvis du er bedre matematisk krængning og du pludselig
se 3.14159265 flyvende rundt i din kode,
du sikkert ved, det er at tale om pi.
Men måske kan vi give det en lidt mere symbolsk betydning.
Og vi kan i stedet sige #define pi som mundfuld numre
at jeg ikke har tænkt mig at holde læse igen og igen.
>> Og hvad der vil ske derefter på kompilere tidspunkt er, når programmet er
kompileret, den første ting, vil ske, er det vil gå igennem
og det vil erstatte hver gang den ser kapital P, kapital I,
det vil bogstaveligt erstatte det med 3.14 og så videre, så du
behøver ikke at skrive det hver tid, mens dit program stadig
har den funktionalitet, som du forventer, fordi du arbejder
med manipulation, multiplikation, dividere, hvad det er ved pi.
>> Du er ikke begrænset til denne substitution for kun tal.
For eksempel kunne jeg # define kursus som strengen CS50.
I dette tilfælde, når Programmet er kompileret,
# define vil gå gennem kode, udskiftes hver gang
det ser "kursus" med strengen CS50.
>> Du vil opdage her også, at jeg ofte
# define alle mine definerede symbolsk konstanter, så at sige,
er altid i alle hætter.
Det er en konvention.
Det er ikke påkrævet.
Grunden generelt folk vil bruge alle hovedstæder, når de er #defining
er bare for at gøre det virkelig klart, at denne særlige element i min kode
er en defineret konstant.
Hvis det var små bogstaver, er det muligt, at Det vil kunne forveksles med en variabel.
Og det er nok ikke en god ting at gøre.
>> Så denne særlige opløsning er meget bedre
end nogen af ​​de tidligere.
Hvis jeg først #define dæk størrelse 52, så nu er min brug af 52, eller dæk størrelse her,
er meget mere intuitiv og meget sikrere.
Du kan ikke manipulere en konstant.
Man kan ikke sige 52 plus plus.
Det kommer ikke til at konvertere det til 53.
Du kan ikke ændre 52 til noget.
>> Du kan ændre en variabel hvis værdi er 52,
som var det første fix, vi havde før.
Og du kan øge denne variabel til 53.
Men du kan ikke sige 52 plus plus og har der pludselig slå 52 ind 53.
52 er altid 52.
Og så kan du ikke uforvarende ændrer dæk størrelse her ved at manipulere det,
>> En anden god side Effekten af ​​denne er dog
der er du klar over, at der ikke alle lande rundt om i verden
bruge et spil kort i størrelse 52?
For eksempel, det er virkelig almindeligt i Tyskland at anvende et dæk på 32,
hvor de strimler nogle af de lavere kort værdi.
Og i dette tilfælde, jeg ønskede at port min suite
funktioner, der beskæftiger sig med card manipulation til Tyskland.
Jeg kunne i første omgang vi viste, nødt til at gå og erstatte
alle forekomster af 52 i min kode med 32.
>> Men her, hvis jeg # define dæk størrelse som 32 på toppen af ​​min kode,
hvis jeg har brug for at ændre det, kan jeg bare gå og ændre det én ting.
Genkompilere min kode, og alle pludselig udbreder sig gennem.
I virkeligheden, kan vi ændre dæk størrelse til enhver værdi, vi ønsker.
>> Kan jeg interesserer dig i en spil dæk størrelse pickup?
>> Jeg er Doug Lloyd.
Og det er CS50.