[Powered by Google Translate] [Uke 3]
[David J. Malan - Harvard University]
[Dette er CS50. - CS50.TV]
La meg styre oss i retning av der vi slapp forrige gang,
som var begynt å tenke litt mer enn om syntaks
og prøver å tenke litt mindre om alle de bagateller
som tar litt tid å venne seg til så langt i form av semikolon
og parenteser og klammeparentes,
å begynne å ta ting litt på et høyere konseptuelt nivå
slik at de problemene vi nå begynne å løse i løpet av de neste ukene
kommer til å innebære mye mer inn høyere nivå konseptuelle problemer
og litt mindre i syntaktisk som du får dine føtter våt
og hendene skitne med noen av syntaksen fra disse siste ukene.
>> Så husker at forrige uke lanserte vi denne oppfatningen av en matrise.
Og en matrise på engelsk kan beskrives som hva? >> [Uhørlig student respons]
Beklager?
En samling av? >> [Uhørlig student respons] >> Ok, bra.
En samling av elementer. Så vi så arrays i Scratch.
Hvis du tilfeldigvis bruke for pset 0 en av Scratch lister som du kan dra ting
som appelsiner og bananer i, en opptelling av former,
som er typen som hva en matrise er.
Og deretter mer teknisk, i sammenheng med en faktisk datamaskin,
en matrise er rett og slett en sammenhengende del av minnet.
Med andre ord, har du en byte, og deretter en annen byte, og deretter en annen byte, og deretter en annen byte,
og hvis du skulle trekke disse bytes i et bilde,
de ville være rygg mot rygg til rygg mot rygg. Det er det vi mener med sammenhengende.
>> Så det er byte nummer 1, deretter 2, deretter 3.
Det betyr ikke opp her, her oppe, her oppe, her oppe.
En matrise er en sammenhengende del av 0 eller flere byte.
Så hva er de nyttige for?
Husker vi hadde denne typen contrived eksempel på lagring folks quiz karakterer i et program
å beregne din quiz gjennomsnittet for noen kurs,
og huske at vi kunne begynne å skrive at programmet ved å erklære en variabel quiz1.
Da kunne vi ha en annen variabel kalt quiz2.
Men så hvis det var 3 quizer i denne klassen, quiz4.
Eller hvis det var en ukentlig quiz, ville det være quiz5, quiz6, quiz7.
Så du ville ha alle disse variablene erklært innsiden av hoved
eller et annet sted i programmet,
og problemet med denne tilnærmingen, lett skjønt det er å bare kopiere og lime inn,
er det bare veldig fort blir uhåndterlig.
Gud forby du faktisk har 30 spørrekonkurranser eller 50 spørrekonkurranser.
Hvis det er som en high school stil daglig pop quiz,
så du bare har en latterlig lang liste av variabler deklareres,
og dette bare veldig fort kommer ut av kontroll.
Det er stygt, er det vanskelig å vedlikeholde, er det så mye lettere å gjøre en skrivefeil
hvis du får en rekke skrevet feil et sted i programmet.
>> Så vi introduserte begrepet en matrise i stedet.
Og huske at vi implementert dette programmet ved å gjøre litt noe sånt som dette.
La meg gå inn i dagens Kilde 3 mandag katalog
og åpne opp array, som vi så forrige gang.
Og selv om det var et par nye C triks her,
blant dem ideen om en konstant,
husker at vi erklært flere flyter hovedsak ved hjelp av denne syntaksen:
flyte, så navnet på variabelen, så vi brukte firkant parenteser virkelig for første gang,
og hva vi gjorde innsiden av de firkantede bukseseler ble effektivt satt et tall.
Men i stedet for å sette et tall, la jeg denne ord med store bokstaver, spørrekonkurranser.
Og hva var motivasjonen for å sette en balanseført ord som spørrekonkurranser
og deretter bruke linje 17 er trikset her for å faktisk gi den et nummer?
Hva var motivasjonen der? Ja.
>> [Uhørlig student respons] >> Nettopp.
Hvis vi ønsker å endre denne verdien 2, vi trenger bare å endre den i en plass
fordi vurdere - Jeg vet ikke engang huske hva dette programmet gjorde akkurat,
men hvis du bare skumme det du ser spørrekonkurranser, quiz.
Du ser spørrekonkurranser, ned her mer spørrekonkurranser.
Så hvis vi ikke har dette konstant, denne bruken av skarp definere,
vi ville ha skrevet to, deretter 2, deretter 2, deretter 2, som er fine. Det ville være like riktig.
Men anta at neste år har vi tre quizer i CS50.
Så jeg må gå og oppdatere koden, må jeg rekompilere det,
men problemet er hvis jeg gjør noe dumt, som jeg overse en omtale av to
og glemmer å plugge i tre, kan hele programmet veldig godt bryte.
Så vi bare be om problemer.
>> Så tanken om en konstant handler om factoring ut noen del av data,
enten det er en streng eller en røye eller en flåte eller hva,
og erklære det en plass, slik at du kan lettere endre det i fremtiden.
Og det er også ærlig, litt lettere å lese fordi hvis du bare tenker på dette nå,
det er spørrekonkurranser, eller vi kan selv endre navnet noe sånt som NUMBER_OF_QUIZZES
eller noe mer eksplisitt.
Koden blir bare litt mer opplagt på hva det gjør,
og du lurer på litt mindre hva nummer 2 kan skje til å bety.
Så den konstante hadde ingenting å gjøre fundamentalt med arrays.
Matrisen ble introdusert i form av disse firkantede bukseseler.
>> Så merke til at i tråd 23 spør vi bruker, "Hva var dine quiz score?"
Så vi bare har denne sløyfen som tilsynelatende ber brukeren om sine karakterer. Hvordan?
Det gjentar 0-2. Og jeg sier 2 fordi quizer i alle caps er nå 2.
Så det gjentar fra 0 til 2 og deretter det skrives ut Quiz # noe av noe,
og deretter den bruker GetFloat å få en verdi fra brukeren.
Så merke dette er den eneste andre nye stykke syntaks fra sist onsdag.
Hvis du ønsker å lagre noe på et bestemt sted i denne matrisen,
du igjen bruke klammeparentesene.
>> Så det er litt av dikotomi her.
Den første gangen du bruker hakeparenteser
du bruke den til å angi hvor stor du vil at tabellen skal være.
Men dette neste sammenheng her hvor vi igjen ansette disse hakeparenteser
betyr hvor i denne matrisen vil du sette noen verdi?
Og skillet her kan utledes fra sammenheng.
Legg merke her har vi en datatype, så har vi navnet på en variabel,
så har vi våre firkant parenteser med en rekke inne, semikolon. Det var det.
Så det er en erklæring.
Det er akkurat som om vi hadde gjort noe sånt flyte Grade1, float Grade2;
men igjen, dette svært raskt tilfaller inn altfor mye kopiere, lime,
så i stedet vi bare forenklet det som sådan,
som betyr heretter vi har en karakter som kan lagres på brakett 0,
Vi har en annen karakter som kan lagres på trinn 1,
men hva om jeg tabbe og, for eksempel, går min sløyfe så langt -
for eksempel, gjør jeg dette mindre enn eller lik,
som husker var kilden til en tidligere bug -
som betyr effektivt at på noen tredje utilsiktet gjentakelse av denne sløyfen
Jeg bruker brakett 2. Effektivt, hva kan skje her? Beklager?
[Student] Det kommer til å bli erstattet. >> Er det kommer til å bli erstattet?
Hva ville bli erstattet?
Dette bokstavelig sier erstatte det er på stedet 2 med returverdien av GetFloat.
Men problemet er hvor stor er rekken på dette punktet i historien?
[Uhørlig student respons] >> Matrisen er fortsatt bare av størrelse 2
fordi tabellen, som en variabel, ble erklært først, før vi brukte den,
og vi angitt her på grunn av dette konstant at jeg har to karakterer som jeg kommer til å sette.
>> Men husk, dataforskere begynne å telle fra 0.
Så det første stedet i denne matrisen er brakett 0.
Neste lokasjon er en. Denne saken er aldri så litt for langt til siden.
Så med andre ord, hvis jeg faktisk hadde denne tabellen -
og la meg se hvor godt dette cooperates her for oss -
hvis jeg har en matrise som jeg har rett og slett tegnet som følger
og jeg har avsatt plass for to elementer, kan jeg trekke dette som dette i minnet
hvor denne store hvite lerretet er.
Det er bare RAM jeg har i min datamaskin, en gig RAM, 2 gigabyte RAM, uansett,
men disse to boksene som nå individuelt representerer en flåte, 32 biter.
Så hvis jeg legger en rekke her som 1.0, så jeg satte et annet nummer her som 3,2
men så gjør jeg to brakett, det er som å sette noe her.
Og som bildet antyder, det er ingenting der.
Det er liksom som ingenmannsland fordi jeg ikke har bedt om operativsystemet
å gi meg denne tredje quiz.
Hvis jeg hadde lyst at tredje quiz, jeg skulle ha hatt forethought
å be operativsystemet for det ved å erklære quizer å være ikke 2
men å i stedet utgjøre 3.
>> Så med andre ord, ser det bildet som vi effektivt har for hånden som dette her.
Dette er igjen ingenmannsland. Vi bedre ikke prøve å skrive verdier her.
Men igjen, fordi dataforskere telle fra 0,
når vi snakker om denne plasseringen i matrisen, er det ment å være plassering 0,
dette er ment å være plassering 1, og dette betyr ikke engang eksisterer
fordi vi bare bedt operativsystemet for to slike steder.
Så de av dere med tidligere erfaring med programmering fra andre språk
kanskje vet at dette er ikke alltid tilfelle med matriser eller ting som kalles vektorer.
Snarere kan du bare fortsette å legge og legge og legge ting til matriser,
som, ærlig, hadde vi den muligheten i spill og ennå vi synes å ha gitt det opp her
fordi med C er du programmerer mye mer eksplisitt.
Det er bare du og datamaskinen akkurat nå, og at datamaskinen er bare kommer til å gjøre
hva du ber den om.
Så hvis du bare fortelle det for å gi deg to flottører ved hjelp av linje 22 her,
det er alt du kommer til å komme tilbake fra operativsystemet: plass til 2.
>> Så i økende grad programmene skal tidvis være buggy med hensyn til arrays.
Dette er bare en slags natur dyret der alle av oss er ufeilbarlige,
og på et tidspunkt vil du høyst sannsynlig indeks utover grensen av arrayet.
Og det er bare en fancy måte å si at du gikk inn brakett noe
og noe var bare for stor til et tall. Du gikk utenfor grensene av arrayet.
Men oppsiden er nå dette.
Resten av dette programmet har egentlig ingenting fundamentalt å gjøre med arrays.
Det handler bare om noen enkel aritmetikk for databehandling gjennomsnitt.
Så vi har her i dette for loop her først en variabel kalt sum som vi initialisere til 0.
Da vi iterate fra 0 til 2 igjen, og vi legger til at summering variabel
-te klasse, så brakett 0, så braketten en.
Og deretter som du ville gjort i grunnskolen til å beregne gjennomsnitt,
vi bare ta denne summen, dele den med det totale antall tester,
og deretter for godt mål vi kaller en funksjon her kalt runde.
>> Nå, som en side, hva er greia med denne parenthetical int på linje 34?
Det kan ha kommet opp allerede i snitt, har egentlig ikke snakket om det formelt her,
men hva er dette int i parentesar sannsynligvis gjør? >> [Uhørlig student respons]
Ja, dette refererer til støping eller typecasting,
som betyr å ta en datatype og konvertere den til en annen.
Du kan ikke gjøre dette med alle datatyper fordi noen ganger det ville være litt rart.
Men i dette tilfellet, hvis returverdien runden er en flottør
fordi, tross alt, jeg tar en dupp og dele det på et tall som 2,
Jeg kommer til å få tilbake en flåte.
Men grunnskolen folk ikke liker å vite at deres gjennomsnittlige var 93,4
fordi de vil innse at de var aldri så nær at 95 avrunding punktet.
>> Så vi ønsker å i stedet bruke int å runde alle til nærmeste int,
som i dette tilfellet kommer til å være 94 med noe punkt etter den.
Så det er bare en liten matematisk triks.
Og vi vil komme tilbake til denne tanken for å kaste fordi det vil ha konsekvenser,
Hvis du ikke har oppdaget allerede, for problemet sett 2.
Så en matrise så kan du tenke på - det kommer til å gjøre meg smile hele dagen.
Det ser ut som dette hvis du tegner et bilde av det,
men nøkkelen er at størrelsen også er valgt av deg
når du ber om det fra operativsystemet.
Eventuelle spørsmål deretter på arrays? Ja.
[Uhørlig student spørsmål]
Ah, godt spørsmål.
Spørsmålet er hva som skjer med null 0 i array? Det finnes ikke i denne sammenheng.
Som bare finnes i sammenheng med strenger, som vi er i ferd med å komme til i løpet av et øyeblikk.
Men for en matrise, som i dette tilfellet, er alt du får det du ber operativsystemet for.
>> Og som en side, så dette være uklart,
Jeg holder å si at du spør operativsystemet, spør operativsystemet.
Et operativsystem, som du sikkert vet, er Mac OS, Windows, Linux.
Når du ringer funksjoner som GetFloat
eller du erklære variabler som karakterer,
på slutten av dagen er du effektivt å spørre noen andre til å gi deg den minne
fordi vi som håper programmerere
har ingen anelse om hvordan å faktisk få fysisk tilgang til minnet.
Men noen gjør: operativsystemet.
Så i tillegg til å presentere oss med pen ikoner og menyer og mapper og lignende
som du ser på ditt skrivebord, enten en Mac eller PC,
operativsystemer også gjøre det lave nivået dagligdagse ting,
den svært tekniske ting å forvalte gigabyte
eller 2 gigabyte minne som du har, administrerende CPU som du har, og så videre.
Så når du skriver kode,
du virkelig trekke på operativsystemet i den forstand.
Jeg kommer til å minimere det. OK.
>> Andre spørsmål om arrays?
Nei? Okay.
Så overgangen naturlig fra arrays er faktisk et emne som er litt kjent.
Og vi så aldri så kort på denne siste gangen også.
Dette var en streng eksempel fra onsdag.
Denne strengen eksempel var en ganske enkelt program,
og jeg har faktisk forenklet det ved et par linjer for dagens formål.
Alt den gjør i linje 19 er å få en streng fra brukeren, lagrer den i en variabel kalt s.
Så i linje 22 og fremover er det tilsynelatende skriver at strengen en tegn per linje.
Men hvordan er det å gjøre dette?
Vi erklærer en variabel i, sette den lik 0,
og dette blir gammel vane nå.
Vi hadde ikke sett dette før onsdag, men du kan slags antyde fra sitt navn
strlen returnerer akkurat hva når gitt s? Lengden av strengen.
Så hvis jeg passerer det en streng, sitat-unquote DAVID,
det er forhåpentligvis kommer til å returnere til meg nummer 5 på grunn av DAVID.
Så det er dens formål i livet er å ta en streng, enten hardkodet av deg
eller i dette tilfellet koblet som en variabel, som et argument,
og det finner ut hva lengden på strengen er.
>> Så her nå er vi låne noen notasjon fra forrige quiz eksempel.
Dette har ingenting å gjøre med flottører, har ingenting å gjøre med spørrekonkurranser,
men det viser seg at den lille hvite løgnen vi har vært å fortelle deg siden uke 1
er at en streng egentlig ikke finnes i C.
En streng på slutten av dagen er egentlig bare en matrise.
Det er en rekke bytes, så byte, byte, byte, byte, som tilbakekallingen er bare 8 bits,
så mengde minne, del av minnet, del av minnet, del av minnet.
Og midlene som en streng er implementert
er ved å sette det første tegnet her,
så her, så her, så her, rygg mot rygg mot rygg i datamaskinens minne.
Så hvis du ønsker å stave ut et ord som HELLO, ville du sette en karakter H,
deretter E, deretter L deretter L, deretter O - 5 tegn i totalt - et sted i datamaskinens RAM.
Men viktig detalj her er at de kommer til å være tilbake til rygg mot rygg til rygg,
rett ved siden av hverandre.
Når når jeg sier s [i], hva i engelsk er dette gi meg?
Hva betyr s [i] representerer i dette tilfellet? Ja.
>> [Student] Den ith tegnet i strengen. >> Nettopp. Den ed tegnet i strengen.
Nå er jeg kommer til å starte på 0 pr min for loop her,
men det er bra fordi alt begynner å telle fra 0.
Så s [0] kommer til å representere bokstaven H i et ord som HELLO,
s [1] kommer til å representere en bokstav som E i et ord som Hallo, og så videre.
Og hva vi synes å være å gjøre på hver iterasjon av denne sløyfen
midlertidig lagring av ed tegnet i en variabel kalt c, som er bare en røye,
og så skal vi skrive ut c
slik at ved slutten av dagen hva dette programmet gjør er følgende.
Hvis jeg går inn i kilden katalogen og jeg gjør streng1 og jeg går videre og kjøre streng1,
og da jeg skriver inn et ord som HELLO, Enter, er alt den gjør ut dette en tegn om gangen.
>> Så det er en mulighet for videreutvikling her.
Jeg er litt å gjøre mer arbeid, selv om det er mer tydelig kanskje på denne måten, enn nødvendig.
Hvilken linje av koden her kan jeg nok kaste bort helt? Ja.
Linje 24. I linje 24 jeg erklære en variabel c.
Jeg lagre i. karakter er i det, men da jeg bruker c her.
Så jeg bruker c, så jeg føler at jeg kan ikke bare kaste line 24 unna.
[Uhørlig student kommentar] >> Nettopp.
Så når det gjelder å snakke om design av programmer,
merke til dette liten forenkling av koden, som er like lesbar,
men innser at s er bare en variabel, er datatypen en matrise,
så s [i] er bare kommer til å umiddelbart gå tilbake til deg i. tegnet i strengen.
Og hvis du ønsker å skrive det ut, er det fint.
Du må bare bruke% c fordi du ikke skriver ut en streng,
du skriver et tegn i en streng, og dette også har effekten av å trykke den ith karakter.
Og minnes den eneste forskjellen egentlig fra forrige uke med å bruke printf
er at mens i ukene tidligere vi ville gjøre noe super enkelt
som% s plassholderen deretter navnet på en streng her,
nå er vi dykking i en litt dypere under panseret og sa
ikke ut strengen, skrive ut enkelt tegn der.
>> Så vi kan gjøre noe litt annerledes her fordi det er en annen - ikke bug
fordi dette programmet er riktig, men jeg gjør noe dumt
som jeg nevnte kort på onsdag.
Men tenker tilbake, hvordan kunne dette programmet design bli forbedret ytterligere? Ja.
[Uhørlig student respons] >> Å, bra.
Så husker at vi innførte en ny variabel kalt n siste gang,
som synes å være motstridende oss fordi mitt mål en andre siden
var bare å kaste bort en variabel som unødvendig,
men husker at på onsdag faktisk vi gjorde dette.
Jeg har forandret for loop å faktisk ha et komma her, så n = strlen,
og deretter over her gjorde jeg i <n, så jeg gjorde mine trinn.
Hva er den grunnleggende gevinst som jeg oppnå ved å endre min initialisering til dette
og min tilstand til dette nå? >> [Uhørlig student respons] >> Nettopp.
Jeg er ikke tilbakekaller strlen igjen og igjen og igjen fordi husker hvordan for løkke fungerer.
Selv om de begynner å bli mer komplisert utseende,
husker at ting før det første semikolon er initialisering, som skjer en gang.
Tilstanden, men er i midten,
og dette blir sjekket hver gang du går gjennom løkken.
>> Så det er litt dumt å spørre datamaskinen det samme spørsmålet igjen og igjen -
Hva er lengden på HELLO? Hva er lengden på HELLO? Hva er lengden på HELLO? -
fordi vi vil se i dag og på onsdag, er dette definitivt kommer til å ta tid,
og det er ikke en veldig god bruk av tid fordi å finne ut lengden på en streng
faktisk tar litt innsats.
Det er ikke umiddelbar, som det er i enkelte språk.
Så ved å endre dette til n, er prisen jeg betaler hva?
Vi ser en avveining her.
Jeg kan spare tid ved å ikke stille det samme jævla spørsmålet igjen og igjen,
men det kommer til å koste meg noe, som er hva?
>> [Student] Du mister en viss mengde minne. >> Nettopp. Det kommer til å koste meg minne.
Så i dette tilfellet koster det meg hva?
En annen 32 biter fordi n er bare en int, som underforstått av ordet int her.
Men er det greit?
Ærlig talt, det er nok greit fordi hvis du tenker på det,
jo lenger strengen er, jo mer tid jeg kommer til å være å kaste bort
fordi strlen kommer til å bli kalt igjen og igjen og igjen
for hver iterasjon av sløyfen.
Og i disse dager, har min Mac 2 gigabyte RAM, i disse dager 4 gigabyte RAM noen ganger.
Jeg tror jeg kan ha råd til 4 av disse byte å faktisk fortgang.
Men dette kommer til å bli en avveining og et tema virkelig i programmering og i informatikk
av egentlig aldri å få noe gratis.
Hvis du ønsker å forbedre noe her, må du betale for det i den andre hånden eller annen måte.
Plass mot tid i dette tilfellet.
>> Så dette var alt ledet opp mot noe kryptisk som dette,
som, som du sikkert funnet ut av nå, sier egentlig?
[Uhørlig student respons] >> Ja, så dette er, sørg for å drikke din Ovaltine,
faktisk bruker en algoritme som heter ROT13, ROT 1-3,
som betyr bare rotere alle bokstavene 13 plasser,
som betyr å ta A og deretter legge 13 til den og gå prikk, prikk, prikk
hele veien til det 13. brevet bort, gjør det samme for B og for C, og for D og så videre.
Og så hvis vi faktisk konvertere dette her med en forskyvning av 13 plasser,
vi vil komme tilbake til det lille Ralphie hadde, som var, sørg for å drikke din Ovaltine.
Men nå for problem sett 2, i standardutgaven minst,
du må slags gjør dette enciphering selv,
og vi må liksom ta i input som dette og kryptere det eller dekryptere den.
>> Så hvilke av disse grunnleggende slags fører oss til denne muligheten?
La oss ta en titt på denne tredje eksempel her.
Først av alt, det heter ASCII. Hva refererer ASCII tilbake til?
American Standard Code for Information Interchange,
som er en veldig lang vei å si hva? Hva er ASCII?
[Uhørlig student respons] >> Hva er det? >> [Student] Et tegn kart. >> Et tegn kart.
Det bare kartlegger tall til bokstaver fordi verden har standardisert
hva tallene vil representere hva bokstavene slik at alle av oss kan bruke datamaskiner
og våre programmer alle er like kompatible når det kommer til å skrive ut ting på skjermen.
Så husker at 65 skjer til å representere A, skjer 97 til å representere små bokstaver en.
Og så dette enkle programmet her ASCII tar nytte av det faktum -
at verden vet at kapitalen A er 65 - og det er bare å skrive ut kartleggingen.
>> Så før vi dykke inn denne koden, la meg i stedet åpne opp en terminal vindu.
La meg gå videre og gjøre ASCII, og så la oss bare kjøre denne ting bare for å ødelegge utgang.
Og det gjør nettopp dette: en virkelig stor diagram som bare forteller meg alle de forskjellige koder
for alle de ulike bokstavene.
Så en super enkelt program, men jeg har ikke for hardt kode de 52 linjer med:
26 store, 26 små bokstaver.
I stedet gjorde jeg dette programmatisk med et par sløyfer.
Legg merke til hva jeg gjorde her.
Jeg iterated fra jeg er 65 på opp til 65 + 26 fordi jeg ønsket å skrive ut 26 bokstaver
i det engelske alfabetet, i + + på hver iterasjon, og nå merker dette på nytt.
Det er gjentakelse av vår venn typecasting
der du konverterer en datatype til en annen
fordi det ønsker jeg å gjøre i dette programmet?
Jeg ønsker å telle numerisk fordi det er hvordan jeg vokste opp telling - 65, 66, 67, og så videre -
men jeg ønsker ikke å skrive ut bare tallene.
Jeg ønsker å skrive brevet etterfulgt av nummeret.
Jeg ønsker å skrive ut A: nummer, B: nummer, men jeg kan gjøre dette med de samme variabel.
Så jeg skrive ut% c som plassholder for et tegn,
% D som plassholder for et siffer eller nummer.
Så hva plugge jeg i for de to plassholdere?
Jeg først koble tegnet tilsvarende i, og da jeg skrive ut i seg selv.
>> Så merker dette også fungerer.
Akkurat som jeg kan kaste fra en flåte til en int
for å gå fra et reelt tall til et heltall,
her kan jeg gå fra en int til en røye, som er litt rart -
ikke helt kartlegge på den virkelige verden - men i datamaskiner
en røye er bare et tall under panseret,
så vi blir aldri så eksplisitt her til datamaskinen, sa
printf, skrive ut ikke jeg som 65, skrive den ut som sin numerisk tilsvarende.
Og det viser seg at jeg teknisk sett ikke engang trenger dette.
Hva jeg gjorde for et øyeblikk siden er eksplisitt avstøpning
ved å angi hva datatype jeg ønsker å gå fra og til.
Men merker at jeg allerede har denne plassholder% c
og denne andre% c plassholder her.
Selv om dette ikke er int, innser datamaskinen som en røye,
det er bare en int under panseret.
>> Så hvis jeg faktisk rekompilere denne og kjør ASCII-programmet,
merker det fortsatt bare fungerer fordi datamaskinen innser at det er denne korrespondansen.
Nå er det mer viktig å gjøre det eksplisitte casting i verden av flyter til ints
fordi det du faktisk gjør en kalkulert avgjørelse:
kaste bort alt etter desimaltegnet.
Her er det virkelig ingenting å kaste bort fordi et tegn er bare et tall,
og en streng er bare en rekke tegn.
Så når det gjelder tid til å implementere noen kryptering eller dekryptering,
hvordan er det at vi faktisk kan oversette noe sånt som dette tullet til,
Sørg for å drikke din Ovaltine?
Hva om vi vet akkurat nå - la oss ta som forutsetning - at nøkkelen,
nummeret som vi roterer alle disse brevene ved, er nummer 13?
Så vi gikk fra bokstaven B hele veien til O ved starten av setningen,
Sørg for å drikke din Ovaltine, fordi hvis jeg gjør B
og da går C, D, E, F, G, H, I, J, K, L, M, N, O,
det er derfor kryptering av bokstaven B blir O
fordi jeg nettopp har lagt 13 til det.
>> Så hvis jeg ønsker å dekryptere dette, jeg egentlig har å ta O og deretter trekke 13 fra det.
Eller, ærlig, fordi det er 26 bokstaver i alfabetet, er dette fantastisk symmetrisk,
Vi kan også bare legge 13 og vi vil komme tilbake til bokstaven B.
Men hvordan går du om å implementere noe slikt i Caesar
eller egentlig manipulere strenger generelt?
Hvis bokstaven B er hvilket nummer?
Hva er bokstaven B? Så det er 66, ikke sant?
Så hvis bokstaven A er 65 og bokstaven B er 66,
så 66, er alt jeg har å gjøre er å legge 13 til det, og dette gir meg 79.
Og hvis vi går til vår lille jukse ark, 79 faktisk kart på O.
>> Men det er litt av et hjørne tilfelle her.
Hva er for eksempel bokstaven Z?
Hvis vi gjør 66 + 25 for å få hele veien til slutten av alfabetet, er vi på 91.
91 + 13 gir meg 104, og gjett hva?
104 ikke lik ikke en stor bokstav.
La oss gå tilbake til en liten jukselapp her.
Hvis jeg kjøre dette programmet i apparatet, legg merke til at 104, hvis jeg går tilbake til terminalen vinduet,
104 er tilsynelatende små timer.
Så vi trenger noen viktige triks her for å sørge for at når vi begynner på Z
og vi legger 13 til det vi ønsker ikke å bare holde bygge videre til større og større tall.
Hva vet vi egentlig ønsker å gjøre?
Du ønsker å vikle rundt.
>> Så det viser seg, som du har sett sannsynligvis i avsnittet nå eller i oppgavesettet spec selv
innsett at det er denne andre operatør i C som også er et prosenttegn,
men mens vi har brukt% her for å angi en plassholder,
vet at, spesielt for oppgavesettet 2, det er også noe som dette:
int x = y% z.
La meg bare presentere dette som en svært generisk form av denne.
Prosent betyr det i et programmeringsspråk? >> [Student] Modulo.
Modulo, som er en fancy måte å si resten.
Selv om det er en liten forskjell med definisjonen der,
dette betyr dele y ved z, men ikke returnere resultatet av denne avdelingen;
stedet, tilbake resten.
>> Så hvis y er faktisk 3 og z er faktisk 2, 3 delt på 2 er en med en rest på 1,
så hva gjør x faktisk like i dette scenariet? 1.
Dette er en så enkel, lavt nivå idé.
Det tar litt tid å få tankene surret rundt det
fordi det er trolig vært en stund siden du hadde å bry seg om rester
og faktisk bruke dem til noe meningsfylt,
men i dette tilfellet det enkle faktum at du kan gå fra et stort antall som 3
til et relativt lite antall som 2 og deretter vikle rundt effektivt
ved å bruke resten til en mindre verdi som en kommer til å være en uvurderlig triks
at vi kan bruke både for noe sånt som Caesar og denne andre ting Vigenere
i problemet sett 2, men dette kommer til å være et tilbakevendende triks gjennom semesteret.
Denne enkle, enkel idé om bare å ta resten generelt
kommer til å tillate oss å vikle rundt.
Og som vi begynner å spille mer med matriser, som vi begynner å spille mer med minne seg selv,
dette kommer til å bli mer og mer av en kraftig knep.
>> Så noen spørsmål så på ASCII eller representasjon av strenger som arrays?
Og vi vil ta det opp 1 hakk videre. Ja.
[Uhørlig student spørsmål] >> Godt spørsmål.
Hva betyr det når en variabel har en stjerne foran den?
La meg utsette å svare at i enhver detalj,
men som refererer til et emne som kalles en peker.
Pekere har å gjøre med minne, og vi er faktisk i dag
ta det første skrittet mot den diskusjonen,
men for nå, la meg late at stjernen ikke eksisterer
og vi vil fortsette å kalle strenger strenger i stedet for å bruke char *,
som du sikkert har sett før, og jeg skal sette på skjermen i løpet av et øyeblikk som en teaser.
Så vi vil komme tilbake til det i måten nærmere enn mange av dere vil sannsynligvis liker.
Til slutt, ikke i dag. Ja.
>> [Uhørlig student spørsmål]
I hvilken sammenheng har du å gi tegn for et tegn? >> [Student] Yeah.
Så som standard, når du ikke sette en +, er bare positive tall til grunn.
Så hvis bare skrive nummer 1, er det en positiv en.
Hvis du faktisk ønsker å spesifisere negasjonen av en verdi,
you have to do -1 på tastaturet.
Men dette er trolig ikke spørsmålet ditt. >> [Uhørlig student respons]
>> Godt spørsmål. Okay.
Så dette har å gjøre, jeg samle, med en slags insekt du kjørte inn i
fordi du var å konvertere et heltall til et tegn,
men noe negativitet ble involvert,
og så tegnet bare kom ut munged annen måte.
Så for nå, la meg forenkle litt før vi kommer tilbake til denne typen emnet.
For nå, tenke på ting på denne måten - og dette er en overforenkling.
Men i en verden av et heltall, har du hvor mange biter til din disposisjon?
Du har 32 biter.
Og så langt har vi snakket om det totale antall heltall kan derfor representere
er rundt 4 milliarder kroner fordi du har 32 bits,
så det er 2 til 32, så det er omtrent 4 milliarder.
Men vi så en uke eller to siden at du ikke egentlig har en rekke tall
fra 0 på opptil 4 milliarder kroner.
Utvalget går i stedet fra ca negative 2 milliarder til positiv 2 milliarder.
Men dette ber deretter spørsmålet, hvordan du representerer begrepet negative 2000000000
enn si negative 1?
For nå kan vi forenkle og bare si at vi kommer til å bruke lengst til venstre bit
av disse 32 bits, og hvis det er en 1 er det et negativt tall,
og hvis det er en 0 er det et positivt tall.
Problemet med at forenklet representasjon av negative tall
er at hvis du var bevisst å være flink og prøver å konvertere fra et tegn til et tall
eller vice versa, er det ingen slike ting som en negativ karakter.
I en verden av ASCII, som bare bruker 8 bits, alle 8 av dem biter saken,
og lengst til venstre bit har ingenting å gjøre med negativitet.
Og bare for å være klar, når jeg sier lengst til venstre biter,
husker at da vi gjorde vår bit-relaterte eksempler i den første uken
husker at vi trakk ting som 1001101, noe som dette.
Når jeg sier lengst til venstre litt, jeg bare bokstavelig talt bety en som du skriver hele veien over til venstre.
Så i en verden av tegn er det ingen forestilling av negativitet,
slik at venstre bit faktisk har noe å gjøre med ASCII, ingenting å gjøre med negativitet.
>> Så det høres ut som - og ut av sammenheng er det vanskelig å svare nøyaktig -
men noe ble koden forvirrende at venstre bit som representerer en negativ verdi
når det egentlig var en del av tegnet i spørsmålet.
Og igjen, jeg oversimplifying fordi datamaskiner faktisk gjøre noe litt mer avansert
enn bare å endre det venstre litt til en 1 for et minustegn versus en 0.
De i stedet, hvis du er nysgjerrig på å Google, bruker noe typisk kalt 2-komplement,
som er litt mer sofistikert av en tilnærming
men ideen er slutt den samme.
>> Så kort sagt, det hadde å gjøre med det faktum at du var masserer et nummer til en karakter
eller vice versa, men koden var ikke bevisst på det faktum
at en av de bitene hadde betydning i den numeriske verden.
Det er ikke tilfelle i tegnet verden.
Men det høres ut som du fast, og da Moot nå. Andre spørsmål.
Okay.
Så så langt har alle de programmene vi har skrevet tatt innspill kanskje fra brukeren
i form av funksjoner som GetInt, GetString,
eller hvis du har lest videre i ulike bøker eller online referanser,
dere selv kan ha brukt funksjoner som scanf som, ærlig, bruker vi i CS50 biblioteket.
Men i en uke eller to, vil vi faktisk vise deg hvordan CS50 biblioteket er implementert
slik at vi kan ta de trening hjul av helt.
>> Men det viser seg at det er en annen måte å få innspill fra en bruker.
Faktisk har vi selv vært med kommandolinjeargumenter
for et par uker nå.
Hver gang vi har kjørt Clang eller vi har kjørt gjøre,
Vi har ikke bare skrevet clang, Enter, vi har ikke skrevet gjøre, Enter.
Hva har vi vanligvis skrevet etter ordet clang på vår terminal vinduer spørsmål?
[Student] Filnavnet. >> Filnavnet, ikke sant?
Hallo.c eller mario.c eller hva den aktuelle filen heter.
Og i den forstand hva du har virkelig gjort er at du har påvirket oppførselen til Clang
fordi absolutt folk som skrev Clang hadde ingen anelse om at litt gammel du
hadde tenkt å skrive et program som heter mario.c år senere.
Så du måtte liksom påvirke atferden til det programmet,
og at programmet Clang måtte være skrevet på en slik måte at den kan ta imot data fra du
ved tilsetting av ord på spørsmål før brukeren treff Enter.
>> Så det viser seg at for noen tid har vi vært erklære nesten alle av våre programmer
å starte som dette - int main (void) - og så har vi gått foran
og begynte å skrive vår kode.
Og vi kan ha noen skarpe omfatter øverst filen,
men nesten alle av våre programmer så langt har begynt med dette
selv om du kanskje har sett i snitt, i bøker, referanser
at dette ikke faktisk må være ugyldig.
En annen legitim form for at dette skal ta er int argc og streng argv [].
Så nå hva er dette antyder?
Det viser seg at argc, som er en menneskelig konvensjonen - du kan kalle dette foo,
men det ville bare være mye mindre klart for leserne -
argc er bare et argument til funksjonen kalles viktigste som representerer hva?
Hva står argc for for de som er kjent?
>> [Uhørlig student respons] >> Ja, antall argumenter eller argument teller.
Det er så enkelt som det.
Hvor mange argumenter ble sendt til dette programmet?
Hva betyr det?
Hvis på kommandolinjen jeg har kjørt noe sånt som dette - clang mario.c--
argc når jeg treffer Enter kommer til å ta på en verdi av, noe forvirrende, 2.
Så det viser seg at argc er argument teller,
men for historiske årsaker, er navnet på selve programmet inkludert i som teller.
Så argc er 2 når jeg skrev clang mario.c.
Hva inneholder argv?
Først av alt, ser argv som en streng, men ikke helt
fordi som sist onsdag og alle de mer i dag,
disse hakeparenteser betegne hva? Det er en matrise.
Det er ingen tall i rekken, og det bør være fornuftig intuitivt
fordi folk som skrev clang år siden sikkert hadde ingen anelse
hvor mange ord folk som oss ville skrive på spørsmål før du trykker på Enter.
>> Så i dette tilfellet her har de erklært funksjonen main som tar en rekke argumenter,
0 eller flere argumenter.
De vet ikke på forhånd hvor mange det er,
så det er bevisst noe nummer på innsiden av disse hakeparenteser.
Men det faktum at de klammer er der forteller datamaskinen,
forventer en matrise.
Argv er bare stenografi notasjon for argument vektor.
En vektor er en fancy måte å si array,
og matrise er en fancy måte å si en liste eller samling.
Så dette betyr bare at hvis du skriver viktigste som dette
i stedet for som hvordan vi har gjort det for de siste par ukene,
programmet har nå muligheten til å akseptere kommandolinjeargumenter
slik at ingen lenger har du å skrive mario og trykk Enter,
skriver inn et tall for hvor mange blokker høyt du vil at pyramiden skal være,
trykk Enter igjen.
Vi trenger ikke engang å bruke GetString lenger eller GetInt eller GetFloat for den saks skyld.
Vi kan bare forvente at brukeren skriver disse ordene på prompten
akkurat som forfatterne av Clang besluttet det ville være en virkelig irriterende program
om å kompilere koden du først skrev klang, trykk Enter,
da vi sa til brukeren, vennligst skriv inn navnet på filen du ønsker å kompilere,
så vi skriver i mario.c og trykk Enter.
Men det er akkurat det vi har gjort til våre brukere de siste par ukene.
Vi bruker GetString og vi vente til programmet kjører for å be dem om innspill.
Som ikke lenger trenger å være tilfelle.
>> Så i dette eksempelet her, vi har nå streng argv,
og dette er også en overforenkling,
trening hjul som vil ganske snart komme.
Dette er mer riktig måte å skrive denne alternative deklarering av hoved
fordi det viser seg at det vi holder ringer streng faktisk har en stjerne,
en stjerne i sin faktiske definisjonen, men dette bare ser komplisert ut,
det er forvirrende i begynnelsen, så vi forenkle ved å bare lage et synonym slags
i CS50 bibliotek som kartlegger char * til dette mer brukervennlig ord streng.
>> Så la oss faktisk prøve dette da. La meg gå videre og åpne opp gedit her.
La meg gå videre og åpne argv av en.
Dette programmet tilsynelatende skriver argumentene, men i engelsk vilkår,
ved å se på denne koden, hva dette gjør mer spesifikt?
Hvis jeg skriver i kommandoen a.out foo bar, blir det trykt i min svart og hvitt vindu?
A.out foo bar, Enter.
Gå fremover. Ja. >> [Uhørlig student respons]
Bra. Så a.out, ny linje, foo, ny linje, bar, ny linje.
Hvorfor er dette? Vi kan absolutt bekrefte på bare et øyeblikk.
Dette er en slags lun linje med kode.
Det skrives bare en ny linje bare for å gjøre ting penere på skjermen.
Dette er en sløyfe som er iterating fra 0 på opptil argc,
og dette er inkrementering på hver iterasjon + +.
Så dette er nå si ut en streng, som underforstått av denne% s.
Argv [i] er ganske mye den samme ideen fra forrige eksempel.
Vi pleide å kalle den variable s, nå det heter, vilkårlig, argv.
Dette betyr ut i. argument som ble skrevet på kommandolinjen,
og deretter etter alt dette er gjort, bare for godt mål ut en ny linje.
>> Så la oss se dette. La meg åpne opp terminal-vinduet.
La meg kompilere argv på 1, og nå la meg kjøre argv på 1, Enter. Hmm. Okay.
La oss kjøre foo bar. Interessant. Baz.
Og hvis du noen gang har lurt på hvorfor jeg skriver dette,
dette er bare også en dum datamaskin science konvensjonen.
Verden trenger ofte bare verbale plassholdere for ord.
Så hvis du ønsker å snakke om noen generiske streng,
dataforskere bare en tendens til å si Foo når de trenger et tilfeldig ord,
så de sier bar hvis de trenger en andre tilfeldig ord,
så de sier baz hvis de trenger en tredje ordet, så de sier qux hvis de trenger en fjerde ordet,
og så er det en stor religiøs debatt på nettet om hva som kommer etter qux,
slik at du kan google det å finne ut hva den andre vilkårlig ord bør være.
Men disse har ingen mening overhodet,
om foo bar, hvis du Google det, som ikke har mening,
som er en del av den etymology her.
>> Så alt dette gjør så skriver en av disse strengene per linje.
Så hvis jeg i stedet, men ønsket å få en litt mer avansert,
anta at jeg ikke ønsker å skrive ut hver streng per linje;
Jeg ønsket å skrive ut hver karakter fra hver streng per linje.
Hvordan kunne jeg i stedet gjøre det?
Hva trenger jeg å endre om dette programmet hvis jeg ønsker å skrive ut ikke hvert ord
men jeg ønsker å skrive ut hvert ord bokstav for bokstav for bokstav,
så det neste ordet bokstav for bokstav for bokstav?
Hvordan kombinerer vi gjør disse ideene så langt? Ja.
[Student]% c. >> Greit. Så vi et sted trenger en% c.
Bra, fordi jeg ikke vil skrive ut hele strenger, jeg ønsker å skrive ut tegn. Hva annet?
>> [Uhørlig student respons] >> Interessant.
Så vi trenger en slags ny dimensjon her nå
fordi tenke på argv som en matrise, men det er en rekke strenger.
Men som av, liker, 15 minutter siden, hva er en streng? Det er en rekke tegn.
Så egentlig er argv en rekke en rekke tegn,
en rekke matriser av tegn.
Så det viser seg at vi kan bruke bare mer hakeparentes merknader. Så la oss gjøre dette.
I toppen av denne sløyfen på linje 19, kommer jeg til å veksle fra jeg opp til argc,
men da jeg kommer til å gjøre dette:
for - ikke jeg kan bruke jeg nå.
Jeg trenger en annen variabel fordi jeg ønsker å iterere over ordene
men da også over bokstavene i ordene
så jeg slags har en vertikal akse og en horisontal akse, liksom konseptuelt.
Så int j får 0, så jeg ønsker å gjøre j så lenge j er mindre enn - og jeg vil rydde opp i en bit.
Hvordan iterere jeg over bokstavene i en streng? Vi gjorde dette for et øyeblikk siden.
Strlen av argv [i]. Bra.
Og igjen, jeg gjør litt ineffektivitet her ved ikke å skape n eller hva,
men vi vil komme tilbake til det.
>> Så nå j + +. Nå må jeg rykke nærmere her.
Hva gjør jeg nå ønsker å skrive ut på hver iterasjon?
[Uhørlig student respons] >> Så [i] vil gi meg ordet.
[I] [j], liksom som en matrise.
De av dere med matte-y bakgrunn,
Vi er liksom indeksering enda dypere inn i denne matrisen eller denne rekke matriser,
Dette 2-dimensjonale struktur.
Så la oss nå se hva som skjer her. La meg åpne opp min større terminal-vinduet.
La meg kjøre gjøre av argv av en.
Og jeg har skrudd opp her, som er en god leksjon fordi jeg også glemte å gjøre dette.
Implisitt erklære C biblioteket funksjon 'strlen' med type 'usignert -
Jeg vet ikke engang hva resten av det betyr, men jeg har sett dette før,
implisitt sier.
Når vi ser denne feilen, hva dette vanligvis bety?
>> [Uhørlig student respons] >> Jeg glemte et bibliotek opp toppen. Men vent litt.
Vanligvis har jeg skrudd opp fordi jeg glemte CS50 biblioteket, men det er det.
Vanligvis har jeg skrudd opp fordi jeg har glemt standard I / O.
Og ærlig talt, jeg vet ikke engang trenger dette. Vi bruker ikke GetString dag.
Så hva er det jeg mangler?
Det er et annet bibliotek som nå må vi bruke noen ganger kalt string.h,
og dette er bare enda en bibliotek som har flere funksjoner som ikke er i standard I / O.
>> Så la oss gå tilbake til min store terminal vinduet.
Okay. Nå, for faen, jeg tror jeg var galt. Jeg var bruker CS50 biblioteket.
Så vi kan fikse dette på en av to måter.
Vi kan ta trening hjul av akkurat nå og bare gjøre dette,
eller la oss slags holde at forenkling bare for nå, lime dette tilbake i,
løse det problemet, og nå går tilbake til terminalen vinduet.
Så for å være klar, i CS50 biblioteket ikke bare fungerer,
det er også nøkkelordet strengen, som er grunnen til at feilen skjedde.
>> Så her går vi. Jeg fikset begge bibliotek problemer. Enter. Bra.
Argv av 1, foo bar, Enter. Utmerket.
Så nå har vi hver bokstav i hvert ord skrives en per linje,
som ikke gjør for en meget interessant program,
men varsel nå har vi evnen til ikke bare gjentar over ord
men også over enkelte bokstaver i ord, som lyder svært kjent
til selv de enkleste programmene som scrambling bokstaver i en streng som dette.
La oss gå videre og ta vår 5-minutters pause her.
Og når vi kommer tilbake, vil vi begynne å snakke om effektivitet
som vi kan gjøre disse tingene bedre.
>> OK. Vi er tilbake.
Takket være en av våre TFS som spiller mye bananagrams,
vi faktisk har en hel haug med tegn med oss ​​her i dag
fysisk inkarnert med disse små plast stykker,
og la meg foreslå at denne blank hvit skifer her representerer RAM i datamaskinen min -
laptop, desktop, uansett - og det ser ut som mye av det
fordi hvis vi begynner hakke opp dette RAM i små byte-størrelse stykker,
la oss vilkårlig si at noe som størrelse og at uklare representerer -
der vi går, og la oss zoome ut litt her -
la oss si noe som størrelse representerer en enkelt byte.
Så vi kan faktisk passe en hel haug med byte eller tegn innsiden av dette minnet,
som foreslått av den relative størrelsen her.
>> Så antar nå at målet er å allokere minne for en streng.
Hvordan virker dette faktisk fungerer?
I programmene vi har skrevet, har vi vanligvis brukt GetString,
men nå, tydelig, det er denne andre kanalen via hvor vi kan få brukerens input i argv
via kommandolinjeargumenter.
Men hva som egentlig skjer under panseret?
Det viser seg hvis vi kaller - la oss bla tilbake til GetString - funksjonen GetString
i CS50 biblioteket, blir brukeren bedt om en streng,
brukeren skriver i noen ord - la oss kalle det HELLO.
Og vi har sagt i de siste par ukene at avkastningen verdien av GetString
er faktisk en streng, som ordet HELLO.
>> Men hva er GetString egentlig gjør?
Mens brukeren skriver i HELLO, Enter, blir GetString finne ut,
okay, hvor mange tegn er dette? Dette er H-E-L-L-O.
Så det må fordele, må den be operativsystemet - Linux i dette tilfellet -
i minst 5 byte for å lagre HELLO.
Og hva det deretter fortsetter å gjøre når det kommer tilbake de 5 bytes fra operativsystemet
er å legge ut HELLO rygg mot rygg til rygg mot rygg.
Og så hva som egentlig returnert fra GetString er en del av data som ser ut som dette.
Men dette er litt unøyaktig fordi det viser seg at det ikke er så enkelt
som bare lagring HELLO i datamaskinens minne
fordi anta at mitt program som jeg skriver i C så kaller GetString igjen,
og det neste ordet brukeren skriver i er BYE, BYE.
Vel, jeg må passe på at ordet BYE sted i minnet.
Jeg kan ikke clobber HELLO.
For eksempel, jeg ønsker ikke at datamaskinen skal bare begynne overskriving som dette
den opprinnelige ordet fordi jeg kan fortsatt bruke ordet HELLO i en variabel
et annet sted i programmet mitt.
>> Så B-Y-E har å ende opp et annet sted i minnet.
Men konvensjonen er typisk at neste strengen du tildele
sannsynligvis, men ikke alltid, kommer til å ende opp på neste tilgjengelige minneområde.
Og hvis jeg ikke har bedt operativsystemet for noe minne
siden sist gang jeg ringte GetString, oddsen er ordet BYE
kommer til å ende opp rett etter ordet HELLO i minnet.
Men på dette punktet kan du kanskje se hvor et potensielt problem oppstår.
Fordi de neste mengder minne, de neste byte som var bare gratis -
ren hvit skifer - i datamaskinens minne var rett ved siden HELLO,
det føles som den første strengen jeg ba om kan plutselig nå endre
fordi jeg har egentlig endret det til HELLOBYE
i stedet for en eller annen måte demarcing starten av BYE og slutten av HELLO.
>> Så det viser seg at det som egentlig skjer under panseret,
som du kanskje har observert i online referanser eller § eller bøker
eller ikke i det hele tatt bare ennå, er at det faktisk er en bevisst avgrensning
mellom ord i datamaskinens minne.
Og faktisk, i dette tilfellet her, snarere enn bare sette BYE rett ved siden HELLO,
stedet, settes datamaskinen en spesiell karakter, den spesielle null karakter, så å si,
som er representert med en markør med backslash 0.
Så lang historie kort, husker at tegnene er representert i ASCII.
ASCII er bare en mapping mellom tall og bokstaver,
og de fleste av disse brevene begynner omtrent 65 for kapital A,
men det viser seg at du kan sikkert representere tallet 0 som et heltall eller binær,
og det viser seg at verden bestemt for lenge, lenge siden, "Vet du hva?"
"La oss reserve nummer 0 som ikke representerer noen tegn på tastaturet -
"Ingen brev, ingen tall, ingen tegnsetting. 0 er spesiell."
"Det kommer til å bli den spesielle null karakter, og vi kommer til å skrive det som \ 0".
Forskjellen er hvis vi bare skrev 0, 0 er et tegn.
Husker at det ASCII-koder for 0, for en, for 2, for 3
fordi tegnet 0, er forskjellig fra tallet 0.
Og du kan se at hvis du ser tilbake fra uke 1 når vi først snakket om ASCII,
0 og 1 og 2 og 3 hele veien opp til 9 hadde sine egne ASCII-koder.
De er ikke tilfeldigvis 0 til 9. De er svært forskjellige.
Så 0 betyr bare "jeg er spesiell", og de \ 0 betyr, bokstavelig talt, "Jeg er ikke den 0 karakter."
"Jeg er denne spesielle verdi, null karakter."
Så jeg faktisk trenger en annen av disse siden jeg ikke kan gjøre den samme feilen to ganger.
>> Så etter ordet BYE vi også kommer til å trenge en av disse nulltegn.
La meg ta min penn her og la meg raskt trekke et \ 0
slik at etter at jeg har bedt operativsystemet for to strenger
via GetString etterfulgt av et annet kall til GetString,
dette er hva som faktisk er i minnet.
Så når jeg kommer tilbake en streng, jeg virkelig får tilbake at,
og når jeg får den neste strengen, jeg virkelig å få tilbake det.
Så dette ber spørsmålet, strlen, først av alt, hva skal det tilbake?
Når jeg ringer strlen på strengen s og s var ordet HELLO at brukeren har skrevet inn,
hva gjorde vi selvsagt si lengden på HELLO var for noen minutter siden?
Det var 5, ikke sant? H-E-L-L-O. Og det er faktisk hvordan strlen fungerer.
Den returnerer hva et normalt menneske ville forvente lengden på en streng å være.
Men i virkeligheten, hvor stor er rekke tegn som er lagring hallo?
Det er faktisk seks.
Så strlen nevner ikke det faktum for deg.
Men under panseret datamaskinen faktisk bruker 6 bytes til å lagre en 5-brev ord,
og dette gjelder uansett hvor lenge ordet er.
Det er alltid kommer til å være en spesiell null terminerende tegnet på slutten av strengen
å demarc sin totale lengde.
>> Så hvis du er nå den som implementerer strlen 20, 30 år siden,
hvordan du går om å implementere strlen seg selv?
Vi tar for gitt at den eksisterer, akkurat som vi tar for gitt at printf eksisterer,
men hvis HELLO er ordet i spørsmålet
og hva jeg har i minnet er noe som ser ut som dette,
hvis du måtte reimplement strlen fordi du ble bedt om å
eller fordi, ærlig, visste du ikke strlen eksisterte -
du måtte rulle dette på egen hånd - hvordan kunne du gjennomføre strlen
når det gis noe som ser ut som dette?
Nå som vi vet en streng er en matrise, kan vi iterere over hver av de enkelte tegn
bruke noe sånt som - la oss prøve å gjøre dette på fly.
>> La meg gå inn i apparatet. La meg lage en ny fil, strlen.c.
La meg gå videre nå og tar med stdio.h slik at vi har tilgang til printf.
La meg gjøre int main (void). Oh. Jeg skal bare gjøre dette på min egen for nå da. [Humrer]
Takk.
Dette er hva jeg gjør. OK.
Så før jeg skrudde på skjermen, jeg skrev alt dette.
Og nå hva jeg skal gjøre er følgende:
printf ("Gi meg en streng:")
Det er bare LUN instruksjoner.
Nå la meg gjøre string s = GetString.
Jeg har allerede trenger å gjøre en endring nå.
Jeg bruker CS50 bibliotek plutselig, så la meg gå videre og skrive cs50.h.
Og nå la oss gjøre dette: printf ("Lengden er:% d, strlen [s] -
og jeg er ikke ferdig ennå. Hva annet har jeg å legge til dette programmet?
>> [Student] string.h. >> String.h.
Så for nå bruker vi strlen, så la oss sørge for at kompilatoren vet hvor det er,
så litt sunn fornuft sjekk.
Jeg får en streng på linje 8, og i linje 9 Jeg skriver ut sin lengde med% d.
Så la oss gå videre og åpne opp dette.
Vi har å gjøre strlen - sammenstiller greit -
strlen - la meg zoome inn - Enter, H-E-L-L-O, Enter. Lengden er 5.
>> Ok, så strlen ser ut til å fungere, men verden kjente det.
Så la oss nå implementere strlen oss som følger.
La meg ta dette biblioteket unna.
Vi har ikke lenger tilgang til string.h fordi jeg ikke engang at det eksisterte.
Men det er greit fordi jeg kan implementere strlen selv
og må ta det en streng som heter input,
og nå trenger jeg å finne ut lengden på denne strengen.
Så hvordan kan jeg gjøre dette?
Hva hvis jeg gjør - la oss se hvordan du gjør dette - Hva vil du gjøre?
>> [Uhørlig student respons] >> Ok.
Så vi kan gjøre dette på en rekke måter. La meg prøve å ta denne tilnærmingen.
La meg gi meg en int variabel i, så jeg starter på 0.
Og la meg si dette: mens input [i] er ikke lik hva? \ 0.
Så det viser seg, som med tilfellet med alle chars når du skriver dem bokstavelig talt i et program,
du må bruke enkle anførselstegn, ikke doble anførselstegn.
Så hvis jeg skulle skrive bokstaven a, vil jeg gjøre det, bokstav b, vil jeg gjøre det.
Dette, derimot, ville være en streng, ikke en individuell karakter.
>> Så jeg vil \ 0 bokstavelig. Hva ønsker jeg å gjøre i denne loop?
Egentlig trenger jeg en annen variabel, så int lengde får 0.
Selv om du ikke var sikker på hvorfor vi startet den måten vi gjorde,
nå som vi kommer ned denne veien, hva jeg ønsker å gjøre på linje 9?
lengde + + og deretter ned her på linje 10, retur lengde.
Så hvordan er strlen implementert?
Det er faktisk gjennomført trolig som dette.
Kanskje den personen brukte en for loop, kanskje en gjøre mens loop - hvem vet?
Vi hadde virkelig nødt til å se under panseret på selve kildekoden
i noen fil som heter string.c sannsynligvis.
>> Men her la oss tenke på hva jeg gjør.
Jeg erklærer en variabel kalt i, sette den lik 0.
Jeg så erklære en annen variabel kalt lengde, sette den lik 0.
Så jeg sier, mens ith karakter i inngangen er ikke lik den spesielle null karakter, \ 0,
inkrementere lengden.
Men så snart ed karakter er denne spesielle karakter, hva skjer med loop?
Det kortslutninger. Den stopper, noe som betyr at vi da umiddelbart returnere lengde.
>> Så hvis jeg ikke rotet opp, la oss gå videre og gå tilbake til min terminal-vinduet.
La meg rekompilere. Og jeg ikke skru opp.
Uforenlig redeklarasjon av biblioteket funksjon strlen.
Så jeg prøvde å få altfor smart for mitt eget beste her.
Kompilatoren vet faktisk at det er en funksjon kalt strlen
selv om vi ikke har inkludert biblioteket. Det er fint. Uansett.
Vi bare kommer til å samarbeide da. La oss endre navnet på denne lengden.
La meg endre bruken av det til lengde her, og dette vil gjøre Clang lykkeligere.
Som en side, fordi noen av disse funksjonene er så darn felles -
strlen, prinf - de faktisk har slags spesiell status.
Og så Clang vet bare noe spesielt med dem.
Det er ikke alltid tilfelle med de fleste funksjoner, så det er derfor vi fikk skreket til.
>> La meg prøve igjen. Heldigvis, det virket den gangen.
Så nå la meg kjøre min egen strlen program.
Gi meg en streng: H-E-L-L-O, Enter. Og jeg har skrudd opp.
Hvorfor? >> [Uhørlig student respons] >> Nettopp.
Så jeg har meg selv her en veldig pen uendelig loop
fordi selv om jeg økes lengden på hver iterasjon,
hva jeg åpenbart ikke gjør? Jeg er ikke økes i. Okay. Lett å fikse. Ja?
Okay. Nei Nå vil vi kjøre på kant med noen andre vanlige feil der jeg trenger parentes.
Og ærlig, er denne koden begynner å se stygt,
så vi får ta en stikke på rengjøring dette opp i et øyeblikk.
Men nå er jeg økes både lengde og jeg.
Ærlig, jeg ser allerede en mulighet for forbedring her, men vi vil komme tilbake til det.
>> Så nå la oss bare sørge for at vi er minst gjør fremskritt.
Dette har skjedd til noen av dere, og jeg forsømmer å nevne dette på forhånd.
Når du har ulykke av et scenario som dette, hvordan kan du fikse dette
kort med å starte apparatet eller datamaskinen eller lukke vinduet?
Det er faktisk lett.
Kontroll C vil sende denne lille gulrot symbol C, og som bare avslutter de fleste programmer.
Hvis du har en virkelig dårlig uendelig loop som er skrive ting uendelig mange ganger,
noen ganger må du kanskje treffe kontroll C tusen ganger for å gjøre det faktisk høre det.
Så bare innser nå fordi jeg ikke skrive noe, det var ganske enkelt.
Og teknisk, en gang er nok, men jeg bli utålmodig og jeg vanligvis treffer det at mange ganger.
>> Så strlen. Gi meg en streng: HELLO. Er det kommer til å fungere denne gangen?
Okay. En annen vanlig feil. Nødt til å rekompilere.
Som var tilsiktet, at en. OK.
Så strlen, H-E-L-L-O, Enter. Utmerket.
Så vi har nå en strlen til 5.
Så vi har bokstavelig talt reimplemented at hjulet.
Så nå la oss rydde opp dette fordi dette ikke gjør meg imponert
med utformingen av koden min.
Hva kan vi tydelig eliminere i dette programmet for å rydde opp?
[Uhørlig student respons] >> Ja. Bokstavelig talt, vi behandler i og lengde likt.
Så hvorfor ikke vi bare få smart og si mens lengden?
Snarere, la oss bare kalle det lengde til å begynne med, initialisere den til 0
fordi standard strengen har ingen lengde inntil vi finner ut hva det er.
>> Nå gjør vi dette, og nå er dette en ganske elegant program.
En variabel. Jeg ryddet det opp, strammet opp.
Så nå la oss gå tilbake til min terminal-vinduet. La oss gå videre og kjøre denne.
Gjør strlen. Ser bra ut. Kjør strlen igjen, Enter.
Gi meg en streng: HELLO, Enter. Og det ser ut til å virke som 5.
Nå, for å være klar, hvis jeg ikke hadde skrevet, for eksempel, HELLO i en streng
og deretter BYE i en annen, kan vi sikkert ha flere ord.
Hvis uttrykket jeg faktisk ønsket å skrive var ikke HELLO men, for eksempel,
HELLO WORLD, legg merke til at det vi ikke ville ha er denne situasjonen her, ikke sant?
Som skulle tilsi at det er to strenger.
Du sikkert kan ha plass bar tegn, så hvis vi faktisk skrevet i en lengre setning
som HELLO WORLD, hva vi ville virkelig ha i minnet
ser litt noe sånt der.
>> OK. Eventuelle spørsmål da om representasjon her av strenger?
Nei? OK.
Så jeg sa tidligere at ringer strlen igjen og igjen bevisst sånn
sannsynligvis ikke den beste ideen fordi du kommer til å gjøre en hel masse arbeid
igjen og igjen og igjen.
Ja, hva slags arbeid som er nødvendig for å finne ut lengden på en streng, tilsynelatende?
Du må starte på begynnelsen og deretter se, se, se, se, se
til du endelig se den spesielle karakter, noe som medførte, ah, nå vet jeg lengden.
Så tidligere da vi hadde strlen bli kalt igjen og igjen og igjen,
grunnen til at jeg foreslo det var litt dumt er fordi igjen, ser at strengen sånn.
Det kommer ikke til å endres hver gang du iterate gjennom noen loop,
så du gjør unødig arbeid.
Samtidig bør du vet, som en side, at kompilatorer som Clang disse dager
har blitt utviklet over mange år,
og kompilatoren forfattere, programmerere, er ganske smart.
Og så viser det seg at klang og andre kompilatorer kan faktisk finne ut at,
okay, ja, du skrev strlen i din tilstand,
som betyr teknisk at vi vil kalle det igjen og igjen og igjen.
Men smarte kompilatorer kan faktisk optimalisere slike dårlig brukeropplevelse beslutninger
ut av koden din til oppreisning ting.
>> Så bare innse at noen ganger kompilatoren er smartere enn oss
og vil slags skjule våre egne feil.
Men sikkert når det kommer til oppgavesett og lignende,
gjør være å tenke på de fundamentalt feilaktige design beslutninger
potensielt av den enkle grunn at vi skulle gjøre mye mer arbeid
enn vi faktisk har å gjøre. Men hvor mye mer arbeid?
I tilfelle av HELLO WORLD, la oss begynne å generalisere størrelsen på dette problemet.
Hva er lengden på problemet eller størrelsen av problemet
når ordet brukeren skrev inn er HELLO?
Det er tydeligvis 5, kanskje 6. Pluss eller minus 1. Uansett.
Det er så nær vi vil bare kalle det 5.
>> Så hva er størrelsen på problemet her når du prøver å finne ut lengden på HELLO?
Det er 1, 2, 3, 4, 5, og kanskje 6 for det siste tegnet, men la generalisere at som n.
Så n, bare variabelen n, er det dataforskere ville vanligvis bruker
å beskrive størrelsen på et problem, og problemet på hånden er hvor lenge er HELLO?
Hvor mye tid tar strlen?
Det tar på rekkefølgen av n trinn, hvor hvert trinn innebærer se et tegn,
se på et tegn, se på et tegn.
Og vi hadde denne diskusjonen en stund tilbake, antall operasjoner noe tar.
Den aller første dagen i klassen vi hadde alle klønete stå opp,
og deretter begynte alle sammenkobling av med hverandre
for å faktisk telle ideelt hvor mange som var i rommet.
Og vi gjorde også en annen ting der hvis jeg i stedet gjorde det den gamle skolen måte
av bare starter 1, 2, 3, 4, 5, 6 og så videre,
det også, var størrelsen på det problemet av størrelse n. Det var n mennesker i rommet.
Men jeg kunne fremskynde det opp, ikke sant? Klasse på skolen stil jeg kunne begynne å telle i 2s.
2, 4, 6, 8, 10, 12. Og det føles så mye raskere, og faktisk er det.
Det er bokstavelig talt dobbelt så fort, men igjen, hvis en annen 400 mennesker gikk inn i dette rommet
alt på en gang, ville disse algoritmene ta ytterligere 400 eller kanskje 200 trinnene.
>> Men derimot, hvis vi virkelig bli smart og vi i stedet har alle dere telle selv,
husker hvordan det algoritmen fungerte.
Du alle sto opp. La meg spole frem til dette.
Du alle sto opp, du koblet sammen, så halvparten av dere satte seg,
halvparten av dere satte seg, satte halvparten av dere ned,
og på hver iterasjon av denne sløyfen fra uke 0, halvert vi problemet på hånden
og gikk til n / 2, så n / 4, deretter n / 8.
Og konsekvensen av det er at hvis en annen 400 personer gå inn i rommet, ingen big deal,
det vil ta oss en runde til, ikke 400 flere runder, ikke 200 flere runder.
Og så historien vi fortalte en stund tilbake måtte gjøre litt noe med dette.
Denne røde linjen her er lineær, er det rett, og det er merket som n
fordi som størrelsen av et problem vokser,
hvis algoritme eller program som du løse det tar n skritt,
vi kan plotte det som en rett linje hvor det tar mer tid jo større størrelsen av problemet.
Og twosies tilnærming, telling 2, 4, 6, 8, fremdeles en rett linje, bare litt bedre.
Det tar litt mindre tid, så den gule linjen er under den røde linjen punkt for punkt.
>> Men enda bedre var denne hellige gral av det vi kalte logaritmisk tid
der selv om vi igjen doble antall personer i rommet,
Vi dobler størrelsen på den telefonen bok fra første kursdag,
ingen big deal, det tar 1 mer siden tåre, tar en mer sitte ned
for å løse et problem som er dobbelt så stort.
Og så samtalen vi nå får å begynne å ha er
hvordan gjør vi faktisk løse problemer effektivt
hvis vi betrakter den enkleste av problemer som dette?
Anta at vi har åtte dører bak som er noen tall,
og hver av disse tallene ikke er sortert på noen måte,
de er bare tilfeldige heltall bak disse dørene,
og vi stiller spørsmålet hvordan du går om å finne nummeret - hvem vet -
7 bak disse dørene?
Hva ville du, et menneske, gjør for å finne meg nummer 7
hvis igjen hver av disse er dører og for å se en verdi du må åpne en dør?
Hva ville din algoritmen være kanskje?
>> [Uhørlig student respons] >> Så starter med venstre og åpne en dør, åpne en dør, åpner en dør.
Og i verste fall er hvor lang tid det kommer til å ta oss med å finne nummer 7?
Og igjen, de er ikke sortert, så det er ikke så lett som, vel, jeg kommer til å åpne den 7. døren.
Det kan ta oss, maksimalt, 8 trinn.
I verste fall er 7 tilfeldig på slutten av linjen av dører,
så vi må kanskje prøve alle n dører.
Så igjen her, synes vi å ha en lineær algoritme.
Faktisk, vi gjorde dette bare et par år siden.
En av dine forgjengere ble utfordret med nettopp dette
der vi ikke har en digital versjon, vi i stedet hadde en tavle
med noen biter av papir på den.
Og det jeg trodde jeg ville gjøre er å ta en rask titt tilbake på hvordan dette gikk,
en av de beste og kanskje mest pinlige muligheter på scenen
å ha en demonstrasjon her på Sanders.
Vi hadde 2 rader med tall.
Vi kommer bare til å se på hva som skjer her med Sean for toppen av disse radene.
Med mindre ingen noensinne igjen frivillige i CS50,
Vi hadde Sean velsignelse for å holde dette på kameraet,
så han vet at hundrevis av mennesker har vært å se dette nå i år.
Men Sean gjorde en fantastisk jobb - eller gjorde han? - På å faktisk finne oss et bestemt nummer.
>> Så la oss se hvordan han løste denne algoritmen slik at vi vil gjenoppta denne samtalen før lenge
hvordan finner vi ting effektivt.
[Malan på video] Jeg har gjemt bak disse dørene nummer 7,
men gjemt bort i noen av disse dørene også er andre ikke-negative tall,
og målet ditt er å tenke på dette øverste raden med tall som bare en matrise
eller bare en sekvens av biter av papir med tall bak dem,
og målet ditt er, bare å bruke den øverste rekke her, finne meg nummer 7.
Og vi deretter gå til kritikk hvordan du går om å gjøre det. >> Greit.
[Malan] Finn oss nummer 7, takk.
[Latter]
[Malan] Nei [latter]
5, 19, 13, [latter]. Det er ikke et lurespørsmål.
1.
[Latter]
På dette punktet poengsummen din er ikke veldig bra, så du kan like godt holde det gående. [Latter]
3.
Gå på. Oppriktig, jeg kan ikke hjelpe, men lurer på hva du tenker selv om. [Latter]
Bare den øverste raden, slik at du har tre venstre. Så finn me 7.
[Studenter mumlet]
[Malan] 17.
[Studenter mumlet]
[Malan] 7! [Applaus]
>> Så på onsdag vil vi dykke inn i dette og mer sofistikerte algoritmer for å finne ting.
For nå skal vi la deg med Sean og se deg på onsdag.
[CS50.TV]