[Powered by Google Translate] Problema Secțiunea Set 2: Hacker Edition Rob Bowden, Universitatea Harvard Acest lucru este CS50. CS50.TV Deci, eu sunt Rob. Sunt un senior în Kirkland. Acesta este al treilea an TFing CS50. Este pentru prima dată când suntem schimba din secțiunea tradițional prelegere în stil, în cazul în care am doar un fel de comentariu este ceea ce sa întâmplat în curs și apoi voi pune întrebări, acum a fi o problemă mult mai-based, în cazul în care vom folosi spațiile, și - Oh, deci ideea este de a merge la link-ul de pe care v-am trimis si apoi vei fi în locul meu. Nu are nimeni un laptop? Bine. Deci, vom folosi acest lucru și vom face probleme trăiesc în secțiunea și discutarea lor și imaginind ceea ce e în neregulă și eu s-ar putea trage în sus o parte din codul, si eu s-ar putea discuta despre ideile tale. Deci, a avut cineva probleme? Puteți vorbi pe partea, eu nu știu dacă vom avea un motiv pentru asta. Acum, la fel ca supersection anterior, în cazul în care ai fost la această clasă, știi despre ce e vorba. La toate seturile P acolo va fi aceste secțiuni. Deci, P-set 2, caietul de sarcini, cred că ai văzut pe P-Set 1 deja. Dar ne putem uita la P-Set 2 pentru ceea ce am de gând să fie merge peste ziua de azi. Și veți vedea o secțiune de întrebări. Deci, acest lucru va fi în toate P-grupuri electrogene; acolo va fi o secțiune de întrebări. Până acum ne-am spus, "Luați în considerare aceasta o oportunitate de a practica." Tu nu vor fi rugați să prezinte acest program. Ideea este că acestea ar trebui să fel de a vă ajuta să începeți cu set de probleme. Cred că pe editie Hacker, multe dintre ele ar trebui să fie doar lucruri noi, interesante de a învăța. Acestea nu pot fi direct aplicabile set de probleme. Si acum ca nu avem ce le prezinte, dar în teorie, pentru seturi de probleme mai târziu, s-ar putea să le prezinte, și, astfel, vă pot veni fie de la pct. sau viziona secțiune pentru a obține răspunsuri, sau puteți obține doar le pe cont propriu dacă nu vă simțiți ca și cum se bucură de prezența mea. Deci - Cred că acesta este primul. Oh. De asemenea, în cadrul acestor secțiuni de întrebări și noi vă pune întrebări legate de pantaloni scurți. Deci, cred că, în teorie, tu ar trebui sa ma uit la aceste înainte de a veni la secțiunea, dar e bine daca nu, vom trece peste ele oricum. Astfel încât să putem începe cu acestea: "Cum o buclă în timp ce diferă de la o buclă do-timp? Când este deosebit de utilă din urmă? " Deci, cineva orice -? [Student] do-while va executa întotdeauna cel puțin o dată. Da. Deci, care este diferența. O buclă în timp ce - Voi doar să-l fac pe aici - în timp ce bucla, avem condiție chiar aici, în timp ce un do-timp, nu aveți o condiție până când vom ajunge aici. Și astfel, atunci când programul este de executare, precum și de a ajunge la bucla în timp ce, imediat verifică dacă această condiție este adevărată. Dacă această condiție nu este adevărată, se va trece doar peste bucla în întregime. Do-buclă în timp ce, așa cum este programul de executare, se ajunge la "a face". Nimic nu se întâmplă în acest moment, doar continuă de executare. Apoi, când va atinge "în timp ce," în cazul în care condiția este adevărată, se va bucla înapoi și fă-o din nou și din nou și din nou până când condiția nu este adevărată și apoi doar cade prin intermediul. Deci, diferența fiind, că acest lucru poate sări chiar de la început. Acest mod necesar execută o singură dată și apoi se pot executa mai multe ori în cazul în care condiția este încă adevărat. Deci, în timp ce bucla va face doar o singură dată, sau - în timp ce bucla - nu avem nevoie de a face acest lucru la toate, deoarece, imediat ce ajungem la ea, în cazul în care condiția este falsă, vom sări doar dreptul de peste el. Întrucât do-while, va fi execute o dată, în mod necesar. Apoi, când ajungem la starea, vom verifica dacă e adevărat sau fals. Dacă e adevărat, vom face din nou, dacă e falsă, vom continua doar de gând. Deci, atunci când acesta din urmă este deosebit de utilă? Deci, eu pot spune că, în totalitatea 4 ani, 3 ani, indiferent, că am fost de programare, am folosit acest lucru, cum ar fi, de 10 de ori. Și, probabil, 5 dintre ele sunt în CS50 atunci când vom introduce do-în timp ce buclele. Așa că atunci când te faci utilizat în timp ce-bucle? Când este - da? [Student] Când sunteți încercarea de a obține date introduse de utilizator, sau ceva pe care doriți să verificați - Da. Deci, în timp ce do-bucle, ghidul de intrare este unul mare. De aceea, pe seturi prima problemă de cuplu, atunci când doriți să întreb de utilizator, cum ar fi, "Dă-mi un șir," nu poate continua până când veți obține acel șir. Și așa, în mod obligatoriu, trebuie să solicite șir de cel puțin o dată. Dar, apoi, în cazul în care răspunde la ceva rău, atunci ai nevoie pentru a bucla înapoi și să ceară din nou. Dar, altele decât introduse de utilizator, este foarte rar ca am întâlni un caz în cazul în care vreau să bucla "cel puțin o dată", ci, eventual, mai mult. Întrebări sau -? Are cineva a folosit un do-while oriunde altundeva? Bine. Deci, următoarea este: "Ce vrea de identificare nedeclarate de obicei, indică dacă scoase de zăngănit? " Deci, ce fel de cod ar putea scriu pentru a obține "identificator nedeclarate?" [Student] că x = 2? Astfel încât să putem încerca doar să-l aici, x = 2. Vom rula acest lucru - oh, nu l-am faceți clic pe. Deci, aici avem - în regulă. "Utilizarea de identificare x nedeclarate." Așa că e identificatorul nedeclarate, o variabilă. Acesta va apela frecvent o variabilă un identificator. Deci, este posibil să nu știe că e de fapt o variabila, ea nu știe ce este. Deci, este un identificator. Deci, de ce este nedeclarate? Da. Deci, să fie clar în terminologia, declararea unei variabile este atunci când spui "x int" sau "șir y", indiferent de. Inițializare a variabilei, sau atribuirea variabilei, ori de câte ori este spui "x = 2." Astfel încât să putem face aceste în etape separate, int x, x = 2, și până la - putem avea o grămadă de lucruri aici - dar până la această linie se întâmplă, x este încă neinitializata, dar a fost declarat. Și astfel putem face, evident, în 1 linie, iar acum suntem declararea si initializarea. Întrebări? Și, în sfârșit, "De ce nu este cifrul lui Cezar foarte sigur?" Deci în primul rând, nimeni nu vrea să spună ce Cifrul Caesar este? [Student] Cezar Cifrul este faptul că doar harta, te schimbă în fiecare scrisoare, un anumit număr de scrisori trece peste, și pentru a muta înapoi peste, și nu e foarte sigur, deoarece există doar 26 de opțiuni posibile și trebuie doar să încercați fiecare 1 din cei până când îl obține. Oh. Deci, ar trebui să repet? Cifrul Caesar, e. - Adică, vei fi de-a face cu ea pe problemele pe care le - sau Cred că ediția standard a setului problemă care nu e pe ediția hacker. Deci, pe ediția standard a set de probleme, primiți un mesaj de genul, "Bună ziua, lume," și aveți, de asemenea, un număr de 6 cum ar fi, și să luați acest mesaj, și fiecare caracter individual, îl rotiți cu 6 poziții în alfabetul. Deci, "h" în salut ar deveni h-i-j-k-L-m-n. Deci, prima scrisoare ar fi n. Noi facem acelasi lucru cu e. Dacă avem o, ca, Z sau ceva, apoi ne înfășurați în jurul valorii de înapoi la "o". Dar fiecare personaj devine succed 6 caractere mai târziu, în alfabet, și nu e foarte sigur din moment ce există doar 26 de posibilități de câte feluri ai ar putea încheia o singură literă. Astfel încât să puteți încerca pur și simplu toți cei 26 de ei și, probabil, pentru un mesaj destul de lung, numai 1 din aceste posibile 26 lucruri va fi lizibilă, iar cel lizibile va fi mesajul original. Deci nu e un mod foarte bun de criptare nimic, la toate. Nu au legătură cu aceste pantaloni scurti, "Ce este o funcție?" Deci, ce este o funcție? Da. [Student] E ca o bucată separată de cod pe care le puteți apela pentru a merge prin și apoi obține valoarea de returnare a orice. Da. Așa că voi răspunde prin a răspunde, de asemenea, următoarea - sau se repetă, de asemenea, răspunzând doar următoarea. Aveți posibilitatea să utilizați funcțiile în loc de doar copierea și lipirea codul de peste si peste din nou. Doar că cod, puneți-l într-o Functie, apoi ai putea apela doar funcția ori de câte ori ați fost copierea și lipirea. Deci, funcțiile sunt utile. Deci, acum, vom face probleme reale. Primul. Deci, ideea de prima este, tu treci un șir, și indiferent de - sau nu-l spune totul cu litere mici? Ea nu spune tot cu litere mici. Deci, mesajul poate fi orice, și - oh, nu. Ea face. "Pentru simplitate, se poate presupune că utilizatorul va numai de intrare cu litere mici si spatii." Așa că am să-l dați un mesaj cu doar litere mici și apoi vom alterna între capital și minuscule - vom schimba șir de capital să fie și mici, alternativ. Deci, înainte de a ne oferi o secundă să se scufunde chiar și în problema, ceea ce este primul lucru pe care trebuie să facem? Oh, ce am doar să faceți clic pe? Oh, am dat click pe un e-mail aici. Deci, primul lucru ce trebuie să facem - să mă uit la una greșită? Este aceasta o parte din asta? Nu, cei care sunt încă acolo, totuși. Bine, încă aici. Acum nu putem presupune -? Da. Aici nu putem presupune că e doar litere mici si spatii. Deci, acum avem de a face cu faptul că scrisorile pot fi orice dorim să fie. Și astfel primul lucru pe care vrem să facem este obține doar mesajul. Avem nevoie doar de a obține un șir, sirul s = getString, bine. Acum această problemă, există o serie de moduri de a face asta. Dar suntem de gând să doriți să utilizați operatori la nivel de bit aici. Există persoane care fie nu au fost la supersection, sau ceva, și nu știu ce operatorii pe biți sunt? Sau modul în care acestea se referă la ASCII în vreun fel? [Student] nu am fost la supersection, dar eu știu ce operatorii pe biți sunt. Bine. Deci nu am pentru a trece peste elementele de bază ale acestora, dar voi explica ceea ce am de gând să doriți să utilizați aici. Deci, "A": reprezentare binară a capitalului A, numărul este de 65. Sunt doar de gând să se uite la - 41 va fi 01000001. Așa că ar trebui să fie 65 de ani în zecimal; astfel încât acesta este reprezentarea binară a capitalului A. caracterul Acum, reprezentarea binară a caracterului litere mici "a" va fi același lucru, aproape. Este că - 6, da. Acest lucru este drept. Deci, capitalul binar Un litere mici, binar "o". Deci, observăm că diferența dintre A și "a" este acest singur bit. Și aceasta se întâmplă să fie de 32 biți, biți reprezentând numărul 32. Și asta face sens, deoarece A este 65; "a" este 97. Diferența dintre ele este 32. Deci, acum stim ca putem converti de la A la "A" de a lua o și la nivel de bit-l ring, cu - care arată ca un 1. Acesta este un nivel de bit SAU, cu 00100000, și că ne va da "un." Și putem obține de la "a" la A la nivel de bit de ANDing cu 11, 0 în acel loc, 11111. Deci, acest lucru va da apoi ne exact ceea ce "a" a fost, dar se anulează acest bit individuală, deci vom avea 01000001, eu nu știu dacă am numărat bine. Dar aceasta tehnica de la nivel de bit ring pentru a obține din capital la litere mici, și la nivel de bit ANDing pentru a obține de la litere mici la capital nu este exclusiv la A. Toate scrisorile, K vs K, Z vs Z, toate acestea sunt doar de gând să difere de această singur bit. Și astfel încât să puteți folosi aceasta pentru a comuta de pe orice literă mică la orice scrisoare de capital și vice-versa. Bine. Deci, o modalitate ușoară de a obține de la aceasta - așa că în loc de a trebui să scrie tot ce este 1011111 - o modalitate ușoară de a reprezenta acest număr, iar acest lucru nu este unul că m-am dus peste in supersection, dar tilda (~) este un alt operator de la nivel de bit. Ce face ~ este se pare la reprezentarea biți. Să luăm orice număr. Acesta este doar un numar binar, și ceea ce nu este ~ flips doar toate biți. Deci, asta a fost un 1, acum un 0, acest lucru este un 0, acum un 1, 010100. Deci, asta e tot ~ face. Deci, 32 se va fi numărul de - a scăpa de faptul că - deci 32 va fi numărul 00100000, și așa mai departe ~ a acestei va fi acest număr până aici că am ANDed "a", cu. Are toată lumea vezi asta? Acest lucru este destul de comună, la fel ca atunci când doriți să dau seama pentru lucruri mai târziu pe care am putea fi văzut, atunci când vrem să vedem dacă - sau ne dorim totul, fiecare set singur bit, cu excepția pentru 1 aveți tendința de a face ~ de biți pe care nu vrem setat. Deci, nu vrem set de 32 de biți, deci avem ~ de 32. Bine. Astfel încât să putem folosi pe toți cei aici. În regulă, așa că e bine, dacă nu ai terminat, vom merge încet peste împreună, sau mers pe jos peste asta, așa - prin asta. Plimbare prin asta. Deci avem șirul nostru, și vrem să bucla peste fiecare caracter în șir și să facem ceva pentru ea. Deci, cum putem bucla peste un șir? Ce ar trebui să folosim? Eu nu am de gând să-l fac pe aici. Da. Deci, am iterator meu, iar el a spus, dar cum nu știu cât de multe caractere sunt în șir? Strlen (s), apoi i + +. Deci, ceea ce am făcut aici, nu este cel mai bun mod de a face lucrurile. Stie cineva de ce? Pentru ca esti verificarea limba șir de fiecare dată singur. Așa că am de gând să doriți să se mute strlen, am putea spune aici, int lungime = strlen (s), și apoi face i > 1 bit. Acesta ar putea fi mai mult de 1 bit, atâta timp cât toate de mai jos biți această poziție sunt aceleași. Deci, avem nevoie de cel puțin 26 de caractere - sau, există 26 de caractere. Deci, avem nevoie de cel puțin 26 de numere pentru a reprezenta diferența - Diferența dintre A și "a" trebuie să fie de cel puțin 26, sau altfel nu ne-ar fi reprezentat toate numerele de capital. Asta înseamnă că A, în cazul în care vom începe de la 1, se va folosi toate aceste biți, toate aceste primii 5 biți, pentru a reprezenta totul prin Z. De aceea biți următoare, sau acest bit, următorul bit este cel care a ales să se facă distincția între A și "o". Asta e, de asemenea, motivul pentru care, în tabelul ASCII, există 5 simboluri de separare litere din capital de la litere mici. Deoarece acestea sunt simbolurile, plus 5, care aduce 32 fiind diferența dintre ele. [Student] Deci, am putea face acest lucru, pentru că ASCII este proiectat în acest fel. Da. Dar ASCII - diferența ar putea fi, de asemenea, ambele biți. Ca, dacă A fost 10000001, și "a" a fost 11100001 - Am uitat, indiferent. Dar dacă ar fi fost acest lucru, atunci am putea folosi în continuare "a" - A. E doar acum diferența dintre A și "a" este în continuare aceste 2 biți. Cred că e scris 48. Este 32 + 64? Cred că este? Ar fi inca 2 biți; fiecare caracter unic, cum ar fi, Z și Z, K și K, ei ar avea în continuare aceleași biți exacte stabilite, cu excepția acelor 2 biți. Deci, atâta timp cât e întotdeauna adevărat, indiferent dacă suntem folosind ASCII sau un alt sistem, atât timp cât nu există decât un anumit număr de biți, care sunt diferite pentru fiecare personaj, apoi că funcționează bine. E doar faptul că 32 a fost înființat pentru că e primul ne-ar putea folosi, eventual. Mișto >>. Eu tind să prefere, în cazul în care nu ați văzut, în cazul în care blocul este doar o singură linie, poti scapa de acolade; așa că am tendința de a prefera face acest lucru. De asemenea, știți cum putem face lucruri cum ar fi s [i] + = 1? Puteți face, de asemenea, s [i] la nivel de bit SI = 32. Și la nivel de bit SAU = 32. De asemenea, luate în considerare mod 2 == 0. Așa că ne amintim - nu voi scrie - orice valoare non-zero, este adevărat, și 0 este falsă. Deci, "în cazul în care numărul de mod 2 == 0" este aceeași cu a spune "daca nu conta mod 2." Eu, probabil, ar fi inversat doar liniile și a spus, "dacă numărul Mod 2, nu sau 1, altceva ȘI 1 ", așa că nu am nevoie de" nu ". Dar acest lucru funcționează la fel de bine. Și ce altceva pot face aici? Ai putea să le combine cu ternar, dacă ai vrut, dar apoi asta ar face doar lucrurile Messier și, probabil, mult mai greu de citit, așa că nu va face asta. Oricine are orice alte sugestii? Este că toate problema cerut? Oh, da. Deci, scapa de aceste linii goale, acum vom imprima f,% s fiind unul pentru siruri de caractere, Vom imprima F, S. Acum, hai să-l rulați. Am făcut ceva greșit? Asta e un \ "; Vreau un nr. Bine. Acum vom rula. Va țipa la mine, probabil. Strlen este în string.h. Deci, asta este un lucru frumos despre zăngănit este vă spune ce e în, în loc de GCC care doar spune, "Hei, ai uitat ceva, nu știu ce a fost." Dar acest lucru va spune-mi, "Ai vrut să includă string.h." Așa că nu am cere nimic, așa că nu se spune nimic. Dar vom face exemplul lor, "thanks 4 add". Asta arata bine. Ura. Deci, revenind la principala ta, eu nu fac asta aproape. E opțional. Și principal este singura funcție pentru care este opțională. Dacă nu întoarce nimic din principal, se presupune că ai vrut să returnați valoarea 0. Întrebări? Bine. Deci, acum doua problemă. "Recall la prelegerea 2 săptămâni de-al doilea, care pompare valori 2 variabilelor prin trecerea cele 2 variabile la o funcție (chiar dacă sunt chemați de swap) nu funcționează exact, cel puțin nu fără "indicii". Și să ignore indicii până când vom ajunge la ele. Dorim să schimbe 2 variabile, noi nu utilizați o funcție pentru a face acest lucru. Suntem încă de gând să-l facă în principal ca se spune. Dar pentru a folosi cele 2 variabile, noi nu doriți să utilizați o variabilă temporară. Există 2 moduri de a face acest lucru. Poti sa o faci folosind dvs. de operatorii tradiționali binare. Deci, nimeni nu știe un mod rapid și murdar de a face asta? S-ar putea avea de fapt un minut de gândire. Dacă am - Voi seta problema sus ca ei cer. Deci, dacă am 2 variabile, A, care este doar un număr întreg că m-au dau, și suma variabila B, care este un alt întreg care am dat. Deci, dacă am aceste 2 variabile, acum vreau sa le schimba. Tradițional, folosindu-vă operatorii regulate binare, vreau sa spun, ca +, -, ÷. Nu operatori la nivel de bit, care acționează pe binar. Prin utilizarea așa -, +, ÷, și toți cei. Am putea schimba de a face ceva de genul a = a + b, și b = a - b, a = a - b. Deci, bun-simț verifica, iar apoi vom vedea de ce lucrări. Să spunem că un = 7, b = 3, atunci A + B va fi 10. Deci suntem de stabilire acum un 10 =, iar apoi facem b = a - b. Deci, facem b = a - b, care va fi de 7, și b = a - b, din nou, sau o = a - b. Care este de gând să fie cu 10 - 7, care este de 3. Deci, acum, în mod corect, "A" a fost de 7, b a fost de 3, iar acum b este 7 și "a" este 3. Deci, acest tip de sens; "a" este combinația dintre cele 2 numere. În acest moment, "a" este combinația, iar apoi vom scăzând din b originală, și apoi vom scăderea ce a fost original "o". Dar acest lucru nu funcționează pentru toate numerele. Pentru a vedea acest lucru, să ia în considerare un sistem; așa ne gândim de obicei de numere întregi, ca 32 de biți. Hai să lucreze la ceva care e doar ca 4 biți. Sperăm că am venit cu un exemplu bun acum. Deci, eu știu, acest lucru va fi ușor. Să spunem noastre 2 numere sunt 1111, 1111 și, deci suntem în binar acum. În zecimale reale, în cazul în care doriți să se gândească în felul ăsta, o. = 15 și b = 15 Și astfel ne așteptăm, după ce le-am schimba - ele nu trebuie nici măcar să fie aceleași numere, dar am făcut-o în acest fel. Să nu-i face aceleași numere. Să facem 1111 și 0001. Deci, un = 15 și b = 1. După ce le-am schimba, ne așteptăm la "A" pentru a fi 1 și b să fie 15. Deci, primul nostru pas este un = a + b. Numerele noastre sunt numai 4 biți, astfel încât "o", care este 1111, + b, care este 0001, se va termina prin a fi 10000, dar avem doar 4 biți. Deci, acum un = 0. Și acum vrem să setați b = a - b - de fapt, acest lucru încă funcționează perfect. a = a - să vedem dacă asta funcționează perfect - b. Deci, atunci b = 0 - 1, care ar fi încă 15, și apoi a = a - b, ceea ce ar fi 1. Poate că acest lucru nu. Mă simt ca nu e un motiv pentru care nu funcționează cu ajutorul regulat. Ok, deci lucrează la ipoteza că acesta nu funcționează cu operațiunile regulate binare, și voi căuta - Voi Google pentru a vedea dacă acest lucru este adevărat. Așa că vrem să o facem folosind operatori la nivel de bit, iar indiciu aici este XOR. Deci, introducerea XOR (^) în cazul în care nu ați văzut-o încă. E, din nou, un operator de bit așa că acționează bit cu bit, si este - Dacă aveți biți 0 și 1, atunci aceasta va fi 1. Dacă aveți de 1 și 0 biți, acesta va fi 1, aveți la 0 și 0 biți va fi 0, și, dacă aveți un biți și 1 va fi 0. Deci e ca și cum SAU. Dacă oricare dintre biți sunt adevărate, e 1, dar spre deosebire de SAU, ea nu poate fi atât de biți care sunt adevărate. Sau ar fi aceasta să fie de 1, XOR ar avea acest fi 0. Așa că de gând să doriți să utilizați XOR aici. Gândește-te pentru un minut, am de gând să Google. Ei bine, nu puteți citi că, eu sunt în prezent pe pagina de algoritmul XOR de swap. Sperăm că acest lucru va explica de ce Nu pot - Acest lucru este exact algoritmul pe care tocmai l-am făcut-o. Eu tot nu văd de ce - am ales trebuie să fi doar un exemplu rău, dar acest caz, în cazul în care "o" sa întâmplat de a deveni 0, după ce la 5 biti, asa ca acum "a" este 0, asta este ceea ce se numește "de tip integer overflow." Conform Wikipedia, "Spre deosebire de swap XOR, această variație presupune că acesta utilizează unele metode pentru a garanta că x + y nu determina o integer overflow. " Deci, acest lucru nu avea probleme, acest lucru a fost de tip integer overflow, dar am făcut ceva greșit. Nu sunt sigur. Voi încerca să vină cu un altul. [Student] Ei bine, nu este de tip integer overflow atunci când sunteți încercarea de a pune un număr de acolo mai mare decât suma de biti care le-ați alocat? Da. Avem 4 biți. Asta e. - am avut 4 biți, ne apoi încercați să adăugați la 1 la acesta, așa că am termina cu 5 biți. Dar bit cincea doar se taie, da. S-ar putea, de fapt - [Student] Asta te arunc o eroare, sau nu, care - ar arunca asta vreo eroare? Nu Deci nu e nici o eroare. Când ajungi la nivelul de asamblare, un pic de construcții undeva este stabilit faptul că a spus că a fost un preaplin, dar în C ai un fel de pur si simplu nu a face cu asta. Tu de fapt, nu se poate face cu ea, decât dacă folosiți instrucțiuni speciale de asamblare în C. Să ne gândim de swap XOR. Și cred că articolul din Wikipedia ar fi fost, de asemenea spunând că - Deci, de asemenea, adus aritmetica modulara, deci cred că am fost, în teorie, face aritmetica modulara când am spus că 0 - 1 este din nou 15. Deci, care ar putea, de fapt - pe un procesor obișnuit care face 0 - 1 = 15. Din moment ce am ajuns la 0, scădem 1, astfel încât atunci doar se încadrează în jurul valorii de înapoi la 1111. Deci, acest algoritm ar putea lucra, de fapt, a + b, a - b, b - o, pentru ca s-ar putea să fie bine. Dar există unele procesoare care nu face acest lucru, și astfel nu ar fi bine în aceste cele specifice. Swap-XOR va funcționa pe orice procesor. Bine. Ideea este ca ar trebui sa fie la fel, totuși. În cazul în care ne folosim XOR pentru a obține într-un fel de informații atât în ​​1 a variabilelor, și apoi trageți afară de informații a variabilelor individuale din nou. Deci, nimeni nu are idei / răspuns? [Răspuns Student, neinteligibil] Deci, acest lucru ar trebui funcționeze, și, de asemenea, XOR este comutativ. Indiferent de scopul pe care aceste 2 numere se întâmplă să fie în sus aici, acest rezultat va fi la fel. Deci, un ^ b este b ^ o. S-ar putea vedea, de asemenea este scris ca o ^ = b, b = ^ o, o ^ = b din nou. Deci, acest lucru este drept, și pentru a vedea de ce functioneaza, cred că de biți. Folosind un număr de smallish, să zicem 11001, 01100 și. Deci, aceasta este "o"; aceasta este b. Deci, un ^ = b. Vom fi stabilirea = 'A' la XOR din aceste 2 lucruri. Și-așa 1 ^ 0 este 1; 1 ^ 1 este 0, 0 ^ 1 este 1, și 0 ^ 0 este 0, 1 ^ 0 este 1. Deci "o," dacă te uiți la numărul zecimal, aceasta va fi - nu vei vedea mai mult de o relație între versiunea originală "a" și noul "o", dar uită la biți, "a" este acum ca o plasă de informații atât original, 'a' și b originale. Deci, dacă luăm b ^ o, vom vedea că vom ajunge la originalul "o". Și dacă luăm în original "a" ^ nou "o", vom vedea vom ajunge la b original. Deci (a ^ b) ^ b = original "o". Și (a ^ b) ^ a = b original. Nu există - un alt mod de a vedea acest lucru este XOR nimic în sine este întotdeauna 0. Deci, 1101 ^ 1101, toți biții vor fi aceleași. Deci, nu a existat niciodată o să fie un caz în care 1 este un 0 și cealaltă este 1. Deci, asta este 0000. Același lucru cu acest lucru. (A ^ b) ^ b este ca un ^ (b ^ b). (B ^ b) va fi 0; un ^ 0 este doar de gând să fie "o", deoarece toți biții sunt 0. Deci, singurii care vor fi în cazul în care "o", a fost inițial o 1 - a avut cele. Și aici, aceeași idee, eu sunt destul de sigur că e, de asemenea, comutativ. Da. Eu am spus înainte că a fost comutative. ^ "O", și este asociativ, asa ca acum (b ^ a) ^ o. Și putem face b ^ (a ^ a). Și astfel, din nou, avem b original. Deci, "a" este acum combinație de "a" și b împreună. Folosind noul nostru combo-'a' b = spunem Combo "a" ^ b originală, avem originalul "o". Și acum un combo = "a" ^ b noua, care a fost inițial - sau care este acum ceea ce a fost "o", sau b. Asta e acest caz aici. Acest lucru este = b, b vechi. Deci, acum totul este din nou în ordinea schimbate. Dacă avem de fapt uitat la biți, b = o ^ b, este de gând să XOR aceste 2, și răspunsul va fi acest lucru, și apoi o = o ^ b este XORing aceste 2 și răspunsul este aceasta. Întrebări? Bine. Deci, ultima este ceva mult mai dificil. [Student] Cred că are o întrebare cu privire la aceasta. >> Oh, îmi pare rău. [Student] Ce e de fapt mai repede? Dacă utilizați această XOR, sau este daca declara o variabilă nouă? Deci, ce este de fapt mai rapid, declarând o variabilă nouă sau folosind XOR pentru a schimba? Răspunsul este, după toate probabilitățile, o variabilă temporară. Și asta pentru că după ce a fost compilat în jos - deci la nivel de ansamblu, nu e nici un lucru, cum ar fi variabile locale sau orice variabile temporare sau la oricare dintre aceste lucruri. Sunt la fel ca - nu e de memorie, și există registre. Registre sunt în cazul în care lucrurile se întâmplă în mod activ. Tu nu adăugați 2 lucruri în memorie; se adaugă 2 lucruri în registre. Și aduceți lucrurile din memorie în registrele pentru a adăuga apoi le, și apoi s-ar putea le-a pus înapoi în memorie, dar toate acțiunile se întâmplă în registre. Deci, atunci când utilizați abordarea temporar variabila, de obicei, ceea ce se întâmplă este aceste 2 numere sunt deja în registre. Și apoi de la acel moment, după ce le-am schimbat, acesta va începe doar cu ajutorul alt registru. Oriunde ai fi fost utilizați b, se va folosi doar registrul care a fost deja stocarea "o". Așa că nu trebuie să facă nimic pentru a face de fapt swap. Da? [Student] Dar este nevoie de mai multă memorie, de asemenea, nu? Acesta va lua doar mai multă memorie în cazul în care are nevoie pentru a stoca că variabila temporară. Ca și în cazul în care utilizați mai târziu că variabila temporară din nou undeva, atunci - sau pe care o atribuiți ceva în acest variabilă temporară. Deci, dacă în orice punct în timp "a," b în temperatură au valori distincte sau ceva, atunci va trebui locații distincte în memorie, dar este adevărat că există multe variabile locale care vor exista numai în registre. În care caz, niciodată nu a pus în memorie, și astfel încât să nu pierzi memoria. Bine. Ultima întrebare este un pic mai mult. Deci, aici, în acest aparat CS50, există un dicționar. Și motivul pentru aceasta este că [? B66?] Este un corector ortografic în cazul în care veți fi scris folosind tabele de dispersie sau încearcă sau unele structuri de date. Ai de gând să fi scris un corector ortografic, și ai de gând să fie folosind acest dictionar pentru a face acest lucru. Dar pentru aceasta problema, ne sunt doar de gând să se uite în sus pentru a vedea dacă este un singur cuvânt în dicționar. Deci, în loc de a stoca întregul dicționarul în unele structuri de date și apoi caută peste un întreg document pentru a vedea dacă ceva e greșit, vrem doar să găsească un cuvânt. Deci, putem scana doar peste dicționarul întregul și dacă nu găsim cuvântul în dicționar intreaga, atunci nu era acolo. Dacă vom scana întregul dicționarul și vedeți cuvântul, atunci suntem bine, l-am găsit. Se spune aici că vrem să începi să cauți la C de fișier de manipulare a funcției, din moment ce doriți să citiți dicționarul, dar eu va dau indiciu aici ca la care funcțiile ar trebui să gândi. Le voi scrie pe spațiile. Deci, cele principale pe care veți dori să se uite la f sunt deschise și apoi, în mod inevitabil, f închis, care va merge la sfârșitul programului dumneavoastră, și scanare f f. Ai putea folosi, de asemenea, f citit, dar probabil că nu doriți să pentru că - nu se termină nevoie de asta. F scanare f este ceea ce ai de gând să fie utilizați pentru a scana peste dicționarul. Și așa nu aveți nevoie pentru a coda sus soluția, la fel ca și încercați pseudo-cod-ți de drum la o soluție, iar apoi vom discuta. Și, de fapt, de când am dat deja astea, daca te duci in orice terminal sau shell aparatul dumneavoastră, Aș - Eu de obicei - în cazul în care nu ați văzut-o încă, nu știu dacă ai făcut-o în clasă, dar omul, astfel încât paginile man, sunt destul de utile pentru uită la destul de mult orice funcție. Deci, eu pot face, ca, f omule, scanare f. Aceasta este acum informatii despre familia f scanare de funcții. Aș putea face, de asemenea, deschise f om, și că va da-mi detalii cu privire la acest lucru. Deci, daca stii ce funcția pe care o utilizați, sau ai citit codul și veți vedea unele funcții și tu ești la fel ca, "Ce face asta?" Doar omul care funcția de nume. Există o serie de exemple de ciudat în cazul în care ar putea să aibă de spus place. Man 2, care numele funcției, sau omul 3 că numele funcției, dar trebuie doar să faci asta în cazul în care numele funcției omul nu se întâmplă să lucreze prima dată. [Student] Deci, eu citesc pagina de manual pentru deschis, dar eu sunt încă confuz cu privire la modul de a folosi și programul. Bine. O mulțime de pagini man sunt la mai puțin de ajutor. Sunt mult mai util dacă știți deja ce fac ei si apoi trebuie doar să ne amintim ordinea argumentelor sau ceva de genul. Sau pot oferi o imagine de ansamblu, dar unele dintre ele sunt foarte copleșitoare. Ca f scanare f, de asemenea. Acesta vă oferă informații pentru toate aceste funcții, și 1 linie de aici se întâmplă să spună, "F scanare f citește din punct de șir sau curs de apa." Dar f deschide. Deci, cum ne-ar folosi f deschis? Ideea unui program de care are nevoie pentru a face fișierul I / O este faptul că trebuie mai întâi să deschideți fișierul pe care doriți să faceți lucrurile cu, și în mod inevitabil, citește lucrurile din acel fișier și de a face lucruri cu ele. F deschisă este ceea ce am folosi pentru a deschide fișierul. Lucru ne întoarcem, deci ce fișierul vrem să deschideți, dă-ne - aici se spune "/ user / share / dict / cuvinte." Acesta este fișierul pe care ne-o dorim pentru a deschide, și vrem să-l deschideți - trebuie să ne precizeze în mod explicit dacă vrem să-l deschidă pentru a citi sau dacă vrem să deschideți-l să scrie. Există o serie de combinatii si alte chestii, dar vrem să deschidă asta pentru lectură. Dorim să citească din fișierul. Deci, ce are acest retur? Returnează un fișier stea (*), și voi arăta totul în variabila f, așa *, din nou, este un pointer, dar nu vrem să se ocupe de pointeri. Vă puteți gândi la f ca, f este acum variabila ai de gând să utilizați pentru a reprezenta fișierul. Deci, dacă doriți să citiți din dosar, ai citit din f. Dacă doriți să închideți fișierul, închideți f. Deci, la sfârșitul programului atunci când, inevitabil, să închideți fișierul, ceea ce ar trebui să facem? Vrem să închideți f. Asa ca acum funcția de ultimul fișier pe care am de gând să doriți să utilizați scanarea este f, f f scanare. Și ce face este scanează peste fișierul în căutarea unui model pentru a se potrivi. Privind la pagina de om de aici, vom vedea int f f scanare, ignora valoarea returnata de acum. Primul argument este * flux de fișier, astfel încât primul argument am de gând să doriți să treacă este f. Suntem de scanare peste f. Al doilea argument este un șir format. Eu va voi da un șir format acum. Cred că se întâmplă să spunem, 127s \ n, o mulțime de care e inutil. Ideea a ceea ce șir format este, vă puteți gândi este de f scanare ca opusul lui f de imprimare. Deci f imprimare, imprimare f vom folosi, de asemenea, acest tip de parametru format, dar în f imprimare ceea ce facem noi este - să ne uităm la un echivalent. Imprima atât de f, și există, de asemenea, de fapt f imprimare f, în cazul în care primul argument va fi f. Când imprimați f, am putea spune ceva de genul, "Print 127s \ n" și apoi, dacă am să-l dați niște șir, se va imprima acest șir și apoi o linie nouă. Ce înseamnă 127, sunt destul de sigur, dar eu nu am am limitat la aceasta, Tu nu ar trebui chiar să spun '127 'în f imprimare, dar ce inseamna este imprimați primele 127 de caractere. Așa că eu sunt destul de sigur că e cazul. Puteți Google pentru asta. Dar, în următorul Sunt aproape sigur, înseamnă că. Deci, aceasta este a imprima prima 127 de caractere, urmate de o linie nouă. F f scanare acum, în loc de a privi la o variabilă și imprimarea acesteia, o să se uite la unele șir, și păstrează tiparul în variabila. Să folosim efectiv f scanare într-un alt exemplu. Deci, haideți să spune că am avut unele int, x = 4, și am vrut să creăm un șir format din - a vrut să creeze string că a fost ca, aceasta va veni mult mai târziu, ceva care e la fel ca 4.jpg. Deci, acest lucru ar putea fi un program in care vei avea contra sumei, concluzie a contracara I, și doriți să salvați o grămadă de imagini. Deci, doriți să salvați i.jpg, unde i este un iterație a buclei dumneavoastră. Deci, cum putem face acest șir pentru că JPEG? Dacă ați fi dorit să imprimați 4.jpg, am putea spune doar f imprimare, d.jpg%, și apoi l-ar imprima pentru JPEG. Dar dacă vrem să salvați 4.jpg șir, vom folosi f scanare. Deci sirul s - de fapt, am Cant - personaj, char s, hai să mergem 100. Așa că am declarat doar câteva matrice de 100 de caractere, și asta e ceea ce ne va fi, inevitabil, stocarea că JPEG inch Deci, vom folosi de scanare f, și formatul, cum ne-ar spune d.jpg% , în scopul de a imprima 4.jpg, formatul de acest lucru se întâmplă pentru a fi d.jpg%. Deci, formatul este d.jpg%, ceea ce vrem să înlocuiască d%, cu este x, și acum avem nevoie pentru a stoca acel șir undeva. Și în cazul în care vom păstra acest șir este în s. matrice. Deci, după această linie de cod, e, dacă vom imprima f, s% din variabila, se va imprima 4.jpg. Deci f scanare f este aceeași ca și scanare f, cu exceptia acum se uită peste acest fișier pentru ceea ce a stoca în s.. Asta e ceea ce ultimul argument va fi. Dorim să stocați - "familia de scanare f de scanări funcții atât în ​​funcție de formatul încercat de mai jos. Dacă sunt stocate în punctele de localizare s-ar putea întoarce - " Nu, am putea fi bine. Lasă-mă să mă gândesc o secundă. Deci, scanare f nu - ce naiba este funcția care face asta? Deci, scanare f nu este de gând să ia un întreg și de a face punct jpg. O să [Mumbles]. Salvați variabila int în șir int C. Ce este această variabilă, sau ceea ce este numit această funcție? Da. Asta e. - da. Deci, ceea ce am fost înainte de definirea să te lui a fost f imprimare, care - care face sens mult mai mult, de ce i-am spus că a fost mult mai mult ca f imprimare. Scanare f este încă un fel de f imprimare, dar f e de imprimare este de gând să-l scanați peste și înlocuiți variabilele, iar acum se păstrează într-un șir. În loc de imprimare-l, îl stochează într-un șir. Deci, ignora faptul că în întregime. Poți să te gândești încă de specificatorul de format ca genul asta de f imprimare. Deci, acum, dacă am vrut să facem lucrul 4.jpg, ne-ar face e f imprimare, x de acest lucru. Deci, ceea ce face scanarea f - ceea ce a fost vînzătorului va fi? [Student] Sunt doar confuz asupra a ceea ce încercăm să facem aici cu JPEG. Poți să explici asta timp 1 mai mult? Deci asta a fost - e relevent mai puțin de scanare f f acum, sperăm, se va lega la spate într-un fel de drum. Dar ceea ce am fost inițial intenția de a demonstra a fost - asta este de fapt direct relevante pentru aceste [?? F5] Ai de gând să fie utilizând e f imprimare, în cazul în care, spunem că avem 100 de imagini, și doriți să citiți imagini 1.jpg, 2.jpg, 3.jpg. Deci, în scopul de a face acest lucru, aveți nevoie pentru a f deschis, iar apoi va trebui să treci în șirul pe care doriți să îl deschideți. Deci, ne-am dori să deschidă 1.jpg, în scopul de a crea șir care este 1.jpg, f facem e de imprimare de% d.jpg--nu ne-am făcut pentru int i = 0. i <40, i + +. Deci, s% f imprimare d.jpg lui i. Deci, după această linie, acum e variabilă sau matrice se va 1.jpg. Sau, 0.jpg, 1.jpg, 2.jpg. Și astfel putem deschide, la rândul său, fiecare imagine pentru citire. Deci, asta este ceea ce e tipărarea f face. Nu vezi ce e tipărarea f face acum? [Student] Ok, deci durează - creează un șir, something.jpg, iar apoi îl stochează. Da. Se creează - aceasta este un alt șir format, la fel ca f scanare și f imprimare, în cazul în care acesta introduce toate variabilele în al doilea argument, ar putea fi s, spre deosebire de i.. Poate - Adică, asta e cazul. Dar oricare ar fi ordinea de argumente este. Se va introduce toate variabilele în șir format și depozitați apoi în tampon noastră, noi numim asta un tampon, e în cazul în care suntem stocarea șir. Deci, suntem în interiorul stocarea e-șir corect formatat, d% au fost înlocuite cu 4. [Student] Deci, dacă am făcut acest lucru, este f variabila doar de gând să fie dați afară? Da. Așa că ar trebui să închidă f inițială înainte de a face acest lucru. Dar - și apoi, de asemenea, în cazul în care nu ar exista un f deschide aici, atunci ne-ar trebui să spunem - Da. Dar ar deschide o sută de fișiere diferite. [Student] Dar noi nu ar fi capabil de a accesa sau - în regulă. Bine. Deci scanare f, f f scanare, este un fel de aceeași idee, dar în loc de, în loc de a stoca o într-un șir, e mai mult ca tine sunt acum trecând peste o intepatura și de model de potrivire împotriva acestei șir și stocarea rezultatelor în variabile. Puteți utiliza f scanare pentru a analiza peste ceva de genul 4.jpg, și păstrează întreg în 4 x int suma. Asta e ceea ce putem folosi f scanare pentru. F f scanare este de gând să faci asta la linia de comandă. Sunt de fapt destul de sigur că asta este ceea ce face biblioteca CS50. Deci, atunci când spui, "get int", e de scanare f-ing peste - f scanare este modul în care obține date introduse de utilizator. F f scanare este de gând să facă același lucru, dar folosind un fișier pentru a scana peste. Deci, aici, suntem scanați peste acest fișier. Model incercam pentru a se potrivi este un șir de caractere care este de 127 de caractere urmată de o linie nouă Așa că eu sunt destul de sigur că am putea chiar spune pur și simplu "meci e", deoarece în dicționarul se întâmplă să avem, suntem garantat nici un cuvânt este atât de mult timp, și, de asemenea, f f scanare, cred, se va opri la noua linie, indiferent de ce. Dar vom include noua linie în meci, și - [Student] Dacă nu am include noua linie, nu l-ar găsi părți ale unui cuvânt? Ea - fiecare - se uită la dicționar - Deci, în dicționar, acestea sunt toate cuvintele noastre. Fiecare unul este pe o linie nouă. F scanare este de gând să ia acest cuvânt. Dacă noi nu includ noua linie, atunci este posibil ca f următoarea scanare va citi doar noua linie. Dar incluzând noua linie, atunci va ignora pur și simplu noua linie. Dar niciodata nu vom ajunge o parte a unui cuvânt, deoarece suntem mereu citesc până la o nouă linie, indiferent de ce. [Student] Dar ce se întâmplă dacă veți căuta pentru cuvântul "cissa," ca cissa. Va găsi că, și spun că este un meci? Deci, aici vom - acesta va citi - aceasta este de fapt un punct bun. Noi nu îl utilizați curent - cuvântul căutăm este prima linie de comandă argumentul. Deci șir, cuvânt = argv 1. Deci, șirul căutăm este argv 1. Noi nu suntem în căutarea pentru un cuvânt, la toate în f scanare noastră. Ce facem cu scanare f este obtinerea fiecare cuvânt în dicționar, și apoi o dată avem acest cuvânt vom folosi strcmp pentru a le compara. Vom compara cuvântul nostru și ceea ce tocmai am citit inch Deci în mod inevitabil, vom ajunge să faci o grămadă de scanare fs până când doar așa se întâmplă că f scanare va reveni - acesta va reveni cu o, atâta timp cât acesta a egalat un cuvânt nou, și se va întoarce altceva, de îndată ce nu a reușit să se potrivească cuvântul. Citim peste tot dicționarul, stocarea linie cu linie fiecare cuvânt în variabila. Apoi, suntem comparativ cu cuvântul lui, și dacă compararea == 0, strcmp se întâmplă pentru a aduce 0 daca un meci a fost facut. Deci, în cazul în care a fost de 0, atunci putem imprima f, potrivit, sau cuvântul este în dicționar, sau orice altceva doriți să imprimați f. Și apoi - nu vrem să închidă f peste si peste din nou. Acesta este genul de lucruri ce vrem să facem, iar noi nu sunt doar în căutarea pentru un cuvânt în dicționar. Deci, am putea face asta, dacă am vrut să se uite pentru modelul lor, cissa, cum ai spus mai înainte, în cazul în care am vrut să se uite pentru acel model, atunci acesta ar eșua în cazul pentru că nu e de fapt un cuvânt, dar unul dintre cuvintele din dicționarul se întâmplă să aibă că în ea. Deci, s-ar potrivi la acest cuvânt, dar acest subgrup de cuvânt nu este un cuvânt în sine. Dar asta nu e modul în care ne-l utilizați, suntem lectură în fiecare cuvânt și compararea apoi cuvântul avem cu acel cuvânt. Deci, suntem mereu comparat cuvinte pline. Eu pot trimite soluții finalizate mai târziu. Aceasta este un fel de aproape răspunsul corect, cred. [Comentariu Student, neinteligibil] Oh, am scăpa de asta înainte? Char s, cred ca am spus 127 - Am uitat ce cea mai mare este. Vom face doar 128, așa că acum e este suficient de lung. Nu avem nevoie de nimic pentru a imprima. Suntem, de asemenea, de gând să doriți să aveți pentru a închide dosarul nostru, și că ar trebui să fie despre raspunsul corect. CS50.TV