[Powered by Google Translate] [CS50 Library]
[Нейт Hardison] [Харвардския университет]
[Това е CS50. CS50.TV]
Библиотеката CS50 е полезен инструмент, че имаме инсталиран на уреда
да направи по-лесно да се пишат програми, които подканят потребителите за вход.
В това видео, ние ще дръпнете завесата и да потърсите какво точно е в CS50 библиотека.
>> В видео библиотеки C, ние говорим за начина, по който # включват заглавията файлове
на библиотеката в изходен код,
и след това се свържете с двоичен файл библиотека по време на свързване фаза
процеса на компилация.
Заглавните файлове уточняват интерфейса на библиотеката.
Това означава, че те подробно на всички ресурси, които библиотеката разполага, за да използвате,
като функция декларации, константи, типове данни.
Двоичен файл Библиотеката съдържа изпълнението на библиотеката,
, който е съставен от заглавните файлове на библиотеката и библиотека в изходните файлове код.
>> Двоичен файл библиотеката не е много интересно да гледам тъй като това е добре, в двоичен.
Така че, нека да погледнем в заглавните файлове за библиотеката, вместо.
В този случай, има само един хедър файл, наречен cs50.h.
Сме го инсталирали в инструкцията за директорията
заедно с заглавните файлове на други библиотеки системи.
>> Едно от първите неща, които ще забележите е, че cs50.h # включва хедър файлове от други библиотеки -
поплавък, граници, стандарт BOOL и стандартни Lib.
Отново, следвайки принципа не преоткрива колелото,
сме изградили CS0 колекция с помощта на инструменти, които други, предвидени за нас.
>> Следващото нещо, което ще видите в библиотеката е, че ние определяме един нов вид, наречен "низ".
Тази линия наистина просто създава псевдоним за Чар тип *
така че не магически придават на нов тип низ с атрибути
често се свързва с струнни обекти в други езици,
като дължина.
Причина, ние сме направили това, е да се предпазят нови програмисти от страховити подробности
от указатели, докато те са готови.
>> Следващата част на заглавния файл е декларацията на функциите
CS50 библиотека предоставя заедно с документация.
Обърнете внимание на нивото на детайлност в коментарите тук.
Това е супер важно, така че хората да знаят как да използват тези функции.
Ние заявяваме, от своя страна, функциите да предизвика символа на потребителя и връщане, двойки, плувки, интеджър
дълго копнее, и струнни, използвайки нашата собствена тип низ.
Следвайки принципа на информация се крие,
ние поставяме нашата дефиниция в отделен файл за изпълнение в cs50.c -
се намира в директорията на потребителския източник.
При условие че сме файл, така че можете да вземете един поглед към него,
се поучим от него и да го компилирате на различни машини, ако желаете,
въпреки че ние смятаме, че е по-добре да работят върху уреда за този клас.
Както и да е, нека хвърлим един поглед към него сега.
>> Функциите GetChar, GetDouble, GetFloat, GetInt, и GetLongLong
са построени на върха на GetString функция.
Оказва се, че всички те следват по същество един и същи модел.
Те използват линия, докато да подтикне потребителя за един ред на входа.
Те се връщат със специална стойност, когато потребителят входа празен ред.
Те се опитват да се направи разбор на въвеждане на потребителя като подходящ тип,
Чар, двойни, с плаваща запетая, и др.
И тогава те се връщат резултат, ако входа беше успешно разбор
или reprompt на потребителя.
>> На по-високо ниво, няма нищо наистина труден.
Може да са писали подобно структуриран код себе си в миналото.
Може би най-загадъчен изглеждащи част е sscanf обаждане, че Интерпретира входа на потребителя.
Sscanf е част от семейството на входа формат преобразуване.
Тя живее в io.h стандарт, а нейната задача е да прави разбор на низ C,
в съответствие с определен формат, съхранение на разбора резултати в променлива
предвидени от повикващия.
Тъй като входните функции формат преобразуване са много полезни, широко използвани функции
, които не са супер интуитивен първа
ние ще отидем как sscanf работи.
>> Първият аргумент sscanf е знак * - показалец към символен.
За да работи функцията правилно,
този характер трябва да бъде на първия знак от низ C
прекратява с нулевата \ 0 характер.
Това е низ, да прави разбор
Вторият аргумент sscanf е низ формат,
обикновено премина като низ константа,
и може да са видели низ като преди, когато се използва ФОРМАТ.
Процент знак във формат низ показва означител за преобразуване.
Характер веднага след знак за процент,
показва типа на C, че искаме sscanf да конвертирате.
В GetInt, ще видите, че е налице% D и C%.
Това означава, че sscanf ще се опита да десетична INT -% г и Чар% в.
За всеки означител за преобразуване във формат низ,
sscanf очаква съответния аргумент по-късно в списъкът с аргументите.
Този аргумент трябва да сочи към подходящо въвели място
, в която да се съхранява в резултат на преобразуването.
>> Типичният начин за това е да създадете променлива в стека преди поканата sscanf
за всеки елемент, който искате да се направи разбор на низ
и след това да използвате адреса оператор - амперсанд - да премине указатели
тези променливи в разговора sscanf.
Можете да видите, че в GetInt правим точно това.
Точно преди поканата sscanf, ние заявяваме, вътр нарича н и в знак покана на стека,
и преминаваме указатели към тях в поканата sscanf.
Поставянето на тези променливи в стека е за предпочитане пред отделено място
на купчина с изчистване, тъй като ще избегнете на изчистване разговор,
и не е нужно да се притеснявате за изтичане на памет.
Знаците, които не са предхождани от знак за процент не доведе до конверсия.
Вместо това те просто добавете към спецификацията на формата.
>> Например, ако форматът на низ в GetInt% г вместо това,
sscanf ще изглежда писмо, последвано от едно цяло число,
и докато той ще се опита да конвертирате Int, не би направил нещо друго, с една.
Единственото изключение от това е празно пространство.
Бели символи пространство във формат низ съвпадат всяка сума на празно място -
дори няма изобщо.
Така че, ето защо коментара се посочва, евентуално с водещи и / или в края на интервали.
Така че, в този момент, тя изглежда като нашата sscanf повикване ще се опита да анализира входния низ на потребителя
от проверка за евентуална водеща празно,
последван от вътр, които ще се конвертират и съхраняват в INT променлива N
последвана от някаква сума на празно пространство, и последван от символ
съхраняват в Чар променлива в.
>> Ами върнатата стойност?
Sscanf ще направи разбор на линейния вход от начало до край,
спиране, когато са достигнали до края или когато герой във входа
не съвпада с характер формат или когато не може да се направи конверсия.
Това е връщаната стойност се използва да изредя, когато тя спря.
Ако го спря, тъй като тя стигна до края на входния низ
преди да направи никакви реализации и преди не е съответства на част от формат низ,
тогава специална постоянна EOF се връща.
В противен случай, той се връща на броя на успешните реализации,
която може да бъде 0, 1 или 2, тъй като сме поискали за две реализации.
В нашия случай, ние искаме да се уверим, че потребителският въвели в едно цяло число и само вътр.
>> Така че, ние искаме sscanf да се върне 1. Вижте защо?
Ако sscanf връща 0, тогава никакви реализации са направени,
така че потребителят написали нещо различно от едно цяло число в началото на входа.
Ако sscanf връща две, а след това, че потребителят не правилно да го въведете в в началото на входа,
но след това те написали в някои не-празно характер след това
тъй% в преобразуване успя.
Уау, това е доста дълго обяснение за една функция разговор.
Както и да е, ако искате повече информация за sscanf и неговите братя и сестри,
разгледайте страниците на човек, Google, или и двете.
Има много опции формат низ,
и това може да ви спести много ръчен труд, когато се опитват да се направи разбор конците в C.
>> Крайният функция в библиотеката да погледнете е GetString.
Оказва се, че GetString е сложен функция, за да пишат правилно,
макар и да изглежда като проста, обща задача.
Защо това е така?
Е, нека помислим за това как ги съхраняват линията на потребителя видове инча
Тъй като низ е последователност от символи,
бихме искали да я съхранява в масив в стека,
но ние ще трябва да знам колко дълго масива ще бъде, когато ние го декларира.
По същия начин, ако искаме да го постави на куп,
ние трябва да се премине към изчистване на броя на байтове, искаме да резервирате
но това е невъзможно.
Ние нямаме представа колко символа потребителят ще напишете
преди потребителят действително не ги въвеждате.
>> Наивно решение на този проблем е просто да запази голяма част от пространството, да речем,
блок от 1000 символа за вход на потребителя,
се предполага, че потребителят не би да въведете низ, който дълго.
Това е лоша идея по две причини.
На първо място, като се предполага, че потребителите обикновено не въведете струни толкова дълго,
можете да губи много памет.
На съвременни машини, това не може да бъде проблем, ако направите това
в една или две изолирани случаи,
но ако сте като въвеждане на потребителя в една линия и съхранява за по-нататъшна употреба,
можете бързо да смучат на тон на паметта.
Освен това, ако програмата, която пишете, е за по-малък компютър -
устройство като смартфон или нещо друго с ограничена памет -
това решение ще доведе до проблеми много по-бързо.
Втората, по-сериозна причина да не направите това е, че то оставя вашата програма уязвими
на това, което се нарича атака за препълване на буфера.
Програмиране, буфер памет се използва за временно съхраняване на входящите или изходящите данни,
който в този случай е 1000-Чар блок.
Препълване на буфера се случва, когато данните се записват след края на блока.
>> Например, ако потребителят всъщност прави вид в повече от 1000 символа.
Може да са имали това случайно, когато програмиране с масиви.
Ако имате масив от 10 цели числа, нищо не ви спира да се опитва да чете или пише
15-ти вътр.
Не са открити компилатора предупреждения или грешки.
Програма само гафове напред и достъп до паметта
случаите, когато смята 15-ти Int ще бъде, и това може да се замести други променливи.
В най-лошия случай, може да се замести част от вашата вътрешна програма
механизмите за контрол, което води до вашата програма да изпълнява различни инструкции
отколкото сте възнамерявали.
>> Сега, това не е обичайно да се направи това случайно,
но това е доста често срещано техника, която лошите момчета използват, за да се прекъсне програми
и зловреден код на компютрите на други хора.
Ето защо, ние не можем просто да използвате нашия наивен решение.
Ние се нуждаят от начин да предпазим нашите програми от уязвими
атака за препълване на буфера.
За да направите това, трябва да се уверите, че нашият буфер може да расте както четем
още информация от потребителя.
Решението? Ние използваме куп заделените буфер.
Тъй като ние да преоразмерите да го използвате за преоразмеряване презаделяне функция,
и ние да следите на две числа - индексът на следващия празен слот в буфера
и дължина или капацитет на буфера.
Четем в символа от потребителя в даден момент използване на fgetc функция.
Аргументът на fgetc функция е стандартния вход - е препратка към стандартния вход низ,
което е preconnected входен канал, който се използва за прехвърляне на въвеждане на потребителя
от терминала на програмата.
>> Когато потребителят видове в нов герой, ние проверяваме, за да видите, ако индексът
на следващия свободен слот плюс 1 е по-голяма от капацитета на буфера.
Едно идва, защото ако на следващия свободен индекс е 5,
дължина нашия буфер трябва да бъде 6 благодарение на 0 индексиране.
Ако сме изчерпи пространството в буфер, а след това ние се опитваме да я оразмерите,
удвоява, така че да можем ограничаване на броя пъти, че ние преоразмеряване
ако потребителят пише в един наистина дълъг низ.
Ако низът е намерила твърде дълго или ако бягаме от куп памет,
ние освободим буфер и нула връщане.
>> И накрая, ние добавяме Чар буфера.
След като потребителят натисне влиза или да се върнат, сигнализация нов ред,
или специален Чар - контрол г, което е сигнал за края на входа,
правим проверка, за да се види, ако потребителят действително въвели в каквото и да било.
Ако не, връщаме нула.
В противен случай, защото нашият буфер е може би по-голям, отколкото ни е необходимо,
в най-лошия случай това е почти два пъти по-голям, тъй като имаме нужда
тъй като ние два пъти всеки път, когато преоразмерявате,
правим ново копие на низа, само с помощта на размера на пространството, че имаме нужда.
Ние добавяме допълнително 1 до изчистване разговор,
, така че има място за специален символ нула терминатор - \ 0,
които ние добавяме низ, след като копирате в останалата част от героите,
използване strncpy вместо strcpy
, така че да можем да определим точно колко символа искаме да копирате.
Strcpy копира, докато го удари \ 0.
Тогава ние освободим буфер и връща копието на повикващия.
>> Кой знаеше, че такъв прост-привидна функция може да бъде толкова сложно?
Сега вие знаете какво се случва в библиотеката CS50.
>> Моето име е Нейт Hardison, и това е CS50.
[CS50.TV]