1 00:00:00,000 --> 00:00:02,490 [Powered by Google Translate] [CS50 Library] 2 00:00:02,490 --> 00:00:04,220 [Nate Hardison] [Harvard University] 3 00:00:04,220 --> 00:00:07,260 [To jest CS50. CS50.TV] 4 00:00:07,260 --> 00:00:11,510 Biblioteka CS50 to przydatne narzędzie, które zostało zainstalowane na urządzeniu 5 00:00:11,510 --> 00:00:15,870 aby ułatwić do pisania programów, które monituje użytkowników do wejścia. 6 00:00:15,870 --> 00:00:21,670 W tym filmie, będziemy odciągnąć zasłonę i spójrz na to, co dokładnie jest w CS50 biblioteki. 7 00:00:21,670 --> 00:00:25,520 >> W wideo na bibliotekach C, mówimy o tym, jak nagłówki plików # include 8 00:00:25,520 --> 00:00:27,570 biblioteki w kodzie źródłowym, 9 00:00:27,570 --> 00:00:31,150 a następnie połączyć się z pliku binarnego biblioteki podczas fazy łączącej 10 00:00:31,150 --> 00:00:33,140 procesu kompilacji. 11 00:00:33,140 --> 00:00:36,440 Pliki nagłówkowe określić interfejs biblioteki. 12 00:00:36,440 --> 00:00:41,280 Oznacza to, że informacje o wszystkich zasobów, że biblioteka ma dostępne do użycia, 13 00:00:41,280 --> 00:00:45,250 jak deklaracji funkcji, stałych i typów danych. 14 00:00:45,250 --> 00:00:48,890 Plik binarny biblioteki zawiera implementację biblioteki 15 00:00:48,890 --> 00:00:54,580 który jest skompilowany z biblioteki na pliki nagłówkowe i biblioteki pliki. c kod źródłowy. 16 00:00:54,580 --> 00:00:59,820 >> Plik binarny biblioteka nie jest bardzo ciekawe spojrzenie na, ponieważ jest dobrze, w binarnym. 17 00:00:59,820 --> 00:01:03,300 Więc, rzućmy okiem na pliki nagłówkowe dla biblioteki zamiast. 18 00:01:03,300 --> 00:01:07,710 W tym przypadku jest tylko jeden plik o nazwie header cs50.h. 19 00:01:07,710 --> 00:01:11,040 Mamy zainstalowany w katalogu użytkownika, to 20 00:01:11,040 --> 00:01:15,150 wraz z plikami innych bibliotek systemu "nagłówka. 21 00:01:15,150 --> 00:01:21,530 >> Jedną z pierwszych rzeczy, można zauważyć, jest to, że cs50.h # zawiera pliki nagłówkowe z innych bibliotek - 22 00:01:21,530 --> 00:01:25,670 float, bool limity standardowe i standardowe lib. 23 00:01:25,670 --> 00:01:28,800 Ponownie, zgodnie z zasadą nie wymyślać koła, 24 00:01:28,800 --> 00:01:33,490 mamy zbudował CS0 bibliotekę przy użyciu narzędzi, które inne przewidziane dla nas. 25 00:01:33,490 --> 00:01:38,690 >> Następną rzeczą, którą zobaczysz w bibliotece jest to, że możemy zdefiniować nowy typ o nazwie "string". 26 00:01:38,690 --> 00:01:42,330 Ta linia tak naprawdę tworzy alias dla typu char *, 27 00:01:42,330 --> 00:01:46,000 więc nie magicznie nadać nowy typ ciąg z atrybutami 28 00:01:46,000 --> 00:01:49,650 często związane z obiektami smyczkowych w innych językach, 29 00:01:49,650 --> 00:01:50,850 , takie jak długość. 30 00:01:50,850 --> 00:01:55,180 Powodem zrobiliśmy to, aby chronić nowe programistów od małych detali 31 00:01:55,180 --> 00:01:57,580 wskaźników, dopóki nie jesteśmy gotowi. 32 00:01:57,580 --> 00:02:00,130 >> Kolejna część nagłówka pliku jest deklaracja funkcji 33 00:02:00,130 --> 00:02:04,410 że CS50 biblioteki zapewnia wraz z dokumentacją. 34 00:02:04,410 --> 00:02:06,940 Wskazówka poziomu szczegółowości w komentarzach tutaj. 35 00:02:06,940 --> 00:02:10,560 To jest super ważne, tak, że ludzie wiedzą, jak korzystać z tych funkcji. 36 00:02:10,560 --> 00:02:19,150 Deklarujemy z kolei działa, aby skłonić użytkownika i znaków powrotu, Gra Podwójna, pływaków, wskazówki, 37 00:02:19,150 --> 00:02:24,160 długo tęskni i łańcuchy, za pomocą własnego typu string. 38 00:02:24,160 --> 00:02:26,260 Zgodnie z zasadą ukrywania informacji, 39 00:02:26,260 --> 00:02:31,640 musimy umieścić naszą definicję w oddzielnym pliku c realizacji -. cs50.c-- 40 00:02:31,640 --> 00:02:35,110 znajduje się w katalogu źródłowym użytkownika. 41 00:02:35,110 --> 00:02:38,040 Mamy pod warunkiem, że plik, tak, że można spojrzeć na nią, 42 00:02:38,040 --> 00:02:41,490 uczyć się od niego, i skompilować go na różnych komputerach, jeśli chcesz, 43 00:02:41,490 --> 00:02:45,510 chociaż myślę, że to lepiej pracować na urządzenie w tej klasie. 44 00:02:45,510 --> 00:02:47,580 Anyway, rzućmy okiem na to teraz. 45 00:02:49,020 --> 00:02:54,620 >> Funkcje getchar, GetDouble, GetFloat, getInt i GetLongLong 46 00:02:54,620 --> 00:02:58,160 są zbudowane na górze GetString funkcji. 47 00:02:58,160 --> 00:03:01,510 Okazuje się, że oni wszyscy idą zasadniczo ten sam wzór. 48 00:03:01,510 --> 00:03:04,870 Używają pętlę while, aby skłonić użytkownika do jednej z linii wejściowych. 49 00:03:04,870 --> 00:03:08,430 Zwracają szczególną wartość, jeśli użytkownik wejścia pustą linię. 50 00:03:08,430 --> 00:03:11,750 Próbują analizować wprowadzane przez użytkownika jako odpowiedniego typu, 51 00:03:11,750 --> 00:03:15,010 czy to char, double, float, itp. 52 00:03:15,010 --> 00:03:18,710 A potem albo zwraca wynik, jeśli wejście z powodzeniem analizowane 53 00:03:18,710 --> 00:03:21,330 lub ich reprompt użytkownika. 54 00:03:21,330 --> 00:03:24,230 >> Na wysokim poziomie, nie ma nic naprawdę trudne tutaj. 55 00:03:24,230 --> 00:03:28,760 Możesz napisać o podobnej strukturze kodu się w przeszłości. 56 00:03:28,760 --> 00:03:34,720 Być może najbardziej tajemniczy przystojny część jest sscanf wezwanie który analizuje wprowadzane przez użytkownika. 57 00:03:34,720 --> 00:03:38,160 Sscanf jest częścią formatu wejściowego rodziny konwersji. 58 00:03:38,160 --> 00:03:42,300 Zamieszkuje io.h standardowej, a jego zadaniem jest analizować ciąg C, 59 00:03:42,300 --> 00:03:46,520 zgodnie z określonym formatem, przechowywania wyników analizować przy zmiennej 60 00:03:46,520 --> 00:03:48,720 dostarczone przez dzwoniącego. 61 00:03:48,720 --> 00:03:53,570 Ponieważ funkcje format wejściowy konwersji są bardzo przydatne, powszechnie używane funkcje 62 00:03:53,570 --> 00:03:56,160 że nie są super intuicyjny w pierwszym, 63 00:03:56,160 --> 00:03:58,300 pójdziemy nad tym, jak sscanf działa. 64 00:03:58,300 --> 00:04:03,330 >> Pierwszy argument sscanf jest char * - wskaźnik do znaku. 65 00:04:03,330 --> 00:04:05,150 Aby funkcja działała poprawnie, 66 00:04:05,150 --> 00:04:08,340 że znak powinien być pierwszym znakiem łańcucha C, 67 00:04:08,340 --> 00:04:12,270 zakończony null \ 0 znak. 68 00:04:12,270 --> 00:04:15,120 Jest to ciąg do analizowania 69 00:04:15,120 --> 00:04:18,269 Drugi argument sscanf jest ciąg formatu, 70 00:04:18,269 --> 00:04:20,839 zazwyczaj przekazywana jako stałej strun 71 00:04:20,839 --> 00:04:24,040 a może widzieliście ciąg jak to wcześniej przy użyciu printf. 72 00:04:24,040 --> 00:04:28,650 Znak procent w ciągu formatu wskazuje specyfikacją konwersji. 73 00:04:28,650 --> 00:04:30,850 Charakter bezpośrednio po znaku procentu, 74 00:04:30,850 --> 00:04:35,430 wskazuje typ C, że chcemy sscanf przekonwertować. 75 00:04:35,430 --> 00:04:40,090 W getInt, widać, że jest d% c% i. 76 00:04:40,090 --> 00:04:48,690 Oznacza to, że będzie starał się sscanf dziesiętna int -% d - i char - c%. 77 00:04:48,690 --> 00:04:51,510 Dla każdego specyfikatora konwersji w ciągu formatu, 78 00:04:51,510 --> 00:04:56,620 sscanf oczekuje odpowiadający mu argument później w liście argumentów. 79 00:04:56,620 --> 00:05:00,850 Argument ten musi wskazywać na miejscu odpowiednio wpisywanych 80 00:05:00,850 --> 00:05:04,000 , w którym w celu przechowywania wyniku konwersji. 81 00:05:04,000 --> 00:05:08,910 >> Typowym sposobem na to jest do utworzenia zmiennej na stosie przed wywołaniem sscanf 82 00:05:08,910 --> 00:05:11,440 dla każdej pozycji, którą chcesz analizować z łańcucha 83 00:05:11,440 --> 00:05:15,520 a następnie użyć operatora adres - ampersand - aby przekazać wskaźniki 84 00:05:15,520 --> 00:05:19,100 tych zmiennych na wezwanie sscanf. 85 00:05:19,100 --> 00:05:22,720 Widać, że w getInt robimy dokładnie to. 86 00:05:22,720 --> 00:05:28,240 Tuż przed zaproszenia sscanf oświadczamy, int o nazwie n i char c połączenia na stosie, 87 00:05:28,240 --> 00:05:32,340 i mijamy wskaźniki do nich w zaproszeniu sscanf. 88 00:05:32,340 --> 00:05:35,800 Umieszczenie tych zmiennych na stosie jest preferowana przy użyciu przestrzeni dyskowej 89 00:05:35,800 --> 00:05:39,350 na stercie z malloc, ponieważ uniknie się zaproszenia malloc, 90 00:05:39,350 --> 00:05:43,060 i nie trzeba się martwić o wycieki pamięci. 91 00:05:43,060 --> 00:05:47,280 Postacie nie poprzedzone znakiem procentu nie poprosi konwersji. 92 00:05:47,280 --> 00:05:50,380 Raczej po prostu dodać do specyfikacji formatu. 93 00:05:50,380 --> 00:05:56,500 >> Na przykład, jeżeli w ciągu formatu getInt były d% zamiast 94 00:05:56,500 --> 00:05:59,800 sscanf wyglądałaby dla litery a następnie int, 95 00:05:59,800 --> 00:06:04,360 i chociaż to spróbuje przekonwertować int, nie byłoby nic innego z A. 96 00:06:04,360 --> 00:06:07,440 Jedynym wyjątkiem jest to spacja. 97 00:06:07,440 --> 00:06:11,030 Białe znaki w ciąg formatu dopasować dowolną ilość spacji - 98 00:06:11,030 --> 00:06:12,890 nawet wcale. 99 00:06:12,890 --> 00:06:18,100 Więc dlatego comment wspomina ewentualnie prowadzi i / lub końcowe białe znaki. 100 00:06:18,100 --> 00:06:22,910 Tak, w tym momencie wygląda jak nasz apel sscanf będzie próbował analizować przez użytkownika ciąg znaków 101 00:06:22,910 --> 00:06:25,380 poprzez sprawdzenie możliwości wiodącego spacją, 102 00:06:25,380 --> 00:06:29,300 następnie int będzie skonwertowany i przechowywane w zmiennej n int 103 00:06:29,300 --> 00:06:33,090 następnie pewnych ilości spacji, a następnie znak 104 00:06:33,090 --> 00:06:35,810 przechowywane w char c zmiennej. 105 00:06:35,810 --> 00:06:37,790 >> Co o wartości powrotnej? 106 00:06:37,790 --> 00:06:41,560 Sscanf będzie analizować linię wejściową od początku do końca, 107 00:06:41,560 --> 00:06:44,860 zatrzymania, gdy dojdzie do końca, gdy znak lub na wejściu 108 00:06:44,860 --> 00:06:49,320 nie pasuje znak formatu lub gdy nie może dokonać konwersji. 109 00:06:49,320 --> 00:06:52,690 To zakończenia używany jest wyodrębnić, gdy przestał. 110 00:06:52,690 --> 00:06:55,670 Jeśli się zatrzymał, ponieważ osiągnięty koniec ciągu wejściowego 111 00:06:55,670 --> 00:07:00,630 przed dokonaniem konwersji, a przed nie pasujące części łańcucha formatu, 112 00:07:00,630 --> 00:07:04,840 Następnie specjalna stała EOF jest zwracana. 113 00:07:04,840 --> 00:07:08,200 W przeciwnym razie zwraca liczbę udanych konwersji, 114 00:07:08,200 --> 00:07:14,380 które może wynosić 0, 1, lub 2, od Poprosiliśmy dwóch konwersji. 115 00:07:14,380 --> 00:07:19,000 W naszym przypadku, chcemy się upewnić, że użytkownik wpisze w int i tylko int. 116 00:07:19,000 --> 00:07:23,370 >> Tak, chcemy sscanf wrócić 1. Zobacz, dlaczego? 117 00:07:23,370 --> 00:07:26,850 Jeśli sscanf zwróciło 0, wtedy nie konwersje zostały dokonane, 118 00:07:26,850 --> 00:07:31,690 więc użytkownik wpisze coś innego niż int na początku wejścia. 119 00:07:31,690 --> 00:07:37,100 Jeśli sscanf zwraca 2, użytkownik nie prawidłowo wpisać w na początku wejścia 120 00:07:37,100 --> 00:07:41,390 ale następnie wpisane w jakiś nie-białym znakiem potem 121 00:07:41,390 --> 00:07:44,940 od% c konwersji udało. 122 00:07:44,940 --> 00:07:49,570 Wow, to całkiem długie wyjaśnienie dla jednego wywołania funkcji. 123 00:07:49,570 --> 00:07:53,460 W każdym razie, jeśli chcesz więcej informacji na temat sscanf i jej rodzeństwo, 124 00:07:53,460 --> 00:07:57,130 zobacz strony podręcznika, Google, lub obu. 125 00:07:57,130 --> 00:07:58,780 Istnieje wiele opcji, format string, 126 00:07:58,780 --> 00:08:03,830 a te mogą zaoszczędzić dużo pracy ręcznej, gdy próbuje analizować ciągi w C. 127 00:08:03,830 --> 00:08:07,180 >> Ostatnią funkcją w bibliotece patrzeć na to GetString. 128 00:08:07,180 --> 00:08:10,310 Okazuje się, że jest to trudne GetString funkcja pisać poprawnie, 129 00:08:10,310 --> 00:08:14,290 choć wydaje się, że taki prosty, zadania wspólne. 130 00:08:14,290 --> 00:08:16,170 Dlaczego jest to przypadek? 131 00:08:16,170 --> 00:08:21,380 No cóż, myślę o tym, jak będziemy przechowywać wiersz użytkownik wpisze w. 132 00:08:21,380 --> 00:08:23,880 Ponieważ ciąg jest ciągiem znaków, 133 00:08:23,880 --> 00:08:26,430 możemy chcieć przechowywać w tablicy na stosie, 134 00:08:26,430 --> 00:08:31,250 ale trzeba wiedzieć, jak długo tablica będzie, kiedy to zgłosić. 135 00:08:31,250 --> 00:08:34,030 Podobnie, jeśli chcemy, aby umieścić go na stercie, 136 00:08:34,030 --> 00:08:38,090 musimy przekazać do malloc liczbę bajtów chcemy rezerwy, 137 00:08:38,090 --> 00:08:39,730 , ale nie jest to możliwe. 138 00:08:39,730 --> 00:08:42,760 Nie mamy pojęcia, jak wiele znaków użytkownik wpisać 139 00:08:42,760 --> 00:08:46,590 zanim użytkownik faktycznie musi je wpisać. 140 00:08:46,590 --> 00:08:50,720 >> Naiwne rozwiązanie tego problemu jest po prostu zarezerwować spory kawałek przestrzeni, powiedzmy, 141 00:08:50,720 --> 00:08:54,540 Blok 1000 znaków dla użytkownika danych wejściowych, 142 00:08:54,540 --> 00:08:57,980 przy założeniu, że użytkownik nigdy nie wpisywać w ciąg tak długo. 143 00:08:57,980 --> 00:09:00,810 To jest zły pomysł z dwóch powodów. 144 00:09:00,810 --> 00:09:05,280 Po pierwsze, przy założeniu, że użytkownicy zazwyczaj nie wpisywać ciągi znaków, które długo 145 00:09:05,280 --> 00:09:07,610 można tracić pamięć. 146 00:09:07,610 --> 00:09:10,530 Na nowoczesnych maszynach, to może nie być problemem, jeśli to zrobisz 147 00:09:10,530 --> 00:09:13,890 w jednym lub dwóch pojedynczych przypadkach 148 00:09:13,890 --> 00:09:17,630 ale jeśli bierzesz użytkownika dane w pętli i przechowywania w celu późniejszego wykorzystania, 149 00:09:17,630 --> 00:09:20,870 można szybko wysysają mnóstwo pamięci. 150 00:09:20,870 --> 00:09:24,450 Dodatkowo, jeśli program piszesz jest dla mniejszej komputera - 151 00:09:24,450 --> 00:09:28,100 urządzenie takie jak smartphone czy coś innego z ograniczoną pamięcią - 152 00:09:28,100 --> 00:09:32,060 rozwiązanie to będzie powodować problemy znacznie szybciej. 153 00:09:32,060 --> 00:09:36,450 Drugi, bardziej poważny powód, aby nie jest to, że pozostawia program podatny 154 00:09:36,450 --> 00:09:39,710 co się nazywa atak przepełnienia bufora. 155 00:09:39,710 --> 00:09:45,840 W programowaniu, bufor jest pamięć używana do tymczasowego przechowywania danych wejściowych lub wyjściowych, 156 00:09:45,840 --> 00:09:48,980 która w tym przypadku jest nasz char blok 1000. 157 00:09:48,980 --> 00:09:53,370 Przepełnienie bufora, gdy dane są zapisywane poza końcem bloku. 158 00:09:53,370 --> 00:09:57,790 >> Na przykład, jeśli użytkownik ma typ faktycznie w ponad 1000 znaków. 159 00:09:57,790 --> 00:10:01,570 Być może doświadczyliśmy tego przypadkowo podczas programowania z tablicami. 160 00:10:01,570 --> 00:10:05,620 Jeśli masz tablicę 10 liczb całkowitych, nic nie zatrzyma cię z próby odczytu lub zapisu 161 00:10:05,620 --> 00:10:07,810 15. int. 162 00:10:07,810 --> 00:10:10,000 Brak ostrzeżeń kompilatora lub błędy. 163 00:10:10,000 --> 00:10:13,250 Program tylko gafy prosto i uzyskuje dostęp do pamięci 164 00:10:13,250 --> 00:10:18,150 gdzie myśli 15. int będzie, a to może nadpisać inne zmienne. 165 00:10:18,150 --> 00:10:22,040 W najgorszym przypadku można zastąpić część swojego programu wewnętrznego 166 00:10:22,040 --> 00:10:26,820 mechanizmów kontroli, powodując program rzeczywiście wykonać różne instrukcje 167 00:10:26,820 --> 00:10:28,340 niż zamierzony. 168 00:10:28,340 --> 00:10:31,360 >> Teraz to nie jest wspólne, aby to zrobić przypadkowo, 169 00:10:31,360 --> 00:10:35,150 , ale jest to dość powszechna technika źli używać złamać programy 170 00:10:35,150 --> 00:10:39,080 i umieścić złośliwy kod na komputerach innych osób. 171 00:10:39,080 --> 00:10:42,910 Dlatego nie możemy po prostu skorzystać z naszego naiwnego rozwiązania. 172 00:10:42,910 --> 00:10:45,590 Musimy znaleźć sposób, aby zapobiec nasze programy będąc podatne 173 00:10:45,590 --> 00:10:47,880 na atak przepełnienia bufora. 174 00:10:47,880 --> 00:10:51,430 Aby to zrobić, musimy się upewnić, że nasz bufor może rosnąć jak czytamy 175 00:10:51,430 --> 00:10:53,850 więcej wejście od użytkownika. 176 00:10:53,850 --> 00:10:57,440 Rozwiązanie? Używamy bufor przydzielonej sterty. 177 00:10:57,440 --> 00:10:59,950 Ponieważ możemy zmienić jego rozmiar za pomocą funkcji Resize realloc, 178 00:10:59,950 --> 00:11:04,580 i śledzić z dwóch numerów - indeks następnego wolnego gniazda w buforze 179 00:11:04,580 --> 00:11:08,390 oraz długość i ilość bufora. 180 00:11:08,390 --> 00:11:13,210 Czytamy w znaki od użytkownika po jednym na raz używając fgetc funkcję. 181 00:11:13,210 --> 00:11:19,360 Argument fgetc funkcja przyjmuje - stdin - to odniesienie do standardowego ciągu wejściowego, 182 00:11:19,360 --> 00:11:23,810 który jest preconnected kanał wejściowy, który jest używany do przesyłania wprowadzane przez użytkownika 183 00:11:23,810 --> 00:11:26,270 z terminala do programu. 184 00:11:26,270 --> 00:11:29,890 >> Ilekroć użytkownik wpisze w nowym charakterze, możemy sprawdzić, czy wskaźnik 185 00:11:29,890 --> 00:11:35,810 następnego wolnego otworu oraz 1 jest większa niż pojemność bufora. 186 00:11:35,810 --> 00:11:39,690 +1 Przychodzi bo jeśli następny wolny indeks jest 5, 187 00:11:39,690 --> 00:11:44,150 Następnie nasz bufora długość musi być 6 dzięki 0 indeksowania. 188 00:11:44,150 --> 00:11:48,350 Jeśli zabrakło miejsca w buforze, a następnie staramy się zmienić jego rozmiar, 189 00:11:48,350 --> 00:11:51,690 podwojenie go tak, że obniżyć liczbę razy, że rozmiar 190 00:11:51,690 --> 00:11:54,760 jeśli użytkownik wpisując ciąg naprawdę długo. 191 00:11:54,760 --> 00:11:57,950 Jeśli łańcuch ma zdobyć zbyt długo lub gdy zabraknie pamięci sterty, 192 00:11:57,950 --> 00:12:01,350 Uwolnijmy nasze bufor i zwróć NULL. 193 00:12:01,350 --> 00:12:04,170 >> Wreszcie, dołączyć char do bufora. 194 00:12:04,170 --> 00:12:08,200 Gdy uderza użytkownika Enter lub Return, sygnalizując nowy wiersz, 195 00:12:08,200 --> 00:12:12,050 lub specjalny znak - kontrola d - co sygnalizuje koniec danych wejściowych, 196 00:12:12,050 --> 00:12:16,240 robimy sprawdzić, czy użytkownik faktycznie wpisane w cokolwiek. 197 00:12:16,240 --> 00:12:18,820 Jeśli nie, to zwróci null. 198 00:12:18,820 --> 00:12:22,280 Inaczej, ponieważ nasz bufor jest prawdopodobnie większy niż nam potrzeba, 199 00:12:22,280 --> 00:12:24,830 w najgorszym przypadku jest to prawie dwa razy większy niż potrzebujemy 200 00:12:24,830 --> 00:12:27,830 ponieważ dwukrotnie za każdym razem, zmiana rozmiaru, 201 00:12:27,830 --> 00:12:31,840 tworzymy nową kopię napisu przy użyciu tylko ilość miejsca, że ​​musimy. 202 00:12:31,840 --> 00:12:34,220 Możemy dodać dodatkowy 1 do zaproszenia malloc, 203 00:12:34,220 --> 00:12:37,810 tak, że nie ma miejsca na szczególnym charakterze terminatora null - \ 0, 204 00:12:37,810 --> 00:12:41,990 które dodajemy do ciągu, gdy będziemy kopiować w pozostałych bohaterów, 205 00:12:41,990 --> 00:12:45,060 używając strncpy zamiast strcpy 206 00:12:45,060 --> 00:12:48,830 tak, że możemy dokładnie określić, ile znaków chcemy skopiować. 207 00:12:48,830 --> 00:12:51,690 Strcpy kopiuje aż uderza \ 0. 208 00:12:51,690 --> 00:12:55,740 Potem uwolnić naszą bufora i zwraca kopię do rozmówcy. 209 00:12:55,740 --> 00:12:59,840 >> Kto wiedział takie proste pozorna funkcja może być tak skomplikowane? 210 00:12:59,840 --> 00:13:02,820 Teraz wiesz, co idzie do CS50 biblioteki. 211 00:13:02,820 --> 00:13:06,470 >> Nazywam się Nate Hardison i to CS50. 212 00:13:06,470 --> 00:13:08,350 [CS50.TV]