1 00:00:00,000 --> 00:00:02,500 [Powered by Google Translate] [Avsnitt 5 - Mer Bekväm] 2 00:00:02,500 --> 00:00:04,690 [Rob Bowden - Harvarduniversitetet] 3 00:00:04,690 --> 00:00:07,250 [Detta är CS50. - CS50.TV] 4 00:00:08,990 --> 00:00:14,250 >> Som jag sade i min e-post, det finns en massa saker som du kan använda 5 00:00:14,250 --> 00:00:17,060 annat än apparaten att faktiskt göra problemet uppsättningar. 6 00:00:17,060 --> 00:00:19,910 Vi rekommenderar att du gör det i apparaten bara för att vi lättare kan hjälpa dig 7 00:00:19,910 --> 00:00:22,070 och vi vet hur allt kommer att fungera. 8 00:00:22,070 --> 00:00:26,950 Men som ett exempel på där man kan göra saker om, säg, har du inte tillgång till 9 00:00:26,950 --> 00:00:31,570 till en apparat eller om du vill arbeta i Science Center källaren - 10 00:00:31,570 --> 00:00:33,090 som faktiskt de har apparaten också - 11 00:00:33,090 --> 00:00:35,150 Om du vill arbeta var som helst. 12 00:00:35,150 --> 00:00:42,370 Ett exempel är har du sett / hört talas om SSH? 13 00:00:44,380 --> 00:00:47,780 SSH är i princip precis som ansluter till någonting. 14 00:00:47,780 --> 00:00:51,340 Egentligen, just nu är jag SSHed i apparaten. 15 00:00:51,340 --> 00:00:54,290 Jag arbetar aldrig direkt i apparaten. 16 00:00:55,930 --> 00:01:01,060 Här är apparaten, och om du tittar här nere ser du denna IP-adress. 17 00:01:01,060 --> 00:01:03,650 Jag arbetar aldrig i själva apparaten; 18 00:01:03,650 --> 00:01:08,840 Jag kommer alltid fram till en iTerm2 fönster / terminalfönster. 19 00:01:08,840 --> 00:01:15,910 Du kan SSH för att den IP-adressen, ssh jharvard@192.168.129.128. 20 00:01:15,910 --> 00:01:20,390 Jag minns att antalet mycket lätt eftersom det är en sådan trevlig mönster. 21 00:01:20,390 --> 00:01:24,920 Men det kommer att fråga mig för mitt lösenord, och nu är jag i apparaten. 22 00:01:24,920 --> 00:01:33,060 I grund och botten, på denna punkt, om du öppnat en terminal inuti själva apparaten, 23 00:01:33,060 --> 00:01:36,350 detta gränssnitt, men du skulle använda den, är exakt samma 24 00:01:36,350 --> 00:01:40,010 som gränssnitt jag använder hit men nu är du SSHed. 25 00:01:42,240 --> 00:01:44,920 Du behöver inte SSH till apparaten. 26 00:01:44,920 --> 00:01:52,360 Ett exempel på en annan plats kan du SSH till är jag är ganska säker på att du har som standard - 27 00:01:52,360 --> 00:01:55,020 Åh. Större. 28 00:01:55,020 --> 00:02:01,130 Alla ni bör ha med konton standard FAS på FAS servrar. 29 00:02:01,130 --> 00:02:06,840 För mig skulle jag SSH till rbowden@nice.fas.harvard.edu. 30 00:02:06,840 --> 00:02:11,610 Det kommer att fråga dig om att första gången, och du säger ja. 31 00:02:11,610 --> 00:02:15,840 Mitt lösenord är bara att vara min FAS lösenord. 32 00:02:15,840 --> 00:02:22,650 Och så nu, jag SSHed till fina servrar och jag kan göra vad jag vill här. 33 00:02:22,650 --> 00:02:28,560 Många klasser du kan ta, liksom 124, kommer att få dig upp saker hit 34 00:02:28,560 --> 00:02:30,950 att faktiskt skicka dina problem uppsättningar. 35 00:02:30,950 --> 00:02:34,100 Men säger att du inte har tillgång till din apparat. 36 00:02:34,100 --> 00:02:37,910 Sedan kan du göra saker, som på här det kommer att säga - 37 00:02:37,910 --> 00:02:42,160 Detta är bara vår del av frågorna. 38 00:02:42,160 --> 00:02:45,070 Den kommer att fråga dig att göra detta i apparaten. 39 00:02:45,070 --> 00:02:47,790 Istället ska jag bara göra det på servern. 40 00:02:47,790 --> 00:02:50,560 Jag ska packa det. 41 00:02:50,560 --> 00:02:55,670 Problemet kommer att vara att du är van att använda något som gedit 42 00:02:55,670 --> 00:02:58,160 eller vad inuti apparaten. 43 00:02:58,160 --> 00:03:01,830 Du kommer inte att få det på FAS-servern. 44 00:03:01,830 --> 00:03:04,110 Allt är bara kommer att vara så här text gränssnitt. 45 00:03:04,110 --> 00:03:09,180 Så du kan antingen en, försöka lära en textredigerare som de har. 46 00:03:09,180 --> 00:03:12,130 De har Nano. 47 00:03:12,130 --> 00:03:14,990 Nano är oftast ganska lätt att använda. 48 00:03:14,990 --> 00:03:19,470 Du kan använda dina pilar och skriva normalt. 49 00:03:19,470 --> 00:03:21,250 Så det är inte svårt. 50 00:03:21,250 --> 00:03:24,720 Om du vill bli riktigt fint du kan använda Emacs, 51 00:03:24,720 --> 00:03:29,850 som jag förmodligen inte skulle ha öppnat för jag vet inte ens hur man stänger Emacs. 52 00:03:29,850 --> 00:03:32,760 Kontroll X Kontroll C? Ja. 53 00:03:32,760 --> 00:03:35,310 Eller så kan du använda Vim, vilket är vad jag använder. 54 00:03:35,310 --> 00:03:37,800 Och så de är dina alternativ. 55 00:03:37,800 --> 00:03:43,830 Om du inte vill göra det, kan du också, om man tittar på manual.cs50.net-- 56 00:03:43,830 --> 00:03:45,410 Åh. 57 00:03:45,410 --> 00:03:49,920 På en PC kan du SSH använder PuTTY, 58 00:03:49,920 --> 00:03:51,940 som du kommer att behöva ladda ner separat. 59 00:03:51,940 --> 00:03:55,460 På en Mac kan du bara som standard använder Terminal eller så kan du ladda ner iTerm2, 60 00:03:55,460 --> 00:03:58,490 som är som en trevlig, fin terminal. 61 00:03:58,490 --> 00:04:03,780 Om du går till manual.cs50.net ser du en länk till Notepad + +, 62 00:04:03,780 --> 00:04:07,120 vilket är vad du kan använda på en PC. 63 00:04:07,120 --> 00:04:13,340 Det låter dig SFTP från Notepad + +, vilket är i stort sett SSH. 64 00:04:13,340 --> 00:04:17,750 Vad detta kommer att låta dig göra är redigera dina filer lokalt, 65 00:04:17,750 --> 00:04:20,670 och sedan när du vill spara dem, kommer det att spara till nice.fas, 66 00:04:20,670 --> 00:04:23,670 där du sedan kan köra dem. 67 00:04:23,670 --> 00:04:26,880 Och motsvarande på en Mac kommer att bli TextWrangler. 68 00:04:26,880 --> 00:04:28,760 Så det kan du göra samma sak. 69 00:04:28,760 --> 00:04:32,800 Det låter dig redigera filer lokalt och spara dem till nice.fas, 70 00:04:32,800 --> 00:04:35,730 där du sedan kan köra dem. 71 00:04:35,730 --> 00:04:40,400 Så om du någonsin fastnat utan en apparat har du dessa alternativ 72 00:04:40,400 --> 00:04:44,230 att fortfarande göra dina problemområden uppsättningar. 73 00:04:44,230 --> 00:04:48,250 Ett problem kommer att vara att du inte kommer att ha CS50 biblioteket 74 00:04:48,250 --> 00:04:51,580 eftersom nice.fas inte har som standard att. 75 00:04:51,580 --> 00:04:55,970 Du kan antingen ladda ner CS50 biblioteket - 76 00:04:55,970 --> 00:04:58,470 Jag tror inte jag behöver det på denna punkt. 77 00:04:58,470 --> 00:05:03,270 Du kan antingen ladda ner CS50 biblioteket och kopiera den till nice.fas, 78 00:05:03,270 --> 00:05:07,450 eller jag tror på denna punkt vi inte använder det längre ändå. 79 00:05:07,450 --> 00:05:12,720 Eller om vi gör, kan du tills vidare ersätta det med 80 00:05:12,720 --> 00:05:18,480 Verkställandet av funktionerna i CS50 biblioteket ändå. 81 00:05:18,480 --> 00:05:21,370 Så det bör inte vara så mycket av en begränsning. 82 00:05:21,370 --> 00:05:23,710 Och det är det. 83 00:05:26,460 --> 00:05:29,820 >> Jag ska gå tillbaka till apparaten nu, vi kommer att göra allt i apparaten. 84 00:05:29,820 --> 00:05:37,510 Titta på vår del av frågorna, i början, som jag sade i min e-post, 85 00:05:37,510 --> 00:05:43,620 Vi måste prata om en kort man skulle titta på. 86 00:05:43,620 --> 00:05:51,980 Vi har omdirigera & Rör och dessa tre frågor. 87 00:05:51,980 --> 00:05:56,070 >> Till vilken ström skriver funktioner som printf som standard? 88 00:05:56,070 --> 00:05:59,130 Så ström. Vad är en ström? 89 00:06:06,520 --> 00:06:15,100 En ström är i princip som det är bara några - 90 00:06:15,100 --> 00:06:21,450 Det är inte ens en källa till 1: or och 0: or. 91 00:06:21,450 --> 00:06:24,920 Strömmen det ber om här är vanlig ute. 92 00:06:24,920 --> 00:06:27,250 Och så vanlig ut är en ström som när man skriver det, 93 00:06:27,250 --> 00:06:30,940 det visas på skärmen. 94 00:06:30,940 --> 00:06:36,860 Standard ut genom ström, betyder det att du bara skriva 1s och 0s till det, 95 00:06:36,860 --> 00:06:40,220 och den andra änden av standard ut läser bara från denna ström. 96 00:06:40,220 --> 00:06:43,540 Det är bara en sträng av 1: or och 0: or. 97 00:06:43,540 --> 00:06:45,570 Du kan skriva till strömmar eller du kan läsa från strömmar 98 00:06:45,570 --> 00:06:47,950 beroende på vad strömmen faktiskt är. 99 00:06:47,950 --> 00:06:52,800 De andra två förinställda flöden är standard i och standardfel. 100 00:06:52,800 --> 00:06:57,540 Standard i är när du gör getString, det väntar på dig att mata grejer. 101 00:06:57,540 --> 00:07:01,570 Så det väntar på dig, det väntar faktiskt på standard i, 102 00:07:01,570 --> 00:07:04,880 som verkligen är vad du får när du skriver på tangentbordet. 103 00:07:04,880 --> 00:07:07,530 Du skriver till standard i. 104 00:07:07,530 --> 00:07:10,050 Standardfel är i grunden likvärdig med standard ut, 105 00:07:10,050 --> 00:07:13,280 men det är specialiserade på att när du skriver ut på standard fel, 106 00:07:13,280 --> 00:07:16,770 du ska bara skriva ut felmeddelanden som 107 00:07:16,770 --> 00:07:20,200 så du kan skilja mellan vanliga meddelanden utskrivna på skärmen 108 00:07:20,200 --> 00:07:24,560 kontra felmeddelanden beroende på om de gick till standard ut eller standardfel. 109 00:07:24,560 --> 00:07:28,660 Filer också. 110 00:07:28,660 --> 00:07:32,440 Standard ut, standard i och standardfelet är bara speciella strömmar, 111 00:07:32,440 --> 00:07:36,810 men egentligen alla filer när du öppnar en fil, blir det en ström av bytes 112 00:07:36,810 --> 00:07:40,740 där du kan bara läsa från denna ström. 113 00:07:40,740 --> 00:07:47,770 Du, för det mesta, kan bara tänka på en fil som en ström av bytes. 114 00:07:47,770 --> 00:07:51,190 Så vad strömmar skriver de att som standard? Standard ut. 115 00:07:51,190 --> 00:07:56,980 >> Vad är skillnaden mellan> och >>? 116 00:07:58,140 --> 00:08:03,710 Har någon titta på videon i förväg? Okej. 117 00:08:03,710 --> 00:08:10,960 > Kommer att bli hur du omdirigerar till filer, 118 00:08:10,960 --> 00:08:15,240 och >> kommer också att dirigera utdata i filer, 119 00:08:15,240 --> 00:08:17,820 men det är i stället kommer att lägga till filen. 120 00:08:17,820 --> 00:08:23,430 Till exempel, låt oss säga att jag råkar ha dict här, 121 00:08:23,430 --> 00:08:27,020 och den enda grejer inuti dict är katt, katt, hund, fisk, hund. 122 00:08:27,020 --> 00:08:31,530 Ett kommando som du har på kommandoraden är katt, 123 00:08:31,530 --> 00:08:34,539 som just kommer att skriva ut vad som finns i en fil. 124 00:08:34,539 --> 00:08:40,679 Så när jag säger katt dict, det kommer att skriva ut katt, katt, hund, fisk, hund. Det är allt katt gör. 125 00:08:40,679 --> 00:08:46,280 Det betyder att det skrivs till standard ut katt, katt, hund, fisk, hund. 126 00:08:46,280 --> 00:08:53,240 Om jag istället vill omdirigera det till en fil, kan jag använda> och omdirigera den till vad filen. 127 00:08:53,240 --> 00:08:56,460 Jag ringer filen filen. 128 00:08:56,460 --> 00:09:00,320 Så nu om jag ls, jag ser har jag en ny fil som heter filen. 129 00:09:00,320 --> 00:09:05,700 Och om jag öppnar det, det kommer att ha exakt vad katten sätta på kommandoraden. 130 00:09:05,700 --> 00:09:11,040 Så nu om jag gör det igen, då det kommer att omdirigera utdata till filen, 131 00:09:11,040 --> 00:09:13,930 och jag kommer att ha exakt samma sak. 132 00:09:13,930 --> 00:09:17,910 Så tekniskt, förbigick det helt vad vi hade. 133 00:09:17,910 --> 00:09:22,970 Och vi får se om jag ändrar dict tog jag ut hunden. 134 00:09:22,970 --> 00:09:29,980 Nu om vi katt dict i filen igen, vi kommer att ha den nya versionen med hund bort. 135 00:09:29,980 --> 00:09:32,400 Så det åsidosätter helt det. 136 00:09:32,400 --> 00:09:36,640 Istället, om vi använder >>, det kommer att lägga filen. 137 00:09:36,640 --> 00:09:40,860 Nu öppnar filen ser vi att vi har precis samma sak skrivs två gånger 138 00:09:40,860 --> 00:09:44,920 eftersom det var det en gång, då vi fogas till den ursprungliga. 139 00:09:44,920 --> 00:09:48,130 Så det är vad> och >> gör. 140 00:09:48,130 --> 00:09:50,580 Frågar nästa - Det spelar ingen fråga om det. 141 00:09:50,580 --> 00:09:59,050 >> Den andra som vi har är <, som om> omdirigerar standard ut, 142 00:09:59,050 --> 00:10:01,970 00:10:12,050 Låt oss se om vi har ett exempel. 144 00:10:14,750 --> 00:10:16,930 Jag kan skriva en riktigt snabb. 145 00:10:17,870 --> 00:10:25,700 Låt oss ta en fil, hej.c. 146 00:10:56,060 --> 00:10:59,070 Relativt enkel fil. 147 00:10:59,070 --> 00:11:03,570 Jag bara få en sträng och sedan skriva "Hej" oavsett strängen jag angav var. 148 00:11:03,570 --> 00:11:07,990 Så gör hej och då. / Hej. 149 00:11:07,990 --> 00:11:10,720 Nu är det föranledde mig att skriva något, 150 00:11:10,720 --> 00:11:15,070 vilket betyder att det väntar på saker som ska införas i standard i. 151 00:11:15,070 --> 00:11:20,450 Så skriv vad jag vill i standard i. Vi ska bara säga hej, Rob! 152 00:11:20,450 --> 00:11:23,310 Då är det du skriver till standard ut Hej, Rob! 153 00:11:23,310 --> 00:11:28,860 Om jag gör. / Hej och sedan omdirigera, 154 00:11:30,740 --> 00:11:34,310 för nu kan du bara styra från en fil. 155 00:11:34,310 --> 00:11:41,720 Så om jag sätter i någon fil, txt, och jag satte Rob, 156 00:11:41,720 --> 00:11:52,300 om jag kör hej och sedan dirigera filen txt till. / hej, det kommer att säga Hej, Rob! omedelbart. 157 00:11:52,300 --> 00:11:57,160 När det blir först GetString och väntar på standard i, 158 00:11:57,160 --> 00:12:01,730 standard är inte längre vänta på tangentbordet för data att få angett. 159 00:12:01,730 --> 00:12:05,980 I stället har vi omdirigerat standard i att läsa från filen txt. 160 00:12:05,980 --> 00:12:10,290 Och så det kommer att läsa från filen txt, vilket är just den linjen Rob, 161 00:12:10,290 --> 00:12:13,380 och då det kommer att skriva ut Hej, Rob! 162 00:12:13,380 --> 00:12:18,180 Och om jag ville kunde jag också göra. / Hej 00:12:21,500 och sedan den standard att det tryckeri som är Hej, Rob!, 164 00:12:21,500 --> 00:12:24,700 Jag kan omdirigera det till en egen fil. 165 00:12:24,700 --> 00:12:29,790 Jag ska bara ringa filen hej - nej, jag kommer inte, eftersom det är den körbara - txt2. 166 00:12:29,790 --> 00:12:40,150 Nu är txt2 kommer att ha effekt på. / Hej 00:12:43,520 >> Frågor? 168 00:12:45,900 --> 00:12:49,090 >> Okej. Så så här har vi rörledning. 169 00:12:49,090 --> 00:12:53,510 Rör är den sista enheten av omdirigering. 170 00:12:53,510 --> 00:12:58,750 >> Åh. Jag antar en enhet av omdirigering är om istället för> du gör 2>, 171 00:12:58,750 --> 00:13:01,070 som är omdirigera standard fel. 172 00:13:01,070 --> 00:13:06,280 Så om något gick till standard fel, skulle det inte få sätta in txt2. 173 00:13:06,280 --> 00:13:12,480 Men märker om jag gör 2>, då är det fortfarande skriva Hej, Rob! till kommandoraden 174 00:13:12,480 --> 00:13:18,600 eftersom jag bara omdirigera standard fel, jag styra inte standard ut. 175 00:13:18,600 --> 00:13:22,210 Standardfel och standard ut är olika. 176 00:13:24,210 --> 00:13:27,080 Om du ville verkligen skriva till standard fel, 177 00:13:27,080 --> 00:13:35,080 då jag kunde ändra detta vara fprintf till stderr. 178 00:13:35,080 --> 00:13:37,850 Så printf som standard skriver till standard ut. 179 00:13:37,850 --> 00:13:41,720 Om jag vill skriva ut till standard fel manuellt, då måste jag använda fprintf 180 00:13:41,720 --> 00:13:45,010 och ange vad jag vill skriva ut på. 181 00:13:45,010 --> 00:13:49,720 Om man i stället gjorde jag fprintf stdout, så det är i princip likvärdiga med printf. 182 00:13:49,720 --> 00:13:55,530 Men fprintf till standard fel. 183 00:13:57,790 --> 00:14:03,650 Så nu, om jag omdirigera detta till txt2, Hej, Rob! fortfarande få ut på kommandoraden 184 00:14:03,650 --> 00:14:08,270 eftersom det blir tryckt till standard fel och jag bara omdirigera standard ut. 185 00:14:08,270 --> 00:14:16,420 Om jag nu omdirigera standard fel, nu är det inte få ut och txt2 kommer att bli Hej, Rob! 186 00:14:16,420 --> 00:14:21,910 Så nu kan du skriva ut dina faktiska fel till standard fel 187 00:14:21,910 --> 00:14:24,720 och skriva ut dina vanliga meddelanden till standard ut. 188 00:14:24,720 --> 00:14:31,420 Och så när du kör programmet kan du köra det som. / Hej denna typ med 2> 189 00:14:31,420 --> 00:14:33,800 så att ditt program ska fungera normalt, 190 00:14:33,800 --> 00:14:38,400 men alla felmeddelanden som du får du kan kontrollera senare i felloggen 191 00:14:38,400 --> 00:14:44,500 så fel, och sedan titta senare och dina fel fil kommer att ha några fel som hände. 192 00:14:45,200 --> 00:14:47,540 >> Frågor? 193 00:14:47,540 --> 00:14:58,070 >> Den sista är rör, som du kan tänka på som att ta standarden ur ett kommando 194 00:14:58,070 --> 00:15:01,210 och gör den till den standard på nästa kommando. 195 00:15:01,210 --> 00:15:05,570 Ett exempel här är eko är en kommandorad sak 196 00:15:05,570 --> 00:15:11,840 som bara kommer att upprepa vad jag satte som argument. Jag kommer inte att sätta citattecken. 197 00:15:11,840 --> 00:15:16,150 Echo bla, bla, är bla ska bara skriva ut bla, bla, bla. 198 00:15:16,150 --> 00:15:20,600 Tidigare, när jag sa att jag var tvungen att sätta Rob i en txt-fil 199 00:15:20,600 --> 00:15:28,830 eftersom jag bara kan omdirigera txt-filer i stället / om jag upprepar Rob 200 00:15:28,830 --> 00:15:35,520 och sedan rör den till. / hej, som kommer att också göra samma typ av sak. 201 00:15:35,520 --> 00:15:39,160 Detta tar produktionen av detta kommando, eko Rob, 202 00:15:39,160 --> 00:15:43,610 och använda den som underlag för. / hej. 203 00:15:44,790 --> 00:15:49,560 Du kan se det som första omdirigeringen eko Rob i en fil 204 00:15:49,560 --> 00:15:54,160 och mata in. / hej filen som just matas ut. 205 00:15:54,160 --> 00:15:57,850 Men det tar den temporära filen ur bilden. 206 00:16:01,890 --> 00:16:04,460 >> Frågor på det? 207 00:16:04,460 --> 00:16:07,150 >> Nästa fråga kommer att innebära detta. 208 00:16:07,150 --> 00:16:15,310 Vilken rörledning kan du använda för att hitta antalet unika namn i en fil som heter names.txt? 209 00:16:15,310 --> 00:16:24,160 Kommandona vi kommer att vilja använda här är unika, så uniq och sedan wc. 210 00:16:24,160 --> 00:16:28,840 Du kan göra människan Uniq att faktiskt titta på vad det gör, 211 00:16:28,840 --> 00:16:34,840 och det är bara att filtrera intilliggande matchande rader från ingången. 212 00:16:34,840 --> 00:16:40,690 Och människan wc kommer att skriva ut nyrad, ord och byte räknas för varje fil. 213 00:16:40,690 --> 00:16:43,760 Och den sista vi kommer att vilja använda är sortera, 214 00:16:43,760 --> 00:16:47,410 som kommer att bara sortera raderna i txt-fil. 215 00:16:47,410 --> 00:16:58,080 Om jag gör några txt-fil, names.txt, och det är Rob, Tommy, Josef, Tommy, Josef, RJ, Rob, 216 00:16:58,080 --> 00:17:03,910 vad jag vill göra här är att hitta antalet unika namn i denna fil. 217 00:17:03,910 --> 00:17:08,750 Så vad ska svaret vara? >> [Elev] 4. >> Ja. 218 00:17:08,750 --> 00:17:13,780 Det bör vara 4 eftersom Rob, Tommy, Joseph, RJ är den enda unika namn i denna fil. 219 00:17:13,780 --> 00:17:20,180 Det första steget, om jag bara gör ord räkna names.txt, 220 00:17:20,180 --> 00:17:24,290 Detta är faktiskt säger allt. 221 00:17:24,290 --> 00:17:32,560 Detta är faktiskt utskrift - Nu ska vi se, man wc - radbrytningar, ord och byte count. 222 00:17:32,560 --> 00:17:38,270 Om jag bara bryr sig om linjer, då kan jag bara göra wc-l names.txt. 223 00:17:41,730 --> 00:17:44,300 Så det är steg 1. 224 00:17:44,300 --> 00:17:50,510 Men jag vill inte wc-l names.txt eftersom names.txt bara innehåller alla namn, 225 00:17:50,510 --> 00:17:54,170 och jag vill filtrera bort eventuella icke-unika sådana. 226 00:17:54,170 --> 00:18:01,200 Så om jag gör uniq names.txt, som inte riktigt ge mig vad jag vill 227 00:18:01,200 --> 00:18:03,760 eftersom de duplicerade namnen finns kvar. 228 00:18:03,760 --> 00:18:07,690 Varför det? Varför Uniq gör inte vad jag vill? 229 00:18:07,690 --> 00:18:10,500 [Elev] Den dubbletter inte [ohörbart] >> Ja. 230 00:18:10,500 --> 00:18:16,370 Kom ihåg mansidan för uniq säger Filtrera intilliggande matchande rader. 231 00:18:16,370 --> 00:18:19,680 De är inte angränsande, så det kommer inte filtrera dem. 232 00:18:19,680 --> 00:18:31,100 Om jag sorterar dem först, sortera names.txt kommer att lägga alla dubbla linjer tillsammans. 233 00:18:31,100 --> 00:18:34,450 Så nu Sortera names.txt är det. 234 00:18:34,450 --> 00:18:40,550 Jag kommer att vilja använda det som ingången till uniq, som är | uniq. 235 00:18:40,550 --> 00:18:43,390 Det ger mig Josef, RJ, Rob, Tommy, 236 00:18:43,390 --> 00:18:49,260 och jag vill använda det som ingången till wc-l, 237 00:18:49,260 --> 00:18:52,740 som kommer att ge mig 4. 238 00:18:52,740 --> 00:18:56,930 Som det står här, vad rörledning du använda? 239 00:18:56,930 --> 00:19:01,390 Du kan göra en massa saker som att använda en serie kommandon 240 00:19:01,390 --> 00:19:05,130 där du använder utdata från ett kommando som ingång till nästa kommando. 241 00:19:05,130 --> 00:19:08,780 Du kan göra en massa saker, en massa smarta saker. 242 00:19:08,780 --> 00:19:11,440 >> Frågor? 243 00:19:12,910 --> 00:19:14,600 Okej. 244 00:19:14,600 --> 00:19:17,880 Det var allt för rör och omdirigering. 245 00:19:18,370 --> 00:19:24,090 >> Nu ska vi gå vidare till själva grejer, kodning grejer. 246 00:19:24,090 --> 00:19:29,100 Inuti denna PDF, ser du det här kommandot, 247 00:19:29,100 --> 00:19:32,950 och du vill köra detta kommando i din apparat. 248 00:19:36,240 --> 00:19:42,250 wget är kommandot för bara få något från Internet, i princip, 249 00:19:42,250 --> 00:19:45,180 så wget och denna URL. 250 00:19:45,180 --> 00:19:49,110 Om du gick till denna URL i din webbläsare, skulle det hämtar filen. 251 00:19:49,110 --> 00:19:52,510 Jag klickade bara på det, så det hämtade filen för mig. 252 00:19:52,510 --> 00:19:55,650 Men skriver wget av den saken inne på terminalen 253 00:19:55,650 --> 00:19:58,620 är bara att ladda ner det till din terminal. 254 00:19:58,620 --> 00:20:02,750 Jag har section5.zip, och du kommer att vilja packa section5.zip, 255 00:20:02,750 --> 00:20:06,520 som kommer att ge dig en mapp som heter avsnitt 5, 256 00:20:06,520 --> 00:20:11,550 som kommer att ha alla de filer vi kommer att använda i dag i den. 257 00:20:33,380 --> 00:20:37,710 Eftersom dessa program "filnamn antyder, de är lite buggig, 258 00:20:37,710 --> 00:20:40,990 så ditt uppdrag är att räkna ut varför använder gdb. 259 00:20:40,990 --> 00:20:44,560 Har alla har dem hämtat / vet hur man får dem ner 260 00:20:44,560 --> 00:20:47,480 i sin apparat? Okej. 261 00:20:47,480 --> 00:20:56,400 >> Köra ./buggy1, kommer det att säga segmenteringsfel (core dumpad), 262 00:20:56,400 --> 00:21:00,500 som varje gång du får en segmenteringsfel, det är en dålig sak. 263 00:21:00,500 --> 00:21:03,810 Under vilka omständigheter får du en segmenteringsfel? 264 00:21:03,810 --> 00:21:08,210 [Elev] Dereferencing en null-pekare. >> Ja. Så det är ett exempel. 265 00:21:08,210 --> 00:21:11,580 Dereferencing en nollpekare du kommer att få en segmenteringsfel. 266 00:21:11,580 --> 00:21:16,720 Vad en segmenteringsfel innebär är att du rör minnet inte bör röra. 267 00:21:16,720 --> 00:21:21,350 Så dereferencing en nollpekare vidrör adress 0, 268 00:21:21,350 --> 00:21:28,060 och i princip alla datorer säger numera att adress 0 är minne du ska inte röra. 269 00:21:28,060 --> 00:21:31,920 Så det är därför dereferencing en nollpekare resulterar i en segmenteringsfel. 270 00:21:31,920 --> 00:21:37,210 När du råkar inte initiera en pekare, så det har en skräp värde, 271 00:21:37,210 --> 00:21:41,520 och så när du försöker dereference det, med all sannolikhet du röra minne 272 00:21:41,520 --> 00:21:43,540 Det är i mitten av ingenstans. 273 00:21:43,540 --> 00:21:45,650 Om du råkar ha tur och skräp värde 274 00:21:45,650 --> 00:21:48,440 råkade peka någonstans på stacken eller något, 275 00:21:48,440 --> 00:21:50,820 sedan när du dereference som pekare som du inte har initierats, 276 00:21:50,820 --> 00:21:52,730 ingenting gå fel. 277 00:21:52,730 --> 00:21:55,480 Men om det är att peka på, säg, någonstans mellan stapeln och högen, 278 00:21:55,480 --> 00:21:59,850 eller det pekar bara någonstans som inte har använts av ditt program ännu, 279 00:21:59,850 --> 00:22:02,240 då du vidrör minne du ska inte röra och du segmenteringsfel. 280 00:22:02,240 --> 00:22:06,370 När du skriver en rekursiv funktion och det recurses för många gånger 281 00:22:06,370 --> 00:22:08,720 och din stack blir för stor och kolliderar stack in i saker 282 00:22:08,720 --> 00:22:12,270 att det inte borde kollidera med, du röra minne du inte bör röra, 283 00:22:12,270 --> 00:22:14,810 så du segmenteringsfel. 284 00:22:14,810 --> 00:22:17,010 Det är vad en segmenteringsfel är. 285 00:22:17,010 --> 00:22:21,810 >> Det är också av samma anledning som om du har en sträng som - 286 00:22:21,810 --> 00:22:23,930 låt oss gå tillbaka till det tidigare programmet. 287 00:22:23,930 --> 00:22:28,530 I hej.c--Jag ska bara göra något annat. 288 00:22:28,530 --> 00:22:33,770 char * s = "Hej världen!"; 289 00:22:33,770 --> 00:22:42,310 Om jag använder * s = något eller s [0] = 'X'; 290 00:22:42,310 --> 00:22:47,290 så gör hej,. / hej, varför det segmenteringsfel? 291 00:22:48,410 --> 00:22:51,250 Varför har detta segmenteringsfel? 292 00:22:55,660 --> 00:22:57,890 Vad skulle du förvänta dig att hända? 293 00:22:57,890 --> 00:23:06,640 Om jag gjorde det printf ("% s \ n", s), vad skulle du förvänta dig att skrivas? 294 00:23:06,640 --> 00:23:09,930 [Eleven] X hej. >> Ja. 295 00:23:09,930 --> 00:23:15,140 Problemet är att när du deklarerar en sträng som denna, 296 00:23:15,140 --> 00:23:18,190 s är en pekare som kommer att gå på stacken, 297 00:23:18,190 --> 00:23:25,880 och vad s pekar på är denna sträng som ingår i läsminne. 298 00:23:25,880 --> 00:23:30,560 Så bara genom namnet, läsminne, bör du få idén 299 00:23:30,560 --> 00:23:33,010 att om du försöker ändra vad som finns i ROM-minnet, 300 00:23:33,010 --> 00:23:36,670 du gör något du inte bör göra med minne och du segmenteringsfel. 301 00:23:36,670 --> 00:23:45,360 Detta är faktiskt en stor skillnad mellan char * s och röding s []. 302 00:23:45,360 --> 00:23:48,790 Så röding s [], nu denna sträng ska läggas på stacken, 303 00:23:48,790 --> 00:23:53,960 och stapeln är inte skrivskyddad, vilket innebär att denna bör fungera alldeles utmärkt. 304 00:23:55,500 --> 00:23:57,370 Och det gör det. 305 00:23:57,370 --> 00:24:06,250 Kom ihåg att när jag gör char * s = "Hello world!", S själv på stacken 306 00:24:06,250 --> 00:24:10,390 men s pekar någon annanstans, och att någon annanstans råkar vara skrivskyddad. 307 00:24:10,390 --> 00:24:15,640 Men röding s [] är bara något på stacken. 308 00:24:17,560 --> 00:24:21,760 Så det är ett annat exempel på en segmenteringsfel händer. 309 00:24:21,760 --> 00:24:27,820 >> Vi såg att ./buggy1 resulterade i en segmenteringsfel. 310 00:24:27,820 --> 00:24:31,810 I teorin bör du titta inte på buggy1.c omedelbart. 311 00:24:31,810 --> 00:24:35,170 Istället kommer vi att titta på det genom gdb. 312 00:24:35,170 --> 00:24:37,750 Observera att när du får segmenteringsfel (core dumpad), 313 00:24:37,750 --> 00:24:40,850 du får den här filen hit kallas kärna. 314 00:24:40,850 --> 00:24:45,200 Om vi ​​ls-l, vi ser att kärnan är oftast en ganska stor fil. 315 00:24:45,200 --> 00:24:51,580 Detta är antalet byte i filen, så det ser ut som det är 250-någonting kilobyte. 316 00:24:51,580 --> 00:24:56,120 Anledningen till detta är att det kärnan dumpa faktiskt är 317 00:24:56,120 --> 00:25:01,410 är när ditt program kraschar, tillstånd minne av ditt program 318 00:25:01,410 --> 00:25:05,230 bara blir kopieras och klistras in i denna fil. 319 00:25:05,230 --> 00:25:07,270 Det blir dumpad i den filen. 320 00:25:07,270 --> 00:25:13,060 Detta program, medan det körs, råkade ha en minnesanvändning på cirka 250 kilobyte, 321 00:25:13,060 --> 00:25:17,040 och så det är vad blev dumpad i denna fil. 322 00:25:17,040 --> 00:25:23,630 Nu kan du titta på den filen om vi gdb buggy1 kärna. 323 00:25:23,630 --> 00:25:30,130 Vi kan bara göra gdb buggy1, och det kommer bara starta gdb regelbundet, 324 00:25:30,130 --> 00:25:33,800 med buggy1 som sin indatafil. 325 00:25:33,800 --> 00:25:38,260 Men om du gör gdb buggy1 kärna, då är det särskilt kommer att starta gdb 326 00:25:38,260 --> 00:25:40,330 genom att titta på den centrala filen. 327 00:25:40,330 --> 00:25:45,560 Och du säger buggy1 betyder gdb vet att det kärnfil kommer från buggy1 programmet. 328 00:25:45,560 --> 00:25:49,580 Så gdb buggy1 kärna kommer att omedelbart ge oss 329 00:25:49,580 --> 00:25:52,060 där programmet råkade avsluta. 330 00:25:57,720 --> 00:26:02,340 Vi ser här programmet avslutas med signalen 11, segmenteringsfel. 331 00:26:02,340 --> 00:26:10,110 Vi råkar se en rad församling, som troligen är inte till stor hjälp. 332 00:26:10,110 --> 00:26:15,360 Men om du skriver BT eller bakåtspårning, det är kommer att bli funktionen 333 00:26:15,360 --> 00:26:19,430 som ger oss en lista över våra nuvarande stack ramar. 334 00:26:19,430 --> 00:26:23,150 Så bakåtspårning. Det ser ut som vi bara har två stack ramar. 335 00:26:23,150 --> 00:26:26,310 Den första är vår viktigaste stack ram, 336 00:26:26,310 --> 00:26:29,810 och den andra är stacken ramen för denna funktion som vi råkar vara i, 337 00:26:29,810 --> 00:26:34,440 som ser ut som vi bara har assemblerkod för. 338 00:26:34,440 --> 00:26:38,050 Så låt oss gå tillbaka till vår huvudsakliga funktion, 339 00:26:38,050 --> 00:26:42,300 och att göra det vi kan göra ramen 1, och jag tror att vi också kan göra ner, 340 00:26:42,300 --> 00:26:45,160 men jag nästan aldrig göra ner - eller upp. Ja. 341 00:26:45,160 --> 00:26:50,710 Upp och ner. Upp ger dig upp en stack ram, ner tar dig ner en stack ram. 342 00:26:50,710 --> 00:26:53,240 Jag brukar aldrig använda det. 343 00:26:53,240 --> 00:26:59,120 Jag specifikt säga ram 1, vilket är att gå till bildrutan 1. 344 00:26:59,120 --> 00:27:01,750 Ram 1 kommer att föra oss in i stora stack ram, 345 00:27:01,750 --> 00:27:05,570 och det står här kodraden vi råkar vara på. 346 00:27:05,570 --> 00:27:07,950 Om vi ​​ville ett par fler rader kod, kan vi säga listan, 347 00:27:07,950 --> 00:27:11,280 och det kommer att ge oss alla kodrader runt den. 348 00:27:11,280 --> 00:27:13,360 Den linje vi segfaulted på var 6: 349 00:27:13,360 --> 00:27:17,360 if (strcmp ("CS50 rocks", argv [1]) == 0). 350 00:27:17,360 --> 00:27:24,130 Om det inte är uppenbart ännu kan du få det direkt härifrån bara genom att tänka varför det segfaulted. 351 00:27:24,130 --> 00:27:28,800 Men vi kan ta det ett steg längre och säga, "Varför skulle argv [1] segmenteringsfel?" 352 00:27:28,800 --> 00:27:38,830 Låt oss skriva ut argv [1], och det ser ut som det är 0x0, som är NULL-pekare. 353 00:27:38,830 --> 00:27:44,750 Vi strcmping CS50 stenar och noll, och så det kommer att segmenteringsfel. 354 00:27:44,750 --> 00:27:48,280 Och varför är argv [1] null? 355 00:27:48,640 --> 00:27:51,280 [Eleven] Eftersom vi inte gav det någon kommandoradsargument. 356 00:27:51,280 --> 00:27:53,390 Ja. Vi gav inte det någon kommandoradsargument. 357 00:27:53,390 --> 00:27:58,460 Så ./buggy1 bara kommer att ha argv [0] vara ./buggy1. 358 00:27:58,460 --> 00:28:02,100 Det kommer inte att ha en argv [1], så det kommer att segmenteringsfel. 359 00:28:02,100 --> 00:28:07,450 Men om man istället gör jag bara CS50, det kommer att säga att du får ett D 360 00:28:07,450 --> 00:28:09,950 eftersom det är vad det är tänkt att göra. 361 00:28:09,950 --> 00:28:15,240 Titta på buggy1.c, är det tänkt att skriva ut "Du får en D" - 362 00:28:15,240 --> 00:28:20,820 Om argv [1] är inte "CS50 rocks", "Du får en D", annars "Du får ett A!" 363 00:28:20,820 --> 00:28:25,660 Så om vi vill ha en A behöver vi detta för att jämföra som sant, 364 00:28:25,660 --> 00:28:28,710 vilket innebär att det kan jämföras med 0. 365 00:28:28,710 --> 00:28:31,100 Så argv [1] måste "CS50 rocks". 366 00:28:31,100 --> 00:28:35,660 Om du vill göra det på kommandoraden, måste du använda \ fly utrymmet. 367 00:28:35,660 --> 00:28:41,690 Så CS50 \ stenar och du får ett A! 368 00:28:41,690 --> 00:28:44,060 Om du inte gör det omvända snedstrecket, varför detta inte att fungera? 369 00:28:44,060 --> 00:28:47,190 [Elev] Det är två olika argument. >> Ja. 370 00:28:47,190 --> 00:28:52,540 Argv [1] kommer att bli CS50 och argv [2] kommer att bli stenar. Okej. 371 00:28:52,540 --> 00:28:56,470 >> Nu ./buggy2 ska segmenteringsfel igen. 372 00:28:56,470 --> 00:29:01,880 Istället för att öppna den med sin kärna fil, vi öppnar bara upp buggy2 direkt, 373 00:29:01,880 --> 00:29:05,000 så gdb buggy2. 374 00:29:05,000 --> 00:29:09,590 Nu om vi bara kör vårt program, så det kommer att säga Program mottagen signal SIGSEGV, 375 00:29:09,590 --> 00:29:15,530 som är segmenteringsfel signalen, och det är där det hände skulle hända. 376 00:29:15,530 --> 00:29:21,250 Titta på vår bakåtspårning, ser vi att vi var i funktion oh_no, 377 00:29:21,250 --> 00:29:23,900 som kallades av funktionen dinky, som kallades av funktionen Binky, 378 00:29:23,900 --> 00:29:26,460 som kallades av huvud. 379 00:29:26,460 --> 00:29:31,680 Vi kan också se argumenten för dessa funktioner. 380 00:29:31,680 --> 00:29:34,680 Argumentet till dinky och Binky var 1. 381 00:29:34,680 --> 00:29:44,390 Om vi ​​lista funktionen oh_no, ser vi att oh_no bara gör char ** s = null; 382 00:29:44,390 --> 00:29:47,410 * S = "BOOM"; 383 00:29:47,410 --> 00:29:50,330 Varför skulle det inte? 384 00:29:54,330 --> 00:29:58,380 [Eleven] Du kan inte dereference null pekaren? >> Ja. 385 00:29:58,380 --> 00:30:06,090 Detta är bara att s är NULL, oavsett om det råkar vara en röding ** 386 00:30:06,090 --> 00:30:12,070 som, beroende på hur du tolkar det, kan det vara en pekare till en pekare till en sträng 387 00:30:12,070 --> 00:30:15,550 eller en uppsättning av strängar. 388 00:30:15,550 --> 00:30:21,430 Det är s är NULL så * s är dereferencing en nollpekare, 389 00:30:21,430 --> 00:30:24,800 och så detta kommer att krascha. 390 00:30:24,800 --> 00:30:27,540 Detta är en av de snabbaste sätten du kan möjligen segmenteringsfel. 391 00:30:27,540 --> 00:30:31,300 Det är bara att förklara en null-pekare och omedelbart segfaulting. 392 00:30:31,300 --> 00:30:34,570 Det är vad oh_no gör. 393 00:30:34,570 --> 00:30:43,400 Om vi ​​går upp en ram, då vi kommer att få in den funktion som kallas oh_no. 394 00:30:43,400 --> 00:30:44,830 Jag måste göra det ner. 395 00:30:44,830 --> 00:30:48,610 Om du inte anger ett kommando och du träffar bara Enter igen, 396 00:30:48,610 --> 00:30:52,350 det kommer bara upprepa föregående kommando som du körde. 397 00:30:52,350 --> 00:30:56,610 Vi är i ram 1. 398 00:30:56,610 --> 00:31:04,650 Listar denna ram ser vi här är vår uppgift. 399 00:31:04,650 --> 00:31:08,520 Du kan slå listan igen, eller så kan du göra-lista 20 och det kommer att ge mer. 400 00:31:08,520 --> 00:31:13,640 Funktionen Dinky säger att om jag är 1, sedan gå till oh_no funktionen 401 00:31:13,640 --> 00:31:15,960 annars gå till Slinky funktionen. 402 00:31:15,960 --> 00:31:18,700 Och vi vet att jag är 1 eftersom vi råkar se upp här 403 00:31:18,700 --> 00:31:22,560 att Dinky kallades med argumentet 1. 404 00:31:22,560 --> 00:31:27,560 Eller så kan du bara skriver jag och det kommer att säga att jag är 1. 405 00:31:27,560 --> 00:31:33,770 Vi är för närvarande i dinky, och om vi går upp en annan ram, vi vet att vi kommer att hamna i Binky. 406 00:31:33,770 --> 00:31:36,600 Upp. Nu är vi i Binky. 407 00:31:36,600 --> 00:31:41,340 Listar denna funktion - listan från före halv avbröt mig - 408 00:31:41,340 --> 00:31:52,670 Det började som om jag är 0, då ska vi kalla det oh_no, annars ringer dinky. 409 00:31:52,670 --> 00:31:57,000 Vi vet att jag var 1, så kallas det dinky. 410 00:31:57,000 --> 00:32:05,030 Och nu är vi tillbaka i main, och viktigaste är bara kommer att bli int i = rand ()% 3; 411 00:32:05,030 --> 00:32:08,790 Som bara kommer att ge dig ett slumptal som är antingen 0, 1 eller 2. 412 00:32:08,790 --> 00:32:12,780 Det kommer att kalla Binky med det numret, och det kommer tillbaka 0. 413 00:32:12,780 --> 00:32:16,700 Titta på detta, 414 00:32:16,700 --> 00:32:19,880 bara gå igenom programmet manuellt utan att köra det direkt, 415 00:32:19,880 --> 00:32:25,400 du skulle sätta en brytpunkt på huvud, vilket innebär att när vi kör programmet 416 00:32:25,400 --> 00:32:31,020 ditt program körs tills den träffar en brytpunkt. 417 00:32:31,020 --> 00:32:35,450 Så kör programmet, kommer den att köra och så kommer det att slå huvudfunktionen och sluta köra. 418 00:32:35,450 --> 00:32:44,700 Nu är vi inne i huvud och steg eller nästa kommer att föra oss till nästa kodrad. 419 00:32:44,700 --> 00:32:47,050 Du kan göra steg eller nästa. 420 00:32:47,050 --> 00:32:51,800 Utslagning nästa, nu jag har satts till rand ()% 3, så att vi kan skriva ut värdet av i, 421 00:32:51,800 --> 00:32:55,280 och det kommer att säga att jag är 1. 422 00:32:55,280 --> 00:32:58,110 Nu spelar ingen roll om vi använder nästa eller steg. 423 00:32:58,110 --> 00:33:01,000 Jag antar att det betydde i den föregående, men vi skulle vilja använda härnäst. 424 00:33:01,000 --> 00:33:06,000 Om vi ​​använder steg, vi steg in i funktionen, vilket innebär titta på själva saken 425 00:33:06,000 --> 00:33:07,940 som händer inne i Binky. 426 00:33:07,940 --> 00:33:10,510 Om vi ​​använder nästa, så betyder det att gå över funktionen 427 00:33:10,510 --> 00:33:14,070 och bara gå vidare till nästa kodrad i vår huvudsakliga funktion. 428 00:33:14,070 --> 00:33:17,900 Här på denna linje, jag var på där det stod rand ()% 3; 429 00:33:17,900 --> 00:33:21,320 om jag gjorde steg, skulle det gå till genomförandet av rand 430 00:33:21,320 --> 00:33:25,110 och titta på vad som händer där, och jag kunde gå igenom rand-funktionen. 431 00:33:25,110 --> 00:33:26,920 Men jag bryr mig inte om funktionen rand. 432 00:33:26,920 --> 00:33:30,190 Jag vill bara gå till nästa kodrad i huvud, så jag använder nästa. 433 00:33:30,190 --> 00:33:35,800 Men nu gör jag bryr sig om Binky funktionen, så jag vill kliva in i det. 434 00:33:35,800 --> 00:33:37,730 Nu är jag i Binky. 435 00:33:37,730 --> 00:33:42,040 Den första raden i koden kommer att säga om (i == 0), jag tar ett steg, 436 00:33:42,040 --> 00:33:44,930 Vi ser att vi hamnar på dinky. 437 00:33:44,930 --> 00:33:51,620 Om vi ​​listar saker, ser vi att det kontrolleras är i = 0. 438 00:33:51,620 --> 00:33:55,470 Jag är inte lika med 0, så det gick till annat tillstånd, 439 00:33:55,470 --> 00:33:59,540 som kommer att ringa dinky (i). 440 00:33:59,540 --> 00:34:04,030 Du kan bli förvirrad. 441 00:34:04,030 --> 00:34:07,380 Om du bara tittar på dessa linjer direkt, kanske du tänker om (i == 0), 442 00:34:07,380 --> 00:34:10,800 okej, så jag tog ett steg och nu är jag på dinky (i), 443 00:34:10,800 --> 00:34:14,120 Ni kanske tror att måste betyda i = 0 eller något. 444 00:34:14,120 --> 00:34:18,980 Nej, det betyder bara att det vet att det kan fastna direkt till linjen dinky (i). 445 00:34:18,980 --> 00:34:23,300 Eftersom jag inte är 0, är ​​nästa steg kommer inte att sluta på annat. 446 00:34:23,300 --> 00:34:26,239 Annars är inte en linje att det kommer att stanna vid. 447 00:34:26,239 --> 00:34:31,570 Det är bara att gå till nästa rad kan det faktiskt utföra, vilket är dinky (i). 448 00:34:31,570 --> 00:34:36,090 Kliva in dinky (i), ser vi om (i == 1). 449 00:34:36,090 --> 00:34:42,670 Vi vet i = 1, så när vi steg, vi vet att vi kommer att hamna i oh_no 450 00:34:42,670 --> 00:34:46,489 eftersom i = 1 anropar funktionen oh_no, som du kan kliva in, 451 00:34:46,489 --> 00:34:52,969 som kommer att ställa char ** s = till NULL och omedelbart "BOOM". 452 00:34:54,270 --> 00:34:59,690 Och sedan faktiskt titta på genomförandet av buggy2, 453 00:34:59,690 --> 00:35:04,590 detta är jag få bara ett slumptal - 0, 1, eller 2 - ringer Binky, 454 00:35:04,590 --> 00:35:10,610 som om jag är 0 man kallar oh_no, annars kallar Dinky kommer som hit. 455 00:35:10,610 --> 00:35:18,100 Om jag är 1, ring oh_no, annars kalla slinky som kommer upp hit, 456 00:35:18,100 --> 00:35:20,460 Om jag är 2, ring oh_no. 457 00:35:20,460 --> 00:35:24,720 Jag tror inte ens att det finns ett sätt - 458 00:35:24,720 --> 00:35:30,030 Ser någon ett sätt att göra detta ett program som inte kommer segmenteringsfel? 459 00:35:30,030 --> 00:35:37,530 För om jag missat något, om jag är 0, kommer du segmenteringsfel omedelbart, 460 00:35:37,530 --> 00:35:41,250 annat du gå till en funktion som om jag är en man segmenteringsfel, 461 00:35:41,250 --> 00:35:44,540 annat du gå till en funktion där om jag är 2 du segmenteringsfel. 462 00:35:44,540 --> 00:35:46,810 Så oavsett vad du gör, segmenteringsfel dig. 463 00:35:46,810 --> 00:35:52,380 >> Jag antar att ett sätt att fastställa att det skulle vara istället för att göra char ** s = NULL, 464 00:35:52,380 --> 00:35:55,610 du kan malloc utrymme för den raden. 465 00:35:55,610 --> 00:36:04,230 Vi kan göra malloc (sizeof) - sizeof vad? 466 00:36:09,910 --> 00:36:15,190 [Elev] (char) * 5? >> Verkar detta rätt? 467 00:36:15,190 --> 00:36:21,060 Jag antar detta kommer att fungera om jag faktiskt körde det, men det är inte vad jag letar efter. 468 00:36:24,400 --> 00:36:32,940 Titta på den typ av s. Låt oss lägga int *, så int * x. 469 00:36:32,940 --> 00:36:35,600 Jag skulle göra malloc (sizeof (int)). 470 00:36:35,600 --> 00:36:40,490 Eller om jag ville ha en uppsättning av 5, skulle jag göra (sizeof (int) * 5); 471 00:36:40,490 --> 00:36:44,210 Vad händer om jag har en int **? 472 00:36:46,260 --> 00:36:49,140 Vad skulle jag malloc? 473 00:36:49,140 --> 00:36:53,510 [Elev] Storlek på pekaren. >> Ja. (Sizeof (int *)); 474 00:36:53,510 --> 00:36:56,960 Samma sak här nere. 475 00:36:56,960 --> 00:37:01,280 Jag vill ha (sizeof (char *)); 476 00:37:06,170 --> 00:37:12,840 Detta kommer att allokera utrymme för pekaren som pekar på "BOOM". 477 00:37:12,840 --> 00:37:15,330 Jag behöver inte allokera utrymme för "boom" själv 478 00:37:15,330 --> 00:37:17,210 eftersom detta är i grunden motsvarar vad jag sa tidigare 479 00:37:17,210 --> 00:37:20,870 av char * x = "BOOM". 480 00:37:20,870 --> 00:37:27,950 "BOOM" finns redan. Det händer att existera i skrivskyddade region minne. 481 00:37:27,950 --> 00:37:35,200 Men det finns redan, vilket innebär kodraden, om S är en röding ** 482 00:37:35,200 --> 00:37:43,900 då * s är en char * och du ställer denna char * peka på "BOOM". 483 00:37:43,900 --> 00:37:50,040 Om jag ville kopiera "BOOM" i s, då skulle jag behöva allokera utrymme för s. 484 00:37:55,170 --> 00:38:03,900 Jag gör * s = malloc (sizeof (char) * 5); 485 00:38:03,900 --> 00:38:06,210 Varför 5? 486 00:38:06,210 --> 00:38:10,860 Varför inte 4? Det ser ut som "boom" är 4 tecken. >> [Elev] Den null karaktär. 487 00:38:10,860 --> 00:38:14,580 Ja. Alla dina strängar kommer att behöva null karaktär. 488 00:38:14,580 --> 00:38:23,590 Nu kan jag göra något liknande strcat - Vad är funktionen för att kopiera en sträng? 489 00:38:23,590 --> 00:38:28,520 [Eleven] CpY? >> Strcpy. 490 00:38:28,520 --> 00:38:32,700 Mannen strcpy. 491 00:38:36,120 --> 00:38:39,590 Så strcpy eller strncpy. 492 00:38:39,590 --> 00:38:43,410 strncpy är lite säkrare eftersom du kan ange exakt hur många tecken, 493 00:38:43,410 --> 00:38:46,190 men här spelar det ingen roll eftersom vi vet. 494 00:38:46,190 --> 00:38:50,340 Så strcpy och titta i argumenten. 495 00:38:50,340 --> 00:38:53,100 Det första argumentet är vårt mål. 496 00:38:53,100 --> 00:38:56,770 Det andra argumentet är vår källa. 497 00:38:56,770 --> 00:39:10,310 Vi kommer att kopiera till vår destination * s pekaren "BOOM". 498 00:39:10,310 --> 00:39:19,820 Varför kan du göra detta med en strcpy istället för att bara vad vi hade innan 499 00:39:19,820 --> 00:39:22,800 av * s = "BOOM"? 500 00:39:22,800 --> 00:39:28,630 Det finns en anledning till att du kanske vill göra detta, men vad är den anledningen? 501 00:39:28,630 --> 00:39:31,940 [Eleven] Om du vill ändra något i "boom". >> Ja. 502 00:39:31,940 --> 00:39:37,950 Nu kan jag göra något liknande s [0] = 'X'; 503 00:39:37,950 --> 00:39:48,190 eftersom s pekar på högen och utrymme på högen som är pekar på 504 00:39:48,190 --> 00:39:52,320 är en pekare till mer utrymme på högen, som lagrar "BOOM". 505 00:39:52,320 --> 00:39:55,150 Så denna kopia av "boom" lagras i högen. 506 00:39:55,150 --> 00:39:58,780 Det är tekniskt två exemplar av "boom" i vårt program. 507 00:39:58,780 --> 00:40:03,500 Det är den första som bara ges av detta "BOOM" strängkonstant, 508 00:40:03,500 --> 00:40:09,250 och den andra kopian av "boom", skapade strcpy kopian av "boom". 509 00:40:09,250 --> 00:40:13,100 Men kopia av "boom" lagras på högen, och högen du är fri att ändra. 510 00:40:13,100 --> 00:40:17,250 Högen är inte skrivskyddad innebär så att s [0] 511 00:40:17,250 --> 00:40:20,500 kommer att låta dig ändra värdet på "BOOM". 512 00:40:20,500 --> 00:40:23,130 Det kommer att låta dig ändra dessa tecken. 513 00:40:23,130 --> 00:40:26,640 >> Frågor? 514 00:40:27,740 --> 00:40:29,290 Okej. 515 00:40:29,290 --> 00:40:35,500 >> Går vidare till buggy3, låt oss gdb buggy3. 516 00:40:35,500 --> 00:40:39,840 Vi kör bara det och vi ser att vi får en segmenteringsfel. 517 00:40:39,840 --> 00:40:46,550 Om vi ​​bakåtspårning finns det bara två funktioner. 518 00:40:46,550 --> 00:40:52,970 Om vi ​​går upp i våran funktion, ser vi att vi segfaulted på denna linje. 519 00:40:52,970 --> 00:41:00,180 Så bara att titta på denna linje, int rad = 0 för (, fgets det här inte lika NULL; 520 00:41:00,180 --> 00:41:03,770 linje + +). 521 00:41:03,770 --> 00:41:08,010 Vår tidigare bildruta kallades _IO_fgets. 522 00:41:08,010 --> 00:41:10,720 Du ser att en hel del med inbyggd C funktioner, 523 00:41:10,720 --> 00:41:15,350 att när du får segmenteringsfel kommer det bli riktigt kryptiska funktionsnamn 524 00:41:15,350 --> 00:41:18,090 som detta _IO_fgets. 525 00:41:18,090 --> 00:41:21,770 Men det kommer att relatera till detta fgets samtal. 526 00:41:21,770 --> 00:41:25,850 Någonstans inne här, vi segfaulting. 527 00:41:25,850 --> 00:41:30,340 Om vi ​​tittar på de argument fgets, kan vi skriva ut buffert. 528 00:41:30,340 --> 00:41:41,180 Låt oss skriva ut som en - Åh, nej. 529 00:41:48,980 --> 00:41:51,900 Print kommer inte att fungera precis som jag vill. 530 00:41:55,460 --> 00:41:58,000 Låt oss titta på det aktuella programmet. 531 00:42:02,200 --> 00:42:09,640 Buffert är ett tecken array. Det är ett tecken uppsättning av 128 tecken. 532 00:42:09,640 --> 00:42:14,980 Så när jag säger utskriftsbufferten, det kommer att skriva ut dessa 128 tecken, 533 00:42:14,980 --> 00:42:18,300 som jag antar är vad som förväntas. 534 00:42:18,300 --> 00:42:21,390 Vad jag letar efter är skriva adressen till bufferten, 535 00:42:21,390 --> 00:42:23,680 men som inte säger mig verkligen mycket. 536 00:42:23,680 --> 00:42:30,770 Så när jag råkar säga upp här X buffert, visar mig 0xbffff090, 537 00:42:30,770 --> 00:42:38,690 som, om du kommer ihåg från tidigare eller någon gång, tenderar Oxbffff att bli en stack-ish regionen. 538 00:42:38,690 --> 00:42:46,020 Stacken tenderar att börja någonstans strax under 0xc000. 539 00:42:46,020 --> 00:42:51,890 Bara genom att se denna adress, vet jag att bufferten sker på stacken. 540 00:42:51,890 --> 00:43:04,500 Omstart mitt program, köra, upp, buffert vi såg var denna sekvens av tecken 541 00:43:04,500 --> 00:43:06,530 som är ganska mycket meningslöst. 542 00:43:06,530 --> 00:43:12,270 Sedan skriver fil, vad filen se ut? 543 00:43:15,120 --> 00:43:17,310 [Eleven] Null. >> Ja. 544 00:43:17,310 --> 00:43:22,610 Filen är en av typen FILE *, så det är en pekare, 545 00:43:22,610 --> 00:43:26,610 och värdet av denna pekare är noll. 546 00:43:26,610 --> 00:43:33,240 Så fgets ska försöka läsa från den pekare på ett indirekt sätt, 547 00:43:33,240 --> 00:43:37,320 men för att komma åt den pekare, måste det dereference det. 548 00:43:37,320 --> 00:43:40,550 Eller, för att få tillgång till vad den borde peka på, det dereferences det. 549 00:43:40,550 --> 00:43:43,810 Så det är dereferencing en nollpekare och det segfaults. 550 00:43:46,600 --> 00:43:48,730 Jag kunde ha startat det där. 551 00:43:48,730 --> 00:43:52,170 Om vi ​​bryter på vår viktigaste punkten och kör, 552 00:43:52,170 --> 00:43:57,320 den första raden i koden är char * filnamn = "nonexistent.txt"; 553 00:43:57,320 --> 00:44:00,870 Det borde ge en ganska stor ledtråd till varför detta program inte fungerar. 554 00:44:00,870 --> 00:44:06,080 Skriva nästa leder mig till nästa rad, där jag öppnar den här filen, 555 00:44:06,080 --> 00:44:11,140 och då jag genast komma in vår linje, där en gång jag slog nästa, det kommer att segmenteringsfel. 556 00:44:11,140 --> 00:44:16,880 Vill någon att kasta ut en anledning till att vi kanske segfaulting? 557 00:44:16,880 --> 00:44:19,130 [Elev] Filen existerar inte. >> Ja. 558 00:44:19,130 --> 00:44:22,250 Detta är tänkt att vara en ledtråd 559 00:44:22,250 --> 00:44:29,570 att när du öppnar en fil som du behöver för att kontrollera att filen existerar. 560 00:44:29,570 --> 00:44:31,510 Så här, "nonexistent.txt"; 561 00:44:31,510 --> 00:44:34,700 När vi fopen filnamn för läsning, måste vi då säga 562 00:44:34,700 --> 00:44:45,870 if (fil == NULL) och säg printf ("Filen finns inte!" 563 00:44:45,870 --> 00:44:56,340 eller - ännu bättre - filnamn), avkastning 1; 564 00:44:56,340 --> 00:45:00,300 Så nu vi kontrollera om det är NULL 565 00:45:00,300 --> 00:45:03,930 innan faktiskt fortsätter och försöker läsa från den filen. 566 00:45:03,930 --> 00:45:08,800 Vi kan göra om det bara för att se att det fungerar. 567 00:45:11,020 --> 00:45:14,970 Jag avser att inkludera en ny rad. 568 00:45:21,090 --> 00:45:25,290 Så nu nonexistent.txt inte existerar. 569 00:45:26,890 --> 00:45:30,040 Du bör alltid kontrollera den här sortens saker. 570 00:45:30,040 --> 00:45:33,870 Du bör alltid kontrollera om fopen returnerar null. 571 00:45:33,870 --> 00:45:38,170 Du bör alltid kontrollera att se till att malloc inte returnerar NULL, 572 00:45:38,170 --> 00:45:41,410 eller annat du segmenteringsfel. 573 00:45:42,200 --> 00:45:45,930 >> Nu buggy4.c. 574 00:45:49,190 --> 00:45:58,440 Igång. Jag gissar det väntar på inmatning eller möjligen oändlig loop. 575 00:45:58,440 --> 00:46:01,870 Ja, det är oändligt looping. 576 00:46:01,870 --> 00:46:05,560 Så buggy4. Det ser ut som vi är oändlig loop. 577 00:46:05,560 --> 00:46:12,590 Vi kan bryta på huvud, kör vårt program. 578 00:46:12,590 --> 00:46:20,180 I gdb, så länge förkortning du använder är entydig 579 00:46:20,180 --> 00:46:23,420 eller speciella förkortningar som de tillhandahåller för dig, 580 00:46:23,420 --> 00:46:29,020 då kan du använda n för att använda nästa i stället för att behöva skriva ut nästa hela vägen. 581 00:46:29,020 --> 00:46:33,730 Och nu när jag har drabbats n en gång, kan jag slå bara Enter för att fortsätta nästa 582 00:46:33,730 --> 00:46:36,640 istället för att behöva slå n Ange, n Ange, n Enter. 583 00:46:36,640 --> 00:46:44,630 Det ser ut som jag är i någon form av for-slinga som lurar array [i] till 0. 584 00:46:44,630 --> 00:46:50,510 Det ser ut som jag aldrig bryta sig ur detta för slinga. 585 00:46:50,510 --> 00:46:54,780 Om jag skriver jag, så jag är 2, så jag ska gå härnäst. 586 00:46:54,780 --> 00:46:59,250 Jag skriver jag, jag är 3, så jag ska gå härnäst. 587 00:46:59,250 --> 00:47:05,360 Jag skriver jag och jag är 3. Därefter skriver jag, i är 4. 588 00:47:05,360 --> 00:47:14,520 Egentligen är print sizeof (matris), så storlek matris 20. 589 00:47:16,310 --> 00:47:32,870 Men det ser ut som det finns några speciella gdb-kommandot för att gå tills något händer. 590 00:47:32,870 --> 00:47:37,620 Det är som att ställa ett villkor på värdet av variabeln. Men jag minns inte vad det är. 591 00:47:37,620 --> 00:47:44,100 Så om vi hålla - 592 00:47:44,100 --> 00:47:47,120 Vad var det du sa? Vad tog du med dig? 593 00:47:47,120 --> 00:47:50,500 [Elev] Har visar jag tillägga - >> Ja. Så visar jag kan hjälpa. 594 00:47:50,500 --> 00:47:54,530 Om vi ​​bara visa i, kommer det att sätta upp här vad värdet av i är 595 00:47:54,530 --> 00:47:56,470 så jag behöver inte skriva ut varje gång. 596 00:47:56,470 --> 00:48:02,930 Om vi ​​bara hålla kommer nästa ser vi 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5. 597 00:48:02,930 --> 00:48:08,530 Något går fruktansvärt fel, och jag håller på att återställas till 0. 598 00:48:13,330 --> 00:48:22,220 Titta på buggy4.c ser vi allt som händer är int array [5]; 599 00:48:22,220 --> 00:48:26,200 for (i = 0; i <= sizeof (matris), i + +) 600 00:48:26,200 --> 00:48:28,550 array [i] = 0; 601 00:48:28,550 --> 00:48:31,390 Vad ser vi att det är fel här? 602 00:48:31,390 --> 00:48:39,480 Som en ledtråd, när jag gör gdb buggy4 - låt oss break, run - 603 00:48:39,480 --> 00:48:45,980 Jag skrevs ut sizeof (matris) bara för att se vad tillståndet är där jag bör slutligen bryta ut. 604 00:48:47,690 --> 00:48:51,100 Var är jag? Har jag springa? 605 00:48:51,100 --> 00:48:54,280 Jag har inte deklarera ännu. 606 00:48:54,280 --> 00:48:58,680 Så ut sizeof (matris) och det är 20, 607 00:48:58,680 --> 00:49:06,690 som förväntas eftersom min array är av storlek 5 och det är av 5 heltal, 608 00:49:06,690 --> 00:49:12,410 så det hela ska vara 5 * sizeof (int) byte, där sizeof (int) tenderar att vara 4. 609 00:49:12,410 --> 00:49:14,780 Så sizeof (matris) är 20. 610 00:49:14,780 --> 00:49:17,420 Vad ska det vara? 611 00:49:17,420 --> 00:49:21,720 [Elev] dividerat med sizeof (int). >> Ja, / sizeof (int). 612 00:49:21,720 --> 00:49:30,630 Det ser ut som det är fortfarande ett problem här. Jag tror att detta bara ska vara < 613 00:49:30,630 --> 00:49:36,960 eftersom det är ganska mycket alltid 00:49:44,860 Nu ska vi fundera över varför det var faktiskt bruten. 615 00:49:44,860 --> 00:49:53,370 Har någon gissningar varför var jag återställa till 0 genom varje iteration av slingan? 616 00:50:01,300 --> 00:50:09,350 Det enda inuti här som händer är att array [i] ställs in på 0. 617 00:50:09,350 --> 00:50:15,350 Så på något sätt är denna kodrad som orsakar vår int i sättas till 0. 618 00:50:16,730 --> 00:50:23,130 [Elev] Kan det vara för att det övergripande minnet av denna del av i 619 00:50:23,130 --> 00:50:27,970 när den anser att det är nästa del av matris? >> [Bowden] Ja. 620 00:50:27,970 --> 00:50:33,880 När vi går utöver slutet av vår grupp, 621 00:50:33,880 --> 00:50:39,870 något sätt att utrymme som vi tvingande är tvingande värde i.. 622 00:50:39,870 --> 00:50:48,030 Och så om vi ser på buggy4, break, springa, 623 00:50:48,030 --> 00:50:53,120 låt oss skriva adressen till i.. 624 00:50:53,120 --> 00:50:57,280 Det ser ut som det är bffff124. 625 00:50:57,280 --> 00:51:03,930 Nu ska vi skriva adressen till arrayen [0]. 110. 626 00:51:03,930 --> 00:51:06,290 Hur är [1]? 114. 627 00:51:06,290 --> 00:51:07,920 [2], 118. 628 00:51:07,920 --> 00:51:14,530 11c, 120. Array [5] är bfff124. 629 00:51:14,530 --> 00:51:26,990 Så Array [5] har samma adress som jag, vilket innebär att Array [5] är jag. 630 00:51:26,990 --> 00:51:30,720 Om de har samma adress, är de samma sak. 631 00:51:30,720 --> 00:51:38,410 Så när vi satt array [5] till 0, sätter vi i till 0. 632 00:51:38,410 --> 00:51:46,070 Och om du tänker på detta i form av stapeln, 633 00:51:46,070 --> 00:51:55,590 int i förklaras först, vilket betyder att jag får lite utrymme på stacken. 634 00:51:55,590 --> 00:52:04,730 Då Array [5] fördelas, så då 20 byte tilldelas på stacken. 635 00:52:04,730 --> 00:52:08,400 Så jag får fördelas i första, då dessa 20 byte blir tilldelade. 636 00:52:08,400 --> 00:52:11,400 Så jag händer precis innan arrayen, 637 00:52:11,400 --> 00:52:19,230 och på grund av det sätt, som jag sa förra veckan, där det är tekniskt stapeln växer ner, 638 00:52:19,230 --> 00:52:28,520 när man index i en matris, är vi garanteras att 0:e position i matrisen 639 00:52:28,520 --> 00:52:31,970 alltid händer innan den första positionen i arrayen. 640 00:52:31,970 --> 00:52:35,900 Detta är typ av hur jag drog det förra veckan. 641 00:52:35,900 --> 00:52:42,210 Lägg märke till att vid botten har vi adress 0 och vid toppen har vi adress. 642 00:52:42,210 --> 00:52:44,880 Stacken är alltid växer nedåt. 643 00:52:48,100 --> 00:52:53,500 Låt oss säga att vi fördela i.. 644 00:52:53,500 --> 00:52:59,680 Vi fördela heltal i, vilket betyder låt oss bara säga upp här heltal i blir tilldelade. 645 00:52:59,680 --> 00:53:06,420 Då vi fördela vår samling av 5 heltal, vilket innebär att under det, 646 00:53:06,420 --> 00:53:11,230 eftersom stapeln växer ner, få de 5 heltal tilldelas. 647 00:53:11,230 --> 00:53:15,900 Men på grund av hur arrayer fungerar, vi garanterat att den första positionen i arrayen 648 00:53:15,900 --> 00:53:22,260 alltid har en adress mindre än den andra sak i arrayen. 649 00:53:22,260 --> 00:53:28,270 Så array läge 0 måste alltid ske först i minnet, 650 00:53:28,270 --> 00:53:30,700 medan array läge 1 måste ske efter det 651 00:53:30,700 --> 00:53:33,310 och array läge 2 måste ske efter det, 652 00:53:33,310 --> 00:53:37,900 vilket innebär att array läge 0 skulle hända någonstans här nere, 653 00:53:37,900 --> 00:53:40,690 matrisposition 1 skulle hända ovan att 654 00:53:40,690 --> 00:53:45,530 eftersom flytta upp innebär högre adresser eftersom den högsta adressen är här uppe. 655 00:53:45,530 --> 00:53:50,490 Så array [0] här nere, array [1] upp här, array [2] här uppe, array [3] upp här. 656 00:53:50,490 --> 00:53:55,620 Lägg märke till hur innan vi tilldelades heltal i hela vägen upp hit, 657 00:53:55,620 --> 00:54:01,040 när vi går längre och längre in i vår grupp, vi komma närmare och närmare vår heltal i.. 658 00:54:01,040 --> 00:54:07,640 Det råkar vara så att arrayen [5], som är en plats bortom vår array, 659 00:54:07,640 --> 00:54:13,010 är precis där heltal jag råkade fördelas. 660 00:54:13,010 --> 00:54:16,920 Så det är den punkt där vi råkar slå utrymmet på stacken 661 00:54:16,920 --> 00:54:21,680 som avsatts för heltal i, och vi sätta det till 0. 662 00:54:21,680 --> 00:54:26,160 >> Det är så det fungerar. Frågor? Ja. 663 00:54:26,160 --> 00:54:30,710 [Elev] Strunta. Okej. 664 00:54:30,710 --> 00:54:33,090 [Elev] Hur undviker man denna typ av fel? 665 00:54:33,090 --> 00:54:41,190 Denna typ av fel? Använd inte C som din programmeringsspråk. 666 00:54:41,190 --> 00:54:45,840 Använd ett språk som har array gränskontroll. 667 00:54:45,840 --> 00:54:55,900 Så länge du är försiktig, behöver du bara undvika att gå förbi gränserna för din array. 668 00:54:55,900 --> 00:54:58,300 [Eleven] Så här när vi gick förbi gränserna för din array - 669 00:54:58,300 --> 00:55:01,840 [Bowden] Det är där saker och ting börjar gå snett. >> [Elev] Åh, okej. 670 00:55:01,840 --> 00:55:05,730 Så länge du håller dig i minnet som tilldelats för din array, du bra. 671 00:55:05,730 --> 00:55:12,400 Men C gör ingen felkontroll. Om jag gör array [1000], kommer det gärna bara ändra vad som än händer - 672 00:55:12,400 --> 00:55:16,500 Det går till början av arrayen, så det går 1000 positioner efter och ställer den till 0. 673 00:55:16,500 --> 00:55:20,000 Det gör inte någon kontroll som oh, detta inte faktiskt 1000 saker i den. 674 00:55:20,000 --> 00:55:22,750 1000 är långt utöver vad jag borde förändras, 675 00:55:22,750 --> 00:55:26,940 medan Java eller något du får utbud av gränserna index 676 00:55:26,940 --> 00:55:29,820 eller index utanför gränserna undantag. 677 00:55:29,820 --> 00:55:33,950 Det är därför en hel del på högre nivå språk har dessa saker 678 00:55:33,950 --> 00:55:37,340 där om du går utöver gränserna för matrisen, misslyckas du 679 00:55:37,340 --> 00:55:40,070 så att du inte kan ändra saker från under dig 680 00:55:40,070 --> 00:55:42,590 och sedan det går mycket värre än att bara få ett undantag 681 00:55:42,590 --> 00:55:44,940 säger att du gick längre än till slutet av arrayen. 682 00:55:44,940 --> 00:55:50,970 [Elev] Och så borde vi just ändrat <= bara > [Bowden] Ja. 683 00:55:50,970 --> 00:55:54,800 Det bör vara 00:55:59,560 eftersom sizeof (matris) är 20, men vi vill bara 5. >> [Elev] Rätt. 685 00:55:59,560 --> 00:56:04,060 Fler frågor? Okej. 686 00:56:04,060 --> 00:56:07,380 >> [Elev] Jag har en fråga. >> Ja. 687 00:56:07,380 --> 00:56:16,440 [Eleven] Vad är den verkliga arrayvariabel? 688 00:56:16,440 --> 00:56:20,000 [Bowden] Som vad är array? 689 00:56:20,000 --> 00:56:24,930 Array själv är en symbol. 690 00:56:24,930 --> 00:56:31,490 Det är bara adressen till början av 20 byte som vi refererar. 691 00:56:31,490 --> 00:56:38,070 Du kan se det som en pekare, men det är en konstant pekare. 692 00:56:38,070 --> 00:56:44,140 Så snart saker blir sammanställts existerar variabeln arrayen inte längre. 693 00:56:44,140 --> 00:56:48,210 [Elev] Så hur hittar den storlek array? 694 00:56:48,210 --> 00:56:54,130 Storlek på matris hänvisar till storleken på detta block att den symbolen hänvisar till. 695 00:56:54,130 --> 00:57:01,240 När jag gör något liknande printf ("% p \ n", array); 696 00:57:01,240 --> 00:57:05,140 låt oss köra den. 697 00:57:12,960 --> 00:57:15,530 Vad har jag gjort bara fel? 698 00:57:15,530 --> 00:57:19,220 Array "array" redovisas här. 699 00:57:20,820 --> 00:57:23,200 Åh, här uppe. 700 00:57:23,200 --> 00:57:31,250 Klang är smart, och det händer att märka att jag förklarade matrisen som 5 element 701 00:57:31,250 --> 00:57:34,540 men jag indexera på plats 1000. 702 00:57:34,540 --> 00:57:38,450 Det kan göra det eftersom det är bara konstanter. 703 00:57:38,450 --> 00:57:43,370 Det kan bara gå så långt i att märka att jag kommer förbi gränserna för matrisen. 704 00:57:43,370 --> 00:57:46,880 Men märker innan när vi hade jag vara felaktig, 705 00:57:46,880 --> 00:57:51,040 Det kan omöjligen avgöra hur många värden jag kunde ta på, 706 00:57:51,040 --> 00:57:55,540 så det kan inte bestämma att jag gick längre än till slutet av arrayen. 707 00:57:55,540 --> 00:57:59,430 Det är bara klang är smart. 708 00:57:59,430 --> 00:58:03,340 >> Men nu gör buggy4. Så vad mer gör jag för fel? 709 00:58:03,340 --> 00:58:05,970 Underförstått förklara biblioteksfunktion "printf". 710 00:58:05,970 --> 00:58:14,960 Jag kommer att vilja # include . 711 00:58:14,960 --> 00:58:18,710 Okej. Nu kör buggy4. 712 00:58:18,710 --> 00:58:24,840 Skriva ut värdet i matrisen som jag gjorde här, skriva ut det som en pekare 713 00:58:24,840 --> 00:58:30,060 utskrifter något som ser ut så här - bfb8805c - som är en del adress 714 00:58:30,060 --> 00:58:33,450 Det är i bunten-ish regionen. 715 00:58:33,450 --> 00:58:41,820 Array själv är som en pekare, men det är inte en faktisk pekare, 716 00:58:41,820 --> 00:58:45,410 eftersom en vanlig pekare som vi kan förändra. 717 00:58:45,410 --> 00:58:54,700 Array är bara några konstant. De 20 minnesblock börja adress 0xbfb8805c. 718 00:58:54,700 --> 00:59:09,020 Så bfb8805c genom denna adress +20--eller jag antar -20 - 719 00:59:09,020 --> 00:59:17,400 är allt minne allokeras för denna grupp. 720 00:59:17,400 --> 00:59:20,350 Array, är själva variabeln lagras inte någonstans. 721 00:59:20,350 --> 00:59:27,660 När du kompilerar, kompilatorn - hands våg på det - 722 00:59:27,660 --> 00:59:33,060 men kompilatorn kommer bara använda när den vet array för att vara. 723 00:59:33,060 --> 00:59:36,090 Det vet var den arrayen börjar, 724 00:59:36,090 --> 00:59:40,910 och så det kan alltid bara göra saker när det gäller förskjutningar från början. 725 00:59:40,910 --> 00:59:43,960 Det behöver inte en variabel sig för att representera array. 726 00:59:43,960 --> 00:59:53,730 Men när jag gör något som int * p = array, nu p är en pekare som pekar på den arrayen, 727 00:59:53,730 --> 00:59:57,830 och nu p faktiskt existerar på stacken. 728 00:59:57,830 --> 01:00:01,950 Jag är fri att ändra sid. Jag kan göra p = malloc. 729 01:00:01,950 --> 01:00:06,500 Så det pekade ursprungligen rad, nu pekar på en viss plats på högen. 730 01:00:06,500 --> 01:00:09,620 Jag kan inte göra array = malloc. 731 01:00:09,620 --> 01:00:13,710 Om klang är smart, kommer det att skrika på mig just off the bat. 732 01:00:17,000 --> 01:00:21,430 Jag är faktiskt ganska säker gcc skulle göra detta också. 733 01:00:21,430 --> 01:00:25,010 Så array typ "int [5]" är inte överlåtas. 734 01:00:25,010 --> 01:00:28,040 Du kan inte tilldela något till en array typ 735 01:00:28,040 --> 01:00:30,500 eftersom matrisen är bara en konstant. 736 01:00:30,500 --> 01:00:34,760 Det är en symbol som hänvisar dessa 20 byte. Jag kan inte ändra det. 737 01:00:34,760 --> 01:00:37,690 >> [Elev] Och där är storleken på matrisen lagras? 738 01:00:37,690 --> 01:00:40,670 [Bowden] Det är inte lagras någonstans. Det är när det kompilering. 739 01:00:40,670 --> 01:00:46,310 Så där är storleken på matrisen lagras? 740 01:00:46,310 --> 01:00:51,870 Du kan bara använda sizeof (matris) inuti den funktion som arrayen är förklarat sig. 741 01:00:51,870 --> 01:01:03,150 Så om jag gör någon funktion, foo, och jag gör (int array []) 742 01:01:03,150 --> 01:01:10,450 printf ("% d \ n", sizeof (matris)); 743 01:01:10,450 --> 01:01:21,330 och sedan ner här jag kallar foo (matris); 744 01:01:21,330 --> 01:01:24,840 insidan av denna funktion - låt oss köra den. 745 01:01:34,200 --> 01:01:36,840 Detta är klang är smart igen. 746 01:01:36,840 --> 01:01:43,890 Det säger mig att sizeof på rad funktionsparameter 747 01:01:43,890 --> 01:01:46,690 kommer tillbaka storleken på "int * '. 748 01:01:46,690 --> 01:01:55,150 Detta skulle vara ett misstag om det inte det jag ville skulle hända. 749 01:01:55,150 --> 01:01:58,960 Låt oss verkligen stänga Werror. 750 01:02:14,950 --> 01:02:17,590 Varning. Varningar är bra. 751 01:02:17,590 --> 01:02:19,960 Det kommer fortfarande sammanställer så länge som den har en varning. 752 01:02:19,960 --> 01:02:22,910 . / A.out kommer att skriva ut 4. 753 01:02:22,910 --> 01:02:28,650 Varningen som genererades är en tydlig indikator på vad som gick fel. 754 01:02:28,650 --> 01:02:34,120 Denna int array bara att skriva ut sizeof (int *). 755 01:02:34,120 --> 01:02:39,790 Även om jag sätter array [5] här, det är fortfarande bara att skriva ut sizeof (int *). 756 01:02:39,790 --> 01:02:47,440 Så fort du för in en funktion, skillnaden mellan arrayer och pekare 757 01:02:47,440 --> 01:02:49,670 är obefintlig. 758 01:02:49,670 --> 01:02:52,640 Det råkar vara en array som förklarades på stacken, 759 01:02:52,640 --> 01:02:58,300 men så snart vi passerar det värdet att 0xbf bla, bla, bla i denna funktion, 760 01:02:58,300 --> 01:03:03,350 då denna pekare pekar på den arrayen på stacken. 761 01:03:03,350 --> 01:03:08,310 Så det betyder att sizeof endast gäller den funktion som arrayen förklarades, 762 01:03:08,310 --> 01:03:11,230 vilket innebär att när du kompilerar denna funktion, 763 01:03:11,230 --> 01:03:17,330 När klang går igenom den här funktionen ser det array är en int array av storlek 5. 764 01:03:17,330 --> 01:03:20,640 Så då ser sizeof (matris). Tja, det är 20. 765 01:03:20,640 --> 01:03:26,440 Det är faktiskt hur sizeof princip fungerar för nästan alla fall. 766 01:03:26,440 --> 01:03:31,150 Sizeof är inte en funktion, det är en operatör. 767 01:03:31,150 --> 01:03:33,570 Du kallar inte sizeof funktionen. 768 01:03:33,570 --> 01:03:38,280 Sizeof (int) kommer kompilatorn översätter bara det till 4. 769 01:03:41,480 --> 01:03:43,700 Uppfattat? Okej. 770 01:03:43,700 --> 01:03:47,520 >> [Elev] Så vad är skillnaden mellan sizeof (matris) i huvud och foo! 771 01:03:47,520 --> 01:03:52,840 Detta beror på att vi säger sizeof (matris), som är av typen int *, 772 01:03:52,840 --> 01:03:57,120 medan matrisen här nere är inte av typen int *, det är en int array. 773 01:03:57,120 --> 01:04:04,540 >> [Elev] Så om du hade parametern i arrayen [] istället för int * array, 774 01:04:04,540 --> 01:04:09,230 skulle det betyda att du fortfarande kan ändra uppsättning för nu är det en pekare? 775 01:04:09,230 --> 01:04:14,250 [Bowden] Gillar du? >> [Elev] Ja. Kan du ändra rad i funktionen nu? 776 01:04:14,250 --> 01:04:18,420 [Bowden] Du kan ändra rad i båda fallen. 777 01:04:18,420 --> 01:04:23,130 I båda dessa fall är du fri att säga array [4] = 0. 778 01:04:23,130 --> 01:04:26,590 [Elev] Men kan du göra array pekar på något annat? 779 01:04:26,590 --> 01:04:30,230 [Bowden] Oh. Ja. I båda fallen - >> [elev] Ja. 780 01:04:30,230 --> 01:04:38,410 [Bowden] Skillnaden mellan Array [] och en int * array, det finns ingen. 781 01:04:38,410 --> 01:04:42,570 Du kan också få lite flerdimensionell array här 782 01:04:42,570 --> 01:04:47,050 för några praktiska syntax, men det är fortfarande bara en pekare. 783 01:04:47,050 --> 01:04:56,400 Det innebär att jag är fri att göra array = malloc (sizeof (int)), och nu pekar någon annanstans. 784 01:04:56,400 --> 01:04:59,610 Men precis som hur det fungerar alltid och alltid, 785 01:04:59,610 --> 01:05:03,210 ändra denna rad genom att göra det pekar på något annat 786 01:05:03,210 --> 01:05:07,570 ändrar inte denna array här nere eftersom det är en kopia av argumentet, 787 01:05:07,570 --> 01:05:10,780 det är inte en pekare till det argumentet. 788 01:05:10,780 --> 01:05:16,070 Och faktiskt, precis som mer tecken på att det är exakt samma - 789 01:05:16,070 --> 01:05:21,100 vi såg redan vad utskrifter utskrift array - 790 01:05:21,100 --> 01:05:31,410 Vad händer om vi skriver ut adressen till gruppen eller adressen till adressen i matrisen 791 01:05:31,410 --> 01:05:36,290 till någon av dem? 792 01:05:41,770 --> 01:05:45,220 Låt oss bortse från detta. 793 01:05:48,140 --> 01:05:51,660 Okej. Detta är bra. Det är nu igång. / A.out. 794 01:05:51,660 --> 01:06:00,220 Utskrift matris, sedan skriva adressen till arrayen, är samma sak. 795 01:06:00,220 --> 01:06:02,870 Array bara inte. 796 01:06:02,870 --> 01:06:08,190 Den vet när du skriver array, du skriver den symbol som hänvisar till dessa 20 byte. 797 01:06:08,190 --> 01:06:11,940 Skriva ut adress arrayen, ja, existerar array inte. 798 01:06:11,940 --> 01:06:17,200 Det har inte en adress, så att det bara skriver adressen för dessa 20 bitgrupper. 799 01:06:20,820 --> 01:06:28,150 Så snart du kompilerar ner, som i din sammanställt buggy4. / A.out, 800 01:06:28,150 --> 01:06:30,340 matris är obefintlig. 801 01:06:30,340 --> 01:06:33,640 Pekare finns. Matriser inte. 802 01:06:34,300 --> 01:06:38,060 Blocken minne representerar matrisen finns fortfarande, 803 01:06:38,060 --> 01:06:43,270 men den variabla matris och variabler av denna typ inte finns. 804 01:06:46,260 --> 01:06:50,270 De är som de viktigaste skillnaderna mellan arrayer och pekare 805 01:06:50,270 --> 01:06:55,590 är så fort du gör funktionsanrop, är det ingen skillnad. 806 01:06:55,590 --> 01:07:00,460 Men insidan av funktion som arrayen självt förklaras arbetar sizeof annorlunda 807 01:07:00,460 --> 01:07:05,190 eftersom du skriver storleken på blocken istället för storleken på typen, 808 01:07:05,190 --> 01:07:08,950 och du kan inte ändra det eftersom det är en symbol. 809 01:07:08,950 --> 01:07:14,370 Skriva ut saken och adressen saken skriver samma sak. 810 01:07:14,370 --> 01:07:18,480 Och det är ganska mycket det. 811 01:07:18,480 --> 01:07:20,820 [Elev] Kan du säga att en gång till? 812 01:07:21,170 --> 01:07:24,170 Jag kanske har missat något. 813 01:07:24,170 --> 01:07:29,260 Utskrift array och adress matris skriver samma sak, 814 01:07:29,260 --> 01:07:33,180 medan om du skriver ut en pekare mot adressen till pekaren, 815 01:07:33,180 --> 01:07:36,010 en sak skriver adressen till vad du pekar på, 816 01:07:36,010 --> 01:07:40,360 den andra skriver adressen till pekaren på stacken. 817 01:07:40,360 --> 01:07:47,040 Du kan ändra en pekare, du kan inte ändra en rad symbol. 818 01:07:47,740 --> 01:07:53,270 Och sizeof pekare kommer att skriva ut storleken på den pekartyp. 819 01:07:53,270 --> 01:07:57,470 Så int * p sizeof (p) kommer att skriva ut 4, 820 01:07:57,470 --> 01:08:04,110 men int array [5] Skriv ut sizeof (matris) kommer att skriva ut 20. 821 01:08:04,110 --> 01:08:07,480 [Elev] Så int array [5] kommer att skriva ut 20? >> Ja. 822 01:08:07,480 --> 01:08:13,300 Det är därför inne i buggy4 när det brukade vara sizeof (matris) 823 01:08:13,300 --> 01:08:16,660 detta gjorde i <20, vilket inte är vad vi ville ha. 824 01:08:16,660 --> 01:08:20,880 Vi vill i <5. >> [Elev] Okej. 825 01:08:20,880 --> 01:08:25,569 [Bowden] Och sedan så fort du börjar passerar i funktionerna, 826 01:08:25,569 --> 01:08:34,340 om vi gjorde int * p = array; 827 01:08:34,340 --> 01:08:39,779 insidan av denna funktion, kan vi använda i stort sett p och matris i exakt samma sätt, 828 01:08:39,779 --> 01:08:43,710 med undantag för sizeof problemet och växande problem. 829 01:08:43,710 --> 01:08:49,810 Men p [0] = 1, är detsamma som att säga array [0] = 1; 830 01:08:49,810 --> 01:08:55,600 Och så snart vi säger foo (matris) eller foo (p); 831 01:08:55,600 --> 01:08:59,760 insidan av foo funktionen är samma samtal två gånger. 832 01:08:59,760 --> 01:09:03,350 Det är ingen skillnad mellan dessa två samtal. 833 01:09:07,029 --> 01:09:11,080 >> Alla bra på det? Okej. 834 01:09:14,620 --> 01:09:17,950 Vi har 10 minuter. 835 01:09:17,950 --> 01:09:28,319 >> Vi ska försöka få igenom detta Hacker Typer program 836 01:09:28,319 --> 01:09:32,350 denna webbplats, som kom ut förra året eller något. 837 01:09:34,149 --> 01:09:41,100 Det är bara tänkt att vara som du skriver slumpmässigt och det skrivs ut - 838 01:09:41,100 --> 01:09:46,729 Oavsett fil det händer att ha laddat är vad det ser ut som du skriver. 839 01:09:46,729 --> 01:09:52,069 Det ser ut som något slags operativsystem kod. 840 01:09:53,760 --> 01:09:56,890 Det är vad vi vill genomföra. 841 01:10:08,560 --> 01:10:11,690 Du bör ha en binär körbar heter hacker_typer 842 01:10:11,690 --> 01:10:14,350 som tar i ett enda argument, filen till "hacker-typ." 843 01:10:14,350 --> 01:10:16,480 Köra den körbara ska rensa skärmen 844 01:10:16,480 --> 01:10:20,850 och sedan skriva ut ett tecken från den skickade i fil varje gång användaren trycker på en tangent. 845 01:10:20,850 --> 01:10:24,990 Så vad tangent du trycker på, bör det kasta bort och istället skriva ut ett tecken från filen 846 01:10:24,990 --> 01:10:27,810 som är argumentet. 847 01:10:29,880 --> 01:10:34,350 Jag ska ganska mycket berätta vad de saker vi kommer att behöva veta är. 848 01:10:34,350 --> 01:10:36,440 Men vi vill att checka ut termios biblioteket. 849 01:10:36,440 --> 01:10:44,840 Jag har aldrig använt det här biblioteket i hela mitt liv, så det har mycket minimal syften. 850 01:10:44,840 --> 01:10:48,610 Men detta kommer att bli biblioteket kan vi använda för att kasta bort det tecken du träffar 851 01:10:48,610 --> 01:10:52,390 När du skriver till standard i. 852 01:10:56,970 --> 01:11:05,840 Så hacker_typer.c, och vi kommer att vilja # include . 853 01:11:05,840 --> 01:11:12,870 Man tittar på man-sidan för termios - jag gissar att det terminal OS eller något - 854 01:11:12,870 --> 01:11:16,240 Jag vet inte hur man läser det. 855 01:11:16,240 --> 01:11:21,040 Titta på det här, säger den till att omfatta dessa 2 filer, så vi ska göra det. 856 01:11:37,620 --> 01:11:46,820 >> Första sak först, vill vi ta i ett enda argument, som är den fil som vi skall öppna. 857 01:11:46,820 --> 01:11:52,420 Så vad vill jag göra? Hur kontrollerar jag att se jag har ett enda argument? 858 01:11:52,420 --> 01:11:56,480 [Eleven] Om argc lika det. >> [Bowden] Ja. 859 01:11:56,480 --> 01:12:21,250 Så om (argc = 2!) Printf ("Användning:% s [fil som ska öppnas]"). 860 01:12:21,250 --> 01:12:32,750 Så nu om jag kör det här utan att ge en andra argument - åh, jag behöver den nya linjen - 861 01:12:32,750 --> 01:12:36,240 ser du det står användning:. / hacker_typer, 862 01:12:36,240 --> 01:12:39,770 och sedan det andra argumentet bör vara den fil jag vill öppna. 863 01:12:58,430 --> 01:13:01,260 Vad gör jag? 864 01:13:01,260 --> 01:13:08,490 Jag vill läsa från filen. Hur läser jag från en fil? 865 01:13:08,490 --> 01:13:11,920 [Elev] Du öppnar den första. >> Ja. 866 01:13:11,920 --> 01:13:15,010 Så fopen. Hur ser fopen ut? 867 01:13:15,010 --> 01:13:22,980 [Elev] Filnamn. >> [Bowden] Filnamn kommer att bli argv [1]. 868 01:13:22,980 --> 01:13:26,110 [Elev] och sedan vad du vill göra med det, så - >> [Bowden] Ja. 869 01:13:26,110 --> 01:13:28,740 Så om du inte kommer ihåg, kan du göra precis människa fopen, 870 01:13:28,740 --> 01:13:32,960 där det kommer att bli en const char * sökväg där sökväg är filnamn, 871 01:13:32,960 --> 01:13:34,970 const char *-läge. 872 01:13:34,970 --> 01:13:38,660 Om du råkar inte komma ihåg vad läget är, då kan du leta efter läge. 873 01:13:38,660 --> 01:13:44,660 Inuti man-sidor är snedstreck vad du kan använda för att söka efter saker. 874 01:13:44,660 --> 01:13:49,790 Så jag skriver / läge för att söka efter läge. 875 01:13:49,790 --> 01:13:57,130 n och n är vad du kan använda för att bläddra igenom sökning matcher. 876 01:13:57,130 --> 01:13:59,800 Här står de punkter argument läget till en sträng 877 01:13:59,800 --> 01:14:01,930 början med en av följande sekvenser. 878 01:14:01,930 --> 01:14:06,480 Så r, Öppna textfil för läsning. Det är vad vi vill göra. 879 01:14:08,930 --> 01:14:13,210 För att läsa, och jag vill spara det. 880 01:14:13,210 --> 01:14:18,720 Saken kommer att bli en fil *. Nu vad vill jag göra? 881 01:14:18,720 --> 01:14:21,200 Ge mig en sekund. 882 01:14:28,140 --> 01:14:30,430 Okej. Nu vad vill jag göra? 883 01:14:30,430 --> 01:14:32,940 [Elev] Kontrollera om det är NULL. >> [Bowden] Ja. 884 01:14:32,940 --> 01:14:38,690 Varje gång du öppnar en fil, se till att du framgångsrikt kunna öppna den. 885 01:14:58,930 --> 01:15:10,460 >> Nu vill jag göra det termios saker där jag vill först läsa mina nuvarande inställningar 886 01:15:10,460 --> 01:15:14,050 och spara dem till något, då jag vill ändra mina inställningar 887 01:15:14,050 --> 01:15:19,420 att kasta bort alla tecken som jag skriver, 888 01:15:19,420 --> 01:15:22,520 och då vill jag uppdatera dessa inställningar. 889 01:15:22,520 --> 01:15:27,250 Och sedan i slutet av programmet, vill jag ändra tillbaka till min ursprungliga inställningar. 890 01:15:27,250 --> 01:15:32,080 Så struct kommer att vara av typ termios, och jag kommer att vilja två av dem. 891 01:15:32,080 --> 01:15:35,600 Den första kommer att vara mina current_settings, 892 01:15:35,600 --> 01:15:42,010 och då de kommer att vara mina hacker_settings. 893 01:15:42,010 --> 01:15:48,070 Först kommer jag att vilja spara mina nuvarande inställningar, 894 01:15:48,070 --> 01:15:53,790 då ska jag vill uppdatera hacker_settings, 895 01:15:53,790 --> 01:16:01,570 och sedan sätt i slutet av mitt program vill jag återgå till de aktuella inställningarna. 896 01:16:01,570 --> 01:16:08,660 Så sparar aktuella inställningar, det sätt som fungerar, vi man termios. 897 01:16:08,660 --> 01:16:15,810 Vi ser att vi har denna int tcsetattr, int tcgetattr. 898 01:16:15,810 --> 01:16:22,960 Jag passerar en termios struct av dess pekare. 899 01:16:22,960 --> 01:16:30,640 Hur denna kommer att se är - jag har redan glömt vad funktionen hette. 900 01:16:30,640 --> 01:16:34,930 Kopiera och klistra in den. 901 01:16:39,150 --> 01:16:45,500 Så tcgetattr, då vill jag gå i struct som jag sparar informationen i, 902 01:16:45,500 --> 01:16:49,650 som kommer att bli current_settings, 903 01:16:49,650 --> 01:16:59,120 och det första argumentet är filidentifieraren för det jag vill spara attribut. 904 01:16:59,120 --> 01:17:04,360 Vad filidentifieraren är är som när du öppnar en fil, det blir en filidentifierare. 905 01:17:04,360 --> 01:17:14,560 När jag fopen argv [1], det blir en filidentifierare som du refererar 906 01:17:14,560 --> 01:17:16,730 när du vill läsa eller skriva till den. 907 01:17:16,730 --> 01:17:19,220 Det är inte filidentifieraren jag vill använda här. 908 01:17:19,220 --> 01:17:21,940 Det finns tre filbeskrivningar du har som standard, 909 01:17:21,940 --> 01:17:24,310 som är standard i, standard ut, och standardfel. 910 01:17:24,310 --> 01:17:29,960 Som standard, jag tror det är standard i är 0, är ​​standard ut 1, och standard error är 2. 911 01:17:29,960 --> 01:17:33,980 Så vad vill jag ändra inställningarna för? 912 01:17:33,980 --> 01:17:37,370 Jag vill ändra inställningarna för varje gång jag slog ett tecken, 913 01:17:37,370 --> 01:17:41,590 Jag vill att det ska kasta tecknet bort i stället för att skriva ut det på skärmen. 914 01:17:41,590 --> 01:17:45,960 Vilken ström - standard i, standard ut, eller standardfel - 915 01:17:45,960 --> 01:17:52,050 svarar på saker när jag skriver på tangentbordet? >> [Eleven] Standard i. >> Ja. 916 01:17:52,050 --> 01:17:56,450 Så jag kan antingen göra 0 eller jag kan göra stdin. 917 01:17:56,450 --> 01:17:59,380 Jag får current_settings av standard i. 918 01:17:59,380 --> 01:18:01,720 >> Nu vill jag uppdatera dessa inställningar, 919 01:18:01,720 --> 01:18:07,200 så först ska jag kopiera till hacker_settings vad mina current_settings är. 920 01:18:07,200 --> 01:18:10,430 Och hur structs arbete är det bara kopiera. 921 01:18:10,430 --> 01:18:14,510 Detta kopierar alla fält, som du förväntar dig. 922 01:18:14,510 --> 01:18:17,410 >> Nu vill jag uppdatera några av fälten. 923 01:18:17,410 --> 01:18:21,670 Titta på termios, skulle du behöva läsa igenom en hel del av detta 924 01:18:21,670 --> 01:18:24,110 bara för att se vad du vill söka efter, 925 01:18:24,110 --> 01:18:28,210 men flaggorna du kommer att vilja leta efter är eko, 926 01:18:28,210 --> 01:18:33,110 så ECHO ECHO inmatade tecken. 927 01:18:33,110 --> 01:18:37,710 Först vill jag ställa - jag har redan glömt vad fälten. 928 01:18:45,040 --> 01:18:47,900 Detta är vad struct ser ut. 929 01:18:47,900 --> 01:18:51,060 Så inmatningslägen Jag tror att vi vill ändra. 930 01:18:51,060 --> 01:18:54,210 Vi ska titta på lösningen för att se till att det är vad vi vill förändra. 931 01:19:04,060 --> 01:19:12,610 Vi vill ändra lflag för att förhindra behöva titta igenom alla dessa. 932 01:19:12,610 --> 01:19:14,670 Vi vill förändra lokala lägen. 933 01:19:14,670 --> 01:19:17,710 Du skulle behöva läsa igenom hela denna sak att förstå där allt hör 934 01:19:17,710 --> 01:19:19,320 att vi vill förändra. 935 01:19:19,320 --> 01:19:24,120 Men det är inne i lokala lägen där vi kommer att vilja ändra på det. 936 01:19:27,080 --> 01:19:33,110 Så hacker_settings.cc_lmode är vad det kallas. 937 01:19:39,630 --> 01:19:43,020 c_lflag. 938 01:19:49,060 --> 01:19:52,280 Det är där vi kommer in bitvisa operatörer. 939 01:19:52,280 --> 01:19:54,860 Vi typ av för sent, men vi ska gå igenom det riktigt snabbt. 940 01:19:54,860 --> 01:19:56,600 Det är där vi kommer in bitvisa operatörer, 941 01:19:56,600 --> 01:19:59,950 där jag tror att jag sa en gång för länge sedan att när du börjar att göra med flaggor, 942 01:19:59,950 --> 01:20:03,370 du kommer att använda bitvis mycket. 943 01:20:03,370 --> 01:20:08,240 Varje bit i flaggan motsvarar någon form av beteende. 944 01:20:08,240 --> 01:20:14,090 Så här har denna flagga en massa olika saker, där alla av dem betyder något annat. 945 01:20:14,090 --> 01:20:18,690 Men vad jag vill göra är att stänga precis utanför bit som motsvarar ECHO. 946 01:20:18,690 --> 01:20:25,440 Så för att vända det ut jag & = ¬ ECHO. 947 01:20:25,440 --> 01:20:30,110 Egentligen tycker jag att det är som techo eller något. Jag ska bara kolla igen. 948 01:20:30,110 --> 01:20:34,050 Jag kan termios den. Det är ECHO bara. 949 01:20:34,050 --> 01:20:38,440 ECHO kommer att bli en enda bit. 950 01:20:38,440 --> 01:20:44,230 ¬ ECHO kommer att betyda alla bitar är satta till 1, vilket innebär att alla flaggor som är inställda på true 951 01:20:44,230 --> 01:20:47,140 med undantag för ECHO lite. 952 01:20:47,140 --> 01:20:53,830 Genom att avsluta min lokala flaggor med detta innebär det flagg som för närvarande satt till TRUE 953 01:20:53,830 --> 01:20:56,520 kommer fortfarande att anges till true. 954 01:20:56,520 --> 01:21:03,240 Om min ECHO flaggan är satt till true, då nödvändigtvis inställd till false på ECHO flaggan. 955 01:21:03,240 --> 01:21:07,170 Så här kodraden stänger bara av ECHO flaggan. 956 01:21:07,170 --> 01:21:16,270 De andra kodrader, jag bara kopiera dem till förmån för tid och sedan förklara dem. 957 01:21:27,810 --> 01:21:30,180 I lösningen, sade han 0. 958 01:21:30,180 --> 01:21:33,880 Det är nog bättre att uttryckligen säga stdin. 959 01:21:33,880 --> 01:21:42,100 >> Lägg märke till att jag också ska göra ECHO | icanon här. 960 01:21:42,100 --> 01:21:46,650 Icanon avser något separat, vilket innebär kanoniska läge. 961 01:21:46,650 --> 01:21:50,280 Vilka kanoniska läge betyder är oftast när du skriver ut kommandoraden, 962 01:21:50,280 --> 01:21:54,670 standard i bearbetar inte något förrän du träffar newline. 963 01:21:54,670 --> 01:21:58,230 Så när du gör getString skriver du en massa saker, då du träffar newline. 964 01:21:58,230 --> 01:22:00,590 Det är när det är skickat till standard i. 965 01:22:00,590 --> 01:22:02,680 Det är standard. 966 01:22:02,680 --> 01:22:05,830 När jag stänger av kanoniska läge nu varje enskilt tecken du trycker 967 01:22:05,830 --> 01:22:10,910 är vad som får behandlas, som vanligtvis är typ av dåligt eftersom det är långsamt att bearbeta dessa saker, 968 01:22:10,910 --> 01:22:14,330 varför det är bra att buffra den till hela linjer. 969 01:22:14,330 --> 01:22:16,810 Men jag vill varje tecken som skall behandlas 970 01:22:16,810 --> 01:22:18,810 eftersom jag vill inte att det ska vänta på mig att slå newline 971 01:22:18,810 --> 01:22:21,280 innan bearbetningen alla tecken jag har att skriva. 972 01:22:21,280 --> 01:22:24,760 Detta stänger kanoniska läge. 973 01:22:24,760 --> 01:22:31,320 Här grejer betyder bara när det faktiskt bearbetar tecken. 974 01:22:31,320 --> 01:22:35,830 Detta innebär bearbeta dem omedelbart, så snart jag skriver dem, bearbeta dem. 975 01:22:35,830 --> 01:22:42,510 Och detta är den funktion som uppdaterar mina inställningar för standard i, 976 01:22:42,510 --> 01:22:45,480 och TCSA medel göra det just nu. 977 01:22:45,480 --> 01:22:50,310 De andra alternativen är vänta tills allt som är närvarande på strömmen behandlas. 978 01:22:50,310 --> 01:22:52,030 Det spelar ingen roll egentligen. 979 01:22:52,030 --> 01:22:56,920 Just nu ändra mina inställningar för att vara vad är för närvarande i hacker_typer_settings. 980 01:22:56,920 --> 01:23:02,210 Jag antar att jag kallade det hacker_settings, så låt oss ändra på det. 981 01:23:09,610 --> 01:23:13,500 Ändra allt till hacker_settings. 982 01:23:13,500 --> 01:23:16,870 >> Nu i slutet av vårt program vi kommer att vilja återgå 983 01:23:16,870 --> 01:23:20,210 till vad som för närvarande inne i normal_settings, 984 01:23:20,210 --> 01:23:26,560 som kommer att bara se ut och normal_settings. 985 01:23:26,560 --> 01:23:30,650 Märker jag har inte ändrat någon av mina normal_settings sedan början få det. 986 01:23:30,650 --> 01:23:34,520 Sen att bara ändra dem tillbaka, passerar jag dem tillbaka i slutet. 987 01:23:34,520 --> 01:23:38,390 Detta var uppdateringen. Okej. 988 01:23:38,390 --> 01:23:43,900 >> Nu inne i här jag ska bara förklara koden av intresse för tiden. 989 01:23:43,900 --> 01:23:46,350 Det är inte så mycket kod. 990 01:23:50,770 --> 01:24:03,750 Vi ser att vi läser ett tecken från filen. Vi kallade det f.. 991 01:24:03,750 --> 01:24:07,850 Nu kan du människan fgetc, men hur fgetc kommer att fungera 992 01:24:07,850 --> 01:24:11,910 är bara det kommer att returnera det tecken som du just läst eller EOF, 993 01:24:11,910 --> 01:24:15,680 vilket motsvarar slutet av filen eller några fel händer. 994 01:24:15,680 --> 01:24:19,900 Vi looping, fortsätter att läsa ett tecken från filen, 995 01:24:19,900 --> 01:24:22,420 tills vi har slut på tecken att läsa. 996 01:24:22,420 --> 01:24:26,650 Och medan vi gör det, väntar vi på en enda karaktär från standard i. 997 01:24:26,650 --> 01:24:29,090 Varje gång du skriver något på kommandoraden, 998 01:24:29,090 --> 01:24:32,820 som är läsning i en karaktär från standard i. 999 01:24:32,820 --> 01:24:38,330 Sedan putchar är bara att sätta röding vi läser upp här från filen till standard ut. 1000 01:24:38,330 --> 01:24:42,890 Du kan människan putchar, men det är bara att sätta standard ut, det du skriver tecken. 1001 01:24:42,890 --> 01:24:51,600 Du kan också bara göra printf ("% c", c), samma idé. 1002 01:24:53,330 --> 01:24:56,670 Det kommer att göra det mesta av vårt arbete. 1003 01:24:56,670 --> 01:25:00,300 >> Det sista vi kommer att vilja göra är fclose vår fil. 1004 01:25:00,300 --> 01:25:03,310 Om du inte fclose, det är en minnesläcka. 1005 01:25:03,310 --> 01:25:06,680 Vi vill fclose filen vi ursprungligen öppnade, och jag tror det är det. 1006 01:25:06,680 --> 01:25:13,810 Om vi ​​gör det, fick jag redan problem. 1007 01:25:13,810 --> 01:25:17,260 Låt oss se. 1008 01:25:17,260 --> 01:25:19,960 Vad gjorde det klaga? 1009 01:25:19,960 --> 01:25:30,220 Förväntad "int" men argumentet är av typen "struct _IO_FILE * '. 1010 01:25:36,850 --> 01:25:39,370 Vi får se om det fungerar. 1011 01:25:45,210 --> 01:25:53,540 Tillåts endast i C99. Augh. Okej, gör hacker_typer. 1012 01:25:53,540 --> 01:25:57,760 Nu får vi mer användbara beskrivningar. 1013 01:25:57,760 --> 01:25:59,900 Så använd odeklarerat identifierare "normal_settings". 1014 01:25:59,900 --> 01:26:04,170 Jag har inte kalla det normal_settings. Jag kallade det current_settings. 1015 01:26:04,170 --> 01:26:12,090 Så låt oss ändra på detta. 1016 01:26:17,920 --> 01:26:21,710 Nu passerar argument. 1017 01:26:26,290 --> 01:26:29,500 Jag ska göra det här 0 för nu. 1018 01:26:29,500 --> 01:26:36,720 Okej. . / Hacker_typer cp.c. 1019 01:26:36,720 --> 01:26:39,590 Jag också inte rensa skärmen från början. 1020 01:26:39,590 --> 01:26:42,960 Men du kan se tillbaka på det sista problemet inställda för att se hur du rensar skärmen. 1021 01:26:42,960 --> 01:26:45,160 Det är bara skriva några tecken 1022 01:26:45,160 --> 01:26:47,210 medan detta gör vad jag vill göra. 1023 01:26:47,210 --> 01:26:48,900 Okej. 1024 01:26:48,900 --> 01:26:55,280 Och tänka på varför detta behövs för att 0 istället för standard in, 1025 01:26:55,280 --> 01:27:00,560 som bör # define 0, 1026 01:27:00,560 --> 01:27:03,890 detta klagar på att - 1027 01:27:13,150 --> 01:27:19,360 Innan när jag sa att det finns fil deskriptorer men då har du också din fil *, 1028 01:27:19,360 --> 01:27:23,210 en fil deskriptor är bara en enda heltal, 1029 01:27:23,210 --> 01:27:26,970 medan en fil * har en hel massa saker i samband med detta. 1030 01:27:26,970 --> 01:27:30,380 Anledningen till att vi måste säga 0 istället för stdin 1031 01:27:30,380 --> 01:27:37,480 är att stdin är en fil * som pekar på det som är refererar filidentifierare 0. 1032 01:27:37,480 --> 01:27:45,070 Så även här uppe när jag gör fopen (argv [1], jag får en fil * tillbaka. 1033 01:27:45,070 --> 01:27:51,180 Men någonstans i filen * är en sak motsvarar filidentifieraren för filen. 1034 01:27:51,180 --> 01:27:57,430 Om man tittar på man-sidan för öppen, så jag tror du måste göra människan 3 öppen - nix - 1035 01:27:57,430 --> 01:27:59,380 Man 2 öppna - ja. 1036 01:27:59,380 --> 01:28:06,250 Om du tittar på sidan för öppen är öppen som en lägre nivå fopen, 1037 01:28:06,250 --> 01:28:09,350 och det är tillbaka själva filidentifierare. 1038 01:28:09,350 --> 01:28:12,050 fopen gör en massa saker ovanpå öppen, 1039 01:28:12,050 --> 01:28:17,640 som i stället för att återvända bara den filen deskriptor returnerar en hel fil * pekare 1040 01:28:17,640 --> 01:28:20,590 inuti som är vår lilla filidentifierare. 1041 01:28:20,590 --> 01:28:25,020 Så standard avser FIL * sak, 1042 01:28:25,020 --> 01:28:29,120 medan 0 avser bara filidentifieraren standarden i sig. 1043 01:28:29,120 --> 01:28:32,160 >> Frågor? 1044 01:28:32,160 --> 01:28:35,930 [Skrattar] blåste genom det. 1045 01:28:35,930 --> 01:28:39,140 Okej. Vi är klara. [Skrattar] 1046 01:28:39,140 --> 01:28:42,000 >> [CS50.TV]