1 00:00:00,000 --> 00:00:02,500 [Powered by Google Translate] [Secțiunea 5 - mai confortabil] 2 00:00:02,500 --> 00:00:04,690 [Rob Bowden - Universitatea Harvard] 3 00:00:04,690 --> 00:00:07,250 [Acest lucru este CS50. - CS50.TV] 4 00:00:08,990 --> 00:00:14,250 >> Cum am spus, în email-ul meu, există o mulțime de lucruri pe care le puteți utiliza 5 00:00:14,250 --> 00:00:17,060 altele decât aparatul pentru a face de fapt, seturi de probleme. 6 00:00:17,060 --> 00:00:19,910 Vă recomandăm să o faceți în aparat doar pentru că atunci ne putem mai ușor să te ajut 7 00:00:19,910 --> 00:00:22,070 și știm cum totul va merge. 8 00:00:22,070 --> 00:00:26,950 Dar, ca un exemplu de unde poti sa faci lucruri în cazul în care, spun, nu aveți acces la 9 00:00:26,950 --> 00:00:31,570 la un aparat sau dacă doriți să lucrați în subsol Science Center - 10 00:00:31,570 --> 00:00:33,090 care de fapt au aparat prea - 11 00:00:33,090 --> 00:00:35,150 în cazul în care doriți să lucrați oriunde. 12 00:00:35,150 --> 00:00:42,370 Un exemplu este ati vazut / auzit de SSH? 13 00:00:44,380 --> 00:00:47,780 SSH este de fapt la fel ca conecta la ceva. 14 00:00:47,780 --> 00:00:51,340 De fapt, chiar acum mă SSHed în aparat. 15 00:00:51,340 --> 00:00:54,290 N-am să lucrați direct în aparat. 16 00:00:55,930 --> 00:01:01,060 Aici este aparatul, iar daca te uiti aici veți vedea această adresă IP. 17 00:01:01,060 --> 00:01:03,650 N-am lucra în aparatul în sine; 18 00:01:03,650 --> 00:01:08,840 Eu vin mereu pe la o fereastră iTerm2 / terminal de fereastra. 19 00:01:08,840 --> 00:01:15,910 Poți SSH pentru că adresa IP, ssh jharvard@192.168.129.128. 20 00:01:15,910 --> 00:01:20,390 Îmi amintesc că numărul foarte ușor, pentru că este un astfel de model frumos. 21 00:01:20,390 --> 00:01:24,920 Dar asta mă va cere parola, iar acum eu sunt în aparat. 22 00:01:24,920 --> 00:01:33,060 Practic, în acest moment, în cazul în care aveți deschis un terminal interiorul aparatului în sine, 23 00:01:33,060 --> 00:01:36,350 această interfață, cu toate acestea v-ar folosi, este exact la fel 24 00:01:36,350 --> 00:01:40,010 ca interfață Sunt folosind aici, dar acum esti SSHed. 25 00:01:42,240 --> 00:01:44,920 Nu trebuie să SSH la aparatul. 26 00:01:44,920 --> 00:01:52,360 Un exemplu de un alt loc unde ar putea să SSH este Sunt destul de sigur că aveți în mod implicit - 27 00:01:52,360 --> 00:01:55,020 Oh. Mai mare. 28 00:01:55,020 --> 00:02:01,130 Toți ar trebui să aveți conturi de FAS implicit pe serverele FAS. 29 00:02:01,130 --> 00:02:06,840 Pentru mine, aș SSH la rbowden@nice.fas.harvard.edu. 30 00:02:06,840 --> 00:02:11,610 O să te întreb că prima dată, și tu spui da. 31 00:02:11,610 --> 00:02:15,840 Parola mea este doar de gând să fie parola mea FAS. 32 00:02:15,840 --> 00:02:22,650 Și acum, am SSHed la serverele frumos, si eu pot face orice vreau pe aici. 33 00:02:22,650 --> 00:02:28,560 O mulțime de clase s-ar putea lua, cum ar fi 124, sunt de gând să aibă de a încărca chestii de aici 34 00:02:28,560 --> 00:02:30,950 de fapt, să-și prezinte seturi de problema ta. 35 00:02:30,950 --> 00:02:34,100 Dar spune ca nu au acces la aparatul dumneavoastră. 36 00:02:34,100 --> 00:02:37,910 Apoi, puteți face lucruri, cum ar fi pe aici se va spune - 37 00:02:37,910 --> 00:02:42,160 Aceasta este doar secțiunea noastră de întrebări. 38 00:02:42,160 --> 00:02:45,070 Acesta vă va cere să faceți acest lucru în aparat. 39 00:02:45,070 --> 00:02:47,790 În schimb voi face doar pe server. 40 00:02:47,790 --> 00:02:50,560 Am de gând să unzip asta. 41 00:02:50,560 --> 00:02:55,670 Problema va fi că v-ați obișnuit să utilizați ceva de genul gedit 42 00:02:55,670 --> 00:02:58,160 sau orice interiorul aparatului. 43 00:02:58,160 --> 00:03:01,830 Nu te duci să aibă ca pe serverul de consultanță agricolă. 44 00:03:01,830 --> 00:03:04,110 E totul va fi doar această interfață text. 45 00:03:04,110 --> 00:03:09,180 Deci, ai putea fie una, încercați să învețe un editor de text pe care le posedam. 46 00:03:09,180 --> 00:03:12,130 Ei au Nano. 47 00:03:12,130 --> 00:03:14,990 Nano este, de obicei, destul de ușor de utilizat. 48 00:03:14,990 --> 00:03:19,470 Aveți posibilitatea să utilizați săgețile tale și tastați în mod normal. 49 00:03:19,470 --> 00:03:21,250 Așa că nu e greu. 50 00:03:21,250 --> 00:03:24,720 Dacă doriți să obțineți cu adevărat de lux puteti folosi Emacs, 51 00:03:24,720 --> 00:03:29,850 care, probabil, nu ar fi deschis pentru că nici măcar nu știu cum să închidă Emacs. 52 00:03:29,850 --> 00:03:32,760 De control X, de control C? Da. 53 00:03:32,760 --> 00:03:35,310 Sau puteți folosi Vim, care este ceea ce am folosi. 54 00:03:35,310 --> 00:03:37,800 Și astfel acestea sunt optiunile tale. 55 00:03:37,800 --> 00:03:43,830 Dacă nu vrei să faci asta, puteți, de asemenea, daca te uiti la manual.cs50.net-- 56 00:03:43,830 --> 00:03:45,410 Oh. 57 00:03:45,410 --> 00:03:49,920 Pe un PC, puteți SSH folosind PuTTY, 58 00:03:49,920 --> 00:03:51,940 care ai de gând să aibă de a descărca separat. 59 00:03:51,940 --> 00:03:55,460 Pe un Mac, puteți pur și simplu prin utilizarea Terminal implicit sau puteți descărca iTerm2, 60 00:03:55,460 --> 00:03:58,490 care este ca un terminal frumos, fantezie. 61 00:03:58,490 --> 00:04:03,780 Dacă te duci la manual.cs50.net veți vedea un link către Notepad + +, 62 00:04:03,780 --> 00:04:07,120 care este ceea ce se poate folosi pe un PC. 63 00:04:07,120 --> 00:04:13,340 Acesta vă permite să SFTP din Notepad + +, care este, în principiu SSH. 64 00:04:13,340 --> 00:04:17,750 Ceea ce vă va permite să faceți este să editați fișiere local, 65 00:04:17,750 --> 00:04:20,670 și apoi ori de câte ori doriți să le salvați, acesta va salva în nice.fas, 66 00:04:20,670 --> 00:04:23,670 în cazul în care puteți rula apoi le. 67 00:04:23,670 --> 00:04:26,880 Și echivalentul pe un Mac va fi TextWrangler. 68 00:04:26,880 --> 00:04:28,760 Deci, vă permite să faceți același lucru. 69 00:04:28,760 --> 00:04:32,800 Acesta vă permite să editați fișiere local și salvați-le la nice.fas, 70 00:04:32,800 --> 00:04:35,730 în cazul în care puteți rula apoi le. 71 00:04:35,730 --> 00:04:40,400 Deci, dacă sunteți vreodată blocat, fără un aparat, aveți aceste opțiuni 72 00:04:40,400 --> 00:04:44,230 încă de a face seturi de problema ta. 73 00:04:44,230 --> 00:04:48,250 Singura problemă va fi că nu sunteți de gând să aibă bibliotecă CS50 74 00:04:48,250 --> 00:04:51,580 deoarece nice.fas nu are în mod implicit că are. 75 00:04:51,580 --> 00:04:55,970 Puteți descărca fie biblioteca CS50 - 76 00:04:55,970 --> 00:04:58,470 Nu cred că am nevoie de la acest punct. 77 00:04:58,470 --> 00:05:03,270 Puteți descărca fie biblioteca CS50 și copiați-l pe nice.fas, 78 00:05:03,270 --> 00:05:07,450 sau cred că în acest moment nu-l utilizați mai oricum. 79 00:05:07,450 --> 00:05:12,720 Sau dacă o facem, puteți pentru moment înlocuiți-l cu 80 00:05:12,720 --> 00:05:18,480 implementările de funcții în biblioteca CS50 oricum. 81 00:05:18,480 --> 00:05:21,370 Așa că nu ar trebui să fie faptul că de mult de o restricție. 82 00:05:21,370 --> 00:05:23,710 Și cu asta basta. 83 00:05:26,460 --> 00:05:29,820 >> Mă duc înapoi la aparatul acum, vom face totul în aparat. 84 00:05:29,820 --> 00:05:37,510 Privind la secțiunea noastră de întrebări, la început, așa cum am spus în email-ul meu, 85 00:05:37,510 --> 00:05:43,620 trebuie sa vorbim despre scurt cel pe care ar fi trebuit sa ma uit. 86 00:05:43,620 --> 00:05:51,980 Avem redirecționarea & Țevi și aceste trei întrebări. 87 00:05:51,980 --> 00:05:56,070 >> Pentru ce curs de apa nu funcționează cum ar fi printf scrie în mod implicit? 88 00:05:56,070 --> 00:05:59,130 Deci curs de apa. Ce este un curs de apa? 89 00:06:06,520 --> 00:06:15,100 Un curs de apa este de fapt ca e doar o - 90 00:06:15,100 --> 00:06:21,450 Nu e chiar o sursă de 1s și 0s. 91 00:06:21,450 --> 00:06:24,920 Curs de apa se cere aici este în afara standard. 92 00:06:24,920 --> 00:06:27,250 Și așa de iarnă este un curs de apa, care, atunci când scrie în ea, 93 00:06:27,250 --> 00:06:30,940 apare pe ecran. 94 00:06:30,940 --> 00:06:36,860 Out standard, prin curs de apa, aceasta înseamnă că scrie doar 1 si 0 la acesta, 95 00:06:36,860 --> 00:06:40,220 și celălalt capăt al out standard, doar se citește de la care curge. 96 00:06:40,220 --> 00:06:43,540 E doar un șir de 1 si 0. 97 00:06:43,540 --> 00:06:45,570 Puteți scrie la fluxuri sau puteți citi la fluxurile 98 00:06:45,570 --> 00:06:47,950 în funcție de ceea ce este de fapt curs de apa. 99 00:06:47,950 --> 00:06:52,800 Celelalte două fluxuri implicite sunt standard în și eroarea standard. 100 00:06:52,800 --> 00:06:57,540 Standard în ori de câte ori este faci getString, se așteaptă să chestii de intrare. 101 00:06:57,540 --> 00:07:01,570 Așa că vă așteaptă, este de fapt, așteaptă standard în, 102 00:07:01,570 --> 00:07:04,880 care este într-adevăr ceea ce obții atunci când tastați la tastatura. 103 00:07:04,880 --> 00:07:07,530 Te tastarea în iarnă inch 104 00:07:07,530 --> 00:07:10,050 Eroarea standard este de fapt echivalent cu standardul afară, 105 00:07:10,050 --> 00:07:13,280 dar e specializată în că, atunci când imprimați eroarea standard, 106 00:07:13,280 --> 00:07:16,770 tu ar trebui să imprimați numai mesaje de eroare la 107 00:07:16,770 --> 00:07:20,200 astfel încât să puteți diferenția între mesaje periodice tipărite la ecran 108 00:07:20,200 --> 00:07:24,560 comparativ cu mesaje de eroare, în funcție de faptul dacă s-au dus la out standard sau eroarea standard. 109 00:07:24,560 --> 00:07:28,660 Fișiere prea. 110 00:07:28,660 --> 00:07:32,440 Out standard, standard în, și eroarea standard sunt fluxuri de doar speciale, 111 00:07:32,440 --> 00:07:36,810 dar de fapt orice fișier, atunci când deschideți un fișier, acesta devine un curs de apa de octeți 112 00:07:36,810 --> 00:07:40,740 în cazul în care puteți citi doar de la acel curs de apa. 113 00:07:40,740 --> 00:07:47,770 Tu, pentru cea mai mare parte, se poate gândi doar a unui fișier ca un flux de octeti. 114 00:07:47,770 --> 00:07:51,190 Deci, fluxuri ce se scrie în mod implicit? Standard afară. 115 00:07:51,190 --> 00:07:56,980 >> Care este diferența între> și >>? 116 00:07:58,140 --> 00:08:03,710 Credeți cineva a viziona videoclipul în prealabil? Bine. 117 00:08:03,710 --> 00:08:10,960 > Va fi modul în care redirecționați în fișiere, 118 00:08:10,960 --> 00:08:15,240 și, de asemenea, se va >> pentru a redirecționa de ieșire în fișiere, 119 00:08:15,240 --> 00:08:17,820 dar e loc de gând să anexeze la dosar. 120 00:08:17,820 --> 00:08:23,430 De exemplu, să presupunem că se întâmplă să aibă dict chiar aici, 121 00:08:23,430 --> 00:08:27,020 și chestii doar în interiorul dict este pisica, pisica, caine, pește, câine. 122 00:08:27,020 --> 00:08:31,530 O singură comandă pe care le avea la linia de comandă este pisica, 123 00:08:31,530 --> 00:08:34,539 care este doar de gând să imprima ceea ce este într-un fișier. 124 00:08:34,539 --> 00:08:40,679 Deci, atunci când spun dict pisica, o să imprimați pisica, pisica, caine, pește, câine. Asta e tot ce face pisica. 125 00:08:40,679 --> 00:08:46,280 Asta înseamnă că imprimat cu standardul din pisica, pisica, caine, pește, câine. 126 00:08:46,280 --> 00:08:53,240 Dacă eu vreau să redirecționeze în schimb faptul că într-un fișier, pot folosi> și redirecționarea-l la orice fisier este. 127 00:08:53,240 --> 00:08:56,460 Voi suna fișierul fișierul. 128 00:08:56,460 --> 00:09:00,320 Deci, acum, dacă I ​​ls, voi vedea am un nou fisier numit fișier. 129 00:09:00,320 --> 00:09:05,700 Și dacă l-am deschis, acesta va avea exact ceea ce pisica pune la linia de comandă. 130 00:09:05,700 --> 00:09:11,040 Deci, acum, dacă eu fac asta din nou, atunci va redirecționa de ieșire într-un fișier, 131 00:09:11,040 --> 00:09:13,930 și am de gând să aibă exact acelasi lucru. 132 00:09:13,930 --> 00:09:17,910 Deci punct de vedere tehnic, aceasta complet anulate ceea ce am avut. 133 00:09:17,910 --> 00:09:22,970 Și vom vedea dacă am schimba dict, am scos câinele. 134 00:09:22,970 --> 00:09:29,980 Acum, dacă am pisica dict într-un fișier din nou, vom avea noua versiune cu câinele eliminat. 135 00:09:29,980 --> 00:09:32,400 Așa că-l suprascrie complet. 136 00:09:32,400 --> 00:09:36,640 În schimb, dacă vom folosi >>, o să adăugați fișierul. 137 00:09:36,640 --> 00:09:40,860 Acum, deschide fișierul, vedem avem doar același lucru de două ori tipărite 138 00:09:40,860 --> 00:09:44,920 pentru că a fost acolo o dată, apoi am anexat la original. 139 00:09:44,920 --> 00:09:48,130 Deci, asta e ceea ce> si >> face. 140 00:09:48,130 --> 00:09:50,580 Are urmatorul cere - Nu întreba despre asta. 141 00:09:50,580 --> 00:09:59,050 >> Celălalt pe care o avem este <, care, dacă> redirecționează afară de iarnă, 142 00:09:59,050 --> 00:10:01,970 00:10:12,050 Să vedem dacă avem un exemplu. 144 00:10:14,750 --> 00:10:16,930 Pot să scriu unul foarte repede. 145 00:10:17,870 --> 00:10:25,700 Să luăm orice fișier, hello.c. 146 00:10:56,060 --> 00:10:59,070 Relativ simplă fișier. 147 00:10:59,070 --> 00:11:03,570 Primesc doar un șir și apoi tipărirea "Bună ziua", oricare ar fi șirul tocmai am intrat a fost. 148 00:11:03,570 --> 00:11:07,990 Deci, asigurați-Bună ziua și apoi / salut.. 149 00:11:07,990 --> 00:11:10,720 Acum ma determinat să intre ceva, 150 00:11:10,720 --> 00:11:15,070 ceea ce înseamnă că se așteaptă ca lucrurile să fie introduse în standardul inch 151 00:11:15,070 --> 00:11:20,450 Deci, ce vreau să introduceți în iarnă inch Vom doar de gând să spun Bună ziua, Rob! 152 00:11:20,450 --> 00:11:23,310 Atunci e imprimarea cu standardul afară Salut, Rob! 153 00:11:23,310 --> 00:11:28,860 Dacă fac / salut. Și apoi redirecționați, 154 00:11:30,740 --> 00:11:34,310 De acum puteți redirecționa numai dintr-un fișier. 155 00:11:34,310 --> 00:11:41,720 Deci, dacă am pus într-un dosar, txt, și am pus Rob, 156 00:11:41,720 --> 00:11:52,300 dacă am alerga salut și apoi redirecționați fișier txt în. / Bună ziua, o să spun Bună ziua, Rob! imediat. 157 00:11:52,300 --> 00:11:57,160 Când se ajunge la primul getString și-l așteaptă pe standard în, 158 00:11:57,160 --> 00:12:01,730 standard în nu mai așteaptă pe tastatură pentru a obține datele introduse. 159 00:12:01,730 --> 00:12:05,980 În schimb, ne-am redirecționat standard pentru a citi din fisier txt. 160 00:12:05,980 --> 00:12:10,290 Și așa se va citi din fisierul txt, care este doar Rob linie, 161 00:12:10,290 --> 00:12:13,380 și apoi o să imprimați Salut, Rob! 162 00:12:13,380 --> 00:12:18,180 Și dacă am vrut, aș putea face, de asemenea. / Bună ziua 00:12:21,500 și apoi standard, că e de imprimare, care este Buna ziua, Rob!, 164 00:12:21,500 --> 00:12:24,700 Eu pot redirecționa că în dosarul său. 165 00:12:24,700 --> 00:12:29,790 Voi suna doar fișierul salut - nu, nu voi, pentru că e executabil - txt2. 166 00:12:29,790 --> 00:12:40,150 Acum, txt2 va avea ieșire de / salut. 00:12:43,520 >> Întrebări? 168 00:12:45,900 --> 00:12:49,090 >> Bine. Deci aici avem de conducte. 169 00:12:49,090 --> 00:12:53,510 Țevile sunt ultima unitate de redirecționare. 170 00:12:53,510 --> 00:12:58,750 >> Oh. Cred că o unitate de redirectionare este mai în cazul în care în loc de> ce faci 2>, 171 00:12:58,750 --> 00:13:01,070 care este redirecționarea eroarea standard. 172 00:13:01,070 --> 00:13:06,280 Deci, în cazul în care ceva nu a mers la eroarea standard, aceasta nu ar fi pus în txt2. 173 00:13:06,280 --> 00:13:12,480 Dar observați dacă fac 2>, apoi se imprimă încă Salut, Rob! la linia de comandă 174 00:13:12,480 --> 00:13:18,600 pentru că eu sunt doar redirecționarea eroare standard, nu am redirecționarea standard de afară. 175 00:13:18,600 --> 00:13:22,210 Eroarea standard și din iarnă sunt diferite. 176 00:13:24,210 --> 00:13:27,080 Dacă ați fi dorit să scrie de fapt la eroarea standard, 177 00:13:27,080 --> 00:13:35,080 apoi am putea schimba acest lucru să fie fprintf la stderr. 178 00:13:35,080 --> 00:13:37,850 Deci printf, implicit, pentru a imprima în standard. 179 00:13:37,850 --> 00:13:41,720 Dacă vreau să imprimați eroare standard manual, atunci trebuie sa folosesc fprintf 180 00:13:41,720 --> 00:13:45,010 și să specifice ceea ce vreau să imprimați. 181 00:13:45,010 --> 00:13:49,720 Dacă în schimb am făcut stdout fprintf, atunci asta e practic echivalent cu printf. 182 00:13:49,720 --> 00:13:55,530 Dar fprintf la eroarea standard. 183 00:13:57,790 --> 00:14:03,650 Deci, acum, dacă aș redirecționa acest lucru în txt2, Buna, ziua, Rob! este încă obtinerea tipărită la linia de comandă 184 00:14:03,650 --> 00:14:08,270 din moment ce din ce in ce tipărite la eroarea standard și eu sunt doar redirecționarea standard de afară. 185 00:14:08,270 --> 00:14:16,420 Dacă aș redirecționa acum eroarea standard, acum aceasta nu sa imprimat, și txt2 va fi Salut, Rob! 186 00:14:16,420 --> 00:14:21,910 Deci, acum, aveți posibilitatea de a imprima erorile tale reale de a erorii standard 187 00:14:21,910 --> 00:14:24,720 și imprimați mesajele dvs. regulate pentru a out standard. 188 00:14:24,720 --> 00:14:31,420 Și așa, atunci când rulați programul tău, îl puteți rula ca / ​​salut. Acest tip cu 2> 189 00:14:31,420 --> 00:14:33,800 astfel că programul dvs. este de gând să ruleze în mod normal, 190 00:14:33,800 --> 00:14:38,400 dar orice mesaje de eroare pe care le veți obține puteți verifica mai târziu în jurnalul de erori de dvs., 191 00:14:38,400 --> 00:14:44,500 atât de erori, si uita-te apoi mai târziu și fișierul erori va avea orice erori care au avut loc. 192 00:14:45,200 --> 00:14:47,540 >> Întrebări? 193 00:14:47,540 --> 00:14:58,070 >> Ultima este țeavă, pe care vă puteți gândi ca ia standard, de la o comandă 194 00:14:58,070 --> 00:15:01,210 și făcându-l standard în al următoarea comandă. 195 00:15:01,210 --> 00:15:05,570 Un exemplu este aici ecoul este o linie de lucru de comandă 196 00:15:05,570 --> 00:15:11,840 care este doar de gând să răsune tot ce mi-am pus ca argument. Nu voi pune ghilimele. 197 00:15:11,840 --> 00:15:16,150 Echo bla, bla, bla este doar de gând să imprima bla, bla, bla. 198 00:15:16,150 --> 00:15:20,600 Înainte, când am spus că trebuie să pun Rob într-un fișier txt 199 00:15:20,600 --> 00:15:28,830 pentru că eu pot redirecționa numai fișiere txt, în schimb, / dacă aș repeta Rob 200 00:15:28,830 --> 00:15:35,520 și apoi țeava l în / Bună ziua, care va face, de asemenea, același tip de lucru.. 201 00:15:35,520 --> 00:15:39,160 Acest lucru este de a lua de ieșire a acestei comenzi, echo Rob, 202 00:15:39,160 --> 00:15:43,610 și folosindu-l ca intrare pentru / salut.. 203 00:15:44,790 --> 00:15:49,560 Vă puteți gândi la ea ca redirect primul ecou Rob într-un fișier 204 00:15:49,560 --> 00:15:54,160 și apoi de intrare în / salut. că fișierul care tocmai a fost scoase. 205 00:15:54,160 --> 00:15:57,850 Dar este nevoie de fișier temporar din imagine. 206 00:16:01,890 --> 00:16:04,460 >> Întrebări cu privire la asta? 207 00:16:04,460 --> 00:16:07,150 >> Următoarea întrebare este de gând să implice acest lucru. 208 00:16:07,150 --> 00:16:15,310 Ce ai putea folosi conducta pentru a găsi numărul de nume unice într-un fișier numit names.txt? 209 00:16:15,310 --> 00:16:24,160 Comenzile noi de gând să doriți să utilizați aici sunt unice, atât de Uniq, și apoi WC. 210 00:16:24,160 --> 00:16:28,840 Puteți face Uniq omul să se uite la ceea ce de fapt care face, 211 00:16:28,840 --> 00:16:34,840 și este doar de gând pentru a filtra linii adiacente care se potrivesc de la intrare. 212 00:16:34,840 --> 00:16:40,690 Și omul WC este de gând să imprime cuvântul linie noua,, și numărul de octet pentru fiecare fișier. 213 00:16:40,690 --> 00:16:43,760 Și ultima am de gând să doriți să utilizați un fel, 214 00:16:43,760 --> 00:16:47,410 care este de gând să sortați doar linii de fișier txt. 215 00:16:47,410 --> 00:16:58,080 Dacă aș face un fisier txt, names.txt, și e Rob, Tommy, Iosif, Tommy, Iosif, RJ, Rob, 216 00:16:58,080 --> 00:17:03,910 ceea ce vreau să fac aici este să găsim numărul de nume unice în acest fișier. 217 00:17:03,910 --> 00:17:08,750 Deci, ce ar trebui să fie răspunsul? >> [Elev] 4. Da >>. 218 00:17:08,750 --> 00:17:13,780 Ar trebui să fie 4, deoarece Rob, Tommy, Iosif, RJ sunt numai nume unice în acest fișier. 219 00:17:13,780 --> 00:17:20,180 Primul pas, dacă eu fac doar numărul de cuvinte pe names.txt, 220 00:17:20,180 --> 00:17:24,290 acest lucru este, de fapt spune-mi totul. 221 00:17:24,290 --> 00:17:32,560 Aceasta este de fapt de imprimare - Să vedem, omule WC - rânduri libere, cuvinte, și numărul de octet. 222 00:17:32,560 --> 00:17:38,270 Dacă îmi pasă doar de linii, atunci eu pot face doar wc-am names.txt. 223 00:17:41,730 --> 00:17:44,300 Deci, asta e pasul 1. 224 00:17:44,300 --> 00:17:50,510 Dar eu nu vreau să-l names.txt wc, deoarece conține doar names.txt toate numele, 225 00:17:50,510 --> 00:17:54,170 și vreau să filtreze nici pe cele non-unice. 226 00:17:54,170 --> 00:18:01,200 Deci, dacă am face Uniq names.txt, care nu dă chiar mi ceea ce vreau 227 00:18:01,200 --> 00:18:03,760 deoarece numele duplicate sunt încă acolo. 228 00:18:03,760 --> 00:18:07,690 De ce este asta? De ce nu Uniq face ceea ce vreau? 229 00:18:07,690 --> 00:18:10,500 [Elev] duplicate nu sunt [neauzit] >> Da. 230 00:18:10,500 --> 00:18:16,370 Amintiți-vă pagina de manual pentru Uniq spune filtrul de linii adiacente de potrivire. 231 00:18:16,370 --> 00:18:19,680 Ei nu sunt adiacente, așa că nu le va filtra. 232 00:18:19,680 --> 00:18:31,100 Dacă eu le sorta în primul rând, names.txt sortare se va pune toate liniile duplicat împreună. 233 00:18:31,100 --> 00:18:34,450 Deci, acum names.txt fel este faptul că. 234 00:18:34,450 --> 00:18:40,550 Am de gând să doriți să utilizați că, de intrare la Uniq, care este | Uniq. 235 00:18:40,550 --> 00:18:43,390 Asta îmi dă Iosif, RJ, Rob, Tommy, 236 00:18:43,390 --> 00:18:49,260 și vreau să folosesc ca intrare pentru wc-L, 237 00:18:49,260 --> 00:18:52,740 care este de gând să-mi dea 4. 238 00:18:52,740 --> 00:18:56,930 Ca se spune aici, ce ai putea folosi conducta? 239 00:18:56,930 --> 00:19:01,390 Puteți face o mulțime de lucruri cum ar fi folosind o serie de comenzi 240 00:19:01,390 --> 00:19:05,130 în cazul în care vă folosiți de ieșire dintr-o comandă ca intrare pentru următoarea comandă. 241 00:19:05,130 --> 00:19:08,780 Puteți face o mulțime de lucruri, o mulțime de lucruri inteligente. 242 00:19:08,780 --> 00:19:11,440 >> Întrebări? 243 00:19:12,910 --> 00:19:14,600 Bine. 244 00:19:14,600 --> 00:19:17,880 Asta e. pentru conducte și redirecționarea. 245 00:19:18,370 --> 00:19:24,090 >> Acum mergem pe lucruri reale, chestii de codificare. 246 00:19:24,090 --> 00:19:29,100 În interiorul acestei PDF, veți vedea această comandă, 247 00:19:29,100 --> 00:19:32,950 și veți dori să rulați această comandă în aparatul. 248 00:19:36,240 --> 00:19:42,250 wget este comanda pentru a obține ceva de pe Internet, în esență, 249 00:19:42,250 --> 00:19:45,180 atât de wget și această adresă URL. 250 00:19:45,180 --> 00:19:49,110 Dacă te-ai dus la această adresă URL în browser-ul dumneavoastră, s-ar descărca acest fișier. 251 00:19:49,110 --> 00:19:52,510 Tocmai am dat click pe el, așa că descărcat fișierul pentru mine. 252 00:19:52,510 --> 00:19:55,650 Dar scris wget de chestia aia interiorul terminalului 253 00:19:55,650 --> 00:19:58,620 este doar de gând să-l descărcați în terminalul. 254 00:19:58,620 --> 00:20:02,750 Am section5.zip, și veți dori să dezarhivați section5.zip, 255 00:20:02,750 --> 00:20:06,520 care este de gând să vă dau un folder numit punctului 5, 256 00:20:06,520 --> 00:20:11,550 care va avea toate fișierele care le vom folosi astăzi în interiorul acestuia. 257 00:20:33,380 --> 00:20:37,710 Ca nume de aceste programe "File sugerează, acestea sunt un pic buggy, 258 00:20:37,710 --> 00:20:40,990 astfel încât misiunea ta este să dau seama de ce folosind gdb. 259 00:20:40,990 --> 00:20:44,560 Are toată lumea le-au descărcat / știi cum să-i mai descărcat 260 00:20:44,560 --> 00:20:47,480 în aparat lor? Bine. 261 00:20:47,480 --> 00:20:56,400 >> Rularea ./buggy1, acesta va spune Segmentation fault (core fac obiectul unui dumping), 262 00:20:56,400 --> 00:21:00,500 care în orice moment veți obține o segfault, e un lucru rău. 263 00:21:00,500 --> 00:21:03,810 În ce condiții puteți obține un segfault? 264 00:21:03,810 --> 00:21:08,210 [Elev] Dereferencing un pointer nul. Da >>. Așa că este un exemplu. 265 00:21:08,210 --> 00:21:11,580 Dereferencing un pointer nul ai de gând pentru a obține o segfault. 266 00:21:11,580 --> 00:21:16,720 Ce segfault mijloc este ce te atingi de memorie pe care nu ar trebui să fie ating. 267 00:21:16,720 --> 00:21:21,350 Dereferencing Deci, un pointer nul se atinge adresa 0, 268 00:21:21,350 --> 00:21:28,060 și, practic, toate computerele din zilele noastre spun că 0 este adresa de memorie pe care nu ar trebui să fie ating. 269 00:21:28,060 --> 00:21:31,920 Deci, de aceea dereferencing un rezultat nul indicatorul într-o segfault. 270 00:21:31,920 --> 00:21:37,210 Atunci când se întâmplă, nu pentru a inițializa un pointer, atunci aceasta are o valoare de gunoi, 271 00:21:37,210 --> 00:21:41,520 și așa mai departe, atunci când încercați să-l dereference, după toate probabilitățile, ce te atingi de memorie 272 00:21:41,520 --> 00:21:43,540 că e în mijlocul pustietății. 273 00:21:43,540 --> 00:21:45,650 Dacă se întâmplă să am noroc și valoarea de gunoi 274 00:21:45,650 --> 00:21:48,440 sa întâmplat să indice undeva pe stivă sau ceva, 275 00:21:48,440 --> 00:21:50,820 atunci când dereference că indicatorul care nu ați inițializat, 276 00:21:50,820 --> 00:21:52,730 nimic nu va merge prost. 277 00:21:52,730 --> 00:21:55,480 Dar dacă e îndreptat, să zicem, undeva între stivă și heap, 278 00:21:55,480 --> 00:21:59,850 sau este îndreptat doar pentru undeva că nu a fost folosit de programul tău încă, 279 00:21:59,850 --> 00:22:02,240 atunci esti atingi de memorie pe care nu ar trebui să fie atingerea și tu segfault. 280 00:22:02,240 --> 00:22:06,370 Când scrieți o funcție recursivă și recurses de prea multe ori 281 00:22:06,370 --> 00:22:08,720 și stack-ul creste prea mare și se loveste stivei în lucruri 282 00:22:08,720 --> 00:22:12,270 că nu ar trebui să fie coliziunea cu, te atingi de memorie pe care nu ar trebui să fie atingerea, 283 00:22:12,270 --> 00:22:14,810 astfel încât să segfault. 284 00:22:14,810 --> 00:22:17,010 Asta este ceea ce o segfault este. 285 00:22:17,010 --> 00:22:21,810 >> Este, de asemenea, din același motiv că, dacă aveți un șir cum ar fi - 286 00:22:21,810 --> 00:22:23,930 hai să ne întoarcem la programul anterior. 287 00:22:23,930 --> 00:22:28,530 În hello.c--Sunt doar de gând să facă altceva. 288 00:22:28,530 --> 00:22:33,770 char * s = "Hello World!"; 289 00:22:33,770 --> 00:22:42,310 Dacă am folosi * s = ceva sau s [0] = "X"; 290 00:22:42,310 --> 00:22:47,290 asa ca salut, / Buna ziua., de ce a făcut asta segfault? 291 00:22:48,410 --> 00:22:51,250 De ce a făcut asta segfault? 292 00:22:55,660 --> 00:22:57,890 Ce v-ar aștepta să se întâmple? 293 00:22:57,890 --> 00:23:06,640 Dacă am făcut printf ("% s \ n", s); ceea ce ați aștepta să fie tipărite? 294 00:23:06,640 --> 00:23:09,930 [Elev] X salut. Da >>. 295 00:23:09,930 --> 00:23:15,140 Problema este că, atunci când declară un șir de acest fel, 296 00:23:15,140 --> 00:23:18,190 s este un pointer care este de gând să meargă în stivă, 297 00:23:18,190 --> 00:23:25,880 și ceea ce s indică spre este acest șir de care este conținută în memorie read-only. 298 00:23:25,880 --> 00:23:30,560 Deci, doar de nume, memorie read-only, trebuie să obțineți o idee 299 00:23:30,560 --> 00:23:33,010 că, dacă încercați să schimbați ceea ce e în memorie read-only, 300 00:23:33,010 --> 00:23:36,670 faci ceva ce nu ar trebui să faci și tu cu memorie segfault. 301 00:23:36,670 --> 00:23:45,360 Aceasta este de fapt o mare diferenta intre char * s și s char []. 302 00:23:45,360 --> 00:23:48,790 Deci, char s [], acum acest șir va fi pus pe stivă, 303 00:23:48,790 --> 00:23:53,960 și stiva nu este doar în citire, ceea ce înseamnă că ar trebui să funcționeze perfect această regulă. 304 00:23:55,500 --> 00:23:57,370 Și-l face. 305 00:23:57,370 --> 00:24:06,250 Amintiți-vă că, atunci când fac char * s = "Hello World!", E în sine este pe stiva 306 00:24:06,250 --> 00:24:10,390 dar subliniază s în altă parte, și că în altă parte se întâmplă să fie doar în citire. 307 00:24:10,390 --> 00:24:15,640 Dar char s [] este doar ceva pe stiva. 308 00:24:17,560 --> 00:24:21,760 Deci, asta e un alt exemplu de segfault întâmplă. 309 00:24:21,760 --> 00:24:27,820 >> Am văzut că ./buggy1 a dus la o segfault. 310 00:24:27,820 --> 00:24:31,810 În teorie, nu ar trebui să se uite la buggy1.c imediat. 311 00:24:31,810 --> 00:24:35,170 În schimb, ne vom uita la ea prin gdb. 312 00:24:35,170 --> 00:24:37,750 Observați că atunci când vei ajunge Segmentation fault (core fac obiectul unui dumping), 313 00:24:37,750 --> 00:24:40,850 te acest fișier peste miezul aici sunat. 314 00:24:40,850 --> 00:24:45,200 Dacă ne ls-l, vom vedea că de bază este, de obicei, un fișier destul de mare. 315 00:24:45,200 --> 00:24:51,580 Acesta este numărul de octeți din dosar, astfel încât se pare că e ceva 250-kilobytes. 316 00:24:51,580 --> 00:24:56,120 Motivul pentru aceasta este că ceea ce haldei de bază este de fapt 317 00:24:56,120 --> 00:25:01,410 este atunci când dumneavoastră program se blochează, starea de memorie a programului 318 00:25:01,410 --> 00:25:05,230 doar se copiate și lipite în acest fișier. 319 00:25:05,230 --> 00:25:07,270 Ea devine aruncat în acel fișier. 320 00:25:07,270 --> 00:25:13,060 Acest program, în timp ce fugea, sa întâmplat să aibă o memorie usage de aproximativ 250 kilobiți, 321 00:25:13,060 --> 00:25:17,040 și pentru ca e ceea ce a fost aruncat în acest fișier. 322 00:25:17,040 --> 00:25:23,630 Acum poti sa te uiti la acel fișier, dacă facem gdb de bază buggy1. 323 00:25:23,630 --> 00:25:30,130 Putem face doar gdb buggy1, și că va începe doar până gdb în mod regulat, 324 00:25:30,130 --> 00:25:33,800 folosind buggy1 ca fișier de intrare său. 325 00:25:33,800 --> 00:25:38,260 Dar dacă ai face gdb de bază buggy1, apoi se va în mod special pentru a porni gdb 326 00:25:38,260 --> 00:25:40,330 uitandu-se la faptul că fișierul de bază. 327 00:25:40,330 --> 00:25:45,560 Și tu spui buggy1 gdb înseamnă știe că fișierul de bază vine de la programul de buggy1. 328 00:25:45,560 --> 00:25:49,580 Deci, gdb buggy1 de bază se va aduce imediat ne 329 00:25:49,580 --> 00:25:52,060 pentru a în cazul în care programul sa întâmplat de a rezilia. 330 00:25:57,720 --> 00:26:02,340 Vedem aici programul încheiată cu semnal 11, Segmentation fault. 331 00:26:02,340 --> 00:26:10,110 Se întâmplă să vedem o linie de asamblare, care, probabil, nu este de foarte mare ajutor. 332 00:26:10,110 --> 00:26:15,360 Dar, dacă tastați BT sau backtrace, care va fi funcția de 333 00:26:15,360 --> 00:26:19,430 care ne dă lista de cadre noastre actuale stivă. 334 00:26:19,430 --> 00:26:23,150 Deci, backtrace. Se pare că avem doar două cadre stack. 335 00:26:23,150 --> 00:26:26,310 Primul este cadrul nostru principal stivă, 336 00:26:26,310 --> 00:26:29,810 iar al doilea este cadru stivă pentru această funcție, care se întâmplă să fie în, 337 00:26:29,810 --> 00:26:34,440 care arata ca avem doar cod de asamblare pentru. 338 00:26:34,440 --> 00:26:38,050 Așa că hai să mergem înapoi în funcție nostru principal, 339 00:26:38,050 --> 00:26:42,300 și pentru a face ca putem face cadru 1, și cred că putem face, de asemenea, în jos, 340 00:26:42,300 --> 00:26:45,160 dar eu niciodată nu fac aproape în jos - sau în sus. Da. 341 00:26:45,160 --> 00:26:50,710 În sus și în jos. Până va aduce la un cadru stivă, care se va aduce în jos un cadru stivă. 342 00:26:50,710 --> 00:26:53,240 Eu tind să nu utilizeze niciodată asta. 343 00:26:53,240 --> 00:26:59,120 Eu doar spun în mod specific cadru 1, care se trece la cadrul etichetat 1. 344 00:26:59,120 --> 00:27:01,750 Cadrul 1 este de gând să ne aducă în cadrul stivă principal, 345 00:27:01,750 --> 00:27:05,570 și se spune chiar aici linie de cod se întâmplă să fie la. 346 00:27:05,570 --> 00:27:07,950 Dacă ne-am dorit un cuplu mai multe linii de cod, putem spune listă, 347 00:27:07,950 --> 00:27:11,280 și care va să ne dea toate liniile de cod în jurul ei. 348 00:27:11,280 --> 00:27:13,360 Linia ne segfaulted a fost de 6 la: 349 00:27:13,360 --> 00:27:17,360 în cazul în care (strcmp ("CS50 pietre", argv [1]) == 0). 350 00:27:17,360 --> 00:27:24,130 În cazul în care nu este evident încă, puteți să-l direct de aici doar de gândesc de ce-l segfaulted. 351 00:27:24,130 --> 00:27:28,800 Dar ne putem lua un pas mai departe și spune, "De ce ar argv [1] segfault?" 352 00:27:28,800 --> 00:27:38,830 Imprimare Să argv [1], si se pare ca e 0x0, care este pointer nul. 353 00:27:38,830 --> 00:27:44,750 Suntem strcmping CS50 pietre și nule, și astfel încât va segfault. 354 00:27:44,750 --> 00:27:48,280 Și de ce este argv [1] nul? 355 00:27:48,640 --> 00:27:51,280 [Elev] Pentru ca nu am da orice argumente de linie de comandă. 356 00:27:51,280 --> 00:27:53,390 Da. Noi nu am da orice argumente de linie de comandă. 357 00:27:53,390 --> 00:27:58,460 Deci, ./buggy1 este doar de gând să aibă argv [0] este ./buggy1. 358 00:27:58,460 --> 00:28:02,100 Ea nu va avea un argv [1], astfel încât va segfault. 359 00:28:02,100 --> 00:28:07,450 Dar dacă, în schimb, să fac doar CS50, o să spun Veți obține un D 360 00:28:07,450 --> 00:28:09,950 pentru că asta e ceea ce ar trebui sa fac. 361 00:28:09,950 --> 00:28:15,240 Privind la buggy1.c, se presupune pentru a imprima "Veți obține un D" - 362 00:28:15,240 --> 00:28:20,820 Dacă argv [1] nu este "CS50 pietre", "Ai un D", altfel "Veți obține un A!" 363 00:28:20,820 --> 00:28:25,660 Deci, dacă vrem un A, avem nevoie de aceasta pentru a compara ca fiind adevărate, 364 00:28:25,660 --> 00:28:28,710 ceea ce înseamnă că o compară cu 0. 365 00:28:28,710 --> 00:28:31,100 Deci, argv [1] trebuie să fie "pietre" CS50. 366 00:28:31,100 --> 00:28:35,660 Dacă vrei să faci asta pe linia de comandă, aveți nevoie pentru a utiliza \ pentru a scăpa spațiu. 367 00:28:35,660 --> 00:28:41,690 Deci CS50 \ roci și veți obține un A! 368 00:28:41,690 --> 00:28:44,060 Dacă nu faci backslash, de ce nu funcționează asta? 369 00:28:44,060 --> 00:28:47,190 [Elev] E două argumente diferite. Da >>. 370 00:28:47,190 --> 00:28:52,540 Argv [1] va fi CS50, și argv [2] va fi pietre. Bine. 371 00:28:52,540 --> 00:28:56,470 >> Acum ./buggy2 este de gând să segfault din nou. 372 00:28:56,470 --> 00:29:01,880 În loc de ao deschide cu fișierul miezul ei, vom deschide doar până buggy2 direct, 373 00:29:01,880 --> 00:29:05,000 așa gdb buggy2. 374 00:29:05,000 --> 00:29:09,590 Acum, dacă vom rula doar programul nostru, atunci o să spun Programul a primit semnal de SIGSEGV, 375 00:29:09,590 --> 00:29:15,530 care este segfault semnal, și acest lucru este în cazul în care sa întâmplat să se întâmple. 376 00:29:15,530 --> 00:29:21,250 Privind la backtrace nostru, vom vedea că am fost în oh_no funcție, 377 00:29:21,250 --> 00:29:23,900 care a fost numit de catre Dinky funcția, care a fost numit de către Binky funcția, 378 00:29:23,900 --> 00:29:26,460 care a fost numit de către principal. 379 00:29:26,460 --> 00:29:31,680 Putem vedea, de asemenea, argumentele pentru aceste funcții. 380 00:29:31,680 --> 00:29:34,680 Argument pentru Dinky și Binky a fost de 1. 381 00:29:34,680 --> 00:29:44,390 Dacă am lista functia oh_no, vom vedea că oh_no este de a face doar char ** s = NULL; 382 00:29:44,390 --> 00:29:47,410 * S = "boom"; 383 00:29:47,410 --> 00:29:50,330 De ce ar eșua asta? 384 00:29:54,330 --> 00:29:58,380 [Elev] Nu poți dereference indicatorul nul? Da >>. 385 00:29:58,380 --> 00:30:06,090 Acest lucru este doar că e este NULL, indiferent în cazul în care se întâmplă să fie un char **, 386 00:30:06,090 --> 00:30:12,070 care, în funcție de modul în care interpreta, ar putea fi un pointer la un pointer la un șir de 387 00:30:12,070 --> 00:30:15,550 sau o serie de siruri de caractere. 388 00:30:15,550 --> 00:30:21,430 E s este NULL, deci * s este un pointer nul dereferencing, 389 00:30:21,430 --> 00:30:24,800 și astfel aceasta se va prabusi. 390 00:30:24,800 --> 00:30:27,540 Aceasta este una dintre cele mai rapide moduri în care puteți segfault, eventual. 391 00:30:27,540 --> 00:30:31,300 E doar o declarare pointer nul și imediat segfaulting. 392 00:30:31,300 --> 00:30:34,570 Asta e ceea ce face oh_no. 393 00:30:34,570 --> 00:30:43,400 Dacă vom merge în sus cu un cadru, apoi vom intra în funcția de care a sunat oh_no. 394 00:30:43,400 --> 00:30:44,830 Am nevoie să fac asta în jos. 395 00:30:44,830 --> 00:30:48,610 Dacă nu introduceți o comandă și te-a lovit doar Enter din nou, 396 00:30:48,610 --> 00:30:52,350 se va repeta doar comanda anterioară pe care ai fugit. 397 00:30:52,350 --> 00:30:56,610 Suntem în cadru 1. 398 00:30:56,610 --> 00:31:04,650 Listarea acest cadru, vom vedea aici este funcția noastră. 399 00:31:04,650 --> 00:31:08,520 Puteți lovi din nou lista, sau poti face lista 20 și se va lista mai mult. 400 00:31:08,520 --> 00:31:13,640 Dinky Funcția spune dacă i este 1, atunci du-te la funcția de oh_no, 401 00:31:13,640 --> 00:31:15,960 du-te la altceva funcția Slinky. 402 00:31:15,960 --> 00:31:18,700 Și știm i este 1, deoarece se întâmplă să vedem aici 403 00:31:18,700 --> 00:31:22,560 Dinky că a fost numit cu argumentul 1. 404 00:31:22,560 --> 00:31:27,560 Sau poți să faci pur și simplu i imprima și se va spune i este 1. 405 00:31:27,560 --> 00:31:33,770 Suntem în prezent în Dinky, și dacă mergem un alt cadru, noi știm că vom ajunge în Binky. 406 00:31:33,770 --> 00:31:36,600 Sus. Acum suntem în Binky. 407 00:31:36,600 --> 00:31:41,340 Listarea această funcție - lista de tăiat jumătate înainte de mine off - 408 00:31:41,340 --> 00:31:52,670 Totul a început ca în cazul în care i este 0, atunci vom numi oh_no, suna altfel Dinky. 409 00:31:52,670 --> 00:31:57,000 Stim I a fost de 1, așa că numita Dinky. 410 00:31:57,000 --> 00:32:05,030 Și acum ne-am întors în principal, și principal este doar de gând să fie int i = rand ()% 3; 411 00:32:05,030 --> 00:32:08,790 Asta este doar de gând să vă dau un număr aleatoriu care este fie 0, 1, sau 2. 412 00:32:08,790 --> 00:32:12,780 Se va numi Binky cu acel număr, și se va întoarce 0. 413 00:32:12,780 --> 00:32:16,700 Privind la acest lucru, 414 00:32:16,700 --> 00:32:19,880 doar de mers pe jos prin programul manual fără a executa imediat, 415 00:32:19,880 --> 00:32:25,400 v-ar stabili un punct principal de pauza de la, ceea ce înseamnă că, atunci când vom rula programul 416 00:32:25,400 --> 00:32:31,020 programul rulează până când se lovește un punct de spargere. 417 00:32:31,020 --> 00:32:35,450 Deci, rularea programului, acesta va rula și apoi va lovi funcția principală și se va opri de rulare. 418 00:32:35,450 --> 00:32:44,700 Acum suntem în interiorul principal, și pasul următor este sau ne va aduce la următoarea linie de cod. 419 00:32:44,700 --> 00:32:47,050 Puteți face pasul următor sau. 420 00:32:47,050 --> 00:32:51,800 Lovirea următor, acum i-a fost setat la rand ()% 3, astfel încât să putem tipări valoarea lui I, 421 00:32:51,800 --> 00:32:55,280 și-l va spune i este 1. 422 00:32:55,280 --> 00:32:58,110 Acum contează dacă vom folosi următoarea etapă sau. 423 00:32:58,110 --> 00:33:01,000 Cred că a contat în cel precedent, dar ne-am dori să utilizați următoarea. 424 00:33:01,000 --> 00:33:06,000 Dacă vom folosi pas, vom păși în funcție, ceea ce înseamnă gasiti lucru real 425 00:33:06,000 --> 00:33:07,940 ce se intampla in interiorul Binky. 426 00:33:07,940 --> 00:33:10,510 Dacă vom folosi urmatoarea, atunci înseamnă că trece peste funcția 427 00:33:10,510 --> 00:33:14,070 și du-te la următoarea linie de cod în funcție nostru principal. 428 00:33:14,070 --> 00:33:17,900 Chiar aici pe această linie, în cazul în care am fost la ea a spus RAND () de 3%; 429 00:33:17,900 --> 00:33:21,320 dacă am făcut pas, ar intra în punerea în aplicare a rand 430 00:33:21,320 --> 00:33:25,110 si uita-te la ceea ce se intampla acolo, si am putut parcurge funcția de rand. 431 00:33:25,110 --> 00:33:26,920 Dar nu-mi pasă de funcția rand. 432 00:33:26,920 --> 00:33:30,190 Vreau doar să merg la următoarea linie de cod, în principal, așa că am folosi următoarea. 433 00:33:30,190 --> 00:33:35,800 Dar acum îmi pasă de funcția Binky, așa că vreau să pășească în asta. 434 00:33:35,800 --> 00:33:37,730 Acum sunt în Binky. 435 00:33:37,730 --> 00:33:42,040 Prima linie de cod se va spune în cazul în care (i == 0), iau un pas, 436 00:33:42,040 --> 00:33:44,930 vom vedea vom ajunge la Dinky. 437 00:33:44,930 --> 00:33:51,620 Dacă noi lucrurile lista, vedem că acesta este verificat i = 0. 438 00:33:51,620 --> 00:33:55,470 i nu este egal cu 0, așa că a mers la starea altceva, 439 00:33:55,470 --> 00:33:59,540 care este de gând să sun Dinky (i). 440 00:33:59,540 --> 00:34:04,030 S-ar putea obține confuz. 441 00:34:04,030 --> 00:34:07,380 Dacă te uiți doar la aceste linii direct, ai putea crede că, dacă (i == 0), 442 00:34:07,380 --> 00:34:10,800 ok, apoi am luat un pas, iar acum eu sunt la Dinky (i), 443 00:34:10,800 --> 00:34:14,120 s-ar putea crede că trebuie să însemne i = 0 sau ceva. 444 00:34:14,120 --> 00:34:18,980 Nu, înseamnă doar că se știe că se poate lipi direct la linia de Dinky (i). 445 00:34:18,980 --> 00:34:23,300 Pentru că nu este 0, pasul următor nu se va termina la altceva. 446 00:34:23,300 --> 00:34:26,239 Altceva nu este o linie se va opri de la. 447 00:34:26,239 --> 00:34:31,570 E doar de gând să meargă la următoarea linie se poate executa de fapt, care este Dinky (i). 448 00:34:31,570 --> 00:34:36,090 Pășind în Dinky (i), vom vedea dacă (i == 1). 449 00:34:36,090 --> 00:34:42,670 Știm i = 1, asa ca atunci cand pasim, știm că vom ajunge în oh_no 450 00:34:42,670 --> 00:34:46,489 deoarece i = 1 solicită oh_no funcția, pe care aveți posibilitatea să pas în, 451 00:34:46,489 --> 00:34:52,969 care este de gând să setați char ** s = NULL și imediat la "boom". 452 00:34:54,270 --> 00:34:59,690 Și apoi, de fapt se uită la punerea în aplicare a buggy2, 453 00:34:59,690 --> 00:35:04,590 acest lucru, i se obtinerea doar un număr aleatoriu - 0, 1, sau 2 - chemare Binky, 454 00:35:04,590 --> 00:35:10,610 care, dacă i este 0 se numește oh_no, altfel solicită Dinky, care vine aici. 455 00:35:10,610 --> 00:35:18,100 Dacă i este 1, apelul oh_no, suna altfel Slinky, care vine aici, 456 00:35:18,100 --> 00:35:20,460 în cazul în care i este 2, suna oh_no. 457 00:35:20,460 --> 00:35:24,720 Nu cred că chiar și acolo este o modalitate - 458 00:35:24,720 --> 00:35:30,030 Are cineva vedea o modalitate de a face acest lucru un program care nu va segfault? 459 00:35:30,030 --> 00:35:37,530 Pentru că dacă nu mă lipsește ceva, dacă i este 0, vei segfault imediat, 460 00:35:37,530 --> 00:35:41,250 altceva te duci la o funcție care, dacă i este 1 vă segfault, 461 00:35:41,250 --> 00:35:44,540 altceva te duci la o funcție în cazul în care, dacă i este 2 vă segfault. 462 00:35:44,540 --> 00:35:46,810 Deci, indiferent de ceea ce faci, te segfault. 463 00:35:46,810 --> 00:35:52,380 >> Cred ca o modalitate de a stabili, ar fi loc de a face char ** s = NULL, 464 00:35:52,380 --> 00:35:55,610 ai putea malloc spațiu pentru acel șir. 465 00:35:55,610 --> 00:36:04,230 Am putea face malloc (sizeof) - sizeof ce? 466 00:36:09,910 --> 00:36:15,190 [Elev] (char) * 5? Are acest >> se pare corect? 467 00:36:15,190 --> 00:36:21,060 Sunt presupunând că acest lucru va funcționa dacă eu de fapt ea a fugit, dar nu e ceea ce caut. 468 00:36:24,400 --> 00:36:32,940 Uită-te la tipul de e. Să adăugăm * int, int * x asa. 469 00:36:32,940 --> 00:36:35,600 Mi-ar face malloc (sizeof (int)). 470 00:36:35,600 --> 00:36:40,490 Sau dacă am vrut o serie de 5, mi-ar face (sizeof (int) * 5); 471 00:36:40,490 --> 00:36:44,210 Ce se întâmplă dacă am o int **? 472 00:36:46,260 --> 00:36:49,140 Ce aș malloc? 473 00:36:49,140 --> 00:36:53,510 [Elev] Mărimea indicatorului. Da >>. (Sizeof (int *)); 474 00:36:53,510 --> 00:36:56,960 Acelasi lucru aici. 475 00:36:56,960 --> 00:37:01,280 Vreau (sizeof (char *)); 476 00:37:06,170 --> 00:37:12,840 Acest lucru se întâmplă pentru a aloca spațiu pentru indicatorul care indică "boom". 477 00:37:12,840 --> 00:37:15,330 Nu am nevoie să aloce spatiu pentru "boom" în sine 478 00:37:15,330 --> 00:37:17,210 deoarece aceasta este de fapt echivalent cu ceea ce am spus mai înainte 479 00:37:17,210 --> 00:37:20,870 de char * x = "boom". 480 00:37:20,870 --> 00:37:27,950 "Boom" există deja. Se întâmplă să existe în regiunea read-only de memorie. 481 00:37:27,950 --> 00:37:35,200 Dar ea există deja, ceea ce înseamnă această linie de cod, în cazul în care s este un char **, 482 00:37:35,200 --> 00:37:43,900 * atunci s este un char * si tu setarea acestei char * pentru a indica "boom". 483 00:37:43,900 --> 00:37:50,040 Dacă aș fi vrut să copiați "boom" în s, atunci mi-ar trebui să aloce spațiu pentru s.. 484 00:37:55,170 --> 00:38:03,900 Voi face * s = malloc (sizeof (char) * 5); 485 00:38:03,900 --> 00:38:06,210 De ce 5? 486 00:38:06,210 --> 00:38:10,860 De ce nu 4? Se pare ca "boom" este de 4 caractere. >> [Elev] caracterul nul. 487 00:38:10,860 --> 00:38:14,580 Da. Toate siruri de caractere dvs. sunt de gând să nevoie de un caracter nul. 488 00:38:14,580 --> 00:38:23,590 Acum pot face ceva de genul strcat - Care este funcția pentru copierea unui șir? 489 00:38:23,590 --> 00:38:28,520 [Elev] cpy? Strcpy >>. 490 00:38:28,520 --> 00:38:32,700 strcpy om. 491 00:38:36,120 --> 00:38:39,590 Deci, strcpy sau strncpy. 492 00:38:39,590 --> 00:38:43,410 strncpy este un pic mai sigur, deoarece aveți posibilitatea să specificați exact câte caractere, 493 00:38:43,410 --> 00:38:46,190 dar aici nu contează pentru că știm. 494 00:38:46,190 --> 00:38:50,340 Deci, strcpy si uita-te la argumentele. 495 00:38:50,340 --> 00:38:53,100 Primul argument este destinația noastră. 496 00:38:53,100 --> 00:38:56,770 Al doilea argument este sursa noastră. 497 00:38:56,770 --> 00:39:10,310 Vom copia în * destinația noastră e indicatorul "boom". 498 00:39:10,310 --> 00:39:19,820 De ce ar putea să vă doriți să faceți acest lucru cu un strcpy în loc de doar ceea ce am avut înainte de 499 00:39:19,820 --> 00:39:22,800 de * s = "boom"? 500 00:39:22,800 --> 00:39:28,630 Există un motiv pentru care s-ar putea dori să faceți acest lucru, dar ceea ce este aceea? 501 00:39:28,630 --> 00:39:31,940 [Elev] Dacă doriți să schimbați ceva în "boom". Da >>. 502 00:39:31,940 --> 00:39:37,950 Acum pot face ceva de genul s [0] = "X"; 503 00:39:37,950 --> 00:39:48,190 deoarece punctele s la grămadă și că spațiul pe heap, care s indică spre 504 00:39:48,190 --> 00:39:52,320 este un pointer la mai mult spatiu pe heap, care este stocarea "boom". 505 00:39:52,320 --> 00:39:55,150 Deci, această copie a "boom" este a fi depozitate în grămadă. 506 00:39:55,150 --> 00:39:58,780 Există două copii ale punct de vedere tehnic "boom" în programul nostru. 507 00:39:58,780 --> 00:40:03,500 Nu e primul care e doar dat de prezenta constanta șir "boom", 508 00:40:03,500 --> 00:40:09,250 și al doilea exemplar al "boom", strcpy a creat copie a "boom". 509 00:40:09,250 --> 00:40:13,100 Dar copie a "boom" se stocate pe heap, iar heap ești liber să se schimbe. 510 00:40:13,100 --> 00:40:17,250 Heap nu este doar în citire, astfel încât înseamnă că e [0] 511 00:40:17,250 --> 00:40:20,500 este de gând să vă schimbați valoarea "boom". 512 00:40:20,500 --> 00:40:23,130 O să vă permit să modificați aceste caractere. 513 00:40:23,130 --> 00:40:26,640 >> Întrebări? 514 00:40:27,740 --> 00:40:29,290 Bine. 515 00:40:29,290 --> 00:40:35,500 >> Trecând la buggy3, haideți să gdb buggy3. 516 00:40:35,500 --> 00:40:39,840 Am doar rulați-l și vedem vom obține o segfault. 517 00:40:39,840 --> 00:40:46,550 Dacă vom backtrace, există doar două funcții. 518 00:40:46,550 --> 00:40:52,970 Dacă vom merge în sus, în funcție de principalul nostru, vom vedea că am segfaulted la această linie. 519 00:40:52,970 --> 00:41:00,180 Deci, doar se uită la această linie, pentru (int = 0; line fgets astea nu NULL este egal; 520 00:41:00,180 --> 00:41:03,770 Linia + +). 521 00:41:03,770 --> 00:41:08,010 Cadru noastră anterioară a fost numit _IO_fgets. 522 00:41:08,010 --> 00:41:10,720 Veți vedea că o mulțime cu built-in functii C, 523 00:41:10,720 --> 00:41:15,350 că atunci când vei ajunge segfault, nu va fi într-adevăr numele criptice de funcții 524 00:41:15,350 --> 00:41:18,090 Ca acest _IO_fgets. 525 00:41:18,090 --> 00:41:21,770 Dar asta se va referi la acest apel fgets. 526 00:41:21,770 --> 00:41:25,850 Undeva în interiorul aici, suntem segfaulting. 527 00:41:25,850 --> 00:41:30,340 Dacă ne uităm la argumentele la fgets, putem imprima tampon. 528 00:41:30,340 --> 00:41:41,180 Să o imprimați ca - Oh, nu. 529 00:41:48,980 --> 00:41:51,900 Imprimare nu este de gând să lucreze exact așa cum vreau să. 530 00:41:55,460 --> 00:41:58,000 Să ne uităm la programul actual. 531 00:42:02,200 --> 00:42:09,640 Buffer-ul este un sir de caractere. E un sir de caractere de 128 de caractere. 532 00:42:09,640 --> 00:42:14,980 Deci, atunci când spun tampon de imprimare, se va imprima aceste 128 de caractere, 533 00:42:14,980 --> 00:42:18,300 care cred că este ceea ce este de așteptat. 534 00:42:18,300 --> 00:42:21,390 Ceea ce am fost cautati pentru este imprima adresa de tampon, 535 00:42:21,390 --> 00:42:23,680 dar asta nu ma spune mult. 536 00:42:23,680 --> 00:42:30,770 Asa ca atunci cand se intampla sa spun aici x tampon, se arată-mi 0xbffff090, 537 00:42:30,770 --> 00:42:38,690 care, dacă vă amintiți de la mai devreme sau un anumit punct, Oxbffff tinde să fie o regiune stack-ish. 538 00:42:38,690 --> 00:42:46,020 Stivă tinde să începem de undeva doar sub 0xc000. 539 00:42:46,020 --> 00:42:51,890 Doar prin văzând această adresă, știu că buffer-ul se întâmplă pe stiva. 540 00:42:51,890 --> 00:43:04,500 Repornirea programul meu, fugi, te, tampon am vazut a fost această secvență de caractere 541 00:43:04,500 --> 00:43:06,530 care sunt destul de mult sens. 542 00:43:06,530 --> 00:43:12,270 Apoi imprimați fișierul, ceea ce nu arata dosar? 543 00:43:15,120 --> 00:43:17,310 [Elev] Null. Da >>. 544 00:43:17,310 --> 00:43:22,610 Fișier este un tip de * FILE, deci este un pointer, 545 00:43:22,610 --> 00:43:26,610 și valoarea pe care indicatorul este nul. 546 00:43:26,610 --> 00:43:33,240 Deci, fgets este de gând să încerce să citească de la faptul că indicatorul într-un mod indirect, 547 00:43:33,240 --> 00:43:37,320 dar pentru a accesa că indicatorul, trebuie să-l dereference. 548 00:43:37,320 --> 00:43:40,550 Sau, pentru a accesa ceea ce ar trebui să fie îndreptată spre, îl dereferences. 549 00:43:40,550 --> 00:43:43,810 Deci, este un pointer nul dereferencing și-l segfaults. 550 00:43:46,600 --> 00:43:48,730 Aș fi putut să-l reluat acolo. 551 00:43:48,730 --> 00:43:52,170 Dacă ne rupe la punctul nostru principal și a alerga, 552 00:43:52,170 --> 00:43:57,320 prima linie de cod este char * filename = "nonexistent.txt"; 553 00:43:57,320 --> 00:44:00,870 Asta ar trebui să dea un indiciu destul de mare ca de ce acest program nu reușește. 554 00:44:00,870 --> 00:44:06,080 Tastarea lângă mine aduce la linia următoare, în cazul în care am deschis acest fișier, 555 00:44:06,080 --> 00:44:11,140 și apoi mă imediat în linia noastră, în cazul în care o dată m-am lovit următoare, o să segfault. 556 00:44:11,140 --> 00:44:16,880 Vrea cineva să arunce un motiv pentru care ar putea fi segfaulting? 557 00:44:16,880 --> 00:44:19,130 [Elev] Fișierul nu există. Da >>. 558 00:44:19,130 --> 00:44:22,250 Acest lucru ar trebui să fie un indiciu 559 00:44:22,250 --> 00:44:29,570 că ori de câte ori sunteți deschiderea unui fișier care aveți nevoie pentru a verifica dacă fișierul există de fapt. 560 00:44:29,570 --> 00:44:31,510 Deci, aici, "nonexistent.txt"; 561 00:44:31,510 --> 00:44:34,700 Când ne-am Filename fopen pentru lectură, avem atunci trebuie să spunem 562 00:44:34,700 --> 00:44:45,870 în cazul în care (fișier == NULL), și spun printf ("Fișierul nu există!" 563 00:44:45,870 --> 00:44:56,340 sau - mai bine - filename); întoarcere 1; 564 00:44:56,340 --> 00:45:00,300 Deci, acum vom verifica pentru a vedea dacă este NULL 565 00:45:00,300 --> 00:45:03,930 înainte de a continua de fapt, și încercarea de a citi din acel fișier. 566 00:45:03,930 --> 00:45:08,800 Ne putem reface doar pentru a vedea că lucrările. 567 00:45:11,020 --> 00:45:14,970 Mi-am propus să includă o linie nouă. 568 00:45:21,090 --> 00:45:25,290 Deci, acum nonexistent.txt nu există. 569 00:45:26,890 --> 00:45:30,040 Trebuie să verificați întotdeauna pentru acest fel de lucruri. 570 00:45:30,040 --> 00:45:33,870 Trebuie să verificați întotdeauna pentru a vedea dacă fopen returnează NULL. 571 00:45:33,870 --> 00:45:38,170 Trebuie să verificați întotdeauna pentru a vă asigura că malloc nu se întoarce NULL, 572 00:45:38,170 --> 00:45:41,410 sau altceva segfault. 573 00:45:42,200 --> 00:45:45,930 >> Acum buggy4.c. 574 00:45:49,190 --> 00:45:58,440 Rularea. Cred că acest lucru este în așteptare pentru intrare sau, eventual, loop infinit. 575 00:45:58,440 --> 00:46:01,870 Da, e infinită looping. 576 00:46:01,870 --> 00:46:05,560 Deci, buggy4. Se pare ca suntem looping infinit. 577 00:46:05,560 --> 00:46:12,590 Ne putem rupe de la principal, executați programul nostru. 578 00:46:12,590 --> 00:46:20,180 În gdb, atâta timp cât utilizați abrevierea este lipsit de ambiguitate 579 00:46:20,180 --> 00:46:23,420 sau abrevieri speciale care le oferă pentru tine, 580 00:46:23,420 --> 00:46:29,020 le puteti folosi pentru a utiliza următoarea n loc de a avea pentru a tasta următoare tot drumul. 581 00:46:29,020 --> 00:46:33,730 Și acum că am lovit o dată n, eu pot doar să apăsați Enter pentru a continua următoare 582 00:46:33,730 --> 00:46:36,640 în loc de a avea pentru a lovi n Introduceți, n Introduceți, n Enter. 583 00:46:36,640 --> 00:46:44,630 Se pare că sunt într-un fel de buclă pentru care este setarea matrice [i] la 0. 584 00:46:44,630 --> 00:46:50,510 Se pare ca n-am ieși din această buclă pentru. 585 00:46:50,510 --> 00:46:54,780 Dacă eu am imprima, astfel încât i este 2, atunci voi merge în continuare. 586 00:46:54,780 --> 00:46:59,250 Voi i imprima, i este 3, atunci voi merge în continuare. 587 00:46:59,250 --> 00:47:05,360 Voi i imprima și i este 3. În continuare, imprima i, i este 4. 588 00:47:05,360 --> 00:47:14,520 De fapt, de imprimare sizeof (array), astfel încât dimensiunea matrice este 20. 589 00:47:16,310 --> 00:47:32,870 Dar se pare ca nu e ceva de comandă specială gdb pentru a merge până la ceva se întâmplă. 590 00:47:32,870 --> 00:47:37,620 E ca și cum o condiție privind stabilirea valorii variabilei. Dar eu nu-mi amintesc ce este. 591 00:47:37,620 --> 00:47:44,100 Deci, dacă vom continua - 592 00:47:44,100 --> 00:47:47,120 Ce spuneai? Ce ai adus sus? 593 00:47:47,120 --> 00:47:50,500 [Elev] se afișează adaug - >> Da. Deci afișa te pot ajuta. 594 00:47:50,500 --> 00:47:54,530 Dacă vom afișa doar i, se va pune aici ce valoarea i este 595 00:47:54,530 --> 00:47:56,470 așa că nu trebuie să-l imprimați fiecare dată. 596 00:47:56,470 --> 00:48:02,930 Dacă ținem doar de gând următoare, vom vedea 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5. 597 00:48:02,930 --> 00:48:08,530 Ceva se întâmplă teribil de greșit, și i se resetat la 0. 598 00:48:13,330 --> 00:48:22,220 Privind la buggy4.c, vom vedea tot ce se întâmplă este matrice int [5]; 599 00:48:22,220 --> 00:48:26,200 pentru (i = 0; i <= sizeof (array); i + +) 600 00:48:26,200 --> 00:48:28,550 matrice [i] = 0; 601 00:48:28,550 --> 00:48:31,390 Ce vom vedea că e în neregulă aici? 602 00:48:31,390 --> 00:48:39,480 Ca un indiciu, atunci când am fost făcut gdb buggy4 - hai rupe termen principal, - 603 00:48:39,480 --> 00:48:45,980 Am facut print sizeof (array) doar pentru a vedea ce condiție este locul unde ar trebui să rup în cele din urmă. 604 00:48:47,690 --> 00:48:51,100 În cazul în care sunt eu? Credeți alerg? 605 00:48:51,100 --> 00:48:54,280 Nu am declara încă. 606 00:48:54,280 --> 00:48:58,680 Imprima astfel încât sizeof (array) și că e 20, 607 00:48:58,680 --> 00:49:06,690 care este de așteptat, deoarece gama mea este de marimea 5 și este de 5 numere întregi, 608 00:49:06,690 --> 00:49:12,410 astfel încât întregul lucru ar trebui să fie de 5 * sizeof (int) octeți, în cazul în care sizeof (int) tinde să fie 4. 609 00:49:12,410 --> 00:49:14,780 Deci, sizeof (array) este de 20. 610 00:49:14,780 --> 00:49:17,420 Ce ar trebui să fie asta? 611 00:49:17,420 --> 00:49:21,720 [Elev] Împărțit de sizeof (int). Da >>, / sizeof (int). 612 00:49:21,720 --> 00:49:30,630 Se pare că există încă o problemă aici. Cred că acest lucru ar trebui să fie doar < 613 00:49:30,630 --> 00:49:36,960 din moment ce este destul de mult tot timpul 00:49:44,860 Acum, să ne gândim de ce acest lucru a fost, de fapt rupt. 615 00:49:44,860 --> 00:49:53,370 Are cineva ghiceste de ce am fost resetat la 0 prin fiecare iterație a buclei? 616 00:50:01,300 --> 00:50:09,350 Singurul lucru de aici în interiorul ce se intampla este ca matrice [i] este în curs de la 0. 617 00:50:09,350 --> 00:50:15,350 Deci într-un fel, această linie de cod este cauza noastră int i pentru a fi setat la 0. 618 00:50:16,730 --> 00:50:23,130 [Elev] Ar putea fi, deoarece este imperative de memorie din această parte a I 619 00:50:23,130 --> 00:50:27,970 atunci când crede că e urmatorul element al array? >> [Bowden] Da. 620 00:50:27,970 --> 00:50:33,880 Când mergem dincolo de sfârșitul anului matrice noastre, 621 00:50:33,880 --> 00:50:39,870 într-un fel că spațiul pe care suntem imperative este imperative valoarea lui i. 622 00:50:39,870 --> 00:50:48,030 Și astfel, dacă ne uităm în buggy4, rupe alerga principal,, 623 00:50:48,030 --> 00:50:53,120 să imprimați adresa lui i. 624 00:50:53,120 --> 00:50:57,280 Se pare ca o bffff124. 625 00:50:57,280 --> 00:51:03,930 Acum, haideți să imprimați adresa de matrice [0]. 110. 626 00:51:03,930 --> 00:51:06,290 Ce zici [1]? 114. 627 00:51:06,290 --> 00:51:07,920 [2], 118. 628 00:51:07,920 --> 00:51:14,530 11c, 120. matrice [5] este bfff124. 629 00:51:14,530 --> 00:51:26,990 Deci, matrice [5] are aceeași adresă ca i, ceea ce înseamnă că matrice [5] este i. 630 00:51:26,990 --> 00:51:30,720 Dacă au aceeași adresă, ele sunt același lucru. 631 00:51:30,720 --> 00:51:38,410 Așa că atunci când ne-am stabilit matrice [5] la 0, suntem i setarea la 0. 632 00:51:38,410 --> 00:51:46,070 Și dacă te gândești la asta în termeni de stivă, 633 00:51:46,070 --> 00:51:55,590 int i este declarată în primul rând, ceea ce înseamnă că devine ceva spațiu pe stivă. 634 00:51:55,590 --> 00:52:04,730 Apoi matrice [5] este alocată, astfel încât atunci 20 bytes sunt alocate pe stivă. 635 00:52:04,730 --> 00:52:08,400 Asa ca am devine alocate în primul rând, atunci aceste 20 bytes te alocate. 636 00:52:08,400 --> 00:52:11,400 Asa ca am se întâmplă chiar înainte de matrice, 637 00:52:11,400 --> 00:52:19,230 și din cauza modului, cum am spus săptămâna trecută, în cazul în care punct de vedere tehnic stiva creste în jos, 638 00:52:19,230 --> 00:52:28,520 Atunci când indicele într-o matrice, ne sunt garantate că poziția 0th în matrice 639 00:52:28,520 --> 00:52:31,970 Întotdeauna se întâmplă înainte de prima pozitie in matrice. 640 00:52:31,970 --> 00:52:35,900 Aceasta este un fel de modul în care l-am desenat săptămâna trecută. 641 00:52:35,900 --> 00:52:42,210 Observați că în partea de jos avem adresa 0 și la partea de sus avem max adresa. 642 00:52:42,210 --> 00:52:44,880 Stiva este întotdeauna în creștere în jos. 643 00:52:48,100 --> 00:52:53,500 Să spunem că am aloca. 644 00:52:53,500 --> 00:52:59,680 Noi aloca integer i, ceea ce înseamnă că hai să spunem doar aici întreg i se alocă. 645 00:52:59,680 --> 00:53:06,420 Apoi ne-am aloca gama noastră din 5 numere întregi, ceea ce înseamnă că sub că, 646 00:53:06,420 --> 00:53:11,230 deoarece stiva este în creștere în jos, cele 5 numere întregi se alocate. 647 00:53:11,230 --> 00:53:15,900 Dar, din cauza modului matrice funcționează, suntem garantat că prima poziție în matrice 648 00:53:15,900 --> 00:53:22,260 are întotdeauna o adresă mai mică de al doilea lucru în matrice. 649 00:53:22,260 --> 00:53:28,270 Deci, poziția 0 matrice întotdeauna trebuie să se întâmple mai întâi în memorie, 650 00:53:28,270 --> 00:53:30,700 întrucât poziția matrice 1 are să se întâmple după aceea 651 00:53:30,700 --> 00:53:33,310 și poziția matrice 2 are să se întâmple după aceea, 652 00:53:33,310 --> 00:53:37,900 ceea ce înseamnă că poziția 0 matrice s-ar întâmpla undeva aici jos, 653 00:53:37,900 --> 00:53:40,690 Poziția matrice 1 de mai sus s-ar întâmpla asta 654 00:53:40,690 --> 00:53:45,530 deoarece se deplasează în sus înseamnă adrese mai mari, deoarece adresa maximă este de până aici. 655 00:53:45,530 --> 00:53:50,490 Deci, matrice [0] aici jos, matrice [1] până aici, matrice [2] până aici, matrice [3] aici. 656 00:53:50,490 --> 00:53:55,620 Înainte de a observa cum am alocat întreg i tot drumul până aici, 657 00:53:55,620 --> 00:54:01,040 asa cum am merge mai departe și mai departe în gama noastră, suntem tot mai aproape de a noastră întreg i. 658 00:54:01,040 --> 00:54:07,640 Pur și simplu așa se întâmplă că matrice [5], care este o poziție dincolo de gama noastră, 659 00:54:07,640 --> 00:54:13,010 este exact în cazul în care întreg i sa întâmplat să fie alocate. 660 00:54:13,010 --> 00:54:16,920 Deci, asta e punctul în care se întâmplă să fie lovit spațiul de pe stivă 661 00:54:16,920 --> 00:54:21,680 care a fost alocat pentru întreg i, și suntem setarea că la 0. 662 00:54:21,680 --> 00:54:26,160 >> Asta e modul în care funcționează. Întrebări? Da. 663 00:54:26,160 --> 00:54:30,710 [Elev] Nu contează. Bine. 664 00:54:30,710 --> 00:54:33,090 [Elev] Cum puteți evita aceste tipuri de erori? 665 00:54:33,090 --> 00:54:41,190 Acestea fel de erori? Nu folosiți limbaj de programare C, după dumneavoastră. 666 00:54:41,190 --> 00:54:45,840 Folositi un limbaj care are limite de matrice de control. 667 00:54:45,840 --> 00:54:55,900 Atâta timp cât ești atent, trebuie doar sa evite sa mearga dincolo de limitele matrice dumneavoastră. 668 00:54:55,900 --> 00:54:58,300 [Elev] Deci, aici, când ne-am dus dincolo de limitele matrice dumneavoastră - 669 00:54:58,300 --> 00:55:01,840 [Bowden] Asta e în cazul în care lucrurile încep sa mearga prost. >> [Elev] Oh, bine. 670 00:55:01,840 --> 00:55:05,730 Atâta timp cât stai în memorie alocată pentru matrice dvs., ești bine. 671 00:55:05,730 --> 00:55:12,400 Dar C nu face verificarea erorilor. Dacă fac matrice [1000], acesta va modifica doar cu bucurie ceea ce se întâmplă - 672 00:55:12,400 --> 00:55:16,500 Se merge la începutul matrice, apoi merge pozitii dupa 1000 si il seteaza pe 0. 673 00:55:16,500 --> 00:55:20,000 Ea nu face nici o verificare că oh, acest lucru nu are de fapt 1000 de lucruri în ea. 674 00:55:20,000 --> 00:55:22,750 1000 este dincolo de ceea ce ar trebui să se schimbe, 675 00:55:22,750 --> 00:55:26,940 întrucât Java sau ceva veți obține gama de indicele de limitele 676 00:55:26,940 --> 00:55:29,820 sau indicele de excepție limitele. 677 00:55:29,820 --> 00:55:33,950 De aceea, o mulțime de limbi de nivel superior au aceste lucruri 678 00:55:33,950 --> 00:55:37,340 în cazul în care dacă te duci dincolo de limitele matrice, nu reușesc 679 00:55:37,340 --> 00:55:40,070 astfel încât să nu se poate schimba lucrurile de la sub tine 680 00:55:40,070 --> 00:55:42,590 și apoi lucrurile merg mult mai rău decât obținerea pur și simplu o excepție 681 00:55:42,590 --> 00:55:44,940 spunând că te-ai dus dincolo de sfârșitul matrice. 682 00:55:44,940 --> 00:55:50,970 [Elev] Și astfel ar trebui să ne-am schimbat doar <= la doar > [Bowden] Da. 683 00:55:50,970 --> 00:55:54,800 Ar trebui să fie 00:55:59,560 deoarece sizeof (array) este de 20, dar vrem doar 5. >> [Elev] Corect. 685 00:55:59,560 --> 00:56:04,060 Mai multe întrebări? Bine. 686 00:56:04,060 --> 00:56:07,380 >> [Elev] Am o întrebare. Da >>. 687 00:56:07,380 --> 00:56:16,440 [Elev] Care este variabila matrice reală? 688 00:56:16,440 --> 00:56:20,000 [Bowden] Ca ce este matrice? 689 00:56:20,000 --> 00:56:24,930 Array sine este un simbol. 690 00:56:24,930 --> 00:56:31,490 Acesta este doar adresa de start a 20 bytes pe care le fac referire. 691 00:56:31,490 --> 00:56:38,070 Vă puteți gândi la ea ca la un pointer, dar este un pointer constant. 692 00:56:38,070 --> 00:56:44,140 De îndată ce lucrurile se compilate, matrice variabilă nu mai există. 693 00:56:44,140 --> 00:56:48,210 [Elev] Deci, cum se afla dimensiunea matrice? 694 00:56:48,210 --> 00:56:54,130 Mărimea matrice se referă la dimensiunea de care blocheaza că simbolul se referă la. 695 00:56:54,130 --> 00:57:01,240 Când m-am face ceva de genul printf ("% p \ n", array); 696 00:57:01,240 --> 00:57:05,140 hai să-l rulați. 697 00:57:12,960 --> 00:57:15,530 Ce-am făcut greșit? 698 00:57:15,530 --> 00:57:19,220 "Matrice" matrice a declarat aici. 699 00:57:20,820 --> 00:57:23,200 Oh, aici. 700 00:57:23,200 --> 00:57:31,250 Zăngănit este inteligent, și se întâmplă să observați că am declarat ca matrice 5 elemente 701 00:57:31,250 --> 00:57:34,540 dar eu sunt indexarea în poziția 1000. 702 00:57:34,540 --> 00:57:38,450 Se poate face acest lucru, deoarece acestea sunt doar constante. 703 00:57:38,450 --> 00:57:43,370 Se poate merge numai în măsura în observ că am de gând dincolo de limitele matrice. 704 00:57:43,370 --> 00:57:46,880 Dar, înainte de a observa când am avut am fi incorectă, 705 00:57:46,880 --> 00:57:51,040 nu se poate determina, eventual, câte valori i-ar putea lua pe, 706 00:57:51,040 --> 00:57:55,540 astfel încât nu se poate stabili faptul că am fost de gând dincolo de sfârșitul matrice. 707 00:57:55,540 --> 00:57:59,430 Asta e doar zăngănit fiind inteligent. 708 00:57:59,430 --> 00:58:03,340 >> Dar fac acum buggy4. Deci, ce altceva fac gresit? 709 00:58:03,340 --> 00:58:05,970 Implicit, declarând funcția de bibliotecă "printf". 710 00:58:05,970 --> 00:58:14,960 Am de gând să doriți să includeți # . 711 00:58:14,960 --> 00:58:18,710 Bine. Rulează acum buggy4. 712 00:58:18,710 --> 00:58:24,840 Imprimarea valoarea de matrice așa cum am făcut-o aici, tipărirea ca un pointer 713 00:58:24,840 --> 00:58:30,060 printuri ceva care arata ca acest lucru - bfb8805c - ceea ce este o adresa 714 00:58:30,060 --> 00:58:33,450 care este în regiunea stiva-ish. 715 00:58:33,450 --> 00:58:41,820 Array sine este ca un pointer, dar nu este un indicator real, 716 00:58:41,820 --> 00:58:45,410 deoarece un pointer regulat putem schimba. 717 00:58:45,410 --> 00:58:54,700 Array este doar o constantă. Cele 20 de blocuri de memorie încep de la 0xbfb8805c adresa. 718 00:58:54,700 --> 00:59:09,020 Deci bfb8805c prin această adresă +20- sau cred -20 - 719 00:59:09,020 --> 00:59:17,400 este tot din memorie alocată pentru această matrice. 720 00:59:17,400 --> 00:59:20,350 Array, variabila în sine nu este stocat nicăieri. 721 00:59:20,350 --> 00:59:27,660 Când sunteți compilarea, compilatorul - val mâna la ea - 722 00:59:27,660 --> 00:59:33,060 dar compilatorul va folosi doar în cazul în care se știe matrice să fie. 723 00:59:33,060 --> 00:59:36,090 Se știe că în cazul în care începe matrice, 724 00:59:36,090 --> 00:59:40,910 si asa se poate face doar lucrurile întotdeauna în termeni de compensări de la acest început. 725 00:59:40,910 --> 00:59:43,960 Ea nu are nevoie de o variabilă sine pentru a reprezenta matrice. 726 00:59:43,960 --> 00:59:53,730 Dar când fac ceva de genul int * p = array; acum p este un pointer care indică faptul că matrice, 727 00:59:53,730 --> 00:59:57,830 și acum, de fapt p exista pe stiva. 728 00:59:57,830 --> 01:00:01,950 Sunt liber să schimbe p.. Eu pot face p = malloc. 729 01:00:01,950 --> 01:00:06,500 Așa că inițial a subliniat matrice, acum arată la unele spațiu pe heap. 730 01:00:06,500 --> 01:00:09,620 Eu nu pot face matrice malloc =. 731 01:00:09,620 --> 01:00:13,710 Dacă zăngănit este inteligent, el va țipa la mine right off BAT. 732 01:00:17,000 --> 01:00:21,430 De fapt, eu sunt destul de sigur că gcc-ar face acest lucru prea. 733 01:00:21,430 --> 01:00:25,010 Deci, de tip array "int [5]" nu este transmisibile. 734 01:00:25,010 --> 01:00:28,040 Nu puteți atribui ceva la un tip de matrice 735 01:00:28,040 --> 01:00:30,500 deoarece matrice este doar o constantă. 736 01:00:30,500 --> 01:00:34,760 Este un simbol care trimiterile cele 20 de octeți. Eu nu pot schimba. 737 01:00:34,760 --> 01:00:37,690 >> [Elev] Iar în cazul în care este dimensiunea matrice stocate? 738 01:00:37,690 --> 01:00:40,670 [Bowden] Nu este stocat nicăieri. E atunci când este compilarea. 739 01:00:40,670 --> 01:00:46,310 Deci, în cazul în care este dimensiunea matrice stocate? 740 01:00:46,310 --> 01:00:51,870 Puteți utiliza numai sizeof (array) în interiorul funcției, care este ea însăși matrice declarată. 741 01:00:51,870 --> 01:01:03,150 Deci, dacă am face o anumită funcție, foo, și îmi place (int matrice []) 742 01:01:03,150 --> 01:01:10,450 printf ("% d \ n", sizeof (array)); 743 01:01:10,450 --> 01:01:21,330 și apoi în jos aici, eu numesc foo (matrice); 744 01:01:21,330 --> 01:01:24,840 în interiorul acestei funcții - să-l rulați. 745 01:01:34,200 --> 01:01:36,840 Acest lucru este zăngănit fi inteligent din nou. 746 01:01:36,840 --> 01:01:43,890 Este să spui că sizeof pe parametrul funcției matrice 747 01:01:43,890 --> 01:01:46,690 va reveni dimensiunea "* int". 748 01:01:46,690 --> 01:01:55,150 Aceasta ar fi o eroare dacă nu e ceea ce am vrut să se întâmple. 749 01:01:55,150 --> 01:01:58,960 Să ne îndreptăm, de fapt off Werror. 750 01:02:14,950 --> 01:02:17,590 Avertisment. Avertismente sunt bine. 751 01:02:17,590 --> 01:02:19,960 Acesta va compila în continuare atâta timp cât acesta are un avertisment. 752 01:02:19,960 --> 01:02:22,910 . / A.out este de gând să imprima 4. 753 01:02:22,910 --> 01:02:28,650 Avertizare care a fost generat este un indicator clar a ceea ce nu a mers bine. 754 01:02:28,650 --> 01:02:34,120 Această matrice int este doar de gând să imprima sizeof (int *). 755 01:02:34,120 --> 01:02:39,790 Chiar daca am pus matrice [5] aici, este încă doar de gând să imprima sizeof (int *). 756 01:02:39,790 --> 01:02:47,440 Asa ca imediat ce-l treci într-o funcție, distincția între matrice și pointeri 757 01:02:47,440 --> 01:02:49,670 este inexistent. 758 01:02:49,670 --> 01:02:52,640 Acest lucru se întâmplă să fie o matrice care a fost declarată în stivă, 759 01:02:52,640 --> 01:02:58,300 dar de îndată ce trecem această valoare, care 0xbf bla, bla, bla în această funcție, 760 01:02:58,300 --> 01:03:03,350 atunci acest indicator arată faptul că pentru a matrice pe stiva. 761 01:03:03,350 --> 01:03:08,310 Deci asta înseamnă că sizeof se aplică numai în funcția pe care a fost declarată matrice, 762 01:03:08,310 --> 01:03:11,230 ceea ce înseamnă că, atunci când sunt compilarea această funcție, 763 01:03:11,230 --> 01:03:17,330 atunci când face să răsune trece prin această funcție, el vede matrice este o matrice de int marimea 5. 764 01:03:17,330 --> 01:03:20,640 Deci, atunci se vede sizeof (array). Ei bine, asta e 20. 765 01:03:20,640 --> 01:03:26,440 Asta e de fapt modul în care funcționează practic sizeof pentru aproape toate cazurile. 766 01:03:26,440 --> 01:03:31,150 Sizeof nu este o funcție, e un operator. 767 01:03:31,150 --> 01:03:33,570 Tu nu apela funcția sizeof. 768 01:03:33,570 --> 01:03:38,280 Sizeof (int), compilatorul va traduce doar că la 4. 769 01:03:41,480 --> 01:03:43,700 Ai inteles? Bine. 770 01:03:43,700 --> 01:03:47,520 >> [Elev] Deci, ceea ce este diferența dintre sizeof (array), în principal și în foo? 771 01:03:47,520 --> 01:03:52,840 Acest lucru se datorează faptului că noi spunem sizeof (array), care este de tipul int *, 772 01:03:52,840 --> 01:03:57,120 întrucât matrice aici nu este de tip int *, este o matrice int. 773 01:03:57,120 --> 01:04:04,540 >> [Elev] Deci, dacă ați avut parametrul în matrice [] în loc de matrice * int, 774 01:04:04,540 --> 01:04:09,230 ar însemna că că ați fi putut schimba în continuare matrice, deoarece acum este un pointer? 775 01:04:09,230 --> 01:04:14,250 [Bowden] Ca asta? >> [Elev] Da. Poți schimba matrice în funcția de acum? 776 01:04:14,250 --> 01:04:18,420 [Bowden] Ai putea schimba matrice, în ambele cazuri. 777 01:04:18,420 --> 01:04:23,130 În ambele cazuri, sunteți liberi să spună matrice [4] = 0. 778 01:04:23,130 --> 01:04:26,590 [Elev] Dar vă pot face punctul de matrice la altceva? 779 01:04:26,590 --> 01:04:30,230 [Bowden] Oh. Da. În ambele cazuri - >> [elev] Da. 780 01:04:30,230 --> 01:04:38,410 [Bowden] Distincția între matrice [] și o matrice * int, nu este nici unul. 781 01:04:38,410 --> 01:04:42,570 Puteți obține de asemenea, unele matrice multidimensională aici 782 01:04:42,570 --> 01:04:47,050 pentru unii sintaxa convenabil, dar este încă doar un pointer. 783 01:04:47,050 --> 01:04:56,400 Acest lucru înseamnă că sunt liber să fac array = malloc (sizeof (int)); iar acum punctul în altă parte. 784 01:04:56,400 --> 01:04:59,610 Dar la fel ca și modul în care aceasta funcționează pentru totdeauna și întotdeauna, 785 01:04:59,610 --> 01:05:03,210 modificarea acestei matrice, făcând-o să arate altceva 786 01:05:03,210 --> 01:05:07,570 nu schimbă această matrice aici pentru că este o copie a argumentului, 787 01:05:07,570 --> 01:05:10,780 nu este un pointer la acest argument. 788 01:05:10,780 --> 01:05:16,070 Și, de fapt, la fel ca și indicație mai mult că e exact la fel - 789 01:05:16,070 --> 01:05:21,100 am vazut deja ce printuri de imprimare matrice - 790 01:05:21,100 --> 01:05:31,410 Ce se întâmplă dacă am imprima adresa matrice sau adresa adresa matrice 791 01:05:31,410 --> 01:05:36,290 la oricare dintre aceste? 792 01:05:41,770 --> 01:05:45,220 Să ignorăm asta. 793 01:05:48,140 --> 01:05:51,660 Bine. Acest lucru este bine. Se rulează acum / a.out.. 794 01:05:51,660 --> 01:06:00,220 Matrice de imprimare, apoi imprimarea adresa matrice, sunt același lucru. 795 01:06:00,220 --> 01:06:02,870 Matrice pur și simplu nu există. 796 01:06:02,870 --> 01:06:08,190 Ea știe când sunteți de imprimare matrice, sunteți de imprimare simbol care face referire la cele 20 de octeți. 797 01:06:08,190 --> 01:06:11,940 Imprimarea adresa matrice, ei bine, matrice nu există. 798 01:06:11,940 --> 01:06:17,200 Ea nu are o adresă, așa că imprimă doar adresa de cele 20 de octeți. 799 01:06:20,820 --> 01:06:28,150 De îndată ce vă compilați jos, ca în buggy4 ta compilat / a.out., 800 01:06:28,150 --> 01:06:30,340 matrice este inexistent. 801 01:06:30,340 --> 01:06:33,640 Pointeri există. Matrice nu. 802 01:06:34,300 --> 01:06:38,060 Blocurile de memorie care reprezintă matrice există încă, 803 01:06:38,060 --> 01:06:43,270 dar matrice variabilă, iar variabilele de acest tip nu există. 804 01:06:46,260 --> 01:06:50,270 Acestea sunt la fel ca principalele diferențe dintre tablouri și pointeri 805 01:06:50,270 --> 01:06:55,590 sunt la fel de repede ca tine face apeluri de funcții, nu există nici o diferență. 806 01:06:55,590 --> 01:07:00,460 Dar în interiorul funcției pe care matrice în sine este declarată, sizeof funcționează diferit 807 01:07:00,460 --> 01:07:05,190 din moment ce te imprimarea dimensiunea de blocuri în loc de mărimea tipul, 808 01:07:05,190 --> 01:07:08,950 și nu se poate schimba pentru că este un simbol. 809 01:07:08,950 --> 01:07:14,370 Imprimarea lucru și adresa lucru imprimă același lucru. 810 01:07:14,370 --> 01:07:18,480 Și asta e destul de mult. 811 01:07:18,480 --> 01:07:20,820 [Elev] Poți spune că o dată mai mult? 812 01:07:21,170 --> 01:07:24,170 S-ar putea să fi scăpat ceva. 813 01:07:24,170 --> 01:07:29,260 Matrice de imprimare și adresa matrice imprimă același lucru, 814 01:07:29,260 --> 01:07:33,180 întrucât dacă imprimați un pointer comparativ cu adresa pointer, 815 01:07:33,180 --> 01:07:36,010 singurul lucru imprimă adresa a ceea ce indică spre, 816 01:07:36,010 --> 01:07:40,360 celălalt imprimă adresa indicatorul pe stivă. 817 01:07:40,360 --> 01:07:47,040 Aveți posibilitatea să modificați un pointer, nu se poate schimba un simbol matrice. 818 01:07:47,740 --> 01:07:53,270 Și indicatorul sizeof este de gând să imprima dimensiunea de acest tip pointer. 819 01:07:53,270 --> 01:07:57,470 Deci, int * p sizeof (p) este de gând să imprima 4, 820 01:07:57,470 --> 01:08:04,110 dar int matrice [5] print sizeof (array) este de gând să imprima 20. 821 01:08:04,110 --> 01:08:07,480 [Elev] Deci, int matrice [5] se vor imprima 20? Da >>. 822 01:08:07,480 --> 01:08:13,300 De aceea, în interiorul buggy4 atunci când este folosit pentru a fi sizeof (array) 823 01:08:13,300 --> 01:08:16,660 acest lucru a fost făcut eu <20, care nu este ceea ce ne-am dorit. 824 01:08:16,660 --> 01:08:20,880 Ne dorim ca i <5. >> [Elev] Ok. 825 01:08:20,880 --> 01:08:25,569 [Bowden] Și apoi, cât mai curând începe să paseze în funcțiile, 826 01:08:25,569 --> 01:08:34,340 dacă am făcut-o int * p = array; 827 01:08:34,340 --> 01:08:39,779 în interiorul acestei funcții, putem folosi practic p și matrice în exact aceleași moduri, 828 01:08:39,779 --> 01:08:43,710 cu excepția problemei sizeof și problema schimbare. 829 01:08:43,710 --> 01:08:49,810 Dar p [0] = 1; este aceeași cu a spune matrice [0] = 1; 830 01:08:49,810 --> 01:08:55,600 Și de îndată ce am spus foo (array) sau foo (p); 831 01:08:55,600 --> 01:08:59,760 interiorul funcției foo, aceasta este aceeași chemare de două ori. 832 01:08:59,760 --> 01:09:03,350 Nu există nici o diferență între aceste două apeluri. 833 01:09:07,029 --> 01:09:11,080 >> Bun pe care toată lumea? Bine. 834 01:09:14,620 --> 01:09:17,950 Avem 10 minute. 835 01:09:17,950 --> 01:09:28,319 >> Vom încerca să obțineți prin intermediul acestui program de Typer Hacker, 836 01:09:28,319 --> 01:09:32,350 acest site, care a venit în anul trecut sau ceva de genul. 837 01:09:34,149 --> 01:09:41,100 Este doar ar trebui să fie ca tine tastați aleatoriu și se imprimă - 838 01:09:41,100 --> 01:09:46,729 Orice fișier se întâmplă să fi încărcat este ceea ce se pare că îl tastați. 839 01:09:46,729 --> 01:09:52,069 Se pare ca un fel de cod sistem de operare. 840 01:09:53,760 --> 01:09:56,890 Asta e ceea ce vrem să pună în aplicare. 841 01:10:08,560 --> 01:10:11,690 Tu ar trebui să aibă un executabil binar numit hacker_typer 842 01:10:11,690 --> 01:10:14,350 care ia într-un singur argument, fișierul "de tip hacker." 843 01:10:14,350 --> 01:10:16,480 Rularea executabil ar trebui să goli ecranul 844 01:10:16,480 --> 01:10:20,850 și apoi să imprimați afară de un caracter din fișierul pass-in de fiecare dată când utilizatorul apasă o cheie. 845 01:10:20,850 --> 01:10:24,990 Deci, indiferent de ce apăsați tasta, ar trebui să arunce și să imprimați în schimb un personaj din dosar 846 01:10:24,990 --> 01:10:27,810 că este argumentul. 847 01:10:29,880 --> 01:10:34,350 Voi destul de mult ti spun ce lucrurile pe care le vom avea nevoie să știe sunt. 848 01:10:34,350 --> 01:10:36,440 Dar vrem să verificați bibliotecă termios. 849 01:10:36,440 --> 01:10:44,840 Nu am folosit această bibliotecă în toată viața mea, așa că are scopuri foarte minime. 850 01:10:44,840 --> 01:10:48,610 Dar acest lucru se va fi bibliotecă putem folosi pentru a arunca caracterul te-a lovit 851 01:10:48,610 --> 01:10:52,390 atunci când sunt tastând în iarnă inch 852 01:10:56,970 --> 01:11:05,840 Deci hacker_typer.c, și vom dori să includă # . 853 01:11:05,840 --> 01:11:12,870 Privind la pagina de manual pentru termios - Sunt ghicitul terminalul e sistemul de operare sau ceva de genul - 854 01:11:12,870 --> 01:11:16,240 Nu știu cum să-l citesc. 855 01:11:16,240 --> 01:11:21,040 Privind la acest lucru, se spune pentru a include aceste 2 imagini, asa ca vom face asta. 856 01:11:37,620 --> 01:11:46,820 >> Primul lucru pe de o parte, dorim să ia într-o singur argument, care este fișierul ar trebui să ne deschidă. 857 01:11:46,820 --> 01:11:52,420 Deci, ce vreau să fac? Cum pot verifica să văd am un singur argument? 858 01:11:52,420 --> 01:11:56,480 [Elev] Dacă argc este egal. >> [Bowden] Da. 859 01:11:56,480 --> 01:12:21,250 Deci, în cazul în care (argc = 2!) Printf ("Folosire:% s [fișier pentru a deschide]"). 860 01:12:21,250 --> 01:12:32,750 Deci, acum, dacă am rula această fără a furniza un al doilea argument - Oh, am nevoie de noua linie - 861 01:12:32,750 --> 01:12:36,240 veți vedea că spune de utilizare: / hacker_typer,. 862 01:12:36,240 --> 01:12:39,770 și apoi al doilea argument ar trebui să fie fișierul pe care îl doriți să îl deschideți. 863 01:12:58,430 --> 01:13:01,260 Acum ce să fac? 864 01:13:01,260 --> 01:13:08,490 Vreau să citesc din acest fișier. Cum am citit dintr-un fișier? 865 01:13:08,490 --> 01:13:11,920 [Elev] Deschide-o tu primul. Da >>. 866 01:13:11,920 --> 01:13:15,010 Deci fopen. Ceea ce nu fopen arata? 867 01:13:15,010 --> 01:13:22,980 [Elev] Numele fisierului. >> [Bowden] Filename va fi argv [1]. 868 01:13:22,980 --> 01:13:26,110 [Elev] Și atunci ce vrei sa faci cu el, așa - >> [Bowden] Da. 869 01:13:26,110 --> 01:13:28,740 Așa că, dacă nu-mi amintesc, ai putea face doar fopen om, 870 01:13:28,740 --> 01:13:32,960 în cazul în care acesta va fi o cale const char * în cazul în care calea este numele fișierului, 871 01:13:32,960 --> 01:13:34,970 Mod de const char *. 872 01:13:34,970 --> 01:13:38,660 Dacă se întâmplă să nu ne amintim ce mod este, atunci poti sa te uiti pentru modul. 873 01:13:38,660 --> 01:13:44,660 In interiorul paginilor man, caracterul slash este ceea ce se poate folosi pentru a căuta lucruri. 874 01:13:44,660 --> 01:13:49,790 Așa că am scrie / mode pentru a căuta modul. 875 01:13:49,790 --> 01:13:57,130 N și N sunt ceea ce se poate utiliza pentru a parcurge meciurile de căutare. 876 01:13:57,130 --> 01:13:59,800 Aici se spune punctele de modul argument pentru un șir 877 01:13:59,800 --> 01:14:01,930 începând cu una dintre următoarele secvențe. 878 01:14:01,930 --> 01:14:06,480 Deci r, fișier text deschis pentru citire. Asta e ceea ce vrem să facem. 879 01:14:08,930 --> 01:14:13,210 Pentru citirea, și vreau pentru a stoca asta. 880 01:14:13,210 --> 01:14:18,720 Lucru va fi un * FILE. Acum, ceea ce vreau să fac? 881 01:14:18,720 --> 01:14:21,200 Dă-mi o secundă. 882 01:14:28,140 --> 01:14:30,430 Bine. Acum, ceea ce vreau să fac? 883 01:14:30,430 --> 01:14:32,940 [Elev] Verificați dacă este NULL. >> [Bowden] Da. 884 01:14:32,940 --> 01:14:38,690 De fiecare dată când deschideți un fișier, asigurați-vă că sunteți cu succes capabil să-l deschidă. 885 01:14:58,930 --> 01:15:10,460 >> Acum vreau să fac lucrurile astea termios în cazul în care vreau să citesc mai întâi setările mele curente 886 01:15:10,460 --> 01:15:14,050 și de a salva pe cei in ceva, atunci vreau să-mi modifica setările 887 01:15:14,050 --> 01:15:19,420 să arunce orice caracter care tip I, 888 01:15:19,420 --> 01:15:22,520 și apoi vreau să actualizați aceste setări. 889 01:15:22,520 --> 01:15:27,250 Și apoi, la sfârșitul programului, vreau pentru a reveni la setările mele originale. 890 01:15:27,250 --> 01:15:32,080 Deci, struct va fi de tip termios, și am de gând să doriți două dintre cele. 891 01:15:32,080 --> 01:15:35,600 Primul va fi current_settings mele, 892 01:15:35,600 --> 01:15:42,010 și apoi ei vor fi hacker_settings mele. 893 01:15:42,010 --> 01:15:48,070 În primul rând, am de gând să doriți să salvați setările mele curente, 894 01:15:48,070 --> 01:15:53,790 apoi m-am de gând să doriți să o actualizați hacker_settings, 895 01:15:53,790 --> 01:16:01,570 și apoi drumul la sfârșitul programului meu, vreau să revin la setările curente. 896 01:16:01,570 --> 01:16:08,660 Deci salvarea setărilor curente, modul în care funcționează, noi termios om. 897 01:16:08,660 --> 01:16:15,810 Vedem că avem această tcsetattr int, int tcgetattr. 898 01:16:15,810 --> 01:16:22,960 Trec într-o struct termios de indicatorul său. 899 01:16:22,960 --> 01:16:30,640 Modul în care acest va arata este - I've uitat deja ce funcția a fost numit. 900 01:16:30,640 --> 01:16:34,930 Copiați și lipiți-l. 901 01:16:39,150 --> 01:16:45,500 Deci tcgetattr, atunci vreau să trec în struct că eu sunt salvarea informațiilor în, 902 01:16:45,500 --> 01:16:49,650 care va fi current_settings, 903 01:16:49,650 --> 01:16:59,120 și primul argument este descriptorul de fisier pentru lucru pe care vreau pentru a salva atributele. 904 01:16:59,120 --> 01:17:04,360 Ce descriptor de fisier este este ca și cum de fiecare dată când deschideți un fișier, acesta devine un descriptor de fișier. 905 01:17:04,360 --> 01:17:14,560 Când m-am fopen argv [1], acesta devine un descriptor de fișier care vă fac referire la 906 01:17:14,560 --> 01:17:16,730 ori de câte ori doriți să citiți sau să-l scrie. 907 01:17:16,730 --> 01:17:19,220 Asta nu e descriptor de fisier vreau să folosesc aici. 908 01:17:19,220 --> 01:17:21,940 Există trei descriptori de fișier pe care trebuie în mod implicit, 909 01:17:21,940 --> 01:17:24,310 care sunt standard în, din standard, si eroarea standard. 910 01:17:24,310 --> 01:17:29,960 În mod implicit, cred că e iarnă în este 0, din standard este 1, iar eroarea standard este 2. 911 01:17:29,960 --> 01:17:33,980 Deci ce vreau pentru a modifica setările de? 912 01:17:33,980 --> 01:17:37,370 Vreau pentru a modifica setările de fiecare dată când am lovit un caracter, 913 01:17:37,370 --> 01:17:41,590 Vreau să arunce acel caracter oaspeți loc de a imprima-l pe ecran. 914 01:17:41,590 --> 01:17:45,960 Ce curs de apa - standard, din standard, sau eroarea standard - 915 01:17:45,960 --> 01:17:52,050 răspunde la lucruri atunci când am introduceți de la tastatură? >> [Elev] Standard inch >> Da. 916 01:17:52,050 --> 01:17:56,450 Deci, eu pot face fie 0 sau pot face stdin. 917 01:17:56,450 --> 01:17:59,380 Primesc current_settings standard inch 918 01:17:59,380 --> 01:18:01,720 >> Acum vreau să actualizați aceste setări, 919 01:18:01,720 --> 01:18:07,200 asa ca prima Voi copia în ceea ce hacker_settings current_settings mele sunt. 920 01:18:07,200 --> 01:18:10,430 Și modul în care munca este struct va copia doar. 921 01:18:10,430 --> 01:18:14,510 Acest copiaza toate câmpurile, așa cum v-ați aștepta. 922 01:18:14,510 --> 01:18:17,410 >> Acum vreau să actualizeze unele câmpuri. 923 01:18:17,410 --> 01:18:21,670 Privind la termios, va trebui să citiți printr-o mulțime de acest 924 01:18:21,670 --> 01:18:24,110 doar pentru a vedea ceea ce ar vrea să se uite pentru, 925 01:18:24,110 --> 01:18:28,210 dar steagurile ai de gând să doriți să căutați pentru sunt ecou, 926 01:18:28,210 --> 01:18:33,110 astfel de caractere de intrare ECHO Echo. 927 01:18:33,110 --> 01:18:37,710 În primul rând vreau să setați - I've uitat deja ce domenii sunt. 928 01:18:45,040 --> 01:18:47,900 Aceasta este ceea ce pare a fi struct. 929 01:18:47,900 --> 01:18:51,060 Deci, modurile de introducere cred că vrea să se schimbe. 930 01:18:51,060 --> 01:18:54,210 Ne vom uita la soluția pentru a se asigura că este ceea ce vrem să se schimbe. 931 01:19:04,060 --> 01:19:12,610 Dorim să schimbe lflag, în scopul de a preveni nevoie să se uite prin toate astea. 932 01:19:12,610 --> 01:19:14,670 Dorim să schimbe modurile locale. 933 01:19:14,670 --> 01:19:17,710 Tu ar trebui să citiți acest lucru întreg pentru a înțelege în cazul în care totul aparține 934 01:19:17,710 --> 01:19:19,320 pe care vrem să se schimbe. 935 01:19:19,320 --> 01:19:24,120 Dar e în interiorul modurilor locale, în cazul în care am de gând să doriți să schimbe acest lucru. 936 01:19:27,080 --> 01:19:33,110 Deci, hacker_settings.cc_lmode este ceea ce se numește. 937 01:19:39,630 --> 01:19:43,020 c_lflag. 938 01:19:49,060 --> 01:19:52,280 Acest lucru este în cazul în care vom intra în operatori la nivel de bit. 939 01:19:52,280 --> 01:19:54,860 Suntem un fel de afara timpului, dar vom merge prin ea repede. 940 01:19:54,860 --> 01:19:56,600 Acest lucru este în cazul în care vom intra în operatori la nivel de bit, 941 01:19:56,600 --> 01:19:59,950 în cazul în care cred că am spus o mult timp în urmă că de fiecare dată când începeți a face cu steaguri, 942 01:19:59,950 --> 01:20:03,370 ai de gând să fie folosind operatorul la nivel de bit foarte mult. 943 01:20:03,370 --> 01:20:08,240 Fiecare bit din pavilion corespunde la un fel de comportament. 944 01:20:08,240 --> 01:20:14,090 Deci, aici, acest indicator are o grămadă de lucruri diferite, în cazul în care toate dintre ele înseamnă ceva diferit. 945 01:20:14,090 --> 01:20:18,690 Dar ceea ce vreau să fac este activa doar pe biți care corespunde ECHO. 946 01:20:18,690 --> 01:20:25,440 Deci, pentru a transforma aia fac & = ¬ ECHO. 947 01:20:25,440 --> 01:20:30,110 De fapt, cred că e ca și cum TECHO sau ceva de genul. Mă duc pentru a verifica din nou. 948 01:20:30,110 --> 01:20:34,050 Pot să-l termios. E doar ECHO. 949 01:20:34,050 --> 01:20:38,440 ECHO este de gând să fie un singur bit. 950 01:20:38,440 --> 01:20:44,230 ¬ ECHO este de gând să spui toate biți sunt setate la 1, ceea ce înseamnă toți indicatorii sunt setate pe true 951 01:20:44,230 --> 01:20:47,140 cu excepția biți ECHO. 952 01:20:47,140 --> 01:20:53,830 Prin încetarea steaguri mele locale cu acest lucru, înseamnă toate pavilion, care sunt în prezent stabilite la adevărata 953 01:20:53,830 --> 01:20:56,520 va fi în continuare setată la true. 954 01:20:56,520 --> 01:21:03,240 În cazul în care steagul meu ECHO este setat la true, atunci acest lucru este necesar setat la fals pe steagul ECHO. 955 01:21:03,240 --> 01:21:07,170 Deci, această linie de cod doar se stinge pavilion ECHO. 956 01:21:07,170 --> 01:21:16,270 Celelalte linii de cod, eu doar le copiați în interesul de timp și apoi a le explica. 957 01:21:27,810 --> 01:21:30,180 În soluție, a spus el 0. 958 01:21:30,180 --> 01:21:33,880 Este, probabil, mai bine să spun în mod explicit stdin. 959 01:21:33,880 --> 01:21:42,100 >> Observați că fac, de asemenea, ECHO | ICANON aici. 960 01:21:42,100 --> 01:21:46,650 ICANON se referă la ceva separat, ceea ce înseamnă modul canonic. 961 01:21:46,650 --> 01:21:50,280 Ce înseamnă modul canonic este, de obicei, atunci când sunteți tastați în linia de comandă, 962 01:21:50,280 --> 01:21:54,670 standard în nu procesa nimic până când te-a lovit newline. 963 01:21:54,670 --> 01:21:58,230 Deci, atunci când nu getString, tastați o grămadă de lucruri, atunci te-a lovit newline. 964 01:21:58,230 --> 01:22:00,590 Asta e atunci când este trimis la standard de inch 965 01:22:00,590 --> 01:22:02,680 Asta e implicită. 966 01:22:02,680 --> 01:22:05,830 Când m-am dezactiva modul canonic, acum fiecare caracter unic apăsați 967 01:22:05,830 --> 01:22:10,910 este ceea ce este procesat, care este de obicei un fel de rău pentru că este lent pentru a procesa aceste lucruri, 968 01:22:10,910 --> 01:22:14,330 care este motivul pentru care e bine să-l tampon în linii întregi. 969 01:22:14,330 --> 01:22:16,810 Dar vreau ca fiecare personaj să fie prelucrate 970 01:22:16,810 --> 01:22:18,810 deoarece nu vreau să mă aștepte la lovit newline 971 01:22:18,810 --> 01:22:21,280 înainte de a le prelucrează toate personajele Am fost tastarea. 972 01:22:21,280 --> 01:22:24,760 Acest lucru dezactivează modul canonic. 973 01:22:24,760 --> 01:22:31,320 Chestia asta înseamnă doar atunci când prelucrează de fapt de caractere. 974 01:22:31,320 --> 01:22:35,830 Acest lucru înseamnă să le proceseze imediat; cât de curând le-am tastarea, le prelucrează. 975 01:22:35,830 --> 01:22:42,510 Și aceasta este funcția care este actualizarea setările mele pentru standard în, 976 01:22:42,510 --> 01:22:45,480 și mijloace de TCSA face chiar acum. 977 01:22:45,480 --> 01:22:50,310 Celelalte opțiuni sunt așteptați până când tot ceea ce este în prezent pe fluxul este procesată. 978 01:22:50,310 --> 01:22:52,030 Asta nu contează cu adevărat. 979 01:22:52,030 --> 01:22:56,920 Doar acum modifica setările mele de a fi ceea ce este în prezent în hacker_typer_settings. 980 01:22:56,920 --> 01:23:02,210 Cred că am numit-o hacker_settings, asa ca hai sa schimba asta. 981 01:23:09,610 --> 01:23:13,500 Schimba totul la hacker_settings. 982 01:23:13,500 --> 01:23:16,870 >> Acum, la sfârșitul programului nostru vom dori să reveniți 983 01:23:16,870 --> 01:23:20,210 la ceea ce este în prezent în interiorul normal_settings, 984 01:23:20,210 --> 01:23:26,560 care este de gând să arate la fel ca si normal_settings. 985 01:23:26,560 --> 01:23:30,650 Observați că nu s-au schimbat nici de normal_settings mele, deoarece initial l primesc. 986 01:23:30,650 --> 01:23:34,520 Apoi, pentru a schimba doar le înapoi, le-am treci înapoi la sfârșitul anului. 987 01:23:34,520 --> 01:23:38,390 Acest lucru a fost de actualizare. Bine. 988 01:23:38,390 --> 01:23:43,900 >> Acum, în interiorul de aici voi explica doar codul din motive de timp. 989 01:23:43,900 --> 01:23:46,350 Nu e acel cod de mult. 990 01:23:50,770 --> 01:24:03,750 Vedem am citit un personaj din dosar. Am numit-o f. 991 01:24:03,750 --> 01:24:07,850 Acum poți om fgetc, dar cum fgetc este de gând să lucreze 992 01:24:07,850 --> 01:24:11,910 este doar o să se întoarcă caracterul pe care tocmai ai citit sau EOF, 993 01:24:11,910 --> 01:24:15,680 care corespunde la sfârșitul fișierului sau unele se întâmplă eroare. 994 01:24:15,680 --> 01:24:19,900 Suntem looping, continuă să citească un singur caracter de la dosar, 995 01:24:19,900 --> 01:24:22,420 până când ne-am alerga afară de caractere pentru a citi. 996 01:24:22,420 --> 01:24:26,650 Și în timp ce noi facem asta, ne așteptăm la un singur caracter de la standard inch 997 01:24:26,650 --> 01:24:29,090 De fiecare dată când tastați ceva la linia de comandă, 998 01:24:29,090 --> 01:24:32,820 care este citit într-un personaj de la standard de inch 999 01:24:32,820 --> 01:24:38,330 Apoi, putchar este doar de gând să pună char am citit până aici din fișierul standard de ieșire. 1000 01:24:38,330 --> 01:24:42,890 Poți om putchar, dar e doar pune la standard afară, se imprimă acel caracter. 1001 01:24:42,890 --> 01:24:51,600 Ai putea, de asemenea, face doar printf ("% c", c); aceeași idee. 1002 01:24:53,330 --> 01:24:56,670 Asta va face cea mai mare parte a muncii noastre. 1003 01:24:56,670 --> 01:25:00,300 >> Ultimul lucru pe care am de gând să doriți să faceți este să fclose doar fisierul. 1004 01:25:00,300 --> 01:25:03,310 Dacă nu fclose, asta e o scurgere de memorie. 1005 01:25:03,310 --> 01:25:06,680 Dorim să fclose fișierul inițial am deschis, și cred că e ea. 1006 01:25:06,680 --> 01:25:13,810 Dacă vom face asta, am deja probleme. 1007 01:25:13,810 --> 01:25:17,260 Să vedem. 1008 01:25:17,260 --> 01:25:19,960 Ce a plâng? 1009 01:25:19,960 --> 01:25:30,220 De așteptat "int", dar argumentul este de tip "struct _IO_FILE * '. 1010 01:25:36,850 --> 01:25:39,370 Vom vedea dacă funcționează. 1011 01:25:45,210 --> 01:25:53,540 Permisă numai în C99. Augh. Bine, fac hacker_typer. 1012 01:25:53,540 --> 01:25:57,760 Acum avem mai multe descrieri utile. 1013 01:25:57,760 --> 01:25:59,900 Deci, utilizarea identificator nedeclarate "normal_settings". 1014 01:25:59,900 --> 01:26:04,170 Nu am sunat-l normal_settings. Am numit-o current_settings. 1015 01:26:04,170 --> 01:26:12,090 Deci, hai să schimbăm toate astea. 1016 01:26:17,920 --> 01:26:21,710 Care trece acum argument. 1017 01:26:26,290 --> 01:26:29,500 Voi face acest lucru 0 pentru acum. 1018 01:26:29,500 --> 01:26:36,720 Bine. / Hacker_typer. Cp.c. 1019 01:26:36,720 --> 01:26:39,590 De asemenea, nu am goli ecranul de la început. 1020 01:26:39,590 --> 01:26:42,960 Dar poti sa te uiti inapoi la ultimul set de probleme pentru a vedea modul în care a goli ecranul. 1021 01:26:42,960 --> 01:26:45,160 E doar tipărirea unor caractere 1022 01:26:45,160 --> 01:26:47,210 în timp ce aceasta este de a face ceea ce vreau să fac. 1023 01:26:47,210 --> 01:26:48,900 Bine. 1024 01:26:48,900 --> 01:26:55,280 Și gândesc de ce acest lucru este necesar pentru a fi 0 în loc de stdin, 1025 01:26:55,280 --> 01:27:00,560 care ar trebui să fie definească # 0, 1026 01:27:00,560 --> 01:27:03,890 acest lucru este plângându-se că - 1027 01:27:13,150 --> 01:27:19,360 Înainte de a când am spus că nu e descriptorii de fisiere, dar atunci va trebui, de asemenea, * de fișiere, 1028 01:27:19,360 --> 01:27:23,210 un descriptor de fișier este doar un singur număr întreg, 1029 01:27:23,210 --> 01:27:26,970 întrucât o * FILE are o grămadă de lucruri asociate cu aceasta. 1030 01:27:26,970 --> 01:27:30,380 Motivul pentru care trebuie să spunem 0 in loc de stdin 1031 01:27:30,380 --> 01:27:37,480 este faptul că stdin este o * FILE care indică lucrul care face referire descriptor de fisier 0. 1032 01:27:37,480 --> 01:27:45,070 Deci, chiar aici când o voi face fopen (argv [1], Primesc un * FILE spate. 1033 01:27:45,070 --> 01:27:51,180 Dar undeva în acel * FILE este un lucru corespunde descriptor de fisier pentru acel fișier. 1034 01:27:51,180 --> 01:27:57,430 Daca te uiti la pagina de manual pentru deschis, deci cred ca va trebui sa facem om deschis 3 - nope - 1035 01:27:57,430 --> 01:27:59,380 Man 2 deschis - Da. 1036 01:27:59,380 --> 01:28:06,250 Daca te uiti la pagina de deschisă, deschisă este ca o fopen de nivel inferior, 1037 01:28:06,250 --> 01:28:09,350 și se întoarce descriptor de fisier reală. 1038 01:28:09,350 --> 01:28:12,050 fopen face o grămadă de chestii pe partea de sus a deschide, 1039 01:28:12,050 --> 01:28:17,640 care, în loc de a se întoarce doar ca descriptor de fisier returnează un pointer întregul dosar * 1040 01:28:17,640 --> 01:28:20,590 în interiorul căruia este descriptor nostru mic fisier. 1041 01:28:20,590 --> 01:28:25,020 Deci standard se referă la lucru * FILE, 1042 01:28:25,020 --> 01:28:29,120 întrucât se referă la 0 doar standard de descriptor de fisier în sine. 1043 01:28:29,120 --> 01:28:32,160 >> Întrebări? 1044 01:28:32,160 --> 01:28:35,930 [Râde] suflat prin asta. 1045 01:28:35,930 --> 01:28:39,140 Bine. Am terminat. [Râde] 1046 01:28:39,140 --> 01:28:42,000 >> [CS50.TV]