[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 и нажмите Ввод, что происходит? [Саад] Я получил SIGSEGV, ошибки сегментации, а затем все это абракадаброй. >> Да. Как мы видим на экране прямо сейчас, и, как Саад сказал: когда мы вводим пробега или R и нажмите Ввод, мы все еще получить тот же сегмент вина. Таким образом, использование GDB не решает наши проблемы. Но это дает нам некоторое абракадабру, и оказывается, что это абракадаброй на самом деле говорит нам, где это происходит. Для разбора этого немного, это первый бит является функцией, в которой все происходит не так. Там эта __ strcmp_sse4_2, и он говорит нам, что это происходит в этом файле называется sysdeps/i386, все это, опять же, вид беспорядок - но линия 254. Это своего рода трудно разобрать. Обычно, когда вы видите такие вещи, как это, , что означает, что она сегментам разломов в одной из системных библиотек. Так что что-то делать с STRCMP. Вы, ребята, видели STRCMP раньше. Не слишком сумасшедшим, но значит ли это, что STRCMP сломан или что есть проблема с STRCMP? Как вы думаете, Александр? [Александр] Это что - составляет 254 линий? И - не двоичный, но это не их потолки, а там другой язык для каждой функции. Разве что 254 в этой функции, или -? >> Это линия 254. Похоже, что в этом нет. Файл с, так что это, вероятно, сборка код. Но, я думаю, более насущные вещи есть, потому что мы получили сегменте вина, и, похоже, это идет от STRCMP функции, это подразумевает, то, что STRCMP не работает? Это не должно, мы надеемся. Таким образом, только потому, что у вас есть ошибки сегментации В одной из функций системы, как правило, это означает, что вы просто не называть его правильно. Самый быстрый, что нужно сделать, чтобы выяснить, что происходит на самом деле когда вы видите что-то сумасшедший, как это, когда вы видите сегмент вина, Особенно, если у вас есть программа, которая использует большее, чем просто основной, это использовать трассировку. Я сокращать след в письменной форме BT, в отличие от полного слова трассировку. Но Шарлотта, что происходит, когда вы набираете BT и нажмите Ввод? [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]