[Powered by Google Translate] [Розділ 5: менш комфортно]
[Nate Хардісон, Гарвардський університет]
[Це CS50.] [CS50.TV]
Так що ласкаво просимо, хлопці.
Ласкаво просимо до розділу 5.
На даний момент, закінчивши тест 0 і побачивши, як ви зробили,
сподіваюся, ви відчуваєте себе дійсно добре, тому що я був дуже вражений бали в цьому розділі.
Для наших глядачів онлайн, у нас було кілька питань
Про двох останніх проблем на проблеми набору - або на тест, а.
Так що ми збираємося перейти на тих, хто дійсно швидко, так що кожен бачить те, що сталося
і як йти через саме рішення, а не просто перегляд самого рішення.
Ми збираємося піти за останні кілька проблем дуже швидко, 32 і 33.
Тільки, знову ж таки, так що онлайн-глядачі можуть побачити це.
>> Якщо ви звернетеся до вашої проблеми 32, яка знаходиться на сторінці 13,
13 з 16, 32, проблема все про свопи.
Це все про обмін двох цілих чисел.
Це проблема, що ми перейшли пару раз в лекції.
І тут, що ми просимо вас зробити, це швидко сліду пам'яті.
Для заповнення значень змінних, так як вони знаходяться на стеку
як код проходить через цю функцію підкачки.
Зокрема, те, що ми шукаємо - я збираюся поставити цю Ipad вниз -
Зокрема, те, що ми дивимося на цей рядок з номером 6 прямо тут.
І це номером 6, тільки зіткнення з попередньої задачі.
Те, що ми хочемо зробити, це показати або позначення стану пам'яті
як це в той час, коли ми виконуємо цю лінію № 6,
який фактично є повернення з наших своп функції прямо тут.
Якщо ми прокрутити вниз тут, ми побачили, що всі адреси в пам'яті була надана для нас.
Це дуже ключа; ми повернемося до цього через хвилину.
А потім тут на дні, у нас було небагато схема пам'яті, які ми збираємося посилатися.
Насправді я зробив це на моєму iPad.
Так що я буду чергувати назад і вперед між IPad і цей код просто для довідки.
>> Давайте почнемо. По-перше, давайте зосередимося на перших двох лініях основний прямо тут.
Для початку, ми збираємося, щоб ініціалізувати х 1 і у 2.
Таким чином, ми маємо два цілочисельних змінних, вони обидва будуть поміщені в стек.
Ми збираємося поставити 1 і 2 в них.
Так що якщо я перевернутися на мій IPad, сподіваюся, давайте подивимося, -
Apple TV дзеркальне відображення, і ми йдемо. Добре.
Так що якщо я перевернутися на мій IPad,
Я хочу, щоб ініціалізувати х 1 і у 2.
Ми робимо це досить просто, написавши 1 в коробку з написом х
і 2 в графі у. Досить просто.
Отже, тепер давайте повернемося до ноутбука, подивимося, що буде далі.
Так що наступна рядок, де все стає складніше.
Ми передаємо адресу х і адресу у як параметри А і В у своп функції.
Адреса х і адресу у речі, які ми не можемо обчислити
без посилання на ці кулі вказує прямо тут.
І, на щастя, перші два пункти говорять нам саме те, що відповіді на них.
Адреса х в пам'яті 10, і адресу у в пам'яті 14.
Так що ті цінності, які отримують передається в якості і б нагорі в нашій своп функції.
Таким чином, знову перейти назад на нашу схему, я можу написати 10 в
і 14 в б.
Тепер ця точка, де ми продовжуємо підкачки.
Таким чином, гортати назад в ноутбук знову,
ми бачимо, що шлях підкачки працює, я спочатку разименовать і зберегти результат в TMP.
Таким чином, оператор разименованія говорить: "Привіт. Лікувати вміст змінної в якості адреси.
Перейти до того, що зберігається за цією адресою, і завантажити його. "
Що ви завантажуєте з змінної будуть зберігатися в нашій TMP змінна.
Подавати назад в iPad.
Якщо ми підемо за рішенням 10, ми знаємо, що адреса 10 є varible х
тому що нам сказали, що наші кулі, що адресу х в пам'ять 10.
Так що ми можемо піти туди, отримати значення його, що 1, як ми бачимо на наших Ipad,
і завантажити в TMP.
Знову ж таки, це не остаточний зміст.
Ми збираємося пройти і ми повернемося до наших кінцевим станом програми в кінці.
Але зараз у нас є значення 1 зберігається в TMP.
>> І є швидкий питання тут.
[Олександр] Є оператором разименованія - це тільки зірки прямо перед змінною?
>> Да. Таким чином, оператор разименованія, як ми перевернути назад в наш ноутбук ще раз,
ця зірка прямо перед.
У цьому сенсі, це - ви порівняти її з оператором множення
яка вимагає двох речей; разименовать оператор унарний оператор.
Тільки стосовно до одного значення, а не бінарний оператор,
де ви подаєте заявку на два різні значення.
Так що те, що відбувається в цій лінії.
Ми завантажили значення 1 і зберігати його в наш тимчасовий цілої змінної.
У наступному рядку, ми зберігаємо вміст б у -
або, скоріше, ми зберігаємо вміст, б вказує на в місце, де вказує.
Якщо ми проаналізуємо цю справа наліво, ми будемо разименованія б,
Ми маємо намір звернутися 14, ми збираємося захопити ціле число, яке є,
а потім ми збираємося перейти за адресою 10,
і ми збираємося кинути результат нашої разименованія б у цей простір.
Подавати до нашої Ipad, де ми можемо зробити це трохи більш конкретним,
це може допомогти, якщо я напишу номери на всі адреси тут.
Отже, ми знаємо, що при в, ми знаходимося на адресу 14, х знаходиться за адресою 10.
Коли ми починаємо на б, ми разименованія б, ми збираємося, щоб захопити значення 2.
Ми збираємося захопити це значення, тому що це цінність, яка мешкає за адресою 14.
І ми збираємося помістити його в змінний, який мешкає за адресою 10,
який тут же, відповідна нашої змінної х.
Так що ми можемо зробити трохи перезапису тут
де ми позбудемося 1 і замість цього написати 2.
Так що все добре, і гарний у світі, хоча ми перезаписані х зараз.
Ми зберегли старе значення х в нашій TMP змінна.
Таким чином, ми можемо завершити своп з нового рядка.
Подавати до нашого ноутбука.
Тепер все, що залишається взяти вміст з нашого тимчасового цілої змінної
і зберігати їх в змінну, яка мешкає за адресою, що б тримає.
Так що ми збираємося ефективно разименованія б одержати доступ до змінної
тобто за адресою, що б проводить у ньому,
і ми збираємося, щоб наповнити значенням, TMP тримається в ній.
Подавати назад в IPad ще раз.
Я можу стерти це значення тут, 2,
, А замість цього ми будемо копіювати на 1 прямо в нього.
Тоді наступна рядок, яка виконує, звичайно, -
якщо перевернути назад в ноутбук - це пункт 6,
, Яка є точкою, в якій ми хотіли, щоб наш схема повністю заповнені.
Таким чином, гортати назад в IPad ще раз, тільки так можна побачити закінчену схему,
Ви можете бачити, що у нас 10 в, 14-В, 1 в TMP, 2-х та 1 в у.
Є запитання з цього приводу?
Чи має це сенс, пройшовши через це?
Зробити менше сенсу? Сподіваюся, що ні. Добре.
>> Покажчики є дуже складний предмет.
Один з хлопців, з якими ми працюємо має дуже поширена приказка:
"Щоб зрозуміти, покажчики, ви повинні спочатку зрозуміти покажчиків".
Який я думаю, що це дуже вірно. Це займе деякий час, щоб звикнути до нього.
Жеребкування фотографій, малювання великим обсягом пам'яті діаграм, як цей дуже корисний,
і після того, як ви йдете через, наприклад, після приклад за прикладом,
він почне робити трохи більше сенсу і трохи більше сенсу і трохи більше сенсу.
Нарешті, в один прекрасний день, ви будете мати все це повністю освоєні.
Будь-які питання, перш ніж ми перейдемо до наступної проблеми? Добре.
Так перевернути назад в ноутбук.
Наступна проблема, у нас це проблема номер 33 на файл I / O.
Збільшити на це небагато.
Завдання 33 - Так?
>> [Даниїл] Я тільки що був швидкий питання. Ця зірка, або зірочки,
це називається разименованія при використанні зірочки раніше.
Як це називається, коли ви використовуєте амперсанд раніше?
>> Амперсанд, перш ніж це адреса-оператора.
Так що давайте прокрутити назад.
Ой. Я в режим масштабування, тому я не можу дійсно прокрутки.
Якщо ми подивимося на цей код дуже швидко, прямо тут,
знову, те ж саме відбувається.
Якщо ми подивимося на цей код прямо тут, на цій лінії, де ми зробити дзвінок, щоб поміняти,
амперсанд просто кажу "отримати адресу, за якою змінна х життя".
Якщо ваш компілятор компілює код,
вона має насправді фізично виділити місце в пам'яті для всіх ваших змінних, щоб жити.
І те, що компілятор може зробити, як тільки ви зібрали всі,
він знає: "О, я поклав х на адресу 10. Я поклав у на адресу 14".
Він може заповнити ці значення для вас.
Таким чином, ви можете - він може потім передати це в проході і і у в а.
Ці хлопці отримати адресу, але вони також, коли ви передаєте їх у своп функції,
цей тип інформації, цей Int * прямо тут, говорить компілятору,
"Добре, ми збираємося інтерпретації цю адресу як адресу цілої змінної".
На адресу INT, який відрізняється від адреси символьної змінної
тому що Int займає, на 32-бітної машині, займає 4 байти простору,
в той час як характер тільки займає 1 байт.
Тому дуже важливо знати і те, що є - те, що живе, який тип значення
мешкає за адресою, який отримав пройшло дюйма
Або адресу, яку ви маєте справу.
Таким чином, ви знаєте, скільки байтів інформації насправді завантажити з оперативної пам'яті.
І потім, так, це оператор разименованія, як ви просили,
йде і доступ до інформації за певною адресою.
Так він каже, з цієї змінної тут, належать зміст, адреса,
піти на цю адресу, і витягнути, завантажити в процесор, навантаження в регістр
Фактичні значення або змісту, які живуть за цією адресою.
Є ще питання? Це хороші питання.
Це багато нової термінології теж.
Це також вид фанк, бачачи & * і в різних місцях.
>> Добре.
Отже, повернемося до задачі 33, файловий ввід / вивід
Це була одна з тих проблем, які я думаю, що пару речей відбулося.
Один з них, це досить нова тема.
Він був представлений досить скоро перед вікторини,
і тоді я думаю, це було щось начебто однієї з тих текстових задач з математики
де вони дають вам багато інформації, але ви насправді не до кінця того, щоб використовувати тонни цього.
У першій частині цієї проблеми опису того, що файл CSV є.
Тепер, файлів CSV, у відповідності з описом, є значень, розділених комами файл.
Причина це взагалі цікаво, і з цієї причини ви ніколи не використовуєте їх,
це, тому що, як багато хто з вас коли-небудь використовували такі речі, як Excel?
Малюнок більшість з вас, напевно, чи буде використовувати в якийсь момент у вашому житті.
Ви будете використовувати щось на зразок Excel.
Для того, щоб отримати дані з таблиці Excel або зробити який-небудь обробці з ним,
якби ви хотіли, щоб написати програму C або Python програми, Java програми,
мати справу з даними, що зберігаються там,
одним з найбільш поширених способів отримати його в файл CSV.
І ви можете відкрити Excel і коли ви йдете в "Зберегти як" діалог,
Ви можете вийти з поточного файлу CSV.
>> Handy знати, як мати справу з цими речами.
Як це працює в тому, що це схоже на - я маю на увазі, вона, по суті, імітуючи таблицю,
де, як ми бачимо тут, у самому лівому шматок,
у нас є всі прізвища.
Отже, ми маємо Малан, то Хардісон, а потім Боуден, MacWilliam, а потім Чан.
Всі прізвища. І тоді кома відокремлює прізвищ з перших імен.
Давид, Nate, Роб, Томмі і Zamyla.
Я завжди змішувати Роббі і Тома.
І ось, нарешті, третій стовпець адреси електронної пошти.
Як тільки ви зрозумієте, що інша частина програми досить простий в реалізації.
Що ми зробили для того, щоб імітувати цю ж структуру в нашій програмі C
це ми використовували структуру.
Ми почнемо грати з цим трохи більше, а також.
Ми бачили їх у перший трохи в проблемі набір 3, коли ми маємо справу зі словниками.
Але це співробітники структура зберігає прізвище, ім'я та електронну пошту.
Так само, як наш файл CSV був зберігання.
Так що це просто конвертації з одного формату в іншій.
Ми повинні перетворити, в цьому випадку, співробітники структур в лінію,
розділених комами лінії, як і що.
Чи має це сенс? Ви, хлопці, всі прийняті вікторини,
так що я думаю, ви по крайней мере, було деякий час, щоб подумати про це.
>> У прокат функції, завдання вимагає від нас, щоб взяти в - МИ збільшити на цьому небагато -
прийняти в штатну структуру, персонал структури, з ім'ям S,
і додати його вміст нашого файлу staff.csv.
Виявляється, що це досить простий у використанні.
Ми видів пограти з цими функціями трохи більше сьогодні.
Але в даному випадку, Fprintf функція дійсно є ключовою.
Так що з Fprintf, ми можемо надрукувати, як і ви, хлопці, вже використовують Printf весь цей термін.
Ви можете Printf рядок у файл.
Таким чином, замість того щоб просто зробити звичайну Printf виклик, де ви даєте йому рядок формату
, А потім замінити всі змінні з наступними аргументами,
з Fprintf, ваш перший аргумент, замість файлу, який ви хочете записати.
Якщо ми подивимося на це в прилад, наприклад, людина Fprintf,
ми можемо побачити різницю між Printf і Fprintf.
Я збільшити тут небагато.
Так що з Printf, ми даємо йому рядок формату, а потім наступні міркування
Тут всі змінні для заміни або підстановки в нашому форматі рядки.
У той час як з Fprintf, перший аргумент насправді цей файл * називається потоком.
>> Повертаючись сюди, щоб наш прокат,
Ми вже отримали наш файл * потік відкритий для нас.
Це те, що це перша лінія робить, він відкриває файл staff.csv,
воно відкривається в режимі додавання, і все, що залишилося для нас зробити, це
написати штатної структури в файл.
І, давайте подивимося, я хочу використовувати IPad?
Я буду використовувати iPad. У нас є порожнеча - Давайте поставимо це на стіл, щоб я міг написати трохи краще -
анулювати оренду і бере в один аргумент, штатна структура називається с.
Є наші дужки, ми отримали наш файл * називається файл,
у нас є Еореп лінії нам дано,
а я просто пишу це як точки, так як це вже в Pedia.
І тоді на нашій наступній рядку, ми збираємося зробити дзвінок в Fprintf
і ми збираємося пройти в файл, який ми хочемо друкувати,
і тоді наша рядок формату, який -
Я повідомлю вам, хлопці скажіть мені, що він виглядає.
Як щодо вас, Стела? Ви знаєте, що перша частина рядка формату виглядає?
[Stella] Я не впевнений. >> Не соромтеся задавати Джиммі.
Чи знаєте ви, Джиммі?
[Джиммі] Чи буде це просто бути в останній раз? Я не знаю. Я не зовсім впевнений.
>> Добре. Як щодо того, хто-небудь отримати правильне на іспиті?
Ні, все в порядку.
Виявляється, що тут все, що ми повинні зробити, це ми хочемо, щоб кожна частина нашої штатної структури
бути роздруковані у вигляді рядка в нашому файлі.
Ми просто використовувати рядок символів заміни трьох різних разів, тому що у нас є прізвища
з подальшою комою, то ім'я слід кома,
і, нарешті, адресу електронної пошти, який слід - що не
установки на екрані - але за ним слідує символ нового рядка.
Так що я збираюся писати тільки там.
А потім після нашого формату рядка,
ми просто повинні заміни, які ми отримуємо доступ допомогою точкової нотації
що ми бачили в проблемі набору 3.
Ми можемо використовувати s.last, s.first, і s.email
замінити в цих трьох цінностей в нашому форматі рядки.
Так як все пройшло? Сенс?
Так? Ні? Можливо? Добре.
>> Остання річ, що ми робимо, після того як ми друкованих та після того як ми відкрили наш файл:
всякий раз, коли ми відкрили файл, ми завжди повинні пам'ятати, щоб закрити його.
Тому що інакше ми в кінцевому підсумку витік пам'яті,
з використанням до файлових дескрипторів.
Таким чином, щоб закрити його, які функції ми використовуємо? Деніел?
[Даниїл] Fclose? >> Fclose, точно.
Таким чином, остання частина цієї проблеми було правильно закрити файл, використовуючи Fclose функції,
який виглядає так.
Не надто божевільним.
Cool.
Так що це проблема 33 на вікторину.
Ми повинні, безумовно, більш файлового введення / виводу йдуть вгору.
Ми зробимо трохи більше в сьогоднішній лекції, або в розділі сьогодні,
тому що це те, що збирається складають основну частину цієї майбутньої PSET.
Давайте перейдемо від вікторину в цій точці. Так?
>> [Charlotte]] Чому Fclose (файл), а Fclose (staff.csv)?
>> Ач. Бо виходить, що - так що питання, яке є більшим,
Ось чому, коли ми пишемо Fclose, ми письмово Fclose (файлу) змінної зірки
на відміну від імен файлів, staff.csv? Хіба це правильно? Так.
Отже, давайте подивимося. Якби я повернутися до моїх ноутбуком,
і давайте подивимося на Fclose функції.
Так Fclose функція закриває потік, і він приймає в покажчик на потік, що ми хочемо закрити,
на відміну від фактичного імені файлу, який ми хочемо закрити.
І це тому, що за лаштунками, коли ви робите виклик Еореп,
коли ви відкриваєте файл, ви насправді виділення пам'яті для зберігання інформації про файл.
Таким чином, у вас є файл покажчик, який містить інформацію про файл,
таких, як він відкритий, його розмір, де ви знаходитеся в даний момент файлу,
так що ви можете зробити читання і запис викликів, що особливе місце у файлі.
Ви в кінцевому підсумку закриття покажчика замість закриття файлу.
>> Так? [Даниїл] Таким чином, для того, щоб використовувати прокат, ви скажете - як це отримати дані, введені користувачем?
Хіба Fprintf діяти як GetString в тому сенсі, що це буде просто чекати введення користувача
і просимо вас ввести цей - або чекати, поки ви вводите ці три речі?
Або вам потрібно використовувати щось для здійснення оренди?
>> Да. Так що ми не - питання було, як ми можемо отримати дані, введені користувачем
З метою реалізації оренду? І те, що ми маємо тут справу з зухвалою прокату,
Пройшло в цьому штаті структура з усіма даними, що зберігаються в структурі вже.
Так Fprintf може просто написати, що дані безпосередньо у файлі.
Там немає очікуванні введення користувача.
Користувач вже дав вхідний належним чином поставивши його в цьому штаті структури.
І все, звичайно, було б зламатися, якщо будь-який з цих покажчиків були нульові,
таким чином, ми прокрутити назад тут, і ми дивимося на нашу структуру.
У нас є остання стрічка, стрічка перше, рядки електронній пошті.
Ми тепер знаємо, що всі ці насправді, під капотом, це символ змінних *.
Це може або не може бути направлений до нуля.
Вони можуть бути спрямовані на пам'ять в купі,
Може бути, пам'ять на стеку.
Ми дійсно не знаємо, але якщо будь-який з цих покажчиків дорівнюють нулю, або недійсним,
, Що неодмінно аварії нашому прокаті функції.
Це було щось, що було частково виходить за рамки іспиту.
Ми не турбуватися про це.
Великий. Добре. Таким чином, переходячи від вікторини.
>> Давайте закриємо цей хлопець, і ми будемо дивитися на PSET 4.
Так що, якщо ви, хлопці, подивіться на специфікації PSET, як тільки ви можете отримати до нього доступ, cs50.net/quizzes,
Ми збираємося пройти через кілька розділу сьогоднішні проблеми.
Я прокрутка вниз - розділ питань починається на третій сторінці PSET спец.
І перша частина просить вас піти і подивитися короткий на перенаправлення та труб.
Який був частково прохолодно Коротше кажучи, показує деякі нові, прохолодно командного рядка трюків, які ви можете використовувати.
І тоді у нас є кілька питань до вас.
Це перше питання про потоки, в яких Printf пише за замовчуванням,
ми частково торкнулися тільки трохи хвилину тому.
Це Fprintf, що ми тільки що обговорювали займає в потік файлу * в якості аргументу.
Fclose займає в потік файлу *, а також,
і значення, що повертається Еореп дає вам файл потоку *, а також.
Тому ми не бачили тих, хто раніше, коли ми мали справу з Printf
Тому Printf за замовчуванням має потоці.
І за замовчуванням потік, в який він записує
Ви дізнаєтеся про в короткостроковій.
Таким чином, безумовно, поглянемо на це.
>> У розділі Сьогодні, ми збираємося поговорити трохи про те, GDB,
тому що чим більше ви знайомі з нею, тим більше практики ви отримуєте разом з ним,
краще ви будете насправді вистежити помилки у власному коді.
Це прискорює процес налагодження до надзвичайно.
Таким чином, за допомогою Printf, кожен раз, коли ви робите, що вам доведеться перекомпілювати ваш код,
Ви повинні запустити його знову, іноді ви повинні рухатися Printf виклик усьому,
закоментувати код, він просто займає деякий час.
Наша мета, щоб спробувати переконати вас, що з GDB, ви можете істотно
Printf нічого в будь-якій точці вашого коду і вам ніколи не доведеться перекомпілювати.
Ви ніколи не повинні починатися і гадати, де Printf наступному.
Перше, що потрібно зробити, це скопіювати цей рядок і отримати код секції від стінки.
Я копіюванні цей рядок коду, яка говорить: "Wget http://cdn.cs50.net".
Я хочу, щоб скопіювати його.
Я збираюся перейти на мій прилад, масштаб таким чином, ви можете бачити, що я роблю,
вставивши туди, і коли я вдарив Enter, ця команда буквально Wget є веб отримаєте.
Це збирається знести цей файл з мережі Інтернет,
і він збирається зберегти його в поточному каталозі.
Тепер, якщо я перераховую моєму поточному каталозі ви можете побачити, що я отримав цю section5.zip файл прямо там.
Щоб справитися з цим хлопцем, щоб розпакувати його,
Це можна зробити в командному рядку, як це.
Section5.zip.
Це буде розпакувати його, створіть папку для мене,
роздмухувати весь вміст, покласти їх туди.
Так що тепер я можу піти в мій розділ 5 каталозі за допомогою компакт-диска команди.
Очистити екран за допомогою ясно. Таким чином очистити екран.
Тепер у мене є хороший чистий термінал справу.
>> Тепер, якщо я список всіх файлів, які я бачу в цьому каталозі,
Ви бачите, що в мене є чотири файли: buggy1, buggy2, buggy3, і buggy4.
Я також отримав відповідні. С файлами.
Ми не збираємося дивитися на. Файли з на даний момент.
Замість цього, ми збираємося використовувати їх, коли ми відкриваємо GDB.
Ми тримали їх навколо так, що ми маємо доступ до вихідного коду, коли ми використовуємо GDB,
але мета цієї частини розділу возитися навколо з GDB
і подивитися, як ми можемо використовувати його, щоб з'ясувати, що відбувається не так з кожною з цих чотирьох програм баггі.
Таким чином, ми тільки збираємося в кімнаті дуже швидко,
і я збираюся попросити кого-небудь запустити одну з програм баггі,
а потім ми підемо в групу через GDB, і ми побачимо, що ми можемо зробити, щоб виправити ці програми,
або, принаймні визначити, що відбувається не так у кожному з них.
Давайте почнемо тут з Даніелем. Чи будете ви балотуватися buggy1? Давайте подивимося, що відбувається.
[Даниїл] Він каже, що є додаток вина. >> Да. Саме так.
Так що, якщо я біжу buggy1, я отримую сегменті вина.
На даний момент, я можу піти і відкрити buggy1.c,
спробувати з'ясувати, що відбувається не так,
але одна з найнеприємніших речей про цю помилку сегменті вина
те, що він не скаже вам про те, що рядок програми речі насправді пішло не так і зламався.
Ви начебто повинні дивитися на код
і з'ясувати, використання припущення і перевірити чи Printf щоб побачити, що відбувається не так.
Одна з кращих речей про GDB є те, що це дуже, дуже легко
щоб з'ясувати лінія, на якій збою програми.
Це повністю стоїть того, щоб його використовувати, навіть якщо тільки для цього.
Таким чином, для завантаження GDB, я типу GDB, а потім я даю йому шлях до виконуваного файлу, що я хочу працювати.
Тут я друкую GDB ./buggy1.
Натисніть Enter. Дає мені все це інформація про авторські права,
і тут ви побачите цей рядок, яка говорить: "Читання символів з / Головна /
jharvard/section5/buggy1 ".
І якщо все піде добре, ви побачите, що виведіть повідомлення, яке виглядає наступним чином.
Він буде читати символи, він скаже: "Я читаю символи з виконуваного файлу"
, А потім вона буде мати це "зроблено" повідомлення тут.
Якщо ви бачите деякі інші варіації цього, чи ви бачите його не могли знайти символи
або щось на зразок того, що це означає, що ви просто ще не складено виконуваний файл належним чином.
При компіляції програми для роботи з GDB, ми повинні використовувати цю спеціальну г-прапор,
і що робиться за замовчуванням, якщо ви компілюєте ваші програми, просто набравши зробити
або роблять помилки або роблять відновити, будь-який з них.
Але якщо ви збираєте вручну за допомогою Clang, то вам доведеться піти і включати, що г-прапор.
>> На даний момент, тепер у нас є GDB рядку
це досить просто запустити програму.
Ми можемо або ввести перспективі, або ми можемо просто Type-R.
Більшість команд GDB може бути скорочена.
Зазвичай тільки один чи пару букв, який є досить хорошим.
Так Саад, якщо ви Type R і натисніть Enter, що відбувається?
[Саад] Я отримав SIGSEGV, помилки сегментації, а потім все це абракадаброю.
>> Да.
Як ми бачимо на екрані прямо зараз, і, як Саад сказав:
коли ми вводимо пробігу або R і натисніть Enter, ми до сих пір отримати той же сегмент вина.
Таким чином, використання GDB не вирішує наші проблеми.
Але це дає нам деякий абракадабру, і виявляється, що це абракадаброю
насправді говорить нам, де це відбувається.
Для розбору цього небагато, це перший біт є функцією, в якій все відбувається не так.
Там ця __ strcmp_sse4_2, і він говорить нам, що відбувається в цьому файлі
називається sysdeps/i386, все це, знову ж, вид безлад - але лінія 254.
Це свого роду важко розібрати. Зазвичай, коли ви бачите такі речі, як це,
, Що означає, що вона сегментам розломів в одній із системних бібліотек.
Так що щось робити з STRCMP. Ви, хлопці, бачили STRCMP раніше.
Не надто божевільним, але це означає, що STRCMP зламаний або що є проблема з STRCMP?
Як ви думаєте, Олександре?
[Олександр] Це що - становить 254 ліній? І - не двійковий, але це не їх стелі,
а там інша мова для кожної функції. Хіба що 254 у цій функції, або -?
>> Це лінія 254. Схоже, що в цьому немає. Файл с, так що це, ймовірно, зборка код.
>> Але, я думаю, більш насущні речі є, тому що ми отримали сегменті вина,
і, схоже, це йде від STRCMP функції,
це має на увазі, те, що STRCMP не працює?
Це не повинно, ми сподіваємося. Таким чином, тільки тому, що у вас є помилки сегментації
В одній з функцій системи, як правило, це означає, що ви просто не називати його правильно.
Найшвидший, що потрібно зробити, щоб з'ясувати, що відбувається насправді
коли ви бачите щось божевільний, як це, коли ви бачите сегмент вина,
Особливо, якщо у вас є програма, яка використовує більше, ніж просто основний,
це використовувати трасування.
Я скорочую слід у письмовій формі BT, на відміну від повного слова трасування.
Але Шарлотта, що відбувається, коли ви набираєте BT і натисніть Enter?
[Charlotte] Він показує мені два рядки, 0 лінією і лінією 1.
>> Да. Таким чином, лінія 0 і лінії 1.
Ці фактичні кадри стека, що в даний час в грі, коли ваша програма розбився.
Починаючи з верхнього кадру, кадр 0 і, підійшовши до самої нижньої, яка є кадр 1.
Наша верхня рама STRCMP кадру.
Ви можете думати про це як же, проблема, яку ми робили тільки на вікторину з покажчиками,
де ми поміняти стек поверх основного кадру стека,
і у нас були змінні, які підкачки використовує у верхній частині змінних, основним використовую.
Тут наша аварії сталися в нашій STRCMP функція, яка отримала назву нашої основної функції,
і трасування дає нам не тільки функції, в якому речі не вдалося,
але це також говорить нам, де все було викликано.
Так що якщо я виділіть на трохи більше правої,
ми бачимо, що так, ми були на лінії 254 цього STRCMP-sse4.s файл.
Але дзвінок був зроблений на buggy1.c, рядок 6.
Таким чином, це означає, що ми можемо зробити, - це ми можемо просто піти перевірити і подивитися, що відбувається на
в buggy1.c, рядок 6.
Знову ж таки, є кілька способів зробити це. Один з них, щоб вийти з GDB
або ваш код відкритий в іншому вікні і перехресні посилання.
Це, само по собі, це дуже зручно, тому що тепер, якщо ви знаходитеся в офісі годин
і у вас є сегменти вина і ваша TF це цікаво, де все було ламати,
Ви можете просто сказати: "О, рядок 6. Я не знаю, що відбувається,
але щось в рядку 6 є причиною моєї програми зламати ".
Інший спосіб зробити це, ви можете використовувати цю команду називали список в GDB.
Ви також можете скорочувати його з л.
Таким чином, якщо ми потрапили л, що ми сюди потрапили?
Ми отримуємо цілу купу дивних речей.
Це фактичний код збірки
, Який знаходиться в strcmp_sse4_2.
Це виглядає роду фанки,
і причина, ми отримуємо це тому, що зараз,
GDB має нас в кадрі 0.
>> Так що в будь-який час ми дивимося на змінні, в будь-який час подивитися на вихідний код,
ми дивимося на вихідний код, який відноситься до кадру стека ми в даний час дюйма
Так що для того, щоб отримати щось значиме, ми повинні
перейти в стеці, що має більше сенсу.
У цьому випадку, основною фрейм стеку б зробити трохи більше сенсу,
тому що це було насправді код, який ми написали.
Чи не STRCMP код.
Те, як ви можете переміщатися між кадрами, в даному випадку, тому що у нас є два,
у нас є 0 і 1,
Ви робите це з вгору і вниз команди.
Якщо я переїду один кадр,
Зараз я в основному фреймі стека.
Я можу рухатися вниз, щоб повернутися туди, де я був,
йти знову, знову спуститися, і піднятися знову.
Якщо ви коли-небудь зробити свою програму в GDB, ви отримуєте аварії, ви отримаєте слід,
і ви побачите, що це в деякому файлі, який ви не знаєте, що відбувається.
Ви намагаєтеся списку, код виглядає не знайомі вам,
погляньте на ваші кадри і з'ясувати, де ви знаходитеся.
Ви, напевно, не в тому фрейм стеку.
Або, принаймні, ти в кадрі стека, що не один, що ви дійсно можете налагоджувати.
Тепер, коли ми знаходимося у відповідному кадрі стека, ми в основному,
Тепер ми можемо використовувати команду списку, щоб з'ясувати, які лінії було.
І ви можете бачити його, він надрукував його для нас прямо тут.
Але ми можемо вдарити перерахувати все те ж саме, і список дає нам цю гарну роздруківку
фактичного вихідного коду, що відбувається тут.
>> Зокрема, ми можемо подивитися на рядку 6.
Ми бачимо, що відбувається тут.
І, схоже, ми робимо порівняння рядків
між рядків "CS50 породи" і ARGV [1].
Щось у цьому було збоїв.
Таким чином, Міссі, чи є у вас думки про те, що може бути тут відбувається?
[Missy] Я не знаю, чому це збій. >> Ти не знаєш, чому це збій?
Джиммі, які думки?
[Джиммі] я не зовсім впевнений, але в останній раз ми використовували порівняння рядків,
або STRCMP, у нас були як три різних випадках під ним.
У нас не було ==, я не думаю, що прямо в першому рядку.
Замість цього він був розділений на три, а один був == 0,
один був <0, я думаю, і один> 0.
Тому, можливо, щось в цьому роді? >> Да. Так що це питання
про ми робимо порівняння правильно?
Stella? Будь-які думки?
[Stella] Я не впевнений. >> Не впевнений. Деніел? Думки? Добре.
Виявляється, те, що відбувається прямо тут, коли ми запустили програму
і ми отримали сегменті провини, коли ви запускаєте програму в перший раз, Данило,
ти дати йому ніяких аргументів командного рядка?
[Даниїл] Немає >> Ні. У такому випадку, що є значенням ARGV [1]?
>> Існує ніякого значення. >> Праві.
Ну, немає відповідного значення рядка.
Але є деяке значення. Що таке значення, яке отримує зберігається там?
>> Сміття значення? >> Це або сміття вартості, або, в даному випадку,
В кінці масиву ARGV завжди закінчується нульовим.
Так що ж насправді є там зберігаються дорівнює нулю.
Іншого способу вирішити цю проблему, а не думати його до кінця,
полягає в спробі друку його.
Це де я говорив, що за допомогою GDB є більшим,
тому що ви можете роздрукувати всі змінні, всі значення, які ви хочете
за допомогою цього зручного денді з командою.
Так що якщо я типу Р, а потім я вводжу значення змінної або ім'я змінної,
кажуть, агдс, я бачу, що агдс 1.
Якщо я хочу, щоб роздрукувати ARGV [0], я можу зробити це просто так.
І, як ми бачили, ARGV [0] завжди є ім'ям вашої програми,
Завжди ім'я виконуваного файлу.
Тут ви бачите, він отримав повне ім'я.
Я також можете роздрукувати ARGV [1] і подивитися, що відбувається.
>> Тут ми отримали таке містичне значення.
Ми отримали цю 0x0.
Пам'ятаєте, на початку семестру, коли ми говорили про шістнадцяткових чисел?
Або що мало хто сумнівається в кінці PSET 0 про те, як складати 50 в шістнадцятковій?
Як ми писати шістнадцяткові числа в CS, тільки щоб не плутати себе
з десятковою числа, ми завжди їх з префіксом 0x.
Так що цей префікс 0x завжди просто означає, інтерпретувати наступним число як шістнадцяткове число,
а не як рядок, а не як десяткове число, а не як двійкові числа.
Так як число 5-0 є дійсним числом в шістнадцятковій.
І це число в десятковій, 50.
Так що це тільки, як ми неоднозначність.
Так 0x0 засобів шістнадцятковому 0, який також є десятковій 0, двійковий 0.
Це тільки значення 0.
Виявляється, що це те, що нульові, власне, в пам'яті.
Null просто 0.
Тут елемент зберігається в ARGV [1] дорівнює нулю.
Таким чином, ми намагаємося порівняти наші "CS50 скелі" рядок порожній рядок.
Так разименованія NULL, намагається отримати доступ до речі в нуль,
ті, як правило, збирається викликати якусь несправність сегментації або інших поганих речей.
І виявляється, що STRCMP не перевірити
або не ви пройшли в значення, яке нульовий.
Швидше за все, він просто йде вперед, намагається робити свою справу,
і якщо він сегментам недоліки, він сегментам недоліки, і це ваша проблема. Ви повинні піти виправити.
Дійсно швидко, як ми могли б вирішити цю проблему? Шарлотта?
[Charlotte] Ви можете перевірити, якщо використання.
Так що, якщо ARGV [1] є недійсним, == 0, то повертається 1, або щось в [нерозбірливо].
>> Да. Так ось один відмінний спосіб зробити це, як ми можемо перевірити,
Значення, яке ми збираємося перейти в STRCMP, ARGV [1], його недійсним?
Якщо це нуль, то можна сказати, добре, перервати.
>> Більш поширений спосіб зробити це полягає у використанні агдс значення.
Ви можете подивитися прямо тут, на самому початку головний,
ми опустили, що перший тест, який ми зазвичай робимо, коли ми використовувати аргументи командного рядка,
яка полягає в перевірці чи наші агдс значення те, що ми очікували.
У цьому випадку, ми очікуємо, принаймні, два аргументи,
Назва програми плюс одна іншу.
Тому що ми збираємося використовувати другий аргумент прямо тут.
Таким чином, за якийсь тест заздалегідь, до нашого STRCMP виклику
що тести, чи дійсно ARGV по крайней мере 2, буде робити те ж саме роду речі.
Ми бачимо, що працює, запустивши програму знову.
Ви завжди можете перезавантажити програму в GDB, який дійсно хороший.
Ви можете запустити, і коли ви проходите в якості аргументів вашої програми,
Ви передаєте їх, коли ви подзвоните працювати, а не при завантаженні GDB.
Таким чином, ви можете зберегти виклику програми з різними аргументами кожен раз.
Так біжіть, або знову ж таки, я можу Type R, і давайте подивимося, що станеться, якщо набрати "привіт".
Він завжди буде питати вас, якщо ви хочете, щоб почати з самого початку ще раз.
Як правило, ви хочете, щоб почати з самого початку ще раз.
І в цей момент, вона запускає його знову, він друкує
Програма, яку ми біжимо, buggy1 з аргументом привіт,
і це виводить з цього стандарту, він говорить: "Ви отримуєте D," сумне обличчя.
Але ми не сегментам вина. Він сказав, що процес завершився нормально.
Так що виглядає досить добре.
Немає більше сегменті вина, ми зробили це минуле,
так що схоже, що це дійсно помилка сегменті вина, що ми отримували.
На жаль, це говорить нам, що ми отримуємо D.
>> Ми можемо повернутися назад і подивитися на вихідний код і подивитися, що там відбувається
щоб з'ясувати, що було - чому воно було говорити нам, що ми отримали D.
Давайте подивимося, от це було Printf кажуть, що ви отримали D.
Якщо ми введемо список, як ви тримаєте введення списку, він тримає ітерації вниз через вашу програму,
так що покажу Вам декілька перших рядків програми.
Тоді покажу вам кілька рядків, а на наступний шматок і наступний шматок.
І він буде намагатися йти вниз.
А тепер ми повернемося до "лінії номер 16 знаходиться поза діапазону".
Тому що він має тільки 15 ліній.
Якщо ви дійшли до цієї точки, і ваші ставите питанням: "Що робити?" Ви можете використовувати команду допомоги.
Використовуйте допомогу, а потім дати йому ім'я команди.
І ви бачите, GDB дає нам всі такого роду речі.
Він говорить: "Без аргументів, перераховує десять рядків після або у всьому попередньому лістингу.
List - список десяти рядків раніше - "
Так давайте спробуємо використовувати список мінус.
І в якому перераховані 10 рядків попередньої, ви можете пограти зі списком небагато.
Ви можете зробити список, список - ви можете навіть дати перерахувати ряд, як і список 8,
і вона буде перерахувати 10 ліній навколо лінії 8.
І ви можете бачити, що відбувається тут, у вас є простий, якщо інше.
Якщо ви наберете в CS50 скелі, він друкує "Ви отримуєте А."
В іншому випадку вона виводить "Ви отримуєте D."
Ледар міста. Добре. Так?
>> [Даниїл] Тому, коли я намагався робити CS50 порід без лапок,
він говорить: "Ви отримуєте D."
Я потребував в лапки, щоб змусити його працювати, чому це?
>> Да. Виявляється, що коли - це ще одна кумедна ласий шматочок -
При запуску програми, якщо ми запустимо його, і ми ввести CS50 порід,
так само, як Данило говорив він зробив, і ви натиснете Enter,
він як і раніше говорить, що ми отримаємо D.
І питання в тому, чому це відбувається?
І виявляється, що обидва наших терміналів і GDB розібрати їх як два окремих аргументів.
Тому що, коли є простір, який має на увазі як
Перший аргумент закінчився, а на наступний аргумент ось-ось почнеться.
Спосіб поєднати ці дві, чи вибачте, в один аргумент,
є використання лапок.
Так що тепер, якщо покласти його в лапки і запустити його знову, ми отримаємо A.
Так просто, щоб резюмувати, без лапок, CS50 і гірських порід обробляються як два окремих аргументів.
З лапками, він обробляється як один аргумент в цілому.
>> Ми бачимо це з точки зупину.
До цих пір ми були працює наша програма, і вона працює вже
до тих пір поки або він сегментам несправності або помилки хіти
або поки він не завершиться, і все було в повному порядку.
Це не обов'язково найкорисніша річ, тому що іноді
у вас є помилки в вашій програмі, але це не викликає помилку сегментації.
Це не викликає вашу програму, щоб зупинити або що-небудь подібне.
Спосіб отримати GDB, щоб призупинити програму в конкретній точці
, Щоб встановити точки зупину.
Ви можете зробити це, встановивши точку зупину на ім'я функції
або ви можете встановити точки зупину на певний рядок коду.
Я хотів би встановити точки зупину на функцію імен, тому що - легко запам'ятати,
і якщо ви насправді піти і змінити свій вихідний код вгору небагато,
то ваша точка останову буде фактично залишатися на тому ж місці в коді.
Беручи до уваги, якщо ви використовуєте номера рядка і номера рядка зміниться
тому що ви додати або видалити частину коду, то ваші точки зупину все повністю облажався.
Один з найпоширеніших речей, які я зробити, це встановити точки зупину на основні функції.
Часто я буду завантажувати GDB, я типу В головній, ударив Enter, і що буде встановити точки зупину
на головною функцією якого просто говорить: "Пауза програми, як тільки ви починаєте бігати"
і, таким чином, коли я запускаю мою програму, скажімо, CS50 порід як два аргументи
і натиснути Enter, він потрапляє в основні функції і зупиняється прямо на самій першій лінії,
Право, перш ніж він оцінює STRCMP функції.
>> Так як я зупинився, тепер я можу почати відведенням навколо і побачивши, що відбувається
з усіма різних змінних, які передаються в моїй програмі.
Тут я можу роздрукувати ARGC і подивитися, що відбувається.
Дивіться, що агдс 3, тому що він отримав 3 різні значення в ньому.
Він отримав назву програми, він отримав перший аргумент, а другий аргумент.
Ми можемо надрукувати ті з дивлячись на ARGV [0], ARGV [1], і ARGV [2].
Так що тепер ви можете зрозуміти, чому цей виклик STRCMP збирається потерпіти невдачу,
тому що ви бачите, що він розділений CS50 і скелі на дві окремі аргументи.
На даний момент, як тільки ви потрапили останову, ви можете продовжити послідовне виконання програми
рядок за рядком, на відміну від запуску програми знову.
Так що, якщо ви не хочете, щоб запустити програму знову і просто продовжувати звідси,
Ви можете використовувати команду тривають і як і раніше буде виконувати програму до кінця.
Так само, як це зробив тут.
Однак, якщо я перезапустити програму, CS50 скелі, він потрапляє моєї точки останову знову,
і на цей раз, якщо я не хочу, щоб просто пройти весь шлях через іншу частину програми,
Я можу використовувати наступну команду, яку я також скорочення з п.
І це буде крок у рамках програми рядок за рядком.
Таким чином, ви можете спостерігати, як речі виконувати, як змінні зміни, як речі оновлюється.
І це дуже приємно.
Інші Відмінна річ, а не повторювати ту ж команду знову і знову, і знову,
якщо ви просто натисніть Enter - так що тут ви бачите, що я не набрав ні в чому -
якщо я просто натисніть Enter, він буде повторювати попередню команду,
або попередньої команди GDB, що я просто вставив
Я можу тримати удар, і саме буду тримати покрокового свій код рядок за рядком.
Я хотів би закликати вас, хлопці, щоб піти перевірити інші програми баггі, а також.
У нас немає часу, щоб пройти через всі з них сьогодні в розділі.
Вихідний код є, так що ви можете почасти бачити, що відбувається на
за кулісами, якщо Ви дійсно застрягли,
але, принаймні, тільки практика завантаженні GDB,
виконання програми поки не зламається на вас,
отримання зворотного трасування, з'ясувати, які функції обвал стався в,
якій лінії він був, виводячи деяких значень змінних,
тільки так ви відчуєте це, тому що дійсно допоможе вам в майбутньому.
На даний момент, ми збираємося вийти з GDB, якій ви використанням кинути або просто ц.
Якщо ваша програма знаходиться в середині працює досі, і вона не вийшла,
він завжди запитає вас: «Ви впевнені, що справді хочете вийти?"
Ви можете просто натиснути да.
>> Тепер ми будемо дивитися на наступна проблема у нас є, що кішка програми.
Якщо ви подивитеся на короткий перенаправлення і труби, ви побачите, що Томмі використовує цю програму
, Що в основному друкує всі вихідні файлу на екран.
Так що, якщо я біжу кішка, це насправді вбудованої програми в прилад,
і якщо у вас є Macs ви можете зробити це на вашому Mac теж, якщо ви відкриваєте термінал.
А ми - кішки, скажімо, cp.c, і натисніть Enter.
Те, що це зробили, якби ми прокручування вгору трохи і подивитися, де ми провели лінію,
або там, де ми запустили кішку команду, він буквально роздрукувати вміст cp.c на нашому екрані.
Ми можемо запустити його знову, і ви можете покласти в декількох файлах.
Таким чином, ви можете зробити кішці cp.c, і тоді ми можемо також об'єднувати cat.c файл,
яка є програма, яку ми збираємося писати,
і він буде друкувати як файли назад, щоб повернутися в наш екран.
Тому, якщо ми прокручування вгору небагато, ми бачимо, що коли ми запустили цей кіт cp.c, cat.c,
Спочатку він розпечатав ф файл, а потім під ним, він розпечатав cat.c файл прямо тут.
Ми збираємося використовувати це, щоб просто отримати наші ноги мокрі.
Пограйте з простої друку на термінал, подивимося, як це працює.
Якщо ви, хлопці відкривають з Gedit cat.c, натисніть Enter,
Ви можете побачити програми, які ми збираємося писати.
Ми включили це хороша плита котла, тому ми не доведеться витрачати час на введення все це.
Ми також перевіряємо кількість аргументів, переданих дюйма
Ми роздрукувати гарне сполучення використанні.
>> Це така штука, що, знову ж, як ми вже говорили,
це майже як м'язова пам'ять.
Тільки не забудьте зберегти робити те ж саме роду речі
і завжди роздруківку свого роду корисними повідомлення
так, що люди знають, як управляти вашої програми.
З кішкою, це досить просто, ми просто збираємося пройти через всі різні аргументи
, Які були передані нашої програми, і ми збираємося для друку
їх вміст, щоб на екрані по одному.
Для того, щоб друкувати файли з до екрану, ми збираємося зробити щось дуже схоже
до того, що ми зробили в кінці вікторини.
В кінці вікторини, які наймають програми, ми повинні були відкрити файл,
і тоді ми повинні були друкувати на ньому.
У цьому випадку, ми збираємося відкрити файл, і ми будемо читати з нього замість цього.
Тоді ми йдемо до друку, а не в файл, ми збираємося друкувати на екрані.
Таким чином, друк на екрані ви все робили з Printf.
Так що це не надто божевільним.
Але читання файлів дивно.
Ми будемо пройти через це трохи за один раз.
Якщо ви, хлопці повернутися до цієї останньої проблеми на вашій вікторини, завдання 33,
перша лінія, що ми збираємося тут робити, відкриття файлу, дуже схожі на те, що ми там робили.
Таким чином, Стелла, що робить цю лінію виглядати, коли ми відкриваємо файл?
[Stella] Столиця FILE *, файл - >> Добре. >> - Рівно Еореп. >> Да.
Які в цьому випадку? Це в коментарі.
>> Це в коментарях? ARGV [я] і г?
>> Саме так. Прямо на. Так Stella абсолютно праві.
Це те, що лінія виглядає.
Ми збираємося, щоб отримати змінний потік файлу, зберегти його у файлі *, так що всі кришки,
FILE *, і ім'я цієї змінної буде файл.
Ми могли б назвати це все, що ми хотіли. Ми могли б назвати це first_file, або file_i, що б ми хотіли.
І тоді ім'я файлу був прийнятий в командному рядку цієї програми.
Таким чином, він зберігається в ARGV [я], і потім ми збираємося відкрити цей файл в режимі читання.
Тепер, коли ми відкрили файл, що те, що ми завжди повинні пам'ятати, щоб зробити
всякий раз, коли ми відкрили файл? Закрийте її.
Таким чином, Міссі, як ми закрити файл?
[Missy] Fclose (файл) >> Fclose (файл). Саме так.
Великий. Добре. Якщо ми подивимося на це, щоб зробити коментар прямо тут,
він говорить, "Відкриті ARGV [я] і роздрукувати його вміст на стандартний вивід".
>> Стандартний вихід це дивне ім'я. Stdout це просто спосіб сказати нашим
Ми хочемо, щоб роздрукувати його на термінал, ми хочемо, щоб роздрукувати його в стандартний вихідний потік.
Ми можемо насправді позбутися від цього коментаря прямо тут.
Я збираюся скопіювати його і вставити його, так як це те, що ми і зробили.
На даний момент, тепер у нас є, щоб прочитати файл по шматочках.
Ми обговорили кілька способів читання файлів.
Які ваші улюблені досі?
Які способи ви бачили або ви пам'ятаєте, для читання файлів?
[Даниїл] FREAD? >> FREAD? Так FREAD один. Джиммі, ви знаєте, будь-які інші?
[Джиммі] Немає >> Добре. Ні. Шарлотта? Олександр? Будь-які інші? Добре.
Таким чином, інші є fgetc, це той, який ми будемо використовувати багато.
Там також fscanf, ви, хлопці, бачити зразок тут?
Всі вони починаються з F. Все, що робити з файлом.
Там в FREAD, fgetc, fscanf. Ці всі функції читання.
Для розміщення у нас є FWRITE, у нас є fputc замість fgetc.
Ми також Fprintf, як ми бачили на вікторину.
Так як це є проблемою, яка включає в себе читання з файлу,
Ми збираємося використовувати одну з цих трьох функцій.
Ми не збираємося використовувати ці функції тут.
Всі ці функції в стандартній бібліотеці введення / виводу.
Так що, якщо ви подивитеся на верхню частину цієї програми,
Ви можете бачити, що ми вже включений файл заголовка для стандартної бібліотеки вводу / виводу.
Якщо ми хочемо, щоб з'ясувати, який ми хочемо використовувати,
ми завжди можемо відкривати людині сторінок.
Таким чином, ми може ввести людину STDIO
і прочитати все про STDIO вхідний і вихідний функції в C.
І ми вже бачимо, ой, дивися. Це згадка fgetc, це згадка fputc.
Таким чином, ви можете розгорнути трохи і подивимося на, скажімо, fgetc
і подивіться на його сторінці.
Ви можете бачити, що він йде разом з цілою купою інших функцій:
fgetc, ЕдеЬз, ЕОКП, GetChar отримує, UNGETC, і його введення символів і рядків.
Так що це, як ми читаємо в символи і рядки з файлів зі стандартного вводу,
яка є по суті від користувача.
І це, як ми це робимо в реальному C.
Так що це не використання GetString і GetChar функцій
, Які ми використовували з CS50 бібліотеки.
Ми збираємося зробити цю проблему декількома способами
так що ви можете побачити два різні способи зробити це.
І FREAD функції, що Данило згадується і fgetc хороші способи зробити це.
Я думаю, що fgetc трохи легше, тому що це тільки має, як бачите,
один аргумент, FILE *, що ми намагаємося прочитати символ з,
і її значення, що повертається Int.
І це трохи дивно, чи не так?
>> Тому що ми отримуємо характер, так чому б не це повернення символів?
Ви, хлопці, є які-небудь ідеї про те, чому це не може повернути символ?
[Missy відповіді, нерозбірливо] >> Да. Так Missy абсолютно праві.
Якщо це ASCII, то це число може бути зіставлений з фактичними символ.
Може бути ASCII символів, і це правильно.
Це саме те, що відбувається.
Ми використовуємо Int просто тому, що він має більше бітів.
Це більше, ніж символ, наш символ має тільки 8 біт, що 1 байт на наш 32-бітних машин.
І Int має варто все 4 байти "простір.
І виявляється, що шлях fgetc працює,
якщо прокрутити вниз в нашу резюме в цій людині сторінці небагато,
Прокрутіть вниз до упору. Виявляється, що вони використовують це спеціальне значення, зване EOF.
Це спеціальна постійна, значення, що повертається функцією fgetc
всякий раз, коли ви потрапили в кінець файлу або якщо ви отримуєте повідомлення про помилку.
І виявляється, що для виконання цих порівнянь з EOF належним чином,
Ви хочете, що додатковий обсяг інформації, яку ви маєте на Int
в порівнянні з використанням символів змінної.
Навіть якщо fgetc ефективно отримувати персонаж з файлу,
Ви хочете, щоб пам'ятати, що вона повертається щось таке, що типу Int до вас.
Тим не менш, він досить простий у використанні.
Це дасть нам характер, тому все, що ми повинні зробити, це продовжувати задавати файл,
"Дайте мені наступний символ, дай мені наступний символ, дай мені наступну характер»,
поки ми не отримаємо до кінця файлу.
І це буде тягнути в один символ за один раз з нашого файлу,
і тоді ми можемо робити все, що ми хотіли з нею.
Ми можемо зберегти його, ми можемо додати його в рядок, ми можемо роздрукувати його.
Виконайте одну з цього.
>> Збільшення назад і повернутися до наших cat.c програми,
якщо ми збираємося використовувати fgetc,
як ми могли б підійти до цієї наступного рядка коду?
Ми збираємося використовувати - FREAD буде робити щось трохи відрізняється.
І на цей раз, ми просто збираємося використовувати fgetc, щоб отримати один символ за один раз.
Щоб обробити весь файл, що ми могли б робити?
Скільки персонажів є у файлі?
Є багато. Таким чином, ви, ймовірно, хочете, щоб отримати один
, А потім отримати іншу і отримати іншу і отримати іншу.
Який алгоритм ви думаєте, ми могли б використати тут?
Який тип - [Олександр] для циклу? >> Саме так.
Деякі типи циклу.
Цикл насправді великий, і в цьому випадку.
І, як ви кажете, це звучить, як ви хочете петлю на весь файл,
отримати символ за один раз.
Будь-які пропозиції про те, як це може виглядати?
[Олександра, нерозбірливо]
>> Добре, тільки скажи мені, англійською мовою, що ви намагаєтеся зробити? [Олександра, нерозбірливо]
Таким чином, в даному випадку, схоже, ми просто намагаємося петлю на весь файл.
[Олександр] Так я <розмір Int? >> Розмір -?
Я припускаю, що розмір файлу, вірно? Розмір - МИ просто написати це так.
Розмір файлу в даний час, я + +.
Ось і виходить, що те, як ви це за допомогою fgetc, і це нове,
в тому, що не існує простий спосіб, щоб просто отримати розмір файлу
з цим "SizeOf" типу побудуємо, що ви бачили раніше.
Коли ми використовуємо цю функцію fgetc, ми представляємо якийсь
новий, фанк синтаксис для цього циклу, де замість використання тільки основний лічильник
піти по одному символу, ми збираємося вивести один символ за один раз,
по одному символу за один раз, і то, як ми знаємо, що ми в кінці
Не тоді, коли ми вважали певну кількість символів,
Але коли ми характері витягнути те, що спеціальна символ кінця файлу.
Таким чином, ми можемо зробити це, - я називаю це гол, і ми збираємося його ініціалізації
наш перший виклик, щоб отримати перший символ з файлу.
Таким чином, ця частина прямо тут, це буде отримати символ з файлу
і зберігати його в змінної гл.
Ми збираємося продовжувати робити це, поки ми дійдемо до кінця файлу,
що ми і робимо, тестуючи для персонажа не рівні, що спеціальний символ EOF.
І тоді замість того, щоб робити CH + +, яка б просто збільшити значення,
тому, якщо ми читаємо з файлу, капітал, скажімо,
CH + + дасть нам б, і тоді ми отримаємо С, а потім р.
Це явно не те, що ми хочемо. Що ми хочемо тут
У цьому останньому біт ми хочемо отримати наступний символ з файлу.
>> Так як ми можемо отримати наступний символ з файлу?
Як ми можемо отримати перший символ з файлу?
[Студент] fgetfile? >> Fgetc, або, вибачте, ви мали цілковиту рацію.
Я неправильно його прямо там. Так що так.
Тут замість того, щоб робити CH + +,
Ми просто будемо називати fgetc (файл) знову
і зберегти результат в наших же змінної гл.
[Студент питання, нерозбірливо]
>> Це де ці хлопці FILE * є спеціальними.
Те, як вони працюють, вони - при першому відкритті - коли ви спочатку переконайтеся, що Еореп виклику,
FILE * ефективно служить в якості покажчика на початок файлу.
І тоді кожен раз, коли ви дзвоните fgetc, вона рухається по одному символу за допомогою файлу.
Тому, коли ви називаєте це, ви збільшуючи покажчик на один символ.
І коли ви fgetc знову, ви рухаєтеся це інший персонаж
і інший характер і інший характер і інший персонаж.
[Студент питання, нерозбірливо] >> А that's - так.
Це свого роду ця чарівна під капотом.
Ви просто продовжуйте збільшуючи до кінця.
На даний момент, ви зможете насправді працювати з характером.
Отже, як ми могли б роздрукувати це на екрані, зараз?
Ми можемо використовувати ті ж Printf річ, яку ми використовували раніше.
Те, що ми вже використали весь семестр.
Ми можемо назвати Printf,
і ми можемо перейти в характері просто так.
Ще один спосіб зробити це швидше, ніж при використанні Printf і мають для цього формату рядка,
ми також можемо використовувати одну з інших функцій.
Ми можемо використовувати fputc, яка виводить символ на екран,
винятком випадків, коли ми дивимося на fputc - дозвольте мені масштаб небагато.
Ми бачимо, що приємно, він приймає в характері, що ми читаємо, використовуючи fgetc,
але тоді ми повинні дати йому потік в друк.
Ми також можемо використовувати ріЬспаг функцію, яка наноситься безпосередньо на стандартний вивід.
Таким чином, існує ціла купа різних варіантів, які ми можемо використовувати для друку.
Вони всі в стандартній бібліотеці введення / виводу.
Всякий раз, коли ви хочете надрукувати - так Printf, за замовчуванням, будуть друкуватися на спеціальній стандартні з потоку,
яких є те, що стандартний вивід.
Таким чином, ми можемо просто посилатися на нього як виду цієї магічне значення, стандартний висновок тут.
Ой. Поставити крапку з комою зовні.
>> Це багато нового, наляканий інформацією тут.
Багато це дуже ідіоматичні, в тому сенсі, що це код
що написано таким чином тільки тому, що це чисто читати, легко читається.
Є багато різних способів зробити це, багато різних функцій, які ви можете використовувати,
але ми, як правило, просто виконайте ці ж моделі знову і знову.
Так що не дивуйтеся, якщо побачите такий код придумати знову і знову.
Добре. На даний момент, ми повинні розірвати протягом дня.
Спасибі, що прийшли. Дякую за перегляд, якщо ви знаходитеся в мережі. І ми побачимося наступного тижня.
[CS50.TV]