[Огляд: Вікторина 1] [Алі Нама, Oreoluwa Barbarinsa, Лукас Фрейтас, Роб Боуден] [Гарвардський університет] [Це CS50.] [CS50.TV] [Лукас Фрейтас] Вітаю всіх. Це відгук для вікторини 1. Так само, як за точність інформації, це - я маю на увазі, що ми збираємося, щоб спробувати покрити як багато матеріалу, як це можливо, але це не означає, що ми збираємося охопити всі речі, які можуть бути у вікторині 1. Так що будьте впевнені, ви також поглянути на лекції, розділами, все, що можна. Вікторина 1 буде в середу, в наступну середу. Так що не забудьте вивчити. Це буде, значною мірою, як і перший вікторини щодо його формат, але це, ймовірно, буде набагато складніше. Принаймні, минулого року, коли я взяв 50, я думав, що це було набагато складніше. Так багато вчитися. Я збираюся покрити структури даних і кодування Гоффмана. Це те, що багато людей думають, є складною, але я збираюся спробувати зробити це якомога простіше. Насамперед, те, що ми хочемо, ви, хлопці, щоб знати вікторини 1 є зрозуміти концептуальні описи кожної зі структур даних, які я збираюся представити. Це означає, що у вас немає насправді реалізації хеш-таблицю у вашій вікторини 1. Ми не хочемо вам реалізувати цілий хеш-таблицю, може бути, ми постараємося щоб ви реалізувати деякі функції, найбільш поширені операції, але ми не збираємося, щоб ви реалізувати все. Тому важливо, що ви розумієте поняття позаду кожної структури даних а також, що ви можете кодувати в C, тільки найпоширеніші операції, які вони мають для кожної структури даних. А також зможете переглянути покажчики і структури, тому що вони з'являються багато в цих структур даних. По-перше, пов'язані списки. Пов'язані списки насправді дуже схожий на масивах, але різниця між зв'язаний список і масив, насамперед, у тому, що зв'язаний список має дуже гнучкий розмір, в той час як в масивах ви повинні або вибрати дуже великий розмір для масиву, так що ви знаєте, що ви збираєтеся бути в змозі зберігати всі ваші дані в цьому масиві, або ви повинні використовувати Танос мати гнучку довжину масиву. У зв'язаних списків, що це дуже легко, щоб просто отримати більше елементів, покласти більше елементів у зв'язаному списку або видаляти елементи. А насправді, якщо ви не хочете зв'язаний список повинен бути відсортований, Ви можете шукати і видаляти елементи в постійне час, так O (1) часу, так що це дуже зручно. Ви просто повинні бути обережні, щоб завжди пам'ятати, щоб Malloc безкоштовно вузли, тільки тому, що якщо ви цього не зробите, ви будете мати витоків пам'яті. Так зв'язані списки - визначення вузла точно так само як те, що ми маємо право там. Я поклав Int N, але ви можете зберігати будь-які дані, які ви хочете. Так що якщо ви хочете зберегти рядок, це прекрасно. Якщо ви хочете зберегти структуру, це прекрасно, подвійний, що ви хочете. Я просто покласти Int N для прикладів тут. І у вас є вказівник на наступний вузол. Так, в основному, пов'язаний список має деякі дані, а потім він вказує на наступний вузол. Якщо це останній елемент у зв'язаному списку, це буде вказувати на NULL. Таким чином, це є прикладом пов'язаного списку. Добре, тепер давайте подивимося, що ми повинні робити, якщо я хочу, щоб вставити елемент у зв'язаному списку. По-перше, функція вставки буде типу порожнечу тому що я не хочу нічого повертати. І я збираюся прийняти Int як аргумент, тому що я хочу знати, що я хочу, щоб вставити. Так що перше, що я повинен робити? Ну, я повинен Malloc на newnode, так що це перша лінія. Я просто створення нового вузла поставити у зв'язаному списку. Так що я можу зробити? Ну, ми знаємо, що в наших реалізацій пов'язаних списків в класі, ми завжди ставимо головку як глобальна змінна. Отже, що ми можемо зробити, це змінити головою. Я можу зробити це новий вузол буде новий глава, і це буде вказувати на попередньої глави. Як ми можемо це зробити? Перше, що я повинен зробити, це змінити 'N' в новому вузлі у вартості, який був прийнятий в функцію. Тоді newnode далі буде глава. Голова буде newnode. Так що це досить просто. Для видалення вузла, ми можемо зробити це як - Один із способів ми могли зробити це, щоб сказати, добре, якби я хотів, щоб видалити, наприклад, 3, що я міг зробити, це просто вказати попередній вузол до наступного вузла 3. Так що я б просто зробити щось на зразок цього. Але в чому проблема з, що робити? У мене є витік пам'яті, так що у мене немає доступу до числа 3 більше. Проблема в тому, що я не збираюся бути в змозі звільнити цей вузол. Я збираюся мати витік пам'яті і (нерозбірливо) збирається мене ненавидиш. Таким чином, замість того, щоб робити це, я, ймовірно, слід мати тимчасовий покажчик. Так що я поклав темп. Вона збирається вказувати на вузлі, що я хочу, щоб видалити. А потім я можу рухатися попередні вузли точки до наступного вузла вузла, що я хочу, щоб видалити. І, нарешті, я можу звільнити покажчик. Чи є у мене, щоб звільнити покажчик, який я створив тут? Я не повинен, тільки тому, що - різниця в тому, що цей вузол був створений за допомогою Танос, так що це в купі, а цей був просто оголошений в якості перемикача NULL в стек. Так у мене немає, щоб звільнити її. Добре. Так що тепер давайте поговоримо про стеків. Штабеля досить прості. Ми зробили стеки і черги в класі тільки за допомогою масивів, але ви повинні бути знайомі - просто треба знати що ви також можете зробити стеки в чергах за допомогою пов'язаних списків, а також. Так що якщо у вас є масив, що було б стек? Стек, по-перше, повинні мати розмір. Ви повинні зберегти те, що це розмір стека, що у вас є зараз. А також ви б масив, в даному випадку чисел, але якщо ви хочете, це може бути масивом рядків, масив структури, все, що ви хочете зберегти. Про стека: Різниця між стеком і пов'язаного списку є те, що в стеку у вас є тільки доступ до останніх елементом, зданому в стек. Вона називається останній увійшов, першим вийшов. Так само, як у вас є стопка підносів, якщо ви поклали піднос на вершині стека, Ви повинні видалити цей лоток першим, щоб мати доступ до інших літаків. Це те ж саме зі стеками. Так що, якщо я хочу, щоб, наприклад, додати елемент в стеку, що я повинен робити? Вона називається поштовх, і це досить просто. Перше, що ви повинні зробити, це перевірити, якщо розмір стека не більш або дорівнює ємності стека. Тому що, якщо у вас вже є на повну потужність, ви не можете що-небудь ще додати. І потім, якщо ні, то ви просто повинні додати елемент в стек. І, нарешті, збільшують розмір. Так що це досить просто. Так що я просто додати номер 2. І якщо я хочу, щоб пхати, а це означає, що я хочу, щоб видалити останній елемент, який додають і повертає значення елемента, Перше, що я повинен перевірити, що стік не порожній. Тому що, якщо він порожній, я нічого не можу повернутися. У цьому випадку, я повертаюся -1. В іншому випадку, я збираюся зменшити розмір специфікації, і повернутися цифри (s.size). Чому я зменшити розмір, а потім повернутися s.size? Це тому, що, в даному випадку, специфікація має розмір 4, і я хочу повернутися четвертий елемент, чи не так? Але те, що індекс четвертого елемента? Три. Так як я розмір - буде 3, я можу просто повернутися s.numbers (s.size) тому що це 3. Так що це просто індекс. Зараз черги. Черги в значній мірі те ж саме. Різниця лише в тому, що замість того, останній увійшов, перший вийшов, у вас є першим увійшов, першим вийшов. Ймовірно, якщо ви чекаєте, щоб піти на концерт, Ви не були б щасливі, якби у вас був стек замість черги. Будучи останньою людиною, який прийшов би першою людиною, щоб увійти в концерт. Ви, напевно, не був би щасливий. У черзі, першою людиною, щоб отримати в також першою людиною, щоб вийти. Таким чином, у визначенні черги, крім того, що розмір масиву, Ви також повинні мати голову, яка індекс до голови стека. Таким чином, перший елемент прямо зараз. Ставити це те ж саме, як поштовх для стеків. Якщо ви були дуже наївні, ви б просто сказати, ну, я можу просто зробити те ж саме, що і я зробив для поштовху. Я можу просто перевірити, якщо це не виходить за межі можливостей. Якщо це так, я повернутися помилковим, інакше я можу просто експортувати нове значення і потім збільшити розмір. Але чому це так? Давайте подивимося цей приклад. Я намагаюся поставити в чергу купу речей, а потім я збираюся з черги і постановки в чергу. Там дуже багато команд, але це дуже просто. Я збираюся поставити в чергу 5, так що додайте 5, а потім 7, 1, 4, 6, а потім я хочу з черги щось, Це означає, що я збираюся видалити перший елемент. Так що я збираюся зняти номер 3, чи не так? Перший елемент. Добре. Тепер, якщо я намагаюся поставити в чергу щось ще, що станеться? За моєю реалізації, Я збирався поставити наступний номер в індексі q.size. У цьому випадку, розмір 8, тому індекс 8 буде прямо тут, в останній позиції. Якщо я намагаюся поставити в чергу 1 прямо тут, я був би перезапису останню позицію до № 1, яке є абсолютно неправильним. Те, що я хочу зробити, це обернути навколо і перейти до першої позиції. Може бути, ви б просто сказати, ну, я просто повинні перевірити якщо я можу насправді покласти щось там. Якщо ні, я просто кажу, про, новий повну потужність насправді потужність - 1, і ви не можете помістити елемент є. Але в чому ж проблема? Проблема в тому, що, якщо я просто з черги все прямо тут а потім я намагаюся додати щось ще, було б просто сказати, ну, ви були на повну потужність, що є 0. Так що ваша черга пішла. Ви повинні обернути навколо, і спосіб обтікання що ви, хлопці дізналися в далекоглядних і інших psets використовував мод. Ви можете спробувати його будинку, щоб зрозуміти, чому ви могли б зробити q.size + q.head мод ємність, але якщо ви подивитеся прямо тут, ми бачимо, що вона працює. Таким чином, в останньому прикладі, q.size було 8 і голова була 1, тому що це було це положення тут масиву. Так буде 8 + 1, 9. Мод ємність 9 буде 0. Було б піти в індексі 0. Ми будемо в правильному положенні. А потім спробуйте чергу будинку. Деякі важливі речі: спробувати зрозуміти різницю між стеком і черги. Будинки, спробувати отримати дуже добре знайомі з реалізації в чергу, Dequeue, поштовх і поп-музики. А також зрозуміти, коли ви будете використовувати кожен з них. Так що давайте відпочити протягом 10 секунд з купою покемонів. А тепер давайте повернемося до структур даних. Хеш-таблиці. Багато людей були налякані хеш-таблиці. в проблему набір 6, Spell Checker. Хеш-таблиці і намагається, багато людей лякаються з них. Вони думають, що вони так важко зрозуміти. Так? [Роб Боуден] Архів завдань 5. Архів завдань 5, так. Завдяки Роб. Так. Шість був Хафф-н-Puff, так. Архів завдань 5 був Spell Checker, і ви повинні були використовувати або хеш-таблицю або спробу. Багато людей думають, що вони були супер важко зрозуміти, але вони насправді досить просто. Що таке хеш-таблицю, в принципі? Хеш-таблиця являє собою масив пов'язаних списків. Єдина різниця між масивом і хеш-таблиці є те, що в хеш-таблиці у вас є те, що називається хеш-функція. Що таке хеш-функція? Я не знаю, якщо ви, хлопці можете прочитати тут. Це є прикладом хеш-таблиці. Таким чином, ви можете бачити, що у вас є масив з 31 елементами. І те, що ми робимо в хеш-таблиці є мати хеш-функцію що збирається перевести ключ, кожен десяткового індексу. Якщо, наприклад, якщо я хочу, щоб вибрати для Б. Харрісон, Я б поставив Б. Харрісон в моїх хеш-функцій, та хеш-функція повернеться 24. Так що я знаю, що я хочу зберегти Б. Харрісон в 24. Так от різниця між просто маючи масив і з хеш-таблицю. У хеш-таблиці ви будете мати функцію, яка збирається, щоб сказати вам де зберігати дані, які ви хочете зберегти. Для хеш-функції, ви хочете подивитися на хеш-функції що є детермінованим і добре розподілені. Як ви можете бачити тут, ви бачите, що багато даних, які я хотів магазині було насправді 19 замість використання 31 і 30 і 29, які були все безкоштовно. Таким чином, хеш-функція, що я використав не дуже добре розподілені. Коли ми говоримо, добре розподілені, це означає, що ми хочемо мати, приблизно, принаймні, 1 або 2 для кожного з - як, різниця в 1 або 2 для кожного з індексів у масивах. Ви хочете, щоб, грубо кажучи, те ж кількість елементів в кожному пов'язаному списку в масиві. І це легко перевірити, якщо вона діє в хеш-таблиці, подивитися як хеш-таблиці. Тоді дерева. Це дерево. Дерева в інформатиці з ніг на голову чомусь. Так прямо тут у вас є корінь дерева, а потім листя. Ви повинні просто знати номенклатуру для батьків і дитини. Кожен вузол має своїх дітей, які є вузли, які знаходяться нижче батька. Так, наприклад, 2 збирається бути батьком для 3 і для іншої дитини тут же, в той час як 3 буде батьківським для 1 і інші діти, які там. І 1 буде 3 дитя, і так далі. У нас є щось набагато більш цікаве, званий бінарне дерево, , В якому всі значення в правій частині вузла будуть праворуч, прямо тут - на правому, будуть більше, ніж елемент в корені. Тому якщо я номер 5 прямо тут, всі елементи на права будуть більше 5, і зліва всі елементи будуть менше 5. Чому це корисно? Ну, якщо я хочу, щоб перевірити, якщо число 7 тут, наприклад, Я просто перейдіть до 5 перших, і я збираюся бачити, є 7 більше або менше 5? Це більше, так що я знаю, що це буде мати, щоб бути на праворуч від дерева. Так що у мене набагато менше речей, щоб дивитися на. У реалізації бінарного дерева пошуку, вузла, я просто хочу, щоб мати дані, так Int N, ви могли б також є рядок або все, що ви хотіли. Ви просто повинні бути обережними на визначенні того, що більше, ніж менше. Так що якщо ви були рядки, наприклад, можна визначити що всі ті речі, що стосуються права будуть мати велику довжину, ліва будете мати більш низькі довжини, так що це дійсно залежить від вас. Як я можу реалізувати знайти для BST? Перше, що ми повинні зробити, це перевірити, якщо корінь NULL. Якщо це NULL, це означає, що річ не існує тому що ви навіть не дерево, вірно? Так що я повернутися помилковим. В іншому випадку, я збираюся перевірити, якщо число більше ніж значення в корені. Я збираюся спробувати знайти елемент праворуч з дерева. Ви бачите, що я використовую рекурсию тут. І потім, якщо це менше, я збираюся подивитися на зліва. І, нарешті, в іншому випадку, якщо це не менше або не більше, це означає, що це саме значення. Так що я просто повернутися вірно. Тут можна побачити, що я використав, якщо, якщо, якщо. І пам'ятайте, у вікторині 0, у нас була проблема, що, якби, якщо, якщо, і ви повинні були знайти неефективність, і неефективність в тому, що ви використовували, якщо. Ви повинні були використовувати, якщо, ще, якщо, ще, якщо, і ще. Так, я повинен використовувати ще, якщо і ще, якщо і ще тут? Хто-небудь - так? [Студент кажучи, нерозбірливо] Відмінно. Так вона каже, що це не має значення, тільки тому, що неефективність, що у нас було раніше було те, що, тому що, може бути, якщо деякий умова була виконана, так що ви виконали дії, але тоді ви збиралися перевірити всі інші умови. Але в цьому випадку, він повернувся відразу ж, так що це не має значення. Так що вам не доведеться використовувати ще, якщо. І, нарешті, давайте поговоримо про спроб, який є улюбленцем. Спроба це дерево масивів. Це дуже швидко для пошуку значення, але він використовує багато пам'яті. І це, як правило, для фільтрації слова, тому, коли ви хочете реалізувати, наприклад, я не знаю,, як телефонна книга в телефоні і ви хочете, щоб мати можливість типу В і просто імена людей, які мають B. Це дуже легко здійснити, що використання спробувати, наприклад. Як ви визначаєте вузол в спробі? Ви просто повинні мати логічне значення, яке збирається бути is_word. Це являє, що використання всіх символів до цього вузла, Ви були в змозі сформувати слово, і тоді ви будете мати масив покажчиків на вузли. Чи бачите ви, що у нас є масив батьківських вузлів, так що вузол * масив? Так? Отже, давайте подивимося, як це буде працювати. Для перевірки правопису, у нас є масив з 27 елементів, тому що у нас всі листи та премії апостроф. Перед тут я просто буду використовувати 2 бо я хочу, щоб мати можливість писати на дошці. Добре. Так що це приклад спроби. Якби я просто визначити перший вузол, я буду є масив 2-х елементів що 2 покажчики на NULL, так що я просто покласти 'A' і 'B'. І я буду мати логічне значення, яке говорить is_word. Це збирається бути помилковим для першого, тільки тому, що, перш ніж, що у вас немає ніяких символів. Так пусте слово не є словом. Так що це брехня. Якщо я хочу додати 'А' до цього словника, що б я повинен зробити? Я б просто повинні Malloc новий вузол для "а", , А потім додати своє слово до істини. Так що просто представляє, що, 'а' збирається, щоб бути правдою. Сенс? Тоді, якщо я хочу додати 'ба', я повинен буду Танос 1 для 'B', а потім я збираюся налаштувати логічне брехня, тому «б» само по собі не є словом. Тоді я збираюся Malloc ще один для "а", так що "ба", а потім я збираюся створити це слово до істини. Тому що «ба» це слово. І потім, якщо я хочу, щоб побачити, якщо «б» в цьому словнику, Я можу просто піти в перший, 'B'. Я спускаюся, і я дивлюся на це слово, і він каже, є хибним. Так що це не слова. Якщо я хочу, щоб перевірити "ба", Я йду в перший, 'B', а потім перейти до "а", і я бачу, правда, так це слово. Сенс? Багато людей заплутатися спроб. Ні? Нарешті, кодування Хаффмана. Кодування Хаффмана дуже корисно для економії пам'яті і стискати текстові файли, тільки тому, що багато разів ви використовуєте 'A' і 'е', наприклад, у ваших документах, але я не знаю, якщо ви, хлопці, використовувати 'Q' або 'Z', як багато. Маючи всього в 1 байт для кожного персонажа, кожен - в 256 символів, які ми маємо в таблиці ASCII не надто оптимальним, тільки тому, що є деякі символи, які ви використовуєте багато іншого, так що ви, мабуть, слід використовувати менше пам'яті для тех. Як я можу використовувати кодування Гоффмана? Ми повинні зробити дерево Хаффмана.  Дерево Хаффмана має вузли що є символ, який збирається бути схожим, 'а', 'б', 'C', листи, що лист у вас є, частота, частота, яка з'являється слово в тексті, що ви створювали дерево Хаффмана для, а потім вузол, який буде вказувати на ліворуч від дерева Хаффмана і інший вузол, який буде вказувати на справа. Так само, як дерево. Як ви будуєте дерево Хаффмана? Ви збираєтеся вибрати 2 вузла, які мають найнижчі частоти. Якщо у вас є краватка ви збираєтеся вибрати 2 вузла які мають найнижчі значення ASCII, а також. Тоді ви збираєтеся створити нове дерево з тих 2 вузлів що матиме комбінований частоту в батьківському вузлі. А потім ви збираєтеся видалити 2 дітей з лісу і замінити їх батьків. І ви збираєтеся повторити, що, поки ви тільки не мають 1 дерево в лісі. Отже, давайте подивимося, як ви могли б зробити дерево Хаффмана для ZAMYLA. Тут можна побачити, що всі букви мають частоту 1 для 'A', крім; що має частоту 2. Так що я створив вузли для всіх листів, які я упорядковують вартості і частоті ASCII. Так що, якщо я хочу створити перше дерево, він буде з 'L' і 'M'. Так що це тут. Частота пари буде два тому що це 1 + 1, то наступний 2 з найнижчими частотами є 'Y' і 'Z'. А то у мене всі з них - мають частоту 2. Так які з них є ті, які мають найменше значення ASCII для наступного? «А» і «L». Так що я створити новий вузол, І, нарешті, це 4 і 2, тому 2 буде ліворуч. І це дерево Хаффмана. Тоді, якщо я хочу написати текст, як у двійковому, щоб перетворити в текст, використовуючи дерево Хаффмана дуже легко. Наприклад, якщо я кажу, що рухаючись вліво є 0 і рухається вправо є 1, Що це буде представляти? Так як 1, 1, так правильно, правильно, і потім 0, так що залишилося б L, а потім 1, 0, 0. Так 1, 0, так що просто 1, 0, 'А'. І тоді 0, 1, так 'Z'. А потім 1, 0, 0 - ні. 0, 0 буде 'Y', так Лінивий. Так що все для мене, Роб збирається взяти на себе. [Роб Боуден] Отже, тиждень 7 матеріал. У нас є багато, щоб перейти дуже швидко. Бітові операції, переповнення буфера, Бібліотека CS50, то HTML, HTTP, CSS. У як від 15 до 20 хвилин. Бітові операції. Є 6 з них, що вам потрібно знати. Бітові і, побітовое АБО, виключає АБО, зрушення вліво, зрушення вправо, а не. Зрушення вправо, а не ви тільки бачили в лекції взагалі. Ми підемо по ньому швидко тут, але це добре, щоб знати, що це 6, що існує. Пам'ятайте, що бітові операції, як, коли ви робите 3 + 4. Ви не маєте справу з бінарними 3 і 4. З побітових операторів ви насправді маємо справу з окремими бітами чисел 3 і 4. Так перше, що ми будемо говорити побитово немає, і все це робить фліп всі біти. Так от, якщо ви пишете це в C, ви б не написати його як ~ 11011 або будь-який інший, можна було б написати це подобається ~ 4, і то було б перевернути бінарне представлення 4. Так от, ~ деякого двійкового числа 1101101 збирається точно перевернути все 1 до 0 і всі 0 до 1 в. Як я кажу, що, часте використання цього і ми побачимо його в трохи, це, як ми хочемо, щоб придумати якийсь числа де всі біти дорівнюють 1, для одного з них, за винятком. Так що це, як правило, легше висловити кількість де тільки що один біт встановлений, а потім взяти ~ його, таким чином, кожен друга встановлено біт для цієї винятком одного. Так от те, що ми збираємося використовувати більше в небагато. Побітовий або. Ось 2 двійкові числа, і ці 2 цифри досить представницьким, так як вони представляють всі можливі Поєднаннябіт вам може знадобитися для роботи на. При цьому, коли я or'd кожен біт, ми тільки збираємося порівнювати прямо вниз. Таким чином, на лівій стороні ми маємо один і 1. Коли я побітовое | тих, що я збираюся отримати? Один. Тоді побітовое | 0 і 1 збирається дати мені? Один. Бітові 1 і 0 буде те ж саме, один. Бітові 0 | 0 збирається дати мені 0. Таким чином, єдиний випадок, коли я отримую 0 знаходиться в 0 | 0 так. І ви можете думати про те, що так само, як ваші логічні ПРС. Так що якщо ви думаєте, що з 1 як істинний і 0 як помилковий, те ж саме можна застосувати і тут. Так правда чи вірно, то вірно, істинно або хибно це правда. Брехня або правда, то правда; брехня чи брехня це єдине, що насправді помилкове. Ось приклад, який ви повинні знати, як досить хороший приклад, коли бітові оператори використовуються. От якби ми чи капіталу "А" з OX20, і ми будемо дивитися на них через секунду, ми отримуємо щось. І якщо ми або рядкова'' з OX20, ми отримуємо щось. Так що давайте підтягнути таблицю ASCII. Добре. Тут ми бачимо, що «А» є - тут ми маємо «А» є десяткового 65. Але я піду з шістнадцятковому, який Ox41. Упевнений, що ми бачили його в класі. Я думаю, що ми бачили його в класі що це досить легко конвертувати з шістнадцятковій в двійкову. Так от, якщо я хочу поставити 4 в двійковий, от тільки буде 0100. Це 1 у вказане місце, 2 у вказане місце, 4 у вказане місце, так що це 4. Тоді я можу розділити 1 в двійковий, який збирається бути 0001. І таким чином, це буде вистава «А» в двійковому вигляді. Беручи нижній регістр 'а', то тепер збирається бути Ox61, де, розділивши ці вгору в його двійковий, тому 6 - Давайте насправді це зробити - чи немає ластик? Ластик. Ox61. Так розділивши 6 в двійковий буде 0 + 4 + 2 + 0. І розщеплення 1 буде 0001. Дивлячись на різницю між цими 2, ми бачимо, що єдина різниця між рядкової і прописної 'А' це один біт. Так повертаючись до тут - все в порядку. Повертаючись до тут, якщо ми подивимося на те, що трохи OX20 є, так розщеплення OX20 в його двійковий, є 0010, 0000. OX20, єдиний біт, який встановлюється це небагато, що ми маємо справу з, з перемиканням між капіталом і нижній регістр 'A'. Якщо я або «А», який є цей, «А», якщо я або "А" з OX20, що я збираюся отримати? [Студент, нерозбірливо] рядкова 'а', тому що він хоче перевернути цей біт в 1. І якщо я або "а" з OX20, що я збираюся отримати? Нижнього регістру, тому що якраз Öring «а» з OX20, Я просто хочу, щоб бути Öring цей один біт на 1, це вже 1, так що це не має значення. Отже, ми отримуємо 'A' і 'A'. Побітовий і. Знову ж, ми можемо вважати, що це наш логічного і колегою. З лівого боку у нас є правда і правда. Це збирається бути правдою, і для всіх випадків, брехня і правда чи правда і брехня, або брехня і брехня, жодна з цих речей не вірні. Отже, що ми в кінцевому підсумку отримати 1000. Так що тепер, ось, ось де я використовував вірний побітовое немає, де у нас були OX20. Так що це OX20. Тепер те, що я хочу зробити, побітовое ~ з OX20. Це збирається перевернути всі біти. Так що у мене 1101, 1111. І так «А» операція AND з ~ OX20 збирається дати мені те, що? Єдина частина ми дійсно повинні думати про те, на цей раз, так, якщо всі ці біти встановлюються в 1, потім ми збираємося, щоб отримати саме те, що «А» був, за винятком, може бути, те, що цей біт. Тому що, якщо це був 1, тепер він збирається бути встановлений на 0, тому що це, операція AND з цим буде 0. Так що ж таке "А" і ~ OX20 збираюся дати мені? [Студенти відповісти, нерозбірливо] А що таке "а" і - це "А". А що таке "а" і ~ OX20 збираюся дати мені? 'А.' Оскільки це нині 1. Андінг з цим +0 збирається зробити це 0, і тепер ми збираємося, щоб отримати 'A'. Обидва ',' і не в останню чергу цього типу, у нас є XOR. Це дуже схоже або, крім це означає виключно або. Це як те, що ви зазвичай думаєте, як і в реальному світі. Таким чином, ви виконаєте одне 'х' або 'у', але не обидва. Тут 1 ^ 1 буде 0. Тому що правда, це - він не працює, а з логічним істинним і хибним як побітовое & і або зробити, але факт ^ вірно невірно. Тому що ми тільки хочемо, щоб повернутися вірно, якщо тільки один з них вірно. Так 1 ^ 1 0. А як щодо 0 ^ 1? Дорівнює 1. 1 ^ 0 дорівнює 1, 0 ^ 0: 0. Так при будь-яких обставин, 0 побітовое щось 0 буде 0. 1 побітовое щось 0 або 0 побітовое 1, якщо це | чи ^, це буде 1, а якщо і це буде 0. І єдиний випадок, коли 1 побітовое 1 цієї статті не 1 з ексклюзивним або. Це 0110. Так от зараз, використовуючи XOR - так ми повернулися в 20. "А" ^ OX20 ці 2 біта ми порівнюємо. Так 1 ^ 0 збирається дати мені що? Один. "А" ^ OX20 збирається дати мені? Нижнього регістру. 'А' ^ OX20 збирається дати мені? Капітал А. Тому що все, що це робить, це операції XOR з OX20 ефективно гортати все цей біт. Якщо це 0, то тепер збирається стати 1. Так як це 1, 1 ^ 1 дорівнює 0. Таким чином, наш «а» стала «А», і наш «А» став «а». Так XOR є дійсно зручним способом просто гортати справу. Ви просто хочете перебрати рядок букв і чергувати справа кожного окремого персонажа, ви просто XOR все з OX20. Тепер ми залишили зрушення. Зрушення вліво просто буде, в основному, натиснути всі номери в, або вліво, а потім вставте 0 за ними. Так от у нас 00001101. Ми збираємося, щоб підштовхнути 3 0 в прохід по правій, і ми отримуємо 01101000. У небінарних точки, ми бачимо, що, що насправді справа 13 лівій зміщену 3, що дає нам 104. Так лівий зсув, ми бачимо тут, х << у в основному х * 2 ^ у. 13 * 2 ^ 3, 2 ^ 3 8, так що 13 * 104 8. Якщо ви просто думаєте про довічним взагалі, як кожної цифри, якщо виходити з права, це в 1 у вказане місце, то в 2 вказане місце, то в 4 у вказане місце. Так, натиснувши на 0-х років по правому флангу, ми просто штовхає речі, які були в 4 в місці з 8 по місцю, і речі, які були в 8 в місці, щоб у 16 ​​свого місця. Кожна зміна просто примножує на 2. Так? [Студент] Що відбудеться, якщо ви перейшли на 5? [Боуден] Якщо ви зсувається на 5, ви просто втратите цифри. Безумовно, це одне і те ж. Мовляв, цілі числа тільки 32 біт, так що якщо ви додати 2 дійсно великі цілі числа, він просто не вписується в ціле число. Так що це те ж саме тут. Якщо ви перейшли по 5, ми б просто втратити, що один. І це зразок того, що я маю на увазі "приблизно" , Де, якщо ви переносите занадто далеко, ви втрачаєте біти. Зрушення вправо буде навпаки, куди ми йдемо засунути 0-х від кінця, і для наших цілей, заповніть 0 з лівого. Так робити це, ми в основному назад те, що ми вже зробили. І ми бачимо, що три 0 про право тільки відвалилася, і ми підштовхнули 1101 все до упору вправо. Це робить 104 3, який є, по суті, х / 2 ^ у. Так що тепер, тут, це подібна ідея. Чому це тільки приблизно х / 2 ^ у, а не насправді х / 2 ^ у? Тому що, якщо я змістився на 4, я б втратив 1. В принципі, що ви думаєте про, просто думаю, цілочисельного ділення в цілому. Так що, як 5/2 становить 2. Це не 2.5. Це та ж ідея тут. Коли ми ділимо на 2, ми можемо втратити непарні біти на цьому шляху. Так що тепер - ось це для побітового. От і все, що вам потрібно знати. Запам'ятати прецеденти, які ми бачили в класі, як бітова маска корисна для операторів побітових або ви використовуєте їх для бітових масок. Заголовні букви і малі літери, перетворення є досить Найпростіший приклад. Гаразд, так атак на переповнення буфера. Хтось пам'ятає, що сталося з цією функцією? Зверніть увагу, ми оголосили масив 12 байт, 12 символів, а потім ми копіюємо в нашу буфера 12 символів вся штрих рядок. Так в чому ж проблема? Магічне число 12 повинно значною мірою негайно вискочити як - чому 12? Що робити, якщо бар, трапляється більше 12 символів? Що робити, якщо бар мільйони героїв? Тут мова йде тетсру. Якщо бар досить довго, це буде просто повністю - 'C', 'C' не хвилює, що це було тільки 12 символів; 'С' не дбає, що вона не може поміститися, що кількість байтів. Це буде просто повністю переписати Чарі, 12 байт ми виділені для нього, і все мимо нього в пам'яті, що насправді не належать цьому буфера з тим, що рядок бар. Так що це була картина ми бачили в класі де у нас є наш стек ріс. Ви повинні бути використані для цих картин або ознайомитися з ними знову. Ми наш стек ріс, адреси пам'яті починаються з 0 на вершині і рости до подобається 4000000000 на дні. У нас є масив 'з' десь у пам'яті, то у нас є вказівник на бар прямо під ним, а то у нас цей збережений покажчик кадру в нашому зворотної адреси та стек нашої материнської рутини в. Пам'ятайте, що ваш зворотну адресу? Це коли основний викликає функціональний Фу, викликає функціональний бар, неминуче, бар віддачу. Тому, коли бар повертається, вони повинні знати, що він збирається повернутися до Foo, який викликав її. Таким чином, зворотну адресу є адресою функції, що він повинен повернутися в коли функція повертає. Причина, по якій важливо для атак переповнення буфера відбувається тому, що, зручно, хакери хотів змінити цю зворотну адресу. Замість того, щоб повертатися до Foo, я збираюся повернутися туди, де хакер хоче, щоб я повернутися. І, зручно, де хакер часто хоче повернутися до є початком буфера, який ми спочатку мали. Так помітити, знову ж, Little Indian. Прилад є прикладом Маленька індійської системі, так ціле або покажчик зберігається з байтах в зворотному порядку. Так от, ми бачимо - це? Так. Ми бачимо Ox80, OxC0, Ox35, OxO8. Пам'ятайте шістнадцяткові цифри? Ми не анулюється шістнадцяткові цифри в Little Indian, бо 2 шістнадцяткові цифри становлять один байт, і ми поміняємо байт. Ось чому ми не зберігаємо, як, 80530CO8. Ми зберігаємо, замість цього, кожну пару 2 цифри, починаючи справа. Ця адреса вказує на адресу початку нашого буфера, що ми насправді хотіли скопіювати в в першу чергу. Причина, по якій корисно тому, що, що, якщо зловмисник трапилося з, замість того, рядок, яка була просто Нешкідливий рядок, як їх ім'я або щось, що, якщо замість, що рядок були лише деякі довільного коду що зробив все, що вони хотіли, щоб це зробити? Таким чином, вони могли - я не можу думати ні про яке прохолодному коду. Це може бути що завгодно, все ж. Будь катастрофічними код. Якби вони хотіли, вони могли б просто зробити щось на сегментах несправностей, але це було б безглуздо. Як правило, вони роблять це, щоб зламати вашу систему. Добре. CS50 бібліотека. Це, в основному, GetInt, GetString, всі ці функції ми надали для вас. Тому у нас є символ * рядок, і це абстракція, що ми здув в якийсь момент під час семестру. Пам'ятайте, що рядок просто масив символів. Так от ми бачимо скорочену версію GetString. Ви повинні озирнутися на нього, щоб згадати, як це насправді реалізується. Основні деталі, зверніть увагу ми отримуємо в один символ за один раз від стандартних у, яка як би нам набравши їх з клавіатури. Так один символ за один раз, і якщо ми отримаємо надто багато символів, тому, якщо п + 1 більше потужності, то ми повинні збільшити пропускну здатність нашого буфера. Так от ми подвоюємо розмір нашого буфера. І це продовжує йти, ми вставити символ в нашу буфера поки ми не отримаємо нову лінію або кінець файлу або будь-який інший, в цьому випадку, ми закінчили з рядка, а потім реальної GetString стискається пам'ять, як якщо б ми виділено занадто багато пам'яті він буде повернутися і сідають небагато. Таким чином, ми не показують, що, але основна ідея полягає він повинен читати в один символ за один раз. Вона не може просто прочитати в цілому річ відразу, тому що їх буфер тільки певного розміру. Таким чином, якщо рядок, вона спробує вставити в буфер занадто великий, то це було б переповнити. І ось ми запобігти це лише читання в один символ в той час, і росте, коли нам потрібно. Так GetInt та інші бібліотечні функції CS50 як правило, використовують GetString в їх реалізації. Так що я звернув увагу на важливі речі. Він закликає GetString, щоб отримати рядок. Якщо GetString не повернувся пам'ять, пам'ятайте, що GetString mallocs щось, тому, коли ви телефонуєте GetString ви не повинні (нерозбірливо) безкоштовно цю рядок, який ви отримали. Так от, якщо його не вдалося Malloc щось, ми повертаємося INT_MAX просто як прапор, який, агов, ми не були насправді в змозі отримати ціле. Ви повинні ігнорувати все, що я повернуся до вас, або ви не повинні розглядати це як правильний ввід. Нарешті, вважаючи, що так вийде, ми використовуємо Sscanf з тим спеціальним прапором, що означає, в першу відповідати ціле, Потім відповідати будь-яким символам після цього цілого. Так помітите, що ми хочемо, щоб він дорівнює 1. Так Sscanf повертається скільки матчів, якщо успішно зробив? Це поверне 1, якщо вона успішно підібрані ціле, це поверне 0, якщо вона не відповідає ціле, і він повернеться 2 якщо воно відповідає цілому числу слідують деяким характером. Так помітите, що ми повторити, наскільки ми підходимо нічого, крім 1. Таким чином, якщо ми увійшли 1, 2, 3, C, або 1, 2, 3, X, потім 1, 2, 3 отримуватиме зберігається в ціле, X буде отримати зберігаються на характер, Sscanf повернеться 2, і ми хотіли б повторити, тому що ми тільки хочемо ціле. Швидко продувки HTML, HTTP, CSS. Мова розмітки гіпертексту є структура і семантика в Інтернеті. Ось приклад з лекції, де у нас є HTML-теги. У нас є голови теги, теги тіла, у нас є приклади порожніх тегів, де ми насправді не мають початку і закриває тег, ми просто повинні посилання і зображення. Там немає закриття тег картинки; є тільки один тег, який виконує всі тег повинен робити. Зв'язок є прикладом; ми побачимо, як Ви даєте посилання на CSS, сценарій є прикладом того, як Ви даєте посилання на зовнішній JavaScript. Це досить просто, і пам'ятайте, HTML не є мовою програмування. Ось, пам'ятайте, як би ви визначити форму або принаймні те, що це буде робити? Така форма має дію, і спосіб. Методи, які ви тільки коли-небудь бачите, GET і POST. Так GET є версія, де річ отримує покласти в URL. POST, де не ставиться в URL. Замість цього будь-які дані з форми вставляється більш приховані в запиті HTTP. Так от, дія визначає, коли запит HTTP йде. Де він збирається це google.com / Пошук. Метод. Запам'ятати відмінності між GET та POST, і, просто сказати як приклад, якщо ви хочете закладки чимось. Ви ніколи не будете мати можливість встановити закладку на POST URL оскільки дані не включені в URL. HTTP, зараз, є протокол передачі гіпертексту. Протокол передачі гіпертексту, можна було б очікувати, що для передачі Мова розмітки гіпертексту, і це робить. Але це також передає будь-які зображення, які ви знайдете в Інтернеті, будь-які завантаження ви робите почати як запитом HTTP. Так HTTP просто язик World Wide Web. І тут потрібно визнати цей вид запиту HTTP. Тут HTTP/1.1 на стороні просто говорить, що це версія протоколу я використовую. Це значною мірою завжди буде HTTP/1.1, як ви побачите його. Тоді ми бачимо, що це було GET, альтернатива бути POST, що ви можете побачити. І URL, що я намагався відвідати був www.google.com/search?q = бла, бла, бла. Так що пам'ятайте, що це, знак питання д = бла бла бла, є свого роду матеріал, який представляється у формі. Відповідь може повернутися до мене б виглядати приблизно так. Знову ж, починаючи з протоколу, який збирається бути, що, потім код стану. Ось це 200 ОК. І, нарешті, веб-сторінки, що я насправді попросив послідує. Можливий код стану ви можете побачити, і ви повинні знати деякі з них. 200 ОК ви, напевно, бачили раніше. 403 Forbidden, 404 Not Found, Error 500 Internal Server , Як правило, якщо ви йдете на сайт і щось не працює або їх аварій PHP код, в той час як в приладі маємо великий помаранчевий прямокутник що приходить і каже, начебто, щось не так, цей код не працює або ця функція погано. Зазвичай веб-сайти не хочу, щоб ви, знаючи, які функції насправді погано, так замість цього вони просто дам вам 500 Внутрішні помилки сервера. TCP / IP є 1 шар під HTTP. Пам'ятайте, що існує Інтернет за межами Всесвітньої павутини. Подібно до цього, якщо ви граєте в онлайн гри, яка не проходить через HTTP, це буде через іншого - вона як і раніше з використанням Інтернету, але він не використовує HTTP. HTTP є лише одним із прикладів протоколу побудований на TCP / IP. IP буквально означає Internet Protocol. Кожен комп'ютер має IP-адресу, вони ці 4-значні речі як 192.168.2.1, або що, то, як правило, локальний характер. Але це картина з IP-адреси. Таким чином, DNS, Domain Name Service, це те, що переводить такі речі, як google.com до фактичного IP адресою. Так що якщо ви введете, що IP-адреса в URL, що б привести вас до Google, але ви, як правило не згадувати ці речі. Ви, як правило, замість пам'ятати google.com. Останнє, що ми маємо, порти, де це TCP частиною IP. TCP робить більше. Подумайте про те,, як, ви запустили веб-браузера. Може бути, у вас є деякі працюють програми електронної пошти, може бути, у вас є інші програми, що використовує Інтернет працює. Всі вони потребують доступу до мережі Інтернет, але ваш комп'ютер має тільки 1 WiFi карти або будь-який інший. Так порти так, що ми в змозі розділити як ці додатки можуть використовувати Інтернет. Кожна програма отримує 1 певний порт, що він може слухати на, і за замовчуванням, HTTP використовує порт 80. Деякі поштові служби використовують 25. Ті, низьким номером, як правило, захищені. Ви, як правило, в змозі отримати більш високим номером ті для себе. CSS, каскадні таблиці стилів. Ми стилі веб-сторінок за допомогою CSS, а не з HTML. Є 3 місця, які ви можете помістити свій CSS. Це може бути вбудованим, між тегами стилі, або в абсолютно окремому файлі і потім пов'язані дюйма А ось якраз приклад CSS. Ви повинні визнати цю модель, де перший приклад ми відповідні теги тіла, і тут ми центрування тег тіла. Другий приклад, ми не поступаються річ з ID виносці, і ми застосовуємо деякі стилі до цього. Зверніть увагу, що ID Сноска вирівнює вліво, в той час як тіло текстові вирівнює центр. Footer знаходиться всередині тіла. Це буде, замість цього, вирівнювання тексту залишилося, хоча тіло говорить вирівнювання тексту центр. У цьому вся каскадних частиною. Ви можете мати - можна вказати стилі для тіла, і тоді все в організмі можна вказати більш конкретні стилі, і все це працює, як ви очікуєте. Більш конкретні CSS специфікатори мають пріоритет. Я думаю, що це він. [Алі Нама] Привіт всім. Якби я міг привернути вашу увагу. Я Алі, і я збираюся пройти через PHP і SQL дуже швидко. Таким чином, ми можемо почати. PHP є скороченням PHP: Hypertext Preprocessor. І, як ви всі повинні знати, що це на стороні сервера скриптова мова, і ми використовуємо його для задньої частини веб-сайтів, і як вона робить багато обчислень, з боку за кадром. Синтаксис. Це не схоже на C, здивування, подив. Це завжди повинно починатися з, якщо ви бачите, - я не можу рухатися вперед. Ви можете бачити, вам потрібні нові види брекетів, а потім ви також потребують PHP?. Це завжди, як ви повинні сформулювати свій PHP текст, ваш код PHP. Тому він не може бути просто, як С, де ви начебто покласти його в першу чергу. Ви повинні завжди оточують його. А тепер, майор синтаксис, що всі змінні повинні почати з символу $. Ви повинні зробити це, коли ви визначаєте їх, ви повинні зробити це коли ви маєте на увазі до них пізніше. Ви завжди повинні, що $. Це ваш новий кращий друг, досить багато. Ви не - на відміну від C, вам не потрібно ставити яку типу змінної це. Таким чином, хоча ви дійсно потребуєте $, вам не потрібно ставити, як, внутр х або рядок у, і так далі, і так далі. Так невелика різниця. В результаті цього, це означає, що РНР є слабо типу. PHP є слабо мову Тип, і він слабо типізовані змінні. Іншими словами, це означає, що ви можете перемикатися між різними видами типів змінних. Ви можете зберегти свій номер 1 у вигляді цілого числа, Ви можете зберегти його у вигляді рядка, і ви можете зберегти його як поплавок, і це все буде, що число 1. Навіть якщо ви зберігати його в різних формах, вона як і раніше - типи змінних все ще тримають в кінці кінців. Так що, якщо ви подивіться сюди, якщо ви пам'ятаєте з PSet 7, багато хто з вас, ймовірно, були проблеми з цим. Два знака рівності, 3 знаки рівності, 4 знака рівності. Добре, немає 4 знаки рівності, але є 2 і 3. Ви можете використовувати два знаки рівності для перевірки значень. Він може перевірити за типами. Так що якщо ви можете бачити на першому прикладі, У мене є num_int == num_string. Так що ваш внутр і ваша рядок обидва, технічно, 1, але вони різні типи. Але для подвійних рівних, це буде ще пройти. Проте, для потрійних рівних, він перевіряє значення, а також різні типи. Це означає, що він не збирається в той другому випадку тут, де ви використовуєте 3 знак рівності, а не. Так ось головна відмінність, що ви повинні все показали зараз. Об'єднання рядків є ще одним потужним, що ви можете використовувати в PHP. Це в основному тільки цей зручний точкової нотації, і от як можна прив'язати рядків разом. Так що якщо у вас є кішка і у вас є собака, і ви хочете, щоб покласти 2 рядки разом, Ви можете використати період, і це частково, як це працює. Ви також можете просто розмістити їх поруч один з одним, як ви можете бачити тут, в нижній Наприклад, де я луна рядок 1, простір рядок 2. PHP знатиме, щоб замінити їх як таких. Масиви. Тепер, в PHP, є 2 різні види масивів. Ви можете мати регулярні масиви, і ви також можете мати асоціативні масиви, і ми збираємося пройти через них прямо зараз. Регулярні масиви просто це в C, і тому ви повинні індексів, які пронумеровані. Зараз ми тільки збираємося, щоб створити одну і покласти - так що це, як ми створюємо порожній масив, то ми збираємося покласти в індекс числа 0. Ми збираємося поставити номер 6, значення 6. Ви можете бачити це на дні тут. Where's - в з порядковим номером 1, ми збираємося поставити значення номер 4, і тому ви можете побачити, що є 6, є 4, а потім, як ми друку речі, коли ми намагаємося і роздрукувати значення з індексом числа 0, тоді ми побачимо значення 6 його роздруківки. Круто? Так от регулярні масиви для вас. Іншим способом ви можете додати речі звичайних масивів зараз що ви можете просто додати їх у кінці. Це означає, що вам не доведеться вказувати конкретний індекс. Ви можете побачити номер, а потім у квадратних дужках немає вказаний індекс. І він буде знати, - PHP буде знати, щоб просто додати його в кінець списку, наступного вільне місце. Таким чином, ви можете побачити 1 тут же в той 0 місці, 2 пішов тут же в першому місці. 3 йде - додається там же. Так що вид має сенс. Ти просто постійно додавати його, а потім, коли ми вторячи індекс числа 1, він видасть значення 2. Тоді у нас є масиви, які є асоціативні масиви. Асоціативні масиви, замість того, числові індекси, що вони роблять, вони мають індекси, які по рядку. Ви можете бачити, замість того, щоб - я позбавився всіх цих числових індексів, і тепер це ключ1, ключ2, ключ3, і вони в подвійні лапки, щоб показати, що вони всі рядки. Так ми можемо мати приклад цього. Прикладом цього є те, що у нас є TF, і це ім'я індексу. Ми збираємося поставити "Алі" як ім'я, на індекс, калорії з'їдені, ми можемо покласти целочисленное цей раз замість рядка, , А потім в індексних любить, ми можемо покласти весь масив всередині нього. Так що це свого роду - це аналогічна концепція того, як ми повинні були індекси з номерами, але тепер ми можемо змінити індекси навколо мати їх як рядки, а не. Ви також можете зробити це, крім усього робити це індивідуально, Ви можете зробити все це в одному шматку. Таким чином, ви можете бачити, що TF цього масиву, і те покладемо їх в одну гігантську квадратного набір кронштейнів. Так що може прискорити процес. Це скоріше стилістичний вибір, ніж ні. У нас також є петлі. У C ми маємо петлі, які працюють, як це. У нас був наш масив, і ми пішли з індексом 0 в кінці списку, і ми друкуємо все це, чи не так? Крім проблема, для асоціативних масивів, ми не обов'язково знати ці числові індекси тому що тепер у нас є рядкові індекси. Тепер ми використовуємо FOREACH петлі, які, знову ж таки, ви, сподіваємося, використовувані в PSet 7. Foreach петлі буде просто знаю, кожен частину списку. І це не обов'язково має точно знати числовий індекс, що у вас є. Так у вас є синтаксис Еогеасп, так що це Еогеасп, ви поклали масив. Так що мій масив називається PSET, а потім, слово як, а потім ви покладете цей локальний тимчасову змінну, що ви збираєтеся використовувати тільки для конкретної речі, що відбувається провести конкретний - один примірник або одна частина масиву. Pset піт проведе 1, а потім, може бути, буде містити номер 6, , А потім він буде містити номер 2. Але це гарантовано пройти кожен одне значення, це в масиві. Корисні функції, які ви повинні знати в PHP є вимагають, так що робить впевнені, що ви в тому числі певні файли, луна, вихід, порожній. Я настійно рекомендую вам подивитися на PSet 7 і подивитися на цих функцій. Можливо, вам доведеться знати тих, так що я точно знаю, буде те, що, власне, ті, все роблять. А тепер ми збираємося пройти через рамки дуже швидко. В рамках, PHP є свого роду фанки речі, на відміну від C, і так ми тільки збираємося пройти через це швидко. Так скажімо, ми починаємо в цьому стрілки, що у нас є. І ми збираємося почати з $ я. Таким чином, змінна 'я' буде 0, і ми тільки збираємося продовжувати друкувати його в цій великій білій коробці там. Ми збираємося почати з i0, а потім ми збираємося повторити його. Таким чином, є 0. А потім ми збираємося збільшувати його на цикл, , А потім він буде значення 1. Один менше 3, тому він збирається пройти через це цикл, і тоді ми побачимо його знову надруковані. Ми збираємося збільшити його знову до 2, і 2 менше 3, тому він пройде цикл, і він буде друкувати 2. Тоді ви помітите, що 3 не менш 3, тому ми вирватися з циклу. Так що тепер ми вийшли, а потім ми збираємося йти в припинення функції. Добре. Таким чином, ви повинні відзначити, що це змінна, яку ми створили, "Я" змінної, не локальною областю видимості. Це означає, що воно не є локальним в петлю, і що змінна, яку ми досі можуть отримати доступ і змінити згодом, і вона як і раніше буде ефективним. Так що, якщо ви йдете в функцію зараз, ви побачите, що ми також використовуємо "Я" змінну, і ми збираємося, щоб збільшити 'я' + +. Можна було б подумати, по-перше, на основі C, що це копія «Я» змінної. Це зовсім різні речі, що є правильним. Тому, коли ми друкуємо його, ми збираємося надрукувати 'я' + +, який буде друкувати, що 4, а потім ми збираємося - вибачте. Тоді ми збираємося в кінцевому з цієї функції, і ми збираємося бути там, де, що стрілка знаходиться зараз. Це означає, що те, проте, навіть якщо функція змінили значення "Я", це не змінило за межами функції, тому що функція має окремий об'єм. Це означає, що, коли ми відлуння 'я', вона не змінилася в області дії функції, і так, то ми збираємося надрукувати 3 разів. Різні речі про рамки в PHP, ніж у С. Зараз в PHP і HTML. PHP використовується, щоб зробити веб-сторінки динамічними. Це частково робить речі різні. У нас є його відмінність від HTML. З HTML, ми завжди тільки мають той же статичний річ, як те, як Роб показав, в той час як PHP, ви можете змінити речі на основі, ким є користувач. Так що, якщо у мене є це, я, "Ви увійшли як -" а потім ім'я, і я можу змінити ім'я. Так що зараз звуть Йосип, і у нього є "про мене", але тоді я можу також змінити ім'я, щоб мати Томмі. І це була б інша справа. Так тоді ми можемо також змінювати різні речі про нього, і він покаже різний зміст на основі імені. Отже, PHP може частково змінити те, що відбувається у вашому сайті. Те ж саме тут. Проте, зверніть увагу, що у них є різний контент, навіть якщо ви технічно все ще доступ до цієї ж веб-сторінку на поверхні. Створення HTML. Є 2 різних способів, якими ви можете зробити це. Таким чином, ми пройдемо це прямо зараз. Перший спосіб, у вас є - да, жаль. Таким чином, ви просто повинні вашої звичайної для петлі в PHP, і тоді ви луною в PHP, і ви луна з HTML. Використовуючи те, що Роб показав вам з HTML сценарію а потім за допомогою PHP друк, щоб просто роздрукувати його на веб-сторінку. Альтернативний спосіб, щоб робити це як якщо б ви виділити на PHP і HTML. Таким чином, ви можете мати лінію PHP, який починається цикл, то ви можете мати лінію HTML в окремому речі, а потім ви в кінцевому петлю, знову ж таки, з PHP. Так що це свого роду поділу його. З лівого боку, ви можете, що у вас є все - це просто 1 шматок PHP. Праворуч ви можете бачити, що у вас є лінію PHP, у вас є лінію HTML, і у вас є лінію PHP знову. Так поділу його в те, що вони роблять. І ви помітите, що в кожному разі, для будь-якого з них, вони як і раніше роздрукувати зображення, образ, зображення, так що HTML раніше друкується таким же чином. А потім ви все одно побачите 3 зображення з'являються на вашому сайті. Так що це 2 різні способи робити те ж саме. Тепер у нас є форми і запити. Як Роб показав вам, Є форми HTML, і ми якраз вітер через це. У вас є дія і у вас є метод, і ваші дії вид показує вам, де ви збираєтеся відправити його, а метод, чи є він збирається бути GET або POST. І запит GET, як сказав Роб, означає, що ви збираєтеся покласти його у вигляді і ви побачите його як URL, в той час як запит POST, ви не побачите в URL. Так невелика різниця. Тим не менш, одна річ, яка щось подібне є те, що POST і GET в рівній мірі небезпечно. Таким чином, ви можете думати, що тільки тому, що ви не бачите його в URL, це означає, що POST є більш безпечним, але ви все ще можете побачити це в твоїх печиво в інформації, ви посилаєте. Так що не думаю, що про один або одним. Інша справа, слід зазначити, що у вас також є розділ змінних. Ви, хлопці використовували це в PSet 7, щоб отримати код користувача інформацію. Сталося так, що ви можете використовувати цей асоціативний масив, $ _SESSION, А потім ви зможете отримати доступ до різних речі і зберігати різні речі по сторінкам. Остання справа, що у нас є SQL, Structured Query Language, і це мова програмування для управління базами даних. Що, власне, являють собою бази даних? Вони колекції таблиць, і кожна таблиця може мати подібні види об'єктів. Так у нас був стіл користувачів в вашої фінансової PSet. І чому вони корисні? Тому що це спосіб постійного зберігання інформації. Це спосіб відстеження речі і керування речі і насправді бачимо його на різних сторінках і відстеження. У той час як, якщо ви просто зберігати його в то одного безпосередній момент а потім використовувати його пізніше, ви не зможете отримати доступ до все, що ви зберегли. У нас є 4 основні речі, які ми використовуємо для команд SQL. У нас є вибирати, вставляти, видаляти та оновлення. Ті, які дійсно важливі для вас, хлопці знають, для вашого вікторини. Ми швидко перейти виберіть прямо зараз. В принципі, ви вибору рядків з бази даних. Так що якщо у вас є, прямо тут - у нас є ці 2 різні речі, і ми хочемо, щоб вибрати з таблиці класів де дивним - де в дивовижному колонці значення дорівнює 1. Таким чином, ви можете бачити тут, у нас є ці 2 речі імені класу, CS50 і Stat110, і у нас є коди класів і гасло. Тому ми хочемо, щоб вибрати все, що інформація. Тоді ви можете побачити прямо тут, що це частково вибираючи з цієї дивовижної колонці, де всі речі 1, а потім вона має ідентифікатор класу, ім'я класу і гасло, що він може вибрати з. Як саме ви будете робити це в коді? Ви повинні використовувати PHP. Так що ніби як PHP і SQL пов'язані один з одним. Тепер у нас є наш код, і ми збираємося використовувати нашу функцію запиту як ми робили в PSet 7, і ми збираємося запустити SQL запит. Тоді ми будемо мати - ми завжди повинні перевірити, якщо трійка дорівнює Роу якщо ложно. Отже, ще раз, ви хочете перевірити тип і значення, а потім, якщо він не працює, то ви хочете, щоб вибачитися, як звичайно, як ми робили в PSet 7. В іншому випадку, ви хочете перебрати все з тими зручно Еогеасп петлі, що ми просто перейшли. Тепер, коли ми пробігаємо по і ми зробили це в минулому, давайте припустимо, що наш запит пройшов, тепер у нас є цикл по кожному елементу. І перший рядок має, так що ось рядок, прямо тут, це в коробку. Це збирається роздрукувати всю інформацію, яку він отримав. Так це буде роздрукувати на дні "Хочеш дізнатися HTML?" Тоді це буде перейти до наступного ряду, тому що вона завершена перша цикл, і так, то це буде роздрукувати другий рядок ній, який буде STAT110, Знайти всі моменти. І ще одне знаходиться на SQL вразливостей. Я знаю, Девід торкнувся цього трохи в лекції. Ви можете прочитати це пізніше. Це дійсно забавно. SQL-ін'єкція є свого роду складна річ. Давайте припустимо, що ви просто дотримуватися цих змінних прямо у вашому запиті, як ви можете бачити в цьому першій лінії. Так що, схоже прекрасно, чи не так? Ви просто покласти в імені користувача і пароль до своєї черги, і ви хочете вантажити його і отримати те, що знаходиться в таблиці даних. Це здається досить простим. Так що давайте говорити хтось кладе в, для пароля, це чи текст прямо тут - повинні насправді бути в червоній коробці. Так скажемо, що вони вкладають у цей пароль - це те, що вони входять. Так вони поміщають або "1" = 1. Вид дурною пароль, щоб мати. Тепер давайте просто замінити його, і ви помітите, що в цьому SQL запиті, тепер, він оцінює завжди вірно, тому що ви помітите, що Ви можете SQL запитів виберіть всю цю інформацію або ви можете просто є 1 = 1. Так що завжди буде оцінити до істини. Це не буде по-справжньому працювати, тому що це означає, що хакер може зламати вашу систему. Вирішення цієї проблеми є те, що ви повинні використовувати систему PDO, Це означає, що ви повинні використовувати знаки питання, що і ви, хлопці, використовувані в PSet 7, де ви збираєтеся використовувати знак питання на місці, де ви хочете, щоб покласти щось, і тоді ви будете мати кому, а потім ви будете мати після цього, після рядка, різні змінні, які ви хочете замінити в ваш знак питання. Таким чином, ви будете відзначити, що тепер у мене є ці червоні знаки питання. Тоді я поклав змінні після моїх рядків так що я знаю, щоб замінити їх у такому порядку після цього. Це дозволить переконатися, що якщо хтось робить це, як це, і у них є або 1 = 1 ситуацію, що буде переконатися, в задній частині, переконайтеся, що він не буде насправді зламати SQL запит. Добре, таким чином, що в значній мірі він, вихор PHP і SQL. Удачі всім вам, і тепер, щоб штат Орегон [Oreoluwatomiwa Babarinsa] Добре все. Час перейти деякий наявність і деякі інші речі дуже швидко, тому ми не тримати вас сьогодні ввечері. JavaScript. Так. JavaScript є своєрідною прохолодному речі, нібито. Те, що ви дійсно повинні знати про JavaScript, це ніби як на стороні клієнта кінець того, що ваш веб-додаток буде робити. Там-то речі, які ви просто не хочете, щоб піклуватися про весь час на стороні сервера. Всі маленькі взаємодії, підкресливши одне, що робить щось зникає. Ви дійсно не хочете, щоб поговорити з вашим сервером весь час для цього. І деякі, що навіть не представляється можливим зробити на стороні сервера. Ось чому ми повинні щось на зразок JavaScript. Прохолодний речі про JavaScript: Він динамічно типізованих. Що це означає, що ваша програма не потрібно знати що саме змінні, коли ви пишете його. Це буде просто свого роду зрозуміти це, як це працює. Інші речі, які здорово про це: Це кучеряве мову дужки, це означає, що синтаксис схожий на С і РНР. Ви не повинні робити багато переробок, коли ви вчитеся JavaScript. Тут у нас є трохи JavaScript. Цікава річ прямо тут у тому, що, якщо ви подивитеся на неї, у нас є трохи JavaScript тут же в голові теги. Що таке робить, в основному просто включити файл JavaScript. Це один із способів ви можете включити JavaScript у вашу програму. Тоді другий трохи насправді деякі вбудовані JavaScript, дуже схоже на вбудованого стилю з CSS, і ви просто писати код дуже швидко там. JavaScript має масиви. Просто ще один спосіб зберегти дані навколо, дуже корисно. Дуже приємно і легко синтаксис. Ви можете використовувати квадратні дужки для доступу все і тримати всі разом. Ніщо не надто складним. Саме чудове JavaScript і скриптових мов в цілому є те, що вам не доведеться турбуватися про розміри масиву. Ви можете просто використовувати array.length і відстежувати його, а також масив може рости або зменшуватися, як вам це потрібно. Таким чином, ви навіть не потрібно турбуватися про будь, о ні, мені потрібно виділити більше речей, або що-небудь в цьому роді. Відмінна річ у тому, що JavaScript має те, що називається об'єкти. Це об'єктно-орієнтована мова, так що він, по суті, спосіб для вас для групування даних разом, чимось нагадує на структуру, але ви можете отримати доступ до нього, як структури або в синтаксисі асоціативного масиву. Це досить просто, а що ви можете зробити з цим група даних разом якщо у вас є купа даних, що пов'язано. Тому що це все речі, які потрібно описати автомобіль, Вам не потрібно мати його в купу різних місцях. Ви можете просто дотримуватися його в 1 об'єкта в JavaScript. Як ви, напевно, знаєте, ітерації є одним з тих трудомістких завдань. Ви просто зробити це протягом знову. Вам потрібно поговорити з кожного об'єкта в автомобілі, або вам потрібно пройти через кожен елемент у списку або щось на зразок цього. Так JavaScript має, подібно PHP, синтаксис Еогеасп. У цьому випадку, це для в циклі. Ви хочете використовувати цей тільки на об'єктах. Є деякі проблеми, які виникають, якщо ви використовуєте це на масивах. Це взагалі одна з тих речей, однак, що дуже корисно, тому що ви усунути багато накладних витрат тому що ви не повинні підтягнути всі у вашій об'єкта самостійно. Ви не повинні пам'ятати всі ключові імена. Ви тільки вид отримати їх назад в цьому синтаксисі. У цьому, з протягом, ви просто хочете, щоб пам'ятати що ви отримуєте назад всі ключі, в дуже схожим чином, щоб хеш-таблиці. Якщо ви пам'ятаєте цього, коли ви поклали б в рядку ви могли б отримати щось з що буде мати значення, пов'язане з ним. Що ви можете зробити з цим ви можете сказати, все в порядку, Я посадили в машину, і я назвав його Ferrari. Таким чином, ви можете помістити в рядку Ferrari пізніше, і ви можете отримати це. І ви можете зробити це в циклі, з Бо в петлі. Так що просто більше про об'єкти. Головне з цього ви повинні пам'ятати, є те, що ви можете використовувати об'єктну структуру подібний синтаксис, коли ви хочете з цим, крім того, якщо те, що ти збираєшся використовувати у вигляді рядка не є допустимим ім'ям змінної. Так що, якщо ви подивіться на що, у нас є ключ з пробілами. Ну, якщо б ви були поставити object.key, простір, з, простір, простору, що просто не мало б сенсу синтаксично. Таким чином, ви тільки можете зробити це з такого роду синтаксису кронштейна. Крім того, JavaScript дуже Сфера-мудро PHP. У вас є 2 шляхи вирішення сферу. Ви не можете мати вар перед змінної, і це просто означає, що це глобальна. Ви можете бачити це з будь-якої точки світу. Навіть якщо ви були поставити про це в якщо заява, ніде в коді після цієї точки, ви могли бачити цю змінну. Інша справа, тим не менш, з Вар, вона обмежена будь-якої функції ви дюйма Якщо ви не в функції, ну, це глобальна. Але якщо ви знаходитесь у функції це видно тільки в цій функції. Я не є приклад, але, так. Це одна з тих речей, де Ви можете управляти тим, що змінні, які ви хочете бути глобальним, які змінні ви хочете бути локальним, але ви повинні бути обережні, про це, тому що ви не маєте тип тонкого контролю зерна, що ви робите в C, де якщо щось оголошується в циклі, це збирається залишитися в тому, що цикл. Те, що ми насправді хвилює, використовуючи наявність для маніпулює веб-сторінок, чи не так? Я маю на увазі, ось чому ми робимо це. Щоб зробити це, ми використовуємо те, що називається DOM. Об'єктної моделі документа. Загалом, що вона робить це займає весь ваш HTML і моделі його в купу об'єктів, які вкладені один в одного. Ви починаєте з чимось на зразок цього. У вас є, праворуч для мене, купа коду, що там начебто - Можна подумати, що було б дуже важко маніпулювати, тому що ви б розбору через купу тексту і того, щоб зібрати крім речі. А що, якщо він не був правильно відформатований? Погані речі трапиться. Так JavaScript піклується про це для вас, і ви отримаєте хороший структуру даних, так, як на мій лівий, де ви просто мати документ, і всередині, що у вас є те, що називається HTML, і всередині, що у вас є голова і тіло, і всередині цієї голови у вас є назва, і так далі, і так далі, і так далі. Це спрощує маніпуляції веб-сторінки, так що це просто, о, я просто хочу поговорити з цим об'єктом. Начебто дуже схоже ви говорити з іншим об'єктом ви зробили самі. Як я вже сказав, все DOM в об'єкті документа. Або це просто одне місце, а потім ви можете піти в ньому, щоб знайти речі, і ви можете зробити це - це старий стиль роблять це, там, де ви робите document.getElementById, а потім ім'я, і, як ви, ймовірно, може сказати, це стає дуже громіздким через деякий час. Таким чином, ви, ймовірно, не хочуть цього робити. Ось чому у нас є Наступне, що ми збираємося говорити про після цього. Головне тут те, що, все в порядку, у вас є всі ці елементи, чи не так? Тому, можливо, я можу змінити колір щось при завантаженні сторінки. Ну і що? Що робити, якщо користувач натискає щось? Я хочу, щоб зробити щось цікаве, коли він натискає щось. Ось чому у нас є події. Ви можете, в принципі, знайти будь-який елемент у вашому DOM, а потім кажуть, гей. Коли це завантажує або хтось натискає на неї, або коли вони миші над ним, щось зробити з ним. І що у вас є, у вас є функції, які обробляють це для вас. Ці функції обробники подій. Що they're - це всього лише химерний спосіб сказати, ця функція виконується тільки при виникненні цієї події. Так він обробляє подія, що виникає. Це, як ви б викласти обробник подій. У мене є кнопки, а при натисканні її, вона вибухає. Так що не натиснути кнопку. Це один із способів наближення до нього, чи не так? У вас є кнопка тег, і по клацанню у вас є рядок, яка говорить, о, до речі, я роблю це вибухає річ для мене. В іншому випадку, це просто, як звичайний кнопку ви тільки що зробили. Ви також можете зробити це по-іншому, , Захоплюючи елемент DOM, але ми залишимо, що після того як ми говоримо про JQuery. JQuery: Це бібліотека, яка є крос-браузерні. Ви можете використовувати його в значній мірі чого-небудь. І це якраз дає багато інструментів для роботи с. Оскільки JavaScript, в той час як потужний, не всі інструменти, необхідні з коробки, щоб дійсно вирішувати веб-додаток, ви можете зробити. Так що спрощує багато речей, дає вам багато функцій з коробки, які ви зазвичай доводиться писати самостійно, знову і знову і знову. І так само, робить речі дуже просто. У вас також є селектори, які дозволяють вивезти всі ті елементи, від вашого DOM набагато більш просто, замість того, щоб використовувати ці дуже довгі виклики функцій. Ще на цих селекторів. У вас є, там ви, скажімо, Я хочу отримати елемент з ID "рок". Ну, в JQuery, це просто $, а потім рядок, яка має фунт, а потім "рок". Це дуже просто і набагато швидше, ніж традиційним JavaScript шляхи вирішення цієї проблеми. А у вас є подібні речі для класів і типів елементів. JQuery - один з цікавих функцій, що ви можете роду стискати вниз запитах на вашому DOM дуже, дуже швидко. Тепер ми повернулися до обробки подій, і це, як ви б впоратися одна подія в JQuery. Так що ми збираємося тут ми говоримо, все в порядку. У мене є тег сценарію, чи не так? Тому у мене є цей інлайн JavaScript. Те, що ми збираємося зробити, це ми збираємося сказати, все в порядку. Коли документ буде готовий, а це значить, це був завантажений документ, ми збираємося йти до цієї функції, і ми збираємося сказати, все в порядку, ця функція насправді робити щось ще. Це в основному говорять, все в порядку, дай мені елемент з ID "MyID." А потім дати це обробник функції, яка виконує, коли ви клацніть по ньому. В основному те, що це робить, він каже, все в порядку. Сторінка завантажується, тому я збираюся в, знайти цей елемент, дати йому цей обробник подій, і це в основному налаштовує сторінки для вас. І це, як ви хочете думати про обробку подій. Ви просто хочете, щоб думати, все в порядку, коли щось відбувається, то, що я хочу щоб це сталося? Ви ж не хочете, щоб думати про, добре, мені потрібно, щоб переконатися, ця річ переговори на цю річ, ця річ бла-бла-бла, тому що ви просто хочете поговорити річ з точки зору подій. Коли це відбувається, це відбувається. Коли це відбувається, що відбувається. І якщо події викликають інші речі, це здорово. Але ви не хочете, щоб спробувати зробити складний код де ви викликавши кілька речей одночасно, тому що ви тільки збираєтеся дати собі головний біль. Добре. Тепер ми можемо отримати нашу сторінку для обробки подій, але, скажімо, мій користувач натискає кнопку. Що робити, якщо я хочу відправити це прохання назад на сервер, але я не хочу, щоб перезавантажити сторінку, так як необхідності перезавантаження нову сторінку кожен раз, коли стає почасти утомливо, і навіщо він мені потрібен знести заголовок знову, а в нижньому знову, і всі елементи сторінки знову просто щоб оновити привітання або час? Так ось чому у нас є щось на зразок Ajax. Що ми можемо зробити тут з Ajax є, можна сказати, все в порядку, Я хочу відправити деякі дані на сервер, і я хочу, щоб отримати відповідь назад, щоб я міг оновлювати свою сторінку, або може бути просто робити деякі алгоритмічні обчислення, що не обов'язково показувати все, щоб користувачеві. Що потрібно для цього? Ну, вам потрібен URL вам потрібно поговорити. Ваш сервер не може просто чарівно слухати з нізвідки. Ви повинні мати певне місце ви посилаєте ці дані. І ви також повинні деякі дані для відправки, або, може бути, це без даних запитів. Ви просто хочете, щоб перевірити зв'язок назад на сервер і сказати, агов, я живий, або щось на зразок цього. А потім ви хочете функцію, яка в основному обробляє успіхом. Припустимо, ви повернутися деяку інформацію з вашого сервера, і ви хочете змінити посаду користувача на своїй сторінці. Так ви отримаєте інформацію назад, і буде ви натискаєте, що на екрані. Що відбувається, є, коли сторінка готова, Ви створюєте на функції клік для цієї кнопки під назвою зазивала. Що це, то робить це, коли, що кнопка натиснута, Ви говорите з greetings.php, ви робите запит POST, а ви говорите, агов, дай мені що-небудь з вашої сторінці. Ми дійсно не потрібно, щоб описати це, але greetings.php, давайте просто скажемо,, віддає "Hello World". Отже, ми отримуємо назад цей "привіт світ", і у випадку успішного завершення цього припускаючи все йде не так, то ми просто піти в цей цільовий місці що ми визначили, і ми просто дотримуватися відповідь там. І це дуже простий спосіб створення запиту Ajax. Дуже швидко, Роб роду згадав про це вже, все може піти не так, погані речі можуть трапитися, так що ви хочете, щоб ознайомитися з цими кодами HTTP реагування. Що це просто, як, 200, все пройшло добре. Щось ще, погані речі сталося. Це взагалі, що ви хочете запам'ятати. Але приємно знати, все це. І, нарешті, як тільки ми пройшли через все це, ми повинні говорити дуже швидко про дизайн, і тоді ми зможемо дозволити вам всім піти. Дизайн. Те, що ви хочете запам'ятати. Задайте собі ці питання: Хто буде використовувати це? Що вони будуть використовувати його для? Що мої користувачі піклуються про? Що вони не піклуються про? Ви просто не хочете зробити додаток, і нехай він просто рости і стати цей гігант, всепоглинаючої, що ви не можете навіть закінчити. Ви хочете мати дискретні цілі та плани і речі, які ви хочете звернутися. Зробити це легко. Все це говорить, в основному, зробити його легким для користувача, щоб використовувати його, чи не зробити його гігантський згусток тексту як цей слайд, власне. Ви просто хочете, щоб він щось де це дуже легко для когось іти в і робити те, що вони хочуть зробити. Ви ж не хочете, щоб вони мали орієнтуватися 5 сторінок щоб дістатися до вашого прем'єр-функції вашого сайту. Якщо Google було 5 сторінок, перш ніж ви могли навіть шукати щось, ніхто не буде використовувати його. І, нарешті, папір прототип, фокус-група. Є хороший дизайн і практики тестування. Просто тому, що ви думаєте, він працює для вас, не означає, хтось ще думає, що це працює. Але так, ось воно що. [CS50.TV]