1 00:00:00,000 --> 00:00:02,350 >> [Muziek] 2 00:00:02,350 --> 00:00:05,444 3 00:00:05,444 --> 00:00:06,360 DOUG LLOYD: Oké. 4 00:00:06,360 --> 00:00:07,770 Kind van een vreemde onderwerp, toch? 5 00:00:07,770 --> 00:00:09,050 Magische getallen. 6 00:00:09,050 --> 00:00:12,012 Wat doe hij bedoelt als hij over magische getallen? 7 00:00:12,012 --> 00:00:14,220 Nou, een deel van de programma's dat we in CS50 heb geschreven 8 00:00:14,220 --> 00:00:16,660 tot nu toe hebben sommige rare gehad aantallen soort gegooid in hen. 9 00:00:16,660 --> 00:00:19,680 Misschien om redenen die we niet doen volledig begrijpen nu. 10 00:00:19,680 --> 00:00:23,950 Bijvoorbeeld, in het Mario probleem, we bedekte de hoogte van de piramide op 23. 11 00:00:23,950 --> 00:00:26,880 We expliciet gezegd dat je kan niet hoger zijn dan 23. 12 00:00:26,880 --> 00:00:28,702 >> Maar wat betekent 23 betekenen? 13 00:00:28,702 --> 00:00:30,410 Nou, als je de spec zorgvuldig, u 14 00:00:30,410 --> 00:00:32,493 misschien gezien dat de reden waarom we bedekte het op 23 15 00:00:32,493 --> 00:00:36,160 omdat de standaardhoogte van een terminal venster is 24. 16 00:00:36,160 --> 00:00:38,860 En dus als we de pyramide groter dan die, 17 00:00:38,860 --> 00:00:41,290 is het misschien een raar ding te doen waar het loopt van het scherm af. 18 00:00:41,290 --> 00:00:45,140 En weet je, wat doet dat betekent in de context, toch? 19 00:00:45,140 --> 00:00:48,880 >> Is de betekenis van 23 onmiddellijk duidelijk aan iemand die kijkt naar je programma 20 00:00:48,880 --> 00:00:51,550 en heeft misschien een andere grootte terminal venster? 21 00:00:51,550 --> 00:00:52,330 Waarschijnlijk niet. 22 00:00:52,330 --> 00:00:53,080 Het lijkt alsof, OK. 23 00:00:53,080 --> 00:00:55,005 Nou, waarom is het iets minder dan 23? 24 00:00:55,005 --> 00:00:56,880 In het algemeen, het is een soort van een slechte gewoonte eigenlijk 25 00:00:56,880 --> 00:00:58,940 constanten schrijven in uw code. 26 00:00:58,940 --> 00:01:02,190 Daarbij, als je eigenlijk doen schrijf een constante in uw code, 27 00:01:02,190 --> 00:01:05,630 het wordt soms aangeduid als het gebruik magische getallen, dat is iets 28 00:01:05,630 --> 00:01:08,030 we willen over het algemeen proberen te vermijden. 29 00:01:08,030 --> 00:01:12,830 >> Bijvoorbeeld, laten we eens een kijkje nemen Dit eenvoudige functie here. 30 00:01:12,830 --> 00:01:15,726 Uiteraard is er geen gegevens Typ C genaamd kaart of dek. 31 00:01:15,726 --> 00:01:16,600 Dus gewoon geduld met mij. 32 00:01:16,600 --> 00:01:18,910 Het is een beetje pseudocode gemengd in hier. 33 00:01:18,910 --> 00:01:21,050 Dit is een functie genaamd behandelen kaart die blijkbaar 34 00:01:21,050 --> 00:01:26,570 neemt een dek als parameter, en wil uitgang voor mij een enkele kaart. 35 00:01:26,570 --> 00:01:30,990 >> En ik ben hier om iets te doen waar ik een lus die loopt van 0 tot en met 52 36 00:01:30,990 --> 00:01:33,394 en ik om een ​​kaart. 37 00:01:33,394 --> 00:01:35,310 Nou, we hebben een magische gekregen nummer hier, rechts. 38 00:01:35,310 --> 00:01:38,790 Ziet u wat het magische getal is? 39 00:01:38,790 --> 00:01:42,280 Of nog belangrijker, wil je zien wat het probleem is hier? 40 00:01:42,280 --> 00:01:44,310 Vooral indien is slechts één functie 41 00:01:44,310 --> 00:01:48,030 in zijn eigen bestand in een map bevat 42 00:01:48,030 --> 00:01:49,970 een bos van verschillende files, die elk 43 00:01:49,970 --> 00:01:51,670 doet een ander ding om een ​​spel kaarten. 44 00:01:51,670 --> 00:01:57,310 Misschien schudt hen, of gaat een hand vijf kaarten in plaats van een enkele kaart. 45 00:01:57,310 --> 00:01:59,420 >> Ziet u wat de probleem zou hier zijn? 46 00:01:59,420 --> 00:02:03,220 Zie je het magische getal Ik heb geïnjecteerd in de code? 47 00:02:03,220 --> 00:02:04,390 Het is 52, rechts. 48 00:02:04,390 --> 00:02:06,440 >> Zoals, intuïtief weet je waarschijnlijk, OK. 49 00:02:06,440 --> 00:02:09,740 Als een standaard dek van kaarten bevat 52 kaarten. 50 00:02:09,740 --> 00:02:12,570 Maar in ons programma, het is gewoon soort rondzweven in. 51 00:02:12,570 --> 00:02:15,280 Het is als ineens is er een 52. 52 00:02:15,280 --> 00:02:18,290 >> Een manier om dit op te lossen probleem is om dit te doen. 53 00:02:18,290 --> 00:02:22,724 We zijn nu heel expliciet roepen het dek grootte als 52. 54 00:02:22,724 --> 00:02:25,390 Het geeft het een beetje meer intuïtief wat betekent dat wanneer in de lus 55 00:02:25,390 --> 00:02:28,650 Later wij dan zeggen, i minder dan dekgrootte. 56 00:02:28,650 --> 00:02:32,666 Het lijkt beter dan zeggen 52. 57 00:02:32,666 --> 00:02:34,290 Nu dit betekent eigenlijk het probleem op te lossen. 58 00:02:34,290 --> 00:02:38,460 Het geeft een aantal symbolische betekent de constante. 59 00:02:38,460 --> 00:02:40,820 Maar het soort eigenlijk ander probleem introduceren 60 00:02:40,820 --> 00:02:43,770 dat misschien niet direct duidelijk. 61 00:02:43,770 --> 00:02:45,859 Zelfs als deze variabele wordt verklaard globally-- 62 00:02:45,859 --> 00:02:47,650 herinnert u zich wat het betekent dat wanneer we verklaren 63 00:02:47,650 --> 00:02:50,500 een variabele globaal versus lokaal? 64 00:02:50,500 --> 00:02:53,340 Zelfs als we een variabele declareert wereldwijd, wat als er 65 00:02:53,340 --> 00:02:55,500 andere functie in onze suite van functies 66 00:02:55,500 --> 00:02:59,750 die deal met kaart manipulatie die per ongeluk verandert dek grootte, 67 00:02:59,750 --> 00:03:02,727 of verhoogt door 1 of verlaagt door 1. 68 00:03:02,727 --> 00:03:04,060 Dat kan spellen problemen, toch? 69 00:03:04,060 --> 00:03:08,261 Vooral als we te maken hebben met een set kaarten, waar het schudden van de volledige dek 70 00:03:08,261 --> 00:03:08,760 is vereist. 71 00:03:08,760 --> 00:03:12,804 Als het dek wordt verkleind 1 door, bijvoorbeeld, 51, 72 00:03:12,804 --> 00:03:14,970 we eigenlijk niet schuifelen alle kaarten mogelijk. 73 00:03:14,970 --> 00:03:16,500 We vertrekken een van hen uit. 74 00:03:16,500 --> 00:03:21,680 En die waarde kan misschien zijn voorspeld of uitgebuit door een slechte acteur. 75 00:03:21,680 --> 00:03:24,920 >> C biedt wat heet een preprocessor richtlijn, die 76 00:03:24,920 --> 00:03:27,764 wordt ook wel een macro voor creëren symbolische constanten. 77 00:03:27,764 --> 00:03:30,180 En in feite, al heb je gezien een richtlijn preprocessor, 78 00:03:30,180 --> 00:03:32,916 zelfs als je het nog niet gehoord riep dat met #include. 79 00:03:32,916 --> 00:03:37,150 Het is een ander voorbeeld van een macro of richtlijn preprocessor. 80 00:03:37,150 --> 00:03:41,290 >> De manier om symbolische constanten te maken, of het geven van een naam aan een constante 81 00:03:41,290 --> 00:03:43,740 zodat het meer betekenis is als volgt. 82 00:03:43,740 --> 00:03:47,030 #define, naam, vervanging. 83 00:03:47,030 --> 00:03:49,140 Echt belangrijk opzij hier erg snel. 84 00:03:49,140 --> 00:03:54,180 Zet geen puntkomma aan het einde van uw #defines. 85 00:03:54,180 --> 00:03:57,310 Dus het is #define, naam, vervanging. 86 00:03:57,310 --> 00:03:59,540 >> Wanneer het programma wordt samengesteld, wat er werkelijk gebeurt 87 00:03:59,540 --> 00:04:01,740 is de compiler wanneer gaan om te gaan door uw code 88 00:04:01,740 --> 00:04:06,770 en vervang elke instantie van het woord "naam" met alles wat je 89 00:04:06,770 --> 00:04:08,860 zet als vervanging. 90 00:04:08,860 --> 00:04:13,060 Analoog, als #include is een soort van vergelijkbaar met het kopiëren en plakken, 91 00:04:13,060 --> 00:04:15,700 dan is #define soort Soortgelijke zoeken en vervangen, 92 00:04:15,700 --> 00:04:19,180 als je ooit hebt gebruikt die functie in een tekstverwerkingsprogramma, bijvoorbeeld. 93 00:04:19,180 --> 00:04:26,345 >> Dus bijvoorbeeld als ik #define pi als 3.14159265, 94 00:04:26,345 --> 00:04:28,720 Als je beter bent wiskundig hellende en je plotseling 95 00:04:28,720 --> 00:04:31,640 zie 3.14159265 vliegen rond in uw code, 96 00:04:31,640 --> 00:04:33,517 u waarschijnlijk weet dat het over pi. 97 00:04:33,517 --> 00:04:35,850 Maar misschien kunnen we het eens beetje meer symbolische betekenis. 98 00:04:35,850 --> 00:04:39,850 En we kunnen in plaats daarvan zeggen #define pi als die hap van getallen 99 00:04:39,850 --> 00:04:42,110 dat ik ben niet van plan om te blijven lezen over en voorbij. 100 00:04:42,110 --> 00:04:45,560 >> En wat gaat er dan gebeuren bij compileren tijd is wanneer het programma is 101 00:04:45,560 --> 00:04:48,530 gecompileerd, het eerste ding dat zal gebeuren is het zal gaan door 102 00:04:48,530 --> 00:04:51,520 en het zal elke keer vervangen het ziet hoofdstad P, kapitaal I, 103 00:04:51,520 --> 00:04:55,610 het zal letterlijk vervangen door 3,14 enzovoorts, zodat je 104 00:04:55,610 --> 00:04:58,090 niet hoeft te elk type tijd, terwijl het programma nog steeds 105 00:04:58,090 --> 00:05:00,631 heeft de functionaliteit die u verwachten, want je werkt 106 00:05:00,631 --> 00:05:05,090 met manipuleren, te vermenigvuldigen, verdelen, wat het ook is door pi. 107 00:05:05,090 --> 00:05:08,230 >> Je niet beperkt tot deze vervanging van alleen cijfers. 108 00:05:08,230 --> 00:05:12,279 Zo kon ik #define Natuurlijk als de string CS50. 109 00:05:12,279 --> 00:05:14,070 In dit geval, wanneer de programma gecompileerd, 110 00:05:14,070 --> 00:05:16,236 #define zal gaan door de code, vervang elke keer 111 00:05:16,236 --> 00:05:19,900 het ziet "cursus" met de string CS50. 112 00:05:19,900 --> 00:05:21,720 >> U zult hier opmerken ook dat ik vaak 113 00:05:21,720 --> 00:05:26,090 #define al mijn gedefinieerd symbolische constanten zogezegd, 114 00:05:26,090 --> 00:05:28,130 zijn altijd in hoofdletters. 115 00:05:28,130 --> 00:05:28,960 Het is een conventie. 116 00:05:28,960 --> 00:05:30,170 Het is niet vereist. 117 00:05:30,170 --> 00:05:33,900 De reden dat het algemeen mensen zullen gebruiken alle hoofdsteden als ze #defining 118 00:05:33,900 --> 00:05:37,590 is alleen maar om het echt duidelijk dat maken dit bijzondere element van mijn code 119 00:05:37,590 --> 00:05:38,820 is een gedefinieerde constante. 120 00:05:38,820 --> 00:05:43,730 Als het kleine, is het mogelijk dat het zou kunnen worden verward met een variabele. 121 00:05:43,730 --> 00:05:46,120 En dat is waarschijnlijk niet een goede zaak te doen. 122 00:05:46,120 --> 00:05:48,910 >> Dus dit oplossing is veel beter 123 00:05:48,910 --> 00:05:50,550 dan elk van de voorgaande. 124 00:05:50,550 --> 00:05:59,950 Als ik voor het eerst #define dek maat 52, dan nu mijn gebruik van 52, of dek grootte hier, 125 00:05:59,950 --> 00:06:01,850 is veel meer intuïtief en een stuk veiliger. 126 00:06:01,850 --> 00:06:03,280 U kunt een constante niet manipuleren. 127 00:06:03,280 --> 00:06:05,259 Je kunt niet zeggen 52 plus plus. 128 00:06:05,259 --> 00:06:06,800 Dat gaat niet om te zetten naar 53. 129 00:06:06,800 --> 00:06:09,390 Je kunt niet veranderen 52 iets. 130 00:06:09,390 --> 00:06:12,470 >> U kunt een variabele veranderen waarvan de waarde is 52, 131 00:06:12,470 --> 00:06:14,870 dat was de eerste fix we eerder hadden. 132 00:06:14,870 --> 00:06:17,000 En je zou kunnen verhogen dat variabele 53. 133 00:06:17,000 --> 00:06:21,100 Maar je kunt niet zeggen dat 52 plus en plus hebben die opeens 52 tot 53. 134 00:06:21,100 --> 00:06:23,350 52 altijd 52. 135 00:06:23,350 --> 00:06:28,860 En dus kun je niet per ongeluk veranderen dek grootte hier door het manipuleren van het, 136 00:06:28,860 --> 00:06:29,940 137 00:06:29,940 --> 00:06:32,390 >> Een andere goede kant effect hiervan is echter 138 00:06:32,390 --> 00:06:38,310 dat bent u ervan bewust dat niet alle landen over de hele wereld 139 00:06:38,310 --> 00:06:40,690 gebruik maken van een spel kaarten van maat 52? 140 00:06:40,690 --> 00:06:45,630 Bijvoorbeeld, het is echt gebruikelijk in Duitsland naar een dek van 32 te gebruiken, 141 00:06:45,630 --> 00:06:48,020 waar ze ontdoen van een aantal de lagere waarde kaarten. 142 00:06:48,020 --> 00:06:50,960 En in dit geval, I wilde de haven mijn suite 143 00:06:50,960 --> 00:06:55,390 functies die betrekking hebben card manipulatie naar Duitsland. 144 00:06:55,390 --> 00:06:59,440 Ik kon in eerste instantie we toonde, moet gaan en te vervangen 145 00:06:59,440 --> 00:07:03,570 alle exemplaren van 52 in mijn code met 32. 146 00:07:03,570 --> 00:07:07,940 >> Maar hier, als ik #define dek formaat als 32 op de top van mijn code, 147 00:07:07,940 --> 00:07:11,730 als ik het nodig om het te veranderen, kan ik gewoon gaan en te veranderen dat een ding. 148 00:07:11,730 --> 00:07:15,010 Recompile mijn code, en al Ineens voortplant door. 149 00:07:15,010 --> 00:07:18,850 In feite, kunnen we deck veranderen grootte op een waarde die we willen. 150 00:07:18,850 --> 00:07:22,500 >> Kan ik u interesseren in een spel van het dek grootte pick-up? 151 00:07:22,500 --> 00:07:23,430 >> Ik ben Doug Lloyd. 152 00:07:23,430 --> 00:07:25,840 En dit is CS50. 153 00:07:25,840 --> 00:07:27,772