[Powered by Google Translate] [SECCIÓ 5: menys còmoda]
[Nate Hardison, Harvard University]
[Aquesta és CS50.] [CS50.TV]
Així que benvinguts de nou, nois.
Benvinguts a la secció 5.
En aquest punt, després d'haver completat prova 0 i després d'haver vist com s'ha fet,
esperem que pugui sentir realment bé perquè jo estava molt impressionat pels resultats en aquesta secció.
Per als nostres espectadors en línia, hem tingut un parell de preguntes
sobre els dos últims problemes en el conjunt de problemes - o en l'examen, més aviat.
Així que anem a repassar aquells molt ràpid perquè tothom veu el que va passar
i la forma d'anar a través de la solució real en lloc de només visualització de la pròpia solució.
Anem a anar en l'últim parell de problemes molt ràpid, 32 i 33.
Així, de nou, de manera que els espectadors en línia es pot veure això.
>> Si gira al seu problema 32, que és a la pàgina 13,
13 dels 16, 32 problema té a veure amb swaps.
Es tractava de canvi de dos nombres enters.
És el problema que havíem anat un parell de vegades a la conferència.
I aquí, el que estem demanant que facin és una empremta de memòria ràpida.
Per omplir els valors de les variables com ho són a la pila
ja que el codi passa a través d'aquesta funció swap.
En particular, el que estem veient - Vaig a posar això iPad baix -
en particular, el que estem veient és la línia número 6 aquí.
I és el número 6 per només contigüitat amb el problema anterior.
El que vull fer és mostrar l'etiqueta o l'estat de la memòria
com ho és en el moment quan s'executa aquest número de línia 6,
que és efectivament un retorn de la nostra funció d'intercanvi aquí.
Si ens desplacem fins aquí, hem vist que les adreces de tot en la memòria s'ha proveït per a nosaltres.
Això és molt clau, anem a tornar-hi en un moment.
I després aquí baix a la part inferior hi ha un diagrama de poca memòria que ens referirem.
De fet, he fet això en el meu iPad.
Així que vaig a alternar anada i tornada entre l'iPad i el codi aquesta penes per la referència.
>> Anem a començar. En primer lloc, ens centrarem en les dues primeres línies del principal aquí.
Per començar, anem a inicialitzar x i i a 1 a 2.
Així que tenim dues variables senceres, són alhora serà col · locat a la pila.
Posarem un 1 i un 2 en les mateixes.
Així que si li dono la volta al meu iPad, és d'esperar, anem a veure -
Apple TV mirroring, i aquí anem. Bé.
Així que si li dono la volta al meu iPad,
Vull inicialitzar x i i a 1 a 2.
Ho fem simplement escrivint un 1 a la casella x
i un 2 a la casella marcada i. Bastant simple.
Així que ara anem a tornar a l'ordinador portàtil, a veure què passa després.
Així que aquesta següent línia és on les coses es posen difícils.
Passem la direcció de x i de i la direcció com els paràmetres a i b per a la funció swap.
La direcció de x i la direcció de i són coses que no podem calcular
sense fer referència a aquests punts de bala just aquí baix.
I per sort, els dos primers punts de la bala dir-nos exactament quines són les respostes.
La direcció de xa la memòria és 10, i la direcció de i en la memòria és 14.
Així que aquests són els valors que es transmeten en com A i B a la part alta a la nostra funció d'intercanvi.
Així que de nou, tornant al nostre diagrama, puc escriure un 10 en una
i un 14 en b.
Ara, aquest punt és on es procedeix amb el canvi.
Així que voltejar de nou a l'ordinador portàtil de nou,
veiem que la forma en què l'intercanvi d'obres és de desfer abans la referència a i emmagatzemar el resultat en tmp.
De manera que l'operador d'indirecció diu: "Hey. Tractar el contingut d'una variable com una adreça.
Anar al que està emmagatzemat en aquesta direcció, i el carregarà. "
Què càrrega de la variable que serà emmagatzemat en la nostra variable tmp.
Moure d'una tirada de nou a la iPad.
Si abordarem 10, se sap que 10 és la direcció x varible
perquè ens van dir que el nostre punt de bala que la direcció de xa la memòria és de 10.
Així que podem anar-hi, obtenir el valor de la mateixa, que és 1, com podem veure en el nostre iPad,
i carregar això en tmp.
Un cop més, això no és el contingut final.
Anem a caminar a través i arribarem al nostre estat final del programa al final.
Però en aquest moment, tenim el valor emmagatzemat en una tmp.
>> I hi ha una pregunta ràpida per aquí.
[Alexander] És l'operador d'indirecció - això és només el dret asterisc al principi de la variable?
Sí >>. De manera que l'operador d'indirecció, ja que voltejar cap enrere per al nostre portàtil, una vegada més,
és aquest estel just al davant.
En aquest sentit, és - el que contrasta amb l'operador de multiplicació
que requereix dues coses: l'operador d'indirecció és un operador unari.
Només s'aplica a un valor en lloc d'un operador binari,
on s'aplica a dos valors diferents.
Així que això és el que passa en aquesta línia.
Carreguem el valor 1 i s'emmagatzema en la variable temporal sencer.
La següent línia, s'emmagatzema el contingut de b en -
o, més aviat, guardem els continguts que s'assenyalen a b en el lloc on una està apuntant.
Si analitzem aquest de dreta a esquerra, anem a eliminar la referència b,
abordarem 14, anem a agafar el sencer que està allà,
i després anirem a l'adreça 10,
i anem a llançar el resultat d'eliminar la referència de b en aquest espai.
Voltejant al nostre iPad, on podem fer això una mica més concret,
pot ser que ajudi si escric nombres en totes les direccions aquí.
Així que sabem que en i, estem en la direcció 14, x és a la direcció 10.
Quan vam començar a b, b dereference, prendrem el valor 2.
Agafem aquest valor pel fet que és el valor que viu a la direcció 14.
I anem a posar-lo en la variable que viu a la direcció 10,
que hi és, que correspon als nostres variable x.
Així que podem fer una mica de sobreescriure aquí
on ens desfem de la nostra 1 i en el seu lloc escriure un 2.
Així que tot està bé i és bo en el món, tot i que hem x sobrescrits ara.
Hem emmagatzemat antic valor de xa la variable tmp.
Així podem completar l'intercanvi amb la línia següent.
Moure d'una tirada de nou al nostre portàtil.
Ara tot el que queda és prendre el contingut de la nostra variable sencera temporal
i els emmagatzema en la variable que viu en la direcció que b està sostenint.
Així que anem a eliminar la referència b eficaç per aconseguir l'accés a la variable
és a dir, en la direcció que b té en ell,
i anem a ficar el valor que està duent a terme tmp-hi.
Voltejar de nou a l'iPad un cop més.
Puc esborrar aquest valor aquí, 2,
i en el seu lloc anem a copiar la dreta 1 en ell.
A continuació, la següent línia que s'executa, per descomptat -
si tirem de nou a l'ordinador portàtil - és aquest el punt 6,
que és el punt en què volíem tenir el nostre diagrama omplerta completament.
Així que voltejar de nou a l'iPad un cop més, només perquè pugui veure el diagrama complet,
es pot veure que tenim un 10 en una, un 14 en b, a 1 en tmp, un 2 en x, i un 1 en i.
Hi ha alguna pregunta sobre això?
Això té més sentit, d'haver caminat a través d'ell?
Fer menys sentit? Esperem que no. Bé.
>> Els punters són un tema molt delicat.
Un dels nois amb els que treballem té una dita molt comú:
"Per entendre els punters, primer cal entendre punters".
El que crec que és molt cert. No obstant això, pren algun temps per acostumar-se a ella.
Dibuix moltes fotos, sorteig de diagrames de memòria com aquesta són molt útils,
i després de caminar a través de l'exemple després exemple després exemple,
que començarà a tenir sentit una mica més i una mica més de sentit i una mica més de sentit.
Finalment, un dia, tindràs tot completament dominat.
Qualsevol pregunta abans de passar al següent problema? Està bé.
Així que donar la volta de nou a l'ordinador portàtil.
El següent problema que tenim és el problema número 33 a l'arxiu I / O.
Zoom sobre això una mica.
Problema 33 - Sí?
>> [Daniel] Acabo de tenir una pregunta ràpida. Aquesta estrella, o l'asterisc,
es diu eliminació de referències quan s'utilitza un asterisc abans.
Com es diu quan s'utilitza el signe & abans?
>> El signe & abans és l'operador de direcció.
Així que passarem de tornada.
Oops. Estic en la manera de zoom, així que no pot desplaçar-se.
Si ens fixem en el codi molt ràpid aquí,
de nou, el mateix succeïa.
Si ens fixem en el codi aquí mateix, en aquesta línia on fem la crida a canviar,
el signe és només dir "obtenir l'adreça on viu la variable x."
Quan el compilador compila el codi,
ha de físicament marcar un lloc en la memòria per totes les seves variables per viure.
I així, el que el compilador pot fer una vegada que compila tot,
ho sap "Oh, vaig posar x en la direcció 10. Poso i en la direcció 14."
A continuació, pot omplir aquests valors per a vostè.
Així que vostè pot - pot Passan això i pass & i endins també.
Aquests nois obtenir l'adreça, sinó que també, quan es passa a la funció d'intercanvi,
aquest tipus d'informació, aquesta * int aquí, li diu al compilador,
"Està bé, estarem interpretant aquesta direcció com una adreça d'una variable sencera".
Com una direcció d'un sencer, que és diferent de la direcció d'una variable de caràcter
perquè un int ocupa, en una màquina de 32-bit, presa fins a 4 bytes d'espai,
mentre que un personatge només ocupa 1 byte d'espai.
Així que és important saber també el que és - el que viu, quin tipus de valor
viu en la direcció que he passat polz
O l'adreça que vostè està tractant.
D'aquesta manera, vostè sap quants bytes d'informació per carregar realitat de la memòria RAM.
I llavors, sí, aquest operador per desfer referències, com si estiguessis demanant,
va i s'accedeix a la informació en una direcció particular.
Pel que diu, amb aquesta variable a aquí, tractar els continguts d'una com direcció,
anar a aquesta direcció, i extreure, carregar en el processador, la càrrega en un registre
els valors reals o dels continguts que viuen en aquest domicili.
Una mica més preguntes? Aquestes són bones preguntes.
És un munt de noves tecnologies també.
És també una espècie de funky, i veient * i en diferents llocs.
>> Està bé.
Així que tornem al problema de 33 anys, presentar I / O.
Aquest va ser un d'aquells problemes que crec que un parell de coses van succeir.
Un, que és un tema bastant nou.
Es va presentar molt aviat abans de la prova,
i llavors jo crec que va ser alguna cosa així com un d'aquests problemes verbals de matemàtiques
on et donen un munt d'informació, però en realitat no acaben sobre d'haver d'usar un munt d'ell.
La primera part d'aquest problema es descriu què és un arxiu CSV.
Ara, un arxiu CSV, d'acord amb la descripció, és un arxiu de valors separats per comes.
La raó que aquests són per res interessant, i la raó per la qual mai els utilitzen,
És a dir, perquè, quants de vosaltres heu utilitzat alguna vegada coses com Excel?
Figura majoria de vostès, probablement, o va a utilitzar en algun moment de la seva vida.
Anem a fer servir alguna cosa com Excel.
Per tal d'obtenir les dades d'un full de càlcul d'Excel o fer qualsevol tipus de tractament efectuat amb ella,
si vols escriure un programa en C o programa en Python, un programa Java,
per fer front a les dades que hagi emmagatzemat aquí,
una de les formes més comunes per treure'l està en un arxiu CSV.
I vostè pot obrir Excel i quan vas a l'opció 'Guardar com' diàleg,
vostè pot sortir un fitxer CSV real.
>> És útil saber com tractar amb aquestes coses.
La forma en que funciona és que és similar a - Vull dir, és essencialment imitant un full de càlcul,
on, com veiem aquí, a la part més a l'esquerra,
tenim tots els cognoms.
Així que tenim Malan, a continuació, Hardison, i després Bowden, MacWilliam, i després Chan.
Tots els cognoms. I després una coma separa els cognoms dels noms de pila.
David, Nate, Rob, Tommy, i Zamyla.
Sempre barrejar Robby i Tom.
I llavors, per fi, la tercera columna és l'adreça de correu electrònic.
Quan entenguis això, la resta del programa és bastant senzill d'implementar.
El que hem fet per tal d'imitar l'estructura mateixa del nostre programa en C
és que hem utilitzat una estructura.
Anem a començar a jugar amb ells una mica més també.
Els vam veure en el primer trosset petit problema en el conjunt 3, quan es tractava dels diccionaris.
Però aquesta estructura personal emmagatzema un cognom, un nom, i un correu electrònic.
Igual que el nostre arxiu CSV estava emmagatzemant.
Així que això és només la conversió d'un format a un altre.
Hem de convertir, en aquest cas, una estructura personal en una línia,
una línia separada per comes, així com així.
Això té sentit? Vostès han pres l'examen,
així que m'imagino que si més no han tingut temps per pensar en això.
>> En la funció de contractació, el problema demana que prenguem en - ens tornarem a ampliar això una mica mica -
prendre en una estructura de personal, una estructura de personal, amb el nom de s,
i afegir el seu contingut al nostre arxiu staff.csv.
Resulta que aquest és bastant senzill d'utilitzar.
Anem a classe de jugar amb aquestes funcions una mica més avui en dia.
Però en aquest cas, la funció fprintf és realment la clau.
Així que amb fprintf, podem imprimir, igual que vostès han estat usant printf aquest terme sencer.
Pot printf una línia en un arxiu.
Així que en lloc de només fer l'anomenada printf habitual on se li dóna la cadena de format
i després canvia totes les variables amb els següents arguments,
amb fprintf, el seu primer argument és en canvi el fitxer que voleu escriure.
Si anéssim a veure això en l'aparell, per exemple, l'home fprintf,
podem veure la diferència entre printf i fprintf.
Vaig a ampliar aquí una mica.
Així que amb printf, li donem una cadena de format i, a continuació els arguments posteriors
són totes les variables per al reemplaçament o substitució en la nostra cadena de format.
Mentre que amb fprintf, el primer argument és precisament aquesta * arxiu anomenat un rierol.
>> Tornant aquí als nostres contractes de lloguer,
ja tenim el nostre flux * arxiu obert per a nosaltres.
Això és el primer que fa aquesta línia, s'obre l'arxiu staff.csv,
l'obre en mode append, i és tot el que ens queda per fer
escriure l'estructura de la plantilla a l'arxiu.
I, anem a veure, em vols fer servir l'iPad?
Vaig a utilitzar l'iPad. Tenim buit - Posarem això sobre la taula perquè podia escriure una mica millor -
anul · lar el lloguer i que es necessita en un argument, una estructura de personal anomenat s.
Got nostres claus, tenim el nostre arxiu anomenat * arxiu,
tenim la nostra línia fopen donat a nosaltres,
i jo només vaig a escriure en forma de punts, ja que ja és al demanava.
I després, en la nostra línia següent, farem una crida a fprintf
i passarem a l'arxiu que voleu imprimir,
i després el nostre format de cadena, que -
Vaig a deixar que vostès em diuen el que sembla.
I tu, Stella? Saps que la primera part de la cadena de format s'assembla?
[Stella] Jo no estic segur. >> No dubti a preguntar Jimmy.
Sap vostè, Jimmy?
[Jimmy] Podria ser només passat? No. No estic del tot segur.
>> Okay. Com va, algú obtenir aquesta correcte en l'examen?
No Està bé.
Resulta que aquí l'únic que hem de fer és que volem que cada part de la nostra estructura de personal
per ser imprès com una cadena en el nostre arxiu.
Ens limitem a fer servir el personatge de substitució de cadenes en tres ocasions diferents, perquè tenim un cognom
seguit de coma, després d'un primer nom seguit d'una coma,
i, finalment, l'adreça de correu electrònic que és seguit - que no és
muntar a la meva pantalla - però és seguit per un caràcter de nova línia.
Així que vaig a escriure just allà baix.
I després, després de la nostra cadena de format,
només tenim les substitucions, que s'accedeix mitjançant la notació de punts
que vam veure en el butlletí de problemes 3.
Podem utilitzar s.last, s.first i s.email
per substituir en aquests tres valors en la nostra cadena de format.
Llavors, com et va anar? Té sentit?
Sí? No? Possiblement? Bé.
>> L'última cosa que fem després d'haver imprès i després que hem obert el nostre arxiu:
cada vegada que hem obert un arxiu, sempre hem de recordar per tancar-la.
Perquè si no anem a acabar la filtració de la memòria,
utilitzant fins descriptors de fitxer.
Així que per tancar, que funcionen fem servir? Daniel?
[Daniel] fclose? >> Fclose, exactament.
Així que l'última part d'aquest problema consistia a tancar correctament l'arxiu, utilitzant la funció fclose,
que només s'assembla a això.
No està boig.
Cool.
Així que això és problema 33 en el concurs.
Tindrem arxiu definitivament més I / O ve.
Anem a fer una mica més en la conferència d'avui, oa la secció d'avui,
perquè això és el que constituirà la major part d'aquest conjunt de processadors proper.
Anem a passar de la prova en aquest punt. Sí?
>> [Charlotte]] Per què fclose (arxiu) en comptes de fclose (staff.csv)?
>> Ah. Perquè resulta que - de manera que la pregunta, que és un gran,
Per això, quan escrivim fclose, estem escrivint fclose (arxiu) estrella variable
en contraposició al nom d'arxiu, staff.csv? És això correcte? Si.
Així que anem a fer una ullada. Si torno al meu ordinador portàtil,
i donem una ullada a la funció fclose.
Així que la funció fclose tanca un rierol i que es necessita en el punter al flux que volem tancar,
en comparació amb el nom real de l'arxiu que voleu tancar.
I és que darrere de les escenes, quan vostè fa una crida a fopen,
quan s'obre un arxiu, en realitat estàs assignació de memòria per emmagatzemar la informació sobre l'arxiu.
Així que tens punter de l'arxiu que conté informació sobre l'arxiu,
tal com està obert, la seva mida, en la qual es troben actualment a l'arxiu,
de manera que vostè pot fer que la lectura i l'escriptura trucades a aquest lloc en particular dins de l'arxiu.
S'acaba de tancar el punter en lloc de tancar el nom del fitxer.
>> Sí? [Daniel] Així que per tal d'utilitzar de lloguer, diria vostè - com obtenir l'entrada de l'usuari?
Té fprintf actuar com GetString en el sentit que només vaig a esperar que l'entrada de l'usuari
i li demanarà que escrigui això - o esperar que escrigui aquestes tres coses?
O és necessari utilitzar una mica d'implementar lloguer?
Sí >>. Així que no estem - la pregunta va ser, com fem perquè la entrada de l'usuari
amb la finalitat d'implementar lloguer? I el que tenim aquí és el llamador de lloguer,
aprovada en aquesta estructura personal amb totes les dades emmagatzemades en l'estructura ja.
Així fprintf és capaç d'escriure només les dades directament a l'arxiu.
No cal esperar que l'usuari.
L'usuari ja està donat per l'entrada correctament posant en aquesta estructura de personal.
I les coses, és clar, es trencaria si algun dels punters eren nul · les,
pel que desplaçar-se de nou fins aquí i ens fixem en la nostra estructura.
Tenim string cognom, nom, adreça de correu electrònic cadena.
Ara sabem que tots els que en realitat, sota el capó, són variables char *.
Que pot o no pot estar apuntant a null.
Poden estar apuntant a la memòria en el munt,
tal memòria a la pila.
Realment no ho sé, però, si algun d'aquests indicadors és nul o no vàlid
que que definitivament va a estavellar nostra funció de contractació.
Això era una cosa que estava una mica més enllà de l'abast de l'examen.
No haurem de preocupar per això.
Gran. Bé. Així de passar de la prova.
>> Anem a tancar aquest tipus, i veurem pset 4.
Així que si vostès mirar les especificacions conjunt de processadors, una vegada que es pot accedir, cs50.net/quizzes,
anirem a través d'alguns dels problemes de la secció actual.
Estic desplaçament cap avall - secció de preguntes comença a la tercera pàgina de l'especificació de conjunt de processadors.
I el primer que demana per anar a veure el curt a la reorientació i canonades.
La qual cosa era una mena de fresc a curt, et mostra alguns trucs nous, frescos línia de comandes que es poden utilitzar.
I després tenim algunes preguntes per a vostè també.
Aquesta primera pregunta sobre els rierols, perquè printf escriu per defecte,
quin tipus de tocat una mica fa un moment.
Aquesta fprintf que estàvem discutint pren en un rierol arxiu * com a argument.
fclose presa en un flux d'arxiu *, així,
i el valor retornat per fopen li dóna un corrent * arxiu també.
La raó per la qual no hem vist abans, quan els hem tractat amb printf
és perquè printf té una seqüència.
I el corrent de defecte als que s'escriu
podràs conèixer en el curt termini.
Així que definitivament fer una ullada.
>> A la secció d'avui, parlarem una mica sobre GDB,
ja que com més familiaritzat estigui amb ell, la pràctica més que s'obté amb ella,
el millor preparat estarà per caçar als insectes en realitat en el seu propi codi.
Això accelera el procés de depuració tremendament.
Així mitjançant l'ús de printf, cada vegada que fas això has de tornar a compilar el codi,
has de córrer de nou, de vegades cal moure l'anomenada printf voltant,
comentar codi, només es necessita un temps.
El nostre objectiu és intentar convèncer-los que amb GDB, vostè pot essencialment
printf res en qualsevol punt del seu codi i vostè no haurà de tornar a compilar.
Vostè mai ha d'iniciar i mantenir endevinant on printf següent.
El primer que ha de fer és copiar aquesta línia i obtenir el codi de secció de la web.
Estic copiant aquesta línia de codi que diu: "http://cdn.cs50.net wget".
Jo ho vaig a copiar.
Vaig a anar al meu aparell, allunyar perquè pugui veure el que estic fent,
enganxar-lo allà, i quan premeu la tecla Enter, aquesta comanda wget literalment és un web aconseguir-ho.
Va a baixar l'arxiu fora de la Internet,
i va a guardar en el directori actual.
Ara bé, si enumero meu directori actual es pot veure que tinc l'arxiu section5.zip bé aquí.
La manera de tractar amb aquest tipus és que descomprimir,
que es pot fer en la línia d'ordres, igual que aquest.
Section5.zip.
Això ho descomprimeixi, creu la carpeta per a mi,
inflar tot el contingut, els va posar allà.
Així que ara puc anar al meu secció 5 directori amb la comanda cd.
Netejar la pantalla amb clara. Així que netejar la pantalla.
Ara tinc un terminal net i agradable d'utilitzar.
>> Ara bé, si una llista de tots els arxius que apareixen en aquest directori,
veieu que jo tinc quatre arxius: buggy1, buggy2, buggy3 i buggy4.
També tinc els arxius de C corresponent ..
No anem a mirar els arxius. C per ara.
En el seu lloc, anem a usar quan obrim GDB.
Ens hem mantingut al voltant del que tenim accés al codi font real quan estem utilitzant GDB,
però l'objectiu d'aquesta part de la secció és jugar una mica amb GDB
i veure com podem utilitzar-lo per esbrinar el que va malament amb cada un d'aquests quatre programes amb errors.
Així que només anem a pel quart molt ràpid,
i jo vaig a demanar a algú per executar un dels programes amb errors,
i després anirem com un grup a través del BGF, i veurem què podem fer per vos d'aquestes programes,
o identificar almenys el que va malament en cadascun d'ells.
Començarem per aquí amb Daniel. ¿Va a córrer buggy1? Anem a veure què passa.
[Daniel] Es diu que hi ha un error d'aplicació. Sí >>. Exactament.
Així que si em quedo buggy1, em surt un error seg.
En aquest punt, jo podria anar i obrir buggy1.c,
intentar esbrinar el que va malament,
però una de les coses més desagradables sobre aquest error d'errors seg
és que no et diu en quina línia del programa de les coses realment va sortir malament i es va trencar.
D'alguna manera hem de mirar el codi
i esbrinar mitjançant conjectures i comprovar o printf per veure el que va malament.
Una de les millors coses sobre GDB és que és molt, molt fàcil
per esbrinar la línia a la qual el programa es bloqueja.
Està totalment digne d'ell per usar-lo, encara que només sigui per això.
Així que per arrencar GDB, tipus I GDB, i després li dono la ruta d'accés a l'arxiu executable que voleu executar.
Aquí estic escrivint gdb ./buggy1.
Premeu Enter. Em dóna tota aquesta informació de drets d'autor,
i aquí vostè veurà aquesta línia que diu: "Lectura de símbols / home /
jharvard/section5/buggy1 ".
I si tot va bé, veuràs que imprimeixi un missatge semblant a aquest.
Es va a llegir els símbols, que dirà "Estic llegint els símbols del seu arxiu executable"
i llavors tindrà aquest "fet" missatge aquí.
Si veus alguna altra variant d'això, o veure que no podia trobar els símbols
o alguna cosa per l'estil, el que vol dir és que vostè no hagi compilat el seu executable correctament.
En compilar programes per funcionar amb GDB, hem de fer servir aquesta bandera especialment g,
i això es fa per defecte compilant els programes, simplement teclejant make
o fer buggy o fer recuperar, res d'això.
Però si estàs compilant manualment amb Clang, llavors vostè haurà d'anar i que inclouen-g.
>> En aquest punt, ara que tenim el nostre GDB del sistema,
que és molt simple d'executar el programa.
Podem escriure run, o simplement podem escriure r.
La majoria de les ordres de GDB pot ser abreujat.
En general, a només una o unes lletres d'un parell, la qual cosa és bastant agradable.
Així Saad, si escriu r i premeu Enter, què passa?
[Saad] Tinc SIGSEGV, fallada de segmentació, i llavors tot aquest galimaties.
Sí >>.
Com estem veient a la pantalla en aquest moment, i com va dir Saad,
quan teclegem carrera o r i premeu la tecla Enter, se segueix rebent el mateix error seg.
Així que usant GDB no resol el nostre problema.
Però ens dóna un argot, i resulta que aquesta argot
en realitat ens diu on està succeint.
Per analitzar això una mica, aquest primer bit és la funció en què tot va malament.
Hi ha un __ strcmp_sse4_2, i ens diu que està succeint en aquest arxiu
anomenat sysdeps/i386, tot això, de nou, una mena de desastre - però la línia 254.
Això és una mica difícil d'analitzar. Normalment, quan veus coses com aquesta,
que vol dir que està seg amb error en una de les biblioteques del sistema.
Així que alguna cosa a veure amb strcmp. Heu vist strcmp abans.
No està boig, però això vol dir que strcmp està trencat o hi ha problema amb strcmp?
Què et sembla, Alejandro?
[Alexander] És que - és de 254 la línia? I - no el binari, però no és els seus sostres,
i després hi ha un altre idioma per a cada funció. Això és 254 en aquesta funció, o -?
>> És la línia 254. Sembla que en aquest arxiu. S, de manera que és probable que el codi assemblador.
>> No obstant això, crec que la cosa més urgent és, perquè hem aconseguit una fallada seg,
i sembla com si vingués de la funció strcmp,
Què implica això, doncs, que strcmp es trenca?
No hauria, esperançat. Així que només perquè vostè té una fallada de segmentació
en una de les funcions del sistema, en general això significa que no l'han anomenat correctament.
La forma més ràpida que es pot fer per esbrinar el que realment està passant
quan veus alguna cosa boig com aquest, cada vegada que vegi una falla seg,
especialment si vostè té un programa que utilitzeu més que principal,
és utilitzar un backtrace.
I abreujar backtrace per escrit bt, en oposició a la paraula traça completa.
Però Charlotte, el que passa quan s'escriu bt i premeu Enter?
[Charlotte] Em mostra dues línies, la línia 0 i la línia 1.
Sí >>. Així que la línia 0 i la línia 1.
Aquests són els marcs de pila reals que estan actualment en joc quan el programa es va estavellar.
A partir del marc superior, el marc 0, i anar a la part inferior més, que és el quadre 1.
El nostre marc superior és el marc strcmp.
Vostè pot pensar en això com similar al problema que estàvem fent en el concurs amb els punters,
on havíem intercanviar marc de pila a la part superior del marc de pila principal,
i vam tenir les variables que s'utilitzen swaps a la part superior de les variables que s'utilitzen principal.
Aquí el nostre accident ha passat a la nostra funció strcmp, que va ser cridat per la nostra funció principal,
i backtrace ens està donant no només les funcions en què les coses fallides,
però també se'ns diu que tot va ser anomenat.
Així que si em desplaço en una mica més a la dreta,
podem veure que sí, que estàvem en la línia 254 de aquest arxiu strcmp-sse4.s.
Però la trucada es va fer en buggy1.c, línia 6.
Així que això vol dir que podem fer - és simplement podem anar a veure cap a fora i veure el que estava passant
en buggy1.c, línia 6.
Un cop més, hi ha un parell de maneres de fer això. Un és per sortir del GDB
o té el seu codi obert en una altra finestra i referència creuada.
Això, en si mateix, és bastant útil perquè ara si vostè està en horari d'oficina
i vostè té una falla seg i la seva TF està preguntant on tot es trencava,
vostè pot dir: "Oh, la línia 6. No sé el que està passant,
però alguna cosa en la línia 6 està causant el meu programa de trencar. "
L'altra manera de fer-ho és que vostè pot utilitat junt anomenat de llista a GDB.
També es pot abreujar amb l.
Així que si arribem a l, què fem aquí?
Tenim un munt de coses rares.
Aquest és el codi assemblador real
que és en strcmp_sse4_2.
Això sembla una mica funky,
i la raó per la qual estem rebent és perquè en aquest moment,
GDB ens té en el marc 0.
>> Així que en qualsevol moment ens fixem en les variables, en qualsevol moment ens fixem en el codi font,
estem veient el codi font que pertany al marc de pila que es troba,
Així que per aconseguir alguna cosa significativa, hem de
passar a un marc de pila que té més sentit.
En aquest cas, el marc de pila principal tindria sentit una mica més,
perquè aquest era realment el codi que nosaltres escrivim.
No és el codi strcmp.
La manera com es pot moure entre els quadres, en aquest cas, perquè tenim dos,
tenim 0 i 1,
ho fa amb l'amunt i avall els comandaments.
Si em mut a un fotograma,
ara estic en el marc de la pila principal.
Em puc moure cap avall per tornar a on estava,
pujar de nou, tornar a baixar, i pujar de nou.
Si tornes a fer el seu programa en GDB, s'obté un accident, s'obté la traça de depuració,
i es veu que està en algun arxiu que vostè no sap el que està passant.
Intenta llista, el codi no es veu familiar,
fer una ullada als seus quadres i esbrinar on es troba.
Vostè està probablement en el marc de pila incorrecta.
O almenys vostè està en un marc de pila que no és la que realment es pot depurar.
Ara que estem en el marc de pila apropiat, estem en el principal,
Ara podem usar la comanda list per esbrinar el que la línia era.
I vostè pot veure, sinó que ho va imprimir per a nosaltres aquí.
Però podem arribar a una llista de tot el mateix, i la llista ens dóna aquesta impressió agradable
del codi font real que està passant aquí.
>> En particular, podem mirar la línia 6.
Podem veure el que està passant aquí.
I sembla que estem fent una comparació de cadenes
entre la cadena "CS50" i roques argv [1].
Una mica d'això es caigui.
Així Missy, té vostè alguna idea sobre el que podria estar passant aquí?
[Missy] No sé per què està fallant. >> No sé per què està trencant?
Jimmy, alguna idea?
[Jimmy] No estic del tot segur, però comparar l'última vegada que es va utilitzar cadena,
o strcmp, teníem com tres casos diferents sota el mateix.
No teníem un ==, no crec que, just en aquesta primera línia.
En el seu lloc, es va dividir en tres, i un era == 0,
un era <0, crec, i un va ser> 0.
Així que potser alguna cosa així? Sí >>. Així que aquesta qüestió
que estem fent la comparació correcta?
Stella? Alguna idea?
[Stella] Jo no estic segur. >> No estic segur. Daniel? Pensaments? Bé.
Resulta que el que està succeint aquí és quan ens trobem amb el programa
i ens van donar la culpa segons, en executar el programa per primera vegada, Daniel,
se li donen els arguments de línia de comandaments?
[Daniel] >> No No En aquest cas, quin és el valor de argv [1]?
>> No hi ha cap valor. >> Dret.
Bé, no hi ha cap valor de cadena apropiat.
Però hi ha alguna cosa de valor. Quin és el valor que s'emmagatzema allà?
>> Un valor escombraries? >> És un valor escombraries o, en aquest cas,
al final de la matriu argv sempre acaba amb null.
Llavors, què he guardat allà és nul.
L'altra manera de resoldre això, en lloc de pensar a través,
és tractar d'imprimir.
Aquí és on m'estava dient que l'ús de GDB és gran,
perquè vostè pot imprimir totes les variables, tots els valors que desitja
utilitat junt pràctic-excel · lent p.
Així La introducció p i aleshores creeu el valor d'una variable o el nom d'una variable,
dir, argc, veig que argc és 1.
Si voleu imprimir argv [0], puc fer-ho sense més.
I com hem vist, argv [0] és sempre el nom del seu programa,
sempre el nom de l'executable.
Aquí es veu que té el nom de ruta complet.
També pot imprimir argv [1] i veure què passa.
>> Aquí tenim a aquest tipus de valor místic.
Vam aconseguir aquest 0x0.
Recordeu que al començament de la legislatura, quan parlem de números hexadecimals?
O que pocs dubtes al final del conjunt de processadors 0 sobre com representar 50 a hexadecimal?
La forma d'escriure els nombres hexadecimals de CS, no només a nosaltres mateixos confondre
amb nombres decimals, és que sempre els prefix 0x.
Així que aquest prefix 0x sempre només significa interpretar el següent nombre com un nombre hexadecimal,
no com una cadena, no com un nombre decimal, no com un nombre binari.
Com que el nombre 5-0 és un nombre vàlid en hexadecimal.
I és un nombre en decimal, 50.
Així que això és només la manera com eliminar l'ambigüitat.
Així 0x0 1/2 hexadecimal 0, la qual cosa també és decimal, binari 0 0.
És només el valor 0.
Resulta que això és el nul és, en realitat, en la memòria.
Null és 0.
Aquí, l'element emmagatzemat a argv [1] és nul.
Així que estem tractant de comparar el nostre "CS50 rocks" cadena en una cadena nul · la.
Així desreferencia nul, intenteu accedir a les coses en null,
els que normalment es produirà algun tipus de fallada de segmentació o d'altres coses dolentes succeeixin.
I resulta que strcmp no comprova per veure
si vostè ha passat en un valor que és nul.
Per contra, només segueix endavant, tracta de fer el seu,
i si s faltes, segons faltes, i és el teu problema. Has d'anar a arreglar.
Molt ràpidament, com podem solucionar aquest problema? Charlotte?
[Charlotte] Pot comprovar si l'ús.
Així que si argv [1] és nul, == 0, llavors tornar 1, o alguna cosa així [inintel · ligible].
Sí >>. Així que aquesta és una bona manera de fer-ho, com podem comprovar,
el valor que està a punt de passar a strcmp, argv [1], l'hi nul?
Si és nul, llavors podem dir que està bé, avortar.
>> Una forma més comú de fer això és utilitzar el valor de argc.
Es pot veure aquí al començament de principal,
ometem que la primera prova que solem fer quan fem servir arguments de línia de comandes,
que és per provar si el nostre valor argc és el que esperem.
En aquest cas, estem esperant almenys dos arguments,
el nom del programa més l'altre.
Com que estem a punt de fer servir el argument aquí.
Així que tenir algun tipus de prova per endavant, abans de la nostra anomenada strcmp
que les proves siguin o no argv és almenys 2, també podria fer el mateix tipus de coses.
Podem veure si això funciona, executeu el programa de nou.
Sempre es pot reiniciar el programa dins de GDB, que és realment bonica.
Es pot córrer, i quan es passa arguments al seu programa,
les passades en quan es diu a córrer, no en arrencar GDB.
D'aquesta manera vostè pot mantenir invocant el programa amb arguments diferents cada vegada.
Correu de tal manera o una altra, puc escriure r, i ja veurem què passa si escrivim "hola".
Sempre se't preguntarà si vols començar des del principi una altra vegada.
En general, el vull començar des del principi una altra vegada.
I en aquest punt, es reinicia de nou, imprimeix
el programa que s'està executant, buggy1, amb l'argument hola,
i imprimeix aquesta sortida estàndard, sinó que diu: "Vostè rep una D," cara trista.
Però no ens falla seg. Es va dir que el procés va acabar normalment.
Així que es veu molt bé.
No més culpa s, ho hem fet passat,
pel que sembla que era de fet l'error seg culpa que ens donarien.
Per desgràcia, ens diu que estem arribant a una D.
>> Podem tornar enrere i mirar el codi i veure el que estava passant allà
per esbrinar el que era - per què se'ns està dient que tenim una D.
Anem a veure, aquí s'està printf dient que tens una D.
Si teclegem llista, que es mantingui la llista escrivint, segueix iterant a través del seu programa,
pel que vaig a mostrar les primeres línies del seu programa.
A continuació, li mostrarem les pròximes línies, i el tros següent, i el següent tros.
I seguirà tractant de baixar.
I ara anem a arribar a "alinear el número 16 està fora d'abast".
Com que només compta amb 15 línies.
Si s'arriba a aquest punt, i la seva pregunta: "Què he de fer?" pot utilitzar la comanda help.
Utilitzeu ajudar i després donar-li el nom d'una comanda.
I veus el BGF ens dóna tot aquest tipus de coses.
Diu: "Sense un argument, una llista de deu línies o més, després de tot el llistat anterior.
Llista - llista les deu línies abans - "
Així que anem a tractar d'usar menys de la llista.
I que les llistes de les 10 línies anteriors, es pot jugar amb la llista una mica.
Vostè pot fer la llista, llista -, fins i tot es pot donar una llista d'un nombre, com llista 8,
i que va a enumerar les 10 línies al voltant de la línia 8.
I vostè pot veure el que està passant aquí és que tens un simple if else.
Si escriu en CS50 roques, imprimeix "S'obté un excel · lent"
En cas contrari, s'imprimeix "S'obté una D."
Bummer ciutat. Està bé. Sí?
>> [Daniel] Així que quan he intentat fer CS50 roques sense les cometes,
diu "Et donen una D."
Necessitava les cometes per a aconseguir que funcioni, per què és això?
Sí >>. Resulta que quan - aquest és altra dada poc divertit -
en executar el programa, si l'executem i ens escriu en CS50 roques,
igual que Daniel estava dient que ell va fer, i prémer Intro,
encara diu que obtenim una D.
I la pregunta és, per què és això?
I resulta que tant el nostre terminal i GDB analitzar aquests com dos arguments diferents.
Perquè quan hi ha un espai, que està implicat com
el primer argument acabar, el següent argument està a punt de començar.
La forma de combinar els dos en, o perdó, en un argument,
és l'ús de les cometes.
Així que ara, si ho posem entre cometes i d'executar, obtenim una A.
Així que per recapitular, sense cometes, CS50 i les roques són interpretades com dos arguments diferents.
Amb les cotitzacions, s'analitza com un argument complet.
>> Podem veure això amb un punt d'interrupció.
Fins ara hem estat funcionant el nostre programa, i que s'està executant s'ha
fins que el seg falles o èxits d'un error
o fins que hagi sortit i tot ha estat totalment bé.
Això no és necessàriament el més útil, perquè de vegades
té un error en el seu programa, però no és la causa d'un error de segmentació.
No és la causa del seu programa per aturar o alguna cosa així.
La manera d'aconseguir GDB per aturar el seu programa en un punt particular
és establir un punt d'interrupció.
Vostè pot fer això mitjançant l'establiment d'un punt d'interrupció en un nom de funció
o pot establir un punt d'interrupció en una línia de codi en particular.
M'agradaria establir punts d'interrupció en els noms de funcions, perquè - fàcil de recordar,
i si realment entrar i canviar el codi font una mica,
llavors el punt d'interrupció que s'allotja en el mateix lloc dins del seu codi.
Mentre que si vostè està utilitzant els nombres de línia, i canviar els números de línia
perquè afegeix o elimina una mica de codi, a continuació, els seus punts de ruptura estan totalment fotut.
Una de les coses més comuns que fan és establir un punt d'interrupció en la funció principal.
Sovint vaig a arrencar GDB, vaig a escriure b principal, premeu Enter, i que va a establir un punt d'interrupció
la funció principal, que simplement diu, "Pausa el programa tan bon punt comenceu a córrer"
i d'aquesta manera, quan executo el meu programa amb, diguem, CS50 roques com dos arguments
i premeu la tecla Enter, es torna a la funció principal i s'atura just a la primera línia,
just abans que avalua la funció strcmp.
>> Des que estic en pausa, ara puc començar netejant voltant i veure el que està passant
amb totes les diferents variables que es passen en el meu programa.
Aquí puc imprimir argc i veure el que està passant.
Veure que argc és 3, perquè té 3 valors diferents en el mateix.
Té el nom del programa, té el primer argument i el segon argument.
Podem imprimir els en mirar argv [0], argv [1], i argv [2].
Així que ara també es pot veure per què aquesta crida strcmp va a fracassar,
perquè veus que es divideix el CS50 i les roques en dos arguments diferents.
En aquest punt, un cop has arribat a un punt d'interrupció, pot continuar amb el pas a través del seu programa
línia per línia, en lloc de començar el seu programa de nou.
Així que si vostè no vol començar el seu programa de nou i seguim des d'aquí,
pot utilitzar la comanda continue i continuarà executar el programa fins al final.
Igual que ho va fer aquí.
No obstant això, si es em reinicia el programa, CS50 roques, colpeja el meu punt d'interrupció una vegada més,
i aquesta vegada, si no vol només ha d'anar tot el camí a través de la resta del programa,
Puc utilitzar la comanda següent, que jo també abreujar amb núm.
I això passarà per la línia de programa en línia.
Així que vostè pot veure les coses com executar, a mesura que canvien les variables, com les coses s'actualitza.
La qual cosa és bastant agradable.
El millor és un altre lloc de repetir el mateix ordre una vegada i una i altra vegada,
si prem Intro - així que aquí veus que ho has escrit en qualsevol cosa -
si tan sols prémer Intro, es repetirà la comanda anterior,
o la comanda GDB anterior que acabo de posar polz
Puc mantenir prement Enter i seguirà pas a pas a través del meu codi línia per línia.
M'agradaria animar a vostès per anar a veure els programes amb errors d'altres també.
No tenim temps per passar per tots ells avui a la secció.
El codi font està aquí, així que vostè pot tipus de veure el que està passant
darrere de les escenes si et quedes realment encallat,
però almenys, només la pràctica d'arrencar GDB,
l'execució del programa fins que es trenca en vostè,
obtenir la traça de depuració, esbrinar quina és la funció de l'accident es trobava,
el que estava en línia, la impressió d'alguns valors de les variables,
només pel que tenir una idea d'això, perquè el que realment l'ajudarà en el futur.
En aquest punt, deixarem de GDB, el que ho fa deixar d'usar o simplement q.
Si el programa està en el mitjà de funcionament encara, i no ha sortit,
sempre li preguntarà: "Estàs segur que realment vol deixar de fumar?"
Només pot colpejar si.
>> Ara anem a veure el problema que tenim, que és el programa de gat.
Si vostè mira el curt a la reorientació i canonades, veuràs que Tommy utilitza aquest programa
que bàsicament imprimeix tota la sortida d'un arxiu a la pantalla.
Així que si em quedo gat, en realitat és un programa integrat en l'aparell,
i si tens Mac pots fer-ho a la teva Mac també, si vostè obre terminal.
I nosaltres - gat, diguem, cp.c, i premeu Enter.
El que això va fer, si ens desplacem una mica i veure on ens trobem amb la línia,
o on va executar la comanda cat, que literalment acaba d'imprimir el contingut de cp.c a la nostra pantalla.
Podem d'executar i es pot posar en diversos arxius junts.
Així que vostè pot fer cp.c gat, i llavors també podem concatenar l'arxiu Cat.C,
que és el programa que anem a escriure,
i que voleu imprimir dos arxius d'esquena a la nostra pantalla.
Així que si ens desplacem una mica, veiem que quan ens trobem amb aquest cp.c gat, Cat.C,
primer es imprimeix l'arxiu cp, i després a continuació, s'imprimeix l'arxiu Cat.C aquí baix.
Anem a utilitzar això per obtenir només els peus mullats.
Juga una mica amb la impressió simple a la terminal, veure com funciona.
Si vostès obren amb gedit Cat.C, premeu Enter,
vostè pot veure el programa que estem a punt d'escriure.
Hem inclòs aquesta placa de la caldera agradable, així que no ha de gastar temps escrivint tot el que fos.
També vam comprovar que el nombre d'arguments passats polz
Ens imprimir cap missatge d'ús agradable.
>> Aquest és el tipus de coses que, de nou, igual que hem estat parlant,
és gairebé com la memòria muscular.
Només recordi de seguir fent el mateix tipus de coses
i sempre imprimint algun tipus de missatge útil
de manera que la gent sap com executar el seu programa.
Amb gat, és bastant simple, només anirem a través de tots els diferents arguments
que es van passar al nostre programa, i anem a imprimir
seu contingut cap a fora a la pantalla d'una en una.
Per imprimir arxius fora de la pantalla, farem alguna cosa molt semblant
al que vam fer al final de la prova.
Al final de la prova, que contracten programa, vam haver d'obrir un arxiu,
i després vam haver imprimir-hi.
En aquest cas, anem a obrir un arxiu, i anem a llegir d'ella en el seu lloc.
A continuació, anem a imprimir, en lloc de a un arxiu, anem a imprimir a la pantalla.
Així que la impressió a la pantalla que tots hem fet abans amb printf.
Així que no és massa boig.
Però la lectura d'un arxiu és una mica estrany.
Anem a passar per això una mica a la vegada.
Si vostès tornar a aquest últim problema al quiz, problema 33,
la primera línia que farem aquí, en obrir l'arxiu, és molt semblant al que vam fer allà.
Llavors, Stella, què significa aquesta mirada línia com, quan obrim un arxiu?
[Stella] Capital * Arxiu, Arxiu - >> Bé. >> - És igual a fopen. >> Yup.
Que en aquest cas és? Està en el comentari.
>> Està en el comentari? argv [i] i el r?
>> Exactament. Molt bé. Així que Stella és totalment correcte.
Això és el que la línia s'assembla.
Comencem amb una variable de seqüència d'arxiu, deseu en un FILE *, de manera que totes les tapes,
FILE, *, i el nom d'aquesta variable serà l'arxiu.
El podríem anomenar el que ens agrada. Podríem dir first_file o file_i, qualsevol cosa que volgués.
I després el nom del fitxer que es va aprovar en la línia d'ordres per a aquest programa.
Així que està emmagatzemat en argv [i] i després anem a obrir el fitxer en mode de lectura.
Ara que hem obert l'arxiu, què és el que sempre hem de recordar de fer
cada vegada que hem obert un arxiu? Prop d'ell.
Així Missy, com tancar un arxiu?
[Missy] fclose (arxiu) >> fclose (arxiu). Exactament.
Gran. Bé. Si ens fixem en això per fer un comentari aquí mateix,
que diu, "Open argv [i] i mostra el seu contingut a la sortida estàndard."
>> Fora Standard és un nom estrany. Stdout és només la nostra manera de dir
volem imprimir al terminal, volem imprimir la seqüència de sortida estàndard.
En realitat, pot desfer-se d'aquest comentari aquí.
Jo en copiar i enganxar ja que és el que vam fer.
En aquest punt, ara hem de llegir el bit d'arxiu de poc.
Hem parlat d'un parell de maneres de llegir arxius.
Quins són els seus favorits fins ara?
Què maneres has vist ni et recordes, per llegir els arxius?
[Daniel] fread? >> Fread? Així fread és un. Jimmy, coneixes alguna altra?
[Jimmy] >> No Està bé. Nope. Charlotte? Alexander? Algun altre? Bé.
Així que els altres són fgetc, és el que farem servir.
També hi ha fscanf; vostès veure un patró aquí?
Tots comencen amb. Res a veure amb un arxiu.
Hi ha fread, fgetc, fscanf. Aquestes són totes les funcions de lectura.
Per escriure tenim fwrite, tenim fputc en lloc de fgetc.
També hem fprintf com hem vist al qüestionari.
Atès que aquest és un problema que involucra la lectura d'un arxiu,
utilitzarem una d'aquestes tres funcions.
No utilitzarem aquestes funcions aquí baix.
Aquestes funcions es troben tots en l'estàndard d'E / S de la biblioteca.
Així que si ens fixem en la part superior d'aquest programa,
es pot veure que ja hem inclòs l'arxiu de capçalera per a l'estàndard d'E / S de la biblioteca.
Si volem esbrinar quin volem utilitzar,
sempre podem obrir les pàgines de manual.
Així que podem escriure stdio home
i llegir tot sobre l'entrada de stdio i funcions de sortida en C.
I ja podem veure oh, mira. S'esmenta fgetc, s'esmenta fputc.
Així que vostè pot aprofundir una mica més i veure, per exemple, fgetc
i buscar a la seva pàgina de manual.
Vostè pot veure que va juntament amb un munt d'altres funcions:
fgetc, fgets, getc, getchar, aconsegueix, ungetc, i la seva entrada de caràcters i cadenes.
Així que així és com es llegeix en caràcters i cadenes dels fitxers d'entrada estàndard,
que és essencialment l'usuari.
I així és com ho fem en real C.
Així que això no està utilitzant el GetString i funcions getchar
que es va utilitzar la biblioteca de CS50.
Anem a fer aquest problema en un parell de maneres
de manera que vostè pot veure dues maneres diferents de fer-ho.
Tant la funció fread que Daniel esmenta i fgetc són bones maneres de fer-ho.
Crec fgetc és una mica més fàcil, ja que només té, com vostè veu,
un argument, el FILE * que estem tractant de llegir el caràcter de,
i el seu valor de retorn és un int.
I això és una mica confús, no?
>> Com que estem arribant a un personatge, així que per què no fa una declaració char?
Vostès tenen alguna idea de per què això no pot tornar un char?
[Missy respostes, inintel · ligible] >> Yeah. Així que Missy és totalment correcte.
Si és ASCII, llavors aquest sencer podria ser assignada a una xerrada real.
Podria ser un caràcter ASCII, i així és.
Això és exactament el que està passant.
Estem usant un int simplement perquè té més bits.
És més gran que un char, la nostra xerrada només té 8 bits, 1 byte que en les nostres màquines de 32 bits.
I un int té valor en els 4 bytes 'de l'espai.
I resulta que la forma fgetc funciona,
si es desplaça cap avall en la nostra sinopsi d'aquesta pàgina de manual una mica,
desplaceu-vos fins al fons. Resulta que utilitzen aquest valor especial anomenat EOF.
És una constant especial com el valor retornat per la funció fgetc
cada vegada que es prem el final de l'arxiu o si es produeix un error.
I és que per fer aquestes comparacions amb EOF correctament,
Vols tenir aquesta quantitat extra d'informació que vostè té en un int
en lloc d'utilitzar una variable char.
Tot i que està efectivament fgetc aconseguir un personatge d'un arxiu,
vol recordar que s'està tornant una cosa que és de tipus int a vostè.
Dit això, és bastant fàcil d'utilitzar.
Això ens donarà un caràcter, de manera que tots hem de fer és seguir demanant l'arxiu,
"Dóna'm el següent caràcter, em dóna el següent caràcter, dóna'm el personatge que ve"
fins que arribem al final de l'arxiu.
I això va a estirar un caràcter alhora del nostre arxiu,
i llavors podem fer el que vulguem amb ella.
Podem emmagatzemar, podem afegir a una cadena, podem imprimir.
Fer res d'això.
>> Acostament a sortir i tornar al nostre programa Cat.C,
si utilitzarem fgetc,
Com ens acostem a aquesta següent línia de codi?
Anem a utilitzar - fread farà alguna cosa una mica diferent.
I aquesta vegada, només utilitzarem fgetc per obtenir un caràcter alhora.
Per processar un arxiu complet, el que hem de fer?
Quants personatges hi ha en un arxiu?
Hi ha un munt. Així que és probable que desitgi obtenir una
i després un altre i aconseguir un altre i aconseguir un altre.
Quin tipus d'algorisme creus que potser us caldrà emprar aquí?
Quin tipus de -? [Alejandro] Un bucle for? >> Exactament.
Algun tipus de bucle.
Un bucle és realment gran, en aquest cas.
I, com vostè deia, sembla que vols un llaç sobre la totalitat de l'expedient,
aconseguir un caràcter alhora.
Alguna suggeriment sobre el que pot tenir un aspecte semblant?
[Alexander, inintel · ligible]
>> Bé, m'ho dius en anglès el que estàs tractant de fer? [Alexander, inintel · ligible]
Així que en aquest cas, sembla que només estem tractant de iterar sobre l'arxiu complet.
[Alejandro] Així que > La mida de -?
Suposo que la mida de l'arxiu, no? La mida - ens tornarem simplement escriure així.
Mida d'arxiu de moment, i + +.
Així que resulta que la manera de fer això utilitzant fgetc, i això és nou,
és que no hi ha manera fàcil d'aconseguir tot just la mida d'un arxiu
amb aquest "sizeof" tipus de construcció que hagi vist abans.
Quan fem servir aquesta funció fgetc, estem introduint algun tipus de
nova sintaxi, funky a aquest bucle, on en lloc d'utilitzar simplement un comptador bàsic
anar caràcter per caràcter, anem a tirar un caràcter alhora,
un caràcter alhora, i la manera com sabem que estem al final
no és quan hem comptat un nombre determinat de caràcters,
però quan el personatge de treure és que la final de caràcter especial d'arxiu.
Així que podem fer això - Jo dic a aquesta cap, i nosaltres anem a inicialitzar
amb la nostra primera trucada per obtenir el primer caràcter de l'arxiu.
Així que aquesta part, just aquí, això es va a posar a un personatge fora de l'arxiu
i emmagatzemar-lo en la variable ch.
Seguirem fent això fins que arribi al final de l'arxiu,
que fem per les proves que el personatge no és igual a aquest caràcter EOF especial.
I a continuació, en lloc de fer ch + +, que acaba d'incrementar el valor,
pel que si llegim un fora d'un arxiu, una A majúscula, per exemple,
ch + + ens donaria b, i després ens anàvem a c i d.
Això no és clarament el que volem. El que volem aquí
en aquesta última part és que volem obtenir el següent caràcter de l'arxiu.
>> Llavors, com podem obtenir el següent caràcter de l'arxiu?
Com aconseguim el primer caràcter de l'arxiu?
[Estudiant] fgetfile? >> Fgetc, o, ho sento, tenies tota la raó.
El mal escrit aquí. Així que sí.
Aquí en comptes de fer ch + +,
només anomenarem fgetc (arxiu) de nou
i emmagatzemar el resultat en la variable ch mateix.
[Pregunta Estudiant, inintel · ligible]
>> Aquí és on aquests tipus de fitxers * són especials.
La forma de treballar que és - quan obri per primera vegada - la primera vegada que faci aquesta crida fopen,
L'arxiu * serveix efectivament com un punter al començament de l'arxiu.
I cada vegada que truqui fgetc, es mou un personatge amb el fitxer.
Així que cada vegada que es cridi a això, vostè està incrementant l'apuntador d'arxiu per un caràcter.
I quan fgetc de nou, estàs en moviment a un altre personatge
i un altre personatge i un altre personatge i un altre personatge.
[Pregunta Estudiant, inintel · ligible] >> I això és - si.
És una mica d'aquesta màgia sota el capó.
Vostè acaba de seguir incrementant a través.
En aquest punt, vostè és capaç de treballar realment amb un personatge.
Llavors, com podem imprimir això a la pantalla, ara?
Podem utilitzar la mateixa cosa printf que utilitzem abans.
Que hem estat utilitzant durant tot el semestre.
Podem trucar a printf,
i que pot passar en el caràcter just d'aquesta manera.
Una altra forma de fer-ho és en comptes d'usar printf i haver de fer aquesta cadena de format,
També es pot utilitzar una de les altres funcions.
Podem utilitzar fputc, que imprimeix un caràcter en la pantalla,
excepte si ens fixem en fputc - vull allunyar una mica.
Veiem el millor és que es necessita en el caràcter que llegim a terme utilitzant fgetc,
però llavors hem de donar-li un rierol per imprimir.
També pot utilitzar la funció putchar, que posarà directament a la sortida estàndard.
Així que hi ha un munt d'opcions diferents que podem utilitzar per a la impressió.
Estan tots en l'estàndard d'E / S de la biblioteca.
Cada vegada que vol imprimir - per printf, per defecte, s'imprimirà en la norma especial fora corrent,
que és la sortida estàndard.
Així que només pot referir-se a ell com una mena de màgia aquest valor, stdout aquí.
Oops. Posar el punt i coma fora.
>> Es tracta d'una gran quantitat de nova informació, funky aquí.
Molt d'això és molt idiomàtic, en el sentit que aquest és el codi
el que està escrit aquí només perquè està net de llegir, fàcil de llegir.
Hi ha moltes maneres diferents de fer-ho, moltes funcions diferents que pot utilitzar,
però tendim a seguir només els mateixos patrons una i altra vegada.
Així que no es sorprengui si vostè veu un codi com el que ve una i una altra.
Està bé. En aquest punt, hem de trencar el dia.
Gràcies per venir. Gràcies per veure si estàs en línia. I ens veiem la setmana que ve.
[CS50.TV]