[Powered by Google Translate] [Обзор] [Викторина 0] [Lexi Росс, Томми MacWilliam, Лукас Фрейтас, Иосиф Ong] [Harvard University] [Это CS50.] [CS50.TV] Привет, всем. Добро пожаловать на рассмотрение сессии Викторина 0, которое проходит в среду. Что мы собираемся делать сегодня вечером, я с 3 другими ТФ, и вместе мы собираемся пройти через обзор того, что мы сделали в ходе сих пор. Это не собирается быть на 100% всеобъемлющей, но она должна дать вам более полное представление о том, что у вас уже есть вниз и то, что вы все еще нужно изучить, прежде чем в среду. И не стесняйтесь поднимать руку с вопросами, когда мы собираемся вместе, но имейте в виду, что мы будем иметь немного времени в конце- если мы пройдем с нескольких минут, чтобы запасных, чтобы сделать общие вопросы, так что имейте это в виду, и поэтому мы собираемся начать в начале недели с 0. [Викторина 0 Обзор] [Часть 0] [Lexi Ross] Но прежде чем мы это сделаем, давайте поговорим о материально-техническое обеспечение викторины. [Логистика] [викторины состоится в среду 10/10 вместо лекции] [(См. http://cdn.cs50.net/2012/fall/quizzes/0/about0.pdf подробности)] Это в среду, 10 октября. Вот в эту среду, и если вы идете на этот адрес здесь, который также доступен из CS50.net-Там ссылка на него- Вы можете увидеть информацию о том, куда пойти на основе Вашу фамилию или школу принадлежности, а также он говорит именно о том, что тест будет охватывать и типов вопросов, что вы собираетесь получить. Имейте в виду, что вы также будете иметь возможность просмотреть на викторину в разделе так что ваши ТФ должны идти на некоторые практики проблемы, и это еще один хороший шанс, чтобы увидеть, где вы все еще нужно изучить для викторины. Давайте начнем с самого начала с Б-н-бит. Помните, чуть только 0 или 1, и байт представляет собой набор из 8 этих битов. Давайте посмотрим на эту коллекцию битов прямо здесь. Мы должны быть в состоянии выяснить, сколько бит есть. Где мы рассчитываем есть только 8 из них восемь 0 или 1 шт. А так как есть 8 бит, это 1 байт, и давайте преобразовать его в шестнадцатеричный. Шестнадцатеричные является основанием 16, и это довольно легко преобразовать Число в двоичной системе, которая является, что это такое, и их число в шестнадцатеричное. Все что мы делаем, мы смотрим на группы по 4, и мы конвертировать их в соответствующий шестнадцатеричный. Начнем с самой правой группе 4, поэтому 0011. Это будет одна 1 и одна 2, так вместе, что делает 3. А потом давайте посмотрим на другой блок 4. 1101. Это будет одна 1, одна 4, и один 8. Вместе что это будет 13, что делает D. И мы будем помнить, что в шестнадцатеричной мы не просто идти от 0 до 9. Мы идем от 0 до F, так что после 9, 10 соответствует, От 11 до B, и так далее, где F 15. Здесь 13 представляет собой D, так, чтобы преобразовать его в десятичное все что мы делаем, мы на самом деле относиться друг к позиции силы 2. Это одна 1, одна 2, нулевой 4s, 8s нуля, одной 16, и так далее, и это немного трудно вычислить в вашей голове, но если мы идем к следующему слайду мы видим, ответ на этот вопрос. По сути, мы собираемся напротив право вернуться к левым, и мы умножая каждую цифру соответствующей степенью 2. И помните, для шестнадцатеричных обозначить эти цифры с 0x в начале поэтому мы не путайте его с десятичное число. Продолжая, это ASCII таблицы, и то, что мы используем для ASCII является преобразование из символов в числовые значения. Помните, в PSET криптографии мы широко использовали ASCII таблицы Для использования различных методов криптографии, Цезарь и шифр Виженера, конвертировать различные буквы В строку в соответствии с ключевыми задается пользователем. Давайте посмотрим на немного ASCII математике. Глядя на 'P' + 1, в символьной форме, которая была бы Q, и помните, что '5 '≠ 5. И как бы мы точно конвертировать между этими 2 формы? Это на самом деле не слишком трудно. Для того, чтобы получить 5 мы вычитаем '0 ' потому что есть 5 мест между '0 'и '5. Для того, чтобы пойти по другому пути, мы просто добавим 0, так что это вроде как регулярные арифметика. Только помните, что, когда что-то кавычки, это характер и, следовательно, соответствует значению в таблице ASCII. Перемещение в более общие темы по информатике. Мы узнали, что такое алгоритм и как мы используем программированию для реализации алгоритмов. Некоторые примеры алгоритмов нечто простое, как проверки, является ли число четным или нечетным. Для этого помните, что мы мода число на 2 и проверить, если результат равен 0. Если это так, то это еще. Если нет, то это странно. И это пример действительно основной алгоритм. Немного сложнее один бинарный поиск, которые мы рассмотрим позже в обзоре сессии. И программировании термин, который мы используем для принятия алгоритма и преобразование его в код, компьютер может читать. 2 примера программирования Scratch, что мы и сделали в неделю 0. Даже если мы на самом деле не впечатать код это способ реализации Этот алгоритм, который печатает номера 1-10, и здесь мы сделать то же самое на языке программирования Си. Эти функционально эквивалентны, только что написанные на разных языках или синтаксиса. Затем мы узнали о логических выражений, и логическое является значение, которое либо истинно, либо ложно, и здесь часто логические выражения Заходим внутрь условиях, так что если (х ≤ 5), Ну, мы уже установлены х = 5, так что условие будет оценить, верно. И если это правда, что код под условие будет оцениваться с помощью компьютера, так что строка будет печататься на стандартный вывод, а термин условие относится к тому, что находится внутри скобки, если заявление. Помните, что все операторы. Помните, что это && и | |, когда мы пытаемся объединить 2 или более условий, Не == = проверить 2 вещи равны. Помните, что = для назначения в то время как == это логический оператор. ≤, ≥, а затем окончательный 2 говорят сами за себя. Общий обзор булевой логики здесь. И логические выражения также являются важными в петлях, которые мы рассмотрим сейчас. Мы узнали о 3 вида петель до сих пор в CS50, ибо, в то время как, и сделать в то время. И это важно знать, что в то время как для большинства целей мы действительно можем использовать любой тип цикла в целом Есть определенные типы целей или общих закономерностей в программировании, что конкретный призыв к одному из этих петель , которые делают его наиболее эффективным и элегантным, чтобы закодировать его таким образом. Давайте посмотрим, что каждая из этих петель, как правило, используется для наиболее часто. В цикл мы в целом уже знаю, сколько раз мы хотим перебрать. Это то, что мы вкладываем в состоянии. Ибо, я = 0, <10, например. Мы уже знаем, что мы хотим сделать что-то в 10 раз. Теперь, в то время как цикл, как правило, мы не обязательно знаю, сколько раз мы хотим, чтобы петля для запуска. Но мы знаем, своего рода условие, что мы хотим, чтобы Всегда быть истинным или ложным всегда. Например, в то время установлена. Давайте говорить, что это логическая переменная. Хотя это правда, мы хотим, чтобы код, чтобы оценить, так что немного более расширяемой, немного более общее, чем цикл, но любой цикл может быть преобразовано в то время как петля. И, наконец, делать, пока петли, которая может быть самая сложная понять сразу, часто используется, когда мы хотим оценить Сначала код Перед Впервые мы проверяем состояние. Общий случай использования делать во время цикла когда вы хотите получить пользовательский ввод, и вы знаете, вы хотите спросить пользователя для ввода крайней мере один раз, но если они не дают вам хорошие входные сразу Вы хотите продолжать просить их, пока они дают вам хороший вход. Это самый распространенный способ использования этого время цикла, и давайте посмотрим на реальную структуру этих петель. Как правило, они всегда стремятся следовать этим паттернам. На цикл внутри вас есть 3 компонента: инициализации, как правило, что-то вроде Int я = 0, где я есть счетчик, состояние, в котором мы хотим сказать, запустить этот цикл, пока это условие остается в силе, как я <10, и, наконец, обновление, который является, как мы увеличиваем переменная счетчика в каждой точке цикла. Обычная вещь, чтобы видеть, что есть только я + +, что означает увеличивать я на 1 каждый раз. Вы также можете сделать что-то вроде я + = 2, что означает, добавьте 2 к я каждый раз вы идете через петлю. И тогда сделать это только относится к любой код, который фактически работает как часть цикла. И на некоторое время цикла, на этот раз у нас действительно есть инициализация вне цикла, Так, например, предположим, что мы пытаемся сделать то же самое тип цикла, как я только что описал. Мы хотели бы сказать Int = 0 перед началом цикла. Тогда мы могли бы сказать, когда я <10 этого так же блок кода, как и прежде, и на этот раз обновление части кода, например, я + +, на самом деле происходит внутри цикла. И, наконец, в то время как делать, это похоже на время цикла, но мы должны помнить, что код будет оценивать раза Перед условие проверяется, поэтому он делает намного больше смысла если вы посмотрите на нее в порядке сверху вниз. В то время как цикл сделать код оценивает прежде, чем вы даже смотреть на это время условия, в то время как время цикла, она проверяет в первую очередь. Заявления и переменные. Когда мы хотим создать новую переменную, мы сначала хотим инициализировать его. Например, внутр бар инициализирует переменную бар, но это не дает ей значение, так что значение баре сейчас? Мы не знаем. Это может быть какая-то фигня значение, которое хранится в памяти там, и мы не хотим использовать эту переменную пока мы фактически не дать ему значения, таким образом, мы объявим его здесь. Затем мы инициализируем, что это будет 42 ниже. Сейчас, конечно, мы знаем, что это может быть сделано на одной линии, внутр бар = 42. Но Просто чтобы быть ясно нескольких шагов, что происходит, Декларация и инициализация происходит раздельно. Это происходит на один шаг, и следующий, внутр Баз = бар + 1, это утверждение ниже, которое увеличивает Баз, так что в конце этого блока кода если бы мы были на печать значение Баз было бы 44 потому что мы объявить и инициализировать, что это будет 1> бара, и тогда мы увеличиваем его еще раз с + +. Мы пошли на это довольно кратко, но это хорошо, чтобы иметь общее понимание того, что темы и события. В основном мы сделали это в Scratch, так что вы можете думать о темы, как несколько последовательностей кода работает в то же время. На самом деле, это, вероятно, не работает, в то же время, а как бы абстрактно мы можем думать об этом таким образом. В Scratch, например, у нас было несколько спрайтов. Это может быть выполнение другого кода, в то же время. Можно было ходить, а другой говорит что-то В другой части экрана. События еще один способ выделения логики между различными элементами кода, и царапинам, мы смогли смоделировать события с помощью трансляции, и что на самом деле, когда я получаю, а не когда я слышу, но по сути это способ передачи информации от одного спрайта на другой. Например, вы можете передать игру на себя, и когда другой спрайт получает за игру, он реагирует определенным образом. Это важная модель для понимания программирования. Просто перейти на основную неделя 0, то, что мы перешли до сих пор, давайте посмотрим на этот простой программы на Си. Текст может быть немного небольшим отсюда, но я пойду на это очень быстро. Мы в том числе 2 файлы заголовков в верхней части, cs50.h и stdio.h. Мы тогда определении постоянной называется пределом в 100. Мы тогда осуществлении нашей главной функции. Так как мы не будем использовать аргументы командной строки здесь мы должны поставить недействительными в качестве аргументов для основного. Мы видим Int выше основного. Это тип возвращаемого значения, поэтому возвращать 0 в нижней части. И мы используем CS50 функции библиотеки получают Int спросить пользователя для входа, и мы храним его в этой переменной х, таким образом, мы заявляем х выше, и мы инициализировать его с х = GetInt. Затем мы проверяем, если пользователь дал нам хороший вход. Если это ≥ LIMIT мы хотим вернуть код ошибки 1 и печатать сообщение об ошибке. И, наконец, если пользователь дал нам хороший вход мы собираемся возвести в квадрат числа и распечатать этот результат. Просто чтобы убедиться, что те все хит домой Вы можете видеть этикетки различных частей кода здесь. Я упоминал постоянно, файлы заголовков. О, Int х. Убедитесь в том, помните, что это локальная переменная. Это контрастирует его от глобальных переменных, которые мы будем говорить о Чуть позже в обзоре сессии и мы призываем библиотечные функции Printf, так что, если бы мы не включили заголовочный файл stdio.h мы не были бы в состоянии назвать Printf. И я считаю, что стрелка, которая получила отрезать здесь указывает на% D, которая является форматирования строки в Printf. Он говорит, распечатайте эту переменную как число,% D. И это все за неделю 0. Теперь Лукас намерен продолжать. Эй, ребята. Меня зовут Лукас. Я на втором курсе в лучшем доме на территории кампуса, Mather, и я хочу поговорить немного о неделя 1 и 2,1. [Неделя 1 и 2,1!] [Лукас Фрейтас] Как Lexi говорил, когда мы начали переводить код с нуля C одна из вещей, которые мы заметили, что вы не можете просто написать свой код и запустить его с помощью зеленого флага больше. На самом деле, вы должны использовать некоторые шаги, чтобы сделать вашу программу C стали исполняемый файл. В основном, что вы делаете, когда вы пишете программы является то, что Вы переводите ваши идеи на язык, компилятор может понять, поэтому, когда вы пишете программу в C что вы делаете на самом деле что-то писал, что компилятор будет понимать, , а затем компилятор собирается перевести этот код в то, что ваш компьютер будет понимать. А дело в том, компьютер на самом деле очень глупо. Ваш компьютер может понять только 0 и 1, так на самом деле в первые компьютеры обычно люди запрограммированы использование 0 и 1, но не больше, слава Богу. Мы не нужно запоминать последовательности 0 и 1 за цикл или цикл, пока и так далее. Вот почему у нас есть компилятор. Какой компилятор делает это в основном переводит код C, В нашем случае, к языку, что ваш компьютер будет понимать, которая является объектный код, а компилятор, который мы используем называется звон, так что это на самом деле символ лязг. Если у вас есть программа, что вам нужно сделать 2 вещи. Во-первых, вы должны компилировать вашу программу, а затем вы собираетесь запустить программу. Для компиляции программы у вас есть много вариантов, чтобы сделать это. Первый делать лязг program.c В какой программе это название вашей программы. В этом случае вы можете видеть, что они просто говорят: "Эй, компиляции моей программы". Вы не говорите "я хочу это название для моей программы", или ничего. Второй вариант дает название вашей программы. Можно сказать, лязг-O, а затем имя, которое вы хотите исполняемый файл будет называться, как и program.c. И вы также можете сделать сделать программу, и посмотреть, как в первых 2-х случаях Я ставлю. С, а в третьем у меня только программы? Да, вы на самом деле не стоит ставить. С, когда вы используете сделать. В противном случае компилятор на самом деле происходит, чтобы кричать на вас. А также, я не знаю, если вы, ребята, помните, но много раз мы также использовали lcs50-или-лм. Это называется связей. Он просто сообщает компилятору, что вы будете использовать эти библиотеки тут же, так что если вы хотите использовать cs50.h вы на самом деле должны ввести лязг program.c-lcs50. Если вы не сделаете этого, компилятор не будет знать, что вы используете эти функции в cs50.h. И когда вы хотите запустить вашу программу у вас есть 2 варианта. Если вы сделали лязг program.c Вы не дать название вашей программы. Вы должны запустить его с помощью. / A.out. A.out является стандартным именем, лязг дает вашей программе, если вы не даете ему имя. В противном случае вы собираетесь делать. / Программа, если вы дали название вашей программы, а также, если вы делали программу имя, которое программа будет получить уже будет запрограммирован тем же именем, что и файл с. Тогда мы говорили о типах данных и данных. Основном типов данных одни и те же вещи, как маленькие коробочки они используют для хранения значений, так что типы данных на самом деле так же, как покемонов. Они бывают разных размеров и типов. Я не знаю, что аналогия имеет смысл. Размер данных на самом деле зависит от архитектуры машины. Все данные размеров, что я собираюсь показать здесь на самом деле для 32-битных машин, которые в случае нашего прибора, Но если вы на самом деле кодирования вашего Mac или Windows, в также вероятно, вы будете иметь 64-разрядные машины, так что не забудьте, что данные размеры, которые я собираюсь показать здесь предназначены для 32-разрядных машин. Первое, что мы увидели, было INT, который является довольно простым. Вы можете использовать Int для хранения целого числа. Мы также видели символ, символ. Если вы хотите использовать буквы или символа мало вы, вероятно, будете использовать символ. Символ имеет 1 байт, что означает 8 бит, как сказала Лекси. В основном мы должны ASCII таблицы, что имеет 256 возможные комбинации 0 и 1, , а затем, когда вы вводите символ он собирается переводить символ, который вы входов номер, который вы имеете в ASCII таблице, как Лекси сказала. У нас также есть поплавок, который мы используем для хранения десятичных чисел. Если вы хотите выбрать 3.14, например, вы собираетесь использовать поплавок или двойной, который имеет больше точности. Поплавок имеет 4 байт. Двойное имеет 8 байт, поэтому разница только в том точностью. У нас также есть длинный, который используется для целых чисел, и вы можете видеть на 32-битной машине Int и длинный имеют одинаковый размер, таким образом, это действительно не имеет смысла использовать длинный в 32-битной машине. Но если вы используете Mac и 64-разрядных машин, на самом деле давно имеет размер 8, так что это действительно зависит от архитектуры. Для 32-битной машине он не имеет смысла использовать длинный действительности. А потом долго долго, с другой стороны, имеет 8 байт, так что это очень хорошо, если вы хотите иметь больше целого. И, наконец, у нас есть строка, которая является на самом деле символ *, , который является указателем на символ. Это очень легко думать, что размер строки будет, как Количество символов, которые у вас там, но на самом деле символ * сама имеет размер указателя на символ, который составляет 4 байта. Размер символ * 4 байта. Это не имеет значения, если у вас есть небольшой словом или письмом или ничего. Это будет 4 байт. Мы также узнали немного о литья, так как вы можете видеть, если у вас, например, программу, которая говорит Int х = 3, а затем Е ("% D", х / 2) вы, ребята, знаете, что он собирается печатать на экране? Кто-то? >> [Студенты] 2. 1. >> 1, да. Когда вы делаете 3/2 он собирается получить 1,5, но так как мы используем целое она собирается игнорировать дробной части, и вы будете иметь 1. Если вы не хотите, чтобы это случилось, что вы можете сделать, например, это объявить поплавок у = х. Тогда х, что раньше было 3, теперь будет 3,000 в год. И тогда вы можете печатать у / 2. На самом деле, я должен иметь 2. там. Он собирается сделать 3.00/2.00, и вы будете получать 1,5. А у нас это 0,2 F просто спрашивать 2 десятичных единиц в десятичной части. Если у вас есть 0,3 F, что это будет иметь на самом деле 1.500. Если это 2 это будет 1,50. У нас также есть это в данном случае. Если вы поплавок х = 3,14, и тогда вы Printf х Вы собираетесь получить 3,14. И если вы делаете х = Int х, , что означает лечение х в виде целого числа и печати х сейчас Вы будете иметь 3,00. Имеет ли это смысл? Потому что вы первый лечении х как целое, так что вы не обращая внимания на дробную часть, а затем вы печатаете х. И, наконец, вы также можете сделать это, Int х = 65, а затем объявить символ с = х, а затем, если вы печатаете с вы на самом деле собираетесь получить , Поэтому в основном то, что вы здесь делаете переводит целое число в символ, как ASCII таблице делает. Мы также говорили о математике операторов. Большинство из них довольно просты, поэтому +, -, *, /, а также мы говорили о моде, которая является остаток от деления 2-х номеров. Если у вас есть 10% 3, например, это означает, разделите 10 на 3, а что остальные? Это будет 1, так что это на самом деле очень полезно для многих программ. Для Виженера и Цезаря я уверен, что все вы, ребята использовали мод. О математические операторы, будьте очень осторожны при комбинировании * и /. Например, если вы делаете (3/2) * 2, что вы собираетесь получить? [Студенты] 2. Да, 2, так как 3/2 будет 1,5, но так как вы делаете операции между 2 целых чисел на самом деле вы только собираетесь считать 1, и 1 * 2 будет 2, так что будьте очень, очень осторожны когда делать арифметические действия с целыми числами, потому что Вы могли бы получить, что 2 = 3, в этом случае. А также быть очень осторожным приоритет. Вы должны обычно использовать скобки, чтобы быть уверенным, что вы знаете, что вы делаете. Некоторые полезные ярлыки, конечно, один я + + или я + = 1 или с помощью + =. Это то же самое, что делал I = I + 1. Вы также можете сделать я - или я - = 1, что то же самое, что и I = -1, что-то вы, ребята используют много в циклы, по крайней мере. Кроме того, для *, если вы используете * = и, если вы, например, я * = 2, то же самое, говоря, что я = I * 2, и то же самое для деления. Если у вас в / = 2 это то же самое, что я = я / 2. Теперь о функциях. Вы, ребята узнали, что функции являются очень хорошей стратегией для сохранения кода в то время как вы программируете, поэтому, если вы хотите выполнить ту же задачу в код снова и снова, вероятно, вы хотите использовать функцию просто так вам не придется скопировать и вставить код снова и снова. На самом деле, основная функция, и когда я покажу вам формат функции Вы увидите, что это довольно очевидно. Мы также используем некоторые функции из библиотеки, Например, Printf, Getin, что из библиотеки CS50, и другие функции, такие как ToUpper. Все эти функции реализуются на практике в других библиотеках, и когда вы поместить эти файлы троса в начале вашей программы Вы говорите, не могли бы вы дать мне код для этих функций так что я не должна реализовывать их самостоятельно? Также вы можете написать свои собственные функции, поэтому, когда вы начинаете программирование Вы понимаете, что библиотеки не имеют все функции, которые вам нужно. За последние PSET, например, мы писали рисовать, борьба и поиск, , и это очень, очень важно, чтобы иметь возможность писать функции потому что они полезны, и мы используем их все время в программировании, и это экономит много кода. Формат функции этого. У нас есть возвращаемого типа в самом начале. Какой тип возвращаемого значения? Это просто, когда ваша функция будет возвращать. Если у вас есть функция, например, факторного, , которая будет вычислять факториал целого числа, вероятно, он собирается возвращать целое число, тоже. Тогда возвращаемого типа будет Int. Printf на самом деле имеет пустоту возвращаемого типа потому что вы не возвращается ничего. Ты просто печатать вещи на экране и выход из функции после этого. Тогда у вас есть имя функции, которые вы можете выбрать. Вы должны быть немного разумны, как не выбирают имя, как XYZ или как х2. Попробуйте сделать себе имя, которое имеет смысл. Например, если это факториал, скажем факториал. Если это функция, которая будет рисовать что-то, назовите его рисовать. И тогда у нас есть параметры, которые также называются аргументами, , которые, как ресурсы, что ваша функция должна из вашего кода для выполнения своих задач. Если вы хотите, чтобы вычислить факториал числа вероятно, у Вас должен быть рядом, чтобы вычислить факториал. Один из аргументов, которые вы собираетесь есть, сам номер. И тогда это будет что-то делать, и возвращать значение в конце если это не пустота функции. Давайте посмотрим на примере. Если я хочу написать функцию, которая суммирует все числа в массив целых чисел, Прежде всего, возвращаемого типа будет Int потому что у меня есть массив целых чисел. И тогда я буду иметь имя функции, как sumArray, а затем он собирается взять сам массив, в целое НУМС, , а затем длину массива, поэтому я знаю, как много чисел, у меня подвести. Тогда у меня есть для инициализации переменной называют сумму, например, 0, и каждый раз, когда я вижу элемент в массиве я должен добавить его в сумму, поэтому я сделал цикл. Так же, как Лекси сказала, вы делаете Int я = 0, <длина и я + +. И для каждого элемента в массиве я сделал сумму + = НУМС [я], а потом я вернулся сумму, так что это очень просто, и это экономит много кода если вы используете эту функцию много раз. Затем мы рассмотрели условия. У нас, если, еще, и еще, если. Давайте посмотрим, в чем разница между теми, кто. Взгляните на эти 2 коды. В чем разница между ними? Первая была в основном-коды хочу, чтобы ты если число +, - или 0. Первый говорит, что если он> 0, то это положительно. Если это = 0, то это 0, а если <0, то это отрицательно. А другой делает, если, иначе, если другое. Разница между ними состоит в том, что этот человек на самом деле собирается проверить, если> 0, <0 = 0 или три раза, так что если у вас есть номер 2, например, он собирается приехать сюда и сказать: Если (X> 0), и он скажет да, так я печатать положительные. Но, хотя я знаю, что это> 0, и он не собирается быть 0 или <0 Я все еще собираюсь делать это 0, то <0, так что я на самом деле происходит внутри IFS, что я не должна потому что я уже знаю, что он не собирается, чтобы удовлетворить любое из этих условий. Я могу использовать, если, иначе, если другое заявление. Это в основном говорит, что если х = 0 напечатать положительные. Если это не так, я буду также проверить это. Если это 2 не я собираюсь это сделать. В принципе, если у меня было х = 2 вы могли бы сказать Если (X> 0), да, так печатать. Теперь, когда я знаю, что это> 0 и что он удовлетворен первым, если Я даже не собираюсь запустить этот код. Код работает быстрее, на самом деле, в 3 раза быстрее, если вы используете это. Мы также узнали о и и или. Я не собираюсь пройти через это, потому что Лекси уже говорили о них. Это просто && и | | оператора. Единственное, что я скажу, будьте осторожны, когда у вас есть 3 условия. Используйте скобки, потому что это очень запутанным, когда у Вас есть условие и еще одно или другое. Используйте скобки просто чтобы быть уверенным, что ваши условия смысла потому что в этом случае, например, вы можете себе представить, что это может быть первым условием и одним или другим или 2 условия объединенных в и или третье, так что будьте осторожны. И, наконец, мы говорили о коммутаторах. Выключатель очень полезно, когда у вас есть переменная. Давайте предположим, что у вас есть переменная, как п что может быть 0, 1 или 2, и для каждого из этих случаев Вы собираетесь выполнить задачу. Вы можете сказать переключения переменной, а это означает, что значение то, как value1 я собираюсь сделать это, а потом ломается, который означает, что я не буду смотреть на любую из других случаях потому что мы уже удовлетворены тем, что дело , а затем value2 и так далее, и я также может иметь значение по умолчанию переключателя. Это означает, что, если он не удовлетворяет ни одному из дел, которые у меня были что я собираюсь сделать что-то еще, но это необязательно. Это все для меня. Теперь давайте Томми. Все правильно, это будет неделя 3-иш. Вот некоторые из тем, которые мы будем покрытие, крипто, сферы применения, массивы, и так далее. Просто слов о криптографии. Мы не собираемся забивать этим домом. Мы сделали это в PSET 2, но для тест убедитесь, что вы знаете разницу между шифр Цезаря и шифр Виженера, как обе эти работы шифров и что это такое для шифрования и расшифровать текст, используя эти 2 шифры. Помните, что шифр Цезаря просто поворачивает каждый символ на ту же сумму, убедившись, что вы мода на количество букв в алфавите. И шифра Виженера, с другой стороны, вращается каждый символ по другую сумму, так что вместо того, чтобы говорить каждый персонаж повернут на 3 Виженера будет вращать каждый символ на разное количество в зависимости от некоторых ключевых слов где каждая буква в ключевое слово представляет собой некоторую другую сумму чтобы повернуть открытым текстом по. Давайте сначала поговорим о переменной области. Есть 2 различных типов переменных. У нас есть локальные переменные, и эти будут определены за пределами основного или вне какой-либо функции или блока, и они будут доступны в любом месте программы. Если у вас есть функция, и в этой функции является время цикла большие глобальные переменные доступны везде. Локальная переменная, с другой стороны, является областью к месту, где она определена. Если у вас есть функция Вот, например, у нас есть эта функция г, и внутри G есть переменная здесь называется у, и это означает, что это локальная переменная. Даже если эта переменная называется у и эта переменная называется у этих 2 функций не знаю, что друг друга локальных переменных. С другой стороны, здесь мы говорим Int х = 5, и это выходит за рамки любой функции. Это выходит за рамки основного, так это глобальная переменная. Это означает, что внутри этих 2 функций, когда я говорю х - или х + + Я доступ к той же х причем это у и у этого являются различными переменными. Вот в чем разница между глобальных переменных и локальных переменных. Что касается дизайна, то, иногда это хорошей идеей сохранить локальные переменные, когда вы, возможно, может так как с кучей глобальных переменных можно получить очень запутанной. Если у вас есть куча функций все изменения одно и то же Вы можете забыть, что если эта функция случайного изменяет этот глобальный, и эта другая функция не знает об этом, и это действительно становится довольно запутанным, как вы получите больше кода. Сохранение локальных переменных, когда вы, возможно, может просто хороший дизайн. Массивы, помните, что это просто списки из элементов того же типа. Внутри CI не может иметь список, как 1, 2,0, здравствуйте. Мы просто не можем этого сделать. Когда мы объявляем массив в C все элементы должны быть того же типа. Здесь у меня есть массив из 3 целых чисел. Вот у меня есть длина массива, но если я просто объявить его в этот синтаксис где я указываю, что все элементы я технически не нужна эта 3. Компилятор достаточно умен, чтобы понять, насколько большой массив должен быть. Теперь, когда я хочу, чтобы получить или установить значение массива это синтаксис, чтобы сделать это. Это на самом деле изменить второй элемент массива, потому что, помните, Нумерация начинается с 0, а не с 1. Если я хочу прочитать, что значение я могу сказать что-то вроде Int х = массив [1]. Или, если я хочу установить это значение, как я здесь делаю, Я могу сказать, массив [1] = 4. В это время доступ к элементам по индексу или их положения или где они находятся в массиве, и что в каталоге начинается с 0. Мы можем также есть массивы массивов, и это называется многомерным массивом. Когда у нас есть многомерный массив это означает, что мы можем иметь что-то вроде строк и столбцов, и это только один из способов визуализации этого или думать об этом. Когда у меня есть многомерный массив, который означает, что я собираюсь начать нуждающихся более чем на 1 индекс, потому что если у меня есть сетка просто говорю, что строка вы находитесь в не дает нам номер. Это действительно просто хочу, чтобы дать нам список номеров. Скажем, у меня есть этот массив здесь. У меня есть массив называется сетка, и я говорю, что это 2 строки и 3 столбца, и таким образом, это является одним из способов визуализации его. Когда я говорю, я хочу, чтобы элемент [1] [2] это означает, что, поскольку эти строки, а затем столбцы Я собираюсь перейти на строку 1, так как я сказал 1. Тогда я собираюсь приехать сюда в колонке 2, и я собираюсь получить значение 6. Смысл? Многомерные массивы, помните, что технически просто массив массивов. Мы можем иметь массивы массивов массивов. Мы можем продолжать, но действительно один способ думать о как это в настоящее время заложен, и то, что происходит, чтобы визуализировать в сетке, как это. Когда мы передаем массивов в функции, они будут вести себя немного по-другому, чем когда мы переходим регулярных переменных функции как передача Int или с плавающей точкой. Когда мы передаем в Int или символ или любой из этих других типов данных мы только что рассмотрели, если функция изменяет значение этой переменной, что изменения не собираюсь распространяться вверх в вызывающую функцию. С массивом, с другой стороны, что будет происходить. Если бы я передать массив к некоторой функции и функция изменяет некоторые элементы, когда я вернусь к функции, которые назвали его мой массив теперь будет по-другому, и словарь для этого это массивы передаются по ссылке, как мы увидим позже. Это связано как указатели работы, где эти основные типы данных, С другой стороны, передаются по значению. Мы можем думать о том, как сделать копию некоторые переменные и переходя затем в копии. Не имеет значения, что мы делаем с этой переменной. Вызывающая функция не будет знать, что он изменился. Массивы являются лишь немного отличается в этом отношении. Например, как мы только что видели, основным является просто функцией что можно взять в 2 аргументов. Первый аргумент основной функцией является агдс, или количество аргументов, а второй аргумент называется ARGV, и те фактические значения этих аргументов. Скажем, у меня есть программа под названием this.c, и я говорю это сделать, и я собираюсь запустить в командной строке. Теперь, чтобы пройти в некоторые аргументы, чтобы моя программа называется это, Я мог бы сказать нечто подобное. / Это CS 50. Это то, что мы воображаем, Дэвид делать каждый день на терминале. Но теперь основная функция внутри этой программы имеет следующие значения, так агдс равна 4. Это может быть немного запутанным, потому что на самом деле мы только проходящие в это CS 50. Вот только 3. Но помните, что первый элемент ARGV или первый аргумент это имя самой функции. Таким образом, это означает, что у нас есть 4 вещи здесь, и первый элемент будет. / это. И это будет представлено в виде строки. Тогда остальные элементы того, что мы набрали после названия программы. Так же, как в стороне, так как мы, наверное, видели в PSET 2, помните, что строка 50, ≠ целых 50. Поэтому мы не можем сказать что-то вроде: "INT X = ARGV 3". Вот только не собирается смысла, потому что это строка, и это число. Так что, если вы хотите конвертировать между 2, помните, что мы собираемся есть эта волшебная функция называется atoi. , Которая принимает строку и возвращает целое число представлено в этой строке. Так что это легко сделать ошибку в викторине, просто думал, что это будет автоматически правильный тип. Но точно знаю, что это всегда будет строк даже если строка содержит только целое число или символ или с плавающей точкой. Итак, теперь давайте поговорим о времени работы. Когда у нас есть все эти алгоритмы, которые делают все эти безумные вещи, это становится действительно полезно задаться вопросом: «Как долго они принимают?" Мы представляем, что нечто, называемое асимптотическое обозначение. Таким образом, это означает, что - ну, скажем, мы даем нашим алгоритмом некоторые очень, очень, очень большой вклад. Мы хотим задать вопрос: "Как долго это займет? Сколько шагов займет наш алгоритм для запуска в зависимости от размера входных данных? " Итак, первый способ, которым мы можем описать время выполнения с большой О. И это наш наихудший ход времени. Поэтому если мы хотим, чтобы отсортировать массив, и мы даем нашим алгоритмом массива это в порядке убывания, когда оно должно быть в порядке возрастания, что будет в худшем случае. Это наша верхняя грань в максимальное время наш алгоритм будет. С другой стороны, эта Ω будет описывать лучшем случае время работы. Так что, если мы дадим уже отсортированный массив в алгоритм сортировки, Как долго это займет, чтобы уладить его? И это, то, описывает нижнюю границу на время работы. Итак, вот лишь некоторые слова, которые описывают некоторые общие работает раза. Это в порядке возрастания. Самый быстрый бег времени у нас называется постоянным. Это означает, что независимо от того, сколько элементов мы даем нашим алгоритмом, независимо от того, насколько велика наша массив, сортировка или делать то, что мы делаем в массив всегда будет такое же количество времени. Таким образом, мы можем представить, что только с 1, который является постоянным. Мы также посмотрели на логарифмическое время перспективе. Так что-то вроде двоичного поиска является логарифмической, где мы сократили проблема в два раза каждый раз, когда а потом все просто получить высшее оттуда. И если вы когда-нибудь письменно о любых факториал алгоритм, Вы, вероятно, не следует рассматривать это как свою работу дня. Когда мы сравниваем времени работы очень важно иметь в виду эти вещи. Так что, если у меня есть алгоритм, который O (N), а кто-то другой была алгоритма O (2n), это на самом деле асимптотически эквивалентны. Таким образом, если представить себе, п быть большое количество, как eleventy млрд: поэтому, когда мы сравниваем eleventy млрд. что-то вроде eleventy млрд. + 3, +3 внезапно, что на самом деле не делают большой разницы больше. Вот почему мы собираемся начать рассматривать эти вещи, чтобы быть эквивалентными. Так что такие вещи, как эти константы здесь, есть 2 х это, или добавление 3, это просто константы, и они собираются бросить вверх. Так вот почему все эти 3 раза перспективе такие же, как говорят они O (N). Аналогично, если у нас есть 2 другие времена перспективе, скажем, O (N ³ + 2n ²), мы можем добавить + П, + 7, а затем у нас есть еще время выполнения, что просто O (N ³). опять же, это одно и то же, потому что это - это не то же самое. Это те же самые вещи, извините. Таким образом, это те же самые, потому что эта ³ п будет доминировать в этом 2n ². Что не одно и то же, если мы уже запустили время, как O (N ³) и O (N ²) потому что эта ³ п гораздо больше, чем эта ² н. Так что, если у нас есть показатели, вдруг это начинает значения, Но когда мы просто дело с факторами, как мы здесь, то он не собирается значения, потому что они только собираются бросать. Давайте взглянем на некоторые алгоритмы, которые мы видели до сих пор и говорить об их выполнения. Первый взгляд на номер в списке, который мы видели, был линейный поиск. И реализация линейного поиска супер просто. Мы просто есть список, и мы будем смотреть на каждый отдельный элемент в списке пока мы не найдем число, которое мы ищем. Таким образом, это означает, что в худшем случае, это O (N). А в худшем случае здесь могло бы быть, если элемент Последний элемент, то с помощью линейного поиска, мы должны смотреть на каждый отдельный элемент пока мы не получим до последнего, чтобы знать, что это было на самом деле в списке. Мы не можем просто бросить на полпути и сказать: "Это, наверное, нет». С линейный поиск, мы должны смотреть на все это. Лучшем случае время работы, с другой стороны, постоянно потому что в лучшем случае элемент мы ищем это только первый в списке. Таким образом, он собирается взять нас ровно на 1 шаг, независимо от того, насколько большой список если мы ищем первый элемент каждый раз. Поэтому, когда вы будете искать, помните, это не требует, чтобы наш список будет отсортирован. Потому что мы просто будем смотреть на каждый отдельный элемент, и это действительно не имеет значения в каком порядке эти элементы дюйма Более интеллектуальный алгоритм поиска что-то вроде бинарного поиска. Помните, что реализация бинарного поиска, когда вы собираетесь продолжайте смотреть в середину списка. И потому, что мы смотрим на середине, мы требуем, чтобы список сортируется иначе мы не знаем, где середина, и мы должны смотреть на весь список, чтобы найти его, а затем на тот момент мы просто теряем время. Так что, если у нас есть отсортированный список, и мы находим середину, мы собираемся сравнить средние к элементу мы ищем. Если она слишком высока, то мы можем забыть правой половины потому что мы знаем, что если наш элемент уже слишком высоки и все, что правее этого элемента еще выше, то мы не должны смотреть там больше. Если, с другой стороны, если наш элемент является слишком низкой, Мы знаем все, чтобы слева от этого элемента также является слишком низкой, таким образом, это действительно не имеет смысла искать там, также. Таким образом, с каждым шагом, и каждый раз, когда мы смотрим на середину списка, Мы собираемся сократить наши проблемы в половину, потому что внезапно мы знаем, целую кучу цифр, что не может быть тот, который мы ищем. В псевдокоде это будет выглядеть примерно так, и потому, что мы резки списка в два раза каждый раз, наши наихудшие время выполнения прыжков с линейной к логарифмической. Так неожиданно мы имеем вход в систему шаги для того, чтобы найти элемент в списке. Лучшем случае ход времени, хотя, по-прежнему постоянной потому что теперь, давайте просто скажем, что элемент мы ищем является Всегда точно посередине первоначального списка. Так что мы можем развивать наш список как большой, как мы хотим, но если элемент мы ищем находится на середине, Затем она только собирается взять нас на 1 шаг. Так вот почему мы O (журнал N) и Ω (1) или постоянными. Давайте реально работать бинарный поиск в этом списке. Так что давайте говорить, что мы ищем элемент 164. Первое, что мы собираемся сделать, это найти середину этого списка. Просто так получилось, что середина будет падать между этими 2 номера, так что давайте просто сколь угодно говорить, каждый раз середина находится между 2 номера, Давайте просто округлить. Нам просто нужно убедиться, что мы делаем это каждый шаг пути. Так что мы собираемся сгонять, и мы собираемся сказать, что 161 является средним из нашего списка. Так что 161 <164, и каждый элемент в левом из 161 Также <164, так что мы знаем, что это не поможет нам на всех , чтобы начать искать здесь, потому что элемент мы ищем не может быть там. Итак, что мы можем сделать, мы можем просто забыть о том, что вся левая половина списка, а теперь рассматривать только с правой из 161 и далее. Итак, еще раз, это середина, давайте просто округлить. Сейчас 175 является слишком большой. Итак, мы знаем, что это не поможет нам искать здесь или здесь, поэтому мы можем просто бросить, что далеко, и в итоге мы попали в 164. Любые вопросы по двоичного поиска? Давайте перейдем от поиска в уже отсортированный список на самом деле принимает список чисел в любом порядке и сделать этот список в порядке возрастания. Первый алгоритм мы смотрели на называлось пузырьковой сортировки. И это будет гораздо проще алгоритмов, которые мы видели. Bubble рода говорит, что когда любые 2 элемента внутри списка не на месте, то есть есть большее число слева от меньшего числа, Затем мы собираемся поменять их местами, потому что это означает, что список будет "Более упорядоченные", чем это было раньше. И мы просто будем продолжать этот процесс снова и снова, и снова пока в конце концов элементов вида пузырь на их правильное расположение и у нас есть отсортированный список. Время выполнения этого будет O (N ²). Почему? Ну, потому что в худшем случае, мы собираемся взять каждый элемент, и мы собираемся в конечном итоге, сравнивая ее с любой другой элемент в списке. Но в лучшем случае, у нас есть уже отсортированный список, пузырьковой сортировки в только собирается пройти один раз, сказать: "Нет. Я не делал никаких свопов, так что я сделал". Итак, мы имеем лучшем случае время работы Ω (N). Давайте запустим пузырьковой сортировки в списке. Или сначала, давайте просто посмотрим на некоторые псевдокод очень быстро. Мы хотим сказать, что мы хотим отслеживать, в каждой итерации цикла, отслеживать ли мы изменили какие-либо элементы. Таким образом, причина этого в том, что мы собираемся остановиться, когда мы не поменялись местами любые элементы. Таким образом, в начале нашего цикла мы не поменялись местами ничего, поэтому мы будем говорить, что это ложь. Теперь, мы собираемся пройтись по списку и сравнить элемента к элементу я я + 1 и если это так, что есть большее число слева от меньшего числа, Затем мы только собираемся, чтобы поменять их местами. И тогда мы будем помнить, что мы поменялись местами элемент. Это означает, что мы должны идти по списку, по крайней мере, еще 1 раз потому что состояние, в котором мы остановились, когда весь список уже отсортирован, означает, что мы не сделали никаких свопов. Так вот почему наши условия здесь является «в то время как некоторые элементы были заменены. Итак, теперь давайте посмотрим на это работает на список. У меня есть список 5,0,1,6,4. Bubble рода собирается начать весь путь слева, и это будет для сравнения я элементов, так от 0 до + 1, которое является элементом 1. Он скажет, ну 5> 0, но прямо сейчас 5 находится слева, так что мне нужно поменять местами 5 и 0. Когда я поменять их местами, вдруг я получаю это другой список. Сейчас 5> 1, так что мы собираемся поменять их местами. 5 не> 6, поэтому мы не должны ничего делать здесь. Но 6> 4, так что мы должны поменять. Опять же, нам нужно запустить весь список, чтобы в конце концов обнаружить что эти вышли из строя, мы поменять их местами, и в этот момент нам нужно запустить через список еще 1 раз чтобы убедиться, что все в его распоряжении, и в этот момент пузырьковой сортировки закончен. Различных алгоритмов для принятия некоторых элементов и сортировка них является выбор рода. Идея выбора рода является то, что мы собираемся построить отсортированный часть списка 1 элемент одновременно. И то, как мы собираемся сделать это путем создания левой части списка. А в принципе, каждый - на каждом шагу, мы собираемся взять наименьший элемент мы оставили , которые не были отсортированы еще, и мы собираемся, чтобы переместить его в это отсортированный сегменте. Это означает, что мы должны постоянно находить минимальный элемент несортированные , а затем принять, что минимальный элемент и поменять его с тем, что левый элемент, который не сортируется. Время выполнения этого будет O (N ²), потому что в худшем случае мы должны сравнить каждый элемент любой другой элемент. Потому что мы говорим, что если мы начнем в левой половине списка, мы должны пройти через весь правый сегмент, чтобы найти наименьший элемент. А потом, опять же, мы должны идти в течение всего правого сегмента и продолжать над этим снова и снова, и снова. Это будет п ². Мы собираемся нужно цикл внутри другого цикла что свидетельствует о п ². В лучшем случае мысль, скажем, мы даем ему уже отсортированный список; мы на самом деле не делают лучше, чем ² н. Потому что выбор рода не имеет возможности узнать, что минимальный элемент только один я, случается, смотрит. Он по-прежнему должен убедиться, что это действительно минимум. И единственный способ, чтобы убедиться, что это минимум, с помощью этого алгоритма, , чтобы смотреть на каждый отдельный элемент снова. Так на самом деле, если вы даете ему - если вы дадите выбор рода уже отсортированный список, он не собирается делать лучше, чем дать ему список, что не отсортирован еще нет. Кстати, если оно произойдет, будет случай, что что-то O (что-то) и омега-то, мы можем только сказать, более кратко, что это θ чего-то. Так что если вы видите, что придумать в любом месте, это то, что это просто означает. Если что-то тета-н ², это и большая O (N ²) и Ω (N ²). Так лучшем случае, а худшем случае, это не делает разницы, Алгоритм собирается сделать то же самое каждый раз. Так это то, что псевдокод для выбора рода могла бы выглядеть. Мы в основном будем говорить, что я хочу пройти по списку слева направо, и на каждой итерации цикла, я собираюсь переехать минимальный элемент в этой отсортированы часть списка. И как только я перехожу что-то там, я никогда не должны смотреть на этот элемент снова. Потому что как только я поменять элемент в левой части списка, это отсортированный потому что мы делаем все, что в порядке возрастания с использованием минимума. Поэтому мы сказали, хорошо, что мы в положении я, и мы должны смотреть на все элементы справа от меня, чтобы найти минимум. Таким образом, это означает, что мы хотим смотреть с г + 1 в конец списка. И теперь, если элемент, который мы в настоящее время смотрим на это меньше, чем наши минимальные до сих пор, который, помните, что мы начинаем с минимальным просто быть любого элемента мы в настоящее время, я буду считать, что это минимум. Если я найду элемент, который меньше, чем это, то я буду говорить, ладно, Ну, я нашел новый минимум. Я буду помнить, где что было минимальным. Так что теперь, когда я прошел через это право несортированные сегменте, Я могу сказать, что я собираюсь поменять местами минимальный элемент с элементом, который находится в положении я. Это собирается построить мой список, отсортированный моей части списка слева направо, и мы никогда не должны смотреть на элемент снова, как только она в этой части. Как только мы сменил его. Так что давайте работать выбор рода в этом списке. Синие элементом здесь будет я, а красный элемент будет минимальным элементом. Так что я все начинается путь в левой части списка, так на 5. Теперь нам нужно найти минимум несортированные элемент. Поэтому мы говорим, 0 <5, так что 0 является мой новый минимум. Но я не могу остановиться, потому что даже если мы можем признать, что 0 является наименьшим, нам нужно запустить через любой другой элемент списка, чтобы убедиться. Таким образом, 1 больше, 6 больше, 4 больше. Это означает, что после того, глядя на все эти элементы, я определяли 0 является наименьшим. Так что я собираюсь поменять 5 и 0. Однажды я поменять, что я собираюсь получить новый список, и я знаю, что я никогда не нужно смотреть на что 0 раз потому что как только я сменил его, я уладил его, и мы сделали. Теперь так уж случилось, что синий элемент снова 5, и мы должны смотреть на 1, 6 и 4, чтобы определить, что 1 является наименьшим минимальным элементом, поэтому мы переставляем 1 и 5. Опять же, мы должны смотреть на - сравнить от 5 до 6 и 4, и мы собираемся поменять 4 и 5, и, наконец, сравнить эти 2 номера и поменять их местами, пока мы не получим наши отсортированный список. Любые вопросы по выбору рода? Хорошо. Давайте перейдем к последней теме здесь, и это рекурсия. Рекурсия, помните, что это действительно мета вещь, где функция неоднократно называет себя. Так что в какой-то момент, в то время как наши Fuction неоднократно называет себя, там должно быть некоторое точке, в которой мы перестать называть себя. Потому что если мы не сделаем этого, то мы просто будем продолжать делать это вечно, и наша программа просто не будет прекращаться. Мы называем это состояние базового варианта. И базовый вариант, говорит, вместо вызова функции снова, Я просто хочу вернуть некоторое значение. Поэтому, как только мы вернулись значение, мы перестали называть себя, и остальные вызовы мы сделали до сих пор можно вернуть. В противоположность базу случае является рекурсивным случае. И это, когда мы хотим сделать еще один вызов функции, которые мы в настоящее время дюйма И мы, вероятно, хотя и не всегда, хотят использовать различные аргументы. Так что, если у нас есть функция под названием F и F только что позвонил принимать по 1 аргумент, и мы просто звонят F (1), F (1), F (1), и так уж случилось, что аргумент 1 попадает в рекурсивном случае, мы еще ни разу не собирается останавливаться. Даже если у нас есть базовый вариант, мы должны убедиться, что в конечном счете мы собираемся ударить, что базовый вариант. Мы не просто сохранить, проживающие в этом случае рекурсивной. Вообще, когда мы называем себя, мы, вероятно, будем иметь другой аргумент каждый раз. Вот очень простой рекурсивной функции. Так что это будет вычислить факториал числа. До начала здесь мы имеем нашу базу случае. В случае, когда п ≤ 1, мы не будем называть факториальным снова. Мы собираемся останавливаться, мы просто собираемся вернуть некоторое значение. Если это не так, то мы собираемся ударить нашем случае рекурсивной. Заметьте, что здесь мы не просто вызовом факториал (п), потому что это было бы очень полезно. Мы будем называть факториал что-то другое. И поэтому вы можете увидеть, в конце концов, если мы передадим факториал (5) или что-то, мы будем называть факториал (4) и так далее, и в конце концов мы собираемся ударить эту базу случае. Таким образом, это хорошо выглядит. Давайте посмотрим, что происходит, когда мы реально работать это. Это стека, и давайте скажем, что основным будет вызывать эту функцию с аргументом (4). Поэтому, как только видит и факториал = 4, факторный будет называть себя. Теперь, вдруг, у нас есть факториал (3). Таким образом, эти функции будет продолжать расти, пока в конце концов мы попали нашу базу случае. На данный момент, возвращаемым значением этого является возвращение (NX возвращаемого значения этого), возвращаемым значением этого NX возвращаемого значения этому. В конечном счете мы должны поразить некоторое число. В верхней здесь, мы говорим, возвращает 1. Это означает, что, когда мы вернемся это число, мы можем поп этом из стека. Так что это факториал (1), то сделано. Когда 1 возвращается, это факториал (1) возвращается, это возвращение к 1. Возвращаемым значением этого, помню, был NX возвращаемого значения этому. Так неожиданно, этот парень знает, что я хочу вернуть 2. Так что помните, вернуть значение это просто NX возвращаемого значения здесь. Так что теперь мы можем сказать, 3 х 2 и, наконец, здесь мы можем сказать, это просто будет 4 х 3 х 2. И как только это возвращается, мы спускаемся к одному внутри целого основной. Любые вопросы по рекурсии? Хорошо. Таким образом, есть больше времени на вопросы в конце, но теперь Джозеф покроет оставшиеся вопросы. [Джозеф Ong] Все в порядке. Так что теперь мы говорили о рекурсии, Давайте немного поговорим о том, что слияние сортировки. Слияние рода в основном другой способ сортировки списка чисел. И как это работает, с сортировки слиянием у вас есть список, и то, что мы делаем, мы говорим, давайте разделить это на 2 половинки. Мы сначала запустить сортировки слиянием снова на левой половине, Затем мы запустим сортировки слиянием на правой половине, и это дает нам сейчас 2 половинки, которые сортируются, и теперь мы собираемся объединить эти половинки вместе. Это немного трудно понять без примера, поэтому мы будем проходить через движения и посмотреть, что происходит. Таким образом, вы начинаете с этого списка, мы разделили его на 2 половинки. Мы проводим сортировки слиянием на левой половине первого. Так вот левую половину, и теперь мы пропустить их через этот список еще раз который передается в сортировки слиянием, а затем мы посмотрим, опять же, в левой части этого списка, и мы побежали сортировки слиянием на нем. Теперь мы перейдем к списку из 2 цифр, и теперь левая половина всего 1 элемент длинный, и мы не можем разделить список, в котором только 1 элемент в половину, так что мы просто скажем, раз у нас есть 50, который находится всего в 1 элемент, он уже отсортирован. Как только мы закончим с этим, мы видим, что мы можем перейти на правую половину этого списка, и 3 также сортируются, и поэтому сейчас, что обе половины этого списка сортируются мы можем объединить эти цифры вместе. Таким образом, мы смотрим на 50 и 3, 3 меньше, чем 50, поэтому он идет в первый и затем 50 приходит дюйма Теперь это будет сделано, мы вернемся к этому списку и сортировка это правая половина. 42 является его собственный номер, так что это уже отсортированы. Итак, теперь мы сравним эти 2 и 3 меньше, чем 42, так что получает положить в первом, теперь 42 получает положить в, и 50 получает вставил Так вот, это упорядоченные, мы пройти весь путь наверх, 1337 и 15. Ну, мы сейчас посмотрим на левую половину этого списка; 1337 сама по себе так что он сортируется и то же самое с 15. Так что теперь мы объединим эти 2 номера для сортировки, что первоначальный список, 15 <1337, поэтому она идет в первый, то 1337 идет дюйма А теперь сортируются обе половинки исходного списка наверху. И все, что нам нужно сделать, это объединить эти. Мы смотрим на первые 2 номера из этого списка, 3 <15, поэтому она идет в сортировки массива в первую очередь. 15 <42, поэтому она идет дюйма Теперь, 42 <1337, который идет дюйма 50 <1337, поэтому она идет дюйма И заметил, что мы просто взяли 2 номера с этого списка. Таким образом, мы не только чередуя 2 списка. Мы просто глядя на начало, и мы берем элемент вот и меньше, а затем положить его в наш массив. Теперь мы объединились все половинки, и мы сделали. Любые вопросы о слиянии рода? Да? [Студент] Если это расщепление в различных группах, почему они не просто разделить его один раз и у вас есть 3 и 2 в группе? [Остальные вопросы неразборчиво] Причина - так что вопрос в том, почему мы не можем просто объединить их в тот первый шаг после того, как они у нас есть? Поэтому мы можем сделать это, начните с самого левого элементы с обеих сторон, , а затем взять поменьше и положил его в том, что мы знаем, что эти отдельные списки в отсортированном заказов. Так что, если я смотрю на самый левый элементы обеих половин, Я знаю, что они собираются быть мельчайших элементов из этих списков. Так что я могу положить их в местах наименьшего элемента этого большого списка. С другой стороны, если я смотрю на эти 2 списка второго уровня там, 50, 3, 42, 1337 и 15, тем не сортируются. Так что, если я смотрю на 50 и 1337, я собираюсь поставить 50 в моем списке первым. Но это не имеет смысла, так как 3 наименьший элемент из всех из них. Таким образом, единственная причина, мы можем сделать это объединение шаг, потому что наши списки уже отсортированы. Именно поэтому мы должны спускаться на всем пути до дна потому что, когда у нас есть только одно число, вы знаете, что один номер само по себе уже является отсортированный список. Есть вопросы? Нет? Сложность? Ну, вы видите, что на каждом шагу есть конец числа, и мы можем разделить список журнала 1/2 п раз, где мы получим этот журнал п х п сложности. И вы увидите, в лучшем случае для сортировки слиянием п § п, и так уж случилось, , что в худшем случае, или Ω там, также п п войти. Нужно иметь в виду. Двигаемся дальше, давайте перейдем к некоторым супер основной файл I / O. Если вы посмотрите на Scramble, вы заметите, у нас была какая-то система где вы могли бы написать в лог-файл, если вы читаете по коду. Давайте посмотрим, как вы могли бы сделать это. Ну, у нас Fprintf, которые вы можете думать, как только Printf, но только печать в файл, а и, следовательно, F в самом начале. Такой код здесь, что он делает, как вы, возможно, видели в Scramble, она проходит через вашу 2-мерный массив из печати ряд за рядом, что числа. В этом случае Выводит на ваш терминал или что мы называем стандартный вывод разделе. И теперь, в этом случае, все, что мы должны сделать, это заменить Printf с Fprintf, сказать ему, что файл, который вы хотите печатать, и в этом случае он просто выводит ее на этот файл вместо того, чтобы печатать его на терминал. Ну, то, что напрашивается вопрос: Где же взять такого рода файлов из, верно? Мы прошли войти в эту Fprintf Fuction но мы понятия не имел, откуда оно взялось. Ну, в самом начале кода, то, что мы имели, был этот кусок кода сюда, , который в основном говорит, что открыть файл вызывает log.txt. Что мы делаем после этого, что мы должны убедиться, что файл на самом деле был успешно открыт. Так что, возможно, не по нескольким причинам, вам не хватает места на вашем компьютере, например. Таким образом, это всегда важно, прежде чем делать любые операции с файлами что мы проверяем, что файл был открыт успешно. Так что это, это аргумент Еореп, хорошо, мы можем открыть файл по-разному. Что мы можем сделать, мы можем передать его вес, а значит изменить файл, если он выходит уже, Мы можем передать, что они добавляем в конец файла, а не перекрывая его, или мы можем указать R, что означает, давайте открыть файл только для чтения. Таким образом, если программа пытается внести изменения в файл, кричать на них и не позволяют им это сделать. Наконец, когда мы закончили с файлом, сделал делают операции на ней, Мы должны убедиться, что мы закрываем файл. И вот в конце вашей программы, вы собираетесь передать их снова это файл, который вы открыли, и просто закрыть его. Так что это что-то важное, что вы должны убедиться, что вы делаете. Так что помните, что вы можете открыть файл, то вы можете записать в файл, делать операции в файле, но тогда вы должны закрыть файл в конце. Любые вопросы по основным файла I / O? Да? [Студент вопрос, неразборчиво] Прямо здесь. Вопрос в том, где же этот файл log.txt появляются? Ну, если вы просто дать ему log.txt, он создает его в том же каталоге, что и исполняемый файл. Так что, если вы - >> [Студенческий вопрос, неразборчиво] Да. В той же папке, или в том же каталоге, как вы это называете. Теперь память, стек и кучу. Так, как это память, изложенных в компьютере? Ну, вы можете себе память как своего рода этом блоке здесь. И в памяти у нас есть то, что называется кучей застряли там, и стек, что там внизу. И куча растет вниз, а стек растет вверх. Так как Томми упоминал, - о, хорошо, и у нас есть эти другие 4 сегментов, которые я получу в секунду - Как сказал Томми раньше, вы знаете, как его называют себя функции и называют друг друга? Они создают такого рода кадра стека. Ну, если основные вызовы Фу, Фу получает положить в стек. Foo называет, бар получите поставим в стек, и что получает положить в стек после. И когда они вернутся, каждая из них получают снять стек. Что каждый из этих мест и память держать? Ну, верхний, который является сегмент текста, содержит саму программу. Таким образом, машинный код, что там, как только вы скомпилировать программу. Далее, любая инициализируются глобальные переменные. Таким образом, у Вас есть глобальные переменные в вашей программе, а вы говорите, как, = 5, , который получает положить в этом сегменте, и прямо под этим, у вас есть какие-то неинициализированные глобальные данные, которые просто INT, но вы не говорю, что это равно ничего. Поймите, это глобальные переменные, так что они за пределами основного. Таким образом, это означает, что любые глобальные переменные, которые объявлены, но не инициализируются. Так что в куче? Память распределяется с помощью таНос, который мы получим в немного. И, наконец, со стеком у вас есть какие-то локальные переменные и любой функции можно вызвать в любой из их параметров. Последняя вещь, вы действительно не должны знать, что переменные окружения делать, но всякий раз, когда вы запускаете программу, есть что-то связано, как это имя пользователя, который запустил программу. И это будет как бы на дне. С точки зрения адреса памяти, которые являются шестнадцатеричные значения, Значения в верхней начинаются с 0, и пройти весь путь до дна. В этом случае, если вы находитесь на 32-битной системе, адресу, указанному внизу будет 0x, а затем А.Ф., потому что это 32 бит, , что на 8 байт, и в этом случае 8 байт соответствует 8 шестнадцатеричных цифр. Так что здесь вы будете иметь, вроде бы, 0xffffff, и там вы будете иметь 0. Так что указатели? Некоторые из вас, возможно, не покрытые этим в разделе ранее. но мы не вдаваться в лекции, поэтому указатель просто тип данных которые магазинах, а не какое-то значение, например 50, она сохраняет адрес определенное место в памяти. Как и что память [неразборчиво]. Таким образом, в данном случае, то, что мы есть, мы имеем указатель на целое или целое число *, и содержит этом шестнадцатеричный адрес 0xDEADBEEF. Итак, что мы имеем сейчас, этот указатель указывает на определенное место в памяти, и это только, значение 50 в это расположение в памяти. На некоторых 32-битных системах, на всех 32-битных систем, указатели занимают 32 бита или 4 байта. Но, например, на 64-битной системе, указатели являются 64-битными. Так что то, что вы хотите, чтобы держать в уме. Таким образом, на конец-битной системы, указатель конца бит. Указатели являются своего рода трудно переварить без дополнительных вещей, так давайте пройдем пример динамического распределения памяти. Что динамического распределения памяти делает для вас, или то, что мы называем таНос, она позволяет выделить какой-то данных за пределами съемочной площадке. Таким образом, эти данные является своего рода более постоянным в течение всего срока программы. Потому что, как вы знаете, если вы объявите х внутри функции, а функция возвращает значение, Вам больше не имеют доступа к данным, которые хранятся в х. Что указатели будем делать, они позволяют нам хранить память или хранят значения в другой сегмент памяти, а именно в кучу. Теперь, когда мы вернемся из функций тех пор, пока у нас есть указатель в то же место в памяти, то, что мы можем сделать, мы можем просто смотреть на значения там. Давайте посмотрим на примере: Это наша память макет снова. И у нас есть эта функция, основной. Что она делает это - хорошо, так просто, правда? - Int х = 5, вот только на стеке в главном. С другой стороны, теперь мы объявляем указатель, который вызывает функцию giveMeThreeInts. И вот теперь мы идем в эту функцию, и мы создаем новый кадр стека для него. Однако, в этом кадре стека, мы заявляем Int * температура, который в mallocs 3 целых для нас. Таким образом, размер Int даст нам сколько байт этом Int есть, и таНос дает нам, что многие байт пространства в куче. Таким образом, в этом случае, мы создали достаточно места для 3 числа, и куча путь там, поэтому я нарисовал ее выше. Как только мы закончим, мы вернемся сюда, вам нужно всего лишь 3 целыми вернулись, и она возвращает адрес, в данном случае над тем, где эта память. И мы поставили указатель = выключатель, и там у нас есть еще один указатель. Но то, что эта функция возвращает укладывается здесь и исчезает. Таким образом, темп исчезает, но мы по-прежнему поддерживают адреса, где эти 3 числа находятся внутри сети. Таким образом, в этом наборе, указатели областью на местном уровне для сложенных кадров, но память к которым они относятся в кучу. Имеет ли это смысл? [Студент] Не могли бы вы повторить? >> [Иосиф] Да. Так что, если я вернусь чуть-чуть, вы видите, что температура выделено некоторый объем памяти в куче там. Поэтому, когда эта функция, giveMeThreeInts возвращается, этот стек здесь собирается исчезать. А вместе с ней любой из переменных, в данном случае, это указатель, который был выделен в стек кадра. То есть исчезнет, ​​но так как мы вернулись температура и мы указателя = температура, указатель теперь будет указывать ту же самую память о месте, темп был. Так что теперь, даже если мы потеряем темп, что местные указатель, Мы по-прежнему сохраняют адрес памяти, что он был направлен внутрь этой переменной указатель. Вопросы? Это может быть даже запутанной темы, если вы не перешли его в разделе. Мы можем, ваш TF определенно пойдет на это и, конечно, мы можем ответить на вопросы В конце сессии по обзору для этого. Но это своего рода сложный вопрос, и у меня есть другие примеры, которые собираются, чтобы показать , которая поможет прояснить, что указатели на самом деле. В этом случае, указателей эквивалентно массивов, так что я могу просто использовать этот указатель, как то же самое, Int массива. Так что я индексации в 0, и изменение первое число 1, изменение второго числа 2, и 3-й целое число 3. Так что больше на указатели. Ну, вспомните Бинки. В этом случае мы выделили указатель, или мы объявили указатель, но вначале, когда я только что объявили указатель, это не указывает на любой памяти. Это просто мусор значения внутри него. Так что я понятия не имею, где этот указатель указывает. Он имеет адрес, который просто наполнен 0 и 1, где он был изначально объявлен. Я ничего не могу сделать с этим, пока я называю таНос на нее и это дает мне мало места в куче, где я могу поставить значения внутри. Опять же, я не знаю, что внутри этой памяти. Поэтому первое, что я должен сделать, это проверить, является ли система имела достаточно памяти , чтобы дать мне назад 1 целое, в первую очередь, поэтому я делаю это проверить. Если указатель пуст, это означает, что у него не было достаточно места, или другие ошибки, так что я должен выйти из моей программы.  Но если это и не удалось, теперь я могу использовать этот указатель и то, что * указатель делает это следующим где адрес где это значение, и это отличает его равным 1. Так что здесь, мы проверяем, если что память существует. Когда вы знаете, она существует, вы можете поместить в нее Какое значение вы хотите вложить в нее, в этом случае 1. Как только мы покончим с этим, необходимо, чтобы освободить этот указатель потому что мы должны вернуться к системе, памяти, которые вы просили в первую очередь. Поскольку компьютер не знает, когда мы покончим с этим. В этом случае мы явно говорит он, хорошо, мы закончили с этой памятью. Если некоторые другие процессы в ней нуждается, некоторые другие программы в ней нуждается, не стесняйтесь идти вперед и принимать его. Что мы можем сделать, это мы можем просто получить адрес локальных переменных на съемочной площадке. Так Int х находится внутри сложены рамках основной. И когда мы используем этот символ, это и оператора, что она делает это он принимает х, и х лишь некоторые данные в памяти, но у него есть адрес. Она находится где-то. Так, позвонив по телефону и х, то, что это делает он дает нам по адресу х. Делая это, мы делаем указатель точки, где х находится в памяти. Теперь мы просто сделать что-то вроде * х, мы собираемся, чтобы получить 5 назад. Звезда называется разыменования его. Вы следуете адрес, и вы получите значение она хранится там. Есть вопросы? Да? [Студент] Если вы этого не сделаете 3-заостренные вещь, это все еще скомпилировать? Да. Если вы этого не сделаете 3-указатель вещь, она по-прежнему будет составлять, Но я покажу вам, что происходит в секунду, а без этого, это то, что мы называем утечкой памяти. Вы не даете системе Резервное его памяти, так что через некоторое время программа будет накапливаться память, что она не используется, и ничто другое не может его использовать. Если вы когда-либо видели Firefox с 1,5 миллиона килобайт на вашем компьютере, в диспетчере задач, вот что происходит. У вас есть утечки памяти в программе, что они не обрабатывает. Так как же арифметика указателей работы? Ну, арифметика указателей вроде как индексация в массиве. В этом случае, у меня есть указатель, и то, что я делаю, я делаю указатель указывает на первый элемент этого массив из 3 целых чисел, которые я выделил. Так что теперь мне делать, звезда просто меняет указатель на первый элемент в списке. Звезда указатель +1 очков здесь. Таким образом, указатель мыши здесь, +1 является указателем здесь, указатель +2 является здесь. Так что добавление 1, то же самое, двигаясь по этому массиву. Что мы делаем, когда мы делаем указатель +1 Вы получите адрес здесь, и для того, чтобы получить значение здесь, вы положили звезду в от всего выражения Обращаться к ним. Таким образом, в данном случае, я устанавливаю первое место в этом массиве в 1, Второе место 2, а третье место на 3. Затем, что я делаю здесь есть я печатаю наш указатель +1, который просто дает мне 2. Теперь я увеличивая указатель, поэтому указатель равно указатель +1, , которая движется вперед. И вот теперь, если я распечатать указатель +1, указатель +1 теперь 3, который в данном случае выводит 3. И для того, чтобы что-то бесплатно, указатель, который я даю ему должны быть направлены на начало массива, который я вернулся из таНос. Таким образом, в данном случае, если бы я был звонить 3 прямо здесь, это было бы неправильно, потому что это в середине массива. Я должен вычесть, чтобы получить на прежнем месте начальная первом месте прежде чем я смогу освободить его. Итак, вот более сложный пример. В этом случае, мы выделении 7 символов в массив символов. И в этом случае то, что мы делаем, мы циклов в течение первых 6 из них, и мы устанавливаем их в Z. Таким образом, для Int я = 0, г> 6, я + +, Таким образом, указатель + Я просто дать нам, в данном случае, указатель, указатель +1, +2 указатель, указатель +3, и так далее, и так далее в цикле. Что он собирается делать это получает, что адрес, разыменовывает его, чтобы получить значение, и изменения, значение Z. Затем, в конце помните, что это строка, не так ли? Все строки должны закончить с нулевой символ завершения. Итак, что я делаю, это указатель в 6 я поставил пустой символ конца дюйма А теперь то, что я в основном делаю здесь реализуется Printf для строки, не так ли? Итак, когда же Printf теперь, когда она достигла конца строки? Когда она снизится до нулевой символ завершения. Таким образом, в данном случае, мои исходные точки, указатель на начало этого массива. Я напечатать первый символ из. Я переместить его на один. Я печатаю этот символ из. Я двигаюсь его. И я продолжаю делать это, пока я дойти до конца. А теперь указатель конца * будет разыменовать и получить нулевой завершающий символ назад. И поэтому моя в то время как цикл выполняется только тогда, когда это значение не является нулевой символ завершения. Итак, теперь я выйти из этой петли. И поэтому, если я вычесть 6 из этого указателя, Я возвращаюсь весь путь с самого начала. Помните, я делаю это потому, что я должен пойти к началу, чтобы освободить его. Так вот, я знаю, что было много. Есть ли вопросы? Пожалуйста, да? [Студент вопрос неразборчиво] Можете ли вы сказать, что громче? Извините. [Студент] На последнем слайде право, прежде чем освободить указатель, где вы были на самом деле изменить значение указателя? [Джозеф] Так, прямо здесь. >> [Студент] О, все в порядке. [Джозеф] Итак, у меня есть указатель минус минус, право, который перемещает вещи обратно на один, а потом освободить его, потому что этот указатель должен быть указала на начало массива. [Студент] Но это был бы не нужен, если бы вы остановились после этой строки. [Джозеф] Так что, если я остановился после этого, это будет рассматриваться как утечка памяти, потому что я не запустить бесплатный. [Студент] Я [неразборчиво] после первых трех линиях, где вы были указателя +1 [неразборчиво]. [Джозеф] Угу. Так, что вопрос там? Извините. Нет, нет. Иди, иди, пожалуйста. [Студент] Таким образом, вы не изменив значение указателей. Вы не должны были бы сделать указатель минус минус. [Джозеф] Да, именно так. Так что, когда я делаю указатель и указатель +1 +2, Я не делаю указателя равно указатель +1. Таким образом, указатель остается только указывает на начало массива. И только когда я делаю плюс плюс, что он устанавливает значение обратно в указатель, что он фактически движется вдоль этого. Хорошо. Еще вопросы? Опять же, если это является своего рода подавляющим, это будут рассмотрены на сессии. Попросите вашего обучения коллег об этом, и мы можем ответить на вопросы в конце. И обычно мы не хотели делать это минус вещь. Это должно требуют от меня отслеживать, насколько я Смещение в массиве. Так, в общем, это просто объяснить, как работает арифметика указателей. Но то, что мы обычно нравится делать, мы хотели бы создать копию указателя, и тогда мы будем использовать эту копию, когда мы движемся вокруг в строку. Таким образом, в этих случае если вы используете копии напечатать всю строку, но мы не должны делать, как указатель минус 6 или отслеживать, сколько мы переехали в это, только потому, что мы знаем, что наша исходная точка по-прежнему указывает на начало списка и все, что мы изменили эта копия. Так, в общем, изменять копии оригинальных указатель. Не пытайтесь что-то вроде - don't изменить экземплярах. Попытка изменить только копии оригинала. Таким образом, вы заметите, когда мы передаем строку в Printf Вы не должны поместить звезду перед ним, как мы делали со всеми другими разыменовывает, верно? Так что, если вы печатаете из всей строки с% ожидает, что это адрес, и в этом случае указатель или в данном случае, как массив символов. Персонажи, символ * с, и массивы одно и то же. Указатель состоит в символы и символьные массивы одно и то же. А так, все, что мы должны сделать, это передать в указатель. Мы не должны проходить в как указатель * или что-нибудь подобное. Таким образом, массивы и указатели одно и то же. Когда вы делаете что-то вроде X [Y] здесь для массива, что он делает под капотом это говорит, хорошо, что это массив символов, так что это указатель. И поэтому х одно и то же, и так, что он делает это добавляет г х, что то же самое, что двигаться вперед в памяти, что много. А теперь х + у дает нам какой-то адрес, и мы разыменовать адрес или следить за стрелками где это место в памяти, и мы получим значение из этого места в памяти. Таким образом, так что эти две точно такие же вещи. Это просто синтаксический сахар. Они делают то же самое. Они просто разные синтактика друг для друга. Итак, что может пойти не так с указателями? Мол, много. Хорошо. Так, плохие вещи. Некоторые плохие вещи, которые вы можете сделать, не проверяя, если ваш таНос вызов возвращает нуль, верно? В этом случае, я прошу системы, чтобы дать мне - что это за номер? Мне нравится 2 миллиарда раз 4, так как размер целое 4 байта. Я спрашиваю его для как 8 миллиардов байт. Конечно, мой компьютер не будет в состоянии дать мне, что столько же обратно памяти. И мы не проверить, если это нуль, поэтому, когда мы пытаемся разыменования его там - следить за стрелками, где она собирается - у нас нет этой памяти. Это то, что мы называем разыменования нулевого указателя. А это существенно заставляет Вас падать. Это один из способов сегментации. Другие плохие вещи, которые вы можете сделать - да ладно. Это было разыменования нулевого указателя. Хорошо. Другие плохих вещей - ну, чтобы исправить, что вы просто поставьте галочку там , которая проверяет, является ли указатель является нулевым и выйти из программы, если она случается, что таНос возвращает нулевой указатель. Это XKCD комиксов. Люди понимают это сейчас. Вроде того. Таким образом, память. И я пошел по этому поводу. Мы призываем таНос в цикле, но каждый раз, когда мы называем таНос мы теряем отслеживать, где этот указатель указывает на, потому что мы удалив его. Таким образом, первоначальный вызов таНос дает мне памяти здесь. Моя указатель указатели на это. Теперь, я не освободить его, так что теперь я называю таНос снова. Теперь он указывает здесь. Сейчас в моей памяти указывает здесь. Указывая здесь. Указывая здесь. Но я потерял все адреса памяти здесь, что я выделил. И вот теперь у меня нет никаких ссылок на них больше. Таким образом, я не могу освободить их за пределами этого цикла. И поэтому для того, чтобы исправить что-то вроде этого, если вы забыли, чтобы освободить память, и вы получите эту утечку памяти, Вы должны освободить память, внутри этой петли, как только вы сделали с ним. Ну, это то, что происходит. Я знаю, многие из вас ненавижу это. Но теперь - ура! Вы получаете как 44000 килобайт. Таким образом, вы освободите его в конце цикла, и что собирается просто освободить память каждый раз. По сути, ваша программа не имеет утечки памяти больше. А теперь что-то еще, что вы можете сделать, это освободить часть памяти, что вы просили в два раза. В этом случае, вы таНос что-то, вы измените его значение. Вы освободить его сразу, потому что вы говорили, что сделали с ним. Но тогда мы освободили его снова. Это то, что очень плохо. Он не собирался изначально сегментации, но через некоторое время, что это будет двойное освобождение этой портит вашу кучу структуры, и вы узнаете немного больше об этом, если вы решили взять класс, как CS61. Но по существу, через некоторое время ваш компьютер будет запутаться о том, что ячейки памяти, куда и где он хранится - где данные хранятся в памяти. И поэтому освобождение указателя дважды это плохо, что вы не хотите делать. Другие вещи, которые могут пойти не так, не использует SizeOf. Таким образом, в этом случае вы Malloc 8 байт, и это то же самое, что и два целых числа, правильно? Таким образом, это совершенно безопасно, но это такое? Ну, как Лукас говорил о на разных архитектурах, целых чисел различной длины. Так, на устройство, которое вы используете, целые около 4 байта, но на некоторых других системах они могут быть 8 байтов или они могут быть 16 байт. Так что, если я просто использовать этот номер здесь, эта программа может работать на приборе, но он не собирается выделить достаточно памяти на некоторые другие системы. В этом случае, это то, что оператор SizeOf используется. Когда мы называем SizeOf (INT), что это делает  это дает нам размер целого в системе, что программа работает. Таким образом, в данном случае, SizeOf (INT) вернет 4 на что-то вроде прибора, и теперь это будет 4 * 2, что на 8, , который является только объем пространства, необходимого для двух целых чисел. На другой системе, если Int, как 16 байт или 8 байтов, это просто собирается вернуться достаточно байта для хранения этой суммы. И, наконец, структуры. Так что, если вы хотите сохранить судоку доска в память, как мы могли бы это сделать? Вы можете представить себе, как переменной для первой вещью, переменных для второго вещь, переменная третья вещь, Переменная за четвертый вещь - плохо, верно? Так, один улучшению вы можете сделать на верхней части этого сделать 9 х 9 массива. Это прекрасно, но что, если вы хотите, чтобы связать другие вещи с доски судоку нравится то, что трудности платы, или, к примеру, что ваш счет, и сколько времени это заняло вам решить эту конференцию? Ну, что вы можете сделать, вы можете создать структуры. То, что я в основном говорю я определяю эту структуру здесь, и я определяю судоку борту которого состоит из платы, что составляет 9 х 9. И то, что она у него есть указатели на имя уровне. Она также имеет х и у, которые являются координатами, где я нахожусь сейчас. Он также время, затраченное [неразборчиво], и он имеет общее число ходов я введенные до сих пор. И поэтому в данном случае, я могу сгруппировать целую кучу данных в одну структуру вместо того, чтобы, как он летает в как различные переменные что я не могу отслеживать. И это позволяет нам иметь просто хороший синтаксис для рода ссылки разные вещи внутри этой структуры. Я просто могу сделать board.board, и я получаю судоку доска назад. Board.level, я понял, как тяжело это. Board.x и board.y дать мне координаты, где я мог бы быть в совете. И поэтому я доступе, что мы называем поля в структуре. Это определяет sudokuBoard, который является типом, который у меня есть. И вот теперь мы здесь. У меня есть переменная называется "доска" типа sudokuBoard. И вот теперь я могу получить доступ ко всем полям, которые составляют эту структуру сюда. Любые вопросы о структурах? Да? [Студент] Для Int х, у, вы объявили обе на одной линии? >> [Иосиф] Угу. [Студент] Таким образом, вы могли бы просто сделать это с ними со всеми? Как и в х, у запятой раз, что общее? [Джозеф] Да, можно определенно сделать это, но причина, я положил х и у на той же строке - и вопрос в том, почему мы можем просто сделать это на той же линии? Почему мы не просто поставить все это на одной линии х и у связаны друг с другом, и это только стилистически более правильно, в определенном смысле, потому что это группировка две вещи, на той же линии что, как и рода относятся к одной вещи. И я просто разделить эти части. Это просто стиль вещь. Это функционально делает никакой разницы. Любые другие вопросы, касающиеся структуры? Вы можете определить с Pokédex структуры. Покемон имеет номер и он имеет письме, владелец, тип. И потом, если у вас есть массив из покемонов, вы можете составить Pokédex, верно? Хорошо, прохладно. Таким образом, вопросы о структур. Это связано с структурам. Наконец, GDB. Что GDB позволяют вам делать? Это позволяет отлаживать вашу программу. И если вы не использовали GDB, я бы рекомендовал смотреть на короткое и как раз собирался за то, что GDB является, как вы с ним работать, как вы можете использовать его, и проверить его на программу. И то, что GDB позволяет вам делать это позволяет приостановить [неразборчиво] до вашей программы и практической линии. Например, я хочу, чтобы приостановить выполнение в строке 3, как из моей программы, и пока я на линии 3 я могу напечатать все значения, которые есть. И так, что мы называем, как пауза в линию это мы называем это положить останова на этой линии и тогда мы сможем распечатать переменных на состояние программы в то время. Мы можем затем оттуда пройти по программе линия за линией. И тогда мы можем посмотреть на состояние стека в то время. И так, чтобы использовать GDB, что мы делаем, мы называем лязг на файл C, но мы должны его пройти, ggdb флаг. И как только мы закончим с этим, мы просто запустить GDB на результирующий файл вывода. И поэтому вы сможете получить некоторые, как масса текста, как это, но на самом деле все, что вам нужно сделать, это ввести команды в самом начале. Перерыв основные ставит точку останова на основной. Список 400 перечислены строк кода вокруг линии 400. И поэтому в этом случае вы можете просто посмотреть вокруг и сказать, ой, Я хочу, чтобы установить точки останова в строке 397, который эту линию, и тогда ваша программа работает на такой шаг, и он собирается сломать. Это собирается сделать паузу там, и Вы можете распечатать, например, значение низкое или высокое. И так есть куча команд, которые вы должны знать, и это слайд-шоу будет идти на сайт, так что если вы просто хотите, чтобы ссылки на эти или, как положить их на свой шпаргалок, не стесняйтесь. Cool. Это была викторина отзыв 0, и мы будем придерживаться вокруг, если вы имеете любые вопросы. Хорошо.  [Аплодисменты] [CS50.TV]