1 00:00:00,000 --> 00:00:02,490 [Powered by Google Translate] [CS50 библиотека] 2 00:00:02,490 --> 00:00:04,220 [Нејт Hardison] [Универзитетот Харвард] 3 00:00:04,220 --> 00:00:07,260 [Ова е CS50. CS50.TV] 4 00:00:07,260 --> 00:00:11,510 Во библиотеката CS50 е корисна алатка која ние инсталиран на уредот 5 00:00:11,510 --> 00:00:15,870 да се направи полесно за вас да пишуваат програми кои брза корисници за влез. 6 00:00:15,870 --> 00:00:21,670 Во ова видео, ќе се повлечат завесата и се погледне во што точно е во CS50 библиотека. 7 00:00:21,670 --> 00:00:25,520 >> Во видео на C библиотеки, ние зборуваме за тоа како можете # вклучуваат заглавија датотеки 8 00:00:25,520 --> 00:00:27,570 на библиотеката во вашиот изворен код, 9 00:00:27,570 --> 00:00:31,150 а потоа ќе се поврзе со бинарен библиотека датотеката во текот на поврзување фаза 10 00:00:31,150 --> 00:00:33,140 на компилацијата процес. 11 00:00:33,140 --> 00:00:36,440 Насловот датотеки наведете интерфејс на библиотеката. 12 00:00:36,440 --> 00:00:41,280 Тоа е, тие детално сите ресурси кои библиотеката има на располагање за да го користиш, 13 00:00:41,280 --> 00:00:45,250 како функција декларации, константи, и типови на податоци. 14 00:00:45,250 --> 00:00:48,890 На бинарни библиотека датотека содржи спроведувањето на библиотеката, 15 00:00:48,890 --> 00:00:54,580 која е составена од насловот датотеки на библиотеката и на библиотеката. Со изворниот код датотеки. 16 00:00:54,580 --> 00:00:59,820 >> На бинарни библиотека датотека не е многу интересно да се погледне, бидејќи тоа е, добро, во бинарна. 17 00:00:59,820 --> 00:01:03,300 Значи, ајде да ги разгледаме во насловот датотеки за библиотеката наместо тоа. 18 00:01:03,300 --> 00:01:07,710 Во овој случај, има само еден хедер датотека наречена cs50.h. 19 00:01:07,710 --> 00:01:11,040 Ние го инсталирани во на корисникот вклучуваат директориум 20 00:01:11,040 --> 00:01:15,150 заедно со насловот датотеки на други системски библиотеки. 21 00:01:15,150 --> 00:01:21,530 >> Една од првите работи што ќе забележите е дека cs50.h # вклучува насловот датотеки од други библиотеки - 22 00:01:21,530 --> 00:01:25,670 плови, граници, стандард bool, и стандардни lib. 23 00:01:25,670 --> 00:01:28,800 Повторно, по принципот на не reinventing на тркалото, 24 00:01:28,800 --> 00:01:33,490 ние сме изградиле CS0 библиотека користење алатки кои други предвидени за нас. 25 00:01:33,490 --> 00:01:38,690 >> Следното нешто што ќе видите во библиотеката е дека ние се дефинира нов вид наречен "стринг." 26 00:01:38,690 --> 00:01:42,330 Оваа линија навистина само создава алијас за char * тип, 27 00:01:42,330 --> 00:01:46,000 па тоа не магично насаждам новиот стринг тип со атрибути 28 00:01:46,000 --> 00:01:49,650 обично се поврзуваат со низа објекти во други јазици, 29 00:01:49,650 --> 00:01:50,850 како што се должината. 30 00:01:50,850 --> 00:01:55,180 Причината ние го направивме ова е да се заштити нови програмери од крвави детали 31 00:01:55,180 --> 00:01:57,580 на покажувачи се додека не завршиш. 32 00:01:57,580 --> 00:02:00,130 >> Следниот дел од хедер датотека е декларацијата на функции 33 00:02:00,130 --> 00:02:04,410 дека CS50 библиотека обезбедува заедно со документација. 34 00:02:04,410 --> 00:02:06,940 Обрнете внимание на нивото на детали во коментари тука. 35 00:02:06,940 --> 00:02:10,560 Ова е супер важно, така што луѓето знаат како да ги користат овие функции. 36 00:02:10,560 --> 00:02:19,150 Изјавуваме, пак, функционира за да го извести корисникот и враќање карактери, двојки, плови, ints, 37 00:02:19,150 --> 00:02:24,160 долго копнее, и стрингови, користејќи свој стринг тип. 38 00:02:24,160 --> 00:02:26,260 По принципот на информации крие, 39 00:02:26,260 --> 00:02:31,640 имаме стави нашата дефиниција во посебен в имплементација датотека -. cs50.c-- 40 00:02:31,640 --> 00:02:35,110 се наоѓа во на корисникот изворниот директориум. 41 00:02:35,110 --> 00:02:38,040 Ние сме под услов датотека, па можете да ги погледне во него, 42 00:02:38,040 --> 00:02:41,490 учат од неа, и прекомпајлирате тоа на различни машини ако сакате, 43 00:02:41,490 --> 00:02:45,510 иако ние мислиме дека е подобро да се работи на апаратот за оваа класа. 44 00:02:45,510 --> 00:02:47,580 Како и да е, ајде да ги разгледаме во тоа сега. 45 00:02:49,020 --> 00:02:54,620 >> Функциите GetChar, GetDouble, GetFloat, GetInt и GetLongLong 46 00:02:54,620 --> 00:02:58,160 сите се изградени на врвот на GetString функција. 47 00:02:58,160 --> 00:03:01,510 Се испоставува дека сите тие следат истите шема. 48 00:03:01,510 --> 00:03:04,870 Тие ги користат додека јамка за да го извести корисникот за една линија на влез. 49 00:03:04,870 --> 00:03:08,430 Ќе се вратат посебна вредност, ако на корисникот влезови празна линија. 50 00:03:08,430 --> 00:03:11,750 Тие се обидуваат да го анализирам влез на корисникот како соодветен вид, 51 00:03:11,750 --> 00:03:15,010 било да е тоа знак, двојно, плови, итн 52 00:03:15,010 --> 00:03:18,710 А потоа тие или врати резултатот ако влезот е успешно разложени 53 00:03:18,710 --> 00:03:21,330 или тие reprompt на корисникот. 54 00:03:21,330 --> 00:03:24,230 >> На високо ниво, не постои ништо навистина незгодно тука. 55 00:03:24,230 --> 00:03:28,760 Може да го имаат напишано слично структурирани кодот себе во минатото. 56 00:03:28,760 --> 00:03:34,720 Можеби повеќето криптичната изглед дел е sscanf повик дека parses влез на корисникот. 57 00:03:34,720 --> 00:03:38,160 Sscanf е дел од внесување формат конверзија семејство. 58 00:03:38,160 --> 00:03:42,300 Таа живее во стандард io.h, а неговата работа е да го анализирам низа Ц, 59 00:03:42,300 --> 00:03:46,520 според одреден формат, чување анализирам резултати во променлива 60 00:03:46,520 --> 00:03:48,720 обезбедени од страна на повикувачот. 61 00:03:48,720 --> 00:03:53,570 Од влез формат конверзија функции се многу корисни, широко користените функции 62 00:03:53,570 --> 00:03:56,160 кои не се супер интуитивен во прв, 63 00:03:56,160 --> 00:03:58,300 ќе одиме околу тоа како sscanf работи. 64 00:03:58,300 --> 00:04:03,330 >> Првиот аргумент да sscanf е char * - покажувач кон карактер. 65 00:04:03,330 --> 00:04:05,150 За функцијата за да работи правилно, 66 00:04:05,150 --> 00:04:08,340 дека карактерот треба да биде првиот карактер на стрингот Ц, 67 00:04:08,340 --> 00:04:12,270 престанува со нула \ 0 карактер. 68 00:04:12,270 --> 00:04:15,120 Ова е стринг за да се анализира 69 00:04:15,120 --> 00:04:18,269 Вториот аргумент да sscanf е формат стринг, 70 00:04:18,269 --> 00:04:20,839 обично донесен во како стринг константа, 71 00:04:20,839 --> 00:04:24,040 и може да се гледа низа како тоа порано кога користите printf. 72 00:04:24,040 --> 00:04:28,650 А знакот за процент во формат стринг укажува на конверзија назначувач. 73 00:04:28,650 --> 00:04:30,850 Ликот веднаш по знакот за процент, 74 00:04:30,850 --> 00:04:35,430 укажува на типот Ц што сакаме sscanf да го конвертирате во. 75 00:04:35,430 --> 00:04:40,090 Во GetInt, ќе видите дека има% d и% c. 76 00:04:40,090 --> 00:04:48,690 Ова значи дека sscanf ќе се обиде да една децимална int -% d - и знак - на% c. 77 00:04:48,690 --> 00:04:51,510 За секоја пренамена назначувач во формат стринг, 78 00:04:51,510 --> 00:04:56,620 sscanf очекува соодветен аргумент подоцна во својот аргумент листа. 79 00:04:56,620 --> 00:05:00,850 Тој аргумент да се укаже на соодветно внесе локација 80 00:05:00,850 --> 00:05:04,000 во која за чување резултат на реализација. 81 00:05:04,000 --> 00:05:08,910 >> Типичен начин за тоа е да се создаде променлива на магацинот пред повикот sscanf 82 00:05:08,910 --> 00:05:11,440 за секоја ставка што сакате да го анализирам од низа 83 00:05:11,440 --> 00:05:15,520 и потоа користете адреса оператор - на симболот - да помине совети 84 00:05:15,520 --> 00:05:19,100 на овие променливи на повикот sscanf. 85 00:05:19,100 --> 00:05:22,720 Можете да видите дека во GetInt правиме токму тоа. 86 00:05:22,720 --> 00:05:28,240 Непосредно пред повикот sscanf, ние прогласи int нарекува n и знак повик в на магацинот, 87 00:05:28,240 --> 00:05:32,340 и ние помине совети како да ги во повикот sscanf. 88 00:05:32,340 --> 00:05:35,800 Ставањето на овие променливи на магацинот се препорачува пред користење на просторот распределени 89 00:05:35,800 --> 00:05:39,350 на грамада со Примерок, бидејќи ќе се избегне над глава на Примерок повик, 90 00:05:39,350 --> 00:05:43,060 а вие не мора да се грижите за протекување меморија. 91 00:05:43,060 --> 00:05:47,280 Знаци не префикс знакот за процент не поттикне реализација. 92 00:05:47,280 --> 00:05:50,380 А тие само го додадете во формат спецификација. 93 00:05:50,380 --> 00:05:56,500 >> На пример, ако формат стринг во GetInt беа% d наместо тоа, 94 00:05:56,500 --> 00:05:59,800 sscanf ќе изгледа за писмо проследено со int, 95 00:05:59,800 --> 00:06:04,360 и додека тоа ќе се обиде да го конвертирате int, тоа не би сторил ништо друго со еден. 96 00:06:04,360 --> 00:06:07,440 Единствен исклучок на ова е празни места. 97 00:06:07,440 --> 00:06:11,030 Белата простор на знаци во формат стринг одговара на ниеден количината на празни места - 98 00:06:11,030 --> 00:06:12,890 дури нема воопшто. 99 00:06:12,890 --> 00:06:18,100 Значи, тоа е зошто коментар споменува евентуално со водечките и / или Аргументот. 100 00:06:18,100 --> 00:06:22,910 Значи, во овој момент изгледа нашата sscanf повик ќе се обиде да го анализирам внесување гудачки на корисникот 101 00:06:22,910 --> 00:06:25,380 со проверка за можни водечки празни места, 102 00:06:25,380 --> 00:06:29,300 проследено со int кој ќе се конвертира и се чуваат во int променлива n 103 00:06:29,300 --> 00:06:33,090 проследено со некои количината на празни места, и по карактер 104 00:06:33,090 --> 00:06:35,810 чуваат во знак променлива в. 105 00:06:35,810 --> 00:06:37,790 >> Што е повратната вредност? 106 00:06:37,790 --> 00:06:41,560 Sscanf ќе го анализира влезни линија од почеток до крај, 107 00:06:41,560 --> 00:06:44,860 запирање кога го достигне крајот или кога некој лик во влез 108 00:06:44,860 --> 00:06:49,320 не се поклопува формат карактер или кога тоа не може да се направи конверзија. 109 00:06:49,320 --> 00:06:52,690 Тоа е повратната вредност се користи за да издвојат кога тој престана. 110 00:06:52,690 --> 00:06:55,670 Ако го запре, бидејќи до крајот на внесување гудачки 111 00:06:55,670 --> 00:07:00,630 пред да направите било конверзии и пред неуспехот да одговара на дел од формат стринг, 112 00:07:00,630 --> 00:07:04,840 тогаш специјален постојан EOF се враќа. 113 00:07:04,840 --> 00:07:08,200 Во спротивно, го враќа бројот на успешни имплементацијата, 114 00:07:08,200 --> 00:07:14,380 која може да биде 0, 1 или 2, бидејќи ние сме праша за две конверзии. 115 00:07:14,380 --> 00:07:19,000 Во нашиот случај, ние сакаме да се осигураме дека корисникот ја внеле во int и само int. 116 00:07:19,000 --> 00:07:23,370 >> Значи, ние сакаме sscanf да се врати 1. Погледнете зошто? 117 00:07:23,370 --> 00:07:26,850 Ако sscanf врати 0, тогаш нема конверзии биле направени, 118 00:07:26,850 --> 00:07:31,690 па така корисниците внеле нешто друго од int на почетокот на влез. 119 00:07:31,690 --> 00:07:37,100 Ако sscanf враќа 2, тогаш корисникот не правилно да го напишете во почетокот на влез, 120 00:07:37,100 --> 00:07:41,390 но тие потоа ја внеле во некои карактер не-празни места потоа 121 00:07:41,390 --> 00:07:44,940 од% c конверзија успеа. 122 00:07:44,940 --> 00:07:49,570 Леле, тоа е прилично долга објаснување за еден повик на функција. 123 00:07:49,570 --> 00:07:53,460 Впрочем, ако сакате повеќе информации за sscanf и нејзините браќа и сестри, 124 00:07:53,460 --> 00:07:57,130 проверете на човекот страници, Гугл, или и двете. 125 00:07:57,130 --> 00:07:58,780 Постојат многу формат низа опции, 126 00:07:58,780 --> 00:08:03,830 и овие може да ве спаси многу физичка работа, кога се обидуваат да го анализирам жици во C. 127 00:08:03,830 --> 00:08:07,180 >> Конечниот функција во библиотеката да се погледне е GetString. 128 00:08:07,180 --> 00:08:10,310 Излегува дека GetString е слабо функција да се напише правилно, 129 00:08:10,310 --> 00:08:14,290 иако ми се чини дека таквата едноставна, заедничка задача. 130 00:08:14,290 --> 00:08:16,170 Зошто е тоа така? 131 00:08:16,170 --> 00:08:21,380 Па, ајде да размислиме за тоа како ние ќе ја зачувате линијата која на корисникот видови внатре 132 00:08:21,380 --> 00:08:23,880 Од низа е низа од карактери, 133 00:08:23,880 --> 00:08:26,430 ние можеби ќе сакате да се чува во низа на магацинот, 134 00:08:26,430 --> 00:08:31,250 но ние ќе треба да се знае колку долго низа ќе биде кога ќе се изјасни. 135 00:08:31,250 --> 00:08:34,030 Исто така, ако сакаме да го стави на куп, 136 00:08:34,030 --> 00:08:38,090 ние треба да помине Примерок бројот на бајти сакаме да ги резервирате, 137 00:08:38,090 --> 00:08:39,730 но тоа е невозможно. 138 00:08:39,730 --> 00:08:42,760 Ние немаме идеја како многу знаци на корисникот ќе тип во 139 00:08:42,760 --> 00:08:46,590 пред корисникот всушност не ги напишете. 140 00:08:46,590 --> 00:08:50,720 >> А наивниот решение за овој проблем е само да резервирам голем дел од просторот, да речеме, 141 00:08:50,720 --> 00:08:54,540 блок од 1000 карактери за внесување на корисникот, 142 00:08:54,540 --> 00:08:57,980 претпоставувајќи дека корисникот никогаш не би тип во низа која долго време. 143 00:08:57,980 --> 00:09:00,810 Ова е лоша идеја за две причини. 144 00:09:00,810 --> 00:09:05,280 Прво, претпоставувајќи дека корисниците обично не напишете стрингови кои долго, 145 00:09:05,280 --> 00:09:07,610 можете да отпад многу меморија. 146 00:09:07,610 --> 00:09:10,530 На современи машини, ова не може да биде проблем ако го направите тоа 147 00:09:10,530 --> 00:09:13,890 во една или две изолирани случаи, 148 00:09:13,890 --> 00:09:17,630 но ако сте земајќи влез корисникот во јамка и чување за подоцнежна употреба, 149 00:09:17,630 --> 00:09:20,870 ќе можете брзо да си го цица до еден тон на меморија. 150 00:09:20,870 --> 00:09:24,450 Покрај тоа, ако програмата сте пишување е за помал компјутер - 151 00:09:24,450 --> 00:09:28,100 уред како паметен телефон или нешто друго со ограничена меморија - 152 00:09:28,100 --> 00:09:32,060 ова решение ќе предизвика проблеми многу побрзо. 153 00:09:32,060 --> 00:09:36,450 Вториот, посериозни причина да не го направите ова е дека тоа остава вашата програма ранливи 154 00:09:36,450 --> 00:09:39,710 на она што се нарекува buffer overflow напад. 155 00:09:39,710 --> 00:09:45,840 Во програмирање, тампон е меморијата се користи за привремено чување влез или излез на податоци, 156 00:09:45,840 --> 00:09:48,980 кој во овој случај е нашата 1000-знак блок. 157 00:09:48,980 --> 00:09:53,370 А buffer overflow се случува кога податоците се напишани изминатите крајот на блок. 158 00:09:53,370 --> 00:09:57,790 >> На пример, ако корисникот всушност не тип во повеќе од 1000 карактери. 159 00:09:57,790 --> 00:10:01,570 Може да ги искусиле ова случајно кога програмирање со низи. 160 00:10:01,570 --> 00:10:05,620 Ако имате низа од 10 ints, ништо не ви запира од обидот да се прочита или запише 161 00:10:05,620 --> 00:10:07,810 15 int. 162 00:10:07,810 --> 00:10:10,000 Нема компајлерот предупредувања или грешки. 163 00:10:10,000 --> 00:10:13,250 Програмата исто грешки право напред и пристапи на меморија 164 00:10:13,250 --> 00:10:18,150 каде што смета дека 15 int ќе биде, а тоа може да го изгубите Вашиот другите варијабли. 165 00:10:18,150 --> 00:10:22,040 Во најлош случај, може да се запише некои од внатрешните вашата програма 166 00:10:22,040 --> 00:10:26,820 контролни механизми, предизвикувајќи вашиот програмата за всушност извршување различни инструкции 167 00:10:26,820 --> 00:10:28,340 отколку што се наменети. 168 00:10:28,340 --> 00:10:31,360 >> Сега, тоа не е заеднички да го направите ова случајно, 169 00:10:31,360 --> 00:10:35,150 но ова е прилично заеднички техника која лошите момци го користите да се пробие програми 170 00:10:35,150 --> 00:10:39,080 и го стави малициозен код на компјутери на други луѓе. 171 00:10:39,080 --> 00:10:42,910 Затоа, ние не може само да ги користат нашите наивни решение. 172 00:10:42,910 --> 00:10:45,590 Ние треба начин да се спречат нашите програми од се ранливи 173 00:10:45,590 --> 00:10:47,880 на buffer overflow напад. 174 00:10:47,880 --> 00:10:51,430 За да го направите ова, ние треба да бидете сигурни дека нашите тампон може да расте како што се чита 175 00:10:51,430 --> 00:10:53,850 повеќе влез од корисникот. 176 00:10:53,850 --> 00:10:57,440 Решението? Ние ги користиме на грамада распределени тампон. 177 00:10:57,440 --> 00:10:59,950 Бидејќи можеме да големината на тоа со помош на големината на realloc функција, 178 00:10:59,950 --> 00:11:04,580 и ние ги пратите на два броја - индексот на следната празен слот во тампон 179 00:11:04,580 --> 00:11:08,390 и должината или капацитетот на тампон. 180 00:11:08,390 --> 00:11:13,210 Читаме во карактери од корисникот едно по едно време со користење на fgetc функција. 181 00:11:13,210 --> 00:11:19,360 Аргументот на fgetc функција потребно - stdin - е повикување на стандарден влез стринг, 182 00:11:19,360 --> 00:11:23,810 која е preconnected внесување на канал кој се користи за пренос на внесување на корисникот 183 00:11:23,810 --> 00:11:26,270 од терминалот на програмата. 184 00:11:26,270 --> 00:11:29,890 >> Секогаш кога корисник видови во нов лик, ние се провери да се види дали на индексот 185 00:11:29,890 --> 00:11:35,810 на следниот слободен слот плус 1 е поголем од капацитетот на тампон. 186 00:11:35,810 --> 00:11:39,690 На 1 доаѓа во затоа што ако следниот слободен индекс е 5, 187 00:11:39,690 --> 00:11:44,150 тогаш должината нашите тампон мора да биде 6 благодарение 0 индексирање. 188 00:11:44,150 --> 00:11:48,350 Ако ние сме снема простор во тампон, а потоа ќе се обиде да ја промени големината, 189 00:11:48,350 --> 00:11:51,690 удвојување на тоа, така што можеме да го намали бројот на пати, што ние ја промените големината 190 00:11:51,690 --> 00:11:54,760 ако корисникот пишува во едно навистина долга низа. 191 00:11:54,760 --> 00:11:57,950 Ако стрингот има добивано и премногу долго или ако снема на грамада меморија, 192 00:11:57,950 --> 00:12:01,350 ние ослободи нашите тампон и враќање нула. 193 00:12:01,350 --> 00:12:04,170 >> Конечно, ние додаваат знак на тампон. 194 00:12:04,170 --> 00:12:08,200 Откако на корисникот хитови влезат или да се вратат, сигнализирајќи нова линија, 195 00:12:08,200 --> 00:12:12,050 или посебен знак - контрола г - кој сигнализира крајот на влез, 196 00:12:12,050 --> 00:12:16,240 ние направи проверка за да види дали на корисникот всушност ја внеле во нешто во сите. 197 00:12:16,240 --> 00:12:18,820 Ако не, ќе се вратиме нула. 198 00:12:18,820 --> 00:12:22,280 Инаку, бидејќи нашите тампон е веројатно поголема отколку што треба, 199 00:12:22,280 --> 00:12:24,830 во најлош случај тоа е речиси двапати поголем како што треба 200 00:12:24,830 --> 00:12:27,830 бидејќи ние двојно секој пат кога големината, 201 00:12:27,830 --> 00:12:31,840 правиме нова копија на стринг со користење само на износот на просторот што ни е потребно. 202 00:12:31,840 --> 00:12:34,220 Ние додаваме дополнителни 1 до Примерок повик, 203 00:12:34,220 --> 00:12:37,810 така што има простор за специјални null терминаторот карактер - на \ 0, 204 00:12:37,810 --> 00:12:41,990 кои додаваат до низа еднаш сме го копирате во остатокот од ликовите, 205 00:12:41,990 --> 00:12:45,060 користење strncpy наместо strcpy 206 00:12:45,060 --> 00:12:48,830 така што може да се определи точно колку карактери сакаме да го копирате. 207 00:12:48,830 --> 00:12:51,690 Strcpy копии, додека таа хитови \ 0. 208 00:12:51,690 --> 00:12:55,740 Тогаш ние ослободи нашите тампон и се врати на копија на повикувачот. 209 00:12:55,740 --> 00:12:59,840 >> Кој не знаеше како едноставна-навидум функција може да биде толку комплицирано? 210 00:12:59,840 --> 00:13:02,820 Сега знаеш што оди во CS50 библиотека. 211 00:13:02,820 --> 00:13:06,470 >> Моето име е Нејт Hardison, и ова е CS50. 212 00:13:06,470 --> 00:13:08,350 [CS50.TV]