1 00:00:00,000 --> 00:00:02,500 [Powered by Google Translate] [Раздел 5 - по-комфортно] 2 00:00:02,500 --> 00:00:04,690 [Роб Боудън - Харвардския университет] 3 00:00:04,690 --> 00:00:07,250 [Това е CS50. - CS50.TV] 4 00:00:08,990 --> 00:00:14,250 >> Както казах в моя имейл, че има много неща, които можете да използвате 5 00:00:14,250 --> 00:00:17,060 различна от уреда, за да се прави на проблемните комплекти. 6 00:00:17,060 --> 00:00:19,910 Препоръчваме ви да го направите в уреда само защото тогава ние можем да ви помогне по-лесно 7 00:00:19,910 --> 00:00:22,070 и ние знаем как всичко ще работи. 8 00:00:22,070 --> 00:00:26,950 Но както един пример от където можете да направите неща, ако, да речем, не да имат достъп 9 00:00:26,950 --> 00:00:31,570 на уреда или искате да работите в мазето Science Center - 10 00:00:31,570 --> 00:00:33,090 което всъщност те имат уреда - 11 00:00:33,090 --> 00:00:35,150 ако искате да работите навсякъде. 12 00:00:35,150 --> 00:00:42,370 Един такъв пример е виждали ли сте / чували за SSH? 13 00:00:44,380 --> 00:00:47,780 SSH е просто като се свърже с нещо. 14 00:00:47,780 --> 00:00:51,340 Всъщност, точно сега съм SSHed в уреда. 15 00:00:51,340 --> 00:00:54,290 Аз никога не работят директно в уреда. 16 00:00:55,930 --> 00:01:01,060 Тук е уред, и ако погледнете тук виждате този IP адрес. 17 00:01:01,060 --> 00:01:03,650 Аз никога не работят в самия уред; 18 00:01:03,650 --> 00:01:08,840 Аз винаги идват на iTerm2 прозорец / терминален прозорец. 19 00:01:08,840 --> 00:01:15,910 Можете SSH, че IP адрес, SSH jharvard@192.168.129.128. 20 00:01:15,910 --> 00:01:20,390 Спомням си, че номер много лесно, защото това е толкова хубав модел. 21 00:01:20,390 --> 00:01:24,920 Но това ще ме питате за моята парола, а сега съм в уреда. 22 00:01:24,920 --> 00:01:33,060 По принцип, в този момент, ако сте отворили терминал вътре в самия уред, 23 00:01:33,060 --> 00:01:36,350 този интерфейс, но можете да го използвате, е точно същото 24 00:01:36,350 --> 00:01:40,010 като интерфейс съм тук, но сега сте SSHed. 25 00:01:42,240 --> 00:01:44,920 Вие не трябва да SSH на уреда. 26 00:01:44,920 --> 00:01:52,360 Един пример на друго място, където бихте могли да SSH е, че съм сигурен, че имате по подразбиране - 27 00:01:52,360 --> 00:01:55,020 О. По-голяма. 28 00:01:55,020 --> 00:02:01,130 Всеки от вас трябва да са по подразбиране FAS на сървърите на FAS. 29 00:02:01,130 --> 00:02:06,840 За мен, аз ще SSH на rbowden@nice.fas.harvard.edu. 30 00:02:06,840 --> 00:02:11,610 Това ще да ви попитам, че за първи път, а вие казвате "да". 31 00:02:11,610 --> 00:02:15,840 Моята парола е просто ще бъде паролата си FAS. 32 00:02:15,840 --> 00:02:22,650 И така, сега, аз съм SSHed хубави сървъри, и мога да правя каквото си искам тук. 33 00:02:22,650 --> 00:02:28,560 Много от класове, може да предприемете, като 124, ще трябва да качите неща тук 34 00:02:28,560 --> 00:02:30,950 действително да представят проблемните комплекти. 35 00:02:30,950 --> 00:02:34,100 Но казват, че не разполагат с достъп до вашия уред. 36 00:02:34,100 --> 00:02:37,910 След това можете да правите неща, като тук ще кажа - 37 00:02:37,910 --> 00:02:42,160 Това е само нашата секция от въпроси. 38 00:02:42,160 --> 00:02:45,070 Тя ще ви помоля да направите това в уреда. 39 00:02:45,070 --> 00:02:47,790 Вместо това просто ще го направя на сървъра. 40 00:02:47,790 --> 00:02:50,560 Отивам да разархивирате. 41 00:02:50,560 --> 00:02:55,670 Проблемът ще бъде, че сте свикнали да използвате нещо като Gedit 42 00:02:55,670 --> 00:02:58,160 или каквото и вътрешността на уреда. 43 00:02:58,160 --> 00:03:01,830 Нали няма да има, че на FAS сървър. 44 00:03:01,830 --> 00:03:04,110 Всичко това е просто ще бъде този текстова интерфейс. 45 00:03:04,110 --> 00:03:09,180 Така бихте могли да, опитайте се да научите текстов редактор, който те имат. 46 00:03:09,180 --> 00:03:12,130 Те имат Nano. 47 00:03:12,130 --> 00:03:14,990 Нано обикновено е доста лесен за използване. 48 00:03:14,990 --> 00:03:19,470 Можете да използвате стрелките и въведете нормално. 49 00:03:19,470 --> 00:03:21,250 Така че не е трудно. 50 00:03:21,250 --> 00:03:24,720 Ако искате да получите наистина фантазия можете да използвате Emacs, 51 00:03:24,720 --> 00:03:29,850 което аз вероятно не трябва да се отвори, защото аз дори не знам как да затворите Emacs. 52 00:03:29,850 --> 00:03:32,760 Control X, Control C? Да. 53 00:03:32,760 --> 00:03:35,310 Или можете да използвате Vim, който е това, което аз използвам. 54 00:03:35,310 --> 00:03:37,800 И така, това са вашите възможности. 55 00:03:37,800 --> 00:03:43,830 Ако не искате да направите това, можете също така, ако се вгледате в manual.cs50.net - 56 00:03:43,830 --> 00:03:45,410 О. 57 00:03:45,410 --> 00:03:49,920 На компютър, можете да SSH с PuTTY, 58 00:03:49,920 --> 00:03:51,940 които вие ще трябва да изтеглите отделно. 59 00:03:51,940 --> 00:03:55,460 На Mac, може просто от Терминал употреба или по подразбиране можете да изтеглите iTerm2, 60 00:03:55,460 --> 00:03:58,490 което е като хубава, специален терминал. 61 00:03:58,490 --> 00:04:03,780 Ако отидете в manual.cs50.net ще видите линк към Notepad + +, 62 00:04:03,780 --> 00:04:07,120 което е това, което можете да използвате на компютъра. 63 00:04:07,120 --> 00:04:13,340 Тя ви позволява да SFTP от Notepad + +, която е в основата SSH. 64 00:04:13,340 --> 00:04:17,750 Това ще ви позволи да направите, е да редактирате вашите файлове локално, 65 00:04:17,750 --> 00:04:20,670 и след това всеки път, когато искате да ги спаси, ще спаси на nice.fas, 66 00:04:20,670 --> 00:04:23,670 , където ще можете да ги изпълните. 67 00:04:23,670 --> 00:04:26,880 И еквивалент на Mac ще да TextWrangler. 68 00:04:26,880 --> 00:04:28,760 Така че ви позволява да правите едно и също нещо. 69 00:04:28,760 --> 00:04:32,800 Тя ви позволява да редактирате файлове на местно ниво и да ги запишете на nice.fas, 70 00:04:32,800 --> 00:04:35,730 , където ще можете да ги изпълните. 71 00:04:35,730 --> 00:04:40,400 Така че, ако някога сте остана без един уред, имате тези опции 72 00:04:40,400 --> 00:04:44,230 все още го правя проблемните комплекти. 73 00:04:44,230 --> 00:04:48,250 Един проблем ще бъде, че няма да има CS50 библиотека 74 00:04:48,250 --> 00:04:51,580 защото nice.fas не по подразбиране това. 75 00:04:51,580 --> 00:04:55,970 Можете да изтеглите CS50 библиотека - 76 00:04:55,970 --> 00:04:58,470 Не мисля, че имам нужда, че в този момент. 77 00:04:58,470 --> 00:05:03,270 Можете да изтеглите CS50 библиотека и го копирайте в nice.fas 78 00:05:03,270 --> 00:05:07,450 или аз мисля, че в този момент ние не го използвате повече така или иначе. 79 00:05:07,450 --> 00:05:12,720 Или, ако го направим, можете да за момента да го замени с 80 00:05:12,720 --> 00:05:18,480 реализации на функциите в библиотеката CS50 така или иначе. 81 00:05:18,480 --> 00:05:21,370 Така че не трябва да бъде, че голяма част ограничение. 82 00:05:21,370 --> 00:05:23,710 И това е всичко. 83 00:05:26,460 --> 00:05:29,820 >> Аз ще се върна на уреда, ние ще направим всичко, което е по уреда. 84 00:05:29,820 --> 00:05:37,510 Поглед към нашата секция от въпроси, в началото, както казах в моя имейл, 85 00:05:37,510 --> 00:05:43,620 ние трябва да говорим за един кратък, който трябваше да се гледа. 86 00:05:43,620 --> 00:05:51,980 Ние имаме пренасочване на тръби и тези три въпроса. 87 00:05:51,980 --> 00:05:56,070 >> На което поток функции като ФОРМАТ напиши по подразбиране? 88 00:05:56,070 --> 00:05:59,130 Така поток. Какво е поток? 89 00:06:06,520 --> 00:06:15,100 Поток е в общи линии, като това е само част - 90 00:06:15,100 --> 00:06:21,450 Тя дори не е източник на 1s и 0s. 91 00:06:21,450 --> 00:06:24,920 Потокът, че искам тук е стандартна. 92 00:06:24,920 --> 00:06:27,250 И така стандарт навън е поток, който, когато ви пиша до него, 93 00:06:27,250 --> 00:06:30,940 се появява на екрана. 94 00:06:30,940 --> 00:06:36,860 Стандартен изход, като поток, това означава, че просто напишете 1s и 0s да го 95 00:06:36,860 --> 00:06:40,220 и на другия край на стандартния изход просто чете от този поток. 96 00:06:40,220 --> 00:06:43,540 Това е просто низ от 1s и 0s. 97 00:06:43,540 --> 00:06:45,570 Можете да пишете на потоци или можете да прочетете от потоци 98 00:06:45,570 --> 00:06:47,950 в зависимост от това какво всъщност е потока. 99 00:06:47,950 --> 00:06:52,800 Другите две по подразбиране потоци са стандартни и стандартната грешка. 100 00:06:52,800 --> 00:06:57,540 Standard е, когато се GetString, ви чака да въведете неща. 101 00:06:57,540 --> 00:07:01,570 Така че ви очаква, всъщност чака на стандарт в 102 00:07:01,570 --> 00:07:04,880 , което е наистина това, което ще получите, когато пишете на клавиатурата. 103 00:07:04,880 --> 00:07:07,530 Вие пишете в стандарт инча 104 00:07:07,530 --> 00:07:10,050 Стандартна грешка по същество е еквивалент на стандартния изход, 105 00:07:10,050 --> 00:07:13,280 но тя е специализирана в тази при печат на стандартна грешка, 106 00:07:13,280 --> 00:07:16,770 което се очаква да отпечатвате само съобщения за грешки на това 107 00:07:16,770 --> 00:07:20,200 така че може да прави разлика между редовните съобщения, отпечатани на екрана 108 00:07:20,200 --> 00:07:24,560 срещу съобщения за грешки, в зависимост от това дали те отидоха в стандарт или за стандартната грешка. 109 00:07:24,560 --> 00:07:28,660 Файлове. 110 00:07:28,660 --> 00:07:32,440 Стандарт, като стандарт, и стандартната грешка са само специални потоци, 111 00:07:32,440 --> 00:07:36,810 но наистина всеки файл, когато отворите файл, тя се превръща в поток от байтове 112 00:07:36,810 --> 00:07:40,740 където можете просто да прочетете от този поток. 113 00:07:40,740 --> 00:07:47,770 Вие, в по-голямата си част, може просто да мисля, че на файл като поток от байтове. 114 00:07:47,770 --> 00:07:51,190 Така че това, което потоци да те пишат по подразбиране? Стандартна навън. 115 00:07:51,190 --> 00:07:56,980 >> Каква е разликата между> и >>? 116 00:07:58,140 --> 00:08:03,710 Ли гледате видео преди това? Добре. 117 00:08:03,710 --> 00:08:10,960 > Ще бъде как да пренасочат в файлове, 118 00:08:10,960 --> 00:08:15,240 и >> също ще пренасочване на изхода във файл, 119 00:08:15,240 --> 00:08:17,820 но това е, вместо да приложи към файла. 120 00:08:17,820 --> 00:08:23,430 Например, нека кажем, че се случи да има волята си тук, 121 00:08:23,430 --> 00:08:27,020 и само неща вътрешността на волята си е котка, котка, куче, риба, куче. 122 00:08:27,020 --> 00:08:31,530 Едно, че имате команда в командния ред е котка, 123 00:08:31,530 --> 00:08:34,539 която е просто да отпечатате това, което е във файл. 124 00:08:34,539 --> 00:08:40,679 Така че, когато казвам волята си котка, тя ще да отпечатате котка, котка, куче, риба, куче. Това е, всички котка. 125 00:08:40,679 --> 00:08:46,280 Това означава, че отпечатва стандарт, котка, котка, куче, риба, куче. 126 00:08:46,280 --> 00:08:53,240 Ако аз вместо искате да пренасочите, че във файл, да използвате> и го пренасочи към каквото и да е файл. 127 00:08:53,240 --> 00:08:56,460 Ще се обадя на файла. 128 00:08:56,460 --> 00:09:00,320 Така че сега, ако ли, ще видиш, че има нов файл, наречен файл. 129 00:09:00,320 --> 00:09:05,700 И ако го отворя, ще има точно това, което и котки, пригодени в командния ред. 130 00:09:05,700 --> 00:09:11,040 Така че сега, ако аз го направя отново, то тогава ще да пренасочи изхода в досието, 131 00:09:11,040 --> 00:09:13,930 Отивам да имат една и съща точно това. 132 00:09:13,930 --> 00:09:17,910 Така че технически, то напълно се припокрива, което имахме. 133 00:09:17,910 --> 00:09:22,970 И ние ще видя дали мога да променя волята си, взех куче. 134 00:09:22,970 --> 00:09:29,980 Сега, ако ние котка Dict отново в досието, ще има нова версия с куче отстранени. 135 00:09:29,980 --> 00:09:32,400 Така че напълно го отменя. 136 00:09:32,400 --> 00:09:36,640 Вместо това, ако ние използваме >>, е да добавите файл. 137 00:09:36,640 --> 00:09:40,860 Сега, отваряне на файл, ние имаме само отпечатва два пъти едно и също нещо 138 00:09:40,860 --> 00:09:44,920 защото тя беше там веднъж, после ние добавят към оригиналната. 139 00:09:44,920 --> 00:09:48,130 Така че това> и >>. 140 00:09:48,130 --> 00:09:50,580 Ли следващата попитам - Той не пита за това. 141 00:09:50,580 --> 00:09:59,050 >> Другото, което имаме е <, която, ако пренасочва стандарт, 142 00:09:59,050 --> 00:10:01,970 <Ще се пренасочи стандартния. 143 00:10:01,970 --> 00:10:12,050 Нека видим дали имаме пример. 144 00:10:14,750 --> 00:10:16,930 Мога да напиша една истинска бързо. 145 00:10:17,870 --> 00:10:25,700 Нека да вземем всеки файл, hello.c. 146 00:10:56,060 --> 00:10:59,070 Относително проста файл. 147 00:10:59,070 --> 00:11:03,570 Аз съм просто низ и след това печат "Hello" независимо от низ, аз току-що влезе. 148 00:11:03,570 --> 00:11:07,990 Така че направи здрасти и след това. / Здрасти. 149 00:11:07,990 --> 00:11:10,720 Сега той ме подкани да въведете нещо, 150 00:11:10,720 --> 00:11:15,070 което означава, че те чака на неща, които трябва да се вписват в стандартната инча 151 00:11:15,070 --> 00:11:20,450 Така че въведете каквото си искам в стандарт инча Ние просто ще да кажа здрасти, Роб! 152 00:11:20,450 --> 00:11:23,310 След това печат за стандарта Здравейте, Роб! 153 00:11:23,310 --> 00:11:28,860 Ако го направя. / Здрасти и след това пренасочване, 154 00:11:30,740 --> 00:11:34,310 за сега можете да пренасочват само от файл. 155 00:11:34,310 --> 00:11:41,720 Така че, ако в някой файл, TXT, и аз си Роб, 156 00:11:41,720 --> 00:11:52,300 ако аз тичам здрасти и след това пренасочване на текстовия файл в / Здравейте, това е ще да кажа здрасти, Роб! веднага. 157 00:11:52,300 --> 00:11:57,160 Когато за първи път получава GetString и чака стандарт в 158 00:11:57,160 --> 00:12:01,730 стандарт е вече не чака на клавиатурата за да се вписани данни. 159 00:12:01,730 --> 00:12:05,980 Вместо това, ние сме пренасочени стандарт, за да се четат от текстовия файл. 160 00:12:05,980 --> 00:12:10,290 И така ще четат от текстовия файл, който е само линията Роб, 161 00:12:10,290 --> 00:12:13,380 и след това да отпечатате Здравейте, Роб! 162 00:12:13,380 --> 00:12:18,180 И ако исках, аз също може да свърши работа. / Здравей 00:12:21,500 и след това стандарта, че това е печат, което е Здравейте, Роб! 164 00:12:21,500 --> 00:12:24,700 Да пренасочите, че в своя файл. 165 00:12:24,700 --> 00:12:29,790 Просто ще се обадя файла здравей - не, аз не ще, защото това е изпълнимо - txt2. 166 00:12:29,790 --> 00:12:40,150 Сега, txt2 ще има на изхода на / здравей <списък, който ще бъде Здравейте, Роб! 167 00:12:41,370 --> 00:12:43,520 >> Въпроси? 168 00:12:45,900 --> 00:12:49,090 >> Добре. Значи тук имаме газопровод. 169 00:12:49,090 --> 00:12:53,510 Тръбите са последната единица на пренасочване. 170 00:12:53,510 --> 00:12:58,750 >> О. Предполагам, че още една единица от пренасочване е, ако вместо> правиш 2> 171 00:12:58,750 --> 00:13:01,070 пренасочване на стандартната грешка. 172 00:13:01,070 --> 00:13:06,280 Така че, ако нещо се стандартната грешка, тя не би се сложи в txt2. 173 00:13:06,280 --> 00:13:12,480 Но ако го направя 2>, то тогава все още отпечатване Здравейте, Роб! командния ред 174 00:13:12,480 --> 00:13:18,600 защото аз съм само пренасочване на стандартната грешка, аз не съм пренасочване стандарт. 175 00:13:18,600 --> 00:13:22,210 Стандартна грешка и извън стандарта са различни. 176 00:13:24,210 --> 00:13:27,080 Ако искате да пишете на стандартната грешка, 177 00:13:27,080 --> 00:13:35,080 след това може да се промени това, за да бъде fprintf да STDERR. 178 00:13:35,080 --> 00:13:37,850 Така че, по подразбиране, ФОРМАТ отпечатва на стандартния изход. 179 00:13:37,850 --> 00:13:41,720 Ако искам да печатате ръчно стандартна грешка, тогава трябва да използвате fprintf 180 00:13:41,720 --> 00:13:45,010 и да определи това, което искате да печатате. 181 00:13:45,010 --> 00:13:49,720 Ако вместо това е fprintf стандартния изход, това е в общи линии еквивалентни на ФОРМАТ. 182 00:13:49,720 --> 00:13:55,530 Но fprintf стандартна грешка. 183 00:13:57,790 --> 00:14:03,650 Така че сега, ако пренасочи в txt2 Здравейте, Роб! все още се отпечатва в командния ред 184 00:14:03,650 --> 00:14:08,270 , тъй като тя ще се отпечатват на стандартна грешка и аз съм само пренасочване стандарт. 185 00:14:08,270 --> 00:14:16,420 Ако сега пренасочване на стандартната грешка, сега не се отпечатва и txt2 ще бъде Здравейте, Роб! 186 00:14:16,420 --> 00:14:21,910 Така че сега, можете да отпечатате вашите действителни грешки стандартната грешка 187 00:14:21,910 --> 00:14:24,720 и да отпечатате вашите редовни съобщения на стандартния изход. 188 00:14:24,720 --> 00:14:31,420 И така, когато изпълнявате вашата програма, можете да го стартирате като / Здравей, този тип с 2> 189 00:14:31,420 --> 00:14:33,800 така, че вашата програма ще протичат нормално, 190 00:14:33,800 --> 00:14:38,400 но всички съобщения за грешки, които ви да проверите по-късно в грешка дневник 191 00:14:38,400 --> 00:14:44,500 толкова грешки, и след това погледнете по-късно и грешки файл ще има каквито и да било грешки, които са се случили. 192 00:14:45,200 --> 00:14:47,540 >> Въпроси? 193 00:14:47,540 --> 00:14:58,070 >> Последното от тях е тръба, която можеш да се сетиш, като стандарт от една команда 194 00:14:58,070 --> 00:15:01,210 и стандарта на следващата команда. 195 00:15:01,210 --> 00:15:05,570 Един пример тук е ехо е нещо командния ред 196 00:15:05,570 --> 00:15:11,840 че е просто ще ехо, каквото и да постави като аргумент. Аз няма да сложи кавички. 197 00:15:11,840 --> 00:15:16,150 Echo дрън, дрън, дрън е просто да отпечатате дрън, дрън, дрън. 198 00:15:16,150 --> 00:15:20,600 Преди, когато казах, че трябваше да се примири Роб в текстовия файл 199 00:15:20,600 --> 00:15:28,830 защото мога да пренасочват само текстови файлове, вместо това / ако Повтарям Роб 200 00:15:28,830 --> 00:15:35,520 и след това тръба в него. / здравей, това ще направи същото вид на нещо. 201 00:15:35,520 --> 00:15:39,160 Това е изхода от тази команда, ехо Роб, 202 00:15:39,160 --> 00:15:43,610 и да го използвате като вход за / здрасти. 203 00:15:44,790 --> 00:15:49,560 Можете да мислите за него като за първото пренасочване ехо Роб във файл 204 00:15:49,560 --> 00:15:54,160 и след въвеждане в / Здравей, този файл, който бе изведен. 205 00:15:54,160 --> 00:15:57,850 Но това отнема временен файл на картината. 206 00:16:01,890 --> 00:16:04,460 >> Въпроси за това? 207 00:16:04,460 --> 00:16:07,150 >> Следващият въпрос е ще включва това. 208 00:16:07,150 --> 00:16:15,310 Какво тръбопровода може да използвате, за да намерите броя на уникални имена във файл, наречен names.txt? 209 00:16:15,310 --> 00:16:24,160 Командите, които ще искате да използвате тук са уникални, така че Uniq, а след това и тоалетна. 210 00:16:24,160 --> 00:16:28,840 Можете да направите Uniq човек да погледнете какво прави, 211 00:16:28,840 --> 00:16:34,840 и това е просто ще филтрира съседни съвпадение на линии от входа. 212 00:16:34,840 --> 00:16:40,690 И човекът тоалетна ще да отпечатате нов ред, дума и броя байтове за всеки файл. 213 00:16:40,690 --> 00:16:43,760 И последно, че ще искате да използвате, е нещо, 214 00:16:43,760 --> 00:16:47,410 , което се случва просто да сортирате линии на текстовия файл. 215 00:16:47,410 --> 00:16:58,080 Ако направя някой файл TXT, names.txt, и това е Роб, Томи, Йосиф, Томи, Йосиф, RJ, Роб, 216 00:16:58,080 --> 00:17:03,910 това, което искам да направя тук, е да се намери броят на уникални имена в този файл. 217 00:17:03,910 --> 00:17:08,750 И така, какво трябва да бъде отговорът? >> [Ученик] 4. >> Да. 218 00:17:08,750 --> 00:17:13,780 Тя трябва да бъде 4, тъй като Роб, Томи, Йосиф, RJ са само уникални имена в този файл. 219 00:17:13,780 --> 00:17:20,180 Първата стъпка, ако аз просто правя брой думи на names.txt, 220 00:17:20,180 --> 00:17:24,290 това всъщност ми казва всичко. 221 00:17:24,290 --> 00:17:32,560 Това всъщност е печат - нека да видим, човек WC - нови редове, думи и брой байтове. 222 00:17:32,560 --> 00:17:38,270 Ако само се грижи за линии, тогава може просто да направи тоалетна-л names.txt. 223 00:17:41,730 --> 00:17:44,300 Така че това е стъпка 1. 224 00:17:44,300 --> 00:17:50,510 Но аз не искам да names.txt WC-л, защото names.txt съдържа само имената на всички, 225 00:17:50,510 --> 00:17:54,170 и аз искам да филтрирате, които не са уникални. 226 00:17:54,170 --> 00:18:01,200 Така че, ако правя Uniq names.txt, че не ме даде това, което искам 227 00:18:01,200 --> 00:18:03,760 защото дублирани имена са все още там. 228 00:18:03,760 --> 00:18:07,690 Защо е така? Защо не е Uniq прави това, което искам? 229 00:18:07,690 --> 00:18:10,500 [Ученик] дубликати не се чува] >> Да. 230 00:18:10,500 --> 00:18:16,370 Запомни страницата човек за Uniq казва филтър съседни линии съвпадение. 231 00:18:16,370 --> 00:18:19,680 Те не са в непосредствена близост, така че няма да ги филтрирате. 232 00:18:19,680 --> 00:18:31,100 Ако аз сортирате тях на първо място, нещо names.txt ще постави всички дублиращи се линии заедно. 233 00:18:31,100 --> 00:18:34,450 Така че сега вид names.txt е това. 234 00:18:34,450 --> 00:18:40,550 Отивам да искате да използвате това като принос към Uniq, което е | Uniq. 235 00:18:40,550 --> 00:18:43,390 Това дава ми Йосиф, RJ, Роб, Томи, 236 00:18:43,390 --> 00:18:49,260 и аз искам да се използват като вход-л тоалетна, 237 00:18:49,260 --> 00:18:52,740 който ще ми даде 4. 238 00:18:52,740 --> 00:18:56,930 Както се казва тук, какво тръбопровода може да използвате? 239 00:18:56,930 --> 00:19:01,390 Можете да направите много неща, като с помощта на поредица от команди 240 00:19:01,390 --> 00:19:05,130 , когато използвате изхода от една команда като вход към следващата команда. 241 00:19:05,130 --> 00:19:08,780 Можете да направите много неща, много умни неща. 242 00:19:08,780 --> 00:19:11,440 >> Въпроси? 243 00:19:12,910 --> 00:19:14,600 Добре. 244 00:19:14,600 --> 00:19:17,880 Това е за тръби и пренасочване. 245 00:19:18,370 --> 00:19:24,090 >> Сега отиваме на действителната неща, кодиране неща. 246 00:19:24,090 --> 00:19:29,100 Вътре в този PDF, ще видите тази команда, 247 00:19:29,100 --> 00:19:32,950 и вие ще искате да стартирате тази команда във вашия уред. 248 00:19:36,240 --> 00:19:42,250 Wget е командата за получаване на нещо от интернет, общо взето, 249 00:19:42,250 --> 00:19:45,180 Wget и този URL. 250 00:19:45,180 --> 00:19:49,110 Ако отидеш на този URL адрес в браузъра ви, че ще свалите този файл. 251 00:19:49,110 --> 00:19:52,510 Аз просто кликне върху него, така че го изтеглили файла за мен. 252 00:19:52,510 --> 00:19:55,650 Но писмено Wget на това нещо вътре в терминала 253 00:19:55,650 --> 00:19:58,620 е просто да го изтеглите във вашия терминал. 254 00:19:58,620 --> 00:20:02,750 Имам section5.zip, и вие ще искате да разархивирате section5.zip 255 00:20:02,750 --> 00:20:06,520 , която ще ви даде една папка, наречена раздел 5, 256 00:20:06,520 --> 00:20:11,550 който ще има всички файлове, ние ще трябва да се използват днес в нея. 257 00:20:33,380 --> 00:20:37,710 Файлови имена на тези програми показват, те са малко бъги, 258 00:20:37,710 --> 00:20:40,990 така че вашата мисия е да разбера защо използването на GDB. 259 00:20:40,990 --> 00:20:44,560 Всички ли са ги изтеглили / знаят как да ги свален 260 00:20:44,560 --> 00:20:47,480 в уреда си? Добре. 261 00:20:47,480 --> 00:20:56,400 >> Работещи ./buggy1, той ще каже Сегментация грешка (ядро дъмпингови), 262 00:20:56,400 --> 00:21:00,500 които всеки път, когато получите segfault, това е нещо лошо. 263 00:21:00,500 --> 00:21:03,810 При какви обстоятелства да получите segfault? 264 00:21:03,810 --> 00:21:08,210 [Ученик] Dereferencing с нулев указател. >> Да. Така че това е един пример. 265 00:21:08,210 --> 00:21:11,580 , Dereferencing нулев указател, ти започваш да се получи segfault. 266 00:21:11,580 --> 00:21:16,720 Какво segfault средства е, че докосвате памет не трябва да се докосват. 267 00:21:16,720 --> 00:21:21,350 Така dereferencing нулев указател докосва адрес 0, 268 00:21:21,350 --> 00:21:28,060 и в общи линии, всички компютри в днешно време казват, че адрес 0 памет не трябва да се докосват. 269 00:21:28,060 --> 00:21:31,920 Така че това е защо dereferencing нулеви резултати показалеца в segfault. 270 00:21:31,920 --> 00:21:37,210 Когато се случи да не се инициализира указател, то тя има стойността на боклук, 271 00:21:37,210 --> 00:21:41,520 и така, когато се опитате да сочен, по всяка вероятност сте докосва памет 272 00:21:41,520 --> 00:21:43,540 , която е в средата на нищото. 273 00:21:43,540 --> 00:21:45,650 Ако се случи да получите късмет и стойността на боклука 274 00:21:45,650 --> 00:21:48,440 се случи да се отбележи някъде на стека или нещо такова, 275 00:21:48,440 --> 00:21:50,820 тогава, когато и сочен, че показалеца, които не са инициализирани 276 00:21:50,820 --> 00:21:52,730 нищо няма да се обърка. 277 00:21:52,730 --> 00:21:55,480 Но ако тя е насочена, да речем, някъде между стека и на куп, 278 00:21:55,480 --> 00:21:59,850 или е насочена само до някъде, че не е била използвана от вашата програма, все още, 279 00:21:59,850 --> 00:22:02,240 тогава сте докосва памет не трябва да се докосват и ви segfault. 280 00:22:02,240 --> 00:22:06,370 Когато се напише рекурсивна функция и тя recurses твърде много пъти 281 00:22:06,370 --> 00:22:08,720 и стака си расте твърде голям и стека се сблъсква в нещата 282 00:22:08,720 --> 00:22:12,270 , че не трябва да се сблъскат с това, което се докосва памет не трябва да се докосва, 283 00:22:12,270 --> 00:22:14,810 така че segfault. 284 00:22:14,810 --> 00:22:17,010 Ето какво segfault. 285 00:22:17,010 --> 00:22:21,810 >> Това е същата причина, че ако имате низ като 286 00:22:21,810 --> 00:22:23,930 нека се върнем към предишната програма. 287 00:22:23,930 --> 00:22:28,530 В hello.c-Аз съм просто ще направи нещо друго. 288 00:22:28,530 --> 00:22:33,770 Чар * = "Здравей, свят!"; 289 00:22:33,770 --> 00:22:42,310 Ако използвам * S = нещо или и [0] = 'X'; 290 00:22:42,310 --> 00:22:47,290 така че се здравей, / здравей, защо че segfault? 291 00:22:48,410 --> 00:22:51,250 Защо това segfault? 292 00:22:55,660 --> 00:22:57,890 Какво би очаквате да се случи? 293 00:22:57,890 --> 00:23:06,640 Ако го бях направил ФОРМАТ ("% S \",), какво бихте се очаква да бъдат отпечатани? 294 00:23:06,640 --> 00:23:09,930 [Ученик] X здрасти. >> Да. 295 00:23:09,930 --> 00:23:15,140 Проблемът е, че когато вие декларирате, низ като това, 296 00:23:15,140 --> 00:23:18,190 и е указател, че ще отиде в стека, 297 00:23:18,190 --> 00:23:25,880 и какво и е насочена към това е низ, който се съдържа в памет само за четене. 298 00:23:25,880 --> 00:23:30,560 Така че просто от името, памет само за четене, можете да получите представа 299 00:23:30,560 --> 00:23:33,010 че ако се опитате да промените това, което е в памет само за четене, 300 00:23:33,010 --> 00:23:36,670 правиш нещо, което не трябва да се прави с памет и ви segfault. 301 00:23:36,670 --> 00:23:45,360 Това всъщност е голяма разликата между Чар * и Чар []. 302 00:23:45,360 --> 00:23:48,790 Така Чар [], сега този низ ще бъде поставен върху стека, 303 00:23:48,790 --> 00:23:53,960 и стека не е само за четене, което означава, че това трябва да работи перфектно глоба. 304 00:23:55,500 --> 00:23:57,370 И го прави. 305 00:23:57,370 --> 00:24:06,250 Не забравяйте, че когато правя Чар * = "Здравей, свят!", А себе си е в стека 306 00:24:06,250 --> 00:24:10,390 но посочва някъде другаде, и че някъде другаде се случва да бъде само за четене. 307 00:24:10,390 --> 00:24:15,640 Но Чар [] е просто нещо, на стека. 308 00:24:17,560 --> 00:24:21,760 Така че това е още един пример на segfault случва. 309 00:24:21,760 --> 00:24:27,820 >> Видяхме че ./buggy1 в segfault. 310 00:24:27,820 --> 00:24:31,810 На теория не би трябвало да изглежда в buggy1.c веднага. 311 00:24:31,810 --> 00:24:35,170 Вместо това, ние ще разгледаме през GDB. 312 00:24:35,170 --> 00:24:37,750 Забележете, че когато се Сегментация грешка (ядро дъмпингови), 313 00:24:37,750 --> 00:24:40,850 можете да получите този файл тук, наречена ядро. 314 00:24:40,850 --> 00:24:45,200 Ако LS-л, ще видим, че основната обикновено е доста голям файл. 315 00:24:45,200 --> 00:24:51,580 Това е броят на байтовете на файла, така че да изглежда като това е 250-тина килобайта. 316 00:24:51,580 --> 00:24:56,120 Причината за това е, че това, което в основата сметището всъщност е 317 00:24:56,120 --> 00:25:01,410 е, когато си програма забива, състоянието на паметта на програмата си 318 00:25:01,410 --> 00:25:05,230 просто получава копират и поставят в този файл. 319 00:25:05,230 --> 00:25:07,270 То се изхвърлят в този файл. 320 00:25:07,270 --> 00:25:13,060 Тази програма, докато тя е била в ход, се случи да има използването на паметта от около 250 килобайта, 321 00:25:13,060 --> 00:25:17,040 и така, че това, което се изхвърлят в този файл. 322 00:25:17,040 --> 00:25:23,630 Сега можете да погледнете този файл, ако ние не направим GDB buggy1 ядро. 323 00:25:23,630 --> 00:25:30,130 Ние можем само да направим GDB buggy1, и че просто ще започнат GDB редовно, 324 00:25:30,130 --> 00:25:33,800 използване на buggy1 като входен файл. 325 00:25:33,800 --> 00:25:38,260 Но ако вие направите GDB buggy1 ядро, то тогава е специално ще се включи GDB 326 00:25:38,260 --> 00:25:40,330 като гледа, че основната файла. 327 00:25:40,330 --> 00:25:45,560 И искаш да кажеш buggy1 средства GDB знае, че, че основният файл идва от buggy1 програма. 328 00:25:45,560 --> 00:25:49,580 Така GDB buggy1 ядрото е незабавно ще ни донесе 329 00:25:49,580 --> 00:25:52,060 до мястото, където се случи да прекрати програмата. 330 00:25:57,720 --> 00:26:02,340 Тук виждаме програма прекратен със сигнал 11, сегментация вина. 331 00:26:02,340 --> 00:26:10,110 Се случи да видите една линия, на събранията, което вероятно не е много полезно. 332 00:26:10,110 --> 00:26:15,360 Но ако въведете BT или обратно проследяване, че ще бъде функцията 333 00:26:15,360 --> 00:26:19,430 , който ни дава списък на нашите настоящи рамки стека. 334 00:26:19,430 --> 00:26:23,150 Така че, обратно проследяване. Изглежда, че имаме само два стека рамки. 335 00:26:23,150 --> 00:26:26,310 Първата е нашата основна рамка стека, 336 00:26:26,310 --> 00:26:29,810 , а втората е стека рамка за тази функция, че да се озовем в 337 00:26:29,810 --> 00:26:34,440 който изглежда като имаме само код събрание за. 338 00:26:34,440 --> 00:26:38,050 Така че нека да се върнем в нашата основна функция, 339 00:26:38,050 --> 00:26:42,300 и да се направи, че не можем да направим рамка 1, и аз мисля, че ние можем да направим надолу, 340 00:26:42,300 --> 00:26:45,160 но почти никога не правя - или нагоре. Да. 341 00:26:45,160 --> 00:26:50,710 Нагоре и надолу. Up ви носи една купчина рамка, надолу ви носи купчина рамка. 342 00:26:50,710 --> 00:26:53,240 Склонен съм никога да не се използва това. 343 00:26:53,240 --> 00:26:59,120 Аз просто казва конкретно рамка 1, която е да отидете на рамката, означен с 1. 344 00:26:59,120 --> 00:27:01,750 Frame 1 ще ни въвеждат в основната стека рамка, 345 00:27:01,750 --> 00:27:05,570 и то се казва тук линията на кода, който се случи да бъде. 346 00:27:05,570 --> 00:27:07,950 Ако искахме още няколко реда код, можем да кажем списък 347 00:27:07,950 --> 00:27:11,280 и това ще ни даде на всички линии на код около него. 348 00:27:11,280 --> 00:27:13,360 Линията segfaulted 6: 349 00:27:13,360 --> 00:27:17,360 ако (strcmp ("CS50 скали", argv [1]) == 0). 350 00:27:17,360 --> 00:27:24,130 Ако това все още не е ясно, можете да го получите направо от тук само с мисъл защо segfaulted. 351 00:27:24,130 --> 00:27:28,800 Но можем да го отнеме една стъпка по-нататък и да каже: "Защо argv [1] segfault? 352 00:27:28,800 --> 00:27:38,830 Печат Да argv [1], и тя изглежда като това е 0x0, което е нулев указател. 353 00:27:38,830 --> 00:27:44,750 Ние сме strcmping CS50 скали и нулеви, и така че ще segfault. 354 00:27:44,750 --> 00:27:48,280 И защо е argv [1] нула? 355 00:27:48,640 --> 00:27:51,280 [Студент, защото не сме го даде никакви аргументи от командния ред. 356 00:27:51,280 --> 00:27:53,390 Да. Ние не даде никакви аргументи от командния ред. 357 00:27:53,390 --> 00:27:58,460 Така ./buggy1 само ще трябва argv [0] да ./buggy1. 358 00:27:58,460 --> 00:28:02,100 Няма да има argv [1], така че ще segfault. 359 00:28:02,100 --> 00:28:07,450 Но ако вместо това, аз правя само CS50, той ще каже Получавате D 360 00:28:07,450 --> 00:28:09,950 защото това е това, което трябваше да направя. 361 00:28:09,950 --> 00:28:15,240 Поглед към buggy1.c, тя е трябвало да отпечатате "Получавате D" - 362 00:28:15,240 --> 00:28:20,820 Ако argv [1] не е "CS50 скали", "Можете да получите D", в противен "Можете да получите А!" 363 00:28:20,820 --> 00:28:25,660 Така че, ако искаме А, ние трябва да се сравни като истински, 364 00:28:25,660 --> 00:28:28,710 което означава, че го сравнява с 0. 365 00:28:28,710 --> 00:28:31,100 Така argv [1] трябва да бъде "CS50 скали". 366 00:28:31,100 --> 00:28:35,660 Ако искате да направите това в командния ред, трябва да използвате \ да избяга пространството. 367 00:28:35,660 --> 00:28:41,690 Така CS50 \ скали и ще получите A! 368 00:28:41,690 --> 00:28:44,060 Ако не направите наклонена черта, защо не работи? 369 00:28:44,060 --> 00:28:47,190 [Ученик] Това са две различни аргументи. >> Да. 370 00:28:47,190 --> 00:28:52,540 Argv [1] ще бъде CS50 и argv [2] ще бъде скали. Добре. 371 00:28:52,540 --> 00:28:56,470 >> Сега ./buggy2 ще segfault отново. 372 00:28:56,470 --> 00:29:01,880 Вместо да го отворите с основната си файл, ние просто ще отвори buggy2 директно, 373 00:29:01,880 --> 00:29:05,000 така GDB buggy2. 374 00:29:05,000 --> 00:29:09,590 Сега, ако ние просто нашата програма, то тогава ще да кажа, програма приемания сигнал SIGSEGV 375 00:29:09,590 --> 00:29:15,530 което е segfault сигнал и това е мястото, където това се е случило да се случи. 376 00:29:15,530 --> 00:29:21,250 Поглед към нашата обратно проследяване, ние виждаме че бяхме във функцията oh_no, 377 00:29:21,250 --> 00:29:23,900 който беше наречен от функцията готина, който беше наречен от функцията Бинки 378 00:29:23,900 --> 00:29:26,460 който беше наречен от главния. 379 00:29:26,460 --> 00:29:31,680 Можем също така да види аргументите на тези функции. 380 00:29:31,680 --> 00:29:34,680 Аргументът за дребен и Бинки е един. 381 00:29:34,680 --> 00:29:44,390 Ако ние списък функцията oh_no, ние виждаме, че oh_no е просто Чар ** = NULL; 382 00:29:44,390 --> 00:29:47,410 * = "Бум"; 383 00:29:47,410 --> 00:29:50,330 Защо се провали? 384 00:29:54,330 --> 00:29:58,380 [Ученик] не може да сочен нулев указател? >> Да. 385 00:29:58,380 --> 00:30:06,090 Това е просто казвам, и е NULL, независимо дали това се случва да бъде знак **, 386 00:30:06,090 --> 00:30:12,070 които, в зависимост от това как го тълкува, тя може да бъде указател към указател към низ 387 00:30:12,070 --> 00:30:15,550 или масив от низове. 388 00:30:15,550 --> 00:30:21,430 Това е и е NULL, така че * и се dereferencing нулев указател, 389 00:30:21,430 --> 00:30:24,800 и така това ще се срине. 390 00:30:24,800 --> 00:30:27,540 Това е един от най-бързите начини, по които би могло да segfault. 391 00:30:27,540 --> 00:30:31,300 Това е просто обявяване на нулев указател и веднага segfaulting. 392 00:30:31,300 --> 00:30:34,570 Ето какво прави oh_no. 393 00:30:34,570 --> 00:30:43,400 Ако се качим един кадър, след това отиваме да влязат в функцията, която нарича oh_no. 394 00:30:43,400 --> 00:30:44,830 Аз трябва да направя това. 395 00:30:44,830 --> 00:30:48,610 Ако не въведете команда и можете просто да натиснете Enter отново 396 00:30:48,610 --> 00:30:52,350 тя просто ще повторете предишната команда, която ще ви се притече. 397 00:30:52,350 --> 00:30:56,610 Ние сме в кадър 1. 398 00:30:56,610 --> 00:31:04,650 Изброяването на тази рамка, което виждаме тук е нашата функция. 399 00:31:04,650 --> 00:31:08,520 Вие може да удари отново, или можете да направите списък 20 и той ще съдържа повече. 400 00:31:08,520 --> 00:31:13,640 Функцията готина казва, че ако аз е 1, тогава отидете на функцията oh_no, 401 00:31:13,640 --> 00:31:15,960 друг да отиде на дебнещ функция. 402 00:31:15,960 --> 00:31:18,700 И знам, че е една, защото ние се случи да видите тук 403 00:31:18,700 --> 00:31:22,560 че готина е наречен с аргумента 1. 404 00:31:22,560 --> 00:31:27,560 Или пък може просто да мога да отпечата и ще кажа, че е една. 405 00:31:27,560 --> 00:31:33,770 В момента сме в готина и ако отидем до друга рамка, ние знаем, че ще свърши в Бинки. 406 00:31:33,770 --> 00:31:36,600 Up. Сега сме в Бинки. 407 00:31:36,600 --> 00:31:41,340 Изброяването на тази функция - списък от преди почивката ме отреже - 408 00:31:41,340 --> 00:31:52,670 тя започна, като че ли е 0, тогава ние ще да го наричат ​​oh_no, друг разговор дребен. 409 00:31:52,670 --> 00:31:57,000 Знаем, че аз бях един, така го наричат ​​дребен. 410 00:31:57,000 --> 00:32:05,030 И сега сме в основната и основната е просто ще бъде Int = RAND () от 3%; 411 00:32:05,030 --> 00:32:08,790 Това е просто ще ви дам един случаен номер, който е или 0, 1 или 2. 412 00:32:08,790 --> 00:32:12,780 Тя ще се обади Бинки с този номер, и тя ще върне 0. 413 00:32:12,780 --> 00:32:16,700 Поглед към това, 414 00:32:16,700 --> 00:32:19,880 просто ходене чрез програмата ръчно, без да го изпълняват веднага, 415 00:32:19,880 --> 00:32:25,400 трябва да зададете точка за пробив в основния, което означава, че когато стартирате програмата 416 00:32:25,400 --> 00:32:31,020 програмата работи, докато не достигне критичната точка. 417 00:32:31,020 --> 00:32:35,450 Така че изпълнението на програмата, тя ще върви и след това ще се появи на основната функция и да спре да работи. 418 00:32:35,450 --> 00:32:44,700 Сега ние сме вътре в основната и стъпка или следващата ще ни доведе до следващия ред код. 419 00:32:44,700 --> 00:32:47,050 Можете да направите стъпка или следващата. 420 00:32:47,050 --> 00:32:51,800 Отиват на следващата, сега аз е настроен да ранд () от 3%, така че ние можем да отпечатаме стойността на I, 421 00:32:51,800 --> 00:32:55,280 и то ще кажа, че е едно. 422 00:32:55,280 --> 00:32:58,110 Сега го прави, независимо дали ние използваме следващата или стъпка. 423 00:32:58,110 --> 00:33:01,000 Предполагам, че това има значение в предишния, но би искал да използва следващия. 424 00:33:01,000 --> 00:33:06,000 Ако използваме стъпка, стъпка в тази функция, което означава поглед към действително нещо 425 00:33:06,000 --> 00:33:07,940 , което се случва вътре в Бинки. 426 00:33:07,940 --> 00:33:10,510 Ако ние използваме следващия, то това означава над функцията 427 00:33:10,510 --> 00:33:14,070 и просто отидете на следващия ред на кода в нашата основна функция. 428 00:33:14,070 --> 00:33:17,900 Точно тук по тази линия, аз бях къде го каза ранд () от 3%; 429 00:33:17,900 --> 00:33:21,320 ако го направя стъпка, той ще отиде в изпълнението на ранд 430 00:33:21,320 --> 00:33:25,110 и погледнете какво се случва там, и аз може да се стъпи чрез функцията ранд. 431 00:33:25,110 --> 00:33:26,920 Но не ми пука за функцията на Ранд. 432 00:33:26,920 --> 00:33:30,190 Аз просто искам да отида на следващия ред код в основната, така че да използвам следващия. 433 00:33:30,190 --> 00:33:35,800 Но сега ми пука за Бинки функция, така че аз искам да се оттегли в това. 434 00:33:35,800 --> 00:33:37,730 Сега съм в Бинки. 435 00:33:37,730 --> 00:33:42,040 Първия ред на кода ще каже, ако (I == 0), направи крачка, 436 00:33:42,040 --> 00:33:44,930 виждаме, че в крайна сметка най-дребен. 437 00:33:44,930 --> 00:33:51,620 Ако списък на нещата, виждаме, че тя проверява е = 0. 438 00:33:51,620 --> 00:33:55,470 аз не е равна на 0, така че тя отиде в друго състояние, 439 00:33:55,470 --> 00:33:59,540 който ще се обадя дребен (I). 440 00:33:59,540 --> 00:34:04,030 Може да се бърка. 441 00:34:04,030 --> 00:34:07,380 Ако просто погледнете тези линии, ще си помислите, ако (I == 0), 442 00:34:07,380 --> 00:34:10,800 Добре, тогава взех една стъпка и сега съм в спретнат (I), 443 00:34:10,800 --> 00:34:14,120 може да мисля, че това трябва да означава, I = 0 или нещо такова. 444 00:34:14,120 --> 00:34:18,980 Това просто означава, че той знае, че може да се придържаме директно на линията готина (I). 445 00:34:18,980 --> 00:34:23,300 , Защото не е 0, следващата стъпка няма да завърши в друго. 446 00:34:23,300 --> 00:34:26,239 Друго не е на линия, че ще поканим в. 447 00:34:26,239 --> 00:34:31,570 Това е просто да отида на следващия ред, тя действително може да изпълни, което е дребен (I). 448 00:34:31,570 --> 00:34:36,090 Стъпвайки в спретнат (I), виждаме, ако (I == 1). 449 00:34:36,090 --> 00:34:42,670 Мога да разбера = 1, така че когато излезем, ние знаем, че започваш да се озове в oh_no 450 00:34:42,670 --> 00:34:46,489 защото аз = 1 се нарича функция oh_no, който можете да влезете, 451 00:34:46,489 --> 00:34:52,969 които ще определят Чар ** = NULL и веднага "Boom". 452 00:34:54,270 --> 00:34:59,690 И тогава всъщност търсят в изпълнението на buggy2, 453 00:34:59,690 --> 00:35:04,590 това, аз просто случаен номер - 0, 1 или 2 - призвание Бинки 454 00:35:04,590 --> 00:35:10,610 които, ако е 0 го нарича oh_no, иначе го нарича дребен, който идва тук. 455 00:35:10,610 --> 00:35:18,100 Ако аз е едно, обадете се oh_no, друг разговор дебнещ, който идва тук, 456 00:35:18,100 --> 00:35:20,460 ако аз е 2, oh_no. 457 00:35:20,460 --> 00:35:24,720 Аз дори не мисля, че има начин - 458 00:35:24,720 --> 00:35:30,030 Ли някой да види начин за извършването на тази програма, която не ще segfault? 459 00:35:30,030 --> 00:35:37,530 Защото, освен ако аз не съм липсва нещо, ако аз е 0, веднага ще segfault, 460 00:35:37,530 --> 00:35:41,250 друго да отидете на функция, която, ако аз 1 ви segfault, 461 00:35:41,250 --> 00:35:44,540 друго да отидете на функция, където, ако аз два segfault. 462 00:35:44,540 --> 00:35:46,810 Така че без значение какво правиш, segfault. 463 00:35:46,810 --> 00:35:52,380 >> Предполагам, че един от начините за определяне би било, вместо да правиш Чар ** = NULL, 464 00:35:52,380 --> 00:35:55,610 изчистване на пространство за тази струна. 465 00:35:55,610 --> 00:36:04,230 Можем да го направим изчистване (sizeof) - sizeof какво? 466 00:36:09,910 --> 00:36:15,190 [Ученик] (Чар) * 5? >> Ли това, изглежда, нали? 467 00:36:15,190 --> 00:36:21,060 Предполагам, че това ще работи, ако аз действително се завтече, но не е това, което търся. 468 00:36:24,400 --> 00:36:32,940 Виж вида на S. Нека добавим INT *, така Int * х. 469 00:36:32,940 --> 00:36:35,600 Аз ще направя изчистване (sizeof (INT)). 470 00:36:35,600 --> 00:36:40,490 Или, ако исках масив от 5, аз ще направя (sizeof (INT) * 5); 471 00:36:40,490 --> 00:36:44,210 Какво ще стане, ако имам INT **? 472 00:36:46,260 --> 00:36:49,140 Това, което бих изчистване? 473 00:36:49,140 --> 00:36:53,510 [Ученик] Размер на показалеца. >> Да. (Sizeof (INT *)); 474 00:36:53,510 --> 00:36:56,960 Същото е и тук. 475 00:36:56,960 --> 00:37:01,280 Искам (sizeof (Чар *)); 476 00:37:06,170 --> 00:37:12,840 Това се случва за разпределяне на пространството за показалеца, който сочи към "Boom". 477 00:37:12,840 --> 00:37:15,330 Не трябва да отделят място за "бум" 478 00:37:15,330 --> 00:37:17,210 защото това по същество е еквивалентно на това, което казах преди 479 00:37:17,210 --> 00:37:20,870 Чар * х = "Boom". 480 00:37:20,870 --> 00:37:27,950 "Boom" вече съществува. Това се случва да съществува само за четене района на паметта. 481 00:37:27,950 --> 00:37:35,200 Но тя вече съществува, което означава, че тази линия на код, ако и е знак **, 482 00:37:35,200 --> 00:37:43,900 * S е знак * и сте създаването на този знак *, за да сочат към "Boom". 483 00:37:43,900 --> 00:37:50,040 Ако исках да копирате "бум" в S, тогава аз ще трябва да отделят място за S. 484 00:37:55,170 --> 00:38:03,900 Ще направя * = изчистване (sizeof (Чар) * 5); 485 00:38:03,900 --> 00:38:06,210 Защо пет? 486 00:38:06,210 --> 00:38:10,860 Защо не 4? Тя изглежда като "бум" е 4 символа. >> Студент Нулевата характер. 487 00:38:10,860 --> 00:38:14,580 Да. Всички на вашите струни ще се нуждаят от нулевата характер. 488 00:38:14,580 --> 00:38:23,590 Сега мога да направя нещо като strcat - Каква е функцията за копиране на низ? 489 00:38:23,590 --> 00:38:28,520 [Ученик] cpy? >> Strcpy. 490 00:38:28,520 --> 00:38:32,700 мъж strcpy. 491 00:38:36,120 --> 00:38:39,590 Така strcpy или strncpy. 492 00:38:39,590 --> 00:38:43,410 strncpy е по-сигурен, тъй като можете да определите точно колко знака, 493 00:38:43,410 --> 00:38:46,190 но тук няма значение, защото ние знаем. 494 00:38:46,190 --> 00:38:50,340 Така strcpy и погледнете в аргументацията. 495 00:38:50,340 --> 00:38:53,100 Първият аргумент е нашата дестинация. 496 00:38:53,100 --> 00:38:56,770 Вторият аргумент е нашият източник. 497 00:38:56,770 --> 00:39:10,310 Отиваме да копирате в нашата дестинация * S показалеца "бум". 498 00:39:10,310 --> 00:39:19,820 Защо може да искате да направите това с strcpy вместо само това, което имахме преди 499 00:39:19,820 --> 00:39:22,800 * S = "бум"? 500 00:39:22,800 --> 00:39:28,630 Има причина, може да искате да направите това, но каква е тази причина? 501 00:39:28,630 --> 00:39:31,940 [Ученик] Ако искате да промените нещо в "бум". >> Да. 502 00:39:31,940 --> 00:39:37,950 Сега мога да направя нещо подобно и [0] = 'X'; 503 00:39:37,950 --> 00:39:48,190 защото точки, за да грамада и, че пространството на куп, че е насочена към 504 00:39:48,190 --> 00:39:52,320 е указател за повече пространство на куп, който се съхранение на "Boom". 505 00:39:52,320 --> 00:39:55,150 Така че това копие на "бум" се съхранява в купчина. 506 00:39:55,150 --> 00:39:58,780 Има технически две копия на "бум" в нашата програма. 507 00:39:58,780 --> 00:40:03,500 Налице е първият, който току-що от този "бум" низ константа, 508 00:40:03,500 --> 00:40:09,250 и второ копие на "Boom", strcpy създаде копие на "Boom". 509 00:40:09,250 --> 00:40:13,100 Но копието на "бум" се съхраняват на куп, и куп вие сте свободни да се промени. 510 00:40:13,100 --> 00:40:17,250 Купчина не е само за четене, така че това означава, че [0] 511 00:40:17,250 --> 00:40:20,500 ще ви позволи да промените стойността на "Boom". 512 00:40:20,500 --> 00:40:23,130 Това ще ви позволи да промените тези знаци. 513 00:40:23,130 --> 00:40:26,640 >> Въпроси? 514 00:40:27,740 --> 00:40:29,290 Добре. 515 00:40:29,290 --> 00:40:35,500 >> Преминавайки към buggy3, нека GDB buggy3. 516 00:40:35,500 --> 00:40:39,840 Ние просто го изпълним и виждаме ние се segfault. 517 00:40:39,840 --> 00:40:46,550 Ако ние обратно проследяване, има само две функции. 518 00:40:46,550 --> 00:40:52,970 Ако се качим в нашата основна функция, ние виждаме, че ние segfaulted в този ред. 519 00:40:52,970 --> 00:41:00,180 Така че, просто гледам на тази линия, за (INT ред = 0; fgets тези неща не е равно NULL; 520 00:41:00,180 --> 00:41:03,770 линия + +). 521 00:41:03,770 --> 00:41:08,010 Нашата предишния кадър се нарича _IO_fgets. 522 00:41:08,010 --> 00:41:10,720 Ще видите, че много с вградени функции C, 523 00:41:10,720 --> 00:41:15,350 че когато получите на segfault, ще има наистина загадъчни имена на функции 524 00:41:15,350 --> 00:41:18,090 Харесвам това _IO_fgets. 525 00:41:18,090 --> 00:41:21,770 Но това ще се отнасят до този fgets повикване. 526 00:41:21,770 --> 00:41:25,850 Някъде вътре, ние сме segfaulting. 527 00:41:25,850 --> 00:41:30,340 Ако се вгледаме в аргументите на fgets, ние можем да отпечатаме буфер. 528 00:41:30,340 --> 00:41:41,180 Нека да отпечатате като - О, не. 529 00:41:48,980 --> 00:41:51,900 Печат не ще да работи точно така, както аз искам тя да. 530 00:41:55,460 --> 00:41:58,000 Нека да погледнем в действителната му програма. 531 00:42:02,200 --> 00:42:09,640 Buffer е знак масив. Той е герой масив от 128 символа. 532 00:42:09,640 --> 00:42:14,980 Така че, когато казвам, печат буфер, ще отпечатате тези 128 символа, 533 00:42:14,980 --> 00:42:18,300 които предполагам е това, което се очаква. 534 00:42:18,300 --> 00:42:21,390 Това, което търсех, е да изписва адреса на буфера, 535 00:42:21,390 --> 00:42:23,680 но това не наистина да ми каже много. 536 00:42:23,680 --> 00:42:30,770 Така че, когато се случи да се каже тук х буфер, той ми показва 0xbffff090, 537 00:42:30,770 --> 00:42:38,690 който, ако си спомняте от по-рано или някакъв момент, Oxbffff тенденция да бъде стак-Иш регион. 538 00:42:38,690 --> 00:42:46,020 Стека има тенденция да се започне от някъде малко под 0xc000. 539 00:42:46,020 --> 00:42:51,890 Просто като видя този адрес, знам, че буфер се случва в стека. 540 00:42:51,890 --> 00:43:04,500 Възобновяване на програмата ми, бягай, буфер, което видяхме беше тази поредица от знаци 541 00:43:04,500 --> 00:43:06,530 , които са почти безсмислени. 542 00:43:06,530 --> 00:43:12,270 След отпечатване на файл, какво файл изглежда? 543 00:43:15,120 --> 00:43:17,310 [Ученик] Null. >> Да. 544 00:43:17,310 --> 00:43:22,610 Файла е * тип файл, така че е указател, 545 00:43:22,610 --> 00:43:26,610 и стойността на тази показалеца е нула. 546 00:43:26,610 --> 00:43:33,240 Така че fgets ще се опита да прочетете от тази показалеца, по индиректен начин, 547 00:43:33,240 --> 00:43:37,320 но за да се достъп до този показалеца, той трябва да го сочен. 548 00:43:37,320 --> 00:43:40,550 Или, с цел достъп до това, което трябва да се посочи, го dereferences. 549 00:43:40,550 --> 00:43:43,810 Така че това е dereferencing нулев указател и да го segfaults. 550 00:43:46,600 --> 00:43:48,730 Можех да го рестартира. 551 00:43:48,730 --> 00:43:52,170 Ако се разделим нашата основна точка и тичам, 552 00:43:52,170 --> 00:43:57,320 първия ред на кода е знак * име на файл = "nonexistent.txt"; 553 00:43:57,320 --> 00:44:00,870 Това би трябвало да даде доста голям намек защо тази програма не успее. 554 00:44:00,870 --> 00:44:06,080 Въвеждане на следващия ме довежда до следващия ред, когато отворите този файл, 555 00:44:06,080 --> 00:44:11,140 и после веднага да влязат в нашата линия, където някога ударих, той ще да segfault. 556 00:44:11,140 --> 00:44:16,880 Някой иска ли да се изхвърлят причина, поради която може да се segfaulting? 557 00:44:16,880 --> 00:44:19,130 [Ученик] Файлът не съществува. >> Да. 558 00:44:19,130 --> 00:44:22,250 Това е трябвало да бъде намек 559 00:44:22,250 --> 00:44:29,570 , че всеки път, когато при отваряне на файла трябва да се провери, че файлът действително съществува. 560 00:44:29,570 --> 00:44:31,510 Така че тук, "nonexistent.txt"; 561 00:44:31,510 --> 00:44:34,700 Когато fopen име на файла за четене, ние трябва да се каже 562 00:44:34,700 --> 00:44:45,870 (файл == NULL) и да кажа ФОРМАТ ("Файлът не съществува!" 563 00:44:45,870 --> 00:44:56,340 или - още по-добре - име на файл); връщане 1; 564 00:44:56,340 --> 00:45:00,300 Така че сега ние проверяваме, за да се види дали е NULL 565 00:45:00,300 --> 00:45:03,930 преди всъщност да продължава и се опитва да чете от този файл. 566 00:45:03,930 --> 00:45:08,800 Ние можем да го правя само за да видя, че това работи. 567 00:45:11,020 --> 00:45:14,970 Имах намерение да се включи нов ред. 568 00:45:21,090 --> 00:45:25,290 Така че сега nonexistent.txt не съществува. 569 00:45:26,890 --> 00:45:30,040 Винаги трябва да проверявате за този вид на нещо. 570 00:45:30,040 --> 00:45:33,870 Винаги трябва да проверите, за да видите, ако fopen връща NULL. 571 00:45:33,870 --> 00:45:38,170 Винаги трябва да проверите, за да сте сигурни, че изчистване не се връща NULL, 572 00:45:38,170 --> 00:45:41,410 или друго, което segfault. 573 00:45:42,200 --> 00:45:45,930 >> Сега buggy4.c. 574 00:45:49,190 --> 00:45:58,440 В града. Предполагам, че това е, че трябва да се изчака за вход или евентуално безкрайно обикаляне. 575 00:45:58,440 --> 00:46:01,870 Да, това е безкрайно обикаляне. 576 00:46:01,870 --> 00:46:05,560 Така buggy4. Изглежда, че ние сме безкрайно обикаляне. 577 00:46:05,560 --> 00:46:12,590 Ние можем да пробие в основния, стартирайте програмата ни. 578 00:46:12,590 --> 00:46:20,180 GDB, толкова дълго, колкото съкращението, която използвате, е недвусмислено 579 00:46:20,180 --> 00:46:23,420 или специални съкращения, които те предоставят за вас, 580 00:46:23,420 --> 00:46:29,020 тогава можете да използвате N, за да се използва по-нататък вместо да се налага да пишете следващата целия път. 581 00:46:29,020 --> 00:46:33,730 И сега, че съм ударен н веднъж, мога да просто да натиснете Enter, за да се запази ще следващия 582 00:46:33,730 --> 00:46:36,640 вместо да се налага да се удари н Въведете, N Enter, N Въведете. 583 00:46:36,640 --> 00:46:44,630 Изглежда, че съм в някаква линия, че настройката на масив [I] 0. 584 00:46:44,630 --> 00:46:50,510 Тя изглежда като аз никога не съм се счупи тази линия. 585 00:46:50,510 --> 00:46:54,780 Ако аз отпечатате, така че е два, тогава ще се върви напред. 586 00:46:54,780 --> 00:46:59,250 Ще отпечатам, аз е 3, тогава ще се върви напред. 587 00:46:59,250 --> 00:47:05,360 Ще отпечатам и аз 3. На следващо място, аз печатате, е 4. 588 00:47:05,360 --> 00:47:14,520 Всъщност, печат sizeof (масив), така че големината на масива е 20. 589 00:47:16,310 --> 00:47:32,870 Но изглежда, че има някаква специална команда GDB, докато нещо се случи. 590 00:47:32,870 --> 00:47:37,620 Това е като състояние на стойността на променливата. Но аз не си спомням какво е то. 591 00:47:37,620 --> 00:47:44,100 Така че, ако продължават 592 00:47:44,100 --> 00:47:47,120 Какво искаш да кажеш? Какво ви донесе? 593 00:47:47,120 --> 00:47:50,500 [Ученик] се показва добавя - >> Да. Така че покажете мога да помогна. 594 00:47:50,500 --> 00:47:54,530 Ако ние просто показва, тя ще постави тук, каква е стойността на АЗ 595 00:47:54,530 --> 00:47:56,470 така че аз не трябва да го разпечатате всеки път. 596 00:47:56,470 --> 00:48:02,930 Ако ние просто продължавай следващия, ние виждаме, 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 Нещо става ужасно погрешно, и аз се върнете към 0. 598 00:48:13,330 --> 00:48:22,220 Поглед към buggy4.c, ние виждаме всичко, което се случва, е INT масив [5]; 599 00:48:22,220 --> 00:48:26,200 за (I = 0; и <= sizeof (масив), аз + +) 600 00:48:26,200 --> 00:48:28,550 масив [] = 0; 601 00:48:28,550 --> 00:48:31,390 Какво виждаме, че не е наред тук? 602 00:48:31,390 --> 00:48:39,480 Като един намек, когато правех GDB buggy4 - нека прекъсне основната писта - 603 00:48:39,480 --> 00:48:45,980 Печат sizeof (масив) само за да видя какво е състоянието е мястото, където най-после трябва да избухне. 604 00:48:47,690 --> 00:48:51,100 Къде съм? Съм тичал? 605 00:48:51,100 --> 00:48:54,280 Не са декларирали все още. 606 00:48:54,280 --> 00:48:58,680 Така отпечатате sizeof (масив) и това е 20, 607 00:48:58,680 --> 00:49:06,690 която се очаква, тъй като моята масив е с размер 5 и е на пет числа, 608 00:49:06,690 --> 00:49:12,410 , така че цялото нещо трябва да бъде 5 * sizeof (INT) байта, където sizeof (INT) Претендира да е 4. 609 00:49:12,410 --> 00:49:14,780 Така че sizeof (масив) е 20. 610 00:49:14,780 --> 00:49:17,420 Какво трябва да стане това? 611 00:49:17,420 --> 00:49:21,720 [Ученик] Разделени от sizeof (INT). >> Да, / sizeof (INT). 612 00:49:21,720 --> 00:49:30,630 Изглежда, че все още има проблем тук. Мисля, че това трябва да бъде само < 613 00:49:30,630 --> 00:49:36,960 тъй като това е почти винаги <и никога не <=. 614 00:49:36,960 --> 00:49:44,860 Сега нека помислим защо това всъщност е разбит. 615 00:49:44,860 --> 00:49:53,370 Някой има ли предположения защо бях възстановите 0 през всяка итерация на цикъла? 616 00:50:01,300 --> 00:50:09,350 Единственото нещо вътре от тук, което се случва е, че масив [I] е настроен на 0. 617 00:50:09,350 --> 00:50:15,350 Така че по някакъв начин, тази линия на код причинява вътр и да бъде поставено на 0. 618 00:50:16,730 --> 00:50:23,130 [Ученик] Може ли да бъде, защото това е незачитане на паметта на тази част от I 619 00:50:23,130 --> 00:50:27,970 , когато мисли, че е следващия елемент на масива? >> Bowden Да. 620 00:50:27,970 --> 00:50:33,880 Когато отиваме след края на нашия масив, 621 00:50:33,880 --> 00:50:39,870 по някакъв начин, че пространството, че ние сме висш висш стойността на I. 622 00:50:39,870 --> 00:50:48,030 И така, ако се вгледаме в buggy4, почивка на Майн, план, 623 00:50:48,030 --> 00:50:53,120 да отпечатате адрес на АЗ. 624 00:50:53,120 --> 00:50:57,280 Тя изглежда като че ли е bffff124. 625 00:50:57,280 --> 00:51:03,930 Сега нека да отпечатате адрес на масив [0]. 110. 626 00:51:03,930 --> 00:51:06,290 Ами [1]? 114. 627 00:51:06,290 --> 00:51:07,920 [2], 118. 628 00:51:07,920 --> 00:51:14,530 11в, 120. масив [5] е bfff124. 629 00:51:14,530 --> 00:51:26,990 Така масив [5] има същия адрес като мен, което означава, че този масив [5]. 630 00:51:26,990 --> 00:51:30,720 Ако те имат един и същ адрес, те са едно и също нещо. 631 00:51:30,720 --> 00:51:38,410 Така че, когато ние се създаде масив [5], за да 0, ние сме и определяне на 0. 632 00:51:38,410 --> 00:51:46,070 И ако мислите за това по отношение на стека, 633 00:51:46,070 --> 00:51:55,590 Int I е обявен за първият, което означава, че получава малко пространство в стека. 634 00:51:55,590 --> 00:52:04,730 Тогава масив [5] се разпределят, така че след това се разпределят 20 байта в стека. 635 00:52:04,730 --> 00:52:08,400 Така че аз се разпределят най-напред, а след това се разпределят тези 20 байта. 636 00:52:08,400 --> 00:52:11,400 Така че аз се случва точно преди масив, 637 00:52:11,400 --> 00:52:19,230 защото от начина, като казах миналата седмица, когато е технически стека расте надолу, 638 00:52:19,230 --> 00:52:28,520 когато индекс в масив, ние се гарантира, че 0th позиция в масива 639 00:52:28,520 --> 00:52:31,970 винаги се случва преди първата позиция в масива. 640 00:52:31,970 --> 00:52:35,900 Това е един вид как да го привлече миналата седмица. 641 00:52:35,900 --> 00:52:42,210 Забележете, че в дъното имаме адрес 0 и в горната част имаме адрес Макс. 642 00:52:42,210 --> 00:52:44,880 Стека стават все повече. 643 00:52:48,100 --> 00:52:53,500 Да кажем, че аз разпределят. 644 00:52:53,500 --> 00:52:59,680 Разпределят цяло число, което означава, нека просто кажем, че тук цяло число и получава разпределени. 645 00:52:59,680 --> 00:53:06,420 Тогава ще разпредели нашата гама от пет числа, което означава, че под това, 646 00:53:06,420 --> 00:53:11,230 от стека се разраства, тези пет числа се разпределят. 647 00:53:11,230 --> 00:53:15,900 Но тъй как масиви, гарантира, че ние сме на първа позиция в масива 648 00:53:15,900 --> 00:53:22,260 винаги има адрес по-малко от второто нещо в масива. 649 00:53:22,260 --> 00:53:28,270 Така 0 масив позиция винаги трябва да се случи първо в паметта, 650 00:53:28,270 --> 00:53:30,700 като има предвид, че масив позиция 1 трябва да се случи след това 651 00:53:30,700 --> 00:53:33,310 и масив позиция 2 трябва да се случи след това, 652 00:53:33,310 --> 00:53:37,900 което означава, че позицията, че 0 масив ще се случи някъде тук, 653 00:53:37,900 --> 00:53:40,690 масив позиция 1 ще се случи горе, че 654 00:53:40,690 --> 00:53:45,530 тъй като се движи нагоре означава по-високи адреси, тъй като максималната адрес е тук. 655 00:53:45,530 --> 00:53:50,490 Така масив [0] тук, масив [1], масив [2], масив [3] тук. 656 00:53:50,490 --> 00:53:55,620 Забележете как преди разпределени цяло число и по целия път до тук, 657 00:53:55,620 --> 00:54:01,040 както ние се движат повече и повече в нашия масив, ние сме все по-близо и по-близо до нашето Аз цяло число. 658 00:54:01,040 --> 00:54:07,640 Просто така се случва, че масив [5], която е една позиция извън нашия масив, 659 00:54:07,640 --> 00:54:13,010 е точно където цяло число се случи да се разпределят. 660 00:54:13,010 --> 00:54:16,920 Така че това е точката, където ние се случи да се удари пространство в стека 661 00:54:16,920 --> 00:54:21,680 , които бяха отпуснати за цяло число и, и ние сме на посочената до 0. 662 00:54:21,680 --> 00:54:26,160 >> Ето как работи. Въпроси? Да. 663 00:54:26,160 --> 00:54:30,710 [Ученик] Никога не обръщай внимание. Добре. 664 00:54:30,710 --> 00:54:33,090 [Ученик] Как да избегнем тези вид на грешки? 665 00:54:33,090 --> 00:54:41,190 Този вид грешки? Да не се използва като език за програмиране. 666 00:54:41,190 --> 00:54:45,840 Използвайте език, който има масив границите проверка. 667 00:54:45,840 --> 00:54:55,900 Докато сте внимателни, просто трябва да избегне покрай границите на вашата масив. 668 00:54:55,900 --> 00:54:58,300 [Ученик] Така че тук, когато мина покрай границите на вашата масив - 669 00:54:58,300 --> 00:55:01,840 [Bowden] Това е, когато нещата започват да се обърка. >> [Ученик] О, добре. 670 00:55:01,840 --> 00:55:05,730 Толкова дълго, колкото да останеш в паметта, разпределена за вашия масив, всичко е наред. 671 00:55:05,730 --> 00:55:12,400 Но C не прави проверка за грешки. Ако го направя масив [1000], с удоволствие ще просто променя каквото и да се случи - 672 00:55:12,400 --> 00:55:16,500 Той отива в началото на масива, а след това той отива 1000 позиции след и го постави на 0. 673 00:55:16,500 --> 00:55:20,000 Той не направи никаква проверка, че о, това не действително да има хиляда неща в него. 674 00:55:20,000 --> 00:55:22,750 1000 е по-далеч от това, което трябва да се променя, 675 00:55:22,750 --> 00:55:26,940 като има предвид, че Java или нещо ще се масив на индекса на границите 676 00:55:26,940 --> 00:55:29,820 или индекс границите изключение. 677 00:55:29,820 --> 00:55:33,950 Ето защо много по-високи езици ниво тези неща 678 00:55:33,950 --> 00:55:37,340 където, ако излизат извън границите на масива, не успеете 679 00:55:37,340 --> 00:55:40,070 така че да не може да промени нещата под вас 680 00:55:40,070 --> 00:55:42,590 и тогава нещата вървят много по-лошо, отколкото просто да се изключение 681 00:55:42,590 --> 00:55:44,940 кажеш, че си отиде след края на масива. 682 00:55:44,940 --> 00:55:50,970 [Ученик] И така, трябва ли току-що са се променили <= просто > Bowden Да. 683 00:55:50,970 --> 00:55:54,800 Той трябва да бъде 00:55:59,560 sizeof (масив) е 20, но искам само 5. >> [Ученик] Точно така. 685 00:55:59,560 --> 00:56:04,060 Още въпроси? Добре. 686 00:56:04,060 --> 00:56:07,380 >> [Ученик] Аз имам един въпрос. >> Да. 687 00:56:07,380 --> 00:56:16,440 [Ученик] Каква е реалната променлива масив? 688 00:56:16,440 --> 00:56:20,000 [Bowden като какво е масив? 689 00:56:20,000 --> 00:56:24,930 Array само по себе си е символ. 690 00:56:24,930 --> 00:56:31,490 Това е само адреса на началото на 20 байта, че ние се обръщате. 691 00:56:31,490 --> 00:56:38,070 Можете да мислите за него като показалка, но той е константа показалеца. 692 00:56:38,070 --> 00:56:44,140 Веднага след като нещата се събират, променливата масив вече не съществува. 693 00:56:44,140 --> 00:56:48,210 [Ученик] И така, как го намери големината на масива? 694 00:56:48,210 --> 00:56:54,130 Размер на масива се отнася до размера на този блок, че този символ се отнася до. 695 00:56:54,130 --> 00:57:01,240 Когато правя нещо подобно ФОРМАТ ("% P \ N", масив); 696 00:57:01,240 --> 00:57:05,140 нека да го стартирате. 697 00:57:12,960 --> 00:57:15,530 Какво съм направил погрешно? 698 00:57:15,530 --> 00:57:19,220 "Масив" Array отчитат тук. 699 00:57:20,820 --> 00:57:23,200 О, тук. 700 00:57:23,200 --> 00:57:31,250 Звъня е умен, и то се случва да забележите, че аз заявих на масива 5 елемента 701 00:57:31,250 --> 00:57:34,540 но аз съм индексиране в позиция 1000. 702 00:57:34,540 --> 00:57:38,450 Той може да направи това, защото това са само константи. 703 00:57:38,450 --> 00:57:43,370 Той може само да отиде толкова далеч, забележи, че аз отивам извън границите на масива. 704 00:57:43,370 --> 00:57:46,880 Но забележете преди, когато ние трябваше да бъда неправилно, 705 00:57:46,880 --> 00:57:51,040 той не може да се определи колко стойности може да поеме, 706 00:57:51,040 --> 00:57:55,540 така че не може да определи, че щях след края на масива. 707 00:57:55,540 --> 00:57:59,430 Това е просто звъня е умен. 708 00:57:59,430 --> 00:58:03,340 >> Но сега buggy4. Така че, какво съм аз греша? 709 00:58:03,340 --> 00:58:05,970 Мълчаливо обявяване библиотека функция "ФОРМАТ". 710 00:58:05,970 --> 00:58:14,960 Отивам да искате да # включват . 711 00:58:14,960 --> 00:58:18,710 Добре. Сега работи buggy4. 712 00:58:18,710 --> 00:58:24,840 Отпечатване на стойността на масива, както направих аз тук, да го отпечатате като показалка 713 00:58:24,840 --> 00:58:30,060 разпечатки нещо, което прилича на това - bfb8805c - което е с около адрес 714 00:58:30,060 --> 00:58:33,450 това е в стак-Иш регион. 715 00:58:33,450 --> 00:58:41,820 Array само по себе си е като показалеца, но това не е действителен показалеца, 716 00:58:41,820 --> 00:58:45,410 тъй като редовно показалеца можем да променим. 717 00:58:45,410 --> 00:58:54,700 Array е просто някакъв постоянен. 20 блокове памет започват адрес 0xbfb8805c. 718 00:58:54,700 --> 00:59:09,020 Толкова bfb8805c чрез този адрес +20- или аз предполагам, -20 - 719 00:59:09,020 --> 00:59:17,400 на паметта, разпределени за този масив. 720 00:59:17,400 --> 00:59:20,350 Array, самата променлива не се съхранява никъде. 721 00:59:20,350 --> 00:59:27,660 Когато сте съставянето, компилаторът ръка вълна - 722 00:59:27,660 --> 00:59:33,060 но компилатора просто ще използвате, когато го знае масив да бъде. 723 00:59:33,060 --> 00:59:36,090 Той знае къде започва този масив, 724 00:59:36,090 --> 00:59:40,910 и така винаги може да просто правя нещата по отношение на компенсации от това начало. 725 00:59:40,910 --> 00:59:43,960 Тя не се нуждае самата променлива да представлява масив. 726 00:59:43,960 --> 00:59:53,730 Но когато правя нещо подобно Int * р = масив, сега стр. е указател, който сочи към този масив, 727 00:59:53,730 --> 00:59:57,830 и сега стр. всъщност не съществува на стека. 728 00:59:57,830 --> 01:00:01,950 Аз съм безплатно да променят стр.. Мога да направя р = изчистване. 729 01:00:01,950 --> 01:00:06,500 Така че първоначално посочи в масив, а сега сочи малко пространство на куп. 730 01:00:06,500 --> 01:00:09,620 Не мога да направя масив = изчистване. 731 01:00:09,620 --> 01:00:13,710 Ако е умен звъня, той ще крещи по мен правото на разстояние бухалката. 732 01:00:17,000 --> 01:00:21,430 Всъщност, аз съм сигурен, че GCC ще направите това също. 733 01:00:21,430 --> 01:00:25,010 Така масив тип "Int [5]" не е отнесен. 734 01:00:25,010 --> 01:00:28,040 Вие не може да възлага нещо за типа масив 735 01:00:28,040 --> 01:00:30,500 защото масивът е просто постоянно. 736 01:00:30,500 --> 01:00:34,760 Това е символ, който референции тези 20 байта. Не мога да го променя. 737 01:00:34,760 --> 01:00:37,690 >> [Ученик], където се съхраняват размера на масива? 738 01:00:37,690 --> 01:00:40,670 [Bowden] не се съхранява никъде. Това е, когато е съставянето. 739 01:00:40,670 --> 01:00:46,310 Е, къде е размерът на масива съхранява? 740 01:00:46,310 --> 01:00:51,870 Можете да използвате само sizeof (масив), в рамките на функцията, която масива се обявява. 741 01:00:51,870 --> 01:01:03,150 Така че, ако го направя някаква функция, Foo, и аз правя (INT масив []) 742 01:01:03,150 --> 01:01:10,450 ФОРМАТ ("% г \ N", sizeof (масив)); 743 01:01:10,450 --> 01:01:21,330 и след това тук аз наричам Foo (масив); 744 01:01:21,330 --> 01:01:24,840 в рамките на тази функция - да го стартирате. 745 01:01:34,200 --> 01:01:36,840 Това е звъня умен отново. 746 01:01:36,840 --> 01:01:43,890 Той ми казва, че sizeof параметър масив функция 747 01:01:43,890 --> 01:01:46,690 ще се върне размера на "INT *". 748 01:01:46,690 --> 01:01:55,150 Това би било грешка, ако то не е това, което исках да се случи. 749 01:01:55,150 --> 01:01:58,960 Да изключите Werror. 750 01:02:14,950 --> 01:02:17,590 Внимание. Предупрежденията са добре. 751 01:02:17,590 --> 01:02:19,960 Той все още ще съставят толкова дълго, тъй като има предупреждение. 752 01:02:19,960 --> 01:02:22,910 / A.out ще да отпечатате 4. 753 01:02:22,910 --> 01:02:28,650 Предупреждението, че е генериран е ясен показател за това какво се е объркало. 754 01:02:28,650 --> 01:02:34,120 Това INT масив е просто да отпечатате sizeof (INT *). 755 01:02:34,120 --> 01:02:39,790 Дори ако сложа на масив [5] тук, е все още само ще да отпечатате sizeof (INT *). 756 01:02:39,790 --> 01:02:47,440 Така че веднага щом го премине във функция, разликата между масиви и указатели 757 01:02:47,440 --> 01:02:49,670 е несъществуваща. 758 01:02:49,670 --> 01:02:52,640 Това се случва да бъде масив, който е обявен в стека, 759 01:02:52,640 --> 01:02:58,300 но веднага след като минаваме покрай тази стойност, че 0xbf дрън, дрън, дрън в тази функция, 760 01:02:58,300 --> 01:03:03,350 този указател сочи към този масив на стека. 761 01:03:03,350 --> 01:03:08,310 Така че това означава, че sizeof се прилага само във функцията, че масивът е обявена, 762 01:03:08,310 --> 01:03:11,230 което означава, че когато съставянето на тази функция, 763 01:03:11,230 --> 01:03:17,330 , когато звъня минава през тази функция, той вижда масив е INT масив с размер 5. 764 01:03:17,330 --> 01:03:20,640 Тогава го вижда sizeof (масив). Е, това е 20. 765 01:03:20,640 --> 01:03:26,440 Това е всъщност как sizeof основно работи за почти всички случаи. 766 01:03:26,440 --> 01:03:31,150 Sizeof не е функция, той е оператор. 767 01:03:31,150 --> 01:03:33,570 Не наричаш sizeof функция. 768 01:03:33,570 --> 01:03:38,280 Sizeof (INT), компилаторът ще просто да преобразува 4. 769 01:03:41,480 --> 01:03:43,700 Ясно ли е? Добре. 770 01:03:43,700 --> 01:03:47,520 >> [Ученик] Така че каква е разликата между sizeof (масив) в основния и в Foo? 771 01:03:47,520 --> 01:03:52,840 Това е така, защото ние казваш sizeof (масив), която е от тип Int *, 772 01:03:52,840 --> 01:03:57,120 като има предвид, че масива тук не е * тип Int, това е едно цяло число масив. 773 01:03:57,120 --> 01:04:04,540 >> [Ученик] Така че, ако сте имали параметър масив [] вместо INT масив *, 774 01:04:04,540 --> 01:04:09,230 това означава, че вие ​​все още може да промени масив, защото сега тя е указател? 775 01:04:09,230 --> 01:04:14,250 Bowden] Харесвам това? >> Студент Да. Може да промените масив в рамките на функцията сега? 776 01:04:14,250 --> 01:04:18,420 [Bowden] може да се промени масив в двата случая. 777 01:04:18,420 --> 01:04:23,130 В двата случая, вие сте свободни да се каже, масив [4] = 0. 778 01:04:23,130 --> 01:04:26,590 [Ученик] Но можете ли да направите точка масив с нещо друго? 779 01:04:26,590 --> 01:04:30,230 [Bowden О Да. И в двата случая - >> [ученик] Да. 780 01:04:30,230 --> 01:04:38,410 Bowden] Разликата между масив [] и INT масив *, няма никой. 781 01:04:38,410 --> 01:04:42,570 Можете да получите също и някои многомерен масив тук 782 01:04:42,570 --> 01:04:47,050 за някои удобен синтаксис, но това е все още само на показалеца. 783 01:04:47,050 --> 01:04:56,400 Това означава, че аз съм свободен да правя масив = изчистване (sizeof (INT)), а сега се отбележи някъде другаде. 784 01:04:56,400 --> 01:04:59,610 Но точно като как работи вечно и винаги, 785 01:04:59,610 --> 01:05:03,210 промяна на този масив, като го сочат към нещо друго 786 01:05:03,210 --> 01:05:07,570 не променя този масив тук, защото това е копие на аргумента, 787 01:05:07,570 --> 01:05:10,780 това не е показалеца на този довод. 788 01:05:10,780 --> 01:05:16,070 И всъщност, точно както повече индикации, че това е точно същото - 789 01:05:16,070 --> 01:05:21,100 ние вече видяхме какви разпечатки печат масив - 790 01:05:21,100 --> 01:05:31,410 какво ще стане, ако се печата адреса на масива или адреса на адреса на масива 791 01:05:31,410 --> 01:05:36,290 Единия от тези? 792 01:05:41,770 --> 01:05:45,220 Да се ​​игнорира това. 793 01:05:48,140 --> 01:05:51,660 Добре. Това е добре. В момента текат. / A.out. 794 01:05:51,660 --> 01:06:00,220 Печат масив, след което отпечатване на адреса на масива, са едно и също нещо. 795 01:06:00,220 --> 01:06:02,870 Array просто не съществува. 796 01:06:02,870 --> 01:06:08,190 Той знае, когато сте отпечатване на масив, отпечатване на символа, който се отнася до тези 20 байта. 797 01:06:08,190 --> 01:06:11,940 Отпечатване на адреса на масива, добре, масив не съществува. 798 01:06:11,940 --> 01:06:17,200 То не трябва адрес, така че просто отпечатва адрес на тези 20 байта. 799 01:06:20,820 --> 01:06:28,150 Веднага след като вие компилирате, като в компилирана buggy4 / a.out, 800 01:06:28,150 --> 01:06:30,340 масив е несъществуваща. 801 01:06:30,340 --> 01:06:33,640 Указатели съществуват. Масивите не. 802 01:06:34,300 --> 01:06:38,060 Блокове памет, представляващи масив все още съществуват, 803 01:06:38,060 --> 01:06:43,270 но променлива масив и променливи от този тип не съществуват. 804 01:06:46,260 --> 01:06:50,270 Тези, които са като основните разлики между масиви и указатели 805 01:06:50,270 --> 01:06:55,590 Веднага след като направите извиквания на функции, няма разлика. 806 01:06:55,590 --> 01:07:00,460 Но вътре на функцията, която е обявена за самия масив, sizeof работи по различен начин 807 01:07:00,460 --> 01:07:05,190 тъй като сте отпечатване на размера на блоковете, а не на размера на типа, 808 01:07:05,190 --> 01:07:08,950 и не можете да го промените, защото то е символ. 809 01:07:08,950 --> 01:07:14,370 Отпечатване на нещо и адреса на нещо отпечатва едно и също нещо. 810 01:07:14,370 --> 01:07:18,480 И това е доста значително. 811 01:07:18,480 --> 01:07:20,820 [Ученик] Може ли да се каже, че още един път? 812 01:07:21,170 --> 01:07:24,170 Може да съм пропуснал нещо. 813 01:07:24,170 --> 01:07:29,260 Печат масив и адрес на масива отпечатва едно и също нещо, 814 01:07:29,260 --> 01:07:33,180 като има предвид, че ако печатате показалеца спрямо адреса на показалеца, 815 01:07:33,180 --> 01:07:36,010 единственото нещо, което отпечатва адрес на това, което сочи, 816 01:07:36,010 --> 01:07:40,360 отпечатва адрес на показалеца на стека. 817 01:07:40,360 --> 01:07:47,040 Можете да промените показалеца, не можете да променяте символ масив. 818 01:07:47,740 --> 01:07:53,270 И sizeof показалецът се ще да отпечатате размер на този тип показалеца. 819 01:07:53,270 --> 01:07:57,470 Така Int * р sizeof (п) ще да отпечатате 4, 820 01:07:57,470 --> 01:08:04,110 но Int масив [5] печат sizeof (масив) ще да отпечатате 20. 821 01:08:04,110 --> 01:08:07,480 [Ученик] Така вътр масив [5] ще отпечата 20? >> Да. 822 01:08:07,480 --> 01:08:13,300 Ето защо вътре в buggy4, когато той да бъде използван sizeof (масив) 823 01:08:13,300 --> 01:08:16,660 това правех <20, което не е това, което искахме. 824 01:08:16,660 --> 01:08:20,880 Искаме I <5. >> Студент Добре. 825 01:08:20,880 --> 01:08:25,569 [Bowden И тогава, както и веднага след като започнете преминаване на функциите, 826 01:08:25,569 --> 01:08:34,340 ако сме направили Int * р = масив; 827 01:08:34,340 --> 01:08:39,779 вътрешността на тази функция, ние можем да основно да използвате стр. и масив точно по същия начин, 828 01:08:39,779 --> 01:08:43,710 изключение на проблема sizeof и промяна проблем. 829 01:08:43,710 --> 01:08:49,810 Но [0] = 1; е същото като каза масив [0] = 1; 830 01:08:49,810 --> 01:08:55,600 И веднага след като казваме, Foo (масив), или Foo (п); 831 01:08:55,600 --> 01:08:59,760 вътрешността на функцията Foo, това е два пъти същия призив. 832 01:08:59,760 --> 01:09:03,350 Няма разлика между тези две повиквания. 833 01:09:07,029 --> 01:09:11,080 >> Всеки добър по този въпрос? Добре. 834 01:09:14,620 --> 01:09:17,950 Имаме 10 минути. 835 01:09:17,950 --> 01:09:28,319 >> Ние ще се опитаме да получите чрез тази програма Hacker Typer 836 01:09:28,319 --> 01:09:32,350 този сайт, който излезе миналата година или нещо такова. 837 01:09:34,149 --> 01:09:41,100 Това е просто трябваше да бъда като теб въведете произволно и отпечатва 838 01:09:41,100 --> 01:09:46,729 Каквото файл, се случва да са натоварени, е това, което изглежда, че въвеждате. 839 01:09:46,729 --> 01:09:52,069 Тя изглежда като някакъв вид на операционната система код. 840 01:09:53,760 --> 01:09:56,890 Това е, което искат да приложат. 841 01:10:08,560 --> 01:10:11,690 Трябва да има бинарен изпълним име hacker_typer 842 01:10:11,690 --> 01:10:14,350 , който отвежда в един-единствен аргумент, файлът "хакер тип". 843 01:10:14,350 --> 01:10:16,480 Изпълнението на изпълним, трябва да изчистите екрана 844 01:10:16,480 --> 01:10:20,850 и след това да отпечатате един символ от изминалата във файл всеки път, когато потребителят натисне ключ. 845 01:10:20,850 --> 01:10:24,990 Така че каквото и ключ натиснете, трябва да изхвърляме и вместо да отпечатате герой от файла 846 01:10:24,990 --> 01:10:27,810 това е аргумент. 847 01:10:29,880 --> 01:10:34,350 Аз ще ви кажа доста неща, за които ще трябва да знаете. 848 01:10:34,350 --> 01:10:36,440 Но ние искаме да се провери в библиотеката termios. 849 01:10:36,440 --> 01:10:44,840 Никога не съм използвал тази библиотека през целия си живот, така че има много минимални цели. 850 01:10:44,840 --> 01:10:48,610 Но това ще бъде библиотеката можем да използваме, за да изхвърлите характера ви удари 851 01:10:48,610 --> 01:10:52,390 когато пишете в стандарт инча 852 01:10:56,970 --> 01:11:05,840 Така hacker_typer.c, и ние ще искате да # включват . 853 01:11:05,840 --> 01:11:12,870 Търси в мъжа страница за termios - Аз съм се познае, че е крайно OS или нещо - 854 01:11:12,870 --> 01:11:16,240 Аз не знам как да го прочетете. 855 01:11:16,240 --> 01:11:21,040 Това се казва да се включат тези два файла, така че ние ще направим това. 856 01:11:37,620 --> 01:11:46,820 >> Първото нещо, което на първо място, искаме да се вземат в един аргумент, който е файл, който трябва да отвори. 857 01:11:46,820 --> 01:11:52,420 Така че това, което искам да направя? Как мога да проверя, за да видиш, че има един-единствен аргумент? 858 01:11:52,420 --> 01:11:56,480 [Ученик] Ако argc равни. >> Bowden Да. 859 01:11:56,480 --> 01:12:21,250 Така че, ако (argc = 2!) ФОРМАТ ("Използване:% [файл, за да отворите]"). 860 01:12:21,250 --> 01:12:32,750 Така че сега, ако аз тичам без да предоставя на втория аргумент - О, имам нужда от нов ред - 861 01:12:32,750 --> 01:12:36,240 ще видите, че казва използване. / hacker_typer, 862 01:12:36,240 --> 01:12:39,770 и след това на втория аргумент трябва да бъде файла, който искате да отворите. 863 01:12:58,430 --> 01:13:01,260 Сега какво да правя? 864 01:13:01,260 --> 01:13:08,490 Искам да се чете от този файл. Как да се чете от файл? 865 01:13:08,490 --> 01:13:11,920 [Ученик] отвори първият. >> Да. 866 01:13:11,920 --> 01:13:15,010 Така fopen. Какво fopen изглежда? 867 01:13:15,010 --> 01:13:22,980 [Ученик] Име. >> Bowden] Filename ще бъде argv [1]. 868 01:13:22,980 --> 01:13:26,110 [Ученик] И тогава това, което искате да правите с него, така че - >> [Bowden Да. 869 01:13:26,110 --> 01:13:28,740 Така че, ако не си спомня, просто може да направи fopen човек, 870 01:13:28,740 --> 01:13:32,960 , където ще бъде Конст Чар път *, където пътят е името на файла, 871 01:13:32,960 --> 01:13:34,970 Конст Чар режим *. 872 01:13:34,970 --> 01:13:38,660 Ако ви се случи да не си спомня какво е режим, а след това можете да погледнете за режим. 873 01:13:38,660 --> 01:13:44,660 Вътре от синтетични страници, характер черта е това, което можете да използвате, за да търсят неща. 874 01:13:44,660 --> 01:13:49,790 Така че аз вид / режим, за да търсите режим. 875 01:13:49,790 --> 01:13:57,130 N и N са това, което можете да използвате, за да преминете през мачовете от търсенето. 876 01:13:57,130 --> 01:13:59,800 Тук се казва аргумент режим, за да низ 877 01:13:59,800 --> 01:14:01,930 започва с един от следните последователности. 878 01:14:01,930 --> 01:14:06,480 Така R, Open текстов файл за четене. Това е, което искаме да направим. 879 01:14:08,930 --> 01:14:13,210 За четене, и аз искам да се съхранява. 880 01:14:13,210 --> 01:14:18,720 Това, което ще бъде файл *. Сега какво искам да направя? 881 01:14:18,720 --> 01:14:21,200 Дай ми секунда. 882 01:14:28,140 --> 01:14:30,430 Добре. Сега какво искам да направя? 883 01:14:30,430 --> 01:14:32,940 [Ученик], ако това е NULL. >> Bowden Да. 884 01:14:32,940 --> 01:14:38,690 Всеки път, когато отворите файл, уверете се, че успешно сте в състояние да го отворите. 885 01:14:58,930 --> 01:15:10,460 >> Сега искам да направя това termios неща там, където искам първо да прочетете моите текущите настройки 886 01:15:10,460 --> 01:15:14,050 и спести тези в нещо, после искам да променя настройките 887 01:15:14,050 --> 01:15:19,420 да изхвърляме всеки символ, който пиша, 888 01:15:19,420 --> 01:15:22,520 и после искам да актуализира тези настройки. 889 01:15:22,520 --> 01:15:27,250 И тогава в края на програмата, искам да се върнете към първоначалните си настройки. 890 01:15:27,250 --> 01:15:32,080 Така че структурата ще бъде от тип termios, и аз отивам да искат два от тях. 891 01:15:32,080 --> 01:15:35,600 Първият от тях ще да ми current_settings, 892 01:15:35,600 --> 01:15:42,010 и след това те ще да ми hacker_settings. 893 01:15:42,010 --> 01:15:48,070 Първо, аз ще искам да запазя текущите настройки, 894 01:15:48,070 --> 01:15:53,790 тогава аз ще искате да актуализирате hacker_settings 895 01:15:53,790 --> 01:16:01,570 и след това в края на моята програма, аз искам да се върне към текущите настройки. 896 01:16:01,570 --> 01:16:08,660 Така спасяването на текущите настройки, начина, по който работи, Ние човек termios. 897 01:16:08,660 --> 01:16:15,810 Ние виждаме, че имаме този INT tcsetattr, вътр tcgetattr. 898 01:16:15,810 --> 01:16:22,960 Минавам с termios структура от неговия показалеца. 899 01:16:22,960 --> 01:16:30,640 Начинът, по който това ще изглежда - I've вече забравили какво е била извикана. 900 01:16:30,640 --> 01:16:34,930 Го копирате и поставите. 901 01:16:39,150 --> 01:16:45,500 Така tcgetattr, тогава искам да премине в структурата, че аз съм спестяване на информацията в 902 01:16:45,500 --> 01:16:49,650 която ще бъде current_settings, 903 01:16:49,650 --> 01:16:59,120 и първият аргумент е файлов дескриптор за нещо, което искате да запишете атрибутите на. 904 01:16:59,120 --> 01:17:04,360 Файлов дескриптор е като всеки път, когато отворите файл, той получава файлов дескриптор. 905 01:17:04,360 --> 01:17:14,560 Когато fopen argv [1], той получава файлов дескриптор, който сте съотнасяне 906 01:17:14,560 --> 01:17:16,730 всеки път, когато искате да прочетете или да го пишете. 907 01:17:16,730 --> 01:17:19,220 Това не е файлов дескриптор Искам да използвам тук. 908 01:17:19,220 --> 01:17:21,940 Има три файлови дескриптори, които имат по подразбиране, 909 01:17:21,940 --> 01:17:24,310 , които са стандарт в стандартния изход и стандартна грешка. 910 01:17:24,310 --> 01:17:29,960 По подразбиране, мисля, че е стандарт в е 0, стандарт от 1 и стандартната грешка е 2. 911 01:17:29,960 --> 01:17:33,980 Така че това, което искам да променя настройките на? 912 01:17:33,980 --> 01:17:37,370 Искам да променя настройките на всеки път, когато удари характер, 913 01:17:37,370 --> 01:17:41,590 Искам да хвърлят този характер, вместо да ги извежда на екрана. 914 01:17:41,590 --> 01:17:45,960 Какво поток - стандарт, стандарт, или стандартна грешка - 915 01:17:45,960 --> 01:17:52,050 отговаря на неща, когато пишете на клавиатурата? >> [Ученик] Серийно инча >> Да. 916 01:17:52,050 --> 01:17:56,450 Така че може да направи 0 или мога да направя стандартния вход. 917 01:17:56,450 --> 01:17:59,380 Аз съм се current_settings на стандартен инча 918 01:17:59,380 --> 01:18:01,720 >> Сега искам да актуализира тези настройки, 919 01:18:01,720 --> 01:18:07,200 така че първо ще копирате в hacker_settings какво ми current_settings. 920 01:18:07,200 --> 01:18:10,430 И как structs работа е, че просто ще копирате. 921 01:18:10,430 --> 01:18:14,510 Това копира всички полета, както бихте очаквали. 922 01:18:14,510 --> 01:18:17,410 >> Сега искам да се актуализират някои от полетата. 923 01:18:17,410 --> 01:18:21,670 Търсите на termios, вие ще трябва да прочетете много от това 924 01:18:21,670 --> 01:18:24,110 само за да видя какво вие ще искате да търсите, 925 01:18:24,110 --> 01:18:28,210 но знамена, ти започваш да искате да погледнете за ехо, 926 01:18:28,210 --> 01:18:33,110 така ECHO входни символи Echo. 927 01:18:33,110 --> 01:18:37,710 Първо искам да настроите - I've вече забравил какво полета са. 928 01:18:45,040 --> 01:18:47,900 Това е, което структура прилича. 929 01:18:47,900 --> 01:18:51,060 Така че режимите за въвеждане Мисля, че ние искаме да променим. 930 01:18:51,060 --> 01:18:54,210 Ще разгледаме решение, за да се уверите, това е, което искаме да променим. 931 01:19:04,060 --> 01:19:12,610 Ние искаме да променим lflag за да се предотврати е необходимо да се погледне през всички тези. 932 01:19:12,610 --> 01:19:14,670 Ние искаме да променим местните режими. 933 01:19:14,670 --> 01:19:17,710 Може би трябва да прочетете цялото това нещо да се разбере, където всичко принадлежи 934 01:19:17,710 --> 01:19:19,320 че искаме да променим. 935 01:19:19,320 --> 01:19:24,120 Но това е в рамките на местните режими, където отиваме да искат да променят това. 936 01:19:27,080 --> 01:19:33,110 Така hacker_settings.cc_lmode е това, което се нарича. 937 01:19:39,630 --> 01:19:43,020 c_lflag. 938 01:19:49,060 --> 01:19:52,280 Това е мястото, където да навлезем в побитовите оператори. 939 01:19:52,280 --> 01:19:54,860 Ние си вид от времето, но ние ще отидем през него бързо. 940 01:19:54,860 --> 01:19:56,600 Това е мястото, където да навлезем в побитовите оператори, 941 01:19:56,600 --> 01:19:59,950 , където мисля, че едно и също време отдавна каза, че винаги, когато започнете да се занимават със знамена, 942 01:19:59,950 --> 01:20:03,370 ти започваш да се използва побитови оператора много. 943 01:20:03,370 --> 01:20:08,240 Всеки бит в знамето съответства на някакъв вид поведение. 944 01:20:08,240 --> 01:20:14,090 Така че тук, на този флаг има един куп различни неща, където всички от тях означава нещо различно. 945 01:20:14,090 --> 01:20:18,690 Но това, което искате да направите е да изключите малко, което съответства на ECHO. 946 01:20:18,690 --> 01:20:25,440 Така че, за да се превърне, че на разстояние правя и = ¬ ECHO. 947 01:20:25,440 --> 01:20:30,110 Всъщност мисля, че това е като Течо или нещо. Аз съм просто ще да се провери отново. 948 01:20:30,110 --> 01:20:34,050 Мога да го termios. Това е просто ехо. 949 01:20:34,050 --> 01:20:38,440 Хуманитарна помощ "ще бъде едно малко. 950 01:20:38,440 --> 01:20:44,230 ¬ Хуманитарна помощ "ще означава всички битове са 1, което означава, че всички флагове да е истина 951 01:20:44,230 --> 01:20:47,140 с изключение на за ECHO малко. 952 01:20:47,140 --> 01:20:53,830 , Като сложи край на моите местни знамена с това, това означава всички знамена, които са в момента, да е истина 953 01:20:53,830 --> 01:20:56,520 ще продължи да се определя да е истина. 954 01:20:56,520 --> 01:21:03,240 Ако ми ECHO флаг е установен да е истина, тогава това е задължително да лъжа на ГД "Хуманитарна помощ" знаме. 955 01:21:03,240 --> 01:21:07,170 Така че тази линия на код просто изключва ECHO флаг. 956 01:21:07,170 --> 01:21:16,270 Реда код, просто ще ги копирате в интерес на времето и след това да ги обясни. 957 01:21:27,810 --> 01:21:30,180 В разтвора, каза той на 0. 958 01:21:30,180 --> 01:21:33,880 Това е може би по-добре изрично да се каже, стандартния вход. 959 01:21:33,880 --> 01:21:42,100 >> Забележете, че аз също съм ECHO | посочва тук. 960 01:21:42,100 --> 01:21:46,650 Посочва се отнася до нещо отделно, което означава, каноничен режим. 961 01:21:46,650 --> 01:21:50,280 Какво каноничен режим средство е обикновено, когато пишете на командния ред, 962 01:21:50,280 --> 01:21:54,670 стандарт в не обработва нищо, докато не удари нов ред. 963 01:21:54,670 --> 01:21:58,230 Така че, когато правиш GetString, въведете куп неща, тогава ви удари нов ред. 964 01:21:58,230 --> 01:22:00,590 Това е, когато е изпратено на стандарта инча 965 01:22:00,590 --> 01:22:02,680 Това е по подразбиране. 966 01:22:02,680 --> 01:22:05,830 Когато изключите каноничен режим, сега всеки един символ, натиснете 967 01:22:05,830 --> 01:22:10,910 е това, което се обработват, което обикновено е вид лошо, защото това е бавен да обработват тези неща, 968 01:22:10,910 --> 01:22:14,330 Ето защо е добре да го буфер в цели линии. 969 01:22:14,330 --> 01:22:16,810 Но аз искам всеки един от героите, за да бъдат обработени 970 01:22:16,810 --> 01:22:18,810 тъй като аз не искам тя да ме чака да се появи нов ред 971 01:22:18,810 --> 01:22:21,280 преди да преработва всички герои съм пишете. 972 01:22:21,280 --> 01:22:24,760 Това изключва каноничен режим. 973 01:22:24,760 --> 01:22:31,320 Тези неща просто означава, че когато всъщност обработва герои. 974 01:22:31,320 --> 01:22:35,830 Това означава, че ги обработват незабавно, веднага след като съм ги пишете, да ги обработват. 975 01:22:35,830 --> 01:22:42,510 И това е функция, която се актуализиране на моите настройки за стандарт в 976 01:22:42,510 --> 01:22:45,480 и TCSA средства да го направя точно сега. 977 01:22:45,480 --> 01:22:50,310 Другите варианти са изчакате, докато всичко, което в момента е на потока се обработват. 978 01:22:50,310 --> 01:22:52,030 Това всъщност няма значение. 979 01:22:52,030 --> 01:22:56,920 Точно сега променя настройките, за да бъде, каквото е в момента hacker_typer_settings. 980 01:22:56,920 --> 01:23:02,210 Предполагам, че го нарече hacker_settings, така че нека променим това. 981 01:23:09,610 --> 01:23:13,500 Промяна всичко hacker_settings. 982 01:23:13,500 --> 01:23:16,870 >> Сега, в края на нашата програма ние ще искате да се върнете 983 01:23:16,870 --> 01:23:20,210 на това, което в момента е в рамките на normal_settings, 984 01:23:20,210 --> 01:23:26,560 която ще просто изглежда и normal_settings. 985 01:23:26,560 --> 01:23:30,650 Забележете, не са променяни по всяко от моите normal_settings, тъй като първоначално го. 986 01:23:30,650 --> 01:23:34,520 Тогава просто да си ги върнете, аз ги да премине отново в края. 987 01:23:34,520 --> 01:23:38,390 Това е актуализация. Добре. 988 01:23:38,390 --> 01:23:43,900 >> Сега вътре от тук просто ще обясни код в интерес на време. 989 01:23:43,900 --> 01:23:46,350 Това не е толкова много код. 990 01:23:50,770 --> 01:24:03,750 Ние виждаме, четем символ от файла. Нарекохме го е. 991 01:24:03,750 --> 01:24:07,850 Сега можете човек fgetc, но как fgetc ще работи 992 01:24:07,850 --> 01:24:11,910 е само, че ще се върне знака, който просто чете или EOF, 993 01:24:11,910 --> 01:24:15,680 която съответства на края на файла или някои се случва грешка. 994 01:24:15,680 --> 01:24:19,900 Ние сме примка, продължава да чете един символ от файла, 995 01:24:19,900 --> 01:24:22,420 докато не изтече от знаци, за да се чете. 996 01:24:22,420 --> 01:24:26,650 И докато правим това, ще чакаме по един символ от стандартния инча 997 01:24:26,650 --> 01:24:29,090 Всеки път, когато напишете нещо в командния ред, 998 01:24:29,090 --> 01:24:32,820 четене в герой от стандарт инча 999 01:24:32,820 --> 01:24:38,330 Тогава putchar е просто ще постави Чар четем от файла на стандартния изход. 1000 01:24:38,330 --> 01:24:42,890 Може ли човек да putchar, но това е само въвеждането на стандарта, това е печат на този характер. 1001 01:24:42,890 --> 01:24:51,600 Вие също може да направи ФОРМАТ ("в", в), същата идея. 1002 01:24:53,330 --> 01:24:56,670 Това ще направи по-голямата част от нашата работа. 1003 01:24:56,670 --> 01:25:00,300 >> Последното нещо, което започваш да искате да направите, е просто неуспешно файл. 1004 01:25:00,300 --> 01:25:03,310 Ако не неуспешно, това е изтичане на памет. 1005 01:25:03,310 --> 01:25:06,680 Ние искаме да неуспешно първоначално отвори файла, и аз мисля, че това е. 1006 01:25:06,680 --> 01:25:13,810 Ако направим това, аз вече имам проблеми. 1007 01:25:13,810 --> 01:25:17,260 Да видим. 1008 01:25:17,260 --> 01:25:19,960 Какво се оплаквате? 1009 01:25:19,960 --> 01:25:30,220 Вместо "INT", но аргумент е от тип "структура _IO_FILE * '. 1010 01:25:36,850 --> 01:25:39,370 Ще видим дали това работи. 1011 01:25:45,210 --> 01:25:53,540 Разрешено само в c99. Augh. Добре, hacker_typer. 1012 01:25:53,540 --> 01:25:57,760 Сега имаме по-полезни описания. 1013 01:25:57,760 --> 01:25:59,900 Така че използването на недекларирания идентификатор "normal_settings". 1014 01:25:59,900 --> 01:26:04,170 Не съм го наричат ​​normal_settings. Го наричат ​​current_settings. 1015 01:26:04,170 --> 01:26:12,090 Така че нека да променим всичко това. 1016 01:26:17,920 --> 01:26:21,710 Сега минава аргумент. 1017 01:26:26,290 --> 01:26:29,500 Ще направя този 0 за сега. 1018 01:26:29,500 --> 01:26:36,720 Добре. / Hacker_typer cp.c. 1019 01:26:36,720 --> 01:26:39,590 Аз също не изчистите екрана в началото. 1020 01:26:39,590 --> 01:26:42,960 Но вие можете да погледнем назад към последния набор проблем, за да видите как можете да изчистите екрана. 1021 01:26:42,960 --> 01:26:45,160 Това е просто отпечатване на някои символи 1022 01:26:45,160 --> 01:26:47,210 докато това се прави това, което искам да направя. 1023 01:26:47,210 --> 01:26:48,900 Добре. 1024 01:26:48,900 --> 01:26:55,280 И да мисля за това, защо това е необходимо да бъде 0 вместо от стандартния вход, 1025 01:26:55,280 --> 01:27:00,560 които трябва да бъдат # определят 0, 1026 01:27:00,560 --> 01:27:03,890 това се оплаква, че 1027 01:27:13,150 --> 01:27:19,360 Преди, когато казах, че има описания на файлове, но тогава вие също имате * FILE, 1028 01:27:19,360 --> 01:27:23,210 файлов дескриптор е просто едно число, 1029 01:27:23,210 --> 01:27:26,970 като има предвид, че FILE * има цял куп неща, свързани с нея. 1030 01:27:26,970 --> 01:27:30,380 Причината, поради която трябва да се каже, 0 вместо от стандартния вход 1031 01:27:30,380 --> 01:27:37,480 е, че стандартния вход е файл *, която сочи към това, което е файлов дескриптор по 0. 1032 01:27:37,480 --> 01:27:45,070 Така че дори и тук, когато правя fopen (argv [1], аз съм се FILE *. 1033 01:27:45,070 --> 01:27:51,180 Но някъде в тази FILE * е нещо, съответстваща на файлов дескриптор за този файл. 1034 01:27:51,180 --> 01:27:57,430 Ако погледнете към мъжа страница отворен, така че аз мисля, че ще трябва да направи човек 3 - няма - 1035 01:27:57,430 --> 01:27:59,380 мъж две отворени - да. 1036 01:27:59,380 --> 01:28:06,250 Ако се вгледате в страницата за открит, отворен е като по-ниско ниво fopen 1037 01:28:06,250 --> 01:28:09,350 и това е връщане действителната файлов дескриптор. 1038 01:28:09,350 --> 01:28:12,050 fopen прави куп неща на върха на отворен 1039 01:28:12,050 --> 01:28:17,640 които вместо да се завърне точно това файлов дескриптор връща цялата FILE * показалеца 1040 01:28:17,640 --> 01:28:20,590 вътрешността на която е нашата малка ЕВРОВОК файл. 1041 01:28:20,590 --> 01:28:25,020 Така стандарт се отнася до нещо, FILE *, 1042 01:28:25,020 --> 01:28:29,120 като има предвид, че 0 се отнася само стандартен файлов дескриптор в себе си. 1043 01:28:29,120 --> 01:28:32,160 >> Въпроси? 1044 01:28:32,160 --> 01:28:35,930 [Смее се] Издуха през това. 1045 01:28:35,930 --> 01:28:39,140 Добре. Свършихме. [Смее се] 1046 01:28:39,140 --> 01:28:42,000 >> [CS50.TV]