[Powered by Google Translate] [РАЗДЕЛ 5: по-малко удобни] [Нейт Hardison, Харвардски университет] [Това е CS50. [CS50.TV] Така че добре дошли обратно, момчета. Добре дошли в раздел 5. В този момент, след като викторина 0 и след като види как сте направили, се надяваме, че се чувствам наистина добре, защото бях много впечатлен от резултатите в този раздел. За нашите онлайн зрителите, имахме няколко въпроса за последните два проблема по проблема, или на теста, а. Така че ние ще отидем над тези, които наистина бързо, така че всеки вижда какво се е случило и как да мине през реалното решение, а не само за гледане самото решение. Ние ще отидем много бързо през последните няколко проблеми, 32 и 33. Просто отново, така че онлайн зрителите могат да видят това. Ако се обърнете към вашия проблем 32, който е на страница 13, 13 от 16 проблеми 32 е всичко за суапове. Това беше всичко, за смяна на две цели числа. Това е проблем, който си отиде няколко пъти в лекция. И тук, това, което искаха да направиш е бърз следа памет. За попълване на стойностите на променливите, тъй като те са в стека кода минава през този суап функция. По-конкретно, това, което ние търсим най - Тръгвам този IPAD - по-специално това, което търсим, е тази линия с номер 6 тук. И тя наброява 6 само за непосредствена близост с предишния проблем. Това, което искаме да направим, е да покажете или етикет на състоянието на паметта тъй като тя е по времето, когато тази линия номер 6, , което е ефективно връщане от нашия суап функция тук. Ако превъртете надолу тук видяхме, че адресите на всичко в паметта е предоставена за нас. Това е много ключов, ние ще се върнем към него само за миг. И тогава тук в долната част, имахме малко диаграма памет, че отива да се позове на. Всъщност съм направил това на моя IPAD. Така че аз отивам да се редуват назад и напред между IPAD и този код само за справка. Нека започнем. Първо, нека се съсредоточим върху първите няколко линии на главната точно тук. За да започнете, отиваме да се инициализира х 1 и у две. Така че ние имаме два целочислени променливи, те двамата ще бъдат поставени в стека. Отиваме да се сложи 1 и 2 в тях. Така че, ако преобърне на моя IPAD, да се надяваме, да видим - Apple TV огледало, и там да отидем. Добре. Така че, ако преобърне на моя IPAD Искам да се инициализира х 1 и у две. Ние правим, че просто от написването на едно в полето отбелязани х и 2 в полето маркирани г. Доста проста. Така че сега, нека се върнем към лаптопа, да видим какво се случва по-нататък. Така че това следващия ред е мястото, където нещата стават трудни. Преминаваме адрес на х и адрес на у параметрите А и Б за суап функция. Адресът на х и адрес на г са неща, които не може да се изчисли без да се позовава на тези куршум точки чак тук. И за щастие, първите две точки ни каже какво точно отговорите са. Адрес на х памет е 10 и адреса на г. в паметта е 14. Така че това са ценностите, които се предават като А и Б отгоре в нашата суап функция. Така че, отново превключване в нашата диаграма, мога да пиша на 10 в и 14 в б. Сега, тази точка е мястото, където да продължим с суапа. Така обръщане на лаптопа отново ние виждаме, че начина, по който суап работи е, че първият сочен и магазин резултата в ПТУ. Така сочен оператор казва, "Хей. Лечение на съдържанието на променлива на адрес. Отиди на каквото и да се съхранява на този адрес и да го заредите. Какво ви зареди на променливата ще се съхраняват в нашия TMP променлива. Показваш на IPAD. Ако тръгнем на адрес 10, знаем, че адрес 10 е varible х защото ни беше казано от нашия точка, че на адреса на х памет е 10. Така че можем да отидем там, да получите стойността на това, което е 1, както виждаме на нашия IPAD, и да заредите, че в малки. Отново, това не е окончателното съдържание. Отиваме да преминете през и ние ще стигнем до крайната ни състоянието на програмата в края. Но точно сега, ние имаме стойност 1 съхраняват в малки. И тук има един бърз въпрос. [Александър] е сочен оператор - това е само право на звездата в предната част на променливата? >> Да. Така сочен оператор, като се обърнете назад към нашия лаптоп отново, е тази звезда точно пред. В този смисъл, това е - да го съпоставят с оператора за умножение , който изисква две неща, сочен оператор е унарен оператор. Само една стойност, за разлика от двоичен оператор, , където се прилагат за две различни стойности. Така че това е това, което се случва в този ред. Натоварени стойност 1 и да го съхраняват временно целочислена променлива. Следващият ред, ние съхраняваме съдържанието на б или по-скоро, ние съхраняваме съдържанието, б сочи в мястото, където е насочена към. Ако анализираме това от дясно на ляво, ние ще сочен б, ние ще Адрес 14, ние ще грабне цяло число, което е там, и тогава ние ще отидем на адреса, 10, и ние ще се хвърлят в резултат на на сочен нашата б в това пространство. Показваш IPAD, където можем да направим това малко по-конкретни, може да помогне, ако пиша номера на всички адреси тук. Така че ние знаем, че в г., ние сме на адрес 14, х е на адрес 10. Когато почнем да б, сочен б, ние отиваме да вземете стойността 2. Ние ще вземете тази стойност, тъй като това е стойността, която живее на адрес 14. И отиваме да го пуснат в променлива, която живее на адрес 10, което е точно там, съответстваща на нашите променливи х. Така че ние можем да направим малко от презаписване тук , където ще се отървем на нашия 1 и вместо да пишем 2. Така че всичко е много добре в света, въпреки че сега сме презаписани х. Ние сме съхранили старата стойност на х в нашия TMP променлива. Така че можем да завърши суап със следващия ред. Показваш обратно на нашия лаптоп. Сега всичко, което остава е да се вземе съдържанието на временно целочислена променлива и да ги съхранява в променлива, която живее на адреса, на който б държи. Така че ние отиваме за ефективно и сочен б, за да получите достъп до променливата , който е на адреса, че б държи в него, и отиваме да се неща стойността, която TMP държи в него. Показваш на IPAD още веднъж. Тук мога да изтриете тази стойност, 2, и вместо това ще копираме 1 право в него. След това на следващия ред, който изпълнява, разбира се - ако се обърнете назад към лаптопа - това е точка 6, което е точката, в която искахме да имаме нашата диаграма напълно попълнени. Така обръщане на IPAD още веднъж, само за да можете да видите диаграма, можете да видите, че ние имаме 10 в 14 б, 1 в ПТУ, 2 х и 1 г.. Има ли някакви въпроси относно това? Това прави ли повече смисъл, след като мина през него? Направете по-малко смисъл? Надявам се не. Добре. Указатели са много труден въпрос. Едно от момчетата, с които работим, има много чести поговорка: "За да се разбере указатели, трябва да първо да разберем указатели." Което мисля, че е много вярно. Тя не отнеме известно време да свикне с него. Тегленето на жребий снимки, теглене на жребий памет схеми като тази са много полезни, и след като преминете през пример след пример след пример, , че ще започнат да правят малко повече разум и малко повече разум и малко повече смисъл. Накрая, един ден, ще имате всичко напълно усвоили. Всички въпроси, преди да преминем към следващия проблем? Добре. Така че обърнете гръб на лаптопа. Следващият проблем, който имаме, е проблем номер 33 на файл I / O. Увеличаване или намаляване на това малко. Задача 33 - Да? Даниел аз просто трябваше един бърз въпрос. Тази звезда, или звездичка, тя се нарича dereferencing когато използвате звездичка преди. Как се нарича, когато използвате амперсанд преди? >> Амперсанд преди е адресът на оператора. Така че нека да превъртите обратно. Опа. Аз съм в режим на увеличение, така че не мога наистина превъртане. Ако се вгледаме в този код наистина бързо тук, отново същото нещо се случва. Ако се вгледаме в този код точно тук, на тази линия, където можем да призоваваме за суап, амперсанд е просто казва "да получите адреса, на който живее променливата х." Компилатор компилира кода си, има действително физически марка място в паметта за всички променливи, които да живеят. И така, какво компилаторът може след това, след като всичко е съставен, го знае, "О, аз слагам х адрес 10. Сложих г. на адрес 14. След това тя може да запълни тези ценности за вас. Така че може да - може да мине и преминават г., както и. Тези момчета са с адрес, но те, когато ги предадат в суап функция, този тип информация, това INT * точно тук, казва на компилатора, "Добре, ние отиваме да бъде тълкуването на този адрес като адрес на целочислена променлива. Като адрес на вътр, който е различен от адреса на променливата характер защото вътр заема, на 32-битова машина, заема 4 байта пространство, като има предвид, че символ заема само 1 байт на пространството. Така че е важно да се знае и това, което е - какво живее, какъв тип на стойност живее на адреса, на който се премина инча Или адрес, че си имате работа с. По този начин, вие знаете колко байта на информация действително да се зареди на вашия RAM. И тогава, да, този сочен оператор, като теб искаха, отива и достъп до информация по конкретен адрес. Така се казва, с тази променлива, лечение на съдържанието на като адрес, отидете на този адрес, и издърпайте, заредете в процесора, натоварване в регистър действителните стойности или съдържанието, които живеят на този адрес. Има ли още въпроси? Това са добри въпроси. Това е много нова терминология. То също е вид фънки, тъй като и и * на различни места. Добре. Така че обратно към проблем 33, подайте I / O. Това е един от тези проблеми, които мисля, че няколко неща се случиха. Едно, че е сравнително нова тема. Той беше представен съвсем скоро преди теста, и след това мисля, че беше нещо като един от проблемите с тези думи по математика , където те дават много информация, но всъщност не в крайна сметка се налага да използвате един тон от него. В първата част на този проблем се описва какво CSV файл. Сега, CSV файл, според описанието, е, разделени със запетая стойности. Причината това са всички интересни и причината, поради която някога ги използват, , защото, колко от вас са използвали някога подобни неща Excel? Фигура повечето от вас, вероятно, или ще се използва в някакъв момент в живота си. Ще използвате нещо като Excel. За да получите данните от таблица в Excel или да направите каквато и да е обработка с него, ако искаш да се напише програма на C или Python програма, Java програма, да се справят с данни, които сте там, един от най-често срещаните начини, за да я получите, е в CSV файл. И можете да отворите Excel и когато отидете на "Save As" диалог, можете да получите действително CSV файл. Добре е да се знае как да се справят с тези неща. Начина, по който тя работи, е, че това е подобно на - Искам да кажа, това е по същество имитира електронна таблица, където, както виждаме тук, в най-лявата част, имаме всички фамилни имена. Така че ние имаме Малан, тогава Hardison, и след това Боудън, MacWilliam, и след това Чан. Всички фамилни имена. И тогава запетая разделя последните имена от първите имена. Дейвид, Нейт, Роб, Томи и Zamyla. Винаги съм се смесват Роби и Том. И най-накрая, третата колона е имейл адресите. След като разбират, че останалата част от програмата е сравнително лесно за изпълнение. Това, което ние сме направили, за да се имитира същата тази структура в нашата програма C е, че ние сме използвали структура. Ще започнете да играете с тези малко повече, както добре. Ние ги видях за първи малко проблем комплект 3, когато ние се занимавахме с речниците. Но този персонал структура съхранява фамилно име, собствено име и имейл. Точно като CSV файла съхранение. Така че това е просто конвертиране от един формат в друг. Трябва да конвертирате, в този случай, структурата на персонала в една линия, , разделени със запетая линия, просто ей така. Това прави ли смисъл? Вие, момчета, всички викторина, така че представете си, че са най-малко трябваше известно време да мисля за това. В наем функция, проблемът ни кара да се вземат в we'll увеличение на това малко - в структурата на персонала, структурата на персонала, с името и, и прилага съдържанието му в нашия файл staff.csv. Оказва се, че това е сравнително лесно за използване. Ще играят наоколо с тези функции малко повече днес. Но в този случай, fprintf функция е наистина ключов. Така че с fprintf, ние може да печата, точно като вас са използвали ФОРМАТ целия този план. Можете да ФОРМАТ линия във файл. Така че, вместо просто обичайната ФОРМАТ повикване, когато ти я дам низ формат и тогава ще замени всички променливи със следните аргументи, с fprintf си първият аргумент е, вместо файла, който искате да напишете. Ако бяхме да гледам на това в уреда, например, човек fprintf можем да видим разликата между ФОРМАТ и fprintf. Ще я увеличите тук малко. ФОРМАТ, ние го дам формат низ, а след това следващите аргументи са всички променливи за замяна или за замяна в нашия формат низ. Като има предвид, че с fprintf, първият аргумент е наистина този файл * нарича поток. Преместване тук, за да ни под наем, Вече си имаме нашия поток файл * отвори за нас. Това е, което прави тази първа линия; го отваря файла staff.csv, тя се отваря в режим за добавяне и всичко, което е останало от нас да направим, е напиши структурата на персонала към файла. И нека да видим, не искам да използвате IPAD? Ще използвам IPAD. Имаме невалидни - Нека сложим на масата, така че мога да напиша малко по-добре - анулира под наем и го отвежда в един аргумент, на персонала, структура, наречена S. Имаме скоби, ние имаме файла * файл, наречен, ние имаме fopen линия, дадена ни, и аз просто ще го напиша като точки, тъй като това е вече в Родословие. И след това на следващия ни ред, ние отиваме да осъществите повикване до fprintf и отиваме да премине в преписката, че искаме да печатате, и след това формат низ, който Ще ви оставя вие да ми кажете това, което изглежда. Какво ще кажете вие, Стела? Знаете ли, това, което прилича на първата част на формат низ? Стела] Аз не съм сигурен. >> Чувствайте се свободни да поиска Джими. Знаеш ли, Джими? [Джими би той просто да бъде последно? Не знам. Аз не съм съвсем сигурен. >> Добре. Какво ще кажете, че някой се това е правилно на изпита? Добре. Оказва се, че тук всичко, което трябва да направим, е да искаме всяка част от структурата на нашия екип да бъдат отпечатани като низ в нашия файл. Ние просто използвайте характер замяна на низ три пъти, защото имаме фамилно име последвано от запетая, а след това първо име, последвано от запетая, и накрая имейл адрес, който е последван - което не е монтиране на екрана си, но е последван от символ за нов ред. Така че аз ще го напиша малко по-надолу има. И тогава след нашия формат низ, ние просто трябва да смени, които достъп се използва отбелязването точка че видяхме в проблем комплект 3. Ние можем да използваме s.last, s.first и s.email да замени в тези три стойности в нашата формат низ. Е, как е, че отиде? Направи ли смисъл? Да? Не? Евентуално? Добре. Крайният нещо, което правим след като сме се отпечатват и след като сме отворили нашия файл: всеки път, когато сте отворили файл, ние винаги трябва да помним, за да го затворите. Защото в противен случай ние ще свършим изтичане на паметта, използване на файлови дескриптори. Така че, за да го затворите, чиято функция ще се използва? Даниел? Даниел] неуспешно? >> Неуспешно, точно така. Така последната част от този проблем е правилно затворете файла, с помощта на функцията неуспешно, което просто изглежда по този начин. Не е твърде луд. Cool. Така че това е проблем на 33 на теста. Ще има определено повече файла I / O идва. Ние ще направим малко повече в лекция днес, или в раздел днес, защото това е какво ще се формират по-голямата част от този предстоящ pset. Нека преминем от теста в този момент. Да? [Шарлот] Защо неуспешно (файл), вместо неуспешно (staff.csv)? >> Ah. Защото се оказва, че - така че въпросът, който е страхотно, Ето защо, когато пишем неуспешно, ще писмено неуспешно (файл) звезда променлива за разлика от името на файла, staff.csv? Вярно ли е? Да. Така че нека да разгледаме. Ако се върнете обратно към лаптопа си, и нека погледнем неуспешно функция. Така че неуспешно функция затваря поток и да го взема в показалеца на поток, който искате да затворите, за разлика от действителното име на файла, който искате да затворите. И това е така, защото зад кулисите, когато се обаждате fopen , когато отворите файл, вие всъщност разпределяне на памет за съхранение на информация за файла. Така имате файлов указател, който има информация за файла, като тя е отворена, неговия размер, къде се намирате в момента файла, така че можете да направите за четене и запис на разговори, че специално място в рамките на файла. В крайна сметка затваряне на показалеца вместо затваряне на името на файла. Да? [Даниел] Така че, за да се използва под наем, ще ви кажа - как получите входния потребител? Ли fprintf действа като GetString в смисъл, че тя просто ще чака за въвеждане на потребителя и да ви помоля да напишете това - или да изчакате, за да въведете тези три неща в? Или ще трябва да използвате нещо, което да се приложи под наем? >> Да. Така че ние не сме - въпросът е, как да получите входния на потребителя с цел да се приложи под наем? И това, което имаме тук, е на повикващия за наем, приет през този персонал структура на данните, съхранявани в структурата вече. Така че fprintf е в състояние само да напиша, че данните директно файла. Няма нужда да чакате за приноса на потребителите. Потребителят вече входа от правилно поставяйки я в този персонал структура. И всичко, разбира се, ще се счупи, ако някой от тези указатели са нула, така че ние превъртете обратно тук, и ние с нетърпение в нашата структура. Имаме низ последно низ първата, низ имейл. Ние вече знаем, че всички тези, които наистина, под капака, Чар * променливите. Това може или не може да се посочи присвоява. Те могат да бъдат насочени към паметта на куп, може би паметта на стека. Ние наистина не знам, но ако някой от тези насоки са нула, или невалидни, , че това със сигурност ще се срине под наем на нашата функция. Това беше нещо, което е вид извън обхвата на изпита. Ние не се тревожим за това. Велики. Добре. Така от теста. Нека да затворите този човек, и отиваме да разгледаме pset 4. Така че, ако вие погледнете в спец. pset, след като можете да го ползвате, cs50.net/quizzes ние ще да мине през някои от днешните проблеми раздел. Аз превъртите надолу - раздел от въпроси започва на трета страница на pset спец.. И първата част ще ви помоли да отидете и да гледате кратко пренасочване на средства и тръби. Кой е вид хладно кратък, показва някои нови, готини трикове на командния ред, които можете да използвате. И тогава ние имаме няколко въпроса към теб, както добре. Този първи въпрос за потоци, към която ФОРМАТ пише по подразбиране, ние вид засегна само малко преди малко. Това fprintf, че ние тъкмо обсъждахме се в потока файл * за аргумент. неуспешно се в потока файл *, както и, и връщане на стойността на fopen ви дава поток файл *, както добре. Причината, поради която не сме виждали онези преди, когато сме разглеждат ФОРМАТ е така, защото ФОРМАТ има по подразбиране поток. И по подразбиране поток, към който може да пише ще разберете в краткосрочен. Така категорично да го погледнете. В раздел днес, отиваме да поговорим малко за GDB, тъй като по-запознати сте с него, повече практика с него, в състояние по-добре ще бъде да преследва грешки в собствения си код. Това ускорява процеса на отстраняване на грешки значително. Така че с помощта ФОРМАТ, всеки път, когато направите това, което трябва да компилирате кода си, трябва да го стартирате отново, понякога трябва да се движат около ФОРМАТ повикване, коментар код, то просто отнема известно време. Нашата цел е да се опита да ви убеди, че с GDB, можете същество ФОРМАТ нещо във всяка точка в кода си и никога не трябва да го компилирате. Вие никога не трябва да се започне и да познае къде да ФОРМАТ следващия. Първото нещо, което трябва да направите, е да копирате този ред и да получите код за раздел на уеб. Съм копиране В този ред на кода, който казва: "Wget http://cdn.cs50.net". Отивам да го копирате. Аз ще отида да ми уред, отдалечаване, така че можете да видите това, което правя, поставяне там, и щом натисна бутона Enter, това Wget команда буквално е уеб получите. Това ще събарят този файл на Интернет, и това ще да го запишете на текущата директория. Сега, ако аз добавя моя текущата директория, можете да видите, че аз имам тази section5.zip файл точно там. Начин да се справят с този човек, е да го разархивирате, което можете да направите в командния ред, просто така. Section5.zip. Това ще го разархивирайте, създайте папка за мен, надуват цялото съдържание, сложете ги там. Така че сега мога да отида в моя точка 5 директория, като използвате CD команда. Изчистете екрана с помощта на ясно. Така изчистване на екрана. Сега имам хубав чист терминал, за да се справят с. Сега, ако се изброят всички файлове, които виждам в тази директория, виждаш ли, че имам четири файлове: buggy1, buggy2, buggy3 и buggy4. Аз също имам съответните им файлове в. Ние не отиваме да разгледаме файлове в предприятието. Вместо това, ние отиваме да ги използва, когато се отворим GDB. Сме ги държат около, така че имаме достъп до действителния изходен код, когато ние използваме GDB, но целта на тази част на секцията е да калайджия наоколо с GDB и да видим как можем да го използваме, за да разбера какво не е наред с всяка от тези четири бъги програми. Така че ние просто ще из стаята много бързо, и аз ще помоля някой, който да се изпълнява една от бъгави програми, и тогава ние ще отидем като група през GDB, и ще видим какво можем да направим, за да се определи тези програми, или поне да се определи какво точно не е наред във всяка от тях. Нека започнем тук с Даниел. Ще ви свършат buggy1? Нека видим какво ще стане. Даниел казва, че има заявление вина. >> Да. Точно така. Така че, ако аз тичам buggy1, получавам сегмента вина. В този момент, мога да отида и отвори buggy1.c, се опитам да разбера какво не е наред, но една от най-неприятните неща за този сегмент грешка вина е, че тя не ви кажа по линия на програмата неща всъщност се обърка и се счупи. Можете вид трябва да погледнете кода и да разбера използва предполагам и проверете или ФОРМАТ за да видим какво точно не е наред. Един от най-готините неща за GDB е, че тя е много, много лесно да разбера линията при които програмата катастрофи. Това е напълно си заслужава да го използвате, дори и ако само за това. Така че, за да се зареди GDB, въведете GDB, и след това го даде пътя към изпълнимия файл, че искам да изпълните. Тук съм пишете GDB ./buggy1. Хит Enter. Дава ми всичко това информация за авторските права, и тук ще видите тази линия, която казва: "Четене на символи от / дом / jharvard/section5/buggy1 ". И ако всичко върви добре, ще видите, че отпечатате съобщение, което прилича на това. Ще прочетете символи, тя ще каже: "Аз чета символите от изпълнимия файл," и след това ще има тази "направи" съобщение тук. Ако видите някой друг вариант на този или виждате, че не можах да намеря символите или нещо подобно, какво означава това е, че просто не са съставили изпълним правилно. Когато се съставят програми за използване с GDB, ние трябва да използваме този специален грама флаг, и че е направено по подразбиране, ако вие компилирате вашите програми, просто като напишете направи или да направите бъги или да възстанови всеки един от тези. Но ако сте съставянето ръчно с звъня, тогава ще трябва да отидат и да включва, че грам флаг. В този момент, сега, че ние имаме GDB ред, Това е доста проста, за да стартирате програмата. Ние можем или да въведете план, или можем просто Type R. Повечето команди GDB може да бъде съкратен. Обикновено само една или няколко букви, което е доста хубаво. Така че Саад, ако Type R и натиснете Enter, какво се случва? Саад] Имам SIGSEGV, сегментация вина, и след това всичко това бръщолевене. >> Да. Както виждаме на екрана, точно сега, и като Саад каза, , когато въвеждате план или R и натиснете Enter, ние все още се същата грешка сегмента. Така че използването GDB не решава нашия проблем. Но това ни дава някаква бръщолевене, и се оказва, че това бръщолевене всъщност ни казва къде това се случва. Да прави разбор на това малко, това първо малко е функция, в която всичко е наред. Е това __ strcmp_sse4_2 и ни казва, че това се случва в този файл наречен sysdeps/i386, всичко това, отново, вид на каша, но линията 254. Това е малко трудно да се направи разбор. Обикновено, когато видя подобни неща, което означава, че Seg Faulting в един от системните библиотеки. Значи нещо да направя с strcmp. Вие, момчета, съм виждал strcmp преди. Не е твърде луд, но това означава, че strcmp е счупен или че има проблем с strcmp? Какво мислиш, Александър? [Александър], че е 254 ред? И - не двоичен, но това не е своите тавани, и тогава там е друг език за всяка функция. Е, че 254 в тази функция, или -? >> Това е линия 254. Изглежда, че в този файл, така че е монтаж код вероятно. Но, предполагам, че още по-наложително е, защото сме придобили сегмента вина, и тя изглежда като тя идва от strcmp функция, означава това, тогава, че strcmp е счупен? Тя не трябва, да се надяваме. Така че просто защото си имат сегментация вина в едно функциите на системата, обикновено това означава, че просто не сте го нарече правилно. Най-бързият нещо, което трябва да направя, за да разбера какво всъщност се случва когато видите нещо лудо като това, всеки път, когато видите сегмента вина, особено ако имате програма, която използва повече от основната, е да използвате обратно проследяване. Съкращавам обратно проследяване от писмено БТ, за разлика от цялата дума, обратно проследяване. Но Шарлот, какво се случва, когато въвеждате БТ и натиснете Enter? Шарлот] ми показва две линии, линия 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. Така че може би нещо подобно? >> Да. Така че този въпрос се правим сравнението правилно? Стела? Някакви идеи? Стела] Аз не съм сигурен. >> Не съм сигурен. Даниел? Мисли? Добре. Оказва се, че това, което се случва тук, е, когато ние се завтече програма и ние имаме сегмента вина, когато сте стартирали програмата за първи път, Даниел, ти я дам никакви аргументи от командния ред? Даниел] бр. >> В този случай, каква е стойността на argv [1]? >> Има никаква стойност. >> Точно така. Е, не е подходяща стойност низ. Но има някаква стойност. Каква е стойността, която се записва там? >> Боклук стойност? >> Това е стойността на боклук или, в този случай, края на масива argv винаги се прекратява с нула. Така че това, което всъщност се съхранява в е нула. Другият начин да се разреши този проблем, вместо да го мислене чрез е да се опитаме да ги извежда. Това е мястото, където казва, че използването на GDB е страхотно, защото можете да отпечатате всички променливи, всички стойности, които искате използвате този удобен конте стр. команда. Така че, ако въведете стр. и след това въведете стойността на променлива или името на дадена променлива, се каже, argc, виждам, че argc е 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 скали" низ с нулев низ. Така dereferencing опитвате да отворите неща на нула, нула, обикновено ще предизвика някаква сегментация вина или други лоши неща да се случат. И се оказва, че strcmp не проверява, за да видите дали или не сте преминали в стойност, която е нула. Вместо това, тя просто върви напред, се опитва да направи нещо, и ако Seg грешки, SEG грешки, и това си е ваш проблем. Вие трябва да отидете да го поправим. Наистина бързо, как бихме могли да решите този проблем? Шарлот? Шарлот] Можете да проверите използвате, ако. Така че, ако argv [1] е нула, == 0, след това се върнете един или нещо неразбираемо. >> Да. Така че това е един чудесен начин да го направя, тъй като можем да проверим, за да видите, стойност, ние сме на път да премине в strcmp, argv [1], е нула? Ако това е нищожна, ние може да се каже нищо, се откажем. По-често срещаният начин да направите това е да използвате argc стойност. Можете да видите точно тук, в началото на главната, бяхме пропуснали, че първият тест, който ние обикновено правим, когато използвате аргументи от командния ред, , която е да се провери дали не ни argc стойност е това, което ние очакваме. В този случай, можем да очакваме най-малко два аргумента, името на програмата плюс един от другите. Защото ние сме на път да използват втория аргумент тук. Така че като някакъв вид тест предварително, преди strcmp нашия призив че тестовете дали или не argv е най-малко два, също така ще направи същото нещо. Ние можем да видим дали това работи като стартирате програмата отново. Винаги можете да стартирате програмата си в рамките на GDB, което е много хубаво. Можете да пуснете, а когато премине в аргументи за вашата програма, преминаване покрай тях, когато ти се обадя управлява, а не когато се стартират GDB. По този начин можете да поддържате позоваването на вашата програма с различни аргументи всеки път. Така тичайте, или отново, мога да Type R и нека да видим какво ще стане, ако напишете "здравей". Тя винаги ще ви попита дали искате да го започне отначало. Обикновено искаш да я стартирате отново от самото начало. И в този момент, тя се рестартира го отново, тя се отпечатва програмата, че ние сме, buggy1, с аргумента, здравей, и го отпечатва този стандарт се, тя казва: "Можете да получите D," тъжно лице. Но ние не Seg вина. Той заяви, че този процес излезе нормално. Така че изглежда доста добре. Не повече сегмента вина, то е минало, така че изглежда, че наистина е SEG бъг виновен, че ние се. За съжаление, това ни казва, че ние сме Г. Можем да се върнем и да погледнете кода и да видите какво се случва там да разбера какво е - защо той ни казва, че имаме D. Да видим, тук е това ФОРМАТ казва, че имаш D. Ако въведете списък, колкото можете да пишете списък, тя продължава да итерации през вашата програма, , така че ще ви покажем първите няколко реда от вашата програма. След това ще ви покажем следващите няколко реда, а на следващия парче и следващото парче. И ще продължавам да опитвам да сляза. И сега ние ще стигнем до "линия номер 16 е извън обхват". Защото има само 15 реда. Ако стигнете до този момент и се чудех, "Какво да правя?" можете да използвате командата помощ. Използвайте помощ и след това да го името на команда. И вие виждате, GDB ни дава този вид неща. Той казва: "По никакъв аргумент, изброява още десет реда след или около предходната регистрация. Списък - изброява десет реда преди " Така че, нека се опитаме списък минус. И това се изброяват 10 линии предишното можете да си поиграете с списъка с малко. Можете да направите списък, списък, може дори да се изброят редица, както и списък 8, и ще посочим 10 линии около линия 8. И можете да видите какво става тук имаш проста, ако друго. Ако напишете в CS50 скали, отпечатва "Можете да получите А." В противен случай той ще отпечатва "Можете да получите Г." Кофти града. Добре. Да? [Даниел] Така че, когато се опитах да прави CS50 скали без кавичките, той казва: "Можете да получите Г." Имах нужда от кавички, за да го накарам да работи, защо е така? >> Да. Оказва се, че когато - това е още една забавна малка хапка - когато стартирате програмата, ако ние го стартирате и въвеждате в CS50 скали, точно като Даниел казваше той го направи, и да ви удари Въведете, тя все още казва, че Г. И въпросът е, защо е това? И се оказва, че и двете ни терминал и GDB разбор като тези две отделни аргументи. Защото, когато има пространство, което е косвено, края на първия аргумент следващия аргумент, който е на път да започне. Начин да се съчетаят тези на две или Съжалявам, в един аргумент, е да се използват кавичките. Така че сега, ако го в кавички и да го стартирате отново, получаваме А. Така че просто трябва да набележи без кавичките, CS50 и скали биват анализирани като две отделни аргументи. С кавички, това е разбор съвсем като един аргумент. Можем да видим това, с точка на прекъсване. Досега сме се провежда в нашата програма, и да го е бил докато или Seg повреди или Хитове грешка или докато не излезе и всичко е било напълно глоба. Това не е непременно най-полезното нещо, защото понякога имате грешка в програмата си, но това не причинява сегментация вина. Не причинява си програма, за да спре или нещо подобно. Начин да се GDB да направите пауза в програмата в определен момент е да зададете точка на прекъсване. Можете да направите това чрез създаване на прекъсване на името на функцията или можете да зададете точка на прекъсване на определена линия на код. Харесва ми да се определят гранични стойности на имена на функции, защото лесно да се помни, и ако действително и промените изходния код на малко, тогава си точка на прекъсване действително ще остане на същото място в кода си. Като има предвид, че ако използвате номерата на редовете и номерата на редовете се променят защото вие добавяте или изтривате някакъв код, след което ви гранични стойности са всички тотално прецакани. Един от най-честите неща, които правя се на прекъсване на основната функция. Често ще стартира GDB, ще въведете б главната удари Въведете, и че ще зададете точка на прекъсване на главната функция, която просто казва: "пауза в програмата, веднага след като започнат да действат", и по този начин, когато пускам моята програма, да речем, CS50 скали като два аргумента и натиснете Enter, той получава основната функция и спира точно в най-горния ред, точно преди да оценява strcmp функция. Тъй като аз съм в пауза, сега мога да започна да се откажете от около и да видим какво става с всички на различните променливи, които са преминали в моята програма. Тук мога да отпечатате argc и да видим какво става. Argc е 3, тъй като тя има три различни стойности в него. Тя получава името на програмата, тя има първият аргумент и на втория аргумент. Ние можем да отпечатате тези от гледаш argv [0], argv [1], и argv [2]. Така че сега можете да видите също и защо настоящата покана strcmp ще се провалят, защото вие виждате, че е разделен на CS50 и скалите в две отделни аргументи. В този момент, след като удари на прекъсване, може да продължи да се засили чрез вашата програма ред по ред, за разлика стартиране на програмата отново. Така че, ако не искате да стартирате програмата отново и просто продължете от тук, можете да използвате командата продължават и продължават да стартирате програмата до края. Точно както го е направил тук. Въпреки това, ако рестартирате програмата, CS50 скали, го удари преКъсване ми, и този път, ако аз не искам просто да отидем по целия път през останалата част от програмата, Мога да използвам следващата команда, която да се съкрати с N. И това ще засили чрез програмата ред по ред. Така че можете да гледате, тъй като нещата се изпълняват, като променливи промяна, тъй като нещата се актуализира. Което е доста хубаво. Другите готино нещо е по-скоро от повтаряне на същата команда отново и отново и отново, ако можете просто да натиснете Enter - така че ето виждаш ли, че не сте въвели в нещо - ако аз просто да натиснете Enter, ще повтори предишната команда, или предишната команда GDB, че аз съм сложил инча Мога да продължа да удря Въведете и ще продължаваме да стъпва чрез моя код ред по ред. Бих насърчил вас да проверя, както и на други програми бъги. Ние не разполагат с време, за да получите чрез всички тях днес в раздел. Изходният код е там, така че да видим какво се случва зад кулисите, ако ви наистина остана, но най-малкото, просто практикуват зарежда GDB, изпълнението на програмата, докато тя се разпада на вас, получаване на обратно проследяване, фигуриращ какво функционират катастрофата е в какво линия, отпечатване на някои променливи стойности, само така можете да получите представа за него, защото това наистина ще ви помогне да вървите напред. В този момент, ние ще излезем на GDB, които можете да използвате откажат или просто р. Ако програмата ви е в средата на все още работи, и то не е излязъл, тя винаги ще ви попита: "Вие ли сте сигурен, че наистина искате да се откажете? Можете просто да удари. Сега отиваме да разгледаме следващия проблем, който имаме, което е програмата на котката. Ако гледате за пренасочване на средства и тръби, ще видите, че Томи използва тази програма , която основно се отпечатва цялата продукция на файл на екрана. Така че, ако аз тичам котка, това всъщност е вграден в програмата на уреда, и ако имате Mac-ове, можете да направите това на вашия Mac, ако се отвори терминал. А ние - котка, да речем, cp.c, и натиснете Enter. Това, ако ние се придвижите нагоре малко и да видим къде се прокара линията, или когато ние се завтече котка команда, буквално отпечатани съдържанието на cp.c да ни екрана. Ние можем да го стартирате отново и можете да поставите в множество файлове. Така че можете да направите cp.c котка, а след това можем да се слеят в cat.c файл, което е програмата сме да пиша, и това ще отпечатате двата файла, за да направите резервно копие на нашия екран. Така че, ако ние превъртете малко, ние виждаме, че когато ние се завтече тази котка cp.c, cat.c, за първи път го отпечатва на КП файл и след това под него, отпечатани cat.c файл чак тук. Отиваме да използвате тази просто да се качите краката ни мокри. Поиграйте си с прости печат към терминала, вижте как работи. Ако вие се отвори с Gedit cat.c, удари Enter, можете да видите програмата, която сме на път да пиша. Включили сме тази хубава плоча на котела, така че не е нужно да прекарват времето си пишете всички, че. Ние също така да проверите броя на аргументи премина инча Ние печат приятен за използване. Това е вид на нещо, че отново, както и ние сме били говорим за, това е почти като мускулна памет. Само не забравяйте да правиш едно и също такива неща и винаги отпечатване някаква полезна съобщение така че хората да знаят как да изпълнявате вашата програма. С котка, това е доста проста, просто щяхме да мине през всички различни аргументи , които бяха приети в нашата програма, и отиваме да отпечатате съдържанието им, на екрана един по един. За да отпечатате файлове на екрана, ние ще направим нещо подобно на това, което направихме в края на теста. В края на теста, които наемат програма, ние трябваше да отвори файл, и след това трябваше да се печата на него. В този случай, ние отиваме да отворите файл, и отива да чете от него, вместо да. След това отиваме да отпечатате, вместо на файл, отиваме да отпечатате на екрана. Така отпечатване на екрана всички сте правили преди с ФОРМАТ. Така че това не е твърде луд. Но четенето на файла е някак странно. Ще отидем през тази малко в даден момент. Ако вие се върнете на последния проблем на викторина, проблем 33, на първа линия, че ние ще направим тук, за отваряне на досието, е много подобен на това, което направихме там. Така Стела, какво прави тази линия изглежда като, когато отворите файл? [Stella] Capital FILE *, файл - >> Добре. >> - Е равна на fopen. >> Мда. Което в този случай? Това е в коментара. >> В коментара? argv [] и R? >> Точно така. Точно така. Така че Стела е напълно прав. Това е линията прилича. Отиваме да се получи променлив поток файл, той се съхранява във файл *, така че всички шапки, FILE *, както и името на тази променлива ще бъде файл. Бихме могли да го наречем, каквото ни харесва. Бихме могли да го наречем first_file или file_i, каквото и да искате. И след това името на файла е приет на командния ред за тази програма. Така че се съхранява в argv [] и след това отиваме да отворите този файл в режим на четене. Сега, когато сме отворили файла, какво е това, което ние винаги трябва да помним, да се направи когато сме отворили файл? Затворете. Така че Миси, как да затворите файл? [Missy] неуспешно (файл) >> неуспешно (файл). Точно така. Велики. Добре. Ако се вгледаме в това да направя коментар тук, се казва: "Open argv [] и отпечатване на съдържанието му на стандартния изход." Standard навън е странно име. STDOUT е само начин да се каже искаме да я отпечатате на терминала, ние искаме да го отпечатате на стандартния изходен поток. Ние действително можем да се отървем от този коментар тук. Отивам да го копирате и да го поставите, тъй като това е, което ние направихме. В този момент, сега ще трябва да прочетете малко на файла по малко. Сме обсъждали няколко начина на четене на файлове. Кои са вашите фаворити досега? Какви начини виждал ли си или не си спомняте, да чете файлове? [Даниел] fread? >> Fread? Така че fread е един. Джими, знаеш ли някакви други? Джими] Не >> Добре. Не. Шарлот? Александър? Всички други? Добре. Затова другите са fgetc, е, че ние ще използваме много. Има също така и fscanf, вие се види модела тук? Всички те започват с е. Нещо общо с даден файл. Fread, fgetc, fscanf. Те всички са от читалищата функции. За писане имаме неуспешно, ние имаме fputc вместо fgetc. Ние също имаме fprintf както видяхме в анкетата. Тъй като това е проблем, който включва четене от файл, отиваме да се използва един от тези три функции. Ние няма да се използват тези функции тук. Тези функции са в стандартния I / O библиотека. Така че, ако се вгледате в горната част на тази програма, можете да видите, че ние вече включва заглавния файл за стандартния I / O библиотека. Ако искаме да разберем кой искате да използвате, винаги можем да се отворят страниците на човек. Така че можем да въведете stdio човек и да прочетете всичко за stdio входни и изходни функции в C. И ние вече можем да видим О, вижте. Споменава fgetc, той споменава fputc. Така че можете да пробиете малко и погледнете, да речем, fgetc и погледнете в страницата си човек. Можете да видите, че той отива заедно с цял куп други функции: fgetc, fgets, getc, getchar, получава, ungetc, и въвеждане на символи и низове. Така че това е как четем в символи и струнни от файлове от стандартния вход, който е по същество от потребителя. И това е как го правим в действителност C. Така че това не е с помощта на GetString и GetChar функции че ние използвахме от библиотеката CS50. Ние ще направим този проблем по няколко начина , така че да могат да се виждат два различни начини да го направите. Както fread функция, която Даниел спомена и fgetc са добри начини да го направя. Мисля, fgetc е малко по-лесно, тъй като тя има само, както виждате, един аргумент, FILE *, че ние се опитваме да прочетете на героя от, и неговото връщане стойност е вътр. И това е малко объркващо, нали? Защото ние сме характер, така че защо не това завръщане Чар? Вие имате някакви идеи за това защо това не може да се върне Чар? [Миси отговори, неразбираем] >> Да, Така че Миси е напълно прав. Ако това е ASCII, тогава това число може да бъде съпоставена с действително Чар. Може да е ASCII характер, и това е вярно. Това е точно това, което се случва. Ние използваме едно цяло число, просто защото тя има повече битове. Това е по-голям от Чар, Чар ни има само 8 бита, че 1 байт на нашите 32-битови машини. И Int има всички 4 байта на пространството. И се оказва, че начина, по който fgetc работи, ако ние превъртете надолу в резюме ни в страницата с този човек малко, превъртете надолу. Оказва се, че те използват тази особена стойност EOF. Това е специална константа като върнатата стойност на fgetc функция всеки път, когато удари в края на файла или ако получите съобщение за грешка. И се оказва, че за да правите тези сравнения с EOF правилно, искате да имате, че допълнително количество информация, която имате в Int за разлика от използването на знак променлива. Въпреки че fgetc е ефективно знак от файл, искате да си припомните, че се връща нещо, което е от тип Int. Това заяви, че е доста лесен за използване. Това ще ни даде знак, така че всичко, което трябва да направим, е да продължавам да се питам файла, "Дай ми следващия знак, дай ми следващия знак, дай ми следващия знак" докато не стигнем до края на файла. И това ще дръпне в един символ в даден момент от нашия файл и след това можем да правим каквото искаме с него. Можем да го съхранява, ние можем да го добавите в низ, можем да го разпечатате. От това. Приближаването обратно и връщане назад към cat.c нашата програма, ако ще да използвате fgetc, как бихме могли да се подходи към този от следващия ред? Отиваме да използвате fread ще направи нещо по-различно. И този път, ние просто ще използваме fgetc да се получи един символ в даден момент. Да обработите цялата преписка, какво бихме могли да трябва да направя? Колко знака има във файл? Има много. Така че най-вероятно искате да се получи един и след това получи друг и да получите друг и да получите друга. Какъв алгоритъм мислиш ли, че може да се наложи да се използва тук? Какъв тип? [Александър] А за контур? >> Точно така. Някакъв вид на линията. А за цикъла всъщност е страхотно, в този случай. И както казах, това звучи като искате примка над цялата преписка, получаване на символ в даден момент. Всички предложения за това какво може да изглежда? [Александър, неразбираем] >> Добре, само ми кажи на английски език това, което се опитваме да направим? [Александър, неразбираем] Така че в този случай, това звучи като ние просто се опитваме да отскача над цялата преписка. [Александър] Така че аз <размера на Int? >> Размер на - Предполагам, че размера на файла, нали? Размер - Ще го напиша по този начин. Размер на файла за момента, аз + +. Така се оказва, че начина, по който се прави със fgetc и това е нещо ново, е, че няма лесен начин да получите размера на файла с този тип конструкция, която сте виждали преди "sizeof". Когато ние използваме тази fgetc функция, ние ви представяме някакъв вид нова, фънки синтаксис за цикъл, където, вместо да използват само основен брояч да отиде знак по знак, отиваме да дръпнете един символ в даден момент, един символ в даден момент, и начина, по който ние знаем, че сме в края когато не сме броят определен брой знаци, но когато характера извадя е, че специална края на файла характер. Така че можем да направим това, като - Аз наричам това CH, и ние ще го инициализира с първата покана за първия знак на файла. Така че тази част точно тук, това ще се получи, символ на файла и да го съхранява в променливата гл. Ние ще продължим да правиш това, докато стигнем до края на файла, , които правим чрез тестване за характера, не е равен на този специален характер EOF. И тогава, вместо да прави CH + +, която просто ще увеличите стойността, така че ако четем от файла, на капитала на, да речем, CH + + ще ни даде б, и тогава ние ще получите в и след това г. Това очевидно не е това, което искаме. Това, което искаме тук в това последно малко искаме да получим следващия знак от файла. И така, как бихме могли да получи следващия знак от файла? Как да стигнем до първия знак от файл? [Студентски fgetfile? >> Fgetc, съжалявам, бяхте напълно прав. Аз го сгрешена точно там. Така че, да. Тук, вместо да правиш CH + +, ние просто ще се обадя fgetc (файл) и запазване на резултата в същото CH променлива. [Student въпрос, неразбираем] >> Това е мястото, където тези момчета файл * са специални. Начинът, по който те работят, те - когато за пръв път отворите - когато за първи път правите, че fopen разговор, FILE * ефективно служи като указател към началото на файла. И тогава всеки път, когато ти се обадя fgetc, тя се движи един символ във файла. Така че, когато ти се обадя, увеличаване на файловия указател от един символ. И когато fgetc отново, сте го движи друг характер и друг характер и друг характер и друг характер. [Student въпрос, неразбираем] >> И това е - да. Това е вид на тази магия под капака. Увеличаване чрез. В този момент, вие сте в състояние действително да работи с характер. И така, как бихме могли да отпечатате това на екрана, сега? Ние можем да използваме същата ФОРМАТ нещо, което сме използвали преди. Че ние сме били семестър. Можем да наречем ФОРМАТ, и ние можем да преминем в характера просто ей така. Друг начин да го направя вместо да използва ФОРМАТ и се налага да правя този низ формат, ние също може да използва един от другите функции. Ние можем да използваме fputc, която отпечатва символ на екрана, освен ако погледнем в fputc - нека я увеличите малко. Виждаме, което е хубаво е, че отнема в характера, които четем, като се използва fgetc, но тогава ние трябва да му се даде поток да печатате. Можем също така да използвате putchar функция, която ще постави директно на стандартния изход. Така че има един куп от различните варианти, които можем да използваме за печат. Те всички са в стандартния I / O библиотека. Всеки път, когато искате да отпечатате - така ФОРМАТ, по подразбиране, ще се отпечата на специален стандарт от поток, което е, че стандартния изход. Така че ние можем само да се отнасят към него като един вид от тази магия стойност, стандартния изход тук. Опа. Поставете запетая извън. Това е много нова, фънки информация тук. Голяма част от това е много идиоматичен, в смисъл, че това е код , което е написано по този начин, само защото тя е чиста, да чете, да се чете лесно. Има много различни начини да го направя, много различни функции, които можете да използвате, но ние сме склонни да просто следвайте същите тези модели отново и отново. Така че не се изненадвайте, ако видите код, като това идва отново и отново. Добре. В този момент, ние трябва да се прекъсне за деня. Благодаря, че дойдохте. Благодаря за гледане, ако сте онлайн. И ние ще се видим следващата седмица. [CS50.TV]