[Powered by Google Translate] Раздел проблеме Set 2: Hacker издание
Роб Боуден, Гарвардский университет
Это CS50. CS50.TV
Так вот, я Роб. Я старший в Kirkland. Это мой третий год TFing CS50.
Это первый раз, когда мы меняем от традиционных лекций стиль раздела,
где мы только отчасти отзыв, что произошло в лекцию, а затем вы, ребята, задавать вопросы,
Теперь, чтобы быть намного больше проблем на основе, где мы используем пространства, и -
О, так идея пойти в ссылку, что Я послал тебя, и тогда вы будете в моем пространстве.
Кто-нибудь нет ноутбука? Хорошо.
Таким образом, мы будем использовать это, и мы собираемся делать проблемами живут в разделе
и обсуждать их и выяснить, что случилось
и я мог бы подтянуть некоторые из вашего кода, и я мог бы обсудить ваши идеи.
Так кто-нибудь с трудом?
Вы можете общаться на сторону, я не знаю, если мы будем иметь основания для этого.
Теперь, как и в предыдущем supersection, если вы были в этом классе, вы знаете, что это о.
На всех множеств P там будет в этих разделах.
Таким образом, P-набор 2, спецификации, я думаю, вы видели это на P-1 уже множество.
Но мы можем посмотреть на P-комплект 2 за то, что мы собираемся идти на сегодня.
И вы увидите раздел вопросов.
Таким образом, это будет во всех P-множеств, там будет раздел вопросов.
До сих пор мы говорили, "Рассмотрим эту возможность на практике".
Вы не будет предложено представить эту программу.
Идея состоит в том, что это, как предполагается, вид помочь вам начать с проблемой набора.
Я думаю, на Hacker издание, многие из них должны быть просто новые, интересные вещи, чтобы учиться.
Они не могут быть непосредственно применимы к проблеме набор.
И сейчас мы не имеющие вы представить их, но в теории,
для последующего множества проблем, вы можете представить их, и таким образом, вы можете прийти к разделу
или посмотреть раздел, чтобы получить ответы на вопросы, или вы можете просто получить их по своему усмотрению
Если вы не чувствуете, как наслаждаться своим присутствием.
Так что - я думаю, это первое.
Ох. Кроме того, в этих разделах вопросы мы и вы будете задавать вопросы о шортах.
Так что я думаю, в теории, вы должны смотреть на этих до приезда в разделе
но это прекрасно, если вы этого не сделаете, мы пойдем на них в любом случае.
Таким образом, мы можем начать с этим: «Как в то время как цикл отличается от сделай то время как цикл?
Когда последняя особенно полезно? "
Таким образом, у кого-нибудь -
[Студент] сделай то время как цикл будет всегда выполнять по крайней мере, один раз.
Да. Так что есть разница. Время цикла - I'll просто сделать это здесь - в то время как петля, имеем условие
прямо здесь, в то время как сделай то время как, у вас нет условий пока мы не получим здесь.
И поэтому, когда ваши программы выполняется, и он попадает в то время как цикл,
он сразу проверяет, если это условие истинно.
Если это условие не выполняется, это будет просто пропустить цикл полностью.
Сделай то время как цикл, так как программа выполняется, он добирается до "делать".
Ничего не происходит в этот момент, просто продолжает выполняться.
Потом, когда она попадает на ", а", если условие истинно, это будет цикл вернуться и сделать это снова
и снова, и снова, пока условие не выполняется, а затем просто проваливается.
Таким образом, разница в том, что это может пропустить с самого начала.
Это обязательно выполняется один раз и затем может выполнить более раз, если условие остается в силе.
Таким образом, в то время как цикл будет делать это только один раз, или - в то время как петли - мы не должны делать это на всех,
поскольку, как только мы доберемся до него, если условие ложно, мы просто сразу перейти на него.
Принимая во внимание, сделай то время как цикл, мы будем выполнять его один раз, обязательно.
Потом, когда мы дойдем до состояния, мы проверяем, если это правда или ложь.
Если это правда, мы сделаем это снова, если оно ложно, мы просто продолжаем идти.
Так, когда последний особенно полезно?
Поэтому я могу сказать, что в совокупности 4 года, 3 года, что угодно,
что я занимался программированием, я использовал это, как, по 10 раз.
И, наверное, 5 из них находятся в CS50, когда мы представляем делать, в то время как петли.
Поэтому, когда вы использовали делать-то время петли?
Когда - да?
[Студент] Когда вы пытаетесь получить пользовательский ввод, или то, что вы хотите проверить -
Да. Так что, в то время как петли, что вводит пользователь, большой.
Вот почему на первых наборов проблема пары, когда вы хотите спросить у пользователя, как,
"Дайте мне строку," вы не можете продолжать, пока вы не получите эту строку.
И поэтому вы, обязательно, необходимо обратиться за строкой по крайней мере, один раз.
Но тогда, если они отвечают что-то плохое, то вы должны цикла назад и спросить еще раз.
Но кроме ввода данных пользователем, это очень редкое, что я сталкиваемся со случаем
, где я хочу, чтобы петля "по крайней мере один раз", но, возможно, больше.
Вопросы или -? Кто-нибудь использовал сделай то время как цикл где-нибудь еще?
Хорошо. Таким образом, следующий: "Что же необъявленный идентификатор
обычно указывают, если выдаваемых звон? "
Так какой код я могу написать, чтобы получить «необъявленный идентификатор?
[Студент], что х = 2?
Так что мы можем только попробовать его здесь, х = 2.
Мы будем работать это - ой, я не щелкните по нему. И вот мы получаем - все в порядке.
"Использование необъявленных х идентификатор".
Так вот необъявленный идентификатор, переменная.
Это часто называют переменной идентификатор.
Таким образом, она может не знать, что это на самом деле переменная, она не знает, что это такое.
Так что это идентификатор.
Так почему же это необъявленная? Да.
Таким образом, чтобы внести ясность в терминологию, объявление переменной
это когда вы говорите "Int х", или "у строки," что угодно.
Инициализации переменной или назначение переменной,
это всякий раз, когда вы говорите "х = 2".
Таким образом, мы можем сделать это в отдельных шагов, Int х, х = 2, а пока - мы можем иметь кучу вещей здесь -
но до этой линии происходит, х еще не инициализирована, но она была объявлена.
И поэтому, очевидно, можно сделать это в 1 линию, и теперь мы объявляем и инициализации.
Вопросы?
И, наконец, "Почему шифр Цезаря не очень безопасно?"
Итак, во-первых, кто-нибудь хочу сказать, что шифр Цезаря?
[Студент] Caesar Cipher только то, что Вы карте, вы переложить каждую букву,
определенное количество букв перейти и вернуться за, и это не очень безопасно, потому что
есть только 26 возможных вариантов, и вы просто должны попробовать каждое 1 из тех, пока вы не получите его.
Ох. Так что, я должна повторять?
Шифр Цезаря, it's - я имею в виду, вы будете иметь дело с его проблемами, что вы -
или я думаю, что и стандартная редакция поставленной задачи это не на хакерской издание.
Таким образом, на стандартном издании поставленной задачи, вы получите сообщение типа: "Привет, мир"
и у вас также есть ряд как 6, и вы принимаете это сообщение, и каждый индивидуальный характер,
Вы поверните его на 6 позиций в алфавите.
Таким образом, 'H' в Привет станет ч-и-т-к-л-м-н.
Таким образом, первое письмо будет п. Мы делаем то же самое с электронной.
Если у нас есть, вроде бы, г или что-то, то мы закончим обратно к '.
Но каждый персонаж получает циклическое 6 символов позже в алфавите, а это не очень безопасно
так как есть только 26 возможностей для сколькими способами можно обернуть одну букву.
Таким образом, вы можете просто попробовать все 26 из них, и, по-видимому, в течение достаточно длительного сообщение
только 1 из возможных 26 вещей будет разборчиво,
и разборчиво, никто не собирается быть исходное сообщение.
Так что это не очень хороший способ шифрования вообще ничего.
Вне всякой связи с тем, шорты, "Что такое функция?"
Так что же такое функция? Да.
[Студент] Это как отдельный кусок кода, который вы можете позвонить, чтобы пройти, а затем получить возвращаемое значение угодно.
Да. Так я отвечу на него также ответить на следующий - или повтор от также просто ответив на следующий.
Вы можете использовать функции, а не просто скопировать и вставить код снова и снова.
Просто возьмите этот код, положил его в Fuction, а затем вы можете просто вызвать функцию
где бы вы ни были копирования и вставки.
Таким образом, функции полезны.
Так что теперь мы будем делать актуальных проблем.
Первый. Так что идея первого, вы передаете его строки, и независимо от того, -
или же она сказать, что все строчные? Не сказать, что все в нижнем регистре.
Таким образом, сообщение может быть что угодно, и - о, нет. Это делает.
"Для простоты можно считать, что пользователь будет только вход строчные буквы и пробелы".
Таким образом, мы передаем ему сообщение с только строчные буквы, а затем мы чередовать
между капиталом и строчные - мы изменим строку в заглавные и строчные, чередуя.
Поэтому, прежде чем дать вам второй даже погрузиться в проблему,
что первое, что мы должны сделать?
Ах, какой же я просто нажмите на? О, я просто нажал на электронную здесь.
Поэтому первое, что мы должны сделать, - я смотрю не тот?
Является ли это частью этого?
Нет, это все еще там, хотя.
Ладно, все еще здесь.
Сейчас мы не можем предположить - Да. Здесь мы не можем предположить, что это только строчные и пробелы.
Так что теперь мы имеем дело с тем, что письма могут быть какими мы хотим их видеть.
И поэтому первое, что мы хотим сделать, это просто получите сообщение.
Нам просто нужно, чтобы получить String, String S = GetString, хорошо.
Теперь эта проблема, есть несколько способов сделать это.
Но мы собираемся хотите использовать битовые операторы здесь.
Есть люди, которые либо не были в supersection,
или что-то, и не знаю, что побитовое операторов?
Или, как они относятся к ASCII в любом случае?
[Студент] Я не был на supersection, но я знаю, что побитовое операторов.
Хорошо. Тогда я не должен идти по основам из них, но я объясню
то, что мы собираемся хотите использовать здесь.
Таким образом, 'A': Двоичное представление капитал, число 65.
Я просто буду смотреть на - 41 будет 01000001.
Так что должно быть 65 в десятичной, так что это двоичное представление символа столицы A.
Теперь, двоичным представлением символов нижнего регистра 'а'
будет то же самое, почти. Это - 6, да. Это правильно.
Таким образом, двоичный капитала, двоичные строчная '.
Так заметить, что разница между А и 'а' это один бит.
И это случается, 32 бит, бит, представляющий число 32.
И это имеет смысл, поскольку является 65; 'а' 97.
Разница между ними 32.
Итак, теперь мы знаем, что можем преобразовать от А до 'а', беря
и битовые ORing это, с - которая выглядит как 1.
Это побитовое ИЛИ, с 00100000, и что даст нам ".
И мы можем получить от 'А' до логического умножения на Побитовая
с 11, 0 в том месте, 11111.
Таким образом, это даст нам именно то, что 'а' было, но отменить эту отдельного бита,
так что нам придется 01000001, я не знаю, если я насчитал права.
Но эта техника Побитовая ORing, чтобы получить от столицы в нижний регистр,
и битовые операции AND, чтобы получить из нижнего регистра в столицу не только для А.
Все письма, K против K, Z против г,
все они только собираются отличаются этом один бит.
И поэтому вы можете использовать это, чтобы изменить любой строчной буквы любой буквы, и наоборот.
Хорошо. Так простой способ получить из этого - так вместо того, чтобы
написать все, что есть 1011111 - легкий способ представления этого числа, а это не один
что я пошел в supersection, но тильды (~) является еще одним побитового оператора.
Что ~ делает это смотрит на битное представление.
Давайте возьмем любое число.
Это лишь некоторые двоичные числа, и то, что делает ~ это просто переворачивает все биты.
Так что это было 1, теперь 0, то это 0, сейчас 1, 010100.
Так что это все ~ делает. Таким образом, 32 будет номер - избавиться от этого -
32 так будет номер 00100000, и так ~ этого будет
этот номер здесь, что я операция AND '' с.
Все ли видели? Это довольно распространенная, как и когда вы хотите, чтобы выяснить
для последующего вещи, которые мы могли бы видеть, когда мы хотим увидеть, если -
или мы хотим, чтобы все, каждый набор бит за исключением 1
Вы склонны делать ~ из немного, что мы не хотим установить.
Таким образом, мы не хотим в 32 бит, поэтому мы ~ 32.
Хорошо. Так что мы можем использовать все тут.
Ладно, это прекрасно, если вы не сделали, мы должны медленно ходить по совокупности
или ходить по этому поводу, так - через это. Пройдите через это.
Таким образом, у нас есть строка, и мы хотим, чтобы цикл по каждому символу в строке, что и делать что-то для этого.
Так как же мы цикл по строке? Что мы должны использовать?
Я не собираюсь делать это здесь. Да.
Так что у меня есть итератор, и он сказал, что это, но как я могу знать, сколько символов в строке?
STRLEN (ы), то я + +.
Так что я здесь сделал, это не лучший способ делать вещи.
Кто-нибудь знает, почему?
Потому что вы проверяете на языке строку каждый раз.
Таким образом, мы собираемся хотите переместить StrLen, я мог бы сказать здесь, внутр длина = StrLen (ы),
и тогда я <длина, а в случае, если вы не видели это раньше,
Я мог бы также сделать Int = 0, длина = StrLen (ы).
И так это несколько предпочтительнее, так как теперь я ограничила сферу
переменной длины всего этого 'для' цикл, вместо того, чтобы объявить его до
и что оно всегда существует, и в случае, если вы не заметили, почему это плохо,
или почему оригинальная было плохо, it's - начать с цикла.
Я проверил состояние. Это я <длина с?
Таким образом, длина с, давайте поработаем с "привет" все время.
Таким образом, длина S, Н-е-л-л-о. Длина 5.
Так что я = 0, длина 5, так что я не <5, так что цикл продолжается.
Тогда мы идем снова. Мы проверяем состояние. Это я <длина Привет?
Так давайте проверим длину привет. Н-е-л-л-о. Это 5, я не <5, поэтому мы продолжаем снова.
Таким образом, мы рассчитываем, мы рассчитываем привет, для каждой итерации,
даже не думал, что это никогда не изменится, он всегда будет 5.
Так что мы просто помним 5 до передней, и теперь все лучше.
Таким образом, итерации по всей строке.
Что мы хотим сделать для каждого символа строки?
[Студент говоря, неразборчиво]
Да. Таким образом, если персонаж находится неалфавитных, то мы просто хотим, чтобы пропустить его.
Потому что мы заботимся только о букв алфавита, мы не можем воспользоваться номером.
Так как мы можем это сделать? Таким образом, наши условия, поэтому если мы хотим что-то - проверить, если он алфавитном порядке.
Так как же нам проверить это?
[Студент] Вы можете просто использовать функцию альфа.
Это включено в любой из этих или любых включают как, char.h, что ли?
Давайте не будем использовать это альфа функции, и использовать явное - так у нас с [я],
, что является восьмым характера с, помните, что строка представляет собой массив символов,
так восьмом характера с.
Теперь, если это буква, мы знаем, что должно быть в определенном диапазоне.
И что это за действия?
Да. Таким образом, если с [я] составляет ≥ 65 лет, и с [я] составляет ≤ 90, что я должен делать вместо этого?
Да. Таким образом, вы должны быть абсолютно даже не нужно знать ASCII значения ни о чем никогда.
Никогда не думайте из чисел 65, 90, 97 и 102, или что это такое.
Вам не нужно - 112 - вы не должны знать тех, кто вообще. Это неправильно тоже.
Используйте только одинарные кавычки символов, одним константы цитаты. Таким образом, 'A' и менее 90 является "З."
И это значительно лучше - я не знаю, с верхней части моей головы, что Z = 90.
Я знаю, с верхней части моей головы, что 'Z' является столицей Z.
Так что, пока это находится в диапазоне капитала к капиталу Z, или мы можем проверить нижнем регистре,
Или, если она находится в диапазоне ≥ 'а' и ≤ г.
Так что это наше условие.
Стиль, где поставить эти вещи меняется.
Я сделаю это, как это.
Итак, что же мы хотим сделать?
Мы знаем, что это письмо характер, алфавита.
Так что мы должны чередоваться ли это теперь должно быть буквы или строчной буквы.
Как мы отслеживаем, один из которых мы хотим быть?
[Студент голоса, неразборчиво]
Так что, да, но позвольте мне проверить.
Модуль 0-2 было сказано, было предложение выброшены, и я с этим согласен.
Кроме заметить, что, например, - это случай? Да.
Это каждый второй, но мы не можем модуль 2 я, или я модулю 2, так как
заметить, что E является столицей и 'а' в нижнем регистре? Но есть пространство, разделяющее их?
Таким образом, они будут такими же, по модулю 2, но они разные случаи.
[Студент вопрос, неразборчиво]
Да. Так что мы просто будем держать счета.
Мы могли бы также сделать это здесь, если мы хотели, то могли бы получить немного громоздким
в цикле заявления, я положу его здесь.
Так соипЬ = начинается с 0.
И вот теперь, я буду считать, сколько буквенные символы, которые мы имели.
Таким образом, мы неизбежно будем рассчитывать + +, так как мы нашли другого алфавита.
Но, так что теперь вы говорите, если количество модулю 2.
Так что, если количество модулю 2? Ох. Я сделаю == 0 на данный момент.
Мы также будем идти по этому поводу. Таким образом, если количество мод 2 == 0, то что?
[Студенты ответ, неразборчиво]
Таким образом, мы хотим, чтобы он в конечном итоге в верхнем регистре.
Есть 2 случаях; прописных и строчных являются 2-х случаях.
Так что, если мы в нижнем регистре, мы должны сделать это верхний регистр.
Если это прописные нам не нужно ничего делать.
Но есть способ - shouldn't было перевернуто -
что мы даже не нужно проверить, является ли это Прописная или строчная?
Что мы можем сделать, чтобы всегда убедиться, что мы всегда в конечном итоге в верхнем регистре?
Так заметить, что мы сделали в нижнем регистре ";, что если бы мы сделали это точно такой же вещи в верхний регистр?
Есть ли верхний регистр изменения, или же изменение значения?
Да. Таким образом, любая буква побитовые операции AND с ~ 32 будет тот же символ верхнего регистра
потому что для любого символа в верхнем регистре 32-й бит не установлен.
Таким образом, если мы хотим принести характера с [я], мы хотим, чтобы он стал строчных или прописных букв.
Так что, если это было в нижнем регистре, то теперь прописными буквами, если бы это был верхний регистр, он по-прежнему прописными буквами, вот и все.
Я сказал об этом в supersection: Вы можете использовать 32, если вы хотите, но я предпочитаю делать "а" -,
вместо того, чтобы просто 32, потому что это может быть любая другая немного.
После того, как 32-разрядные, это может быть любой из них, или у нас не будет достаточно
Номера для представления всех символов.
Так что, если вы получаете 32 бит, это может быть 64 бит, это может быть 128 бит.
Любой из этих битов может быть немного, что различие между прописными и строчными буквами.
Я не должен знать, что это 32 бит.
Я могу использовать эту "а" - чтобы получить немного отличается, что между двумя
без необходимости полагаться на магическое число, которое равно 32.
И вот теперь, иначе рассчитывать было странно, так что я хочу делать?
[Ответы студентов, неразборчиво]
[Студент] Что это?
Я сделаю это за 1 секунду.
Так что теперь, если я хочу - я хочу, чтобы убедиться, что персонаж находится сейчас в нижнем регистре,
и так я могу или на 32, и "'32 смысл - A.
Но заметьте, по тем же соображениям, что и предыдущий, что если
Письмо было уже нижнем регистре, а затем на 32 ORing просто держит его нижний регистр.
Он не изменил первоначальный характер.
Но теперь у меня нет, чтобы не сказать: "Если в нижнем регистре, просто забыть о нем,
если это прописные, а затем изменить его ».
Это гораздо удобнее делать это.
[Студент] Будет ли эта стратегия вычитания из заглавных строчных работу, если бы не 32?
Если бы это было, вроде, 34 или что-то?
Таким образом, вы должны знать, что разница между 2 является -? >> 1 бит.
Это может быть больше, чем 1 бит, пока все биты ниже этой позиции совпадают.
Так что нам нужно по крайней мере 26 символов - или, существует 26 знаков.
Так что нам нужно по крайней мере 26 номеров представляют собой разницу -
Разница между и '' должен быть не менее 26,
иначе мы бы не были представлены все номера капитала.
Это означает, что, если мы начнем с 1, он собирается использовать все эти биты,
Все эти первые 5 бит, представляют все через Z.
Вот почему следующий бит, или этот бит, следующий бит является тот, который выбран, чтобы различать и '.'
Это также, почему в ASCII таблице, существует 5 символов разделения заглавными буквами от строчных букв.
С тех пор являются символами, что дополнительные 5 воспитывает 32-бытия разница между ними.
[Студент] Таким образом, мы можем это сделать, потому что ASCII разработана таким образом.
Да. Но ASCII - разница может быть также оба этих бита.
Мол, если были 10000001 и 'а' был 11100001 - я забыл, что угодно.
Но если бы это было, то мы все еще можем использовать '' - A.
Это просто сейчас разница между А и 'а' по-прежнему эти 2 бита.
Я думаю, что это написано 48. Это 32 + 64? Я думаю, что это?
Он все равно будет 2 бита, каждый отдельный символ, вроде бы, Z и Z, K и K,
они до сих пор точно такой же биты, за исключением тех 2 бита.
Так что, пока что это всегда так, независимо от того, если мы используем ASCII или другие системы,
пока есть только определенное количество битов, которые различны для каждого персонажа,
то, что хорошо работает.
Это просто, что 32 была создана потому, что это первый, который мы могли бы использовать. >> Cool.
Я предпочитаю, в случае, если вы не видели, если блок является лишь одной строки,
Вы можете избавиться от фигурные скобки, так что я предпочитаю делать это.
Кроме того, вы знаете, как мы можем делать такие вещи с [я] + = 1?
Вы также можете сделать с [я] побитовое И = 32.
И побитовое OR = 32.
Кроме того, рассчитывать мод 2 == 0.
Поэтому помните, что - я не буду писать это - любое отличное от нуля значение истинно, и 0 неверно.
Таким образом, "если количество модулю 2 == 0" такой же, как говорят, "если не считать той 2".
Я бы, наверное, просто отменил линий и сказал: "если количество модулю 2,
у OR 1, еще у AND 1 ", так что мне не нужно" нет ".
Но это работает так же хорошо.
А что еще я могу здесь делать?
Вы можете сочетать их с тройной, если вы хотели, но потом, что бы просто сделать все грязнее
и, вероятно, более трудным для чтения, поэтому мы не будем этого делать.
Любой, есть какие-либо другие предложения?
Это все, что проблема просил? Ах да.
Так что избавиться от этих пустых строк, теперь мы будем печатать F,% ы быть один для строки,
Мы будем печатать F, S.
Теперь давайте запустим его. Я сделал что-то не так?
Это \ ", я хочу н.
Хорошо. Теперь мы будем запускать его. Это, наверное, кричать на меня.
STRLEN в string.h.
Так что это хорошая вещь о Clang это говорит вам, что он находится в,
вместо GCC, который просто говорит: "Эй, ты забыл что-то, я не знаю, что это было".
Но это скажет мне: "Ты должна включать string.h".
Так что я не подскажут ни на что, так что это ничего не говорю.
Но мы будем делать их, например, "Спасибо 4 Добавить".
Это выглядит правильно. Ура.
Таким образом, возвращаясь к вашей основной, я почти никогда не делают этого.
Это необязательно. А главное это единственная функция, для которых он не является обязательным.
Если вы ничего не возвращают от главного, то предполагается, что вы хотели возвращать 0.
Вопросы?
Хорошо. Так что теперь вторая проблема.
"Вспомните из второй лекции неделю 2 о том, что замена значения 2 переменных, передавая
эти 2 переменные функции (даже если называют своп) точно не работает, по крайней мере, не без «указатели».
И игнорировать указатели, пока мы не получим на них.
Мы хотим, чтобы поменять 2 переменные, мы не используем функцию сделать это.
Мы все еще собираемся сделать это в главном, как он говорит.
Но использовать эти 2 переменные, мы не хотим использовать временную переменную.
Есть 2 способа сделать это.
Вы можете сделать это с помощью традиционных бинарных операторов.
Так кто-нибудь знает быстрый и грязный способ сделать это?
Это действительно может занять минуту мышления. Если у меня есть -
Я поставил задачу вверх, как они просят. Так что, если у меня есть 2 переменные, A, который находится всего в целое
что они дают мне, и суммой переменных B, которая является еще одним целым, что мне дают.
Так что, если у меня есть эти 2 переменные, теперь я хочу, чтобы поменять их местами.
Традиционно, с помощью регулярных бинарных операторов, я имею в виду, например, +, -, ÷.
Не битовые операторы, которые действуют на двоичный.
Таким образом, использование -, +, ÷, и всех тех.
Мы могли бы поменяться, делая что-то вроде = A + B, и B = A - B, A = A - B.
Таким образом, проверка исправности, и тогда мы увидим, почему это работает.
Скажем = 7, б = 3, то A + B будет 10.
Так что мы теперь полагая а = 10, а затем мы делаем B = A - B.
Таким образом, мы делаем B = A - B, который будет 7, а B = A - B снова,
или = A - B. Какой будет 10 - 7, которая является 3.
Так что теперь, правильно, "а" было 7, б было 3 года, и в настоящее время находится в 7 б и 'а' 3.
Так что вид имеет смысл; «а» является сочетание 2-х номеров.
На данный момент, 'а' это сочетание, а затем мы вычитания из оригинальных б,
а потом мы вычитанием, что было первоначальным ".
Но это не работает для всех номеров.
Чтобы убедиться в этом, давайте рассмотрим систему, поэтому мы обычно думаем о целых чисел в виде 32 бит.
Давайте работать на то, что, как только 4 бита.
Надеюсь, я придумал хороший пример прямо сейчас.
Так вот, я знаю, это будет нелегко.
Скажем, наши 2 номера 1111, и 1111, так что мы в двоичной прямо сейчас.
На самом знаков после запятой, если вы хотите думать о нем, таким образом, = 15 и B = 15.
И поэтому мы ожидаем, после того как мы обменять их - они даже не должны быть одинаковыми номерами,
но я сделал это таким образом.
Давайте сделаем их не одинаковыми номерами. Давайте сделаем 1111 и 0001.
Таким образом, = 15 и B = 1.
После того как мы поменять их местами, мы ожидаем "а" равно 1 и B на 15.
Таким образом, наш первый шаг = а + б.
Наши номера только 4 бита, так что "", который является 1111, + Ь, 0001,
будет в конечном итоге 10000, но у нас есть только 4 бита.
Так что теперь = 0.
А теперь мы хотим установить B = A - B - на самом деле, это все еще работает отлично.
= A - B - давайте посмотрим, если это работает отлично.
Тогда B = 0 - 1, которое все равно будет 15, а затем = A - B, который был бы 1.
Может быть, это действительно работает.
Я чувствую, что есть причина, она не работает с использованием регулярных.
Итак, работающий на предположении, что она не работает с обычными бинарными операциями,
и я буду искать - я Google, чтобы убедиться, что это правда.
Таким образом, мы хотим сделать это с помощью битовых операторов, и ключ здесь XOR.
Таким образом, введение XOR (^), если вы его еще не видела.
Это, опять же, оператор побитового так он действует по крупицам, и it's -
Если у вас есть биты 0 и 1, то это будет 1.
Если у вас есть биты 1 и 0, то это будет 1, у вас есть биты 0 и 0, это будет 0,
и если у вас есть биты 1 и 1 это будет 0.
Так что это как OR. Если один из битов правда, это 1, но в отличие от OR, оно не может быть и битами, которые являются истинными.
Или бы это быть 1, XOR бы это быть 0.
Таким образом, мы собираемся хотите использовать XOR здесь.
Задумайтесь об этом на минуту, я собираюсь Google.
Ну, вы не можете прочитать, что, я в настоящее время нахожусь на алгоритм подкачки страниц XOR.
Надеюсь, это будет объяснить, почему Я не могу -
Это именно алгоритм, который мы только что сделали.
Я все еще не понимаю, почему - я, должно быть, просто выбрал плохой пример,
но это случай, когда «а» произошло стать 0, после получения до 5 бит, так что теперь "а" равно 0,
это то, что называется "целочисленное переполнение".
Согласно Википедии, "в отличие от XOR подкачки, этот вариант требует, что она использует несколько методов
чтобы гарантировать, что х + у не вызывает переполнение целого ".
Так что это действительно есть проблемы, это было целочисленного переполнения, но я сделал что-то не так.
Я не уверен. Я постараюсь придумать другой.
[Студент] Ну, не целочисленное переполнение, когда вы пытаетесь поставить рядом там
больше, чем количество бит вы выделили?
Да. У нас есть 4 бита. That's - у нас было 4 бита, тогда попробуйте добавить к нему 1, так что мы в конечном итоге с 5 бит.
Но пятый бит просто получает отрезать, да.
Это могло бы на самом деле -
[Студент] Значит ли это, бросить вас об ошибке, или же, что - бы, что выдаст ошибку?
Номер Поэтому нет ошибки. Когда вы дойдете до уровня сборки, специальный бит
где-то установлено, что сказал, что переполнение, но в C вы вроде просто не справиться с этим.
На самом деле вы не можете справиться с этим, если вы используете специальные инструкции по сборке в C.
Давайте подумаем о XOR подкачки.
И я думаю, что статьи Википедии, возможно, также говорили, что -
Так он и воспитывался модульной арифметике, так что я думаю, я был, по идее, делать модулярной арифметики
Когда я сказал, что 0 - 1 в 15 раз.
Так что может на самом деле - на регулярной процессора, что делает 0 - 1 = 15.
Так как мы в конечном итоге на 0, мы вычитаем 1, так то просто оборачивает обратно к 1111.
Таким образом, этот алгоритм может на самом деле работают, A + B, A - B, B -, то может быть штраф.
Но есть некоторые процессоры, которые не делают этого, и поэтому он не будет хорошо в эти специфические.
XOR своп будет работать на любом процессоре. Хорошо.
Идея состоит в том, что он должен быть таким же, все же.
Где мы используем XOR каким-то образом получить информацию как в 1 переменных,
, а затем вытащить информацию из отдельных переменных снова.
Так кто-нибудь есть идеи / ответ?
[Студент ответ, неразборчиво]
Так это должно работать, а также, XOR является коммутативной.
Независимо от того, в каком порядке эти 2 номера случится быть в здесь,
Этот результат будет тот же.
Так ^ Ь Ь.
Вы также можете увидеть это в виде = B, B =, = б снова.
Таким образом, это право, и понять, почему это работает, думают о битах.
С помощью небольшого числа, скажем, 11001, 01100 и.
Так что это 'а', это б.
Таким образом, ^ = Ь.
Мы собираемся быть установлен в 'а' = к XOR эти 2 вещи.
Таким образом, 1 ^ 0, 1, 1 ^ 1 = 0, 0 ^ 1 = 1, и 0 ^ 0 = 0, 1 = 0 = 1.
Таким образом, ',', если вы посмотрите на десятичное число, оно будет -
Вы не увидите большую часть отношений между оригиналом "а" и нового ","
но, глядя на бит "," сейчас, как сетка информации
как оригинал "и оригинальные б.
Таким образом, если мы возьмем Ь, мы видим, что мы в конечном итоге на оригинал ".
А если взять оригинал "'^ новые", "мы видим, мы в конечном итоге на оригинальные б.
Таким образом, (Ь) ^ B = оригинал ".
И (Ь) ^ = оригинальные б.
Существует - еще один способ увидеть это ничего XOR сам всегда равен 0.
Таким образом, 1101 * 1101, все биты будет то же самое.
Так что там никогда не будет случай, когда 1 является 0, а другой равен 1.
Итак, это 0000.
То же и с этим. (Ь) ^ б, как ^ (Ь б).
(Б ^ б) будет 0, а Ф 0 только собирается быть "," так как все биты равны 0.
Таким образом, только те, которые собираются быть там, где «а» изначально был 1 - было из них.
И та же идея здесь, я уверен, что это также коммутативна.
Да. Я же говорю, до этого она была коммутативной.
^ ',' И это ассоциативные, так что теперь (Ь) ^.
И мы можем сделать, Ь (^).
И вот снова, мы получим оригинальный б.
Таким образом, '' теперь сочетание 'а' и б вместе.
Используя наш новый комбо "а" мы говорим, B = комбо '' ^ оригинальных б, получаем оригинальный '.
А теперь комбо = 'а' ^ новый б, который был оригинальным - и который теперь, что было "а" или б.
Вот этот случай здесь. Это = б, старая б.
Так что теперь все снова в порядке поменялись местами.
Если бы мы посмотрели на биты, B = ^ B, будет XOR этих 2,
и ответ будет этого, а затем = ^ Ъ XORing эти 2 и ответ заключается в следующем.
Вопросы? Хорошо. Таким образом, последний несколько значительно более трудным.
[Студент] Я думаю, что у него есть сомнения. >> Ой, простите.
[Студент] Что на самом деле быстрее? Если вы используете этот XOR, или это, если вы объявите новую переменную?
Так что же такое на самом деле быстрее, объявив новую переменную или с помощью XOR, чтобы поменять?
Ответ, по всей вероятности, временной переменной.
И это потому, что как только он составлен вниз - так, на уровне сборки,
нет такой вещи, как локальные переменные или временные переменные или любое из этого материала.
Они просто хотели - есть память, и есть регистры.
Регистры, где все активно происходит.
Вы не добавляете 2 вещи в памяти, вы добавляете 2 вещи в регистрах.
И вы приносите вещи из памяти в регистры затем добавить их,
а затем вы можете положить их обратно в память, но все действие происходит в регистрах.
Итак, когда вы с помощью временной переменной подход, как правило, происходит то,
эти 2 номера уже находятся в регистрах.
А потом с этого момента, после того как вы их местами,
это будет просто начать использовать другой регистр.
Где бы вы ни были использованием Ъ, это будет просто использовать регистр, который был уже хранении ".
Так что не нужно ничего делать на самом деле делать замены. Да?
[Студент] Но это также требует больше памяти, правильно?
Это займет больше памяти, если это необходимо для хранения, что временная переменная.
Например, если вы позже использовать эту временную переменную снова где-то,
Затем - или вы назначаете что-то, что временная переменная.
Так, если в любой момент времени ',' б в температуре имеют различные значения или что-то,
то это будет иметь различные места в памяти, но это правда, что
Есть много локальных переменных, которые существуют только в регистрах.
В таком случае, он никогда не ставил в память, и поэтому вы никогда не тратя памяти.
Хорошо. Последний вопрос немного больше.
Так вот, в этом CS50 прибор, есть словарь.
И причина этого в том, что [? B66] является проверка орфографии, где вы будете писать
с использованием хэш-таблиц или попыток или некоторые структуры данных.
Вы собираетесь писать проверки орфографии, и вы собираетесь использовать этот словарь, чтобы сделать это.
Но для этой задачи, мы просто будем смотреть вверх, чтобы увидеть, если одно слово есть в словаре.
Таким образом, вместо того чтобы хранить весь словарь в некоторой структуре данных
, а затем, оглядываясь на весь документ, чтобы увидеть, если ничего это неправильно,
Мы просто хотим, чтобы найти 1 слово. Итак, мы можем просто сканировать по всей словарь
и если мы никогда не найдем слово во всем словаре, то он не был там.
Если мы просматриваем по всей словарь и вижу слово, то, что мы хорошие, мы нашли его.
Здесь говорится, что мы хотим, чтобы начать смотреть на файл-функции обработки C, в
так как мы хотим, чтобы прочитать словарь,
но я дам подсказку здесь о том, какие функции вы должны думать.
Я напишу их на пространствах.
Таким образом, основными из которых вы хотите, чтобы смотреть на это открытая F, а затем, неизбежно, F замкнуто,
, которые пойдут в конце вашей программы, и е е сканирования.
Вы также можете использовать F читать, но вы, вероятно, не хотят
потому что - вы не в конечном итоге нужно это.
F сканирования F является то, что вы собираетесь использовать для сканирования по словарю.
И поэтому вам не нужно, чтобы закодировать до решения, просто попробуйте и, как псевдо-код свой путь
К раствору, а затем мы обсудим это.
А на самом деле, поскольку я уже дал вам это, если вы идете в любом терминале или оболочки прибора, в
Я хотел бы - я обычно - если вы еще не видели, я не знаю, если бы вы сделали в классе,
но человек, поэтому страницах мужчина, довольно полезно для глядя на почти любой функции.
Так что я могу сделать, вроде бы, MAN F, сканирование ф.
Это сейчас Информация о семье сканирования F функций.
Я мог бы также сделать MAN F, открытой, и что даст мне информацию об этом.
Так что, если вы знаете, какие функции вы используете, или вы читаете код
, и вы увидите некоторые функции, и вы вроде: "Что же это делать?"
Просто человек, что имя функции.
Есть несколько странных примеров, где вы могли бы сказать,
нравится. Человек 2, что имя функции, или человека 3, что имя функции,
но Вы только должны сделать, что если человек имя функции не бывает, чтобы работать в первый раз.
[Студент] Так что я читал справочную страницу для открытого, но я до сих пор путают о том, как его использовать и программы.
Хорошо. Многие мужчины страниц меньше, чем полезным.
Они более полезны, если вы уже знаете, что они делают
а затем вы просто должны помнить, порядок аргументов или что-то.
Или они могут дать вам общее представление, но некоторые из них очень подавляющим.
Как и F сканирования F, а также. Это дает вам информацию для всех этих функций,
и 1 строка здесь происходит, сказать: "F F сканирования считывает с точки строку или поток".
Но F открыть. Итак, как мы используем F открыто?
Идея программы, которые необходимо сделать файл ввода / вывода является то, что
Вы сначала нужно открыть файл, который вы хотите сделать что-то с, и неизбежно,
читать вещи из этого файла и делать вещи с ними.
F открытых то, что мы используем, чтобы открыть файл.
То, что мы вернемся, так что файл мы хотим открыть, она дает нам -
Здесь он говорит: "/ пользователя / доли / Dict / слова».
Это файл, который мы хотим открыть, и мы хотим, чтобы открыть его -
мы должны явно указать, хотим ли мы, чтобы открыть его для чтения или, если мы хотим, чтобы открыть его писать.
Там в пару комбинаций и прочее, но мы хотим, чтобы открыть это для чтения.
Мы хотим, чтобы чтение из файла.
Итак, что же это возвращение? Она возвращает файл звездочкой (*),
и я просто покажу все, что в переменной F, так *,
опять же, это указатель, но мы не хотим иметь дело с указателями.
Вы можете думать, как F, F теперь переменная вы собираетесь использовать для представления файла.
Так что, если вы хотите прочитать из файла, вы читаете из ф.
Если вы хотите, чтобы закрыть файл, вы закрываете ф.
Так, в конце программы, когда мы неизбежно хотят закрыть файл, то, что мы должны делать?
Мы хотим, чтобы закрыть ф.
Так что теперь последняя функция файл, который мы собираемся хотите использовать сканирование F, F сканирования ф.
И что, что делает это она сканирует на файл ищет шаблоном.
Глядя на мужчину странице здесь, мы видим Int F сканирования F, игнорировать возвращаемое значение на данный момент.
Первым аргументом является файл потока *, так что первый аргумент мы собираемся хотите передать IS-F.
Мы сканирования по ф.
Второй аргумент является строкой формата.
Я дам вам формат строки прямо сейчас.
Я думаю, что мы, случается, говорят, 127s \ п, много это ненужным.
Идея о том, что этот формат строки, что вы можете думать о е сканирование как противоположность печати ф.
Таким образом, печать F, F печати мы также используем этот тип формата параметра,
но в печати F то, что мы делаем, - давайте посмотрим на эквивалента.
Таким образом, печать е, и есть на самом деле также F печать F, где первый аргумент будет ф.
Когда вы печатаете F, мы могли бы сказать что-то вроде: "печать 127s \ п", а затем, если мы передадим ему некоторые строки,
он собирается напечатать эту строку, а затем с новой строки.
Какие средства 127, я уверен, но я никогда не ограничивал себя к нему,
Вы даже не нужно говорить '127 'в печатных F,
Но что это означает, распечатайте первые 127 символов.
Так что я уверен, что это так. Вы можете Google за это.
Но в следующий я почти уверен, это означает, что.
Так что это напечатать первые 127 символов, а затем с новой строки.
F сканирования F теперь, вместо того, чтобы, глядя на переменную и печать,
это будем смотреть на некоторые строки и сохранить шаблон в переменную.
Давайте реально использовать сканирование е в другой пример.
Так скажем, у нас были некоторые INT, х = 4,
и мы хотели создать строку сделан из - хотели создать строку
, что было похоже, это придет гораздо позже,
то, что точно так же как 4.jpg.
Таким образом, это может быть программа, где вы будете иметь сумму счетчика,
Подводя противодействию я, и вы хотите сэкономить кучу фотографий.
Итак, вы хотите сохранить i.jpg, где я некоторое итерации цикле.
Так как же нам сделать эту строку, что JPEG?
Если вы хотите распечатать 4.jpg, мы могли бы просто сказать, печать F,% d.jpg,
, а затем она будет печатать для этого JPEG.
Но если мы хотим сохранить строку 4.jpg, мы используем сканирование ф.
Таким образом, строка S - на самом деле мы не можешь - символ, символ S, давай 100.
Так что я просто заявили некоторые массив из 100 символов,
и вот что мы неизбежно будем хранить, что JPEG дюйма
Так что мы собираемся использовать сканирование е, и формат, как мы бы сказали,% d.jpg
для того, чтобы распечатать 4.jpg, формат этого будет d.jpg%.
Таким образом, формат% d.jpg, что мы хотим заменить% D, является х,
и теперь мы должны хранить эту строку где-то.
А где мы будем хранить эту строку в массиве с.
Таким образом, после этой строки кода, а, если мы печатаем F,% с переменной с,
он собирается печатать 4.jpg.
Таким образом, F сканирования F такая же, как сканирование F, только теперь она смотрит на этот файл
за то, что хранить в с.
Это то, что последний аргумент будет.
Мы хотим, чтобы хранить - "Scan е семейство функций сканирования и в соответствии с форматом, как пытался ниже.
Если хранится в расположении пунктов вы могли бы вернуться - "
Нет, мы могли бы быть хорошими. Позвольте мне думать ни на секунду.
Таким образом, сканирование F - нет, какого черта это функция, которая делает это?
Таким образом, сканирование F не собирается принимать целое и сделать точку JPG.
Это будет [бормочет].
Сохранить Int переменной в строку Int C.
Что это переменная, или то, что эта функция называется?
Да. That's - да. Так что я был определяющим для вас до этого был с печати F,
который - что намного больше смысла, поэтому я сказал, что это гораздо больше похоже печати ф.
Сканирование F-прежнему вроде как печать F, но с печати F будет проверить его на
и заменить переменные и теперь хранить его в строку.
Вместо печати, оно сохраняет его в строку.
Так что игнорировать полностью. Вы все еще можете думать формата, как такие печати ф.
Так что теперь, если мы хотели сделать 4.jpg вещь, мы будем делать с печати F, X об этом.
Так что сканирование F делает - то, что ваш вопрос будет?
[Студент] Я просто запутался в то, что мы пытаемся сделать прямо здесь
с JPEG. Можете ли вы объяснить, что 1 больше времени?
Так что это было - это менее relevent для сканирования F F теперь, надеюсь, он будет связывать еще в какой-то путь.
Но то, что я изначально собирался показать было - это на самом деле непосредственное отношение к этим [? F5]
Вы собираетесь использовать печать с F, где у нас есть 100 изображений,
и вы хотите читать 1.jpg изображения, 2.jpg, 3.jpg.
Поэтому для того, чтобы сделать это, вам нужно е открытое, а затем вы должны передать в строку, которую вы хотите открыть.
Таким образом, мы хотели бы открыть 1.jpg, для того, чтобы создать строку, которая 1.jpg,
Мы делаем печать с Р% d.jpg--мы не делали для Int = 0.
я <40, я + +.
Таким образом, с печать F% d.jpg ввода.
Таким образом, после этой линии, теперь переменная или массив, а собирается 1.jpg.
Или, 0.jpg, 1.jpg, 2.jpg. И таким образом мы можем открыть, в свою очередь, каждое изображение для чтения.
Так что то, что с печать F делает. Вы видите, что с печать F теперь делать?
[Студент] Итак, он принимает - он создает строку, something.jpg, а затем сохраняет его.
Да. Это создает - это еще одна строка формата, как сканирование и печать F F,
, где он вставляет все переменные во втором аргументе, может быть ей, в отличие от меня.
Может быть - я имею в виду, что это так. Но в любом порядке аргументов.
Это будет вставить все переменные в строку формата
, а затем сохранить в нашем буфере; мы называем это буфер, где мы хранения строки.
Таким образом, мы храним внутри с правильной строки в формате,% D будучи заменены 4.
[Студент] Таким образом, если бы мы сделали это, является переменной F только собирается быть переназначены?
Да. Таким образом, мы должны закрыть оригинальную е, прежде чем делать это.
Но - и тут же, если бы не было F открывают здесь, то мы должны были бы сказать -
Да. Но было бы открыть сотни различных файлов.
[Студент] Но мы не были бы в состоянии получить доступ или - нормально.
Хорошо. Таким образом, сканирование F, F сканирования F, это своего рода та же идея,
но вместо того, вместо того, чтобы хранить его в строку, это больше похоже вы сейчас
переходя жало и сопоставления с этой строкой и хранение результатов в переменные.
Вы можете использовать сканирование F разобрать на что-то вроде 4.jpg, и хранить целое число 4 в сумме х Int.
Это то, что мы можем использовать для сканирования е.
F F сканирования собирается сделать это в командной строке.
Я на самом деле уверен, что это то, что библиотека CS50 делает.
Поэтому, когда вы говорите: "получить Int", это сканирование F-ния более - сканирование F является способ получения пользовательского ввода.
F сканирования F будет делать то же самое, но с использованием файлов для сканирования по.
Так вот, мы сканировании над этим файлом.
Образец, который мы пытаемся соответствовать некоторая строка, которая составляет 127 символов
последовала новая линия
Так что я уверен, что мы могли бы даже просто сказать: "соответствует ы", так как в словаре
Мы, оказывается, есть, мы гарантированно нет слов является то, что длинная,
а также F сканирования е, я думаю, будет останавливаться на новой линии ни на что.
Но мы будем включать новые строки в матче, и -
[Студент] Если мы не будем включать новые линии, не было бы найти части слова?
Это - каждому - глядя на словарь -
Так, в словаре, все эти наши слова.
Каждый из них с новой строки.
F сканирования собирается забрать это слово.
Если мы не будем включать новые линии, то вполне возможно, что следующий F сканирование будет просто прочитать новую строку.
Но в том числе новые линии, то будет просто игнорировать новую строку.
Но мы никогда не получим часть слова, так как мы всегда читал до новой линии, несмотря ни на что.
[Студент] Но что, если вы ищете слово "извращенный аппетит", как извращенный аппетит.
Будет ли это, что и говорить, что это матч?
И вот мы - он будет читать - это на самом деле хороший момент.
Мы никогда с использованием текущего - слово, которое мы ищем первый аргумент командной строки.
Таким образом, строка, слово = ARGV 1.
Таким образом, строка мы ищем является ARGV 1.
Мы не ищем слово вообще в нашем сканирования ф.
То, что мы делали с сканировании F становится каждое слово в словаре,
, а затем, когда у нас, что слово, которое мы собираемся использовать STRCMP чтобы сравнить их.
Мы собираемся сравнить наши слова и то, что мы только что прочитали дюйма
Таким образом, неизбежно, мы собираемся в конечном итоге делает кучу сканирование фс
пока не так уж случилось, что сканирование F вернется -
он будет возвращать один, пока она соответствует новым словом,
и он будет возвращать что-то другое, как только оно не соответствует слово.
Мы читаем по всему словарю, хранение строка за строкой каждое слово в переменную с.
Затем мы сравниваем слово с, а если сравнение == 0,
STRCMP происходит довести 0, если матч был сделан.
Так что, если это был 0, то мы можем напечатать F, совпадают,
или слово в словаре, или что вы хотите напечатать ф.
И потом - мы не хотим, чтобы F закрыть снова и снова.
Это такая вещь, что мы хотим сделать, и мы не просто ищете слово в словаре.
Таким образом, мы могли бы сделать это, если бы мы хотели посмотреть на их картины, извращенный аппетит, как вы говорили,
если мы хотим, чтобы искать эту схему, то оно не будет в том случае,
потому что это на самом деле не слова, а одно из слов в словаре, случается, что в нем.
Так что это будет соответствовать этим словом, но это подмножество слово не само слово.
Но это не то, как мы используем ее, мы читаем в каждом слове
, а затем сравнивая слова у нас с этим словом.
Таким образом, мы всегда сравнению полном слов.
Я могу отправить завершена решение позже.
Это своего рода почти правильный ответ, я думаю.
[Студент комментарий, неразборчиво]
О, я избавиться от этого раньше? Char с, я думаю, мы сказали 127 - я забыл, что крупнейший есть.
Мы просто делаем 128; так что теперь ей достаточно долго.
Мы не нужно ничего печатать.
Мы также собираемся хотите, чтобы закрыть файл, и что должно быть примерно правильный ответ.
CS50.TV