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]