DAVID MALAN: Bine, bine ai revenit. Aceasta este CS50. Acesta este începutul de săptămâna de șapte. Asa ca a fost o vreme, așa că am crezut că vom ia un tur vârtej de unde am rămas și unde vom merge acum. Deci, acest lucru aici ar putea avea a provocat unele Angst, la prima. Dar sperăm că, începi să aclimatizeze la ceea ce aceasta denotă aici - stele reprezintă un indicator, care este doar ceea ce, în termeni mai simpli? Deci, este o adresă. Deci, este adresa de ceva în memorie. Și am început să coaja înapoi straturile în urmă cu câteva săptămâni, lucrurile place Getstring și alte astfel de funcții în tot acest timp au fost revenirea adrese de lucruri în memorie, cum ar fi adresa primului caracter din unele secvență. Deci, am introdus, de asemenea, Valgrind, care veți începe să utilizați pentru această problemă stabilit, în special pentru următorul Problema stabilit, de asemenea. Și Valgrind face ceea ce pentru noi? Se verifică de pierderi de memorie, și-l de asemenea, controale pentru abuz de memorie. Se poate, cu o anumită probabilitate, a detecta dacă codul se va atinge de memorie că pur și simplu nu ar trebui. Deci, nu neapărat o scurgere, dar dacă merge dincolo de limitele unor matrice, și a alerga de fapt Valgrind și induce acest comportament în timp ce Valgrind se execută în program este de funcționare în interiorul de ea, veți obține Mesajele de acest gen - "invalid scrie de Dimensiunea 4, "care, amintesc o pereche de acum câteva săptămâni a însemnat că am avut accidental ca pe una int prea departe dincolo de limitele unei matrice. Și astfel dimensiunea 4 înseamnă aici dimensiunea din care Int special. Astfel încât să ia reasigurării în faptul că ieșire Valgrind, format din ea, este pur și simplu atroce. Este foarte greu de a vedea, prin mizerie pentru scurte informatii. Deci, ceea ce am făcut aici este doar fragment o parte din cuplu de mai linii interesante. Dar dau seama că 80% din lui Valgrind ieșire va fi un pic de o distragere a atenției. Uită-te pentru modele, cum ar fi acestea - invalid dreapta, invalid citit, 40 de bytes și un număr de blocuri sunt cu siguranta a pierdut, cuvinte cheie, cum ar fi asta. Și ceea ce veți vedea sperăm este un un fel de urme de ceea ce funcționează greseala este de fapt inch În acest caz aici, în ceea ce linie de codul meu a fost eroare aparent? 26 într-un fișier denumit memory.c, care a fost exemplu ne jucam cu la momentul respectiv. Deci, nu este, probabil, în malloc. Acesta a fost, probabil, în codul meu loc. Deci, vom vedea acest lucru din nou și din nou înainte de lung. Deci scanf, aceasta a venit într-un câteva forme de pana acum. Am văzut scurt sscanf. A fost ceva un număr de vă scufundat în în ta pregătirile pentru test. Și scanf este de fapt ceea ce CS50 Biblioteca a fost cu sub capota de ceva timp pentru pentru a obține de intrare de la utilizator. De exemplu, dacă am trece pe la CS50 aparat de aici, lasă-mă să deschid un exemplu, astăzi, că se numește scanf-0.c Și e foarte simplu. E doar o câteva linii de cod. Dar se demonstrează într-adevăr cum getint a fost de lucru tot acest timp. În acest program de aici, în linia 16 , Observați că am declara o Int. Deci, nici indicii nimic magic, acolo, doar un Int. Apoi, în linia 17, am solicita utilizator pentru un număr, vă rog. Apoi, la sfârșitul anului 18, am folosi scanf aici. Și am precizat, un fel de cum ar fi printf, că mă aștept citat citatul suta eu. Deci sut i, desigur, denotă o Int. Dar observați ce a doua Argumentul a scanf este. Cum ați descrie cea de a doua Argumentul de după virgulă? Ce este asta? Este adresa de x. Deci, acest lucru este util, deoarece prin furnizarea scanf cu adresa x, ceea ce face care permite această funcție pentru a face? Nu doar du-te acolo, dar, de asemenea, face ce? A face o modificare a acestuia. Pentru ca poti sa te duci acolo, e un fel de ca o hartă la o locație în memorie. Și, atâta timp cât vă oferi scanf, sau orice funcție cu o astfel de hartă, care Funcția poate merge acolo, și nu numai uita-te la valoarea, dar poate, de asemenea, schimba această valoare, ceea ce este util în cazul scop în viață de scanf este de a scana de intrare de la utilizator, în mod specific de la tastatură. Și f denotă formatat, la fel ca printf, f denotă o formatat șir pe care doriți să imprimați. Deci, pe scurt, acest 18 linii pur și simplu spune, încercați să citiți un int de utilizare tastatură și păstrați-l în interiorul lui x, la indiferent de adresa x se întâmplă să trăiască. Și apoi în cele din urmă, linia 19 doar spune, mulțumiri pentru Int, în acest caz. Așa că lasă-mă să merg mai departe și să facă acest lucru. Deci, asigurați-scanf 0. Lasă-mă să merg mai departe și zoom inch Voi merge și a alerga acest lucru cu puncte slash scanf 0. Număr, vă rog? 50. Multumesc pentru 50. Deci, este destul de simplu. Acum, ceea ce este ea nu face? Nu face o grămadă de verificarea erorilor. De exemplu, dacă nu cooperează, și eu nu tastați într-un număr, dar în loc să scriu ceva de genul "Bună ziua," că e doar un fel de ciudat. Și astfel unul din lucrurile pe care CS50 biblioteca a făcut pentru noi, pentru unii timp este că reprompting și reprompting. Încercați din nou fraza rechemare a fost în cs50.c, și că este motivul pentru care getint în biblioteca CS50 este de fapt un întreg grămadă de linii lungi, pentru că suntem verificarea pentru prostii de genul asta. Nu utilizatorul da ne, de fapt, un int? Te-el sau ea să ne dea ceva ca o literă din alfabet? Dacă este așa, vrem să detecteze ca si tipa la ei. Dar lucrurile devin mai interesante în acest exemplu următor. Dacă mă duc la scanf-1.c, ceea ce este cel lucru care este schimbat fundamental în acest Următorul exemplu? Sunt folosind char *, desigur, în loc de Int. Deci, acest lucru este interesant, pentru că char *, amintesc, este de fapt doar același lucru ca șir. Deci, se simte ca poate aceasta este o super- punerea în aplicare simplă a getstring. Dar m-am detasat-o inapoi stratul a CS50 bibliotecii, așa că eu sunt solicită acest char * acum. Deci, haideți să vedem unde, dacă oriunde, am greșit. Linia 17 - Eu spun din nou, te rog da-mi ceva, în acest caz, un șir. Și apoi, în următoarea linie, eu numesc scanf, din nou, dându-i un cod format, dar de data aceasta la suta s. Și atunci acest moment, eu sunt dându-tampon. Acum observați, eu nu folosesc ampersand. Dar de ce este că, probabil, bine aici? Pentru că ceea ce este deja tampon? Este deja un pointer. Este deja o adresă. Și să-i acest cuvânt "confunda," lasă-mă să doar e apel, de exemplu, pentru simplitate. Dar am numit-tampon pentru că în general, în programarea, în cazul în care aveți un bucată de memorie, care într-adevăr un șir la fel este, s-ar putea numi un tampon. Este un loc pentru a stoca informații. Similar cu lucruri, cum ar fi YouTube, atunci când ei tampon, ca să spunem așa, că înseamnă doar se descarcă biți de la internet și stocarea acestora într-un matrice locale, o bucată locale de memorie, astfel încât pe care îl puteți viziona mai târziu, fără a ea sărind peste sau agățat pe te în timpul redării. Deci, există o problemă aici, deși, pentru că eu spun scanf, se așteaptă o șir de la utilizator. Uite adresa de o bucată de memorie. Pune șir acolo. De ce este că legat da noi probleme, deși? Ce-i asta? Am voie să acceseze acea parte a memoriei? Știi, eu nu știu. Pentru că a fost inițializat tampon a ceva? Nu chiar. Și așa este ceea ce am fost sunat o valoare gunoi, care nu este un cuvânt oficial. Înseamnă doar că nu au nici o idee ce biți sunt în interiorul celor patru octeți care Am alocat ca tampon. Nu am sunat malloc. Am siguranta nu numit getstring. Deci, cine știe ce este de fapt interiorul tampon? Și totuși, spune scanf orbește, du-te acolo și pune orice utilizator tastat. Deci, ceea ce este de natură să cauzeze în codul nostru, dacă vom rula? Probabil o segfault. Poate că nu, dar, probabil, o segfault. Și eu spun poate nu pentru că, uneori, ai face, câteodată nu ai o segfault. Uneori, veți obține doar norocos, dar este, totuși, va fi un bug în programul nostru. Așa că lasă-mă să merg mai departe și compila acest lucru. Am de gând să-l calea scoala veche face. Deci bord zăngănit 0, scanf-1, scanf-1.c, Enter. Hopa, scoala prea vechi. Să vedem. Unde am? Oh, buffer char *. Oh, vă mulțumesc - Salvare, bine - scoala foarte veche. Bine, a trecut ceva timp. Deci, tocmai am salvat fișierul, după face ca temporar schimba acum o clipă. Și acum l-am compilat manual cu zăngănit. Și acum am de gând să merg mai departe și a alerga scanf-1, Enter. Șir te rog. Voi scrie în "Bună ziua." Și acum, aici, unde, sincer, printf poate este un pic enervant. Nu se intampla de fapt la segfault în acest caz. Printf este un pic mai special, deoarece E atât de foarte frecvent utilizate, care în esență printf face ne o favoare și dea seama, că nu este un pointer valid. Lasă-mă să-l iau la mine doar să imprime în paranteze nul, chiar desi nu este neaparat ceea ce ne-am așteptat. Deci nu putem induce într-adevăr cu ușurință o segfault cu acest lucru, dar în mod clar acest lucru nu este comportamentul mi-am dorit. Deci, ce este soluția simplă? Ei bine, în scanf-2, permiteți-mi să propun ca în loc de fapt, doar o alocare char *, permiteți-mi să fie un pic mai inteligent despre acest lucru, și lasă-mă să aloce tampon ca o secvență de 16 de caractere. Deci, eu pot face acest lucru într-o serie de moduri. Aș putea folosi absolut malloc. Dar eu pot să mă întorc la doua saptamani când Am nevoie de o grămadă de caractere. Asta e doar un tablou. Deci, lasă-mă în loc redefini tampon să fie o matrice de 16 de caractere. Și acum, când trec tampon din - și acest lucru este ceva ce nu am vorbesc despre in doua saptamani - dar se pot trata o gamă cât deși este o adresă. Punct de vedere tehnic, așa cum am văzut, sunt un pic diferit. Dar scanf nu se va supăra dacă îl trece numele unui tablou, pentru că ceea ce Clang va face pentru noi este, în esență trata numele care matrice ca Adresa de bucată de 16 bytes. Deci, acest lucru este mai bine. Acest lucru înseamnă că acum pot să sperăm procedați în felul următor. Lasă-mă să zoom out pentru o clipă și nu face scanf-2, compilate OK. Acum, lasă-mă să-avem slash scanf-2. Șir te rog. "Bună ziua." Și-l părea să lucreze acest timp. Dar poate cineva propune un scenariu în care s-ar putea să nu funcționeze în continuare? Da? Ceva mai mult de 16 caractere. Și, de fapt, putem fi un pic mai precis. Ceva mai apoi 15 de caractere, pentru că într-adevăr avem nevoie pentru a păstra în minte că avem nevoie de backslash la zero implicit, la sfârșitul șirului, care este o parte scanf va fi de obicei avea grijă de de noi. Deci, lasă-mă să fac ceva de genul - Uneori putem doar lăsați-l așa. OK, deci ne-am indus acum vina noastră segmentare. De ce? Pentru că am scris la mai mult de 15 caractere, și așa ne-am de fapt, memorie mișcată de faptul că de fapt nu ar trebui să aibă. Deci, ceea ce este într-adevăr soluția aici? Ei bine, dacă am nevoie de un șir mai lung? Ei bine, ne poate face 32 de biți. Ei bine, ceea ce în cazul în care nu este suficient de lung? Cum aproximativ 64 biti? Ce se întâmplă dacă asta nu e suficient de lung? Cum de aproximativ 128 sau 200 de biți? Ceea ce este într-adevăr soluția aici, în cazul general, dacă nu știm în avansa ceea ce utilizatorul va tip? E doar un fel de o mare durere în fund, să fiu sincer, care este motivul pentru care CS50 biblioteca are câteva zeci de linii de cod care pun în aplicare colectiv Getstring șir într-un mod pe care noi nu Trebuie să știe în avans ce Utilizatorul este de gând să tastați. În special, dacă te uiți înapoi la cs50.c din urmă cu două săptămâni, veți vedea care getstring de fapt nu Nu folosi scanf în acest fel. Mai degrabă, se citește un caracter la un moment dat. Pentru ca un lucru frumos despre citind un caracter este putem garanta noi înșine pentru totdeauna să aibă cel puțin un char. Eu pot declara doar un caracter, și apoi să ia acești pași cu adevărat copilul la doar citit un caracter de la un timp de la tastatură. Și apoi, ce veți vedea getstring nu este de fiecare dată când rămâne fără, să zicem, 16 de bytes de memorie, se foloseste malloc, sau de un văr, la aloca mai multă memorie, copierea vechi de memorie în noi, și apoi crawling de-a lungul, obtinerea de un caracter la un moment dat, și atunci când se execută din care bucată de memorie, se aruncă departe, graifere o bucată mai mare de memorie, copii vechi în noi, și repetă. Și este cu adevărat o durere de fapt, implementeze ceva la fel de simplu ca obținerea de intrare de la un utilizator. Astfel, puteți folosi scanf. Puteți utiliza alte funcții similare. Și o mulțime de manuale și on-line exemple fac, dar sunt toate vulnerabile la probleme de acest gen. Și în cele din urmă, obtinerea unui segfault este un fel de enervant. Nu e bine pentru utilizator. Dar, în cel mai rău caz, ceea ce face se pune fundamental ta Codul risc de? Un fel de atac, potențial. Am vorbit despre un astfel de atac - debordant stiva. Dar, în general, dacă ai voie să overflow un tampon, asa cum am facut-o câteva săptămâni în urmă, cu doar scris mai mult de "salut" pe stiva, vă poate lua într-adevăr peste, eventual, o calculator, sau cel puțin a ajunge la datele care nu-ți aparține. Deci, pe scurt, acesta este motivul pentru care ne-am aceste roți de formare. Dar acum, vom începe să le ia off, ca programele noastre nu mai au nevoie, în mod necesar, de intrare de la utilizator. Dar în cazul problemei stabilit șase, intrare dvs. va veni de la un imens fișierul dicționar cu 150 unele ciudat mie de cuvinte. Deci, nu va trebui să vă faceți griji cu privire la intrare arbitrar utilizatorului. Noi vă va oferi câteva ipoteze despre acel fișier. Orice întrebări cu privire la indicii sau scanf sau datele introduse de utilizator, în general? Bine, deci o privire rapidă, apoi la o trailing subiect de acum două săptămâni. Și că a fost această noțiune a unei structuri. Nu că - această noțiune de o struct, care a fost ce? Ce a făcut struct pentru noi? Definirea - Îmi pare rău? Defini un tip de variabilă. Deci, un fel de. Suntem combinarea de fapt două subiecte. Deci, cu typedef, amintim că putem declara un tip de propria noastră, ca un sinonim, ca șir de char *. Dar folosind typedef struct si, putem crea cu adevărat propriile noastre structuri de date. De exemplu, dacă mă duc înapoi în gedit aici doar pentru o clipă, și am merge mai departe și de a face ceva de genul, lasă-mă să salveze acest drept, să spunem, structs.c temporar, Mă duc pentru a merge mai departe și să includă standardio.h, void main Int. Și apoi aici, presupunem că vreau pentru a scrie un program care stochează mai multor studenți de la mai multe case, de exemplu. Deci, e ca o registrarial Baza de date de un anumit fel. Deci, dacă am nevoie de numele unui student, am s-ar putea face ceva de genul char nume *, și voi face ceva de genul - De fapt, hai să folosim CS50 biblioteca pentru doar un moment pentru a face acest lucru o mai simplu, astfel încât să putem împrumuta acele zeci de linii de cod. Și hai să păstrați-l simplu. Vom ține-l string, și acum getstring. Deci, eu pretind că le-am stocat numele a unor student, și casa de un elev, pur și simplu, folosind variabile așa cum am făcut și în prima săptămână. Dar să presupunem că acum vreau să sprijin mai multor elevi. În regulă, deci instinctele mele sunt de a face șir name2, se getstring, string house2 devine getstring. Și apoi al treilea elev nostru, hai sa facem NAME3 getstring. Bine, deci acest lucru este, sperăm, frapant tine, ca un fel de stupid, deoarece acest proces este într-adevăr niciodată va sfârși, și este doar de gând să face codul meu arata mai rau și mai rău și mai rău. Dar am rezolvat această prea in doua saptamani. Care a fost soluția noastră relativ curat când am avut mai multe variabile ale același tip de date, care sunt toate legate, dar nu am dorit această mizerie atroce de variabile denumite similar? Ce am făcut în schimb? Deci, cred că am auzit câteva locuri. Am avut o matrice. Dacă doriți mai multe instanțe de ceva, de ce nu ne curata totul și să spun, da-mi array numit nume? Și de acum, sa greu 3 cod. Și apoi dă-mi o matrice numite case, și lasă-mă pentru acum codul greu 3. Și am masiv curățat mizeria pe care am creat. Acum, eu am încă greu codificate 3, dar chiar 3 ar putea proveni de la dinamic utilizator, sau argv, sau cum ar fi. Deci, acest lucru este deja curat. Dar ceea ce e enervant despre acest lucru este faptul că acum, chiar dacă un nume este oarecum legat în mod fundamental casa unui student - este un elev care mi- Vreau să reprezinte - Am acum două tablouri care sunt paralele în sensul că acestea sunt aceeași dimensiune, și nume de suport 0 probabil și hărți la case suport 0, și numele suport 1 hărți la case suport 1. Cu alte cuvinte, că studenților trăiește în casa, iar celălalt elev trăiește în care alte casă. Dar cu siguranță acest lucru ar putea fi făcut chiar mai curat. Ei bine, se poate, de fapt. Și lasă-mă să merg mai departe și deschide sus structs.h, și veți vedea această idee aici. Observați că am folosit typedef, după cum a făcut aluzie la un moment în urmă să declare nostru tip de date proprie. Dar eu sunt, de asemenea, folosind acest alt cuvânt cheie numit struct care îmi dă un nou structură de date. Și această structură de date am pretinde se întâmplă să aibă două lucruri interiorul ea - un șir numit nume, și un șir numit casă. Și numele am de gând să dea la această structură de date se va să fie numit elev. Am putea spune orice vreau, dar acest lucru face semantic sens pentru mine în mintea mea. Deci, acum, dacă am deschide o versiune mai bună a programului am început să scriu acolo, lasă-mă să derulați în partea de sus. Și există ceva mai multe linii de cod aici, dar permiteți-mi să se concentreze pentru momentul pe una. Am declarat-o constanta numita studenți și greu codificate 3 pentru acum. Dar acum, observa cât de curată codul meu începe să se. În linia 22, declar serie de studenți. Și observă că elevul este aparent acum un tip de date. Pentru că în partea de sus a acestui fișier, observa Am inclus acest fișier header că am tras în urmă doar o clipă. Și că fișierul header pur și simplu au avut această definiție a unui student. Deci, acum, am creat propriile mele date personalizate Tipul care autorii de ani C Acum nu cred că a în prealabil. Dar nici o problema. Pot face eu. Deci, acesta este un tablou numit studenți, fiecare dintre membrii căror este o structură elev. Și vreau trei din cei în matrice. Și acum, ceea ce face restul din acest program nu? Am nevoie de ceva un pic arbitrar. Deci, de la on-line 24 incoace, Am itera la 0 la 3. Apoi m-am cere utilizatorului pentru Numele elevului. Și apoi am folosi getstring ca înainte. Apoi m-am cere pentru casa elevului, și am folosi getstring ca înainte. Dar observați - ușor nou bucata de sintaxă - Pot încă indicele de student i-lea, dar nu stiu cum sa la date specifice câmp interiorul struct? Ei bine, ceea ce este aparent noua piesa de sintaxă? E doar operatorul punct. Nu ne-am văzut cu adevărat acest lucru înainte. Ai văzut-o în PSET cinci, dacă ați scufundat în deja cu fișiere bitmap. Dar dot înseamnă doar în interiorul acestui struct sau mai multe domenii, dau puncte nume, sau da-mi dot casa. Asta înseamnă că merge în interiorul a struct și de a lua aceste domenii specifice. Ce face restul acestui program nu? Nu e tot ce sexy. Observa că am repeta la 0 la 3, din nou, și pur și simplu am crea un englez frază ca așa și așa este în astfel de și o astfel de casă, trecând în numele punct de student i-lea și lor casa, de asemenea. Și apoi în cele din urmă, acum vom începe să se anal despre acest lucru, acum că suntem familiarizat cu ceea ce malloc și alte funcții au fost a face tot acest timp. De ce trebuie să elibereze ambele nume și casă, chiar dacă am Nu a sunat malloc? Getstring făcut. Și că a fost secret murdar mic pentru de mai multe săptămâni, dar are getString a fost scurgeri de memorie de peste tot loc tot semestrul până acum. Și, în cele din urmă va valgrand dezvăluie acest lucru pentru noi. Dar nu e mare lucru, pentru că știu care pot elibera pur și simplu numele și casa, deși punct de vedere tehnic, pentru a fie super-super-în condiții de siguranță,, eu ar trebui să fie face niste verificari de erori aici. Care sunt instinctele tale îți spun? Ce ar trebui să fie de verificare pentru înainte de a elibera ceea ce este un șir, alias care un char *? Eu ar trebui să fie într-adevăr verifica dacă elevii suport eu dot nume nu egal nul. Atunci va fi OK pentru a merge mai departe și gratuit că indicatorul, și același sau alt una la fel de bine. Dacă elevii suport i dot casa nu este egal cu zero, acest lucru acum va proteja împotriva caz colț în care Getstring întoarce ceva de genul null. Și am văzut acum o clipă, printf va ne protejeze aici de doar spunând null, care este de gând să se uite ciudat. Dar cel puțin nu va segfault, după cum am văzut. Ei bine, lasă-mă să fac un lucru aici. structs-0 este un fel de program de prost pentru că introduce toate aceste date, și apoi ea a pierdut o dată programul se termină. Dar lasă-mă să merg mai departe și de a face acest lucru. Permiteți-mi să fac terminalul Fereastra un pic mai mare. Permiteți-mi să fac structs-1, care este o versiune nouă a acestui. Voi mări un pic. Și acum lasă-mă să ruleze punct slash structs-1. Numele elevului - David Mather, hai sa facem Rob Kirkland, Să facem Lauren Leverett. Ceea ce este interesant este acum preaviz - și știu că doar acest lucru, deoarece Am scris programul - există un fișier acum pe actualul meu director numit students.csv. Unii dintre voi s-ar putea fi văzut acestea, în lumea reală. Ce este un fișier CSV? Valori separate prin virgulă. E ca un fel de om sărac versiune a unui fișier Excel. Este un tabel de rânduri și coloane care puteți deschide într-un program cum ar fi Excel, sau numere pe un Mac. Și dacă am deschis acest fișier aici pe gedit, notificare - și numerele nu sunt acolo. Asta e doar gedit spune mi numerele de linie. Observați pe prima linie a acestei fișier este David și Mather. Următoarea linie este Rob virgulă Kirkland. Și a treia linie este Lauren virgulă Leverett. Deci, ceea ce am creat? Am scris acum un program C care în mod eficient poate genera foi de calcul care poate fi deschis într-o Programul cum ar fi Excel. Nu tot ce convingatoare un set de date, dar dacă aveți bucăți mai mari de Datele pe care le doresc de fapt să manipula și de a face grafice de și ca, aceasta este, probabil, unul mod de a crea acele date. Mai mult decât atât, CSVs sunt de fapt foarte frecvente doar pentru stocarea de date simple - Yahoo Finance, de pildă, dacă te cotații bursiere, prin intermediul lor așa-numitele API, serviciu gratuit care vă permite să obține curent stoc până-la-data- oferte pentru companii, ele da datele înapoi la format CSV simplu super-. Deci, cum facem asta? Ei bine observa, cele mai multe din acest program aproape aceeași. Dar observa aici, mai degrabă decât de imprimare studenții tunel, pe linia 35 mai departe, eu pretind că eu sunt de economisire studenți la disc, astfel încât salvarea unui fișier. Deci, observăm am declara un fișier * - Acum, acest lucru este un fel de o anomalie în C. Indiferent de motiv, fișierul este cu majuscule, care nu este ca cele mai multe alte tipuri de date în C. Dar aceasta este un built-in tip de date, FILE *. Iar eu declara un pointer la un fișier, este modul în care vă puteți gândi la asta. fopen înseamnă dosar deschis. Ce fisier vrei să deschizi? Vreau să deschid un fișier pe care voi apela arbitrar students.csv. Am putea spune că tot ce vreau. Și apoi să ia o presupunere. Ce face al doilea argument la, probabil, fopen înseamnă? Dreapta, W pentru a scrie, ar putea fie R pentru citire. Există o pentru adăugare, dacă Vreau să adăugați rânduri și nu suprascrie totul. Dar eu vreau doar pentru a crea acest fișier dată, așa că voi folosi citat încheiat citatul w. Și știu că doar de a fi citit documentația sau pagina de manual. Dacă fișierul nu este nul - cu alte cuvinte, în cazul în care nimic nu a mers bine acolo - permiteți-mi repeta peste studenți la 0 la 3. Si acum observa ceva vreodată atât de ușor diferite despre linia 41 aici. Nu e printf. Este fprintf pentru fișier printf. Deci, se va scrie la dosar. Care dosar? Cel al cărui indicator să specificați ca prim argument. Apoi, vom specifica un șir format. Apoi vom specifica ce string vrem să conectați pentru prima s procente, iar apoi o altă variabilă sau doilea s procente. Apoi ne-am închide fișierul cu fclose. Decât am elibera memorie ca înainte, deși Ar trebui să mă întorc și să adăugați unele verificări pentru nul. Și asta e tot. fopen, fprintf, fclose îmi dă abilitatea de a crea fișiere text. Acum, veți vedea în setul problema cinci, care implică imagini, veți fi utilizați fișierele binare în schimb. Dar fundamental, ideea este aceeași, chiar dacă funcțiile Veți vezi sunt un pic diferit. Deci tur vârtej de vânt, dar va primi mult prea familiarizat cu dosarul I/O-- de intrare și ieșire - cu PSET cinci. Și orice întrebări cu privire la Noțiuni de bază inițiale aici? Da? Ce se întâmplă dacă încercați să elibereze o valoare nulă? Eu cred că, dacă nu gratuit a devenit o ceva mai user-friendly, puteți potențial segfault. Trecându-l null este rău pentru că eu nu fac cred liber deranjeaza pentru a verifica pentru tine, deoarece ar reprezenta un deșeu de timp pentru ca aceasta să se facă pentru toată lumea din lume. Bună întrebare, totuși. Bine, deci acest tip de se ne la un subiect interesant. Tema de set de probleme a cinci este criminalistica. Cel puțin asta este o parte setului problemei. Criminalistica, în general, se referă la recuperarea de informații, care pot sau să nu fi fost șters în mod deliberat. Și așa m-am gândit să vă dau un rapid gust de ceea ce se întâmplă cu adevărat pe toate acest timp sub capota a computerului. De exemplu, dacă aveți în interiorul dvs. laptopul sau computerul desktop o hard disk, este fie un mecanic dispozitiv care se învârte de fapt - există lucruri circulare numite platane care arata destul place ce a avut doar pe ecran aici, deși acesta este din ce în ce școală veche. Aceasta este o perioadă de trei-si-un-jumatate de inch hard disk. Și trei ani și jumătate centimetri se referă de cu de lucru atunci când îl instalați într-un calculator. Multi dintre voi în laptop-uri acum au drive-uri solid-state, sau SSD-uri, care nu au părți în mișcare. Sunt mai mult ca RAM și mai puțin ca aceste dispozitive mecanice. Dar ideile sunt în continuare la fel, cu siguranță, în care se referă la problema de cinci seturi. Și dacă te gândești acum un hard-disk reprezintă fiind un cerc, care Voi trage ca asta aici. Când creați un fișier de pe computer, indiferent dacă este un SSD, sau în acest caz, un hard disk școală mai vechi, că dosarul cuprinde mai multe biți. Să spunem că e 0 și 1, o grămadă de 0 si 1. Deci, asta este tot meu disc tare. Acest lucru este aparent un fișier destul de mare. Și se folosește la 0 si 1, la care porțiune de platou fizice. Ei bine, ceea ce este acea parte fizica? Ei bine, se pare ca pe un hard-disk, Cel de acest tip, la, există aceste minuscule particule magnetice. Și ei au, în esență nord și poli de Sud pentru a le, astfel încât, dacă rândul său, unul dintre aceste particule magnetice în acest fel, s-ar putea spune că e reprezentând un 1. Și dacă e cu susul în jos spre sud pentru a nord, s-ar putea spune că e reprezentând un 0. Deci, în lumea fizică reală, care e cum ar putea reprezenta ceva în starea binar de 0 și 1. Deci, asta e tot un fișier este. Există o grămadă de magnetic Particulele care sunt lor acest fel sau În acest fel, modele crearea de 0 si 1. Dar se pare că atunci când salvați un fișier, unele informații este salvat separat. Deci, aceasta este o măsuță, un director, ca să spunem așa. Și eu numesc acest nume coloană, și Voi suna această locație coloană. Și am de gând să spun, să presupunem aceasta este CV-ul meu. Resume.doc mea este depozitat la locație, să spunem 123. Mă duc mereu la acel număr. Dar este suficient să spunem că la fel ca în RAM, puteți lua un hard disk că e un gigabyte sau 200 GB sau un terabyte, și puteți Numărul tuturor bytes. Aveți posibilitatea să numerotați toate bucati de 8 biți. Deci, vom spune că această este locația 123. Deci, acest director interiorul operare mele Sistemul amintește că meu CV-ul este în locația 123. Dar devine interesant atunci când ștergeți un fișier. Deci, de exemplu - și din fericire, cea mai mare din lume are prins pe acest lucru - ceea ce se întâmplă atunci când vă trageți un fișier pentru Mac OS gunoi sau dvs. de Recycle Bin pentru Windows? Care este scopul de a face asta? Este evident, pentru a scăpa de dosar, dar ceea ce face actul de glisare și scăzând în Coșul de gunoi dvs. sau Recycle Bin face pe un calculator? Absolut nimic, într-adevăr. Este la fel ca un folder. Este un folder special, pentru a fi sigur. Dar nu-l șterge de fapt dosarul? Ei bine, nu, pentru că unii dintre voi probabil au fost ca, oh la naiba, nu ai făcut- vrut să fac asta. Deci, dublu clic pe Gunoi sau Recycle Bin. Te-ai băgat nasul și le-ați recuperat fișierul pe care tocmai prin tragere de acolo. Deci, în mod clar, nu este neapărat ștergere. OK, tu ești mai deștept decât atât. Știi că doar trăgând în Gunoi sau Recycle Bin nu înseamnă te golirea coșul de gunoi. Deci, te duci până la meniul, iar tu spui Empty Trash sau Empty Recycle Bin. Atunci ce se întâmplă? Da, așa că este șters mai mult. Dar tot ce se întâmplă este aceasta. Calculator uită unde resume.doc a fost. Dar ceea ce nu sa schimbat, aparent, în imagine? Biți, 0 si 1 pe care le pretind sunt pe site-ul de un aspect fizic de hardware-ul. Ei sunt încă acolo. E doar computerul are uitat ceea ce sunt. Deci, este eliberat, în esență, dosarul de biți, astfel încât acestea pot fi refolosite. Dar nu până când veți crea mai multe fișiere, și mai multe fișiere, și mai multe fișiere va probabilistic, cei 0 si 1, aceste particule magnetice, se reutilizate, partea susul sau dreapta sus, pentru alte fișiere, 0 si 1. Deci, aveți această fereastră de timp. Și nu e de previzibil lungime, într-adevăr. Aceasta depinde de dimensiunea hard dvs. unitate și cât de multe fișiere ai și cât de repede voi face altele noi. Dar există această fereastră de timp în care acest dosar este încă perfect recuperabile. Deci, dacă utilizați vreodată de programe, cum ar fi McAfee sau Norton pentru a încerca să recupereze de date, tot ce faci este încercarea de a recupera această așa-numita director de dau seama unde fișierul a fost. Și uneori Norton și va spune, fișier este de 93% recuperabil. Ei bine, ce înseamnă asta? Asta înseamnă că un alt fișier coincidență ajuns cu, să zicem, aceste biți afara de fișier original. Deci, ceea ce este de fapt implicat în recuperarea de date? Ei bine, dacă nu ai ceva de genul Norton pre-instalat pe computer, tot ce se poate face, uneori, este să privim la întreaga unitate de disc în căutarea tipare de biți. Și una dintre temele de set de probleme cinci este că vă va căuta echivalentul a un hard disk, un medico-legale Imaginea unui card Compact Flash de la un aparat de fotografiat digital, căutarea 0s și 1s ca de obicei, cu mare probabilitate, reprezintă începe cu o imagine JPEG. Și voi puteți recupera acele imagini de presupunând că, dacă am vedea acest model de biți pe imagine medico-legale, cu probabilitate mare, care marchează începutul unei JPEG. Și dacă văd același model nou, care, probabil, marchează începutul o altă JPEG, și un alt JPEG, și un alt JPEG. Și acest lucru este de obicei cum de recuperare de date va funcționa. Ce e frumos despre JPEG este chiar dacă formatul de fișier în sine este oarecum complexe, la începutul fiecărui astfel de fisier este de fapt destul de identificat și simplu, după cum veți vedea, Dacă nu ai deja. Deci, haideți să aruncăm o privire mai atentă sub capota cu privire la exact ceea ce a fost întâmplă, și ceea ce aceștia 0 si 1 sunt, pentru a vă oferi un pic mai mult de un Contextul pentru această provocare specială. [Redare video] -În cazul în care PC-ul stochează mai a datelor sale permanente. Pentru a face acest lucru, datele circula de la RAM împreună cu semnale de software care spun hard disk cum a stoca aceste date. Circuitele de hard disk traduce aceste semnale în tensiune fluctuații. Acestea, la rândul lor, de control al unității greu părți în mișcare, unele din puținele piesele mobile rămase în computer modern. Unele dintre semnalele controla un motor care se învârte platane de metal-filmate. Datele sunt stocate de fapt pe aceste platane. Alte semnale de a muta citire / scriere capete pentru a citi sau scrie date pe platane. Acest utilaje atât de precis ca un om parul nu a putut trece chiar între capete și platane filare. Cu toate acestea, totul funcționează la viteze teribil. [END redare video] DAVID MALAN: Zoom într-o mică mai acum la ceea ce este de fapt, pe aceste platane. [Redare video] -Să ne uităm la ceea ce tocmai am văzut în slow motion. Când un scurt impuls de energie electrică este trimis la citire / scriere cap, în cazul în care răstoarnă pe o electromagnetice mic pentru o fracțiune de secundă. Magnet creează un câmp, care schimbă polaritatea un mic, mic porțiune din particulele de metal care strat fiecare suprafață platou. O serie de tipar aceste mici, acuzat-up zone de pe disc reprezintă un singur bit de date în numărul binar Sistemul utilizat de computere. Acum, dacă curentul este trimis într-un fel prin scriere / citire cap, zona este polarizată într-o singură direcție. Dacă curentul este trimis în direcția opusă, polarizare este inversat. Cum să obțineți date de pe hard disk? Doar inversa procesul. Deci e particulele de pe disc care obține curent în citire / scriere cap de mișcare. Pune împreună milioane de astfel de segmente magnetizate, și ai un fișier. Acum, piesele de un singur fișier poate fi împrăștiate pe o unitate de toate platane, un fel de mizerie de hârtii de pe birou. Deci, un fișier suplimentar special ține evidența de unde totul este. Nu ai vrea să ai ceva de genul asta? [END redare video] DAVID MALAN: OK, nu probabil. Deci, câți dintre voi a crescut cu astea? OK, deci e mai puțini mâinile în fiecare an. Dar mă bucur că ești cel puțin familiar cu ei, pentru că aceasta și propria noastră carte demo, din păcate, sunt pe moarte o foarte încetini moartea aici de familiaritate. Dar asta este ceea ce eu, cel puțin, înapoi în liceu, utilizarea folosit pentru backup-uri. Și a fost uimitor, pentru că ar putea stoca 1,4 megaocteți pe Acest disc. Și aceasta a fost versiunea de înaltă densitate, așa cum este indicat de către HD, care are adică înainte de clipuri video de astăzi HD. Densitate standard a fost de 800 kilobytes. Și înainte de asta, au existat Discuri 400-kilobyte. Și înainte de aceasta, au existat 5 și 1/4 discuri inch, care au fost cu adevărat floppy, și un pic mai lat si mai inalt de aceste lucruri aici. Dar puteți vedea de fapt, așa-numitul aspect floppy din aceste discuri. Și funcțional, de fapt ele sunt destul de similar cu hard disk-uri de la Cel acest tip. Din nou, SSD-urile în calculatoare noi de lucru un pic diferit. Dar, dacă vă deplasați că fila de metal mic, puteți vedea de fapt, un pic de cookie, sau platou. Nu e de metal ca aceasta. Asta e de fapt ceva mai ieftin material plastic. Și puteți fel de wiggle ea. Și ai trully doar șters unele numărul de biți sau particule magnetice din acest disc. Deci, din fericire, nu e nimic pe ea. În cazul în care lucru este în mod - și acoperi ochii și cele ale aproapelui tău - puteți doar un fel de tragere acest tot de pe teaca de genul asta. Dar există un pic de primăvară, așa să fie conștient de faptul că, cu ochii tăi. Deci, acum ai cu adevărat o dischetă. Si ceea ce este remarcabil despre acest este că în măsura în care acest lucru este un reprezentare la scară mică de o mai mare hard disk, aceste lucruri sunt foarte, super-simplu. Dacă vă prindeți în partea de jos a acestuia, acum că chestia aia de metal e oprit, și coaja le deschide, tot ce este este de două bucăți de simțit și așa-numitul dischetă cu o bucată de metal pe interior. Și acolo se duce jumătate din Conținutul disc meu. Nu trece o jumătate de ele. Dar asta e tot ce a fost filare în interiorul a computerului în odinioară. Și din nou, pentru a pune acest lucru în perspectivă, cât de mare este de cele mai multe dvs. hard disk-uri in aceste zile? 500 GB, un terabyte, poate în un computer desktop, 2 terabytes, 3 terabytes, 4 terabytes, nu? Acesta este un megabyte, da sau de a lua, care nu pot potrivi chiar un MP3 tipic anymore aceste zile, sau unele fișier de muzică similară. Deci, un mic suvenir pentru tine azi, și De asemenea, pentru a ajuta contextualiza ceea ce vom fi luați de la sine acum în problema stabilit cinci. Deci, acestea sunt a ta de a păstra. Deci, lasă-mă să tranziția la care va fi cheltuielile PSET următoare, de asemenea. Deci, ne-am stabilit acum aceasta pagina pentru - Oh, o pereche de anunțuri rapid. Acest vineri, în cazul în care doriți alătura CS50 pentru masa de prânz, du-te la locul obișnuit, cs50.net/rsvp. Și proiectul final - astfel încât pe programa, am postat caietul de sarcini finală a proiectului deja. Dau seama că asta nu înseamnă că este din cauza deosebit de curând. Este scris, într-adevăr, doar pentru a obține voi mă gândesc la asta. Și într-adevăr, un important super- procentul va fi abordarea Proiectele finale privind materialele pe care le chiar nu au ajuns la clasă, dar va cat mai devreme saptamana viitoare. Observati, totusi, ca spec. cere câteva componente diferite ale proiectul final. Primul, în câteva săptămâni, este un pre-propunere, un e-mail destul de casual la TF dumneavoastră să-i spui sau ce esti gândit de proiect, cu nici un angajament. Propunerea va fi deosebit dvs. angajament, spunând, aici, aceasta este ceea ce Aș vrea să fac pentru proiectul meu. Ce crezi? Prea mare? Prea mic? Este ușor de gestionat? Și veți vedea spec. pentru mai multe detalii. Câteva săptămâni, după care este statutul Raportul, care este un fel de e-mail casual la TF pentru a spune cât de în urmă sunteți în finala implementarea proiectului, urmat de CS50 Hackathon la care toată lumea Este invitat, care va fi un eveniment de 20:00 pe de o seara pana 07:00 AM în dimineața următoare. Pizza, așa cum poate am menționat în săptămână la zero, Wil fi servit la 09:00, Mancarea chinezeasca la 01:00. Și dacă sunteți încă treaz la 5:00, am să te duc la IHOP pentru micul dejun. Deci Hackathon este unul dintre mai experiențe memorabile din clasa. Apoi punerea în aplicare este datorată, și atunci culminant CS50 Fair. Mai multe detalii despre toate acestea în următoarele săptămâni. Dar să ne întoarcem la ceva scoala veche - din nou, o matrice. Deci, o matrice a fost frumos, pentru că rezolvă probleme cum ar fi am văzut doar o Momentul în urmă cu structurile studențești a obține un pic de sub control, dacă ne doresc să aibă un elev, student doi, elev trei, student dot dot dot, un numar arbitrar de studenți. Deci, tablouri, în urmă cu câteva săptămâni, năpustit în și rezolvat toate problemele noastre de a nu cunoașterea în avans cât de multe lucruri de un anumit tip ne-ar putea dori. Și am văzut că structs ne poate ajuta organiza în continuare codul nostru și să păstreze variabile conceptual similare, cum ar fi o nume și o casă, împreună, astfel încât să putem le poate trata ca o singură entitate, în interiorul din care există bucăți mai mici. Dar tablouri au unele dezavantaje. Care sunt unele dintre dezavantajele ne-am întâlnit cu matrice până acum? Ce-i asta? Dimensiune fixă ​​- Deci, chiar dacă s-ar putea putea aloca memorie pentru o matrice, odată ce știi câți studenți aveți, câte caractere ai de utilizator, odată ce ați alocat matrice, ai un fel de pictat te într-un colț. Pentru că nu puteți introduce elemente noi în mijlocul unei matrice. Nu puteți introduce mai multe elemente la sfârșitul unei matrice. Într-adevăr, va trebui să recurgă la crearea unui matrice cu totul nouă, așa cum am discutat, copierea vechi în noua. Și din nou, că este durere de cap care Getstring oferte cu pentru tine. Dar, din nou, nu poți nici măcar introduce ceva în mijlocul matrice dacă rata nu este umplut în întregime. De exemplu, în cazul în care această matrice aici de mărime șase are doar cinci lucruri în ea, Ei bine, ai putea doar tac ceva pe final. Dar ce se întâmplă dacă doriți să inserați ceva în mijlocul matrice, chiar dacă aceasta ar putea avea cinci din șase lucrurile din ea? Ei bine, ce am făcut atunci când am avut toți de voluntari noastre umane pe scena in ultimele saptamani? Dacă am vrut să pun pe cineva aici, fie acești oameni cum să se miște această fel, sau acești oameni cum să se miște această mod, și care a devenit costisitoare. Deplasarea de oameni în interiorul unui matrice ajuns însumarea și costurilor ne timp, prin urmare, mult pătrat noastre n execută ori ca un fel de inserție, pentru exemplu, în cel mai rău caz. Deci, tablouri sunt mari, dar trebuie să știe în avans cât de mare le doriți. Deci OK, aici este o soluție. Dacă nu știe în avans cât de multe elevii ar putea să am, și eu știu o dată Eu decid, totuși, am ramas cu care mulți studenți, de ce nu am mereu alocarea de doua ori la fel de mult spațiu cum am putea crede că am nevoie? Este că nu o soluție rezonabilă? Realist, nu cred că suntem avea nevoie de mai mult de 50 de sloturi într-o matrice pentru o clasă de dimensiuni medii, asa ca hai sa rotunji doar în sus. Voi face 100 de sloturi în matrice mea, doar astfel încât să putem ajunge cu siguranta numărul de studenți mă aștept să fie într-o clasă de dimensiuni medii. Deci, de ce nu rotunji doar în sus și să aloce mai multă memorie, de obicei, pentru un vector decât credeți că ați putea chiar nevoie? Ce-i asta pushback simplu a venit ideea asta? Doar risipiți memorie. Literalmente fiecare program pe care scrie, atunci este, poate, folosind de două ori la fel de mult de memorie ai de fapt nevoie. Și că pur și simplu nu se simte ca o în special soluție elegantă. Mai mult decât atât, doar scade probabilitatea ca o problemă. Dacă se întâmplă pentru a avea un curs populare un semestru și aveți 101 elevi, programul este încă cu care se confruntă în mod fundamental aceeași problemă. Deci, din fericire, există o soluție pentru acest anunt toate problemele noastre în formă de structuri de date, care sunt mai complexe decât cele am văzut până acum. Acest lucru, eu susțin, este o listă de legat. Aceasta este o listă de numere - 9, 17, 22, 26, și 34 - care au fost legate între ele prin intermediul din ceea ce am desenat ca taste. Cu alte cuvinte, dacă am vrut să reprezinte o matrice, am putea face ceva de genul asta. Și îl voi pune pe tavan într-o clipă. Am putea face - Bună ziua, bine. Stand by. Computer nou aici, clar - În regulă. Deci, dacă am aceste numere în matrice - 9, 17, 22, 26, 24 - nu neapărat la scară. Bine, deci aici este matrice mea - Oh, Doamne. Bine, deci aici este matrice mea. Oh, Doamne. [Râsete] DAVID MALAN: Simularea. E prea mult efort pentru a merge înapoi și repara că, așa că - 26. Deci avem această serie de 9, 17, 22, 26, și 34. Pentru cei dintre voi poate vedea greșeală jenant am făcut, acolo este. Deci, eu spun că aceasta este o soluție foarte eficientă. Am alocat cât mai multe int fi Am nevoie - unul, doi, trei, patru, cinci, sau șase - și am apoi stocate numerele în interiorul acestui tablou. Dar să presupunem, atunci, vreau să introduceți o valoare cum ar fi numărul 8? Ei bine, unde se duc? Să presupunem că doriți să inserați o serie cum ar fi 20. Ei bine, unde se duc? Undeva la mijloc, sau numărul 35 trebuie să meargă undeva la sfârșitul anului. Dar sunt toate de spațiu. Și deci aceasta este o provocare fundamentală de matrice care nu sunt soluția. Am susținut un moment în urmă, getstring rezolvă această problemă. Dacă doriți să introduceți un număr de al șaselea în această matrice, ceea ce este cel puțin unul Soluția poate cădea din nou pe de sigur, la fel cum facem cu getstring? Ce-i asta? Ei bine, să-l mai mare este mai ușor de zis decât de făcut. Noi nu putem face neapărat matrice mai mare, dar ce putem face? Face o matrice nou, care e mai mare, de mărimea 6, sau, poate, dimensiune 10, dacă vrem pentru a merge mai departe de lucruri, și apoi copiați matrice vechi în noua, iar apoi elibera matrice vechi. Dar ceea ce este timpul de funcționare acum de acest proces? E mare O, de n, deoarece copierea se va costa unele unități de timp, deci nu atât de perfect, dacă avem de a aloca o matrice nou, care se va să consume mai mult de doua ori memorie temporar. Copiați vechi în noi - Adică, e doar o durere de cap, care este, din nou, de ce am scris Getstring pentru tine. Deci, ce am putea face în schimb? Ei bine, ce dacă structura noastră de date de fapt, are lacune în ea? Să presupunem că am relaxa scopul meu de a avea bucăți adiacente de memorie, unde 9 este chiar lângă 17, care este în imediata vecinătate a 22, și așa mai departe. Și să presupunem că 9 poate fi aici în RAM, și 17 pot fi aici în RAM, și 22 pot fi aici în RAM. Cu alte cuvinte, nu am nevoie de ele Chiar și la mai înapoi. Trebuie doar să firul cumva un ac prin fiecare din aceste numere, sau fiecare din aceste noduri, așa cum vom numi dreptunghiuri așa cum le-am trase, la amintiți-vă cum să ajungi la ultimul astfel nod din prima. Deci, ceea ce este construcția de programare am vazut destul de recent, cu care am poate pune în aplicare acest fir, sau trase aici, cu care pot pună în aplicare aceste săgeți? Deci indicii, nu? Dacă nu aloca doar o Int, dar un nod - și prin nod, vreau să spun doar recipient. Și vizual, vreau să spun un dreptunghi. Deci, un nod aparent are nevoie de să conțină două valori - Int în sine, și apoi, după cum implicate de jumătatea de jos a dreptunghiului, spațiu suficient pentru un întreg. Deci gândesc la viitor aici, cât de mare este acest nod, această containerul în cauză? Câte bytes pentru int? Probabil 4, dacă e aceeași ca de obicei. Și atunci cum de multe bytes pentru indicatorul? 4. Deci acest container, sau acest nod, este va fi o structură 8-byte. Oh, și că este o coincidență fericită că am introdus doar această noțiune de unei structuri, sau o structură C. Deci, eu pretind că vreau să fac un pas față de această mai sofisticate punerea în aplicare a unei liste de numere, un Lista legate de numere, am nevoie pentru a face o puțin mai mult de gândire în față și declare nu doar un int, dar o struct pe care o voi numi, convențional aici, nodul. Am putea spune orice vrem, dar nod va fi tematic într-o mulțime din lucrurile pe care le începe căutarea de la acum. În interiorul acestui nod este un n int. Și apoi această sintaxă, un pic ciudat la prima vedere - struct nod * viitor. Ei bine pictural, ce e asta? Că este jumătatea de jos a dreptunghiul pe care am văzut- doar o clipă în urmă. Dar ce spun struct nod * spre deosebire de doar nod *? Pentru că în cazul în care indicatorul este îndreptat la un alt nod, e doar adresa unui nod. Aceasta este în concordanță cu ceea ce am discutat despre indicii până acum. Dar de ce, dacă mă susțin această structură este numit nod, nu am să spun struct nod în interiorul aici? Exact. Este un fel de realitate stupid de C. Typedef, ca să spunem așa, nu are sa întâmplat încă. C este foarte literal. Se citește de sus codul de partea de jos, de la stânga la dreapta. Și până când se lovește ca punct și virgulă pe linia de jos, ghici ce nu exista ca un tip de date? Nod, nodul încheiat citatul citat. Dar, din cauza Mai detaliat Declarația am făcut pe prima linie - nod typedef struct - pentru că a venit în primul rând, înainte acolade, care e un fel de pre-educarea răsune asta, Știi ce, dă-mi un struct numit nod struct. Sincer, nu-mi place de asteptare lucruri struct nod, nod struct toate de-a lungul codul meu. Dar voi folosi doar o singură dată, doar în interiorul, astfel încât să pot în mod eficient a crea un fel de referința circulară, nu un pointer la mine în sine, ci un pointer la o alta un tip identic. Deci, se dovedește că pe o structură de date ca aceasta, există câteva operațiunile care ar putea fi de interes pentru noi. S-ar putea dori pentru a insera într-o listă ca aceasta. S-ar putea doriți să ștergeți dintr-o listă ca aceasta. S-ar putea dori să caute pe lista pentru o valoare, sau mai general, traverse. Și de traversare este doar un mod fantezist de a spunând încep de la stânga și muta toate drumul spre dreapta. Și observați, chiar și cu acest ușor mai structura de date sofisticată, să mi propun pe care le pot imprumuta o parte din ideile din ultimele două săptămâni și pună în aplicare o funcție numită căutare cum ar fi aceasta. Se va întoarce adevărat sau fals, indicând, da sau Nu, n este in lista. Al doilea argument este un pointer la lista în sine, astfel încât o pointer la un nod. Tot ce am de gând să faci, atunci este declară o variabilă temporar. O vom numi ptr prin convenție, pentru indicatorul. Și am atribui egal cu începutul listei. Si observa acum bucla în timp ce. Atât timp cât indicatorul nu este egal la null, am de gând să verifice. Este săgeată indicatorul n egal cu n care a fost trecut în? Și așteptați un minut - nou bucată de sintaxă. Ce este săgeata toate dintr-o dată? Da? Exact. Deci, în timp ce câteva minute în urmă, am folosit notația punct de acces ceva în interiorul unei struct, dacă variabila ați nu este struct în sine, ci un pointer la o struct, Din fericire, o bucată de sintaxă care în cele din urmă are sens intuitiv. Săgeata înseamnă să urmeze indicatorul, ca săgețile noastre înseamnă de obicei pictural, și du-te la câmp de date în interior. Deci, săgeata este același lucru ca punct, dar să-l utilizați atunci când aveți un pointer. Deci, doar pentru recapitulare, apoi, în cazul în care câmpul n interiorul struct numit indicatorul egal este egal cu n, return true. În caz contrar, aceasta linie de aici - indicatorul este egal cu indicatorul următor. Deci, despre ce se face, preaviz, este dacă am Sunt în prezent, arătând la struct conținând 9, iar 9 nu este numărul Caut - Presupun Caut pentru n este egal cu 50 - Am de gând să actualizeze indicatorul mea temporar nu la punctul de la acest nod mai, dar indicatorul săgeata de lângă, care este de gând să mă pun aici sus. Acum, am realizat este un vârtej de vânt introducere. Miercuri, vom face de fapt acest lucru cu niște oameni și cu ceva mai mult cod într-un ritm mai lent. Dar dau seama, facem acum datele noastre structuri mai complexe, astfel încât nostru algoritmi pot obține mai eficiente, care va fi necesară pentru PSET șase, când am încărca în, din nou, cei 150.000 de cuvinte, dar trebuie să facă acest lucru eficient, și în mod ideal, creează un program care ruleaza pentru utilizatorii noștri nu în liniar, nu în n pătrat, dar în constanta de timp, în idealul. Ne vedem miercuri. Difuzor: La CS50 următoare, David uită cazul lui de bază. DAVID MALAN: Și asta e cum ai trimite mesaje text cu C. Care - [Mesaj text DIVERSE Sunetele de notificare]