1 00:00:00,000 --> 00:00:02,500 [Powered by Google Translate] [Розділ 5 - більш комфортною] 2 00:00:02,500 --> 00:00:04,690 [Rob Боуден - Гарвардський університет] 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 з приладом або ви хочете працювати в підвалі центру науки - 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 Всі ви повинні бути за замовчуванням ФАС рахунку на серверах ФАС. 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 Мій пароль просто буде моїм ФАС пароль. 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 Ви не будете мати про те, що ФАС сервера. 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 Nano, як правило, дуже проста у використанні. 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 Управління 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 У нас є Redirecting і труби, і ці три питання. 87 00:05:51,980 --> 00:05:56,070 >> На що потік у функцій, таких як Printf написати за замовчуванням? 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 Справа навіть не в джерелі 1 і 0. 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 Стандартний вихід, по потоку, це означає, що ви просто написати 1 і 0 до нього, 95 00:06:36,860 --> 00:06:40,220 , А інший кінець стандартного із просто читає дані з потоку. 96 00:06:40,220 --> 00:06:43,540 Це просто рядок 1 і 0. 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 Стандарт в це всякий раз, коли ви 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 Наприклад, скажімо, у мене, виявляється, є Dict прямо тут, 121 00:08:23,430 --> 00:08:27,020 і єдиний матеріал всередині Dict це кішки, кішки, собаки, риби, собаки. 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 Так що тепер, якщо я Ls, я подивлюся, у мене новий файл з ім'ям файлу. 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 буде мати вихід. / Привіт 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 на стандартний вивід. 178 00:13:35,080 --> 00:13:37,850 Так Printf, за замовчуванням, виводить на стандартний вивід. 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 стандартний вивід, то це в основному еквівалентна Printf. 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 Ехо бла, бла, бла, бла тільки збирається друкувати бла, бла, бла, бла. 198 00:15:16,150 --> 00:15:20,600 Раніше, коли я сказав, що я повинен був помістити Роб в текстовий файл 199 00:15:20,600 --> 00:15:28,830 тому що я можу тільки перенаправити текстові файли, а / я повторюю, якщо Rob 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 Якщо я зроблю деякі текстовий файл, 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 Це насправді друк - Давайте подивимося, чоловік туалет - переклад рядка, слова і байти. 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, тому що 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 який збирається дати вам папку під назвою section5, 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 які в будь-який час ви отримаєте сегментації, це погано. 263 00:21:00,500 --> 00:21:03,810 За яких обставин ви отримуєте сегментації? 264 00:21:03,810 --> 00:21:08,210 [Студент] разименованія нульового покажчика. >> Да. Так що це один з прикладів. 265 00:21:08,210 --> 00:21:11,580 Разименованія нульового покажчика ви збираєтеся отримати сегментації. 266 00:21:11,580 --> 00:21:16,720 Що сегментації значить, ти торкаєшся пам'яті у вас не повинно стосуватися. 267 00:21:16,720 --> 00:21:21,350 Так разименованія нульового покажчика стикається з адресою 0, 268 00:21:21,350 --> 00:21:28,060 і в основному, всі комп'ютери в даний час сказати, що адреса 0 пам'яті у вас не повинно стосуватися. 269 00:21:28,060 --> 00:21:31,920 Так ось чому разименованія нульового покажчика в результатах сегментації. 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 Потім ти торкаєшся пам'яті у вас не повинно стосуватися, і ви сегментації. 280 00:22:02,240 --> 00:22:06,370 При написанні рекурсивної функції, і це рекурсивно занадто багато разів 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 так що ви сегментації. 284 00:22:14,810 --> 00:22:17,010 Це те, що є сегментації. 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 символ * S = "привіт світ!"; 289 00:22:33,770 --> 00:22:42,310 Якщо я використовую * S = щось або з [0] = 'X'; 290 00:22:42,310 --> 00:22:47,290 так що привіт,. / привіт, чому це сегментації? 291 00:22:48,410 --> 00:22:51,250 Чому це сегментації? 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 Ви робите те, що ви не повинні робити з пам'яттю, і ви сегментації. 301 00:23:36,670 --> 00:23:45,360 Це насправді великої різниці між символ * с і символів з []. 302 00:23:45,360 --> 00:23:48,790 Таким чином, символ S [], тепер цей рядок буде покласти в стек, 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 Пам'ятайте, що коли я роблю символ * S = "привіт світ!", А сама перебуває в стеку 306 00:24:06,250 --> 00:24:10,390 але з точки абикуди ще, і що десь в іншому місці, трапляється, тільки для читання. 307 00:24:10,390 --> 00:24:15,640 Але символ S [] тільки те, в стеці. 308 00:24:17,560 --> 00:24:21,760 Так що це ще один приклад сегментації відбувається. 309 00:24:21,760 --> 00:24:27,820 >> Ми бачили, що ./buggy1 в результаті сегментації. 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-L, ми побачимо, що ядро, як правило, досить великий файл. 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 Але якщо ви типу БТ або трасування, що це буде функція 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 Вгору і вниз. До приносить вам один кадр стека, вниз приносить вам вниз стека. 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 Кадр 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] сегментації?" 352 00:27:28,800 --> 00:27:38,830 Друк Давайте ARGV [1], і, схоже, це 0x0, який є нульовим покажчиком. 353 00:27:38,830 --> 00:27:44,750 Ми strcmping CS50 порід і нульові, і так, що збирається падати. 354 00:27:44,750 --> 00:27:48,280 І чому ARGV [1] NULL? 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], так що збирається падати. 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 \ скелі і Ви отримаєте! 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 збирається сегментації знову. 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 яка є сигналу сегментації, і це, де це сталося трапитися. 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 Аргумент витончений і Бінки була 1. 381 00:29:34,680 --> 00:29:44,390 Якщо ми перерахуємо функції oh_no, ми бачимо, що oh_no просто робить символ ** и = NULL; 382 00:29:44,390 --> 00:29:47,410 * S = "БУМ"; 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 Це з порожньою, так * з в разименованія нульового покажчика, 389 00:30:21,430 --> 00:30:24,800 і так це буде крах. 390 00:30:24,800 --> 00:30:27,540 Це один з найшвидших способів можливо, ви можете падати. 391 00:30:27,540 --> 00:30:31,300 Це просто оголосивши нульовий покажчик і відразу ж помилку сегментації. 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 І ми знаємо, я = 1, тому що ми трапиться побачити тут 403 00:31:18,700 --> 00:31:22,560 що витончений був викликаний з аргументом 1. 404 00:31:22,560 --> 00:31:27,560 Або ви можете просто роздрукувати я, і вона буде сказати, що я 1. 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 Ми знаємо, що я був 1, так званий витончений. 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 Натискання наступний, тепер я був установлений в RAND ()% 3, так що ми можемо надрукувати значення я, 421 00:32:51,800 --> 00:32:55,280 і воно буде сказати, що я 1. 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 Прямо тут, на цій лінії, я був в якому він сказав RAND ()% 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 Перший рядок коду буде говорити тоді, коли (я == 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 Якщо ви тільки подивіться на цих ліній безпосередньо, можна подумати, якщо (я == 0), 442 00:34:07,380 --> 00:34:10,800 Добре, тоді я зробив крок, і тепер я у витончений (I), 443 00:34:10,800 --> 00:34:14,120 Ви думаєте, що повинно означати = 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 який буде встановлений символ ** S = NULL, щоб і відразу "БУМ". 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 Якщо я 1, виклик 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 Хто-небудь см. спосіб зробити це програми, які не будуть падати? 459 00:35:30,030 --> 00:35:37,530 Тому що якщо я щось відсутній, якщо я 0, ви відразу сегментації, 460 00:35:37,530 --> 00:35:41,250 ще ви йдете в функції якого, якщо я це 1 Ви сегментації, 461 00:35:41,250 --> 00:35:44,540 ще ви йдете в функції якої, якщо я це 2 ви сегментації. 462 00:35:44,540 --> 00:35:46,810 Так що не має значення, що ви робите, ви сегментації. 463 00:35:46,810 --> 00:35:52,380 >> Я думаю, один із способів фіксації було б замість того, щоб робити символ ** и = NULL, 464 00:35:52,380 --> 00:35:55,610 Ви можете Malloc простору для цього рядка. 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 Подивіться на тип с. Давайте додамо 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 (Char *)); 476 00:37:06,170 --> 00:37:12,840 Це буде виділити місце для покажчика, який вказує на «БУМ». 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 із символів * х = "БУМ". 480 00:37:20,870 --> 00:37:27,950 "БУМ" вже існує. Це відбувається існувати в доступному тільки для читання область пам'яті. 481 00:37:27,950 --> 00:37:35,200 Але він вже існує, а значить цей рядок коду, якщо їй це символ **, 482 00:37:35,200 --> 00:37:43,900 Потім * S є символ * і ви встановлюєте цей символ *, щоб вказати на "БУМ". 483 00:37:43,900 --> 00:37:50,040 Якби я хотів, щоб скопіювати "БУМ" в с, то я мав би виділити місце для с. 484 00:37:55,170 --> 00:38:03,900 Я зроблю * S = Танос (SizeOf (Char) * 5); 485 00:38:03,900 --> 00:38:06,210 Чому 5? 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 [Студент] КПЮ? >> ЗЬгсру. 490 00:38:28,520 --> 00:38:32,700 Людина зЬгсру. 491 00:38:36,120 --> 00:38:39,590 Так зЬгсру або з'гпсру. 492 00:38:39,590 --> 00:38:43,410 з'гпсру трохи безпечніше, оскільки ви можете точно вказати, скільки символів, 493 00:38:43,410 --> 00:38:46,190 але тут це не має значення, тому що ми знаємо. 494 00:38:46,190 --> 00:38:50,340 Так зЬгсру і подивитися в аргументах. 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 Ми збираємося копіювати в нашій призначення * з покажчиком «БУМ». 498 00:39:10,310 --> 00:39:19,820 Чому може ви хочете зробити це з зЬгсру, а не тільки те, що ми мали до 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 Тепер я можу зробити щось подібне S [0] = 'X'; 503 00:39:37,950 --> 00:39:48,190 тому що з точки до купи, і що місця на купі, а вказує на 504 00:39:48,190 --> 00:39:52,320 є покажчиком на більший простір в купі, яка зберігає "БУМ". 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 і другий примірник «БУМ», зЬгсру створив копію "БУМ". 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 збирається дозволити вам змінити значення "БУМ". 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 Ми просто запустіть його і ми бачимо, ми отримуємо сегментації. 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; ЕдеЬз цей матеріал не одно 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 , Що, коли ви отримуєте сегментації, буде дійсно загадкові імена функцій 524 00:41:15,350 --> 00:41:18,090 як це _IO_fgets. 525 00:41:18,090 --> 00:41:21,770 Але це буде ставитися до цього виклику ЕдеЬз. 526 00:41:21,770 --> 00:41:25,850 Десь усередині тут, ми помилку сегментації. 527 00:41:25,850 --> 00:41:30,340 Якщо ми подивимося на аргументи ЕдеЬз, ми можемо надрукувати буфер. 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 Буфер масив символів. Це масив символів 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 Файл типу FILE *, так що це покажчик, 545 00:43:22,610 --> 00:43:26,610 і значення цього покажчика є нульовим. 546 00:43:26,610 --> 00:43:33,240 Так ЕдеЬз буде намагатися читати з цього покажчика, непрямим чином, 547 00:43:33,240 --> 00:43:37,320 але для того, щоб отримати доступ до цього покажчику, вона повинна разименовать його. 548 00:43:37,320 --> 00:43:40,550 Або для того, щоб отримати доступ до якою вона має бути спрямована на це разименовивает його. 549 00:43:40,550 --> 00:43:43,810 Так що це разименованія нульового покажчика та сегментації. 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 і тоді я відразу потрапляють в нашу лінію, де колись я вдарив інший, він збирається падати. 556 00:44:11,140 --> 00:44:16,880 Хто-небудь хоче викинути з причин, чому ми могли б помилку сегментації? 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 Коли ми Еореп файлу для читання, то ми повинні сказати, 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 Ви завжди повинні перевірити, якщо Еореп повертає NULL. 571 00:45:33,870 --> 00:45:38,170 Ви завжди повинні перевірити, щоб переконатися, що Танос не повертає NULL, 572 00:45:38,170 --> 00:45:41,410 , Інакше ви сегментації. 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 Потім ви можете використовувати п використовувати наступну замість того, щоб вводити наступний всю дорогу. 581 00:46:29,020 --> 00:46:33,730 І тепер, коли я потрапив п раз, то я можу просто натиснути Enter, щоб продовжувати йти наступна 582 00:46:33,730 --> 00:46:36,640 замість того, щоб ударити п Enter, Enter п, п Enter. 583 00:46:36,640 --> 00:46:44,630 Схоже, що я перебуваю в якійсь цикл, що сидить масив [я] = 0. 584 00:46:44,630 --> 00:46:50,510 Схоже, я ніколи не вирватися з цього циклу. 585 00:46:50,510 --> 00:46:54,780 Якщо я друкую я, так що я = 2, то я буду йти далі. 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, ми бачимо все, що відбувається, цілочисельний масив [5]; 599 00:48:22,220 --> 00:48:26,200 для (я = 0; I <= 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, і це з 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 Так чи інакше, цей рядок коду викликає нашу Int я повинен бути встановлений на 0. 618 00:50:16,730 --> 00:50:23,130 [Студент] Може бути, тому що це перевизначення пам'ять про цю частину я 619 00:50:23,130 --> 00:50:27,970 , Коли він думає, що це черговий елемент масиву? >> [Боуден] Так. 620 00:50:27,970 --> 00:50:33,880 Коли ми збираємося за межами нашого масиву, 621 00:50:33,880 --> 00:50:39,870 якимось чином, що простір, який ми перевизначення перевизначає значення я. 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 я оголошений перший, який означає, що я отримує деякий простір в стеці. 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 При індекс в масиві, ми гарантували, що 0-я позиція в масиві 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 Тоді ми виділяємо наш масив з 5 цілих чисел, яке означає, що під цим, 646 00:53:06,420 --> 00:53:11,230 Оскільки стек росте вниз, ці 5 чисел отримати виділені. 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 Ці роду помилки? Не використовуйте C в якості мови програмування. 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 [Боуден] Ось де речі починають відбувається не так. >> [Студент] О, все в порядку. 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 Вона не робить ніяких перевірок, що о-о, це насправді не 1000 речей в ньому. 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 [Студент] і тому повинні ми змінили <= просто > [Боуден] Так. 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 [Боуден] Як і те, що масив? 689 00:56:20,000 --> 00:56:24,930 Масив саме по собі є символом. 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 Коли я роблю щось подібне Е ("% п \ п", масив); 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 "Масив" масив, оголошений тут. 699 00:57:20,820 --> 00:57:23,200 О, тут. 700 00:57:23,200 --> 00:57:31,250 Clang розумний, і це відбувається зауважити, що я оголосив масив на 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 Ось тільки Clang лукавить. 708 00:57:59,430 --> 00:58:03,340 >> Але тепер зробити buggy4. Так що ж я роблю не так? 709 00:58:03,340 --> 00:58:05,970 Неявне оголошення бібліотечну функцію "Printf. 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 Масив себе, як покажчик, але це не фактичний покажчик, 716 00:58:41,820 --> 00:58:45,410 З регулярними покажчик ми можемо змінити. 717 00:58:45,410 --> 00:58:54,700 Масив просто деяка константа. 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 Якщо Clang розумний, він буде кричати на мене з місця в кар'єр. 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 [Боуден] Це ніде не зберігаються. Це коли це компіляція. 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 Е ("% г \ п", 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 Це Clang лукавить знову. 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 Clang, коли проходить через цю функцію, він бачить масив 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 *, це 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 [Боуден] Як це? >> [Студент] Так. Чи можете ви змінити масив всередині функції зараз? 776 01:04:14,250 --> 01:04:18,420 [Боуден] Ви можете змінити масив в обох випадках. 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 [Боуден] Ох. Так. У будь-якому випадку - >> [студент] Так. 780 01:04:30,230 --> 01:04:38,410 [Боуден] відмінність між масиву [] і 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 Масив просто не існує. 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 але цілочисельний масив [5] печатку SizeOf (масиву) в друк 20. 821 01:08:04,110 --> 01:08:07,480 [Студент] Так Int масиву [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 Ми хочемо, щоб я <5. >> [Студент] Добре. 825 01:08:20,880 --> 01:08:25,569 [Боуден], а потім, як тільки ви починаєте проходить у функціях, 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 Але P [0] = 1; таке ж, як кажуть масив [0] = 1; 830 01:08:49,810 --> 01:08:55,600 І як тільки ми говоримо, Foo (масив), або Foo (р); 831 01:08:55,600 --> 01:08:59,760 Усередині функції Фу, це ж виклик у два рази. 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 >> Ми постараємося, щоб пройти через цю програму Typer Hacker, 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 Дивлячись на це, він каже, щоб включити ці 2 файли, так що ми будемо робити. 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 одно це. >> [Боуден] Так. 859 01:11:56,480 --> 01:12:21,250 Так що, якщо (ARGC = 2!) Е ("Використання:% S [файл, щоб відкрити]"). 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 Так Еореп. Що Еореп виглядати? 867 01:13:15,010 --> 01:13:22,980 [Студент] Ім'я файлу. >> [Боуден] Ім'я файлу буде ARGV [1]. 868 01:13:22,980 --> 01:13:26,110 [Студент] І те, що ви хочете з ним робити, тому - >> [Боуден] Так. 869 01:13:26,110 --> 01:13:28,740 Так що, якщо ви не пам'ятаєте, ви просто могли б зробити людина Еореп, 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 п і те, що ви можете використовувати, щоб цикл через пошук збігів. 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 Таким чином, г, Відкрити текстовий файл для читання. Ось що ми хочемо зробити. 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. >> [Боуден] Так. 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 Ми бачимо, що у нас є ця tcsetattr Int, Int tcgetattr. 898 01:16:15,810 --> 01:16:22,960 Я проходжу в termios структури його покажчик. 899 01:16:22,960 --> 01:16:30,640 Як це буде виглядати це - ДИСК вже забули, що таке функція була викликана. 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 Коли я Еореп 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 І як структури роботи він буде просто скопіювати. 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 Спочатку я хочу задати - ДИСК вже забули, що таке полів. 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 Але те, що я хочу зробити, це просто вимкнути біт, який відповідає луна. 946 01:20:18,690 --> 01:20:25,440 Таким чином, щоб відключити цю функцію я і = ¬ ECHO. 947 01:20:25,440 --> 01:20:30,110 Насправді, я думаю, що це як Techo або щось. Я просто хочу, щоб перевірити ще раз. 948 01:20:30,110 --> 01:20:34,050 Я можу termios його. Це просто відлуння. 949 01:20:34,050 --> 01:20:38,440 ECHO буде один біт. 950 01:20:38,440 --> 01:20:44,230 ¬ ECHO буде означати всі біти встановлені в 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 прапор встановлено в істинне, то це обов'язково має значення ЛОЖЬ на 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 | ICANON тут. 960 01:21:42,100 --> 01:21:46,650 ICANON посилається на щось окреме, що означає канонічному режимі. 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 Тоді ріЬспаг тільки збирається поставити символ читаємо тут з файлу в стандартний вивід. 1000 01:24:38,330 --> 01:24:42,890 Ви можете ріЬспаг людина, але це просто покласти на стандартний вивід, це друк цього символу. 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 >> Останнє, що ми збираємося потрібно зробити, це просто Fclose наш файл. 1004 01:25:00,300 --> 01:25:03,310 Якщо ви не Fclose, що це витік пам'яті. 1005 01:25:03,310 --> 01:25:06,680 Ми хочемо, щоб Fclose файл, який ми спочатку відкрито, і я думаю, що це вона. 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 Раніше, коли я сказав, що є дескрипторів файлів, але тоді у вас також є файл * 1028 01:27:19,360 --> 01:27:23,210 дескриптор файлу знаходиться всього в одне ціле, 1029 01:27:23,210 --> 01:27:26,970 в той час як файл * має цілу купу речей, пов'язаних з ним. 1030 01:27:26,970 --> 01:27:30,380 Тому ми повинні сказати 0 замість стандартного вводу 1031 01:27:30,380 --> 01:27:37,480 є те, що стандартний ввід є FILE *, який вказує на те, що посилається дескриптор 0. 1032 01:27:37,480 --> 01:27:45,070 Так що навіть тут, коли я роблю Еореп (ARGV [1], я отримую файл * назад. 1033 01:27:45,070 --> 01:27:51,180 Але десь у файлі * річ відповідний дескриптор для цього файлу. 1034 01:27:51,180 --> 01:27:57,430 Якщо ви подивитеся на довідковій сторінці для відкритої, так що я думаю, що ви повинні зробити людині відкриті 3 - Нету - 1035 01:27:57,430 --> 01:27:59,380 Людина 2 відкритих - так. 1036 01:27:59,380 --> 01:28:06,250 Якщо ви подивитеся на сторінку відкритою, відкритою, як більш низького рівня Еореп, 1037 01:28:06,250 --> 01:28:09,350 і він повертається фактичне дескриптор файлу. 1038 01:28:09,350 --> 01:28:12,050 Еореп робить купу речей на верхній відкритій, 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]