1 00:00:00,000 --> 00:00:02,730 [Powered by Google Translate] [SEKCJA 5: mniej wygodne] 2 00:00:02,730 --> 00:00:05,180 [Nate Hardison, Harvard University] 3 00:00:05,180 --> 00:00:08,260 [To jest CS50.] [CS50.TV] 4 00:00:08,260 --> 00:00:11,690 Tak więc witam ponownie, chłopaki. 5 00:00:11,690 --> 00:00:16,320 Witamy w dziale 5. 6 00:00:16,320 --> 00:00:20,220 W tym momencie, po zakończeniu quizu 0 i widząc, jak zrobiłeś, 7 00:00:20,220 --> 00:00:25,770 mam nadzieję, że czujesz się naprawdę dobre, ponieważ byłem bardzo pod wrażeniem wyników w tej sekcji. 8 00:00:25,770 --> 00:00:28,050 Na naszych internetowych widzów, mieliśmy kilka pytań 9 00:00:28,050 --> 00:00:33,680 o ostatnich dwóch problemów na planie problem - czy na quizie, raczej. 10 00:00:33,680 --> 00:00:39,690 Więc mamy zamiar iść na te bardzo szybko tak, że każdy widzi to, co się stało 11 00:00:39,690 --> 00:00:45,060 i jak przejść przez rzeczywistego rozwiązania, a nie tylko oglądania samego rozwiązania. 12 00:00:45,060 --> 00:00:50,330 Będziemy iść w ciągu ostatnich kilku problemów bardzo szybko, 32 i 33. 13 00:00:50,330 --> 00:00:53,240 Wystarczy, ponownie, tak że online widz może zobaczyć. 14 00:00:53,240 --> 00:00:59,080 >> Jeśli zwracasz się do swojego problemu 32, który jest na stronie 13, 15 00:00:59,080 --> 00:01:02,730 13 z 16, problem 32 jest o swapach. 16 00:01:02,730 --> 00:01:05,010 Chodziło o zamianę dwóch liczb całkowitych. 17 00:01:05,010 --> 00:01:08,740 Jest to problem, który wzięliśmy na kilka razy w wykładzie. 18 00:01:08,740 --> 00:01:13,590 A tu, co pytaliśmy ciebie zrobić, to szybkie ślad pamięciowy. 19 00:01:13,590 --> 00:01:17,000 Wypełnić wartości zmiennych są one na stosie 20 00:01:17,000 --> 00:01:20,250 jak kod przechodzi tej funkcji swap. 21 00:01:20,250 --> 00:01:24,500 W szczególności, co patrzymy - Idę umieścić ten iPad dół - 22 00:01:24,500 --> 00:01:29,650 w szczególności, czego szukamy na to jest linia numer 6 tutaj. 23 00:01:29,650 --> 00:01:36,740 I to tylko dla numerach 6 przyległości z poprzednim problemem. 24 00:01:36,740 --> 00:01:41,720 Co chcemy zrobić jest wyświetlane lub oznaczyć stan pamięci 25 00:01:41,720 --> 00:01:46,090 jak to jest w czasie, gdy wykonujemy ten numer linii 6, 26 00:01:46,090 --> 00:01:52,540 który skutecznie powrót z naszej funkcji wymiany tutaj. 27 00:01:52,540 --> 00:01:59,450 Jeśli przewiń tutaj widzieliśmy, że adresy w pamięci wszystko, co zostało przewidziane dla nas. 28 00:01:59,450 --> 00:02:02,540 To jest bardzo klucz; wrócimy do niego za chwilę. 29 00:02:02,540 --> 00:02:09,240 A potem tu na dole, mieliśmy trochę schemat pamięci będziemy się odwoływać. 30 00:02:09,240 --> 00:02:12,490 I rzeczywiście zrobił to na moim iPadzie. 31 00:02:12,490 --> 00:02:20,720 Więc wracam do przełączania się między iPad a kod tylko dla odniesienia. 32 00:02:20,720 --> 00:02:26,540 >> Zacznijmy. Najpierw skupmy się na kilku pierwszych linii głównej tutaj. 33 00:02:26,540 --> 00:02:30,220 Aby rozpocząć, będziemy inicjować x do 1 i Y 2. 34 00:02:30,220 --> 00:02:33,040 Więc mamy dwie zmienne całkowite, oboje będą umieszczone na stosie. 35 00:02:33,040 --> 00:02:36,050 Mamy zamiar umieścić 1 i 2 w nich. 36 00:02:36,050 --> 00:02:43,150 Więc jeśli mogę przerzucić do mojego iPada, miejmy nadzieję, zobaczymy - 37 00:02:43,150 --> 00:02:48,660 Apple TV mirroring i tam iść. Okay. 38 00:02:48,660 --> 00:02:51,670 Więc jeśli mogę przerzucić do mojego iPada, 39 00:02:51,670 --> 00:02:56,220 Chcę zainicjować x do 1 i Y 2. 40 00:02:56,220 --> 00:03:00,580 Robimy to po prostu pisząc 1 w polu oznaczonym x 41 00:03:00,580 --> 00:03:07,730 i 2 w polu oznaczone y. Dość prosty. 42 00:03:07,730 --> 00:03:11,620 Więc teraz wróćmy do laptopa, zobaczyć, co dzieje się dalej. 43 00:03:11,620 --> 00:03:15,810 Więc to następna linia jest gdzie robi się trudne. 44 00:03:15,810 --> 00:03:28,110 Mijamy adres x i adres y jako parametry a i b do funkcji swap. 45 00:03:28,110 --> 00:03:32,380 Adres oraz adres x y są rzeczy, których nie możemy obliczyć 46 00:03:32,380 --> 00:03:36,360 bez odwoływania się do tych punktów kuli aż tutaj. 47 00:03:36,360 --> 00:03:39,750 I na szczęście, pierwsze dwa wypunktowania nam powiedzieć, co dokładnie odpowiedzi są. 48 00:03:39,750 --> 00:03:44,740 Adres w pamięci jest x 10, oraz adres y w pamięci jest 14. 49 00:03:44,740 --> 00:03:51,870 To są wartości, które przejdzie w jak i b się w czołówce naszej funkcji swap. 50 00:03:51,870 --> 00:04:00,760 Więc znowu, przełączenie z powrotem do naszego diagramu, można napisać 10 w 51 00:04:00,760 --> 00:04:07,400 i 14 wb. 52 00:04:07,400 --> 00:04:11,610 Teraz, to jest to, w którym kontynuować wymianę. 53 00:04:11,610 --> 00:04:14,520 Więc skakaniu z powrotem do laptopa ponownie, 54 00:04:14,520 --> 00:04:21,079 widzimy, że sposób wymiany działa jest po raz pierwszy dereference i przechowywać wynik w tmp. 55 00:04:21,079 --> 00:04:27,650 Więc operator dereference mówi: "Hej. Treat zawartości zmiennej jako adres. 56 00:04:27,650 --> 00:04:33,830 Idź do tego, co jest zapisane na ten adres, a następnie załaduj go. " 57 00:04:33,830 --> 00:04:41,720 Co można załadować z zmiennej ma być przechowywane w naszej zmiennej TMP. 58 00:04:41,720 --> 00:04:45,150 Rzut z powrotem do iPad. 59 00:04:45,150 --> 00:04:51,690 Jeśli idziemy do zajęcia 10, wiemy, że adres 10 jest varible x 60 00:04:51,690 --> 00:04:55,480 bo powiedziano nam przez naszego punktu pocisku, że adres w pamięci x jest 10. 61 00:04:55,480 --> 00:05:00,180 Więc możemy tam iść, uzyskać wartość tego, co jest 1, jak widzimy na naszym iPad, 62 00:05:00,180 --> 00:05:06,300 i ładować że w tmp. 63 00:05:06,300 --> 00:05:08,250 Ponownie, nie jest to ostateczna zawartość. 64 00:05:08,250 --> 00:05:14,350 Idziemy na spacer, a my się do naszego ostatecznego stanu programu na końcu. 65 00:05:14,350 --> 00:05:17,210 Ale teraz mamy wartość 1 przechowywane w tmp. 66 00:05:17,210 --> 00:05:19,210 >> I jest szybkie pytanie tutaj. 67 00:05:19,210 --> 00:05:23,980 [Alexander] Czy operator dereference - to jest po prostu prawo gwiazda przed zmienną? 68 00:05:23,980 --> 00:05:27,600 >> Tak. Więc operator dereference, jak przerzucić do naszego laptopa po raz kolejny, 69 00:05:27,600 --> 00:05:33,780 to jest gwiazda tuż. 70 00:05:33,780 --> 00:05:37,460 W tym sensie, że jest - to kontrastować z operatorem mnożenia 71 00:05:37,460 --> 00:05:42,400 które wymaga dwóch rzeczy; operator dereference jest jednoargumentowy operator. 72 00:05:42,400 --> 00:05:46,130 Tylko do jednego zastosowanie, w przeciwieństwie do wartości operatora binarnego 73 00:05:46,130 --> 00:05:48,810 w którym stosuje się dwie różne wartości. 74 00:05:48,810 --> 00:05:52,080 Więc to, co dzieje się w tej linii. 75 00:05:52,080 --> 00:05:58,390 Załadowaliśmy wartość 1 i przechowywano je do naszej zmiennej tymczasowej całkowitą. 76 00:05:58,390 --> 00:06:05,800 Następna linia, możemy przechowywać zawartość b na - 77 00:06:05,800 --> 00:06:12,630 lub raczej, możemy przechowywać zawartość, że B jest wskazujące na miejsce, gdzie jest skierowany do. 78 00:06:12,630 --> 00:06:17,690 Jeśli przeanalizować to od prawej do lewej, idziemy do b. nieprawidłowego, 79 00:06:17,690 --> 00:06:23,580 mamy zamiar zająć 14, mamy zamiar złapać liczbę całkowitą, która jest tam, 80 00:06:23,580 --> 00:06:26,900 a potem będziemy iść na adres 10, 81 00:06:26,900 --> 00:06:34,240 i będziemy rzucać wynik naszej dereference B do tej przestrzeni. 82 00:06:34,240 --> 00:06:40,080 Rzut z powrotem do naszego iPada, gdzie możemy zrobić to trochę bardziej konkretny, 83 00:06:40,080 --> 00:06:44,070 to może pomóc, jeśli piszę numery na wszystkie adresy tutaj. 84 00:06:44,070 --> 00:06:53,820 Wiemy, że na y, jesteśmy w adresie 14, x jest pod adresem 10. 85 00:06:53,820 --> 00:07:00,180 Kiedy zaczynamy w B, mamy dereference b, mamy zamiar pobrać wartość 2. 86 00:07:00,180 --> 00:07:08,320 Mamy zamiar chwycić tę wartość, ponieważ jest to wartość, która mieszka pod adresem 14. 87 00:07:08,320 --> 00:07:15,700 I mamy zamiar umieścić go w zmiennej, która mieszka pod adresem 10, 88 00:07:15,700 --> 00:07:19,160 który jest tam, odpowiadające naszej zmiennej x. 89 00:07:19,160 --> 00:07:21,810 Więc możemy zrobić trochę nadpisania tutaj 90 00:07:21,810 --> 00:07:35,380 gdzie pozbędziemy się naszego 1 i zamiast piszemy 2. 91 00:07:35,380 --> 00:07:39,560 Więc wszystko jest dobrze i dobra w świecie, chociaż mamy nadpisanych x teraz. 92 00:07:39,560 --> 00:07:44,890 Mamy zapisane starą wartość X w naszej zmiennej TMP. 93 00:07:44,890 --> 00:07:50,210 Więc możemy zakończyć swapa z następnego wiersza. 94 00:07:50,210 --> 00:07:53,030 Rzut z powrotem do naszego laptopa. 95 00:07:53,030 --> 00:07:58,150 Teraz pozostaje tylko podjąć zawartość z naszej zmiennej tymczasowej całkowitą 96 00:07:58,150 --> 00:08:05,630 i zapisać je do zmiennej, która mieszka pod adresem, który b trzyma. 97 00:08:05,630 --> 00:08:10,230 Więc będziemy skutecznie b dereference, aby uzyskać dostęp do zmiennej 98 00:08:10,230 --> 00:08:14,340 to, że na adres b posiada w tym, 99 00:08:14,340 --> 00:08:19,190 i jedziemy do rzeczy wartość, tmp jest gospodarstwo do niego. 100 00:08:19,190 --> 00:08:23,280 Rzut z powrotem do iPad raz. 101 00:08:23,280 --> 00:08:31,290 Mogę usunąć tę wartość tutaj, 2, 102 00:08:31,290 --> 00:08:41,010 i zamiast tego będziemy kopiować 1 prawo do niego. 103 00:08:41,010 --> 00:08:43,059 Potem następny wiersz, który wykonuje, oczywiście - 104 00:08:43,059 --> 00:08:47,150 jeśli mamy odwrócić z powrotem do laptopa - to jest punkt 6 105 00:08:47,150 --> 00:08:52,500 który jest punktem, w którym chcieliśmy mieć nasz diagram całkowicie wypełnione. 106 00:08:52,500 --> 00:08:58,940 Więc przerzucanie powrotem do iPada jeszcze raz, tak więc można zobaczyć wypełniony diagram, 107 00:08:58,940 --> 00:09:06,610 widać, że mamy 10 w, 14 w B, 1 w tmp, 2 w X i 1 w Y. 108 00:09:06,610 --> 00:09:11,000 Czy są jakieś pytania na ten temat? 109 00:09:11,000 --> 00:09:14,640 Czy to więcej sensu, po przejściu przez to? 110 00:09:14,640 --> 00:09:24,850 Dodać mniej sensu? Mam nadzieję, że nie. Okay. 111 00:09:24,850 --> 00:09:28,230 >> Wskaźniki są bardzo trudne podlega. 112 00:09:28,230 --> 00:09:33,420 Jeden z facetów, z którymi współpracujemy jest bardzo popularne powiedzenie: 113 00:09:33,420 --> 00:09:36,590 "Aby zrozumieć wskaźniki, należy najpierw zrozumieć wskaźniki". 114 00:09:36,590 --> 00:09:40,530 I myślę, że jest bardzo prawdziwe. Zajmuje to trochę czasu, aby przyzwyczaić się do niego. 115 00:09:40,530 --> 00:09:45,360 Czerpiąc wiele zdjęć, losowanie diagramów pamięci jak ten są bardzo pomocne, 116 00:09:45,360 --> 00:09:49,480 i po przejść przez np. po przykład po przykładzie 117 00:09:49,480 --> 00:09:54,450 będzie to początek, aby trochę więcej rozsądku i trochę więcej rozsądku i trochę więcej sensu. 118 00:09:54,450 --> 00:10:01,560 Wreszcie pewnego dnia, będziesz miał to wszystko całkowicie opanowane. 119 00:10:01,560 --> 00:10:13,800 Wszelkie pytania, zanim przejdziemy do następnego problemu? Dobrze. 120 00:10:13,800 --> 00:10:18,840 Więc przerzucić z powrotem do laptopa. 121 00:10:18,840 --> 00:10:23,300 Kolejnym problemem mamy wiele problemów 33 w pliku I / O. 122 00:10:23,300 --> 00:10:26,350 Powiększyć to trochę mało. 123 00:10:26,350 --> 00:10:28,710 Problem 33 - Tak? 124 00:10:28,710 --> 00:10:32,110 >> [Daniel] miałem tylko szybkie pytanie. Ta gwiazda lub gwiazdka, 125 00:10:32,110 --> 00:10:35,590 to się nazywa dereferencji kiedy użyć gwiazdki przed. 126 00:10:35,590 --> 00:10:38,820 Jak to się nazywa po użyciu ampersand wcześniej? 127 00:10:38,820 --> 00:10:43,140 >> Ampersand przed jest adres-operatora. 128 00:10:43,140 --> 00:10:45,880 Warto więc przejść z powrotem. 129 00:10:45,880 --> 00:10:49,310 Ups. Jestem w trybie powiększenia, tak naprawdę, nie mogę przewijania. 130 00:10:49,310 --> 00:10:52,780 Jeśli spojrzymy na ten kod bardzo szybko tu, 131 00:10:52,780 --> 00:10:54,980 ponownie, to samo się dzieje. 132 00:10:54,980 --> 00:10:59,180 Jeśli przyjrzymy się tym kodem właśnie tutaj, na tej linii, gdzie robimy wywołanie swap, 133 00:10:59,180 --> 00:11:10,460 ampersand jest tylko, że "dostać adres, pod którym mieszka zmiennej x". 134 00:11:10,460 --> 00:11:14,460 Gdy kompilator kompiluje kod, 135 00:11:14,460 --> 00:11:20,590 musi to faktycznie fizycznie zaznaczać miejsca w pamięci dla wszystkich zmiennych, aby żyć. 136 00:11:20,590 --> 00:11:24,910 I co z tego, że kompilator może wtedy zrobić, gdy to skompilowane wszystko 137 00:11:24,910 --> 00:11:31,110 wie, "Oh, I umieścić w adresie 10 x. kładę y pod adresem 14". 138 00:11:31,110 --> 00:11:34,640 Następnie może wypełnić tych wartości dla Ciebie. 139 00:11:34,640 --> 00:11:44,740 Więc możesz - to może następnie przekazać to na przełęczy i & Y w, jak również. 140 00:11:44,740 --> 00:11:50,730 Te Chłopaki uzyskać adres, ale także, kiedy przekazać je do funkcji swap 141 00:11:50,730 --> 00:11:55,690 informacje typu, to int * tu, informuje kompilator, 142 00:11:55,690 --> 00:12:01,350 "Dobra, idziemy do interpretacji tego adresu jako adresu zmiennej całkowitej." 143 00:12:01,350 --> 00:12:05,900 Jako adres int, które różni się od adresu zmiennej znaków 144 00:12:05,900 --> 00:12:09,930 bo int zajmuje, na komputerze 32-bitowym, zajmuje 4 bajty przestrzeni, 145 00:12:09,930 --> 00:12:13,310 natomiast znak zajmuje tylko 1 bajt miejsca. 146 00:12:13,310 --> 00:12:17,310 Tak więc ważne jest, aby wiedzieć, co jest również - co żyje, jaki typ wartości 147 00:12:17,310 --> 00:12:20,340 mieszka pod adresem, który dostał przeszedł w. 148 00:12:20,340 --> 00:12:22,020 Lub adres, który ma się do czynienia. 149 00:12:22,020 --> 00:12:29,020 W ten sposób, wiesz, ile bajtów informacji faktycznie załadować z pamięci RAM. 150 00:12:29,020 --> 00:12:31,780 I wtedy, tak, to operator dereference, jak ty pytali, 151 00:12:31,780 --> 00:12:37,200 idzie i dostęp do informacji w danym adresem. 152 00:12:37,200 --> 00:12:42,820 Więc to mówi, z tym zmiennej tu traktować zawartość jako adres, 153 00:12:42,820 --> 00:12:47,880 przejść do tego adresu, i wyciągnąć, załadować do procesora, obciążenie do rejestru 154 00:12:47,880 --> 00:12:56,340 rzeczywiste wartości lub treści, które żyją pod tym adresem. 155 00:12:56,340 --> 00:12:59,620 Więcej pytań? To są dobre pytania. 156 00:12:59,620 --> 00:13:01,650 To dużo nowej terminologii zbyt. 157 00:13:01,650 --> 00:13:09,800 Jest to także rodzaj funky, widząc & i * w różnych miejscach. 158 00:13:09,800 --> 00:13:13,180 >> Dobrze. 159 00:13:13,180 --> 00:13:18,530 Wracając do problemu 33, plik I / O. 160 00:13:18,530 --> 00:13:22,540 Był to jeden z tych problemów, które myślę, że parę rzeczy się wydarzyło. 161 00:13:22,540 --> 00:13:25,400 Raz, że to dość nowy temat. 162 00:13:25,400 --> 00:13:30,590 Został przedstawiony wkrótce przed quizie, 163 00:13:30,590 --> 00:13:33,400 i myślę, że to było trochę jak jeden z tych problemów, słów w matematyce 164 00:13:33,400 --> 00:13:39,720 gdzie dają ci wiele informacji, ale faktycznie nie kończy się konieczności korzystania mnóstwo niego. 165 00:13:39,720 --> 00:13:44,060 Pierwsza część tego problemu jest opisanie tego, co jest plik CSV. 166 00:13:44,060 --> 00:13:50,620 Teraz, CSV, zgodnie z opisem, jest rozdzielona przecinkami plik wartości. 167 00:13:50,620 --> 00:13:55,300 Powodem są to w ogóle ciekawe, i powód, dla którego nigdy ich używać, 168 00:13:55,300 --> 00:14:00,800 jest, ponieważ, jak wielu z was kiedykolwiek używane rzeczy, jak Excel? 169 00:14:00,800 --> 00:14:03,240 Rysunek większość z was, prawdopodobnie lub będą używać w jakimś momencie swojego życia. 170 00:14:03,240 --> 00:14:06,430 Możesz używać coś jak Excel. 171 00:14:06,430 --> 00:14:10,940 Aby pobrać dane z arkusza kalkulacyjnego Excel czy jakiejkolwiek obróbki z nim, 172 00:14:10,940 --> 00:14:17,240 jeśli chcesz napisać program w C lub program Pythona, program Java, 173 00:14:17,240 --> 00:14:20,070 do czynienia z danymi, które zostały zapisane w tam, 174 00:14:20,070 --> 00:14:23,170 jeden z najbardziej popularnych sposobów, aby uzyskać ją w pliku CSV. 175 00:14:23,170 --> 00:14:26,850 I można otworzyć program Excel i kiedy idziesz do 'Save As' dialogu, 176 00:14:26,850 --> 00:14:32,840 można dostać się rzeczywistą pliku CSV. 177 00:14:32,840 --> 00:14:35,890 >> Handy wiedzieć, jak radzić sobie z tych rzeczy. 178 00:14:35,890 --> 00:14:42,010 Jak to działa jest to, że jest podobny do - mam na myśli, to jest w istocie naśladuje arkusz kalkulacyjny, 179 00:14:42,010 --> 00:14:47,590 gdzie, jak widzimy tutaj, w bardzo skrajny lewy kawałek, 180 00:14:47,590 --> 00:14:49,910 mamy wszystkie nazwiska. 181 00:14:49,910 --> 00:14:54,670 Więc mamy Malan, następnie Hardison, a następnie Bowden, MacWilliam, a następnie Chan. 182 00:14:54,670 --> 00:14:59,470 Wszystkie nazwiska. A potem przecinek oddziela nazwiska od imion. 183 00:14:59,470 --> 00:15:02,970 David, Nate, Rob, Tommy, i Zamyla. 184 00:15:02,970 --> 00:15:06,850 Zawsze mieszać Robby i Toma. 185 00:15:06,850 --> 00:15:10,940 A potem, w końcu, trzecia kolumna to adresy e-mail. 186 00:15:10,940 --> 00:15:18,500 Kiedy zrozumiesz, że reszta z programu jest bardzo prosta do wykonania. 187 00:15:18,500 --> 00:15:23,850 Co mamy zrobić, aby naśladować tę samą strukturę w naszym programie C 188 00:15:23,850 --> 00:15:27,510 jest używaliśmy strukturę. 189 00:15:27,510 --> 00:15:30,520 Zaczniemy grać z nich niewiele więcej, jak również. 190 00:15:30,520 --> 00:15:35,790 Widzieliśmy ich na pierwszy bit w zestawie małego problemu 3, gdy mamy do czynienia ze słowników. 191 00:15:35,790 --> 00:15:40,290 Ale to struct personel przechowuje nazwisko, imię oraz e-mail. 192 00:15:40,290 --> 00:15:44,500 Tak jak nasz plik CSV został przechowywania. 193 00:15:44,500 --> 00:15:47,950 Tak więc jest to po prostu konwersji z jednego formatu na drugi. 194 00:15:47,950 --> 00:15:54,630 Mamy do konwersji, w tym przypadku, struct personelu do linii, 195 00:15:54,630 --> 00:15:59,060 oddzielonych przecinkami line, tak po prostu. 196 00:15:59,060 --> 00:16:01,500 Czy to ma sens? Wy wszyscy wziąć udział w quizie, 197 00:16:01,500 --> 00:16:07,680 więc wyobraź sobie, że przynajmniej miał trochę czasu, aby pomyśleć o tym. 198 00:16:07,680 --> 00:16:16,410 >> W funkcji najmu, problem prosi nas do podjęcia się - we'll powiększyć to trochę mało - 199 00:16:16,410 --> 00:16:22,480 podjąć w strukturze personelu, struct personel, z nazwiskiem, 200 00:16:22,480 --> 00:16:30,900 i dodać jego zawartość do naszego pliku staff.csv. 201 00:16:30,900 --> 00:16:34,230 Okazuje się, że jest to dość proste w użyciu. 202 00:16:34,230 --> 00:16:37,430 Będziemy trochę bawić z tych funkcji nieco więcej dzisiaj. 203 00:16:37,430 --> 00:16:44,510 Ale w tym przypadku, fprintf funkcja jest naprawdę kluczem. 204 00:16:44,510 --> 00:16:51,960 Więc z fprintf, możemy wydrukować, tak jak wy zostały przy użyciu printf cały ten okres. 205 00:16:51,960 --> 00:16:55,050 Możesz printf linii do pliku. 206 00:16:55,050 --> 00:16:59,030 Zamiast więc co zwykłe printf gdzie nadać mu ciąg formatu 207 00:16:59,030 --> 00:17:05,380 a następnie zamienić wszystkie zmienne z następującymi argumentami, 208 00:17:05,380 --> 00:17:11,290 z fprintf, twój pierwszy argument to zamiast plik, który chcesz zapisać. 209 00:17:11,290 --> 00:17:21,170 Gdybyśmy się w tym miejscu do urządzenia, na przykład, człowieka fprintf, 210 00:17:21,170 --> 00:17:25,980 widać różnicę między printf i fprintf. 211 00:17:25,980 --> 00:17:28,960 Będę przybliżyć tutaj trochę. 212 00:17:28,960 --> 00:17:33,140 Więc z printf, dajemy mu ciąg formatu, a następnie kolejne argumenty 213 00:17:33,140 --> 00:17:37,580 są wszystkie zmienne dla wymiany lub zastąpienia w naszym łańcuchu formatu. 214 00:17:37,580 --> 00:17:47,310 Natomiast w fprintf, pierwszy argument jest rzeczywiście ten plik * zwany strumień. 215 00:17:47,310 --> 00:17:51,800 >> Wracając do naszego tu wynajem, 216 00:17:51,800 --> 00:17:54,550 już mamy nasz strumień plik * otworzył dla nas. 217 00:17:54,550 --> 00:17:57,810 To właśnie ten pierwszy wiersz robi, to otwiera plik staff.csv, 218 00:17:57,810 --> 00:18:01,690 otworzy go w trybie dopisywania, i wszystko, co nam pozostało do zrobienia jest 219 00:18:01,690 --> 00:18:08,640 napisz strukturę personelu do pliku. 220 00:18:08,640 --> 00:18:10,870 I zobaczymy, czy chcę korzystać z iPada? 221 00:18:10,870 --> 00:18:17,900 Użyję iPada. Mamy pustkę - Postawmy to na stole, więc można napisać trochę lepiej - 222 00:18:17,900 --> 00:18:33,680 unieważnić wynajem i trwa w jednym argumentem, struktury kadrowej nazwie s. 223 00:18:33,680 --> 00:18:44,120 Dostaliśmy nasze szelki, mamy nasz plik * nazwie pliku, 224 00:18:44,120 --> 00:18:48,380 mamy linię fopen nam dany, 225 00:18:48,380 --> 00:18:51,890 a ja po prostu piszę to jak kropki, ponieważ jest już w Pedia. 226 00:18:51,890 --> 00:19:00,530 I wtedy na naszej następnej linii, mamy zamiar połączyć się fprintf 227 00:19:00,530 --> 00:19:03,700 i zamierzamy przekazać w pliku, który chcemy drukować, 228 00:19:03,700 --> 00:19:10,290 i nasz ciąg formatu, który - 229 00:19:10,290 --> 00:19:14,300 Powiem wam powiedzieć, jak to wygląda. 230 00:19:14,300 --> 00:19:20,500 Jak o tobie, Stella? Czy wiesz, co pierwsza część łańcucha formatu wygląda? 231 00:19:20,500 --> 00:19:24,270 [Stella] Nie jestem pewien. >> Zapraszam do zadawania Jimmy. 232 00:19:24,270 --> 00:19:27,690 Czy wiesz, Jimmy? 233 00:19:27,690 --> 00:19:31,000 [Jimmy] Czy to tylko ostatni? Nie wiem. Nie jestem do końca pewien. 234 00:19:31,000 --> 00:19:39,020 >> Okay. Jak o, czy ktoś dostać to poprawne na egzaminie? 235 00:19:39,020 --> 00:19:41,770 No dobrze. 236 00:19:41,770 --> 00:19:47,920 Okazuje się, że tutaj wszystko, co musimy zrobić, to chcemy każdą część naszej struktury kadrowej 237 00:19:47,920 --> 00:19:53,290 być wydrukowane jako ciąg do naszego pliku. 238 00:19:53,290 --> 00:19:59,900 My po prostu używać znaku podstawiania łańcuchów tekstowych trzy razy, ponieważ mamy nazwisko 239 00:19:59,900 --> 00:20:07,160 następuje przecinek, to imię po nim przecinek, 240 00:20:07,160 --> 00:20:12,430 i wreszcie email który jest następnie - co nie jest 241 00:20:12,430 --> 00:20:15,140 zamontowania na ekranie - ale to następuje znak nowej linii. 242 00:20:15,140 --> 00:20:20,060 Więc mam zamiar napisać to właśnie tam. 243 00:20:20,060 --> 00:20:23,560 I wtedy po naszej ciąg formatu, 244 00:20:23,560 --> 00:20:27,880 musimy tylko podstawienia, które mamy dostęp za pomocą notacji dot 245 00:20:27,880 --> 00:20:31,370 że widzieliśmy w zestawie problemu 3. 246 00:20:31,370 --> 00:20:48,820 Możemy użyć s.last, s.first i s.email 247 00:20:48,820 --> 00:20:58,990 zastąpić w tych trzech wartości do naszego łańcucha formatu. 248 00:20:58,990 --> 00:21:06,190 Więc jak poszło? Ma sens? 249 00:21:06,190 --> 00:21:09,700 Tak? No? Być może? Okay. 250 00:21:09,700 --> 00:21:14,180 >> Ostatnią rzeczą, że robimy po mamy wydrukowane i po my otworzyliśmy nasz plik: 251 00:21:14,180 --> 00:21:17,370 gdy mamy otwarty plik, musimy zawsze pamiętać, aby je zamknąć. 252 00:21:17,370 --> 00:21:19,430 Bo inaczej skończymy wyciek pamięci, 253 00:21:19,430 --> 00:21:22,500 stosując się deskryptory plików. 254 00:21:22,500 --> 00:21:25,950 Tak więc, aby go zamknąć, która funkcja używamy? Daniel? 255 00:21:25,950 --> 00:21:30,120 [Daniel] fclose? >> Fclose, dokładnie. 256 00:21:30,120 --> 00:21:37,520 Więc ostatnia część tego problemu było prawidłowo zamknąć plik, używając funkcji fclose, 257 00:21:37,520 --> 00:21:40,370 który po prostu wygląda. 258 00:21:40,370 --> 00:21:43,880 Nie zbyt szalone. 259 00:21:43,880 --> 00:21:46,990 Cool. 260 00:21:46,990 --> 00:21:49,520 Więc to jest problem, 33 na quiz. 261 00:21:49,520 --> 00:21:52,480 Musimy zdecydowanie więcej plik I / O zbliża. 262 00:21:52,480 --> 00:21:55,130 Zrobimy trochę więcej w wykładzie dzisiaj, lub w sekcji dziś 263 00:21:55,130 --> 00:22:01,710 bo to, co się stanowią większość nadchodzącej PSET. 264 00:22:01,710 --> 00:22:05,020 Przejdźmy od quizu w tym momencie. Tak? 265 00:22:05,020 --> 00:22:10,880 >> [Charlotte]] Dlaczego fclose (plik) zamiast fclose (staff.csv)? 266 00:22:10,880 --> 00:22:19,100 >> Ah. Ponieważ okazuje się, że - tak na pytanie, co jest wielki, 267 00:22:19,100 --> 00:22:27,800 Dlatego też, kiedy piszemy fclose, jesteśmy piśmie fclose (plik), gwiazda zmienna 268 00:22:27,800 --> 00:22:33,680 w przeciwieństwie do nazwy pliku, staff.csv? Czy to prawda? Tak. 269 00:22:33,680 --> 00:22:39,570 Warto więc spojrzeć. Jeśli mam wrócić do mojego laptopa, 270 00:22:39,570 --> 00:22:45,040 i spójrzmy na fclose funkcji. 271 00:22:45,040 --> 00:22:51,460 Więc fclose Zamyka strumień i trwa w wskaźnik do strumienia, który chcemy zamknąć, 272 00:22:51,460 --> 00:22:57,010 w przeciwieństwie do rzeczywistej nazwy pliku, który chcemy zamknąć. 273 00:22:57,010 --> 00:23:01,620 A to dlatego, że za kulisami, kiedy nawiązać połączenie z fopen, 274 00:23:01,620 --> 00:23:12,020 po otwarciu pliku, jesteś rzeczywiście przydzielania pamięci do przechowywania informacji o pliku. 275 00:23:12,020 --> 00:23:16,380 Więc masz wskaźnik pliku, który posiada informacje na temat pliku, 276 00:23:16,380 --> 00:23:23,080 jak to jest otwarte, jego rozmiar, w którym się aktualnie w pliku, 277 00:23:23,080 --> 00:23:29,100 tak, że można dokonać odczytu i zapisu połączeń do danego miejsca w pliku. 278 00:23:29,100 --> 00:23:38,060 Skończyć się zamknięciem wskaźnik zamiast zamykania nazwę pliku. 279 00:23:38,060 --> 00:23:48,990 >> Tak? [Daniel] Aby więc używać wynajem, można by powiedzieć - jak to uzyskać dane wejściowe użytkownika? 280 00:23:48,990 --> 00:23:53,830 Czy fprintf działać jak getString w tym sensie, że będzie to tylko czekać na wejście użytkownika 281 00:23:53,830 --> 00:23:57,180 i poprosić o wpisanie tego - albo czekać na wpisanie tych trzech rzeczy? 282 00:23:57,180 --> 00:24:00,480 Czy trzeba użyć coś wdrożyć wynajem? 283 00:24:00,480 --> 00:24:04,100 >> Tak. Więc nie jesteśmy - pytanie, w jaki sposób możemy uzyskać dane wejściowe użytkownika 284 00:24:04,100 --> 00:24:09,220 w celu realizacji zleceń? I co my tu mamy to rozmówca najmu 285 00:24:09,220 --> 00:24:17,690 uchwalona w tej struktury personelu z wszystkich danych przechowywanych w struktury już. 286 00:24:17,690 --> 00:24:22,990 Więc fprintf jest w stanie po prostu napisać, że dane bezpośrednio do pliku. 287 00:24:22,990 --> 00:24:25,690 Nie ma oczekiwania na polecenia użytkownika. 288 00:24:25,690 --> 00:24:32,110 Użytkownik już podane wejście przez odpowiednio umieszczając go w tej struktury personelu. 289 00:24:32,110 --> 00:24:36,510 I rzeczy, oczywiście, pęknie, jeśli którykolwiek z tych wskaźników były null, 290 00:24:36,510 --> 00:24:40,370 więc przesunąć się z powrotem tu i patrzymy na nasze struktury. 291 00:24:40,370 --> 00:24:43,640 Mamy ciąg ostatni, ciąg 1-ci, email string. 292 00:24:43,640 --> 00:24:48,530 Teraz wiemy, że wszystkie te, tak naprawdę, pod maską, są zmienne char *. 293 00:24:48,530 --> 00:24:53,470 , Które mogą lub nie mogą być skierowane do zera. 294 00:24:53,470 --> 00:24:55,800 Mogą być one w pamięci, wskazując na sterty, 295 00:24:55,800 --> 00:24:59,650 Może pamięci na stosie. 296 00:24:59,650 --> 00:25:04,580 Tak naprawdę nie wiem, ale jeśli któryś z tych wskaźników są nieważne lub nieważne, 297 00:25:04,580 --> 00:25:08,120 że będziemy zdecydowanie awarię naszą funkcję zatrudnić. 298 00:25:08,120 --> 00:25:11,050 To było coś, co było trochę poza zakres egzaminu. 299 00:25:11,050 --> 00:25:16,440 Nie martwisz się o to. 300 00:25:16,440 --> 00:25:22,170 Great. Okay. Więc odejście od quizu. 301 00:25:22,170 --> 00:25:25,760 >> Miejmy zamknąć tego faceta, i będziemy patrzeć na Pset 4. 302 00:25:25,760 --> 00:25:34,700 Więc jeśli macie spojrzeć na specyfikację PSET, raz można go otworzyć, cs50.net/quizzes, 303 00:25:34,700 --> 00:25:42,730 mamy zamiar przejść przez kilka problemów sekcji dziś. 304 00:25:42,730 --> 00:25:52,240 Jestem przewijając - sekcja pytań zaczyna się w trzeciej stronie spec PSET. 305 00:25:52,240 --> 00:25:57,800 I pierwsza część prosi, aby przejść i obejrzeć krótki na przekierowanie i rur. 306 00:25:57,800 --> 00:26:02,820 Który był rodzaj fajne krótkie, pokazuje nowe, fajne sztuczki wiersza polecenia, których można użyć. 307 00:26:02,820 --> 00:26:06,050 A potem mamy kilka pytań do Ciebie. 308 00:26:06,050 --> 00:26:10,860 To pierwsze pytanie o strumieniach, do których pisze printf domyślnie 309 00:26:10,860 --> 00:26:15,920 my niby dotknął tylko trochę chwilą. 310 00:26:15,920 --> 00:26:22,380 Ten fprintf że właśnie omawialiśmy trwa w strumieniu pliku * jako argument. 311 00:26:22,380 --> 00:26:26,580 fclose odbywa się w strumieniu pliku *, jak również, 312 00:26:26,580 --> 00:26:32,660 i wartość zwracana fopen daje strumień pliku *, jak również. 313 00:26:32,660 --> 00:26:36,060 Powodem nie widzieliśmy tych wcześniej, kiedy mamy do czynienia z printf 314 00:26:36,060 --> 00:26:39,450 dlatego printf ma strumień domyślny. 315 00:26:39,450 --> 00:26:41,810 I strumień domyślna, do której pisze 316 00:26:41,810 --> 00:26:45,190 dowiesz się na temat, w skrócie. 317 00:26:45,190 --> 00:26:50,080 Więc na pewno spojrzeć na niego. 318 00:26:50,080 --> 00:26:53,010 >> W dzisiejszej części będziemy mówić trochę o GDB, 319 00:26:53,010 --> 00:26:57,720 ponieważ bardziej zaznajomieni jesteście z nim, więcej praktyki masz z nim, 320 00:26:57,720 --> 00:27:01,390 lepiej będziesz faktycznie wytropić błędy w swoim kodzie. 321 00:27:01,390 --> 00:27:05,540 Przyspiesza to proces debugowania się ogromnie. 322 00:27:05,540 --> 00:27:09,230 Więc za pomocą printf, za każdym razem zrobić, że trzeba przebudować kod 323 00:27:09,230 --> 00:27:13,000 trzeba uruchomić go ponownie, czasem trzeba przesunąć printf wokół, 324 00:27:13,000 --> 00:27:17,100 ustosunkowania się kod, to po prostu trwa. 325 00:27:17,100 --> 00:27:20,850 Naszym celem jest, aby spróbować i przekonać się, że z GDB, można zasadniczo 326 00:27:20,850 --> 00:27:26,810 printf wszystko w dowolnym miejscu w kodzie, a ty nigdy nie musiał przekompilować. 327 00:27:26,810 --> 00:27:35,120 Nigdy nie musisz uruchomić i utrzymać zgadywania gdzie printf następny. 328 00:27:35,120 --> 00:27:40,910 Pierwszą rzeczą do zrobienia jest, aby skopiować ten wiersz i otrzymać kod sekcji wyłączać z sieci. 329 00:27:40,910 --> 00:27:47,530 Jestem kopiowanie tego wiersza kodu, który mówi: "wget ​​http://cdn.cs50.net". 330 00:27:47,530 --> 00:27:49,510 Zamierzam go skopiować. 331 00:27:49,510 --> 00:27:55,950 Mam zamiar iść do mojego urządzenia, pomniejszyć, dzięki czemu można zobaczyć, co robię, 332 00:27:55,950 --> 00:28:01,890 wklejenie go tam, a kiedy nacisnąć enter, to wget polecenie dosłownie to internetowy dostać. 333 00:28:01,890 --> 00:28:06,210 To będzie ciągnąć w dół ten plik z internetu, 334 00:28:06,210 --> 00:28:11,790 i to będzie zapisać go w bieżącym katalogu. 335 00:28:11,790 --> 00:28:21,630 Teraz, jeśli wymienię mój bieżący katalog można zobaczyć, że mam ten plik prawym section5.zip tam. 336 00:28:21,630 --> 00:28:25,260 Sposobem radzenia sobie z tym facetem jest do rozpakowania go, 337 00:28:25,260 --> 00:28:27,650 co można zrobić w linii poleceń, tak jak to. 338 00:28:27,650 --> 00:28:31,880 Section5.zip. 339 00:28:31,880 --> 00:28:36,980 To będzie rozpakuj go, utworzyć folder dla mnie, 340 00:28:36,980 --> 00:28:40,410 nadmuchać całą zawartość, umieścić je w środku. 341 00:28:40,410 --> 00:28:47,410 Więc teraz mogę iść do mojej sekcji 5 katalogu za pomocą komendy cd. 342 00:28:47,410 --> 00:28:58,310 Wyczyść ekran za pomocą jasne. Więc wyczyścić ekran. 343 00:28:58,310 --> 00:29:02,280 Teraz mam ładne czyste terminal do czynienia. 344 00:29:02,280 --> 00:29:06,200 >> Teraz jeśli lista wszystkich plików, które widzę w tym katalogu, 345 00:29:06,200 --> 00:29:12,270 widzisz, że mam cztery pliki: buggy1, buggy2, buggy3 i buggy4. 346 00:29:12,270 --> 00:29:16,180 Ja również, ale ich odpowiednie. Plików C. 347 00:29:16,180 --> 00:29:20,400 Nie będziemy patrzeć na plików. C teraz. 348 00:29:20,400 --> 00:29:24,140 Zamiast tego, mamy zamiar je wykorzystać, kiedy otwieramy GDB. 349 00:29:24,140 --> 00:29:28,220 Musimy na bieżąco je się tak, że mamy dostęp do kodu źródłowego, gdy rzeczywisty używamy GDB, 350 00:29:28,220 --> 00:29:32,740 ale celem tej części rozdziału jest majstrować wokół z GDB 351 00:29:32,740 --> 00:29:40,370 i zobaczyć, w jaki sposób możemy go użyć, aby dowiedzieć się co się dzieje nie tak z każdym z tych czterech programów buggy. 352 00:29:40,370 --> 00:29:43,380 Więc jesteśmy po prostu się po pokoju bardzo szybko, 353 00:29:43,380 --> 00:29:47,000 i mam zamiar poprosić kogoś do uruchomienia jednego z wadliwymi programami 354 00:29:47,000 --> 00:29:54,730 a potem pójdziemy jako grupa przez GDB, a my zobaczymy, co możemy zrobić, aby naprawić te programy, 355 00:29:54,730 --> 00:29:58,460 lub przynajmniej określić, co się dzieje złego w każdym z nich. 356 00:29:58,460 --> 00:30:04,760 Zacznijmy tu z Danielem. Wpadniemy buggy1? Zobaczmy, co się dzieje. 357 00:30:04,760 --> 00:30:09,470 [Daniel] To mówi, że jest błąd aplikacji. >> Tak. Dokładnie. 358 00:30:09,470 --> 00:30:12,460 Więc jeśli mogę uruchomić buggy1, mam SEG usterkę. 359 00:30:12,460 --> 00:30:16,210 W tym momencie, mogę iść i otworzyć buggy1.c, 360 00:30:16,210 --> 00:30:19,450 spróbować dowiedzieć się, co się dzieje nie tak, 361 00:30:19,450 --> 00:30:22,000 ale jeden z najbardziej okropnych rzeczy o tym seg błędu błędu 362 00:30:22,000 --> 00:30:27,610 jest to, że nie mówi nam, co linia z rzeczy program rzeczywiście poszło źle i złamał. 363 00:30:27,610 --> 00:30:29,880 Jesteś rodzaju trzeba patrzeć na kod 364 00:30:29,880 --> 00:30:33,990 i dowiedzieć się, za pomocą przypuszczenia i sprawdzić czy printf, aby zobaczyć, co się dzieje źle. 365 00:30:33,990 --> 00:30:37,840 Jedną z najfajniejszych rzeczy w GDB jest to, że tak naprawdę, naprawdę łatwe 366 00:30:37,840 --> 00:30:42,170 aby dowiedzieć się, na którym twój wiersz awarii programu. 367 00:30:42,170 --> 00:30:46,160 Jest całkowicie warto go używać, nawet jeśli tylko na to. 368 00:30:46,160 --> 00:30:56,190 Więc do rozruchu GDB, wpisuję GDB, a potem dać mu ścieżkę do pliku wykonywalnego, który chcę uruchomić. 369 00:30:56,190 --> 00:31:01,960 Tutaj piszę gdb ./buggy1. 370 00:31:01,960 --> 00:31:06,600 Naciśnij klawisz Enter. Daje mi wszystkie informacje o prawach autorskich, 371 00:31:06,600 --> 00:31:13,000 i tu zobaczysz ten wiersz, który mówi, "czytanie symboli z / home / 372 00:31:13,000 --> 00:31:17,680 jharvard/section5/buggy1 ". 373 00:31:17,680 --> 00:31:22,060 A jeśli wszystko pójdzie dobrze, zobaczysz, to wydrukować wiadomość, że wygląda tak. 374 00:31:22,060 --> 00:31:25,500 Będzie czytać symbole, to będzie powiedzieć "Czytam symboli z pliku wykonywalnego" 375 00:31:25,500 --> 00:31:29,900 a następnie będzie miał ten "Gotowe" wiadomość tutaj. 376 00:31:29,900 --> 00:31:35,410 Jeśli widzisz jakiś inny wariant tego, czy widzisz, że nie mógł znaleźć symbole 377 00:31:35,410 --> 00:31:41,460 lub coś w tym stylu, co to oznacza to, że po prostu nie skompilowaniu wykonywalny prawidłowo. 378 00:31:41,460 --> 00:31:49,980 Kiedy kompilować programy do użytku z GDB, musimy użyć tego specjalnego flagę g, 379 00:31:49,980 --> 00:31:54,540 i że zrobił domyślnie jeśli kompilacji programów, po prostu przez wpisanie się 380 00:31:54,540 --> 00:31:59,320 lub dokonać buggy lub dokonać zwrotu, każdy z nich. 381 00:31:59,320 --> 00:32:07,800 Ale jeśli jesteś kompilacji ręcznie Clang, będziesz musiał iść i to, że-g banderą. 382 00:32:07,800 --> 00:32:10,310 >> W tym momencie, że teraz mamy GDB polecenia, 383 00:32:10,310 --> 00:32:12,310 jest to dość proste do uruchomienia programu. 384 00:32:12,310 --> 00:32:19,740 Możemy wpisać słowo lub możemy po prostu wpisać r. 385 00:32:19,740 --> 00:32:22,820 Większość komend GDB może być skrócona. 386 00:32:22,820 --> 00:32:25,940 Wysyłka do tylko jednej lub kilku liter, które jest bardzo ładne. 387 00:32:25,940 --> 00:32:30,980 Więc Saad, jeśli typ R i naciśnij klawisz Enter, co się dzieje? 388 00:32:30,980 --> 00:32:39,390 [Saad] Mam SIGSEGV, Segmentation fault, a następnie cały ten bełkot. 389 00:32:39,390 --> 00:32:43,650 >> Tak. 390 00:32:43,650 --> 00:32:47,990 Jak widzimy na ekranie, teraz, i jak Saad powiedział, 391 00:32:47,990 --> 00:32:53,430 kiedy wpisać słowo lub R i naciśnij klawisz Enter, ale wciąż ten sam błąd SEG. 392 00:32:53,430 --> 00:32:55,830 Więc za pomocą GDB nie rozwiązuje naszego problemu. 393 00:32:55,830 --> 00:32:59,120 Ale daje nam trochę bełkot, a okazuje się, że to bełkot 394 00:32:59,120 --> 00:33:03,080 rzeczywiście mówi nam, gdzie to się dzieje. 395 00:33:03,080 --> 00:33:10,680 Do obrabiania tego trochę, to pierwszy bit jest funkcja, w której wszystko się dzieje źle. 396 00:33:10,680 --> 00:33:20,270 Jest taki __ strcmp_sse4_2, i mówi nam, że to się dzieje w tym pliku 397 00:33:20,270 --> 00:33:29,450 nazywa sysdeps/i386, wszystko to, ponownie, rodzaj bałaganu - ale linia 254. 398 00:33:29,450 --> 00:33:31,670 To trochę trudne do analizowania. Zazwyczaj, gdy widzisz rzeczy, jak to, 399 00:33:31,670 --> 00:33:38,770 co oznacza, że ​​jest seg uskoki w jednym z bibliotek systemowych. 400 00:33:38,770 --> 00:33:43,220 Więc coś z strcmp. Wy widzieliście strcmp wcześniej. 401 00:33:43,220 --> 00:33:52,730 Nie zbyt szalone, ale to znaczy, że strcmp jest uszkodzony lub, że jest problem z strcmp? 402 00:33:52,730 --> 00:33:57,110 Co sądzisz, Alexander? 403 00:33:57,110 --> 00:34:04,890 [Alexander] Czy to - jest 254 linii? I - nie binarny, ale to nie jest ich sufity, 404 00:34:04,890 --> 00:34:10,590 a potem jeszcze jeden język dla każdej funkcji. Jest to, że w tym funkcji 254, lub -? 405 00:34:10,590 --> 00:34:21,460 >> To linia 254. To wygląda jak w tym pliku. S, więc jest to kod assemblera prawdopodobnie. 406 00:34:21,460 --> 00:34:25,949 >> Ale, myślę, że bardziej palące jest to, ponieważ mamy zdobyć Seg winy, 407 00:34:25,949 --> 00:34:29,960 i wygląda na to, że pochodzi z strcmp funkcji 408 00:34:29,960 --> 00:34:38,030 to oznacza więc, że strcmp jest zepsuty? 409 00:34:38,030 --> 00:34:42,290 Nie powinno, mam nadzieję. Tak tylko dlatego, że masz winy segmentacji 410 00:34:42,290 --> 00:34:49,480 W jednej z funkcji systemu, zwykle oznacza to, że po prostu nie są nazywane prawidłowo. 411 00:34:49,480 --> 00:34:52,440 Najszybszym rzeczą dowiedzieć się, co się właściwie dzieje 412 00:34:52,440 --> 00:34:55,500 gdy widzisz coś szalonego jak to, gdy zobaczysz Seg winy, 413 00:34:55,500 --> 00:34:59,800 zwłaszcza jeśli masz program, który używa więcej niż tylko main, 414 00:34:59,800 --> 00:35:03,570 jest użycie prześledzić. 415 00:35:03,570 --> 00:35:13,080 I skrót backtrace pisząc bt, w przeciwieństwie do pełnej wyrazu backtrace. 416 00:35:13,080 --> 00:35:16,510 Ale Charlotte, co się dzieje, po wpisaniu bt i naciśnij klawisz Enter? 417 00:35:16,510 --> 00:35:23,200 [Charlotte] To pokazuje mi dwie linie, linia 0 i linia 1. 418 00:35:23,200 --> 00:35:26,150 >> Tak. Więc linia 0 i linia 1. 419 00:35:26,150 --> 00:35:34,560 Są to rzeczywiste ramki stosu, które były aktualnie w grze, gdy Twój program rozbił. 420 00:35:34,560 --> 00:35:42,230 Zaczynając od najwyższej ramki, ramki 0, a idąc do dołu najbardziej, czyli ramka 1. 421 00:35:42,230 --> 00:35:45,140 Nasza najwyższa rama jest strcmp frame. 422 00:35:45,140 --> 00:35:50,080 Można myśleć o tym, jako podobny do tego problemu, byliśmy po prostu robi w quizie ze wskaźników, 423 00:35:50,080 --> 00:35:54,890 gdzie mieliśmy zamienić ramkę stosu na górze głównej ramki stosu, 424 00:35:54,890 --> 00:35:59,700 i mieliśmy zmienne, które zamienią się na górze za pomocą zmiennych, że główny został za pomocą. 425 00:35:59,700 --> 00:36:08,440 Oto nasza Crash się w naszym strcmp funkcji, która została wywołana przez naszą główną funkcję, 426 00:36:08,440 --> 00:36:14,370 i backtrace daje nam nie tylko funkcje, w której rzeczy nieudane, 427 00:36:14,370 --> 00:36:16,440 Ale jest to także mówi nam, gdzie wszystko zostało wywołane. 428 00:36:16,440 --> 00:36:18,830 Więc jeśli przewijania nad nieco bardziej w prawo, 429 00:36:18,830 --> 00:36:26,110 widzimy, że tak, że byliśmy na linii 254 tego pliku strcmp-sse4.s. 430 00:36:26,110 --> 00:36:32,540 Ale połączenie zostało dokonane na buggy1.c, linia 6. 431 00:36:32,540 --> 00:36:35,960 To znaczy, że możemy to zrobić - to możemy po prostu iść sprawdzić i zobaczyć, co się dzieje 432 00:36:35,960 --> 00:36:39,930 w buggy1.c, linia 6. 433 00:36:39,930 --> 00:36:43,780 Ponownie, istnieje kilka sposobów, aby to zrobić. Jednym z nich jest, aby wyjść z GDB 434 00:36:43,780 --> 00:36:49,460 lub mieć kod otworzyć w innym oknie i zidentyfikowanie. 435 00:36:49,460 --> 00:36:54,740 To, samo w sobie, jest bardzo przydatny, ponieważ teraz, gdy jesteś w godzinach urzędowania 436 00:36:54,740 --> 00:36:57,220 i masz SEG usterkę a TF zastanawia się, gdzie wszystko było łamanie, 437 00:36:57,220 --> 00:36:59,710 można po prostu powiedzieć: "Och, linia 6. I nie wiem, co się dzieje, 438 00:36:59,710 --> 00:37:03,670 ale coś o linii 6 powoduje mój program do złamania ". 439 00:37:03,670 --> 00:37:10,430 Inny sposób to zrobić to możesz użyć tego polecenia o nazwie lista w GDB. 440 00:37:10,430 --> 00:37:13,650 Możesz również skrócić go l. 441 00:37:13,650 --> 00:37:18,910 Więc jeśli trafiliśmy l, co mamy tutaj? 442 00:37:18,910 --> 00:37:21,160 Mamy całą masę dziwnych rzeczy. 443 00:37:21,160 --> 00:37:26,030 To jest rzeczywisty kod montaż 444 00:37:26,030 --> 00:37:29,860 który jest w strcmp_sse4_2. 445 00:37:29,860 --> 00:37:32,440 Wygląda to rodzaj funky, 446 00:37:32,440 --> 00:37:36,520 a powodem jesteśmy coraz to dlatego teraz, 447 00:37:36,520 --> 00:37:40,160 GDB ma nas w klatce 0. 448 00:37:40,160 --> 00:37:43,070 >> Tak więc w każdej chwili spojrzeć na zmiennych, za każdym razem patrzymy na kod źródłowy, 449 00:37:43,070 --> 00:37:50,530 patrzymy na kodzie źródłowym, który odnosi się do ramki stosu jesteśmy aktualnie znajdujesz 450 00:37:50,530 --> 00:37:53,200 Tak więc w celu uzyskania czegoś sensownego, musimy 451 00:37:53,200 --> 00:37:57,070 przenieść do ramki stosu, że więcej sensu. 452 00:37:57,070 --> 00:38:00,180 W tym przypadku, główna ramka stosu pozwoliłoby trochę więcej sensu, 453 00:38:00,180 --> 00:38:02,680 dlatego, że był w rzeczywistości kod, który napisaliśmy. 454 00:38:02,680 --> 00:38:05,330 Nie strcmp kod. 455 00:38:05,330 --> 00:38:08,650 Sposób można poruszać się między ramkami, w tym przypadku, ponieważ mamy dwa, 456 00:38:08,650 --> 00:38:10,430 mamy 0 i 1, 457 00:38:10,430 --> 00:38:13,650 to zrobić z komend i puchowe. 458 00:38:13,650 --> 00:38:18,480 Jeśli przenieść jedną klatkę, 459 00:38:18,480 --> 00:38:21,770 teraz jestem w głównej ramce stosu. 460 00:38:21,770 --> 00:38:24,330 Można przenieść na dół, aby wrócić do miejsca, gdzie byłem, 461 00:38:24,330 --> 00:38:32,830 Wejdź na górę, przejdź na dół i przejść ponownie. 462 00:38:32,830 --> 00:38:39,750 Jeśli kiedykolwiek zrobić program w GDB, masz awarię, masz prześledzić, 463 00:38:39,750 --> 00:38:42,380 i widać, że jest to w jakimś pliku, że nie wiesz, co się dzieje. 464 00:38:42,380 --> 00:38:45,460 Wypróbuj listę, kod nie wygląda znajomo, 465 00:38:45,460 --> 00:38:48,150 przyjrzeć ramek i dowiedzieć się, gdzie jesteś. 466 00:38:48,150 --> 00:38:51,010 Prawdopodobnie jesteś w niewłaściwym ramce stosu. 467 00:38:51,010 --> 00:38:58,760 Albo przynajmniej, że jesteś w ramce stosu, że nie jest jednym, że naprawdę można debugować. 468 00:38:58,760 --> 00:39:03,110 Teraz jesteśmy w odpowiedniej ramce stosu, jesteśmy w głównym, 469 00:39:03,110 --> 00:39:08,100 Teraz możemy użyć polecenia listy, aby dowiedzieć się, co linia była. 470 00:39:08,100 --> 00:39:13,590 I można go zobaczyć, ale to dla nas drukowane tutaj. 471 00:39:13,590 --> 00:39:19,470 Ale możemy uderzyć listę wszystkich takie same, a lista daje nam ten ładny wydruk 472 00:39:19,470 --> 00:39:23,920 rzeczywistego kodu źródłowego, co dzieje się w tutaj. 473 00:39:23,920 --> 00:39:26,420 >> W szczególności, możemy spojrzeć na linii 6. 474 00:39:26,420 --> 00:39:29,330 Widzimy, co się tutaj dzieje. 475 00:39:29,330 --> 00:39:31,250 I wygląda na to, że robimy porównania łańcuchów 476 00:39:31,250 --> 00:39:41,050 między ciągiem "CS50 skał" i argv [1]. 477 00:39:41,050 --> 00:39:45,700 Coś w tym było upaść. 478 00:39:45,700 --> 00:39:54,120 Więc Missy, masz jakieś przemyślenia na temat tego co może być tutaj dzieje? 479 00:39:54,120 --> 00:39:59,400 [Missy] Nie wiem, dlaczego jest upaść. >> Nie wiem, dlaczego to się zawiesza? 480 00:39:59,400 --> 00:40:02,700 Jimmy, jakieś przemyślenia? 481 00:40:02,700 --> 00:40:06,240 [Jimmy] Nie jestem do końca pewien, ale ostatni raz używany ciąg porównania, 482 00:40:06,240 --> 00:40:10,260 lub strcmp, mieliśmy jak trzech różnych sprawach z nim. 483 00:40:10,260 --> 00:40:12,800 Nie masz ==, nie sądzę, prawo w tej pierwszej linii. 484 00:40:12,800 --> 00:40:16,700 Zamiast tego, oddziela się na trzy, a jeden == 0, 485 00:40:16,700 --> 00:40:19,910 był <0, myślę, i jeden był> 0. 486 00:40:19,910 --> 00:40:22,590 Więc może coś w tym stylu? >> Tak. Więc jest to kwestia 487 00:40:22,590 --> 00:40:27,200 z robimy porównania poprawnie? 488 00:40:27,200 --> 00:40:31,660 Stella? Wszelkie myśli? 489 00:40:31,660 --> 00:40:38,110 [Stella] Nie jestem pewien. >> Nie jestem pewien. Daniel? Myśli? Okay. 490 00:40:38,110 --> 00:40:44,770 Okazuje się, co dzieje się tutaj, jest wtedy, gdy prowadziliśmy program 491 00:40:44,770 --> 00:40:48,370 i dostaliśmy Seg winy, po uruchomieniu programu po raz pierwszy, Daniel, 492 00:40:48,370 --> 00:40:50,800 dałeś mu żadnych argumentów wiersza poleceń? 493 00:40:50,800 --> 00:40:58,420 [Daniel] L. >> No W takim razie, co to jest wartość argv [1]? 494 00:40:58,420 --> 00:41:00,920 >> Nie ma wartości. >> Racja. 495 00:41:00,920 --> 00:41:06,120 Cóż, nie ma odpowiedniej wartości string. 496 00:41:06,120 --> 00:41:10,780 Ale jest jakaś wartość. Co to jest wartość, która pobiera przechowywane tam? 497 00:41:10,780 --> 00:41:15,130 >> Wartość śmieci? >> To albo wartość śmieci lub, w tym przypadku, 498 00:41:15,130 --> 00:41:19,930 Koniec tablicy argv jest zawsze zakończone null. 499 00:41:19,930 --> 00:41:26,050 Więc co tak naprawdę dostałem przechowywane jest null. 500 00:41:26,050 --> 00:41:30,810 Inny sposób rozwiązać ten problem, zamiast myśleć to poprzez, 501 00:41:30,810 --> 00:41:33,420 to spróbuj wydrukować go. 502 00:41:33,420 --> 00:41:35,880 To jest, gdy mówię, że przy użyciu GDB jest wielki, 503 00:41:35,880 --> 00:41:40,640 bo można wydrukować wszystkie zmienne, wszystkie wartości, które chcesz 504 00:41:40,640 --> 00:41:43,230 zastosowaniem handy-dandy polecenia P. 505 00:41:43,230 --> 00:41:48,520 Więc jeśli p, a potem wpisać wartość zmiennej lub nazwę zmiennej, 506 00:41:48,520 --> 00:41:55,320 powiedzieć, argc, widzę, że jest 1 argc. 507 00:41:55,320 --> 00:42:01,830 Jeśli chcę wydrukować argv [0], można to zrobić tak po prostu. 508 00:42:01,830 --> 00:42:04,840 I jak widzieliśmy, argv [0] jest zawsze nazwa programu, 509 00:42:04,840 --> 00:42:06,910 zawsze nazwa pliku wykonywalnego. 510 00:42:06,910 --> 00:42:09,740 Tu zobaczysz to ma pełną nazwę ścieżki. 511 00:42:09,740 --> 00:42:15,920 Mogę także wydrukować argv [1] i zobaczyć, co się dzieje. 512 00:42:15,920 --> 00:42:20,890 >> Tutaj mamy taką mistyczną wartością. 513 00:42:20,890 --> 00:42:23,890 Dostaliśmy to 0x0. 514 00:42:23,890 --> 00:42:27,850 Zapamiętaj na początku terminowi rozmawialiśmy szesnastkowej? 515 00:42:27,850 --> 00:42:34,680 Albo że małe pytanie na koniec Pset 0 o tym, jak do reprezentowania 50 w hex? 516 00:42:34,680 --> 00:42:39,410 Sposób zapisu liczb szesnastkowych w CS, tak, aby nie pomylić się 517 00:42:39,410 --> 00:42:46,080 z liczb dziesiętnych, jest zawsze poprzedzić je 0x. 518 00:42:46,080 --> 00:42:51,420 Więc to prefiks 0x zawsze oznacza tylko interpretować następujący numer jako liczba szesnastkowa, 519 00:42:51,420 --> 00:42:57,400 nie jako ciąg znaków, a nie jako liczba dziesiętna, a nie jako liczba binarna. 520 00:42:57,400 --> 00:43:02,820 Ponieważ liczba 5-0 jest ważna liczba w systemie szesnastkowym. 521 00:43:02,820 --> 00:43:06,240 I jest to liczba w postaci dziesiętnej, 50. 522 00:43:06,240 --> 00:43:10,050 Więc to jest po prostu jak dwuznaczności. 523 00:43:10,050 --> 00:43:14,860 Więc 0x0 oznacza szesnastkowy 0, która jest także dziesiętny 0, binarne 0. 524 00:43:14,860 --> 00:43:17,030 To jest po prostu 0 wartość. 525 00:43:17,030 --> 00:43:22,630 Okazuje się, że jest to, co jest null, faktycznie, w pamięci. 526 00:43:22,630 --> 00:43:25,940 Null jest tylko 0. 527 00:43:25,940 --> 00:43:37,010 Tutaj element przechowywany w argv [1] ma wartość null. 528 00:43:37,010 --> 00:43:45,220 Więc staramy się porównać nasz "CS50 Rocks" ciąg na ciąg pusty. 529 00:43:45,220 --> 00:43:48,130 Więc dereferencji null, próbuje uzyskać dostęp do rzeczy na null, 530 00:43:48,130 --> 00:43:55,050 te są zwykle będzie powodować jakieś usterki segmentacji lub innych złych zjawisk. 531 00:43:55,050 --> 00:43:59,350 I okazuje się, że strcmp nie sprawdzić 532 00:43:59,350 --> 00:44:04,340 czy nie został przekazany w wartości, które jest null. 533 00:44:04,340 --> 00:44:06,370 Przeciwnie, tylko idzie do przodu, próbuje zrobić swoje, 534 00:44:06,370 --> 00:44:14,640 i jeśli seg usterek, to seg usterek, i to jest twój problem. Musisz iść go naprawić. 535 00:44:14,640 --> 00:44:19,730 Naprawdę szybko, jak możemy rozwiązać ten problem? Charlotte? 536 00:44:19,730 --> 00:44:23,540 [Charlotte] Można sprawdzić za pomocą if. 537 00:44:23,540 --> 00:44:32,240 Więc jeśli argv [1] ma wartość null, == 0, powrót 1, lub coś [niezrozumiałe]. 538 00:44:32,240 --> 00:44:34,590 >> Tak. Jest to więc jeden świetny sposób, aby to zrobić, jak możemy sprawdzić, 539 00:44:34,590 --> 00:44:39,230 wartość zamierzamy przejść do strcmp, argv [1], jest to wartość null? 540 00:44:39,230 --> 00:44:45,830 Jeśli jest null, to możemy powiedzieć, okay, przerwanie. 541 00:44:45,830 --> 00:44:49,450 >> Częściej sposobem na to jest użycie argc wartość. 542 00:44:49,450 --> 00:44:52,040 Można zobaczyć tu na początku main, 543 00:44:52,040 --> 00:44:58,040 pominęli ten pierwszy test, który mamy zazwyczaj robić kiedy używamy argumentów linii poleceń, 544 00:44:58,040 --> 00:45:05,240 które ma sprawdzić czy nasz argc wartość oczekujemy. 545 00:45:05,240 --> 00:45:10,290 W tym przypadku spodziewamy się co najmniej dwa argumenty, 546 00:45:10,290 --> 00:45:13,660 nazwa programu oraz jedna. 547 00:45:13,660 --> 00:45:17,140 Ponieważ mamy zamiar użyć drugiego argumentu tutaj. 548 00:45:17,140 --> 00:45:21,350 Więc o jakieś badania wcześniej, przed naszym strcmp zaproszenia 549 00:45:21,350 --> 00:45:37,390 że testy czy argv jest co najmniej 2, to również zrobić tego samego rodzaju rzeczy. 550 00:45:37,390 --> 00:45:40,620 Możemy sprawdzić, czy to działa, uruchamiając ponownie program. 551 00:45:40,620 --> 00:45:45,610 Zawsze można ponownie uruchomić program w GDB, co jest naprawdę miłe. 552 00:45:45,610 --> 00:45:49,310 Można uruchomić, a kiedy przechodzą w argumenty do programu, 553 00:45:49,310 --> 00:45:53,060 przekazać je w podczas wywołania biegać, nie podczas rozruchu GDB. 554 00:45:53,060 --> 00:45:57,120 W ten sposób można zachować wywoływanie programu z różnych argumentów za każdym razem. 555 00:45:57,120 --> 00:46:08,080 Więc biegnij, lub ponownie, mogę Type R, i zobaczymy, co się stanie, jeśli wpiszesz "hello". 556 00:46:08,080 --> 00:46:11,140 Zawsze będzie pytanie, czy chcesz zacząć ją od początku. 557 00:46:11,140 --> 00:46:17,490 Zazwyczaj, chcę zaczynać je od początku. 558 00:46:17,490 --> 00:46:25,010 I w tym momencie, to uruchamia go ponownie, drukuje się 559 00:46:25,010 --> 00:46:28,920 Program, który kończy nam, buggy1, z argumentem Witam, 560 00:46:28,920 --> 00:46:32,720 i drukuje to standardowe wyjście, to mówi: "Dostajesz D," smutną twarz. 561 00:46:32,720 --> 00:46:37,610 Ale nie seg winy. Stwierdzono, że proces zakończył się normalnie. 562 00:46:37,610 --> 00:46:39,900 Tak, że wygląda całkiem nieźle. 563 00:46:39,900 --> 00:46:43,050 Nie więcej seg winy, my zrobiliśmy to w przeszłości, 564 00:46:43,050 --> 00:46:48,190 więc wygląda na to, że rzeczywiście był seg bug wina, że ​​byliśmy się. 565 00:46:48,190 --> 00:46:51,540 Niestety, to mówi nam, że jesteśmy coraz D. 566 00:46:51,540 --> 00:46:54,090 >> Możemy iść do tyłu i spojrzeć na kod i zobaczyć, co się tam dzieje 567 00:46:54,090 --> 00:46:57,980 dowiedzieć się, co było - dlaczego to mówi nam, że mamy D. 568 00:46:57,980 --> 00:47:03,690 Zobaczmy, tutaj był to printf mówiąc, że masz D. 569 00:47:03,690 --> 00:47:08,540 Jeśli wpisać listę, jak zachować listę pisania, utrzymuje Iterowanie dół programu, 570 00:47:08,540 --> 00:47:10,940 więc to pokazać kilka pierwszych linii programu. 571 00:47:10,940 --> 00:47:15,450 Wtedy to pokazać kolejne kilka linijek, a następny kawałek i następny kawałek. 572 00:47:15,450 --> 00:47:18,240 I będzie ona próbować zejść. 573 00:47:18,240 --> 00:47:21,180 A teraz my się do "linii numer 16 znajduje się poza zasięgiem." 574 00:47:21,180 --> 00:47:23,940 Ponieważ ma tylko 15 wierszy. 575 00:47:23,940 --> 00:47:30,310 Jeśli dojdziesz do tego punktu i Twój zastanawiać: "Co mam zrobić?" możesz użyć polecenia help. 576 00:47:30,310 --> 00:47:34,340 Skorzystać z pomocy, a następnie nadać mu nazwę komendy. 577 00:47:34,340 --> 00:47:36,460 I widzisz GDB daje nam tego rodzaju rzeczy. 578 00:47:36,460 --> 00:47:43,870 Mówi: "Bez argumentów, wymienia dziesięć linie po lub wokół poprzedniej aukcji. 579 00:47:43,870 --> 00:47:47,920 Lista - wymienia dziesięć linii przed - " 580 00:47:47,920 --> 00:47:52,960 Więc spróbuj minus lista. 581 00:47:52,960 --> 00:47:57,000 I że wymienia 10 linie poprzedni, można odtwarzać z listy trochę. 582 00:47:57,000 --> 00:48:02,330 Możesz zrobić listę, liście - można nawet dać listy numer, jak liście 8, 583 00:48:02,330 --> 00:48:07,500 i będzie ona listę 10 linii wokół linii 8. 584 00:48:07,500 --> 00:48:10,290 I można zobaczyć, co dzieje się tu masz proste, jeśli inny. 585 00:48:10,290 --> 00:48:13,980 Jeśli wpiszesz w CS50 skał, drukuje się "Dostajesz A." 586 00:48:13,980 --> 00:48:16,530 W przeciwnym razie wypisuje "Dostajesz D." 587 00:48:16,530 --> 00:48:23,770 Miasto porażka. Dobrze. Tak? 588 00:48:23,770 --> 00:48:26,730 >> [Daniel] Więc kiedy próbowałem robić CS50 skały bez cudzysłowów, 589 00:48:26,730 --> 00:48:29,290 mówi "Dostajesz D." 590 00:48:29,290 --> 00:48:32,560 Potrzebowałem cytaty aby zmusić go do pracy; dlaczego tak jest? 591 00:48:32,560 --> 00:48:38,490 >> Tak. Okazuje się, że kiedy - jest to kolejny fajny smakołyk - 592 00:48:38,490 --> 00:48:47,900 Po uruchomieniu programu, jeśli będziemy go uruchomić i wpisać CS50 skał, 593 00:48:47,900 --> 00:48:50,800 jak Daniel mówił on, i naciśnij Enter, 594 00:48:50,800 --> 00:48:52,870 nadal mówi dostajemy D. 595 00:48:52,870 --> 00:48:55,580 I pytanie, dlaczego tak jest? 596 00:48:55,580 --> 00:49:02,120 I okazuje się, że zarówno nasz terminal i GDB analizować je jako dwa odrębne argumenty. 597 00:49:02,120 --> 00:49:04,800 Bo gdy nie ma miejsca, które jest rozumiane jako 598 00:49:04,800 --> 00:49:08,730 Pierwszy argument zakończony, kolejny argument to się zaczyna. 599 00:49:08,730 --> 00:49:13,260 Sposób na połączenie tych na dwie, lub przepraszam, w jednym argumentem, 600 00:49:13,260 --> 00:49:18,510 jest użycie cudzysłowu. 601 00:49:18,510 --> 00:49:29,560 Więc teraz, jeśli umieścić go w cudzysłowie i uruchomić go ponownie, otrzymamy A. 602 00:49:29,560 --> 00:49:38,780 Więc po prostu zakręcić, bez cudzysłowów, CS50 i skały są analizowane jako dwa odrębne argumenty. 603 00:49:38,780 --> 00:49:45,320 Cytatami, jest analizowany jako jeden argument całkowicie. 604 00:49:45,320 --> 00:49:53,070 >> Widzimy to z przerwania. 605 00:49:53,070 --> 00:49:54,920 Do tej pory został uruchomiony nasz program, a to prowadzi 606 00:49:54,920 --> 00:49:58,230 dopóki nie jest seg usterek lub Hits błąd 607 00:49:58,230 --> 00:50:05,930 lub dopóki nie odszedł i wszystko jest całkowicie w porządku. 608 00:50:05,930 --> 00:50:08,360 To nie jest koniecznie najbardziej przydatne rzeczy, bo czasami 609 00:50:08,360 --> 00:50:11,840 masz błąd w programie, ale to nie jest przyczyną usterki segmentacji. 610 00:50:11,840 --> 00:50:16,950 To nie powodując zatrzymanie programu lub coś podobnego. 611 00:50:16,950 --> 00:50:20,730 Sposób na GDB wstrzymać program w określonym punkcie 612 00:50:20,730 --> 00:50:23,260 jest ustawiony punkt przerwania. 613 00:50:23,260 --> 00:50:26,520 Można to zrobić przez ustawienie przerwania na nazwy funkcji 614 00:50:26,520 --> 00:50:30,770 lub można ustawić punkt przerwania na konkretnej linii kodu. 615 00:50:30,770 --> 00:50:34,450 Chcę ustawić punkty przerwania w nazwach funkcji, bo - łatwe do zapamiętania, 616 00:50:34,450 --> 00:50:37,700 a jeśli rzeczywiście iść i zmienić kod źródłowy się trochę, 617 00:50:37,700 --> 00:50:42,020 wówczas breakpoint rzeczywiście pobyt w tym samym miejscu w kodzie. 618 00:50:42,020 --> 00:50:44,760 Natomiast jeśli używasz numery linii i numery linii zmienić 619 00:50:44,760 --> 00:50:51,740 ponieważ można dodać lub usunąć niektóre kodu, twoje pułapki są zupełnie nie przejmował się. 620 00:50:51,740 --> 00:50:58,590 Jednym z najczęstszych rzeczy zrobić jest ustawiony punkt przerwania na głównej funkcji. 621 00:50:58,590 --> 00:51:05,300 Często będę rozruchu GDB, ja typ B main, naciśnij Enter, i że będzie ustawić punkt przerwania 622 00:51:05,300 --> 00:51:10,630 na głównej funkcji, które po prostu mówi: "wstrzymać program, jak tylko zaczną się" 623 00:51:10,630 --> 00:51:17,960 I w ten sposób, gdy uruchomię mój program, powiedzmy, CS50 skałach dwa argumenty 624 00:51:17,960 --> 00:51:24,830 i naciśnij klawisz Enter, dostaje się do głównych funkcji i zatrzymuje się tuż przy linii pierwszy, 625 00:51:24,830 --> 00:51:30,620 tuż przed ocenia strcmp funkcję. 626 00:51:30,620 --> 00:51:34,940 >> Ponieważ jestem wstrzymane, teraz mogę zacząć mucking wokół i widząc, co się dzieje 627 00:51:34,940 --> 00:51:40,250 z wszystkich różnych zmiennych, które są przekazywane do mojego programu. 628 00:51:40,250 --> 00:51:43,670 Tutaj mogę wydrukować ARGC i zobaczyć, co się dzieje. 629 00:51:43,670 --> 00:51:50,030 Zobacz, że argc jest 3, ponieważ dostał 3 różne wartości w nim. 630 00:51:50,030 --> 00:51:54,060 Ma nazwę programu, nie ma to pierwszy argument, a drugi argument. 631 00:51:54,060 --> 00:52:09,330 Możemy wydrukować te obecnie patrząc na argv [0], argv [1], argv [2]. 632 00:52:09,330 --> 00:52:12,030 Więc teraz można zobaczyć, dlaczego to wywołanie strcmp będzie na porażkę, 633 00:52:12,030 --> 00:52:21,650 bo widać, że nie rozstali się na CS50 i skały na dwa odrębne argumenty. 634 00:52:21,650 --> 00:52:27,250 W tym momencie, kiedy został trafiony punkt przerwania, można przejść do kroku za pośrednictwem programu 635 00:52:27,250 --> 00:52:32,920 linia po linii, w przeciwieństwie do uruchamiania programu ponownie. 636 00:52:32,920 --> 00:52:35,520 Więc jeśli nie chcesz, aby uruchomić program ponownie i po prostu dalej od tego miejsca, 637 00:52:35,520 --> 00:52:41,970 możesz użyć polecenia continue i nadal będzie działać program do końca. 638 00:52:41,970 --> 00:52:45,010 Podobnie jak to miało miejsce tutaj. 639 00:52:45,010 --> 00:52:54,880 Jednak, jeśli ponowne uruchomienie programu, CS50 skały, uderza mój przerwania ponownie 640 00:52:54,880 --> 00:52:59,670 i tym razem, jeśli nie chcesz po prostu przejść całą drogę przez resztę programu, 641 00:52:59,670 --> 00:53:08,040 Można użyć następnego polecenia, które ja również skrócić zn. 642 00:53:08,040 --> 00:53:12,960 I to będzie krok po kroku linii programu po linii. 643 00:53:12,960 --> 00:53:17,530 Więc można oglądać jako rzeczy wykonać, jako zmiennych na zmiany, jak rzeczy się aktualizacji. 644 00:53:17,530 --> 00:53:21,550 Które jest bardzo ładne. 645 00:53:21,550 --> 00:53:26,570 Inne fajne jest to, a nie powtarzanie tego samego polecenia w kółko i od nowa, 646 00:53:26,570 --> 00:53:30,670 jeśli po prostu naciśnij Enter - więc widzisz, że nie wpisałeś w nic - 647 00:53:30,670 --> 00:53:33,780 jeśli po prostu naciśnij Enter, będzie powtórzyć poprzednie polecenie, 648 00:53:33,780 --> 00:53:36,900 lub poprzednie polecenie GDB, że po prostu umieścić w. 649 00:53:36,900 --> 00:53:56,000 Mogę naciskamy Enter i będziesz przechowywać Krokowe mojej linii kodu po wierszu. 650 00:53:56,000 --> 00:53:59,310 Chciałbym zachęcić, żebyście go sprawdzić inne programy buggy, jak również. 651 00:53:59,310 --> 00:54:01,330 Nie mamy czasu, żeby ich wszystkich dzisiaj w sekcji. 652 00:54:01,330 --> 00:54:05,890 Kod źródłowy jest tam, więc można trochę zobaczyć, co się dzieje 653 00:54:05,890 --> 00:54:07,730 za kulisami, jeśli się naprawdę zatrzymany, 654 00:54:07,730 --> 00:54:11,940 ale co najmniej, po prostu ćwiczyć uruchamiania GDB, 655 00:54:11,940 --> 00:54:13,940 uruchomieniu programu aż do jego zniszczenia na ciebie, 656 00:54:13,940 --> 00:54:18,260 coraz backtrace, zastanawianie się, jaką funkcję katastrofy był w, 657 00:54:18,260 --> 00:54:24,450 co to było na linii, drukowanie pewne wartości zmiennych, 658 00:54:24,450 --> 00:54:30,140 tylko tak się czuć za to, bo to naprawdę pomóc w przyszłości. 659 00:54:30,140 --> 00:54:36,340 W tym momencie mamy zamiar wyjść z GDB, który można zrobić za pomocą quit lub tylko q. 660 00:54:36,340 --> 00:54:40,460 Jeśli twój program jest w środku działa nadal i nie odszedł, 661 00:54:40,460 --> 00:54:43,510 to zawsze zapytać, "Czy na pewno na pewno chcesz zakończyć?" 662 00:54:43,510 --> 00:54:48,770 Możesz po prostu wciskamy tak. 663 00:54:48,770 --> 00:54:55,250 >> Teraz będziemy patrzeć na kolejny problem, jaki mamy, czyli program cat. 664 00:54:55,250 --> 00:54:59,880 Jeśli oglądasz krótkie na przekierowanie i rur, zobaczysz, że ten program używa Tommy 665 00:54:59,880 --> 00:55:07,540 że w zasadzie drukuje wszystkie dane wyjściowe do pliku na ekranie. 666 00:55:07,540 --> 00:55:12,660 Więc jeśli mogę uruchomić kota, to jest rzeczywiście wbudowany program do urządzenia, 667 00:55:12,660 --> 00:55:16,860 a jeśli masz Mac można to zrobić na komputerze Mac, jeśli chcecie otworzyć terminal. 668 00:55:16,860 --> 00:55:25,630 A my - cat, powiedzmy, cp.c, i naciśnij klawisz Enter. 669 00:55:25,630 --> 00:55:29,640 Co to było, gdybyśmy przewijać się trochę i zobaczyć, gdzie zabrakło nam linię, 670 00:55:29,640 --> 00:55:40,440 lub gdy zabrakło polecenia cat, to dosłownie po prostu wydrukować zawartość cp.c naszym ekranie. 671 00:55:40,440 --> 00:55:44,140 Możemy uruchomić go ponownie i można umieścić w wielu plikach razem. 672 00:55:44,140 --> 00:55:49,880 Więc można zrobić cp.c kota, a następnie możemy złączyć cat.c plik, 673 00:55:49,880 --> 00:55:53,250 co to jest program zamierzamy pisać, 674 00:55:53,250 --> 00:55:58,140 i będzie to wydrukować oba pliki z powrotem do tyłu do naszego ekranu. 675 00:55:58,140 --> 00:56:05,490 Więc jeśli mamy przejść się trochę, widzimy, że kiedy zabrakło tego cp.c kota, cat.c, 676 00:56:05,490 --> 00:56:17,110 Początkowo drukowana cp plik, a następnie pod nią, to wydrukuje cat.c plik aż tutaj. 677 00:56:17,110 --> 00:56:19,650 Zamierzamy to wykorzystać, aby po prostu nasze nogi mokre. 678 00:56:19,650 --> 00:56:25,930 Pobaw się z prostych zadań drukowania do terminalu, zobaczyć, jak to działa. 679 00:56:25,930 --> 00:56:39,170 Jeśli faceci otwarcie z gedit cat.c, naciśnij Enter, 680 00:56:39,170 --> 00:56:43,760 można zobaczyć program, który mamy zamiar pisać. 681 00:56:43,760 --> 00:56:48,980 Zamieściliśmy ten miły talerz kotła, więc nie trzeba tracić czasu na pisanie wszystko to. 682 00:56:48,980 --> 00:56:52,310 Mamy również sprawdzić liczbę argumentów przekazanych w. 683 00:56:52,310 --> 00:56:56,910 Drukujemy z miłą użytkowaniu. 684 00:56:56,910 --> 00:57:00,950 >> To jest coś takiego, że znów, jak rozmawialiśmy o, 685 00:57:00,950 --> 00:57:04,490 to prawie jak pamięci mięśniowej. 686 00:57:04,490 --> 00:57:07,190 Wystarczy pamiętać, aby robić tego samego rodzaju rzeczy 687 00:57:07,190 --> 00:57:11,310 i zawsze drukując jakieś pomocne wiadomości 688 00:57:11,310 --> 00:57:17,670 tak, że ludzie wiedzą, jak uruchomić program. 689 00:57:17,670 --> 00:57:21,630 Z kotem, to całkiem proste, jesteśmy po prostu się przejść przez wszystkie różne argumenty 690 00:57:21,630 --> 00:57:24,300 , które zostały przekazane do naszego programu, a my zamierzamy drukować 691 00:57:24,300 --> 00:57:29,950 ich zawartość uwagę do ekranu jeden na raz. 692 00:57:29,950 --> 00:57:35,670 Aby drukować pliki z do ekranu, mamy zamiar zrobić coś bardzo podobnego 693 00:57:35,670 --> 00:57:38,120 co my w końcu quizu. 694 00:57:38,120 --> 00:57:45,350 Pod koniec quizu, to zatrudnić program, mieliśmy do otwarcia pliku, 695 00:57:45,350 --> 00:57:48,490 a następnie mieliśmy do niej drukować. 696 00:57:48,490 --> 00:57:54,660 W tym przypadku, mamy zamiar otworzyć plik, a będziemy czytać z niej zamiast. 697 00:57:54,660 --> 00:58:00,630 Następnie jedziemy do drukowania, zamiast do pliku, będziemy drukować na ekranie. 698 00:58:00,630 --> 00:58:05,830 Więc wyświetlenie na ekranie, na który wszyscy wykonanej wcześniej z printf. 699 00:58:05,830 --> 00:58:08,290 Tak, że nie jest zbyt szalone. 700 00:58:08,290 --> 00:58:12,190 Ale czytanie pliku jest dziwne. 701 00:58:12,190 --> 00:58:17,300 Pójdziemy przez to trochę mało na raz. 702 00:58:17,300 --> 00:58:20,560 Jeśli faceci wrócić do tego ostatniego problemu na quiz, problem 33, 703 00:58:20,560 --> 00:58:27,280 Pierwszy wiersz, który będziemy robić tutaj, otwierając plik, jest bardzo podobny do tego, co zrobiliśmy tam. 704 00:58:27,280 --> 00:58:36,370 Więc Stella, co robi, że wygląd linii, jak, kiedy otworzyć plik? 705 00:58:36,370 --> 00:58:47,510 [Stella] * FILE Capital, file - >> Ok. >> - Jest równa fopen. >> Tak. 706 00:58:47,510 --> 00:58:55,980 Która w tym przypadku jest? Jest to w komentarzu. 707 00:58:55,980 --> 00:59:06,930 >> To w komentarzu? argv [i] oraz r? 708 00:59:06,930 --> 00:59:11,300 >> Dokładnie. Na prawo. Więc Stella jest całkowicie w porządku. 709 00:59:11,300 --> 00:59:13,720 To, co wygląda jak linia. 710 00:59:13,720 --> 00:59:19,670 Zamierzamy uzyskać zmienną strumienia pliku, zapisać w pliku *, więc wszystkie czapki, 711 00:59:19,670 --> 00:59:25,720 FILE *, oraz nazwę tej zmiennej będzie plik. 712 00:59:25,720 --> 00:59:32,250 Możemy nazwać to, co nam się podoba. Możemy nazwać to first_file lub file_i, cokolwiek byśmy chcieli. 713 00:59:32,250 --> 00:59:37,590 A następnie nazwa pliku została podjęta w wierszu poleceń do tego programu. 714 00:59:37,590 --> 00:59:44,450 Więc to jest przechowywane w argv [i,], a następnie jedziemy do otwarcia tego pliku w trybie odczytu. 715 00:59:44,450 --> 00:59:48,100 Teraz, kiedy otworzył plik, co jest rzeczą, że zawsze musimy pamiętać, aby zrobić 716 00:59:48,100 --> 00:59:52,230 gdy mamy otwarty plik? Zamknij ją. 717 00:59:52,230 --> 00:59:57,220 Więc Missy, w jaki sposób zamknąć plik? 718 00:59:57,220 --> 01:00:01,020 [Missy] fclose (plik) >> fclose (plik). Dokładnie. 719 01:00:01,020 --> 01:00:05,340 Great. Okay. Jeśli spojrzymy na to uwagi komentarz tutaj, 720 01:00:05,340 --> 01:00:11,940 mówi: "Open argv [i] i wydrukować jego zawartość na standardowe wyjście." 721 01:00:11,940 --> 01:00:15,460 >> Obecnie standardem jest dziwne imię. Stdout jest tylko nasz sposób na powiedzenie 722 01:00:15,460 --> 01:00:22,880 chcemy wydrukować go do terminala, chcemy wydrukować go do standardowego strumienia wyjściowego. 723 01:00:22,880 --> 01:00:26,450 Rzeczywiście możemy się pozbyć tego komentarza tutaj. 724 01:00:26,450 --> 01:00:36,480 Idę go skopiować i wkleić go ponieważ to, co zrobiliśmy. 725 01:00:36,480 --> 01:00:41,290 W tym momencie, teraz przeczytać pliku bitu kroku. 726 01:00:41,290 --> 01:00:46,300 Omówiliśmy kilka sposobów czytania plików. 727 01:00:46,300 --> 01:00:51,830 Które z nich są Twoje ulubione do tej pory? 728 01:00:51,830 --> 01:00:57,960 Jakie sposoby widziałaś lub nie pamiętasz, do odczytu plików? 729 01:00:57,960 --> 01:01:04,870 [Daniel] fread? >> Fread? Więc fread jest jeden. Jimmy, czy znacie jakieś inne? 730 01:01:04,870 --> 01:01:12,150 [Jimmy] L. >> Okay. Nope. Charlotte? Alexander? Jakieś inne? Okay. 731 01:01:12,150 --> 01:01:20,740 Inni więc z nich są fgetc, jest jednym, że będziemy korzystać z wielu. 732 01:01:20,740 --> 01:01:26,410 Jest też fscanf; wy patrz wzór tutaj? 733 01:01:26,410 --> 01:01:29,170 Wszyscy zaczynają się f. Coś zrobić z plikiem. 734 01:01:29,170 --> 01:01:35,260 Jest fread, fgetc, fscanf. Są wszystkie funkcje odczytu. 735 01:01:35,260 --> 01:01:49,120 Do pisania mamy fwrite mamy fputc zamiast fgetc. 736 01:01:49,120 --> 01:01:58,250 Mamy również fprintf jak widzieliśmy na quiz. 737 01:01:58,250 --> 01:02:01,680 Ponieważ jest to problem, który obejmuje czytanie z pliku, 738 01:02:01,680 --> 01:02:04,940 mamy zamiar skorzystać z jednej z tych trzech funkcji. 739 01:02:04,940 --> 01:02:10,890 Nie będziemy korzystać z tych funkcji na dole. 740 01:02:10,890 --> 01:02:14,880 Funkcje te są w normie I / O biblioteki. 741 01:02:14,880 --> 01:02:17,510 Więc jeśli spojrzymy na początek programu 742 01:02:17,510 --> 01:02:24,110 widać, że mamy już zawarte w pliku nagłówka dla Standard I / O bibliotece. 743 01:02:24,110 --> 01:02:27,120 Jeśli chcemy dowiedzieć się, który z nich chcemy korzystać, 744 01:02:27,120 --> 01:02:29,690 zawsze możemy otworzyć stron podręcznika. 745 01:02:29,690 --> 01:02:34,350 Tak więc możemy napisać stdio man 746 01:02:34,350 --> 01:02:43,180 i przeczytać o stdio funkcji wejściowych i wyjściowych w C. 747 01:02:43,180 --> 01:02:49,870 I możemy już zobaczyć oh, spójrz. To wspomnieć fgetc, to wspomnieć fputc. 748 01:02:49,870 --> 01:02:57,220 Więc można drążyć trochę i spojrzeć na, powiedzmy, fgetc 749 01:02:57,220 --> 01:03:00,060 i spojrzeć na jego stronie man. 750 01:03:00,060 --> 01:03:03,430 Widać, że to idzie w parze z całą masę innych funkcji: 751 01:03:03,430 --> 01:03:12,640 fgetc, fgets, getc, getchar, dostaje, ungetc, a jej wejście znaków i łańcuchów. 752 01:03:12,640 --> 01:03:19,180 Tak to jest, jak czytamy w znaków i ciągi z plików ze standardowego wejścia, 753 01:03:19,180 --> 01:03:21,990 która jest w zasadzie z użytkownika. 754 01:03:21,990 --> 01:03:24,780 I to jest, jak to robimy w rzeczywistej C. 755 01:03:24,780 --> 01:03:30,850 Więc to nie jest za pomocą funkcji getString i getchar 756 01:03:30,850 --> 01:03:36,840 że kiedyś z CS50 biblioteki. 757 01:03:36,840 --> 01:03:39,710 Mamy zamiar zrobić z tym problemem w kilka sposobów 758 01:03:39,710 --> 01:03:43,430 tak że można zobaczyć dwa różne sposoby to zrobić. 759 01:03:43,430 --> 01:03:48,490 Zarówno funkcja fread Daniel wspomina i fgetc są dobre sposoby, aby to zrobić. 760 01:03:48,490 --> 01:03:53,790 Myślę fgetc jest trochę łatwiej, bo to tylko ma, jak widać, 761 01:03:53,790 --> 01:03:59,660 jeden argument, * FILE, że staramy się odczytać znak z, 762 01:03:59,660 --> 01:04:02,740 , a jego wartość zwracana jest int. 763 01:04:02,740 --> 01:04:05,610 I to jest trochę mylące, prawda? 764 01:04:05,610 --> 01:04:11,450 >> Ponieważ dostajemy znak, więc dlaczego nie ten powrót nie char? 765 01:04:11,450 --> 01:04:18,700 Macie jakieś pomysły, dlaczego to może nie wrócić char? 766 01:04:18,700 --> 01:04:25,510 [Odpowiedzi Missy, niezrozumiały] >> Tak. Więc Missy jest całkowicie w porządku. 767 01:04:25,510 --> 01:04:31,570 Jeśli to jest ASCII, to całkowita może być mapowane do rzeczywistej char. 768 01:04:31,570 --> 01:04:33,520 Może być znak ASCII, i to jest w porządku. 769 01:04:33,520 --> 01:04:36,220 To jest dokładnie to, co się dzieje. 770 01:04:36,220 --> 01:04:39,190 Używamy int tylko dlatego, że ma więcej bitów. 771 01:04:39,190 --> 01:04:44,750 Jest większy niż char; nasz char ma tylko 8 bitów, że 1 bajt na naszych maszynach 32-bitowych. 772 01:04:44,750 --> 01:04:48,520 I int ma warte 4 bajty 'przestrzeni. 773 01:04:48,520 --> 01:04:50,940 I okazuje się, że sposób, fgetc działa 774 01:04:50,940 --> 01:04:53,940 jeśli przewiń w naszym streszczeniu w manualu bitowym mało, 775 01:04:53,940 --> 01:05:05,000 przejść całą drogę w dół. Okazuje się, że używają oni tę szczególną wartość o nazwie EOF. 776 01:05:05,000 --> 01:05:09,640 To specjalny stały jako wartość zwracana z funkcji fgetc 777 01:05:09,640 --> 01:05:14,570 gdy trafisz na koniec pliku lub jeśli pojawia się błąd. 778 01:05:14,570 --> 01:05:18,170 I okazuje się, że aby wykonać te porównania z EOF prawidłowo, 779 01:05:18,170 --> 01:05:24,060 chcesz mieć tę dodatkową ilość informacji, które masz w int 780 01:05:24,060 --> 01:05:28,420 w przeciwieństwie do używania char zmiennej. 781 01:05:28,420 --> 01:05:32,130 Nawet fgetc skutecznie się znak z pliku, 782 01:05:32,130 --> 01:05:38,450 chcesz zapamiętać, że jest coś, co jest powrotem typu int do Ciebie. 783 01:05:38,450 --> 01:05:41,360 Powiedział, że jest to dość łatwe w użyciu. 784 01:05:41,360 --> 01:05:44,960 To da nam znak, więc wszystko, co musimy zrobić, to prosić plik, 785 01:05:44,960 --> 01:05:48,440 "Daj mi następny znak, daj mi kolejny znak, daj mi następnego znaku" 786 01:05:48,440 --> 01:05:51,400 aż dojdziemy do końca pliku. 787 01:05:51,400 --> 01:05:54,730 I to będzie ciągnąć w jednym znaku naraz z naszego pliku, 788 01:05:54,730 --> 01:05:56,250 i możemy robić co chcemy z nim. 789 01:05:56,250 --> 01:06:00,160 Możemy przechowywać, możemy dodać go do łańcucha, możemy wydrukować. 790 01:06:00,160 --> 01:06:04,630 Czy cokolwiek z tego. 791 01:06:04,630 --> 01:06:09,600 >> Powiększanie z powrotem i wraca do naszego cat.c programu 792 01:06:09,600 --> 01:06:16,170 jeśli mamy zamiar używać fgetc, 793 01:06:16,170 --> 01:06:21,710 jak możemy podejść do tego następnego wiersza kodu? 794 01:06:21,710 --> 01:06:26,020 Będziemy używać - fread zrobi coś trochę innego. 795 01:06:26,020 --> 01:06:32,600 I tym razem, po prostu zamierzasz korzystać fgetc dostać jeden znak na raz. 796 01:06:32,600 --> 01:06:40,910 Aby przetworzyć cały plik, co możemy zrobić? 797 01:06:40,910 --> 01:06:44,030 Ile znaków są tam w pliku? 798 01:06:44,030 --> 01:06:47,390 Istnieje wiele. Więc prawdopodobnie chcesz, aby jeden 799 01:06:47,390 --> 01:06:49,860 , a następnie dostać innego i dostać innego i dostać inny. 800 01:06:49,860 --> 01:06:53,330 Jaki algorytm myślisz możemy użyć tutaj? 801 01:06:53,330 --> 01:06:55,470 Jaki rodzaj - [Alexander] w pętli? >> Dokładnie. 802 01:06:55,470 --> 01:06:57,500 Jakiś rodzaj pętli. 803 01:06:57,500 --> 01:07:03,380 W rzeczywistości jest wielkim pętli, w tym przypadku. 804 01:07:03,380 --> 01:07:08,620 I tak jak mówisz, brzmi to tak, jak chcesz pętli w całym pliku, 805 01:07:08,620 --> 01:07:11,820 się postać w czasie. 806 01:07:11,820 --> 01:07:13,850 Wszelkie sugestie na temat, co to może wyglądać? 807 01:07:13,850 --> 01:07:22,090 [Alexander, niezrozumiały] 808 01:07:22,090 --> 01:07:30,050 >> Dobra, tylko powiedz mi, w języku angielskim, co próbujesz zrobić? [Alexander, niezrozumiały] 809 01:07:30,050 --> 01:07:36,270 Więc w tym przypadku, to brzmi jak my po prostu staramy się pętli w całym pliku. 810 01:07:36,270 --> 01:07:45,330 [Alexander] Więc i > -? 811 01:07:45,330 --> 01:07:49,290 Myślę, że rozmiar pliku, prawda? Rozmiar - we'll prostu napisać, że tak. 812 01:07:49,290 --> 01:07:57,470 Rozmiar pliku w danej chwili, i + +. 813 01:07:57,470 --> 01:08:04,610 Tak więc okazuje się, że sposób w jaki to zrobić przy użyciu fgetc, a to jest nowy, 814 01:08:04,610 --> 01:08:10,460 jest, że nie ma łatwego sposobu, aby tylko uzyskać rozmiaru pliku 815 01:08:10,460 --> 01:08:16,979 z tym "sizeof" typu konstrukcji, że już widział. 816 01:08:16,979 --> 01:08:20,910 Gdy używamy tego fgetc funkcji wprowadzamy jakieś 817 01:08:20,910 --> 01:08:29,069 nowy, funky składnia to dla pętli, gdzie zamiast po prostu podstawowy licznik 818 01:08:29,069 --> 01:08:33,920 iść znak po znaku, mamy zamiar wyciągnąć jeden znak na raz, 819 01:08:33,920 --> 01:08:37,120 jeden znak w czasie, jak i sposób wiemy, że jesteśmy na końcu 820 01:08:37,120 --> 01:08:41,290 gdy nie jest już liczyć pewną liczbę znaków, 821 01:08:41,290 --> 01:08:49,939 ale kiedy postać możemy wyciągnąć jest to, że specjalny znak końca pliku. 822 01:08:49,939 --> 01:08:58,689 Tak więc możemy to zrobić - ja nazywam to ch, i mamy zamiar go zainicjować 823 01:08:58,689 --> 01:09:08,050 z naszej pierwszej rozmowy, aby uzyskać pierwszy znak z pliku. 824 01:09:08,050 --> 01:09:14,979 Więc tej części tutaj, to będzie dostać znak z pliku 825 01:09:14,979 --> 01:09:20,840 i zapisać go do zmiennej ch. 826 01:09:20,840 --> 01:09:25,420 Będziemy robić to, aż dojdziemy do końca pliku, 827 01:09:25,420 --> 01:09:41,170 co możemy zrobić, sprawdzając dla postaci nie jest równa tej szczególnej postaci EOF. 828 01:09:41,170 --> 01:09:48,750 A potem zamiast robić ch + +, które po prostu zwiększyć wartość, 829 01:09:48,750 --> 01:09:52,710 więc jeśli czytać A z pliku, kapitału, powiedzmy, 830 01:09:52,710 --> 01:09:56,810 ch + + da nam b, a potem mamy C, a następnie d. 831 01:09:56,810 --> 01:09:59,310 To z pewnością nie to, co chcemy. Co chcemy tutaj 832 01:09:59,310 --> 01:10:05,830 w tym ostatnim trochę się chcemy dostać następny znak z pliku. 833 01:10:05,830 --> 01:10:09,500 >> Więc w jaki sposób możemy uzyskać kolejny znak z pliku? 834 01:10:09,500 --> 01:10:13,470 Jak możemy uzyskać pierwszy znak z pliku? 835 01:10:13,470 --> 01:10:17,200 [Student] fgetfile? >> Fgetc, albo, przepraszam, pan całkowitą rację. 836 01:10:17,200 --> 01:10:20,470 I błędnie go tam. Więc tak. 837 01:10:20,470 --> 01:10:26,240 Tutaj zamiast robić ch + +, 838 01:10:26,240 --> 01:10:29,560 jesteśmy po prostu zadzwonię do fgetc (plik), ponownie 839 01:10:29,560 --> 01:10:39,180 i zapisać wynik w naszym samej zmiennej ch. 840 01:10:39,180 --> 01:10:43,730 [Pytanie Student, niezrozumiały] 841 01:10:43,730 --> 01:10:52,390 >> To jest, gdzie ci faceci plik * są specjalne. 842 01:10:52,390 --> 01:10:59,070 Sposób ich pracy jest to, że - przy pierwszym otwarciu - gdy po raz pierwszy udostępnia tego wywołania fopen, 843 01:10:59,070 --> 01:11:04,260 Plik * skutecznie służy jako wskaźnik na początku pliku. 844 01:11:04,260 --> 01:11:12,830 A następnie za każdym razem wywołać fgetc, porusza się o jeden znak za pośrednictwem pliku. 845 01:11:12,830 --> 01:11:23,280 Jeśli więc nazwać, jesteś inkrementacji wskaźnik pliku o jeden znak. 846 01:11:23,280 --> 01:11:26,210 A kiedy fgetc znowu ruszasz mu inny charakter 847 01:11:26,210 --> 01:11:28,910 a inny charakter i inny charakter i inny charakter. 848 01:11:28,910 --> 01:11:32,030 [Pytanie Student, niezrozumiały] >> I that's - tak. 849 01:11:32,030 --> 01:11:34,810 To trochę tej magii pod maską. 850 01:11:34,810 --> 01:11:37,930 Po prostu zachować inkrementacji przez. 851 01:11:37,930 --> 01:11:46,510 W tym momencie jesteś w stanie właściwie pracować z charakterem. 852 01:11:46,510 --> 01:11:52,150 Więc w jaki sposób możemy drukować na to na ekranie, teraz? 853 01:11:52,150 --> 01:11:58,340 Możemy użyć tej samej rzeczy, że printf używany wcześniej. 854 01:11:58,340 --> 01:12:00,330 Że używaliśmy cały semestr. 855 01:12:00,330 --> 01:12:05,450 Możemy wywołać printf, 856 01:12:05,450 --> 01:12:21,300 i możemy przekazać w postaci tak po prostu. 857 01:12:21,300 --> 01:12:27,430 Innym sposobem na to jest, a nie za pomocą printf i konieczności zrobić ten ciąg formatu, 858 01:12:27,430 --> 01:12:29,490 możemy również skorzystać z jednej z pozostałych funkcji. 859 01:12:29,490 --> 01:12:40,090 Możemy użyć fputc, który drukuje znak na ekranie, 860 01:12:40,090 --> 01:12:52,580 wyjątkiem sytuacji, gdy patrzymy na fputc - pozwól mi oddalić się trochę. 861 01:12:52,580 --> 01:12:56,430 Widzimy to, co miłe jest potrzebny w charakterze że czytamy z wykorzystaniem fgetc, 862 01:12:56,430 --> 01:13:05,100 ale musimy dać mu strumień drukować. 863 01:13:05,100 --> 01:13:11,850 Możemy również użyć putchar funkcję, która położy bezpośrednio wyjście standardowe. 864 01:13:11,850 --> 01:13:16,070 Tak więc istnieje cała masa różnych opcji, które możemy wykorzystać do drukowania. 865 01:13:16,070 --> 01:13:19,580 Oni wszyscy są w standardowym I / O bibliotece. 866 01:13:19,580 --> 01:13:25,150 Ilekroć chcesz drukować - tak printf, domyślnie zostaną wydrukowane w specjalnym standardzie z potoku, 867 01:13:25,150 --> 01:13:27,910 czyli że stdout. 868 01:13:27,910 --> 01:13:41,300 Więc może po prostu o nim jako o rodzaju tej magicznej wartości, stdout tutaj. 869 01:13:41,300 --> 01:13:48,410 Ups. Umieść średnik zewnątrz. 870 01:13:48,410 --> 01:13:52,790 >> To jest dużo nowych, informacji modny tutaj. 871 01:13:52,790 --> 01:13:58,600 Wiele z tego jest bardzo idiomatyczne, w tym sensie, że jest to kod 872 01:13:58,600 --> 01:14:05,700 , co jest napisane w ten sposób tylko dlatego, że jest czysty czytać, łatwe do odczytania. 873 01:14:05,700 --> 01:14:11,520 Istnieje wiele różnych sposobów na to, wiele różnych funkcji, których można użyć, 874 01:14:11,520 --> 01:14:14,680 ale zazwyczaj wystarczy wykonać te same wzory w kółko. 875 01:14:14,680 --> 01:14:20,180 Więc nie zdziw się, jeśli widzisz kod jak to zbliża się ponownie i ponownie. 876 01:14:20,180 --> 01:14:25,690 Dobrze. W tym momencie, że trzeba podzielić na dzień. 877 01:14:25,690 --> 01:14:31,300 Dzięki za przyjście. Dzięki za oglądanie czy jesteś online. I do zobaczenia w przyszłym tygodniu. 878 01:14:31,300 --> 01:14:33,890 [CS50.TV]