[Powered by Google Translate] Problem Sekcja Set 2: Edition Hacker Rob Bowden, Harvard University To CS50. CS50.TV Tak, jestem Rob. Jestem starszy w Kirkland. To jest mój trzeci rok TFing CS50. To jest pierwszy raz, kiedy się zmieniają od tradycyjnego wykładu stylu sekcji gdzie po prostu rodzaj przeglądu, co stało się w wykładzie, a potem wy zadawać pytania, teraz jest o wiele więcej problemów, oparte, gdzie należy używać spacji, a - Oh, więc pomysł jest, aby przejść do tego łącza wysłałem cię i będziesz w mojej przestrzeni. Nie ktoś ma laptopa? Okay. Więc mamy zamiar używać to i będziemy robić problemów żyć w sekcji i omawianie ich i zastanawianie się, co jest nie tak i mógłbym wyciągnąć niektóre z Twojego kodu i mógłbym przedyskutować swoje pomysły. Więc czy ktoś miał trudności? Można rozmawiać na boku, ja nie wiem, czy będziemy mieć powód. Teraz, podobnie jak w poprzednim supersection, jeśli były w tym klasy, wiesz, co to chodzi. Na wszystkich zestawów P nie będzie tych sekcjach. Więc P-set 2, specyfikacje, Chyba widziałem to na P-set 1 już. Ale możemy spojrzeć na P-2 do zestawu, co będziemy się iść na dzisiaj. I zobaczysz sekcję pytań. Więc będzie to w każdym z zestawów P, tam będzie część pytań. Do tej pory powiedział, "Rozważ to okazja do praktyki." Nie będzie poproszony o przesłanie tego programu. Chodzi o to, że te mają rodzaju pomogą Ci rozpocząć z zestawem problem. Chyba od wersji hacker, wiele z nich mają być tylko nowe, ciekawe rzeczy do nauki. Nie mogą być bezpośrednio stosowane do zestawu problemu. A teraz nie masz je zgłosić, ale w teorii, dla późniejszych zespołów problemowych, może je zgłosić, a więc możesz przyjść do sekcji lub obejrzeć sekcję, aby uzyskać odpowiedzi, czy można po prostu ich na własną rękę jeśli nie czujesz się jak cieszyć moją obecność. Tak - myślę, że jest to pierwszy z nich. Oh. Także, w ramach tych sekcji pytań mamy także zadać pytania o szorty. Sądzę więc, że w teorii, masz się oglądać te przed przyjściem do sekcji, ale to jest w porządku, jeśli nie, pójdziemy nad nimi w każdym razie. Tak więc możemy zacząć od tego: "Jak pętla różni się od do-while pętli? Kiedy jest ona szczególnie przydatna? " Więc ktoś ma jakiekolwiek - [Student] do-while zawsze wykonać co najmniej raz. Tak. Tak, że jest różnica. Pętla - ll po prostu zrób to tu - przy pętli, mamy warunek tu, natomiast do-while, nie masz warunek, aż dojdziemy tutaj. I tak, gdy program jest wykonywany, i dostaje się do pętli while, natychmiast sprawdza, czy ten warunek jest spełniony. Jeśli ten warunek nie jest prawdziwy, to po prostu pominąć pętlę całkowicie. Do-while, ponieważ program jest wykonywany, to dostaje się "zrobić". Nic w tym momencie dzieje się, tak kontynuuje wykonywanie. Potem, gdy trafi na "chwilę", jeśli warunek jest spełniony, to będzie pętla kopię i zrobić to ponownie i znowu i znowu, aż warunek nie jest prawdziwy, a potem po prostu spada przez. Tak, różnica jest, że to można pominąć od samego początku. To niekoniecznie jest wykonywany raz i może wykonywać więcej razy, jeśli warunek jest nadal prawdziwe. Więc pętla będzie tylko zrobić to raz, lub - podczas pętli - nie może trzeba to zrobić w ogóle, ponieważ jak najszybciej dostać się do niego, jeśli warunek nie jest spełniony, po prostu pomiń tuż nad nim. Mając na uwadze, do-while, będziemy wykonywać go raz, niekoniecznie. Potem, kiedy dojdziemy do stanu, możemy sprawdzić, czy to prawda czy fałsz. Jeśli to prawda, będziemy zrobić to ponownie, jeśli jest fałszywe, musimy po prostu dalej będzie. Więc kiedy jest ona szczególnie przydatna? Więc mogę powiedzieć, że w całości 4 lata, 3 lata, cokolwiek, że byłem programowania, użyłem tego, jak pod 10 razy. I prawdopodobnie 5 z nich jest w CS50 kiedy wprowadzamy do-while pętle. Więc kiedy użyłeś-while pętle? Kiedy jest - tak? [Student] Jeśli próbujesz dostać dane wprowadzone przez użytkownika, czy coś chcesz sprawdzić - Tak. Więc zrób pętle while, instrukcja wejścia jest duży. Dlatego na pierwszych zbiorów problemowych kilka, jeśli chcesz zwrócić się do użytkownika, jak, "Daj mi łańcuch," nie można kontynuować aż do uzyskania tego ciągu. I tak, koniecznie, trzeba prosić o ciąg co najmniej raz. Ale potem, jeśli odpowiedzieć coś złego, to trzeba do pętli i zapytać ponownie. Ale inne niż wejściowych użytkownika, to bardzo rzadko spotykam przypadek gdzie chcę pętli "co najmniej raz", ale prawdopodobnie więcej. Pytania lub -? Czy ktoś wykorzystywane do-while gdziekolwiek indziej? Okay. Więc następny jest: "Co ma identyfikator nielegalna zazwyczaj wskazują, czy wyprowadzać przez brzękiem? " Więc jaki kod można napisać, aby uzyskać "nielegalnej identyfikator? [Student] To x = 2? Tak więc możemy po prostu spróbować tutaj, x = 2. Pobiegamy ta - oh, nie kliknąć. Więc tutaj mamy - wszystko w porządku. "Korzystanie z niezadeklarowanych x identyfikacyjnych". Więc to jest nielegalna identyfikator, zmienny. To często nazywamy zmienną identyfikator. Więc może nie wiedzieć, że to faktycznie zmienna, ale nie wie, co to jest. Więc to jest identyfikator. Więc dlaczego jest nielegalna? Tak. Tak, aby jasno terminologii deklaracji zmiennej jest, kiedy powiedzieć "int x" lub "ciąg r" Cokolwiek. Inicjalizacja zmiennej, lub przypisanie zmiennej, jest, gdy mówisz "x = 2". Więc możemy zrobić to w oddzielnych etapach, int x, x = 2, a do - możemy mieć kilka rzeczy tutaj - ale dopóki linia ta się dzieje, x jest nadal zainicjowana, ale został uznany. I tak możemy oczywiście zrobić to w 1 linii, a teraz jesteśmy deklarowania i inicjalizacji. Pytania? I wreszcie: "Dlaczego nie jest szyfr Cezara bardzo bezpieczna?" Więc po pierwsze, czy ktoś chce powiedzieć, co Cipher Cezar? [Student] Caesar Cipher tylko jest to, że mapa, zmieniasz każdy list, pewna liczba liter przejść i wrócić nad i nie jest bardzo bezpieczny, ponieważ są tylko 26 możliwych opcji i po prostu trzeba spróbować każdego 1 osób aż dostaniesz. Oh. Tak więc, czy mam powtarzać? Caesar Cipher, it's - mam na myśli, będziemy mieć do czynienia z nim na temat problemów, które - lub chyba standardową edycję zestawu problemów, które nie znajduje się na wydanie hakerów. Więc w standardowej wersji do zestawu problemów, otrzymasz komunikat w stylu: "Witaj, świecie" i masz numer jak 6, i wziąć to przesłanie, a każdy znak, go obrócić o 6 pozycji w alfabecie. Tak "H" w stanie Cześć H-I-J-K-L-M-N. Więc pierwsza litera będzie n. Robimy to samo z e. Jeśli mamy, jak, z, czy coś, potem owinąć powraca do "." Ale każda postać dostaje cyklicznie 6 znaków później w alfabecie, a to nie jest bardzo bezpieczny ponieważ tylko 26 możliwości, jak wiele sposobów można zawinąć pojedynczą literę. Więc możesz po prostu spróbować wszystkich 26 z nich i, prawdopodobnie, przez długi wiadomości wystarczy, tylko 1 z tych możliwych 26 rzeczy będzie czytelne, i czytelne jeden będzie oryginalna wiadomość. Więc to nie jest bardzo dobry sposób szyfrowania w ogóle coś jest. Niezwiązane z tych spodenek, "Co to jest funkcja?" Więc co to jest funkcja? Tak. [Student] To jest jak oddzielny fragment kodu, który można zadzwonić, aby przejść przez, a następnie uzyskać wartości zwracanej cokolwiek. Tak. Więc ja odpowiem również poprzez odpowiadanie następny - lub też po prostu przez powtarzanie odpowiedzi na następny. Możesz użyć funkcji zamiast kopiowania i wklejania kodu w kółko. Wystarczy wziąć ten kod, umieścić go w fuction, a następnie można po prostu wywołać funkcję gdziekolwiek zostały kopiowanie i wklejanie. Więc funkcje są użyteczne. Więc teraz zrobimy rzeczywistych problemów. Pierwszy. Tak więc idea pierwszego jest, przechodzi to łańcuch, i niezależnie od tego - czy też powiedzieć wszystkie małe litery? Nie powiedzieć wszystkie małe litery. Więc wiadomość może być cokolwiek, i - o nie. Robi. "Dla uproszczenia można przyjąć, że użytkownik będzie tylko wejście małych liter i spacji." Więc przekaż mu wiadomość z tylko małymi literami a potem naprzemiennie między wielkimi i małymi literami - zmieniamy łańcuch zostanie kapitał i wielkie, na przemian. Więc zanim damy Ci sekund do nawet nurkować do problemu, to, co jest pierwszą rzeczą, która musimy zrobić? Oh, co ja po prostu kliknij na? Och, ja tylko kliknął email tutaj. Więc pierwszą rzeczą, którą trzeba zrobić - ja szukam w złym jeden? Czy to jest częścią tego? Nie, to nadal tam jest, choć. Ok, nadal tutaj. Teraz nie możemy zakładać, -? Tak. Tutaj nie możemy zakładać, że jest to tylko małe litery i spacje. Więc teraz mamy do czynienia z faktem, że litery mogą być, co chcemy, żeby były. A więc pierwszą rzeczą, którą chcesz zrobić, to po prostu komunikat. Musimy tylko dostać ciąg string s = getString, okay. Teraz ten problem, istnieje kilka sposobów na to zrobić. Ale mamy zamiar użyć operatory bitowe tutaj. Czy są ludzie, którzy albo nie byli w supersection, lub coś, i nie wiem, co operatory bitowe są? Albo jak odnoszą się one do ASCII w jakikolwiek sposób? [Student] I nie było w supersection, ale wiem, co operatory bitowe są. Okay. Więc nie muszę iść na podstawy nich, ale postaram się wyjaśnić co mamy zamiar użyć tutaj. Więc 'A': reprezentacja Binary kapitału A liczba jest 65. Idę patrzeć - 41 będzie 01000001. Tak, że powinno być 65 w notacji dziesiętnej, więc to jest reprezentacja binarna postać kapitału A. Teraz reprezentacja binarna charakteru małe litery 'a' będzie to samo, prawie. Jest to, że - 6, yeah. To jest w porządku. Więc binary kapitał, binarne małej '.' Więc zauważyć, że różnica między i "a" jest to jeden bit. I to dzieje się 32 bit, bit reprezentujący liczbę 32. I to ma sens, ponieważ jest 65, "a" jest 97. Różnica między nimi wynosi 32. Więc teraz wiemy, że możemy przekonwertować z A do 'A' poprzez i logiczną ORing go, z - który wygląda jak 1. To jest bitowym OR z 00100000, i że da nam '. " I możemy się od "A" do poprzez mnożenie logiczne z 11, 0 w tym miejscu, 11111. Więc to będzie nam dać dokładnie to, co "było, ale znoszą tę indywidualną trochę, więc będziemy mieć 01000001, ja nie wiem, czy mogę liczyć w prawo. Ale ta technika bitowej ORing dostać od kapitału na małe litery, i mnożenie logiczne dostać się z małej litery do kapitału nie jest zarezerwowana dla A. Wszystkie litery, K vs K, Z vs z, wszystkie z nich są po prostu będzie się różnić o tego jednego bitu. I tak można to wykorzystać, aby zmienić z dowolnego małej litery do każdej litery i odwrotnie. Okay. Tak łatwy sposób na uzyskanie z tego - więc zamiast pisać cokolwiek 1011111 jest - łatwy sposób reprezentująca ten numer, a to nie jest jeden że poszedłem w supersection, ale tylda (~) jest kolejnym bitwise operator. Co ~ robi to patrzy na reprezentacji bitowej. Weźmy dowolny numer. To tylko niektóre liczbę binarną, a co ~ nie jest to tylko odwraca wszystkie bity. Tak więc jest to 1, teraz 0, to jest 0, teraz 1 010100. Więc to wszystko ~ ma. Tak więc 32 będzie liczba - pozbyć, że - tak, 32 będzie liczba 00100000, i tak ~ to będzie ta liczba się tutaj, że AND "a" z. Czy każdy widzi? Jest to dość powszechne, jak wtedy, gdy chcesz się dowiedzieć dla późniejszych rzeczy, abyśmy się widząc, gdy chcemy sprawdzić, czy - czy chcemy wszystko, każdy set nieco poza 1 masz tendencję do nie ~ z bitem, że nie chcemy ustawić. Więc nie chcesz 32 ustawiony bit, więc robimy z 32 ~. Okay. Tak więc możemy korzystać ze wszystkich tych tutaj. W porządku, więc to dobrze, jeśli nie skończymy, będziemy powoli chodzić nad sobą, lub spacer nad tym, więc - przez to. Spacer po tym. Więc mamy ciąg, i chcemy pętli nad każdego znaku tego łańcucha i coś do niego. Jak więc w pętli nad ciąg? Co powinniśmy używać? Nie zamierzam tego robić tutaj. Tak. Więc mam iteracyjnej, i powiedział to, ale skąd mam wiedzieć, ile znaków w ciągu? Strlen (s), a następnie i + +. Więc to, co zrobiłem tutaj nie najlepszy sposób robienia rzeczy jest. Czy ktoś wie dlaczego? Ponieważ jesteś sprawdzanie języka ciągu każdym razem jeden. Więc będziemy chcieli przenieść strlen, mogę powiedzieć tutaj, int length = strlen (s), a następnie wykonaj i > 1 bit. To może być nieco większa niż 1, o ile wszystkie bity poniżej tej pozycji są takie same. Dlatego musimy co najmniej 26 znaków - czy istnieje 26 znaków. Dlatego musimy co najmniej 26 numerów stanowią różnicę - Różnica między i "a" musi być co najmniej 26, inaczej nie bylibyśmy reprezentowane wszystkie numery kapitałowych. Oznacza to, że, jeśli zaczniemy od 1, to będzie korzystać ze wszystkich tych bitów, Wszystkie z tych pierwszych 5 bitów, które są reprezentatywne wszystko przez Z. Dlatego następny bit, lub ten bit, następny bit jest tym, który zdecydował się odróżnić i "." To też, dlaczego w tabeli ASCII, są 5 symbole oddzielające litery z małych liter. Ponieważ są to symbole, które przynosi dodatkowe 5 do 32 jest różnica między nimi. [Student] Więc możemy to zrobić, bo ASCII zaprojektowany w ten sposób. Tak. Ale ASCII - różnica może być zarówno z tych bitów. Podoba Ci się, jeśli były 10000001 i "" był 11100001 - I zapomnieć, cokolwiek. Ale gdyby było to, to możemy nadal korzystać z 'A' - A. To właśnie różnica między i "a" jest nadal te 2 bity. Myślę, że to jest napisane 48. Czy to jest 32 + 64? Myślę, że jest? Jest jeszcze 2 bity, każdy znak, jak, Z i Z, K i K, nadal są one dokładnie takie same bity ustawione wyjątkiem tych 2 bitów. Tak długo, jak to jest zawsze prawdziwe, niezależnie czy używamy ASCII lub inny system, tak długo, jak jest tylko określoną liczbę bitów, które są różne dla każdej postaci, następnie, że działa dobrze. Tyle tylko, że 32 została utworzona, ponieważ jest to pierwszy moglibyśmy użyć. >> Cool. I wolą, w przypadku, gdy nie widać, jeśli blok jest tylko jeden wiersz, możesz pozbyć się klamrach; więc wolą to robi. Również, w jaki sposób możemy robić takie rzeczy jak s [i] + = 1? Można również zrobić s [i] = 32 bitowe AND. I logiczną OR = 32. Również liczyć mod 2 == 0. Więc pamiętaj, że - nie będę pisać - każdy niezerowa wartość true, a 0 jest fałszywa. Tak ", jeśli mod Ilość 2 == 0" jest taki sam, jak mówi "Jeśli nie liczy mod 2". I pewnie by tak odwrócić linii i powiedział, "jeśli liczba mod 2, nie lub 1 indziej I 1 ", tak że nie muszę" nie ". Ale to działa tak samo dobrze. I co jeszcze mogę zrobić tutaj? Można łączyć je z potrójnych, jeśli chcesz, ale wtedy to, że wystarczy dokonać rzeczy Messier i prawdopodobnie bardziej trudne do odczytania, więc nie będziemy tego robić. Ktoś ma jakieś inne propozycje? Czy to wszystko, problem prosiłem? Oh yeah. Więc pozbyć się tych pustych linii, teraz będziemy drukować f,% s jest jedna dla ciągów, Będziemy drukować F, S. Teraz uruchom go. Czy zrobiłem coś złego? To \ ", chcę się n. Okay. Teraz będziemy go uruchomić. To będzie prawdopodobnie krzycz na mnie. Strlen jest string.h. Więc to jest miłą rzeczą jest to Clang mówi, co to jest w, zamiast GCC, które po prostu mówi: "Hej, zapomniałem o czymś, nie wiem, co to było." Ale to powie mi, "ma obejmować string.h". Więc nie pytaj o nic, więc nie mówi nic. Ale zrobimy za ich przykładem, "Thanks 4 do Dodaj". To wygląda dobrze. Brawo. Więc wracając do głównego, prawie nigdy nie zrobić. Jest to opcjonalne. I jest jedynym głównym funkcji, dla których jest to opcjonalne. Jeśli nie zwraca niczego od głównego, to zakłada się, że masz na myśli powrót 0. Pytania? Okay. Więc teraz drugi problem. "Przypomnijmy od 2 tygodni w drugim wykładzie, że zamiana wartości 2 zmiennych", przekazując te 2 zmienne do funkcji (nawet jeśli nazywa swap) nie dokładnie działa, przynajmniej nie bez "wskazówek". I ignorować wskazówki, aż się do nich dostać. Chcemy zamienić 2 zmiennych; nie używamy funkcji to zrobić. Ciągle dzieje się to zrobić w głównym, jak to mówi. Ale do korzystania z tych 2 zmiennych, nie chcemy użyć zmiennej tymczasowej. Istnieją 2 sposoby, aby to zrobić. Możesz to zrobić za pomocą swoich tradycyjnych operatorów binarnych. Więc czy ktoś wie, szybki i brudny sposób to robi? To może rzeczywiście podjąć minuty myślenia. Jeśli mam - Założę problem się jak pytają. Więc jeśli mam 2 zmienne, które jest po prostu liczbą całkowitą że dają mi, i B zmienna suma, która jest kolejnym całkowitą że jestem podane. Więc jeśli mam te 2 zmienne, teraz chcę, aby zamienić je. Tradycyjny, za pomocą regularnej operatorów binarnych, to znaczy, jak +, -, ÷. Nie operatory bitowe, które działają na binarny. Więc za pomocą -, +, ÷, i wszystkich tych. Możemy zamienić robiąc coś = a + b, a b = a - b, a = - b. Więc, sanity sprawdzić, a potem zobaczymy, dlaczego to działa. Załóżmy, że a = 7, b = 3, a A i B będzie 10. Więc jesteśmy teraz ustawienie = 10, a następnie robimy b = a - b. Więc robimy b = a - b, która ma być 7, b = a - b ponownie, lub = a - b. Który będzie 10 - 7, który jest 3. Więc teraz, w pełnym zakresie "," było 7, b był 3, a teraz b jest 7 i 'a' jest 3. Tak więc tego rodzaju sens, "a" jest połączenie 2 numery. W tym momencie, "a" jest połączenie, a następnie jesteśmy odejmując Oryginał B, a następnie mamy odejmując co oryginał "." Ale to nie działa dla wszystkich numerów. Aby to zobaczyć, rozważmy system, tak zwykle myślimy liczb całkowitych jako 32 bitów. Pracujmy nad czymś, co tylko jak 4 bitów. Mam nadzieję, że wymyślić dobry przykład teraz. Tak, wiem, to będzie łatwe. Powiedzmy, że nasze 2 numery są 1111 i 1111, tak więc jesteśmy w binarnym teraz. W rzeczywistych miejsc po przecinku, jeśli chcesz, aby myśleć o tym w ten sposób, a = 15, b = 15. A więc się spodziewać, po tym jak zamienić je - nawet nie muszą być takie same numery, ale zrobiłem to w ten sposób. Zróbmy ich nie te same numery. Zróbmy 1111 i 0001. Tak = 15 i B = 1. Po zamienić je, oczekujemy "" być 1 i b jest 15. Więc nasz pierwszy krok to a = a + b. Nasze numery tylko 4 bitów, to "", który jest 1111, + b, które jest 0001, będzie w końcu jest 10000, ale mamy tylko 4 bity. Więc teraz = 0. A teraz chcemy ustawić b = a - b - faktycznie, to nadal działa idealnie. = a - b - zobaczymy, czy to działa doskonale. Tak więc B = 0 - 1, które w dalszym ciągu wynosi 15, a A = A - B, który jest 1. Może to działa. Czuję, że jest powód że nie działa za pomocą regularnych. Ok, więc pracuje się na założeniu, że to nie działa z regularnych operacji binarnych, i będę szukać - będę z Google, aby zobaczyć, czy to prawda. Dlatego chcemy, aby to zrobić stosując operatory bitowe, a wskazówką jest XOR. Tak więc, wprowadzenie XOR (^), jeśli nie widziałeś jeszcze. To znowu, operatory bitowe, więc działa po trochu i it's - Jeśli bity 0 i 1, to będzie 1. Jeśli masz bitów 1 i 0, to będzie 1, masz bity 0 i 0 to będzie 0, a jeśli masz bity 1 i 1 to będzie 0. Więc jak to jest OR. Jeśli jeden z bitów są prawdziwe, to 1, ale w przeciwieństwie do I, nie mogą być oba bity są prawdziwe. Lub mogło to być 1, XOR miałoby to być 0. Więc mamy zamiar użyć XOR tutaj. Pomyśl o tym przez chwilę, idę do Google. Cóż, nie można przeczytać, że, jestem obecnie na wymiany XOR strony algorytmu. Mam nadzieję, że będzie to wyjaśnić, dlaczego nie mogę się - To jest dokładnie to algorytm, który właśnie zrobił. I nadal nie rozumiem, dlaczego - Musiałem po prostu wybrał zły przykład, ale w tym przypadku, gdzie "a" się stać 0, po dotarciu do 5 bitów, więc teraz "a" jest 0, że to, co nazywa się "przepełnienie całkowitoliczbowe." Według Wikipedii: "W przeciwieństwie do wymiany XOR, to zmiana wymaga, że ​​używa kilku metod zapewnić, że x + y nie powoduje przepełnienie całkowitoliczbowe. " Więc to ma problemy, to przepełnienie całkowitoliczbowe, ale zrobiłem coś złego. Nie jestem pewien. Postaram się wymyślić innego. [Student] Cóż, nie przepełnienie całkowitoliczbowe jest, kiedy próbujesz umieścić numer tam większa niż ilość bitów zostały rozdzielone? Tak. Mamy 4 bity. That's - mieliśmy 4 bity, a my wtedy spróbować dodać 1 do niego, więc kończy się z 5 bitów. Ale piąty bit tylko pobiera odcięte, tak. To może faktycznie - [Student] Czy to rzucić błąd, czy też, że - by to rzucić błąd? No więc nie ma błędu. Gdy dojdziesz do poziomu zespołu, specjalny bit gdzieś jest, że powiedział, że nie było przepełnienia, ale w C masz rodzaj po prostu nie radzą sobie z tym. Naprawdę nie mogę sobie z tym poradzić, chyba że używa specjalnych instrukcji montażu w C. Pomyślmy o zamianie XOR. I myślę, że artykuł w Wikipedii może się również powiedzieć, że - Więc to też wychowany Arytmetyka modularna, więc myślę, że jestem w teorii robi arytmetyki modularnej kiedy powiedziałem, że 0 - 1 jest 15 ponownie. Tak, że może faktycznie - regularnie procesora, który nie 0 - 1 = 15. Ponieważ kończy się na 0, odejmujemy 1, więc to po prostu owija powraca do 1111. Tak więc w rzeczywistości może to algorytm pracy, A + B, A - B, B -, że może być dobrze. Ale jest kilka procesorów, które tego nie robią, i tak nie byłoby to w porządku w tych konkretnych nich. Swap XOR będzie działać na każdym procesorze. Okay. Chodzi o to, że to ma być taki sam, choć. Gdzie korzystamy XOR jakoś uzyskać informacje zarówno na 1 zmiennych, a następnie wyciągnąć informacje o poszczególnych zmiennych ponownie. Więc czy ktoś ma pomysły / odpowiedź? [Odpowiedź Student, niezrozumiały] Tak to powinno działać, a także, XOR jest przemienne. Niezależnie od tego, w jakiej kolejności te 2 numery stało się w tu, Ten wynik będzie taki sam. Tak ^ b to b ^. Warto również zobaczyć to napisane jak ^ = b, b ^ =, ^ = b ponownie. Tak to jest w porządku, i dlaczego to działa, myślę o bitach. Korzystanie niewielka ilość, powiedzmy, 11001 i 01100. Więc to jest "a", to jest b. Tak ^ = b. Zamierzamy być ustawienie 'a' = do XOR z tych 2 rzeczy. 1 ^ 0, więc jest 1, 1 ^ 1 0., 0 ^ 1 oznacza 1, i 0 ^ 0 jest 0, 1 ^ 0 jest 1. Tak "," Jeśli spojrzeć na liczbę dziesiętną, to będzie - nie będziemy widzieć dużo stosunków między pierwotnym "A" i nowy "," ale patrząc na bitach, "a" jest teraz jak oczka informacji zarówno oryginalnego 'A' i B oryginalnego. Więc jeśli weźmiemy b ^, widzimy, że skończymy na oryginał "." A jeśli wziąć oryginał "'^ nowe", "widzimy skończymy w oryginalnej b. Tak (a ^ b) ^ b = oryginał "." I (a ^ b) ^ = b oryginału. Nie ma - inny sposób widzenia jest to XOR coś sama jest zawsze 0. Tak 1101 ^ 1101, wszystkie bity będą takie same. Tak więc nie będzie to przypadek, gdzie 1 jest 0, a drugi oznacza 1. Więc to jest 0000. To samo z tym. (A ^ b) ^ b jest jak ^ (b ^ b). (B ^ b) będzie 0; ^ 0 jest po prostu będzie "," ponieważ wszystkie bity 0. Tak więc tylko te, które będą, gdzie "a" był początkowo 1 - mieli nich. A sam pomysł tu jestem całkiem pewien, że to również przemienne. Tak. Powiedziałem wcześniej, że to było przemienne. ^ ',' I to jest łączne, więc teraz (b ^) ^. I możemy zrobić b ^ (^). I znowu, mamy oryginalną b. Tak 'a' jest teraz połączenie 'A' i B razem. Korzystanie z naszego nowego combo 'a' b = mówimy combo '' ^ oryginalny b, otrzymujemy oryginał "." A teraz combo = '' ^ nowy b, która była oryginalna - lub co jest teraz to, co było "a" lub b. To ten przypadek tutaj. To = b, old b. Więc teraz wszystko jest z powrotem w zamienione kolejności. Jeśli rzeczywiście wyglądał na bitach, b = a ^ b, będzie XOR te 2, i odpowiedź będzie to i to a = a ^ b jest XORing te 2 i odpowiedź jest następująca. Pytania? Okay. Tak ostatni jest nieco znacznie trudniejsze. [Student] Myślę, że ma wątpliwości. >> O, przepraszam. [Student] Co rzeczywiście szybciej? Jeśli używasz tego XOR, czy to jeśli zadeklarować nową zmienną? Tak więc to, co jest rzeczywiście szybciej, deklarując nową zmienną lub za pomocą XOR do wymiany? Odpowiedź jest, według wszelkiego prawdopodobieństwa, zmienna tymczasowa. A to dlatego, że po jego skompilowany w dół - tak na poziomie złożenia, nie ma czegoś takiego jak zmienne lokalne lub jakichkolwiek zmiennych tymczasowych lub jakiekolwiek z tych rzeczy. Oni po prostu lubią - jest pamięć, a są rejestry. Rejestry są gdzie rzeczy są aktywnie dzieje. Nie dodać 2 rzeczy w pamięci, dodać 2 rzeczy w rejestrach. I przynieść rzeczy z pamięci do rejestrów, a następnie dodać je, a następnie można umieścić je z powrotem do pamięci, ale akcja dzieje się w rejestrach. Więc kiedy używasz zmiennej tymczasowej podejście, zwykle to, co się dzieje, jest te 2 numery są już w rejestrach. , A następnie od tego momentu, po tym, jak zamienić je, będzie to po prostu zacząć używać innego rejestru. Gdziekolwiek używał b, to będzie po prostu korzystać z rejestru, który został już przechowywanie ". Więc nie trzeba nic robić, aby rzeczywiście zrobić swap. Tak? [Student] Ale również zajmuje więcej pamięci, prawda? To zajmie tylko więcej pamięci czy potrzebuje przechowywania tej zmiennej tymczasowej. Lubię, jeśli później użyć tej zmiennej tymczasowej znów gdzieś, następnie - lub przypisać coś do tej zmiennej tymczasowej. Tak więc, jeśli w dowolnym momencie w czasie "," b w temp. mają różne wartości, czy coś, wtedy będzie miał odrębne miejsca w pamięci, ale prawdą jest, że istnieje wiele zmiennych lokalnych, które istnieją tylko w rejestrach. W tym przypadku, to nigdy nie wprowadzony do pamięci, a więc nigdy nie marnujemy pamięć. Okay. Ostatnie pytanie jest nieco bardziej. Więc, w tym urządzenia CS50 istnieje słownika. A powodem tego jest fakt, [? B66] jest sprawdzanie pisowni, gdzie będzie można pisać używając tabel mieszania lub próbuje ani trochę strukturę danych. Idziesz do pisania sprawdzania pisowni, a masz zamiar używać tego słownika to zrobić. Ale dla tego problemu, jesteśmy po prostu będzie patrzeć, czy jedno słowo jest w słowniku. Więc zamiast zapisania całego słownika w jakiejś strukturze danych a następnie patrząc na całego dokumentu, aby zobaczyć, czy coś się błędnie, chcemy tylko znaleźć 1 słowo. Więc może po prostu skanuje cały słownik i jeśli nie znajdziemy tego słowa w całym słowniku, to nie było tam. Jeśli skanowanie w całym słowniku i widzę słowo, to jesteś dobry, znaleźliśmy go. Jest tu napisane, że chcemy zacząć szukać w funkcji obsługi plików z C, ponieważ chcemy czytać słownik, ale dam podpowiedź tutaj, co do których funkcje powinny myśleć. Napiszę je obszarów. Tak więc najważniejsze z nich będziemy chcieli przyjrzeć się f otwarty, a następnie, w sposób nieunikniony, f zamknięty która będzie w końcu programu, F i F skanowania. Można także użyć f czytać, ale prawdopodobnie nie chcesz dlatego, że - nie skończyć potrzebują tego. F scan f jest co masz zamiar używać do skanowania na słownik. A więc nie trzeba kodować do rozwiązania, po prostu spróbuj i jak pseudo-code drogę do rozwiązania, a potem będziemy dyskutować. I rzeczywiście, bo już dał ci to, jeśli pójdziesz do dowolnego terminala lub urzàdzenia w skorupkach, Chciałbym - zwykle - jeśli nie widziałeś jeszcze, nie wiem, jeśli nie w klasie, ale człowiek, więc strony man, są bardzo przydatne do patrząc na prawie każdym funkcji. Więc można zrobić, jak, F Man, skanowania f. To jest teraz temat rodziny skanowania f funkcji. Mogę też zrobić F Man, otwarte, i że dam mi szczegóły tego. Więc jeśli wiesz, jaka funkcja jest używana, lub czytasz kod i widzisz jakąś funkcję i jesteś jak "Co to zrobić?" Tylko człowiek, że nazwa funkcji. Istnieje kilka dziwnych przykładów, gdzie można powiedzieć podoba. man 2, że nazwa funkcji lub man 3, że nazwa funkcji, ale trzeba tylko zrobić człowiek, jeśli nazwa funkcji nie stanie do pracy po raz pierwszy. [Student] Tak czytam manuala dla otwartych, ale wciąż nie wiedzą jak z niego korzystać i program. Okay. Wiele stron podręcznika są mniej, niż pomocny. Są bardziej przydatne, jeśli już wiesz, co robią a potem po prostu trzeba zapamiętać kolejność argumentów czy coś. Lub mogą dać ogólny przegląd, ale niektóre z nich są bardzo przytłaczające. Jak f skanowania f, również. To daje informacje dla wszystkich tych funkcji, i 1 linię w dół tutaj dzieje się powiedzieć, "F f skanowania odczytuje z punktu smyczkowy lub strumienia." Ale f otworzyć. Więc, jak będziemy używać f open? Ideą programu, który musi zrobić plik I / O jest to, że trzeba najpierw otworzyć plik, który chcesz zrobić rzeczy, i nieuchronnie czytać rzeczy z tego pliku i robić rzeczy z nimi. F otwarty jest co możemy użyć do otwarcia pliku. Co nam się wrócić, więc jaki plik chcemy otworzyć, daje nam - tu mówi "/ user / share / dict / words." Jest to plik, który chcemy otworzyć, a my chcemy, aby go otworzyć - musimy wyraźnie określić, czy chcemy, aby go otworzyć do odczytu lub, jeśli chcemy otworzyć go napisać. Istnieje kilka kombinacji i takie tam, ale chcemy, aby otworzyć to do czytania. Chcemy czytać z pliku. Więc co ten powrót? Zwraca plik gwiazdkę (*), a ja po prostu pokazać wszystko w zmiennej f, więc *, ponownie, jest to wskaźnik, ale nie chcemy zajmować się wskaźniki. Możesz myśleć, jak f, f jest teraz zmienna będziesz używać do reprezentowania plik. Więc jeśli chcesz do odczytu z pliku, można przeczytać od f. Jeśli chcesz, aby zamknąć plik, zamykasz f. Więc na koniec programu, kiedy nieuchronnie chce zamknąć plik, co powinniśmy zrobić? Chcemy zamknąć f. Więc teraz ostatnia funkcja plik będziemy chcesz użyć scan f, f f skanowania. I co to robi, to skanuje przed plikiem patrząc na wzór, aby dopasować. Patrząc na manualu tutaj widzimy, int f f skanowania ignorować wartości zwracanej teraz. Pierwszy argument jest strumień plik *, więc pierwszy argument będziemy chcesz przekazać jest f. Jesteśmy skanowanie ponad f. Drugi argument jest łańcuchem formatu. Dam wam ciąg formatu teraz. Myślę, że stało się powiedzieć, 127S \ n, dużo, że to niepotrzebne. Pomysł co to format string jest, jest można myśleć f skanowania jako przeciwieństwo f. druku. Więc f print, print f również korzystać z tego typu parametru formatu, ale f druku, co robimy jest - spójrzmy na ekwiwalent. Więc wydrukować f, a tam rzeczywiście również f print f, gdzie pierwszym argumentem będzie f. Podczas drukowania f, można powiedzieć coś w stylu "print 127S \ n", a następnie, jeśli mijamy mu trochę ciąg, to się wydrukować ten ciąg, a następnie w nowej linii. Co 127 znaczy, jestem pewien, ale ja nigdy nie ogranicza się do tego, Ty nawet nie trzeba mówić '127 'w F druku ale co to znaczy, to wypisuje pierwsze 127 znaków. Więc jestem pewien, że to przypadek. Można google na to. Ale w następnej jestem prawie pewien, że to oznacza, że. Więc jest to wypisuje pierwsze 127 znaków, a następnie w nowej linii. F f skanowania teraz, zamiast patrzeć na zmiennej i drukowania, to będzie wyglądać w pewnym ciągu, i zapisać wzór do zmiennej. Miejmy faktycznie używać f skanowania w innym przykładzie. Powiedzmy więc, że mieliśmy trochę int, x = 4, i chcieliśmy stworzyć łańcuch wykonany z - chciał stworzyć ciąg to było jak, to pojawi się znacznie później, coś, co jest jak 4.jpg. Więc może to być program, w którym będziesz miał licznik SUM, Podsumowując przeciwdziałać i, i chcesz zapisać kilka zdjęć. Więc chcesz zapisać i.jpg, gdzie i jest kilka iteracji swojej pętli. Jak więc uczynić ten ciąg dla tego JPEG? Jeżeli chcesz wydrukować 4.jpg, możemy tylko powiedzieć, f druku, d.jpg%, a potem to wydrukować w tym JPEG. Ale jeśli chcemy zapisać 4.jpg ciąg używamy f skanowania. Więc string s - faktycznie możemy nie mogę się - znak, char s, chodźmy 100. Więc po prostu oświadczył trochę tablicę 100 znaków, i to, co jesteśmy nieuchronnie będzie przechowywanie że JPEG w. Więc mamy zamiar używać f skanowania, a format, jak powiedzielibyśmy d.jpg% w celu wydrukowania 4.jpg, format ten będzie d.jpg%. Więc format d.jpg%, co chcemy zamienić% d z jest x, a teraz trzeba przechowywać ten ciąg gdzieś. A gdzie będziemy przechowywać ten ciąg jest w tablicy s. Tak więc po tej linii kodu, s, jeśli drukujemy F, S% zmiennej s, to będzie drukować 4.jpg. F F tak skanowania jest taki sam, jak skanowania F, lecz teraz to patrząc archiwum za to, co do przechowywania w sekundach. To właśnie ostatni argument będzie. Chcemy zapisać - "rodzina f skanowania funkcji skanowania zarówno wg formatu jak próbowałem poniżej. Jeśli którekolwiek są przechowywane w lokalizacji punktów może wrócić - " Nie możemy być dobry. Niech pomyślę o sekundy. Więc scan f nie jest - co do cholery jest funkcja, która to robi? Więc scan f nie zajmie integer i zrobić dot JPG. To będzie [Mumbles]. Zapisz zmienną int int smyczkową C. Co to jest zmienna, lub co jest ta funkcja nazywa? Tak. That's - tak. Więc co ja do ciebie określenie przed było s print f, które - sprawia, że ​​o wiele więcej sensu, dlaczego powiedział, że był o wiele bardziej jak f druku. Skanowanie f jest jeszcze coś w rodzaju f druku, ale f print s będzie skanować go i zastąpić zmienne i teraz przechowywać ją w ciąg. Zamiast drukować go, przechowuje je w ciąg. Więc zignorować całkowicie. Nadal można myśleć o specyfikatora formatu jako takiego f druku. Więc teraz, jeśli chcemy zrobić 4.jpg rzecz, zrobilibyśmy f Wydrukuj S, X tego. Więc co scan f robi - co twoje pytanie będzie? [Student] Jestem po prostu mylić na co próbujemy zrobić tutaj z tym JPEG. Czy możesz wyjaśnić, że 1 więcej czasu? Tak to było - to mniej istotnych unormowań prawnych do f f skanowania teraz, miejmy nadzieję, że będzie to wiązać z powrotem w jakiś sposób. Ale to, co początkowo zamierzał pokazać było - to jest rzeczywiście bezpośrednio odnoszące się do tych [? F5] Będziesz używać f Wydrukuj s, gdzie, że mamy 100 zdjęć, i chcesz przeczytać plik 1.jpg, 2.jpg, 3.jpg. Tak aby to zrobić, musisz F Otwórz, a następnie trzeba przejść w ciąg, który chcesz otworzyć. Więc chcemy otworzyć 1.jpg, aby utworzyć ciąg, który jest 1.jpg, my s f wydruku% d.jpg--nie zrobić dla int i = 0. i <40, i + +. Więc print s% f d.jpg z i. Tak więc po tej linii, teraz zmienna lub tablica s będzie 1.jpg. Albo 0.jpg, 1.jpg, 2.jpg. I tak można otworzyć, z kolei każdy obraz do odczytu. Więc to jest to, co s wydrukować f robi. Czy widzisz to, co s wydrukować f jest teraz robisz? [Student] Okay, więc to bierze - tworzy ciąg something.jpg, a następnie zapisuje go. Tak. Stwarza to - to jest inny format string, tak jak i f f skanowania wydruku gdzie wstawia wszystkie zmienne do drugiego argumentu, może być s, w przeciwieństwie do i. Być - to znaczy, że to przypadek. Ale cokolwiek by z argumentów jest. To będzie wstawić wszystkie zmienne w ciągu formatu a następnie zapisać się do naszego bufora; nazywamy to bufor, to gdzie będziemy przechowywać ciąg. Więc są przechowywane wewnątrz s prawidłowo sformatowany string,% d został zastąpiony 4. [Student] Więc jeśli to zrobił, to zmienna f tylko będzie przeniesiony? Tak. Więc powinniśmy zamknąć oryginalny f przed zrobieniem tego. Ale - i wtedy również, jeśli nie było f otwarcie tutaj, wtedy musielibyśmy powiedzieć - Tak. Ale byłoby otworzyć sto różnych plików. [Student] Ale nie bylibyśmy w stanie uzyskać dostęp lub - w porządku. Okay. Tak skanowania f, f f skanowania jest rodzaj samej idei, ale zamiast, zamiast przechowywać je w ciąg, to nic więcej jak jesteś teraz będzie ponad użądlenia i wzorzec dopasowywania tego łańcucha i przechowywania wyników do zmiennych. Możesz użyć skanowania f analizować nad czymś 4.jpg i przechowywać całkowitą 4 w x int sum. To, co możemy wykorzystać f skanującej. F scan f zrobi, że w linii poleceń. Właściwie to jestem pewien, że to właśnie biblioteka CS50 ma. Więc kiedy mówisz, "dostać int," to scan f-ing na - f skanowania sposób można uzyskać dane wejściowe użytkownika. F scan f ma zamiar zrobić to samo, ale przy użyciu pliku umożliwia skanowanie za pośrednictwem. Więc tutaj, jesteśmy skanowania nad tym pliku. Wzór staramy się dopasować jakiś ciąg znaków, który jest 127 znaków następnie nowej linii Jestem więc pewien, że moglibyśmy po prostu powiedzieć "pasuje s", ponieważ w słowniku zdarzy nam się mieć, mamy zagwarantowane, że żadne słowo nie jest długa, oraz f f skanowania, jak sądzę, będzie zatrzymywać się na nowej linii, nie wiem co. Ale będziemy to nową linię w tym meczu, a także - [Student] Jeśli nie to nową linię, czy nie byłoby znaleźć części wyrazu? To - każdy - patrząc w słowniku - Tak więc, w słowniku, to wszystko naszych słów. Każdy z nich jest na nowej linii. F skanowania będzie odebrać to słowo. Jeśli nie to nową linię, to jest możliwe, że następny f skanowanie tylko przeczytać w nowej linii. Ale w tym nowej linii to będzie po prostu zignorować nowy wiersz. Ale my nigdy nie dostaniesz część słowa, ponieważ jesteśmy zawsze odczytanie do nowej linii, nie wiem co. [Student] Ale co, jeśli wyszukać słowo "," jak Cissa Cissa. Znajdzie to, i mówią, że to mecz? Więc tutaj - będzie to czytać - to jest rzeczywiście dobry punkt. Nigdy nie używamy prądu - słowo, którego szukasz jest pierwszy argument wiersza polecenia. Więc string, word = argv 1. Więc ciąg szukamy jest argv 1. Nie szukasz słowa w ogóle w naszej f skanowania. Co robimy ze skanowania f jest coraz każde słowo w słowniku, a następnie raz mamy to słowo zamierzamy użyć strcmp ich porównanie. Będziemy porównywać nasze słowo i to co po prostu czytać w. Tak nieuchronnie, mamy zamiar w końcu robić pęczek skanowania fs aż tak się dzieje, że scan f wróci - powróci jeden, tak długo, jak to jest dopasowane nowego słowa i zwróci coś innego, jak tylko nie udało się dopasować słowo. Czytamy w całym słowniku, przechowywania wierszu w każde słowo w zmiennej s. Następnie porównujemy słowo z s, a jeśli porównanie == 0, strcmp dzieje przynieść 0 jeśli mecz został złożony. Więc jeśli to było 0, to możemy wydrukować f, dopasowane, lub słowo jest w słowniku, czy cokolwiek chcesz wydrukować f. A potem - nie chcemy, aby f zamknąć w kółko. To jest jedna z tych rzeczy chcemy zrobić, a my nie tylko szukasz słowa w słowniku. Tak więc możemy zrobić, jeśli chcemy szukać ich wzór, Cissa, tak jak powiedziałem wcześniej, jeśli chcemy szukać tego wzorca, to byłoby nie w przypadku bo to nie jest właściwie słowo, ale jednym z tych słów w słowniku, że zdarza się mieć w nim. Więc to pasuje to słowo, ale to podzbiór słowa nie jest samo słowo. Ale to nie jest, w jaki sposób jest on używany, jesteśmy czytania w każdym słowie a następnie porównanie słowa mamy z tym słowem. Więc jesteśmy zawsze porównując pełne słowa. Mogę wysłać na sfinalizowanych rozwiązań później. Jest to rodzaj prawie odpowiedź prawej, myślę. [Komentarz Student, niezrozumiały] Och, nie mogę się pozbyć tego wcześniej? Char s, myślę, że powiedział, 127 - I zapomnieć, co jest największym. Będziemy po prostu zrobić 128, więc teraz jest to wystarczająco długo. Nie trzeba drukować niczego. Mamy również zamiar chcę zamknąć nasz plik, i że powinna być o prawidłowej odpowiedzi. CS50.TV