1 00:00:00,000 --> 00:00:02,350 >> [MUSIK SPELA] 2 00:00:02,350 --> 00:00:05,444 3 00:00:05,444 --> 00:00:06,360 DOUG LLOYD: Okej. 4 00:00:06,360 --> 00:00:07,770 Typ av en konstig fråga, eller hur? 5 00:00:07,770 --> 00:00:09,050 Magiska tal. 6 00:00:09,050 --> 00:00:12,012 Vad doe han menar när han är talar om magiska tal? 7 00:00:12,012 --> 00:00:14,220 Tja, en del av programmen att vi har skrivit i CS50 8 00:00:14,220 --> 00:00:16,660 hittills har haft några konstiga siffror slags kastat i dem. 9 00:00:16,660 --> 00:00:19,680 Kanske skäl gör vi inte helt förstå just nu. 10 00:00:19,680 --> 00:00:23,950 Till exempel i Mario problemet, vi capped höjden av pyramiden vid 23. 11 00:00:23,950 --> 00:00:26,880 Vi uttryckligen sa att du kan inte gå högre än 23. 12 00:00:26,880 --> 00:00:28,702 >> Men vad betyder 23 detta? 13 00:00:28,702 --> 00:00:30,410 Tja, om du läser spec noga, du 14 00:00:30,410 --> 00:00:32,493 kanske har sett att Anledningen till att vi utjämnade vid 23 15 00:00:32,493 --> 00:00:36,160 beror på att standardhöjden av ett terminalfönster är 24. 16 00:00:36,160 --> 00:00:38,860 Och så om vi har pyramid vara längre än så, 17 00:00:38,860 --> 00:00:41,290 det kan göra detta konstig sak där den rinner av skärmen. 18 00:00:41,290 --> 00:00:45,140 Och du vet, vad gör det innebär i sammanhanget, eller hur? 19 00:00:45,140 --> 00:00:48,880 >> Är innebörden av 23 omedelbart uppenbara till någon som tittar på ditt program 20 00:00:48,880 --> 00:00:51,550 och kanske har en annan storlek terminalfönster? 21 00:00:51,550 --> 00:00:52,330 Antagligen inte. 22 00:00:52,330 --> 00:00:53,080 Det verkar som, OK. 23 00:00:53,080 --> 00:00:55,005 Tja, varför är det bara mindre än 23? 24 00:00:55,005 --> 00:00:56,880 I allmänhet är det slags en dålig vana faktiskt 25 00:00:56,880 --> 00:00:58,940 att skriva konstanter i din kod. 26 00:00:58,940 --> 00:01:02,190 På så sätt, när du faktiskt gör skriva en konstant i koden, 27 00:01:02,190 --> 00:01:05,630 det är ibland kallas att använda Magic Numbers, som är något 28 00:01:05,630 --> 00:01:08,030 vi i allmänhet vill försöka undvika. 29 00:01:08,030 --> 00:01:12,830 >> Till exempel, låt oss ta en titt på detta enkla funktion här. 30 00:01:12,830 --> 00:01:15,726 Uppenbarligen finns det inga uppgifter typ i C kallas kort eller däck. 31 00:01:15,726 --> 00:01:16,600 Så bara bära med mig. 32 00:01:16,600 --> 00:01:18,910 Det är en liten bit av pseudo blandas i här. 33 00:01:18,910 --> 00:01:21,050 Detta är en funktion som kallas hantera kort som tydligen 34 00:01:21,050 --> 00:01:26,570 tar ett däck som sin parameter, och vilja utgång till mig ett enda kort. 35 00:01:26,570 --> 00:01:30,990 >> Och jag gör något här där jag ha en slinga som går från 0 till 52, 36 00:01:30,990 --> 00:01:33,394 och jag hantera ett kort. 37 00:01:33,394 --> 00:01:35,310 Tja, vi har en magisk Antalet här till höger. 38 00:01:35,310 --> 00:01:38,790 Ser du vad det magiska numret är? 39 00:01:38,790 --> 00:01:42,280 Eller ännu viktigare, gör du se vad problemet är här? 40 00:01:42,280 --> 00:01:44,310 Särskilt om detta är bara en funktion 41 00:01:44,310 --> 00:01:48,030 i en egen fil i ett mapp som innehåller 42 00:01:48,030 --> 00:01:49,970 ett gäng olika filer, av vilka var 43 00:01:49,970 --> 00:01:51,670 gör en annan sak att en kortlek. 44 00:01:51,670 --> 00:01:57,310 Kanske blandar dem, eller behandlar en hand av fem kort i stället för ett enda kort. 45 00:01:57,310 --> 00:01:59,420 >> Ser du vad Problemet kan vara här? 46 00:01:59,420 --> 00:02:03,220 Ser du det magiska talet Jag har injicerat i koden? 47 00:02:03,220 --> 00:02:04,390 Det är 52, rätt. 48 00:02:04,390 --> 00:02:06,440 >> Precis, intuitivt förmodligen vet, OK. 49 00:02:06,440 --> 00:02:09,740 Som en vanlig kortlek med kort innehåller 52 kort. 50 00:02:09,740 --> 00:02:12,570 Men i vårt program, det är bara typ av flyter runt där. 51 00:02:12,570 --> 00:02:15,280 Det är som helt plötsligt finns det en 52. 52 00:02:15,280 --> 00:02:18,290 >> Ett sätt att lösa detta problem är att göra detta. 53 00:02:18,290 --> 00:02:22,724 Vi är mycket tydligt nu ropar däck storlek som 52. 54 00:02:22,724 --> 00:02:25,390 Det ger det lite mer intuitiv det vill säga när i för slingan 55 00:02:25,390 --> 00:02:28,650 senare vi då säga att jag är mindre än däck storlek. 56 00:02:28,650 --> 00:02:32,666 Det verkar bara bättre än att säga 52. 57 00:02:32,666 --> 00:02:34,290 Nu är detta inte faktiskt åtgärda problemet. 58 00:02:34,290 --> 00:02:38,460 Det ger en viss symbolisk betyder att den konstanta. 59 00:02:38,460 --> 00:02:40,820 Men den gör slags faktiskt införa ett annat problem 60 00:02:40,820 --> 00:02:43,770 som kanske inte omedelbart uppenbara. 61 00:02:43,770 --> 00:02:45,859 Även om denna variabel deklareras globally-- 62 00:02:45,859 --> 00:02:47,650 minns du vad det betyder när vi förklarar 63 00:02:47,650 --> 00:02:50,500 en variabel globalt kontra lokalt? 64 00:02:50,500 --> 00:02:53,340 Även om vi deklarerar en variabel globalt, tänk om det finns 65 00:02:53,340 --> 00:02:55,500 en annan funktion i vår svit av funktioner 66 00:02:55,500 --> 00:02:59,750 som handlar med kort manipulation som oavsiktligt ändrar däck storlek, 67 00:02:59,750 --> 00:03:02,727 eller det ökar den genom 1 eller minskar det med en. 68 00:03:02,727 --> 00:03:04,060 Det skulle kunna innebära problem, eller hur? 69 00:03:04,060 --> 00:03:08,261 Speciellt om vi har att göra med en uppsättning kort där blandar hela däck 70 00:03:08,261 --> 00:03:08,760 krävs. 71 00:03:08,760 --> 00:03:12,804 Om däck storlek minskas genom en till exempel till 51, 72 00:03:12,804 --> 00:03:14,970 vi faktiskt inte blanda alla korten möjligen. 73 00:03:14,970 --> 00:03:16,500 Vi lämnar en av dem. 74 00:03:16,500 --> 00:03:21,680 Och det värdet kan kanske vara förutses eller utnyttjas av en dålig skådespelare. 75 00:03:21,680 --> 00:03:24,920 >> C ger vad som kallas en preprocessor direktivet, som 76 00:03:24,920 --> 00:03:27,764 kallas också ett makro för skapa symboliska konstanter. 77 00:03:27,764 --> 00:03:30,180 Och i själva verket har du redan sett ett direktiv preprocessor, 78 00:03:30,180 --> 00:03:32,916 även om du inte har hört det kallas det med #include. 79 00:03:32,916 --> 00:03:37,150 Det är ett annat exempel på ett makro eller preprocessor direktivet. 80 00:03:37,150 --> 00:03:41,290 >> Sättet att skapa symboliska konstanter, eller ge ett namn till en konstant 81 00:03:41,290 --> 00:03:43,740 så att det har mer vilket innebär, är följande. 82 00:03:43,740 --> 00:03:47,030 #define, namn, ersättare. 83 00:03:47,030 --> 00:03:49,140 Verkligen viktigt undan här verkligen snabbt. 84 00:03:49,140 --> 00:03:54,180 Inte sätta ett semikolon på I slutet av dina #defines. 85 00:03:54,180 --> 00:03:57,310 Så det är #define, namn, ersättare. 86 00:03:57,310 --> 00:03:59,540 >> När ditt program kompileras, vad som egentligen händer 87 00:03:59,540 --> 00:04:01,740 är kompilatorn om kommer att gå igenom din kod 88 00:04:01,740 --> 00:04:06,770 och ersätta alla förekomster av ordet "namn" med vad du 89 00:04:06,770 --> 00:04:08,860 sätta som ersättning. 90 00:04:08,860 --> 00:04:13,060 Analogt, om #include är typ av liknande kopiera och klistra in, 91 00:04:13,060 --> 00:04:15,700 då #define är typ av liknande sök och ersätt, 92 00:04:15,700 --> 00:04:19,180 Om du någonsin använt den funktionen i en ordbehandlingsprogram, till exempel. 93 00:04:19,180 --> 00:04:26,345 >> Så till exempel, om jag #define pi som 3.14159265, 94 00:04:26,345 --> 00:04:28,720 om du är bättre matematiskt lutande och du plötsligt 95 00:04:28,720 --> 00:04:31,640 se 3.14159265 flygande runt i din kod, 96 00:04:31,640 --> 00:04:33,517 vet du förmodligen att det talar om pi. 97 00:04:33,517 --> 00:04:35,850 Men kanske kan vi ge det en lite mer symbolisk innebörd. 98 00:04:35,850 --> 00:04:39,850 Och vi kan i stället säga #define pi som munfull siffror 99 00:04:39,850 --> 00:04:42,110 att jag inte kommer att hålla läsa om och om igen. 100 00:04:42,110 --> 00:04:45,560 >> Och vad som kommer att hända sedan på kompilering är när programmet är 101 00:04:45,560 --> 00:04:48,530 sammanställs, den första som kommer att hända är att det kommer att gå igenom 102 00:04:48,530 --> 00:04:51,520 och det kommer att ersätta varje gång Det ser kapitalet P, kapital I, 103 00:04:51,520 --> 00:04:55,610 Det kommer bokstavligen ersätta det med 3,14 och så vidare, så att man 104 00:04:55,610 --> 00:04:58,090 behöver inte skriva in det varje tid medan programmet fortfarande 105 00:04:58,090 --> 00:05:00,631 har den funktionalitet som du förväntar sig, eftersom du arbetar 106 00:05:00,631 --> 00:05:05,090 med manipulering, multiplicera, dela, vad det än är med pi. 107 00:05:05,090 --> 00:05:08,230 >> Du är inte begränsad till denna ersättning för endast siffror. 108 00:05:08,230 --> 00:05:12,279 Till exempel kan jag #define kursen som strängen CS50. 109 00:05:12,279 --> 00:05:14,070 I detta fall, när den Programmet sammanställs, 110 00:05:14,070 --> 00:05:16,236 #define kommer att gå igenom kod, byt varje gång 111 00:05:16,236 --> 00:05:19,900 det ser "kurs" med strängen CS50. 112 00:05:19,900 --> 00:05:21,720 >> Du kommer att märka här också att jag ofta 113 00:05:21,720 --> 00:05:26,090 #define alla mina definierade symbolisk konstanter, så att säga, 114 00:05:26,090 --> 00:05:28,130 är alltid med stora bokstäver. 115 00:05:28,130 --> 00:05:28,960 Det är en konvention. 116 00:05:28,960 --> 00:05:30,170 Det är inte nödvändigt. 117 00:05:30,170 --> 00:05:33,900 Anledningen allmänhet människor kommer att använda alla huvudstäder när de #defining 118 00:05:33,900 --> 00:05:37,590 bara för att göra det riktigt klart att just denna del av min kod 119 00:05:37,590 --> 00:05:38,820 är en definierad konstant. 120 00:05:38,820 --> 00:05:43,730 Om det var gemener, är det möjligt att det skulle kunna förväxlas med en variabel. 121 00:05:43,730 --> 00:05:46,120 Och det är förmodligen inte en bra sak att göra. 122 00:05:46,120 --> 00:05:48,910 >> Så denna speciella lösning är mycket bättre 123 00:05:48,910 --> 00:05:50,550 än någon av de tidigare. 124 00:05:50,550 --> 00:05:59,950 Om jag först #define däck storlek 52, då nu min användning av 52, eller däck storlek här, 125 00:05:59,950 --> 00:06:01,850 är mycket mer intuitivt och mycket säkrare. 126 00:06:01,850 --> 00:06:03,280 Du kan inte manipulera en konstant. 127 00:06:03,280 --> 00:06:05,259 Du kan inte säga 52 plus plus. 128 00:06:05,259 --> 00:06:06,800 Det kommer inte att konvertera det till 53. 129 00:06:06,800 --> 00:06:09,390 Du kan inte ändra 52 till något. 130 00:06:09,390 --> 00:06:12,470 >> Du kan ändra en variabel vars värde är 52, 131 00:06:12,470 --> 00:06:14,870 som var den första fix vi hade tidigare. 132 00:06:14,870 --> 00:06:17,000 Och du kan öka denna variabel till 53. 133 00:06:17,000 --> 00:06:21,100 Men du kan inte säga 52 plus plus och har som plötsligt vända 52 till 53. 134 00:06:21,100 --> 00:06:23,350 52 är alltid 52. 135 00:06:23,350 --> 00:06:28,860 Och så du inte kan oavsiktligt ändra däck storlek här genom att manipulera det, 136 00:06:28,860 --> 00:06:29,940 137 00:06:29,940 --> 00:06:32,390 >> En annan bra sida Effekten av detta är dock 138 00:06:32,390 --> 00:06:38,310 som är du medveten om att inte alla länder runt om i världen 139 00:06:38,310 --> 00:06:40,690 Använd en kortlek storlek 52? 140 00:06:40,690 --> 00:06:45,630 Till exempel är det verkligen vanligt i Tyskland använder en kortlek storlek 32, 141 00:06:45,630 --> 00:06:48,020 där de remsor ut några av de lägre valör. 142 00:06:48,020 --> 00:06:50,960 Och i detta fall, jag ville port min svit 143 00:06:50,960 --> 00:06:55,390 funktioner som hanterar kort manipulation till Tyskland. 144 00:06:55,390 --> 00:06:59,440 Jag kunde i första hand vi visade, måste gå och ersätta 145 00:06:59,440 --> 00:07:03,570 alla instanser av 52 i min kod med 32. 146 00:07:03,570 --> 00:07:07,940 >> Men här, om jag #define däck storlek som 32 högst upp på min kod, 147 00:07:07,940 --> 00:07:11,730 om jag behöver ändra det, jag kan bara gå och ändra på det en sak. 148 00:07:11,730 --> 00:07:15,010 Kompilera min kod, och alla plötsligt fortplantar sig genom. 149 00:07:15,010 --> 00:07:18,850 I själva verket kan vi ändra däck storlek något värde vi vill. 150 00:07:18,850 --> 00:07:22,500 >> Kan jag intressera dig i en omgång däck size pickup? 151 00:07:22,500 --> 00:07:23,430 >> Jag är Doug Lloyd. 152 00:07:23,430 --> 00:07:25,840 Och detta är CS50. 153 00:07:25,840 --> 00:07:27,772