1 00:00:00,000 --> 00:00:02,730 [Powered by Google Translate] [SEZIONE 5: meno confortevole] 2 00:00:02,730 --> 00:00:05,180 [Nate Hardison, Harvard University] 3 00:00:05,180 --> 00:00:08,260 [Questo è CS50.] [CS50.TV] 4 00:00:08,260 --> 00:00:11,690 Quindi bentornato, ragazzi. 5 00:00:11,690 --> 00:00:16,320 Benvenuti nella sezione 5. 6 00:00:16,320 --> 00:00:20,220 A questo punto, dopo aver completato quiz 0 e aver visto come hai fatto, 7 00:00:20,220 --> 00:00:25,770 potete sentire veramente bene, perché mi ha colpito molto per i punteggi in questa sezione. 8 00:00:25,770 --> 00:00:28,050 Per i nostri spettatori online, abbiamo avuto un paio di domande 9 00:00:28,050 --> 00:00:33,680 circa gli ultimi due problemi sul set problema - o per il quiz, piuttosto. 10 00:00:33,680 --> 00:00:39,690 Così abbiamo intenzione di andare su quelli molto in fretta in modo che ognuno vede ciò che è accaduto 11 00:00:39,690 --> 00:00:45,060 e come passare attraverso la soluzione reale piuttosto che la visualizzazione della soluzione stessa. 12 00:00:45,060 --> 00:00:50,330 Stiamo per andare oltre l'ultimo paio di problemi molto in fretta, 32 e 33. 13 00:00:50,330 --> 00:00:53,240 Così, ancora una volta, in modo che gli spettatori on-line può vedere questo. 14 00:00:53,240 --> 00:00:59,080 >> Se si attiva al problema 32, che si trova a pagina 13, 15 00:00:59,080 --> 00:01:02,730 13 su 16, problema 32 è tutto di swap. 16 00:01:02,730 --> 00:01:05,010 Si trattava di scambiare due numeri interi. 17 00:01:05,010 --> 00:01:08,740 E 'il problema che avevamo superato un paio di volte a lezione. 18 00:01:08,740 --> 00:01:13,590 E qui, quello che ci chiede di fare è una traccia di memoria veloce. 19 00:01:13,590 --> 00:01:17,000 Per inserire i valori delle variabili come sono in pila 20 00:01:17,000 --> 00:01:20,250 come codice passa attraverso questa funzione swap. 21 00:01:20,250 --> 00:01:24,500 In particolare, quello che stiamo guardando - Sto andando a mettere questo iPad verso il basso - 22 00:01:24,500 --> 00:01:29,650 in particolare, quello che stiamo guardando è la linea numero 6 proprio qui. 23 00:01:29,650 --> 00:01:36,740 Ed è numero 6 solo per contiguità con il problema precedente. 24 00:01:36,740 --> 00:01:41,720 Quello che vogliamo fare è visualizzare o etichettare lo stato della memoria 25 00:01:41,720 --> 00:01:46,090 come è al momento in cui si esegue questa linea 6, 26 00:01:46,090 --> 00:01:52,540 che è di fatto un ritorno dalla nostra funzione di scambio proprio qui. 27 00:01:52,540 --> 00:01:59,450 Se scorrere verso il basso qui, abbiamo visto che gli indirizzi di tutto nella memoria è stato fornito per noi. 28 00:01:59,450 --> 00:02:02,540 Questo è molto fondamentale; torneremo ad esso in un attimo. 29 00:02:02,540 --> 00:02:09,240 E poi qui in basso, abbiamo avuto un piccolo diagramma di memoria che stiamo andando a fare riferimento. 30 00:02:09,240 --> 00:02:12,490 Ho effettivamente fatto questo sul mio iPad. 31 00:02:12,490 --> 00:02:20,720 Quindi ho intenzione di alternare avanti e indietro tra l'iPad e il codice solo per riferimento. 32 00:02:20,720 --> 00:02:26,540 >> Cominciamo. In primo luogo, concentriamoci sul primo paio di righe di principale proprio qui. 33 00:02:26,540 --> 00:02:30,220 Per iniziare, abbiamo intenzione di inizializzare a 1 x e y a 2. 34 00:02:30,220 --> 00:02:33,040 Quindi abbiamo due variabili intere, sono entrambi sta per essere inseriti nello stack. 35 00:02:33,040 --> 00:02:36,050 Stiamo andando a mettere un 1 e un 2 in loro. 36 00:02:36,050 --> 00:02:43,150 Quindi, se ho capovolto per il mio iPad, si spera, vediamo - 37 00:02:43,150 --> 00:02:48,660 Apple TV mirroring, e ci andiamo. Va bene. 38 00:02:48,660 --> 00:02:51,670 Quindi, se ho capovolto per il mio iPad, 39 00:02:51,670 --> 00:02:56,220 Voglio inizializzare x a 1 e y 2. 40 00:02:56,220 --> 00:03:00,580 Lo facciamo semplicemente scrivendo un 1 nella casella contrassegnata x 41 00:03:00,580 --> 00:03:07,730 e 2 nella casella contrassegnata y. Abbastanza semplice. 42 00:03:07,730 --> 00:03:11,620 Così ora torniamo al computer portatile, vedere cosa succede dopo. 43 00:03:11,620 --> 00:03:15,810 Così questa linea successiva è dove le cose si fanno difficili. 44 00:03:15,810 --> 00:03:28,110 Passiamo l'indirizzo di x e l'indirizzo di y come i parametri a e b per la funzione di scambio. 45 00:03:28,110 --> 00:03:32,380 L'indirizzo di x e l'indirizzo di y sono cose che non possiamo calcolare 46 00:03:32,380 --> 00:03:36,360 senza fare riferimento a questi punti proiettile fino qui. 47 00:03:36,360 --> 00:03:39,750 E per fortuna, i primi due punti ci dicono esattamente quali siano le risposte. 48 00:03:39,750 --> 00:03:44,740 L'indirizzo di x in memoria è 10, e l'indirizzo di y in memoria è 14. 49 00:03:44,740 --> 00:03:51,870 Quindi questi sono i valori che vengono passati come a e b sulla cima nella nostra funzione di scambio. 50 00:03:51,870 --> 00:04:00,760 Quindi, di nuovo, tornando al nostro schema, posso scrivere un 10 in un 51 00:04:00,760 --> 00:04:07,400 e 14 in b. 52 00:04:07,400 --> 00:04:11,610 Ora, questo punto è dove si procede con lo swap. 53 00:04:11,610 --> 00:04:14,520 Quindi, lanciando indietro al computer portatile nuovo, 54 00:04:14,520 --> 00:04:21,079 vediamo che il modo in cui funziona è di swap ho dereference prima una e memorizzare il risultato in tmp. 55 00:04:21,079 --> 00:04:27,650 Così l'operatore dereference dice: "Ehi. Trattare il contenuto della variabile a come indirizzo. 56 00:04:27,650 --> 00:04:33,830 Vai a tutto ciò che è memorizzato a quell'indirizzo, e lo carica. " 57 00:04:33,830 --> 00:04:41,720 Che si carica fuori della variabile sta per essere memorizzato nella nostra variabile tmp. 58 00:04:41,720 --> 00:04:45,150 Flipping nuovo al iPad. 59 00:04:45,150 --> 00:04:51,690 Se andiamo ad affrontare 10, sappiamo che l'indirizzo 10 è il x varible 60 00:04:51,690 --> 00:04:55,480 perché ci hanno detto che il nostro punto di proiettile che l'indirizzo di x in memoria è di 10. 61 00:04:55,480 --> 00:05:00,180 Così possiamo andare lì, ottenere il valore di esso, che è 1, come si vede sul nostro iPad, 62 00:05:00,180 --> 00:05:06,300 e caricare che in tmp. 63 00:05:06,300 --> 00:05:08,250 Ancora una volta, questo non è il contenuto finale. 64 00:05:08,250 --> 00:05:14,350 Stiamo andando a piedi attraverso e arriveremo al nostro stato finale del programma alla fine. 65 00:05:14,350 --> 00:05:17,210 Ma in questo momento, abbiamo il valore 1 memorizzato in tmp. 66 00:05:17,210 --> 00:05:19,210 >> E c'è una domanda veloce qui. 67 00:05:19,210 --> 00:05:23,980 [Alexander] è l'operatore dereference - questo è solo il diritto stella di fronte alla variabile? 68 00:05:23,980 --> 00:05:27,600 Sì >>. Così l'operatore dereference, come lanciamo di nuovo al nostro computer portatile, ancora una volta, 69 00:05:27,600 --> 00:05:33,780 questa stella è proprio di fronte. 70 00:05:33,780 --> 00:05:37,460 In questo senso, si tratta - si in contrasto con l'operatore di moltiplicazione 71 00:05:37,460 --> 00:05:42,400 che richiede due cose: l'operatore dereference è un operatore unario. 72 00:05:42,400 --> 00:05:46,130 Appena applicato ad un valore al contrario di un operatore binario, 73 00:05:46,130 --> 00:05:48,810 in cui si applica a due valori diversi. 74 00:05:48,810 --> 00:05:52,080 Ecco, questo è ciò che accade in questa linea. 75 00:05:52,080 --> 00:05:58,390 Abbiamo caricato il valore 1 e memorizzato nella nostra variabile temporanea intero. 76 00:05:58,390 --> 00:06:05,800 La riga successiva, si memorizzare il contenuto di b in - 77 00:06:05,800 --> 00:06:12,630 o, piuttosto, di memorizzare i contenuti che b si punta a nel luogo in cui una sta puntando. 78 00:06:12,630 --> 00:06:17,690 Se analizziamo questo da destra a sinistra, stiamo andando a b dereference, 79 00:06:17,690 --> 00:06:23,580 ci accingiamo ad affrontare 14, ci accingiamo a prendere il numero intero che è lì, 80 00:06:23,580 --> 00:06:26,900 e poi abbiamo intenzione di aprire l'indirizzo 10, 81 00:06:26,900 --> 00:06:34,240 e stiamo andando a gettare il risultato del nostro dereferenziamento di b in quello spazio. 82 00:06:34,240 --> 00:06:40,080 Lanciando di nuovo al nostro iPad, dove si può fare questo un po 'più concreto, 83 00:06:40,080 --> 00:06:44,070 potrebbe essere utile se scrivo i numeri su tutti gli indirizzi qui. 84 00:06:44,070 --> 00:06:53,820 Così sappiamo che a y, siamo a indirizzo 14, x è all'indirizzo 10. 85 00:06:53,820 --> 00:07:00,180 Quando cominciamo a b, si dereferenziare b, stiamo andando a prendere il valore 2. 86 00:07:00,180 --> 00:07:08,320 Abbiamo intenzione di prendere questo valore perché questo è il valore che vive all'indirizzo 14. 87 00:07:08,320 --> 00:07:15,700 E abbiamo intenzione di metterlo nella variabile che vive all'indirizzo 10, 88 00:07:15,700 --> 00:07:19,160 che è proprio lì, corrispondente alla nostra variabile x. 89 00:07:19,160 --> 00:07:21,810 Così siamo in grado di fare un po 'di sovrascrivere qui 90 00:07:21,810 --> 00:07:35,380 in cui ci liberiamo del nostro 1 e invece si scrive un 2. 91 00:07:35,380 --> 00:07:39,560 Quindi tutto è bene e il bene nel mondo, anche se abbiamo x ora sovrascritti. 92 00:07:39,560 --> 00:07:44,890 Abbiamo conservato il vecchio valore di x nella nostra variabile tmp. 93 00:07:44,890 --> 00:07:50,210 Così siamo in grado di completare lo scambio con la linea successiva. 94 00:07:50,210 --> 00:07:53,030 Lanciando di nuovo al nostro portatile. 95 00:07:53,030 --> 00:07:58,150 Ora tutto ciò che rimane è quello di prendere il contenuto dal nostro intero variabile temporanea 96 00:07:58,150 --> 00:08:05,630 e memorizzarle nella variabile che vive presso l'indirizzo che b è in possesso. 97 00:08:05,630 --> 00:08:10,230 Quindi stiamo andando a risolvere il riferimento b efficacemente per ottenere l'accesso alla variabile 98 00:08:10,230 --> 00:08:14,340 che è l'indirizzo che b tiene in esso, 99 00:08:14,340 --> 00:08:19,190 e stiamo andando a riempire il valore che è in possesso di tmp in esso. 100 00:08:19,190 --> 00:08:23,280 Flipping torna l'iPad una volta di più. 101 00:08:23,280 --> 00:08:31,290 Posso cancellare il valore qui, 2, 102 00:08:31,290 --> 00:08:41,010 e invece si copierà l'1 a destra in esso. 103 00:08:41,010 --> 00:08:43,059 Poi la riga successiva che esegue, naturalmente - 104 00:08:43,059 --> 00:08:47,150 Se lanciamo torna al computer portatile - è questo il punto 6, 105 00:08:47,150 --> 00:08:52,500 che è il punto in cui abbiamo voluto avere il nostro schema completamente compilata. 106 00:08:52,500 --> 00:08:58,940 Quindi, lanciando indietro al iPad una volta di più, solo così è possibile vedere lo schema completato, 107 00:08:58,940 --> 00:09:06,610 si può vedere che abbiamo un 10 in una, a 14 in b, un 1 in tmp, a 2 in x, e un 1 in y. 108 00:09:06,610 --> 00:09:11,000 Ci sono delle domande su questo? 109 00:09:11,000 --> 00:09:14,640 Questo ha più senso, dopo aver camminato attraverso di essa? 110 00:09:14,640 --> 00:09:24,850 Fai meno senso? Speriamo di no. Va bene. 111 00:09:24,850 --> 00:09:28,230 >> I puntatori sono un argomento molto delicato. 112 00:09:28,230 --> 00:09:33,420 Uno dei ragazzi con cui lavoriamo è un detto molto comune: 113 00:09:33,420 --> 00:09:36,590 "Per capire i puntatori, è necessario prima capire i puntatori." 114 00:09:36,590 --> 00:09:40,530 Che credo sia molto vero. Ci vuole un po 'per abituarsi ad esso. 115 00:09:40,530 --> 00:09:45,360 Disegno un sacco di foto, sorteggio di diagrammi di memoria come questo sono molto utili, 116 00:09:45,360 --> 00:09:49,480 e dopo si cammina attraverso esempio dopo esempio dopo esempio, 117 00:09:49,480 --> 00:09:54,450 si inizierà ad avere un senso un po 'più e un senso un po' più e un po 'più senso. 118 00:09:54,450 --> 00:10:01,560 Infine, un giorno, avrai tutto completamente padroni. 119 00:10:01,560 --> 00:10:13,800 Tutte le domande prima di passare al problema successivo? Bene. 120 00:10:13,800 --> 00:10:18,840 Quindi, capovolgere torna al computer portatile. 121 00:10:18,840 --> 00:10:23,300 Il problema successivo che abbiamo è il problema numero 33 il file di I / O. 122 00:10:23,300 --> 00:10:26,350 Zoom su questo un po '. 123 00:10:26,350 --> 00:10:28,710 Problema 33 - Sì? 124 00:10:28,710 --> 00:10:32,110 >> [Daniel] Ho appena avuto una domanda veloce. Questa stella, o l'asterisco, 125 00:10:32,110 --> 00:10:35,590 si chiama dereferenziazione quando si utilizza un asterisco prima. 126 00:10:35,590 --> 00:10:38,820 Come si chiama quando si utilizza la e commerciale prima? 127 00:10:38,820 --> 00:10:43,140 >> La e commerciale è prima l'operatore di indirizzo. 128 00:10:43,140 --> 00:10:45,880 Quindi cerchiamo di scorrere verso l'alto. 129 00:10:45,880 --> 00:10:49,310 Oops. Sono in modalità zoom quindi non posso davvero scorrimento. 130 00:10:49,310 --> 00:10:52,780 Se guardiamo a questo codice molto velocemente proprio qui, 131 00:10:52,780 --> 00:10:54,980 ancora una volta, la stessa cosa accade. 132 00:10:54,980 --> 00:10:59,180 Se guardiamo a questo codice proprio qui, su questa linea, dove facciamo la chiamata a scambiare, 133 00:10:59,180 --> 00:11:10,460 la e commerciale è solo dire "ottenere l'indirizzo presso il quale vive x variabili". 134 00:11:10,460 --> 00:11:14,460 Quando il compilatore compila il codice, 135 00:11:14,460 --> 00:11:20,590 deve fisicamente tracciare un posto nella memoria per tutte le variabili di vivere. 136 00:11:20,590 --> 00:11:24,910 E così ciò che il compilatore può fare una volta che è compilato tutto, 137 00:11:24,910 --> 00:11:31,110 lo sa: "Oh, ho messo x all'indirizzo 10. ho messo y all'indirizzo 14." 138 00:11:31,110 --> 00:11:34,640 Si può quindi inserire questi valori per voi. 139 00:11:34,640 --> 00:11:44,740 Così si può allora - si può poi passare questo e passare & y pure. 140 00:11:44,740 --> 00:11:50,730 Questi ragazzi ottenere l'indirizzo, ma anche, quando si passa alla funzione di scambio, 141 00:11:50,730 --> 00:11:55,690 queste informazioni tipo, questo * int proprio qui, dice al compilatore, 142 00:11:55,690 --> 00:12:01,350 "Va bene, stiamo andando a essere interpretare questo indirizzo come un indirizzo di una variabile intera." 143 00:12:01,350 --> 00:12:05,900 Come un indirizzo di un int, che è diverso dall'indirizzo di una variabile carattere 144 00:12:05,900 --> 00:12:09,930 perché un int occupa, su una macchina a 32 bit, occupa 4 byte di spazio, 145 00:12:09,930 --> 00:12:13,310 considerando che un personaggio prende solo fino 1 byte di spazio. 146 00:12:13,310 --> 00:12:17,310 Quindi è importante sapere anche che cosa è - ciò che vive, che tipo di valore 147 00:12:17,310 --> 00:12:20,340 vive presso l'indirizzo che e 'stato superato trovi 148 00:12:20,340 --> 00:12:22,020 O l'indirizzo che hai a che fare con. 149 00:12:22,020 --> 00:12:29,020 In questo modo, si sa quanti byte di informazioni per caricare dalla vostra RAM. 150 00:12:29,020 --> 00:12:31,780 E poi, sì, questo operatore dereferenziare, come se stessi chiedendo, 151 00:12:31,780 --> 00:12:37,200 si accede alle informazioni e ad un indirizzo particolare. 152 00:12:37,200 --> 00:12:42,820 Così si dice, con questa variabile qui, trattare il contenuto di una forma di indirizzo, 153 00:12:42,820 --> 00:12:47,880 vai a questo indirizzo, ed estrarre, caricare nel processore, il carico in un registro 154 00:12:47,880 --> 00:12:56,340 i valori reali o il contenuto che vivono a questo indirizzo. 155 00:12:56,340 --> 00:12:59,620 Altre domande? Queste sono buone domande. 156 00:12:59,620 --> 00:13:01,650 E 'un sacco di nuova terminologia troppo. 157 00:13:01,650 --> 00:13:09,800 E 'anche un po' funky, e vedere * e in luoghi diversi. 158 00:13:09,800 --> 00:13:13,180 >> Bene. 159 00:13:13,180 --> 00:13:18,530 Ma torniamo al problema 33, file I / O. 160 00:13:18,530 --> 00:13:22,540 Questo è stato uno di quei problemi che credo un paio di cose sono successe. 161 00:13:22,540 --> 00:13:25,400 Uno, è un argomento abbastanza nuovo. 162 00:13:25,400 --> 00:13:30,590 E 'stata presentata molto presto prima che il quiz, 163 00:13:30,590 --> 00:13:33,400 e poi penso che sia stata un po 'come uno di quei problemi di parola in matematica 164 00:13:33,400 --> 00:13:39,720 dove ti danno un sacco di informazioni, ma che in realtà non finiscono per dover utilizzare una tonnellata di esso. 165 00:13:39,720 --> 00:13:44,060 La prima parte di questo problema è descrivere ciò che è un file CSV. 166 00:13:44,060 --> 00:13:50,620 Ora, un file CSV, secondo la descrizione, è un file CSV valori. 167 00:13:50,620 --> 00:13:55,300 La ragione per cui questi sono tutti interessanti, e la ragione per cui li uso mai, 168 00:13:55,300 --> 00:14:00,800 è, perché, come molti di voi hanno mai usato roba come Excel? 169 00:14:00,800 --> 00:14:03,240 Figura molti di voi hanno, probabilmente, o userà ad un certo punto della tua vita. 170 00:14:03,240 --> 00:14:06,430 Potrai utilizzare qualcosa di simile a Excel. 171 00:14:06,430 --> 00:14:10,940 Al fine di ottenere i dati di un foglio di calcolo Excel o fare qualsiasi tipo di trattamento effettuato con esso, 172 00:14:10,940 --> 00:14:17,240 se si vuole scrivere un programma C o di un programma Python, programma Java, 173 00:14:17,240 --> 00:14:20,070 a che fare con i dati memorizzati in là, 174 00:14:20,070 --> 00:14:23,170 uno dei modi più comuni per farlo fuori è in un file CSV. 175 00:14:23,170 --> 00:14:26,850 E si può aprire Excel e quando si va a 'Save As' dialogo, 176 00:14:26,850 --> 00:14:32,840 si può uscire da un file vero e CSV. 177 00:14:32,840 --> 00:14:35,890 >> Comodo per sapere come affrontare queste cose. 178 00:14:35,890 --> 00:14:42,010 Il modo in cui funziona è che è simile a - Voglio dire, e 'essenzialmente imitando un foglio di calcolo, 179 00:14:42,010 --> 00:14:47,590 dove, come si vede qui, nel pezzo molto più a sinistra, 180 00:14:47,590 --> 00:14:49,910 abbiamo tutti i cognomi. 181 00:14:49,910 --> 00:14:54,670 Così abbiamo Malan, quindi Hardison, e poi Bowden, MacWilliam, e poi Chan. 182 00:14:54,670 --> 00:14:59,470 Tutti i cognomi. E poi una virgola separa i cognomi dai nomi. 183 00:14:59,470 --> 00:15:02,970 David, Nate, Rob, Tommy, e Zamyla. 184 00:15:02,970 --> 00:15:06,850 Ho sempre mescolare Robby e Tom. 185 00:15:06,850 --> 00:15:10,940 E poi, infine, la terza colonna sono gli indirizzi email. 186 00:15:10,940 --> 00:15:18,500 Una volta capito questo, il resto del programma è abbastanza semplice da implementare. 187 00:15:18,500 --> 00:15:23,850 Quello che abbiamo fatto per imitare la stessa struttura del nostro programma C 188 00:15:23,850 --> 00:15:27,510 si abbiamo usato una struttura. 189 00:15:27,510 --> 00:15:30,520 Si comincerà a giocare con questi un po 'più pure. 190 00:15:30,520 --> 00:15:35,790 Li abbiamo visti per il primo bit piccolo problema nel set 3, quando abbiamo a che fare con i dizionari. 191 00:15:35,790 --> 00:15:40,290 Ma questa struttura personale memorizza un cognome, un nome, e una e-mail. 192 00:15:40,290 --> 00:15:44,500 Proprio come il nostro file CSV è stata l'archiviazione. 193 00:15:44,500 --> 00:15:47,950 Quindi questa è solo la conversione da un formato ad un altro. 194 00:15:47,950 --> 00:15:54,630 Dobbiamo convertire, in questo caso, una struttura del personale in una linea, 195 00:15:54,630 --> 00:15:59,060 separati da virgole linea, proprio così. 196 00:15:59,060 --> 00:16:01,500 Ha senso? Voi ragazzi hanno preso il quiz, 197 00:16:01,500 --> 00:16:07,680 quindi immagino che hai almeno avuto il tempo di pensare a questo. 198 00:16:07,680 --> 00:16:16,410 >> Nella funzione di noleggio, il problema ci chiede di prendere in - zoom we'll su questo un po '- 199 00:16:16,410 --> 00:16:22,480 prendere in una struttura di staff, una struttura del personale, con il nome di s, 200 00:16:22,480 --> 00:16:30,900 e aggiungere il suo contenuto al nostro file staff.csv. 201 00:16:30,900 --> 00:16:34,230 Si scopre che questo è abbastanza semplice da usare. 202 00:16:34,230 --> 00:16:37,430 Ci sorta di giocare con queste funzioni un po 'di più oggi. 203 00:16:37,430 --> 00:16:44,510 Ma in questo caso, la funzione fprintf è davvero la chiave. 204 00:16:44,510 --> 00:16:51,960 Quindi, con fprintf, siamo in grado di stampare, proprio come voi ragazzi hanno utilizzato printf questo termine tutto. 205 00:16:51,960 --> 00:16:55,050 È possibile printf una riga in un file. 206 00:16:55,050 --> 00:16:59,030 Quindi, invece di fare la solita chiamata printf in cui si dà la stringa di formato 207 00:16:59,030 --> 00:17:05,380 e poi di sostituire tutte le variabili con i seguenti argomenti, 208 00:17:05,380 --> 00:17:11,290 con fprintf, il primo argomento è invece il file che si desidera scrivere. 209 00:17:11,290 --> 00:17:21,170 Se dovessimo guardare a questa all'interno dell'apparecchio, per esempio, l'uomo fprintf, 210 00:17:21,170 --> 00:17:25,980 siamo in grado di vedere la differenza tra printf e fprintf. 211 00:17:25,980 --> 00:17:28,960 Io ingrandire qui un po '. 212 00:17:28,960 --> 00:17:33,140 Quindi, con printf, diamo una stringa di formato, e quindi gli argomenti successivi 213 00:17:33,140 --> 00:17:37,580 sono tutte le variabili per la sostituzione o la sostituzione nella nostra stringa di formato. 214 00:17:37,580 --> 00:17:47,310 Considerando che con fprintf, il primo argomento è davvero questa * file chiamato un flusso. 215 00:17:47,310 --> 00:17:51,800 >> Tornando qui al nostro noleggio, 216 00:17:51,800 --> 00:17:54,550 abbiamo già ottenuto il nostro flusso * file aperto per noi. 217 00:17:54,550 --> 00:17:57,810 Questo è ciò che la prima riga fa, ma apre il file staff.csv, 218 00:17:57,810 --> 00:18:01,690 essa si apre in modalità append, e tutto quello che ci resta da fare è 219 00:18:01,690 --> 00:18:08,640 scrivere la struttura del personale al file. 220 00:18:08,640 --> 00:18:10,870 E, vediamo, non voglio usare l'iPad? 221 00:18:10,870 --> 00:18:17,900 Userò l'iPad. Abbiamo vuoto - cerchiamo di mettere questo sul tavolo in modo da poter scrivere un po 'meglio - 222 00:18:17,900 --> 00:18:33,680 annullare noleggio e prende in un argomento, una struttura di staff denominata s. 223 00:18:33,680 --> 00:18:44,120 Hai nostri parentesi graffe, abbiamo il nostro * file chiamato file, 224 00:18:44,120 --> 00:18:48,380 abbiamo la nostra linea fopen dato a noi, 225 00:18:48,380 --> 00:18:51,890 e mi limiterò a scrivere sotto forma di punti dal momento che è già in pedia. 226 00:18:51,890 --> 00:19:00,530 E poi la nostra linea successiva, stiamo andando a fare una chiamata a fprintf 227 00:19:00,530 --> 00:19:03,700 e abbiamo intenzione di passare il file che si desidera stampare, 228 00:19:03,700 --> 00:19:10,290 e poi la nostra stringa di formato, che - 229 00:19:10,290 --> 00:19:14,300 Lascio voi ragazzi mi dicono quello che sembra. 230 00:19:14,300 --> 00:19:20,500 E tu, Stella? Sapete cosa la prima parte della stringa di formato simile? 231 00:19:20,500 --> 00:19:24,270 [Stella] Non sono sicuro. >> Non esitate a chiedere Jimmy. 232 00:19:24,270 --> 00:19:27,690 Sai, Jimmy? 233 00:19:27,690 --> 00:19:31,000 [Jimmy] Sarebbe solo l'ultimo? Non lo so. Io non sono del tutto sicuro. 234 00:19:31,000 --> 00:19:39,020 Va bene >>. Che ne dici, qualcuno ha avere questo corretto l'esame? 235 00:19:39,020 --> 00:19:41,770 No. Va bene. 236 00:19:41,770 --> 00:19:47,920 Si scopre che qui tutto quello che dobbiamo fare è che vogliamo ogni parte della nostra struttura personale 237 00:19:47,920 --> 00:19:53,290 da stampare come una stringa in nostro file. 238 00:19:53,290 --> 00:19:59,900 Abbiamo appena utilizzare il carattere di sostituzione di stringhe tre momenti diversi perché abbiamo un cognome 239 00:19:59,900 --> 00:20:07,160 seguito da una virgola, quindi un nome seguito da una virgola, 240 00:20:07,160 --> 00:20:12,430 e poi finalmente l'indirizzo email a cui fa seguito - che non è 241 00:20:12,430 --> 00:20:15,140 montaggio sul mio schermo - ma è seguito da un carattere di nuova riga. 242 00:20:15,140 --> 00:20:20,060 Quindi ho intenzione di scrivere solo laggiù. 243 00:20:20,060 --> 00:20:23,560 E poi, seguendo la nostra stringa di formato, 244 00:20:23,560 --> 00:20:27,880 dobbiamo solo le sostituzioni, che si accede usando la notazione punto 245 00:20:27,880 --> 00:20:31,370 che abbiamo visto nella serie problema 3. 246 00:20:31,370 --> 00:20:48,820 Possiamo usare s.last, s.first e s.email 247 00:20:48,820 --> 00:20:58,990 di sostituire in quei tre valori nella nostra stringa di formato. 248 00:20:58,990 --> 00:21:06,190 Allora, come e 'andata? Ha senso? 249 00:21:06,190 --> 00:21:09,700 Sì? No? Forse? Va bene. 250 00:21:09,700 --> 00:21:14,180 >> L'ultima cosa che facciamo dopo che abbiamo stampato e dopo abbiamo aperto il nostro file: 251 00:21:14,180 --> 00:21:17,370 ogni volta che abbiamo aperto un file, dobbiamo sempre ricordare per chiuderla. 252 00:21:17,370 --> 00:21:19,430 Perché altrimenti finiremo per perdita della memoria, 253 00:21:19,430 --> 00:21:22,500 utilizzando fino descrittori di file. 254 00:21:22,500 --> 00:21:25,950 Quindi, per chiuderla, quale funzione usiamo? Daniel? 255 00:21:25,950 --> 00:21:30,120 [Daniel] fclose? >> Fclose, esattamente. 256 00:21:30,120 --> 00:21:37,520 Quindi l'ultima parte di questo problema è stato quello di chiudere correttamente il file, utilizzando la funzione fclose, 257 00:21:37,520 --> 00:21:40,370 che sembra proprio così. 258 00:21:40,370 --> 00:21:43,880 Non troppo pazzo. 259 00:21:43,880 --> 00:21:46,990 Cool. 260 00:21:46,990 --> 00:21:49,520 Ecco, questo è un problema 33 sulla quiz. 261 00:21:49,520 --> 00:21:52,480 Avremo sicuramente più file di I / O in arrivo. 262 00:21:52,480 --> 00:21:55,130 Faremo un po 'di più a lezione di oggi, o al punto di oggi, 263 00:21:55,130 --> 00:22:01,710 perché è quello che sta andando a formare la maggior parte di questo pset imminente. 264 00:22:01,710 --> 00:22:05,020 Passiamo dal quiz a questo punto. Sì? 265 00:22:05,020 --> 00:22:10,880 >> [Charlotte]] Perché fclose (file) invece di fclose (staff.csv)? 266 00:22:10,880 --> 00:22:19,100 Ah >>. Perché si scopre che - così la questione, che è un grande, 267 00:22:19,100 --> 00:22:27,800 Ecco perché, quando scriviamo fclose, stiamo scrivendo fclose (file) stella variabile 268 00:22:27,800 --> 00:22:33,680 a differenza del nome del file, staff.csv? E 'corretto? Gia '. 269 00:22:33,680 --> 00:22:39,570 Quindi, diamo uno sguardo. Se dovessi tornare al mio portatile, 270 00:22:39,570 --> 00:22:45,040 e diamo un'occhiata alla funzione fclose. 271 00:22:45,040 --> 00:22:51,460 Quindi la funzione fclose chiude un flusso e lo prende nel puntatore al flusso che si desidera chiudere, 272 00:22:51,460 --> 00:22:57,010 in contrasto con il nome effettivo del file che si desidera chiudere. 273 00:22:57,010 --> 00:23:01,620 E questo è dovuto al fatto dietro le quinte, quando si effettua una chiamata a fopen, 274 00:23:01,620 --> 00:23:12,020 quando si apre un file, si sta effettivamente l'allocazione di memoria per memorizzare le informazioni relative al file. 275 00:23:12,020 --> 00:23:16,380 In modo da avere puntatore del file che contiene le informazioni sul file, 276 00:23:16,380 --> 00:23:23,080 come ad esempio è aperto, le sue dimensioni, dove siete attualmente nel file, 277 00:23:23,080 --> 00:23:29,100 in modo da poter rendere la lettura e la scrittura le chiamate a quel luogo particolare all'interno del file. 278 00:23:29,100 --> 00:23:38,060 Si finisce per chiudere il puntatore, invece di chiudere il nome del file. 279 00:23:38,060 --> 00:23:48,990 >> Sì? [Daniel] Quindi, al fine di utilizzare al noleggio, vuoi dire - come fa a ottenere l'input dell'utente? 280 00:23:48,990 --> 00:23:53,830 Ha fprintf agire come GetString, nel senso che ti basta attendere l'input dell'utente 281 00:23:53,830 --> 00:23:57,180 e vi chiedo di scrivere questo - o attendere per poter digitare queste tre cose? 282 00:23:57,180 --> 00:24:00,480 Oppure avete bisogno di usare qualcosa per implementare noleggio? 283 00:24:00,480 --> 00:24:04,100 Sì >>. Quindi non siamo - la questione è stata, come si fa a ottenere l'input dell'utente 284 00:24:04,100 --> 00:24:09,220 al fine di attuare a noleggio? E quello che abbiamo qui è il chiamante del noleggio, 285 00:24:09,220 --> 00:24:17,690 passata in questo struct personale con tutti i dati memorizzati nella struct già. 286 00:24:17,690 --> 00:24:22,990 Così è fprintf in grado di scrivere solo i dati direttamente al file. 287 00:24:22,990 --> 00:24:25,690 Non c'è nessuna attesa per l'input dell'utente. 288 00:24:25,690 --> 00:24:32,110 L'utente ha già dato l'input con la corretta mettendo in questa struttura del personale. 289 00:24:32,110 --> 00:24:36,510 E le cose, ovviamente, si rompono se uno qualsiasi di questi puntatori erano nulle, 290 00:24:36,510 --> 00:24:40,370 quindi scorrere verso l'alto qui e guardiamo la nostra struttura. 291 00:24:40,370 --> 00:24:43,640 Abbiamo ultima stringa, prima stringa, e-mail stringa. 292 00:24:43,640 --> 00:24:48,530 Ora sappiamo che tutti coloro in realtà, sotto il cofano, sono variabili char *. 293 00:24:48,530 --> 00:24:53,470 Questo può o non può essere che punta a null. 294 00:24:53,470 --> 00:24:55,800 Essi possono essere che punta alla memoria nello heap, 295 00:24:55,800 --> 00:24:59,650 forse memoria sullo stack. 296 00:24:59,650 --> 00:25:04,580 Noi in realtà non so, ma se uno qualsiasi di questi puntatori sono nulle, o non valide, 297 00:25:04,580 --> 00:25:08,120 che questo sarà sicuramente in crash la nostra funzione noleggio. 298 00:25:08,120 --> 00:25:11,050 Era una cosa che era un po 'oltre lo scopo di sostenere l'esame. 299 00:25:11,050 --> 00:25:16,440 Non stiamo preoccuparsi di questo. 300 00:25:16,440 --> 00:25:22,170 Grande. Va bene. Quindi, passando dal quiz. 301 00:25:22,170 --> 00:25:25,760 >> Chiudiamo questo ragazzo, e stiamo andando a guardare pset 4. 302 00:25:25,760 --> 00:25:34,700 Quindi, se voi ragazzi guardano le specifiche pset, una volta che vi si possa accedere, cs50.net/quizzes, 303 00:25:34,700 --> 00:25:42,730 ci accingiamo a passare attraverso alcuni dei problemi della sezione di oggi. 304 00:25:42,730 --> 00:25:52,240 Sto scorrendo verso il basso - sezione di domande inizia sulla terza pagina della specifica pset. 305 00:25:52,240 --> 00:25:57,800 E la prima parte si chiede di andare a vedere il corto di riorientare e tubi. 306 00:25:57,800 --> 00:26:02,820 Che era una specie di breve fresco, si mostra alcune nuove, interessanti trucchi della riga di comando che è possibile utilizzare. 307 00:26:02,820 --> 00:26:06,050 E poi abbiamo alcune domande per voi. 308 00:26:06,050 --> 00:26:10,860 La prima domanda sui flussi, a cui scrive printf per impostazione predefinita, 309 00:26:10,860 --> 00:26:15,920 abbiamo tipo toccato solo un po 'un momento fa. 310 00:26:15,920 --> 00:26:22,380 Questo fprintf che stavamo solo discutendo prende in un flusso di file * come argomento. 311 00:26:22,380 --> 00:26:26,580 fclose prende in un flusso di file * pure, 312 00:26:26,580 --> 00:26:32,660 e il valore di ritorno di fopen ti dà un flusso di file * pure. 313 00:26:32,660 --> 00:26:36,060 Il motivo per cui non abbiamo visto quelli che prima, quando abbiamo avuto a che fare con printf 314 00:26:36,060 --> 00:26:39,450 è perché ha printf un flusso predefinito. 315 00:26:39,450 --> 00:26:41,810 E il flusso predefinito a cui si scrive 316 00:26:41,810 --> 00:26:45,190 potrete scoprire a breve. 317 00:26:45,190 --> 00:26:50,080 Quindi, dare un'occhiata a questo. 318 00:26:50,080 --> 00:26:53,010 >> Nella sezione di oggi, stiamo andando a parlare un po 'di GDB, 319 00:26:53,010 --> 00:26:57,720 poiché il più familiare si è con essa, la pratica più si ottiene con esso, 320 00:26:57,720 --> 00:27:01,390 il meglio che tu possa essere in grado di dare la caccia effettivamente dei bug nel codice. 321 00:27:01,390 --> 00:27:05,540 Questo accelera il processo di debug fino tremendamente. 322 00:27:05,540 --> 00:27:09,230 Quindi, utilizzando printf, ogni volta che fai che devi ricompilare il codice, 323 00:27:09,230 --> 00:27:13,000 devi correre di nuovo, a volte è necessario spostare la chiamata a printf in giro, 324 00:27:13,000 --> 00:27:17,100 commentare il codice, ci vuole solo un po '. 325 00:27:17,100 --> 00:27:20,850 Il nostro obiettivo è quello di cercare di convincervi che con GDB, è possibile essenzialmente 326 00:27:20,850 --> 00:27:26,810 printf nulla in qualsiasi punto nel codice e non avete mai ricompilarlo. 327 00:27:26,810 --> 00:27:35,120 Non hai mai avviare e mantenere indovinare dove printf successivo. 328 00:27:35,120 --> 00:27:40,910 La prima cosa da fare è copiare questa linea e ottenere il codice sezione fuori del web. 329 00:27:40,910 --> 00:27:47,530 Sto copiando questa riga di codice che dice: "http://cdn.cs50.net wget". 330 00:27:47,530 --> 00:27:49,510 Ho intenzione di copiarlo. 331 00:27:49,510 --> 00:27:55,950 Ho intenzione di andare oltre al mio apparecchio, l'ingrandimento in modo da poter vedere quello che sto facendo, 332 00:27:55,950 --> 00:28:01,890 incollarlo in là, e quando ho premere Invio, il comando wget è letteralmente una rete ottenere. 333 00:28:01,890 --> 00:28:06,210 E 'intenzione di tirare giù il file da Internet, 334 00:28:06,210 --> 00:28:11,790 e sta andando a salvarlo nella directory corrente. 335 00:28:11,790 --> 00:28:21,630 Ora, se io la mia lista directory corrente si può vedere che ho questo file section5.zip lì dentro. 336 00:28:21,630 --> 00:28:25,260 Il modo di affrontare quel tipo è quello di decomprimerlo, 337 00:28:25,260 --> 00:28:27,650 che si può fare nella riga di comando, proprio come questo. 338 00:28:27,650 --> 00:28:31,880 Section5.zip. 339 00:28:31,880 --> 00:28:36,980 Che te lo decomprimere, creare la cartella per me, 340 00:28:36,980 --> 00:28:40,410 gonfiare tutti i contenuti, metterli in là. 341 00:28:40,410 --> 00:28:47,410 Così ora posso andare nella mia sezione 5 directory usando il comando cd. 342 00:28:47,410 --> 00:28:58,310 Pulisce lo schermo utilizzando chiaro. Quindi pulire lo schermo. 343 00:28:58,310 --> 00:29:02,280 Adesso ho un terminale bello e pulito da affrontare. 344 00:29:02,280 --> 00:29:06,200 >> Ora, se io elencare tutti i file che vedo in questa directory, 345 00:29:06,200 --> 00:29:12,270 si vede che ho quattro file: buggy1, buggy2, buggy3 e buggy4. 346 00:29:12,270 --> 00:29:16,180 Ho anche avuto i loro file corrispondenti. C. 347 00:29:16,180 --> 00:29:20,400 Non stiamo andando a guardare i files. C per ora. 348 00:29:20,400 --> 00:29:24,140 Invece, abbiamo intenzione di usarli quando ci apriamo GDB. 349 00:29:24,140 --> 00:29:28,220 Li abbiamo tenuti in giro in modo da avere accesso al codice sorgente effettiva in cui stiamo usando GDB, 350 00:29:28,220 --> 00:29:32,740 ma l'obiettivo di questa parte della sezione è quello di armeggiare intorno con GDB 351 00:29:32,740 --> 00:29:40,370 e vedere come si può utilizzare per capire cosa c'è che non va con ciascuno di questi quattro programmi buggy. 352 00:29:40,370 --> 00:29:43,380 Quindi stiamo solo andando a giro per la stanza molto velocemente, 353 00:29:43,380 --> 00:29:47,000 e ho intenzione di chiedere a qualcuno di eseguire uno dei programmi buggy, 354 00:29:47,000 --> 00:29:54,730 e poi ce ne andiamo come un gruppo con GDB, e vedremo cosa possiamo fare per risolvere questi programmi, 355 00:29:54,730 --> 00:29:58,460 o di individuare almeno cosa c'è di sbagliato in ciascuno di essi. 356 00:29:58,460 --> 00:30:04,760 Cominciamo qui con Daniel. Vuoi eseguire buggy1? Vediamo cosa succede. 357 00:30:04,760 --> 00:30:09,470 [Daniel] E dice che c'è un errore dell'applicazione. Sì >>. Esattamente. 358 00:30:09,470 --> 00:30:12,460 Quindi, se corro buggy1, ottengo un errore seg. 359 00:30:12,460 --> 00:30:16,210 A questo punto, potrei andare e aprire buggy1.c, 360 00:30:16,210 --> 00:30:19,450 cercare di capire cosa c'è di sbagliato, 361 00:30:19,450 --> 00:30:22,000 ma una delle cose più sgradevoli su questo errore di errore seg 362 00:30:22,000 --> 00:30:27,610 è che non ti dice su quale linea delle cose del programma in realtà è andato storto e si è rotto. 363 00:30:27,610 --> 00:30:29,880 Si tipo di dover guardare il codice 364 00:30:29,880 --> 00:30:33,990 e capire con ipotesi e verificare o printf per vedere cosa c'è di sbagliato. 365 00:30:33,990 --> 00:30:37,840 Una delle funzioni più interessanti di GDB è che è molto, molto facile 366 00:30:37,840 --> 00:30:42,170 per capire la linea con cui il programma va in crash. 367 00:30:42,170 --> 00:30:46,160 E 'del tutto vale la pena di usarlo, anche se solo per questo. 368 00:30:46,160 --> 00:30:56,190 Quindi, per avviare GDB, tipo I GDB, e poi dare il percorso del file eseguibile che voglio correre. 369 00:30:56,190 --> 00:31:01,960 Qui sto scrivendo gdb ./buggy1. 370 00:31:01,960 --> 00:31:06,600 Hit Enter. Mi dà tutte queste informazioni sul copyright, 371 00:31:06,600 --> 00:31:13,000 e qui vedrete questa linea che dice: "i simboli di lettura da / home / 372 00:31:13,000 --> 00:31:17,680 jharvard/section5/buggy1. " 373 00:31:17,680 --> 00:31:22,060 E se tutto va bene, vedrete che stampare un messaggio che assomiglia a questo. 374 00:31:22,060 --> 00:31:25,500 Sarà leggere i simboli, si dirà "Sto leggendo i simboli dal file eseguibile," 375 00:31:25,500 --> 00:31:29,900 e poi avrà il messaggio "done" qui. 376 00:31:29,900 --> 00:31:35,410 Se vedi qualche altra variante di questo, o si vede che non riusciva a trovare i simboli 377 00:31:35,410 --> 00:31:41,460 o qualcosa del genere, che cosa significa è che proprio non hanno compilato l'eseguibile corretto. 378 00:31:41,460 --> 00:31:49,980 Quando compilare i programmi per l'utilizzo con GDB, dobbiamo usare quella speciale-g, 379 00:31:49,980 --> 00:31:54,540 e che è fatto per impostazione predefinita se si compilare i programmi, semplicemente digitando make 380 00:31:54,540 --> 00:31:59,320 o fare buggy o fare recuperare, una di queste. 381 00:31:59,320 --> 00:32:07,800 Ma se si sta compilando manualmente con Clang, allora dovrete entrare e comprendere il fatto che-g. 382 00:32:07,800 --> 00:32:10,310 >> A questo punto, ora che abbiamo la nostra GDB prompt 383 00:32:10,310 --> 00:32:12,310 è abbastanza semplice per eseguire il programma. 384 00:32:12,310 --> 00:32:19,740 Siamo in grado di digitare run, oppure possiamo semplicemente digitare r. 385 00:32:19,740 --> 00:32:22,820 Maggior parte dei comandi possono essere abbreviati GDB. 386 00:32:22,820 --> 00:32:25,940 Di solito ad un solo o un paio di lettere, che è piuttosto bella. 387 00:32:25,940 --> 00:32:30,980 Così Saad, se si digita r e premere Invio, cosa succede? 388 00:32:30,980 --> 00:32:39,390 [Saad] Ho SIGSEGV, errore di segmentazione, e poi tutto questo incomprensibile. 389 00:32:39,390 --> 00:32:43,650 Sì >>. 390 00:32:43,650 --> 00:32:47,990 Come stiamo vedendo sullo schermo in questo momento, e come ha detto Saad, 391 00:32:47,990 --> 00:32:53,430 quando digita RUN o R e premere Invio, abbiamo ancora ottenere lo stesso difetto seg. 392 00:32:53,430 --> 00:32:55,830 Quindi, utilizzando GDB non risolve il nostro problema. 393 00:32:55,830 --> 00:32:59,120 Ma ci dà un po 'incomprensibile, e si scopre che questo incomprensibile 394 00:32:59,120 --> 00:33:03,080 in realtà ci dice dove sta accadendo. 395 00:33:03,080 --> 00:33:10,680 Per analizzare questo un po ', il primo bit è la funzione in cui tutto è andato storto. 396 00:33:10,680 --> 00:33:20,270 C'è questa __ strcmp_sse4_2, e ci dice che sta accadendo in questo file 397 00:33:20,270 --> 00:33:29,450 chiamato sysdeps/i386, tutto questo, ancora una volta, un po 'un pasticcio - ma la linea 254. 398 00:33:29,450 --> 00:33:31,670 Questo è un po 'difficile da analizzare. Di solito quando si vede cose come questa, 399 00:33:31,670 --> 00:33:38,770 che significa che è seg fault in una delle librerie di sistema. 400 00:33:38,770 --> 00:33:43,220 Quindi, qualcosa a che fare con strcmp. Voi ragazzi avete visto prima di strcmp. 401 00:33:43,220 --> 00:33:52,730 Non troppo folle, ma questo significa che strcmp è rotto o che c'è un problema con strcmp? 402 00:33:52,730 --> 00:33:57,110 Cosa ne pensi, Alexander? 403 00:33:57,110 --> 00:34:04,890 [Alexander] E 'questo - è di 254 la linea? E il - non il binario, ma non è loro soffitti, 404 00:34:04,890 --> 00:34:10,590 e poi c'è un altro linguaggio per ogni funzione. E '254 in quella funzione, o -? 405 00:34:10,590 --> 00:34:21,460 >> E 'la linea 254. Sembra che in questo file. S, quindi è probabilmente il codice assembly. 406 00:34:21,460 --> 00:34:25,949 >> Ma, credo che la cosa più urgente è, perché abbiamo ottenuto un guasto seg, 407 00:34:25,949 --> 00:34:29,960 e sembra che sta arrivando dalla funzione strcmp, 408 00:34:29,960 --> 00:34:38,030 questo implica, quindi, che strcmp è rotto? 409 00:34:38,030 --> 00:34:42,290 Non dovrebbe, si spera. Quindi, solo perché si ha un errore di segmentazione 410 00:34:42,290 --> 00:34:49,480 in una delle funzioni del sistema, in genere ciò significa che proprio non lo hanno chiamato correttamente. 411 00:34:49,480 --> 00:34:52,440 La cosa più veloce da fare per capire cosa sta realmente succedendo 412 00:34:52,440 --> 00:34:55,500 quando si vede qualcosa di pazzo come questo, ogni volta che vedete un errore seg, 413 00:34:55,500 --> 00:34:59,800 soprattutto se si dispone di un programma che, utilizzando più di un semplice principale, 414 00:34:59,800 --> 00:35:03,570 è quello di utilizzare un backtrace. 415 00:35:03,570 --> 00:35:13,080 I abbreviare backtrace scrivendo bt, in contrapposizione alla parola backtrace completo. 416 00:35:13,080 --> 00:35:16,510 Ma Charlotte, cosa succede quando si digita bt e premere Invio? 417 00:35:16,510 --> 00:35:23,200 [Charlotte] Mi mostra due linee, 0 linea e la linea 1. 418 00:35:23,200 --> 00:35:26,150 Sì >>. Così linea 0 e la linea 1. 419 00:35:26,150 --> 00:35:34,560 Questi sono gli stack frame reali che erano attualmente in gioco quando il programma si è bloccato. 420 00:35:34,560 --> 00:35:42,230 A partire dal telaio più in alto, il frame 0, e andare più in basso, che è frame 1. 421 00:35:42,230 --> 00:35:45,140 Il nostro telaio più in alto è il frame strcmp. 422 00:35:45,140 --> 00:35:50,080 Si può pensare a questo come un problema simile a quello che stavamo solo facendo il quiz con i puntatori, 423 00:35:50,080 --> 00:35:54,890 dove avevamo scambiare stack frame in cima alla stack frame principale, 424 00:35:54,890 --> 00:35:59,700 e abbiamo avuto le variabili che utilizzano swap è stato in cima alle variabili che principale è stato utilizzato. 425 00:35:59,700 --> 00:36:08,440 Qui il nostro incidente è accaduto nella nostra funzione strcmp, che è stato chiamato dalla nostra funzione principale, 426 00:36:08,440 --> 00:36:14,370 backtrace e ci sta dando non solo le funzioni in cui le cose non riuscite, 427 00:36:14,370 --> 00:36:16,440 ma è anche ci dice dove tutto era chiamato da. 428 00:36:16,440 --> 00:36:18,830 Quindi, se ho scorrere sopra un po 'più a destra, 429 00:36:18,830 --> 00:36:26,110 possiamo vedere che sì, eravamo in linea 254 di questo strcmp-sse4.s file. 430 00:36:26,110 --> 00:36:32,540 Ma la chiamata è stata fatta a buggy1.c, linea 6. 431 00:36:32,540 --> 00:36:35,960 Quindi questo significa che possiamo fare - è che può solo andare a controllare e vedere che cosa stava succedendo 432 00:36:35,960 --> 00:36:39,930 a buggy1.c, linea 6. 433 00:36:39,930 --> 00:36:43,780 Anche in questo caso, ci sono un paio di modi per farlo. Uno è quello di uscire da GDB 434 00:36:43,780 --> 00:36:49,460 o hanno il codice aperto in un'altra finestra e riferimenti incrociati. 435 00:36:49,460 --> 00:36:54,740 Questo, in sé e per sé, è piuttosto comodo perché ora, se siete in orario d'ufficio 436 00:36:54,740 --> 00:36:57,220 e hai un guasto e il seg TF sta chiedendo dove tutto è stata la rottura, 437 00:36:57,220 --> 00:36:59,710 si può solo dire: "Oh, la linea 6. Non so cosa sta succedendo, 438 00:36:59,710 --> 00:37:03,670 ma qualcosa linea 6 sta causando il mio programma di rompere. " 439 00:37:03,670 --> 00:37:10,430 L'altro modo per farlo è che si può utilizzare questo comando chiamato elenco GDB. 440 00:37:10,430 --> 00:37:13,650 È anche possibile abbreviare con l. 441 00:37:13,650 --> 00:37:18,910 Quindi, se abbiamo raggiunto l, che cosa siamo arrivati ​​qui? 442 00:37:18,910 --> 00:37:21,160 Abbiamo un sacco di cose strane. 443 00:37:21,160 --> 00:37:26,030 Questo è il codice montaggio vero e proprio 444 00:37:26,030 --> 00:37:29,860 che è in strcmp_sse4_2. 445 00:37:29,860 --> 00:37:32,440 Questo sembra un po 'funky, 446 00:37:32,440 --> 00:37:36,520 e il motivo per cui stai ricevendo questo è perché in questo momento, 447 00:37:36,520 --> 00:37:40,160 GDB noi ha nel frame 0. 448 00:37:40,160 --> 00:37:43,070 >> Così ogni volta guardiamo le variabili, ogni volta che guardiamo il codice sorgente, 449 00:37:43,070 --> 00:37:50,530 stiamo guardando il codice sorgente che riguarda lo stack frame siamo attualmente; 450 00:37:50,530 --> 00:37:53,200 Quindi, al fine di ottenere qualcosa di significativo, dobbiamo 451 00:37:53,200 --> 00:37:57,070 passare a un fotogramma stack che ha più senso. 452 00:37:57,070 --> 00:38:00,180 In questo caso, lo stack frame principale avrebbe senso un po 'più, 453 00:38:00,180 --> 00:38:02,680 perché questo era in realtà il codice che abbiamo scritto. 454 00:38:02,680 --> 00:38:05,330 Non il codice strcmp. 455 00:38:05,330 --> 00:38:08,650 Il modo in cui è possibile spostarsi tra i fotogrammi, in questo caso, perché abbiamo due, 456 00:38:08,650 --> 00:38:10,430 abbiamo 0 e 1, 457 00:38:10,430 --> 00:38:13,650 hai fatto con il su e giù i comandi. 458 00:38:13,650 --> 00:38:18,480 Se mi muovo su un fotogramma, 459 00:38:18,480 --> 00:38:21,770 ora sono in stack frame principale. 460 00:38:21,770 --> 00:38:24,330 Posso spostare verso il basso per tornare a dove mi trovavo, 461 00:38:24,330 --> 00:38:32,830 risalire, scendere di nuovo, e salite ancora. 462 00:38:32,830 --> 00:38:39,750 Se mai fare il programma in GDB, si ottiene un crash, si ottiene il backtrace, 463 00:38:39,750 --> 00:38:42,380 e si vede che è in qualche file che non si sa cosa sta succedendo. 464 00:38:42,380 --> 00:38:45,460 Si tenta lista, il codice non sembra familiare a voi, 465 00:38:45,460 --> 00:38:48,150 dare un'occhiata alle cornici e capire dove ti trovi. 466 00:38:48,150 --> 00:38:51,010 Probabilmente siete nello stack frame sbagliato. 467 00:38:51,010 --> 00:38:58,760 O almeno sei in uno stack frame che non è uno che si può veramente eseguire il debug. 468 00:38:58,760 --> 00:39:03,110 Ora che siamo nello stack frame del caso, siamo in main, 469 00:39:03,110 --> 00:39:08,100 Ora possiamo usare il comando list per capire cosa la linea era. 470 00:39:08,100 --> 00:39:13,590 E lo si può vedere, ma è stampato per noi qui. 471 00:39:13,590 --> 00:39:19,470 Ma siamo in grado di colpire elencare tutti uguali, e la lista ci dà questa bella stampa 472 00:39:19,470 --> 00:39:23,920 del codice sorgente effettivo che sta succedendo qui. 473 00:39:23,920 --> 00:39:26,420 >> In particolare, possiamo guardare alla riga 6. 474 00:39:26,420 --> 00:39:29,330 Siamo in grado di vedere quello che sta succedendo qui. 475 00:39:29,330 --> 00:39:31,250 E sembra che stiamo facendo un confronto di stringhe 476 00:39:31,250 --> 00:39:41,050 tra la stringa "CS50 rocce" e argv [1]. 477 00:39:41,050 --> 00:39:45,700 Qualcosa su questo faceva andare in crash. 478 00:39:45,700 --> 00:39:54,120 Quindi Missy, hai qualche idea su quello che potrebbe essere succedendo qui? 479 00:39:54,120 --> 00:39:59,400 [Missy] Non so perché è crash. >> Non sai perché è crash? 480 00:39:59,400 --> 00:40:02,700 Jimmy, qualche idea? 481 00:40:02,700 --> 00:40:06,240 [Jimmy] Io non sono del tutto sicuro, ma l'ultima volta che abbiamo usato stringa di confrontare, 482 00:40:06,240 --> 00:40:10,260 o strcmp, abbiamo avuto come tre diversi casi sotto di essa. 483 00:40:10,260 --> 00:40:12,800 Non abbiamo avuto un ==, non credo che, proprio in quella prima linea. 484 00:40:12,800 --> 00:40:16,700 Invece è stato suddiviso in tre, e uno era == 0, 485 00:40:16,700 --> 00:40:19,910 uno era <0, credo, e uno era> 0. 486 00:40:19,910 --> 00:40:22,590 Quindi forse una cosa del genere? Sì >>. Quindi c'è questo problema 487 00:40:22,590 --> 00:40:27,200 delle stiamo facendo il confronto corretto? 488 00:40:27,200 --> 00:40:31,660 Stella? Qualche idea? 489 00:40:31,660 --> 00:40:38,110 [Stella] Non sono sicuro. >> Non sono sicuro. Daniel? Pensieri? Va bene. 490 00:40:38,110 --> 00:40:44,770 Si scopre quello che sta succedendo qui è quando abbiamo finito il programma 491 00:40:44,770 --> 00:40:48,370 e abbiamo ottenuto il guasto seg, quando è stato eseguito il programma per la prima volta, Daniel, 492 00:40:48,370 --> 00:40:50,800 hai dato tutti gli argomenti della riga di comando? 493 00:40:50,800 --> 00:40:58,420 [Daniel] No. No. >> In tal caso, qual è il valore di argv [1]? 494 00:40:58,420 --> 00:41:00,920 >> Non esiste un valore. >> Destra. 495 00:41:00,920 --> 00:41:06,120 Beh, non vi è alcun valore stringa appropriata. 496 00:41:06,120 --> 00:41:10,780 Ma c'è un certo valore. Qual è il valore che viene memorizzato in là? 497 00:41:10,780 --> 00:41:15,130 Un valore >> spazzatura? >> E 'un valore immondizia o, in questo caso, 498 00:41:15,130 --> 00:41:19,930 la fine della matrice argv è sempre terminata con null. 499 00:41:19,930 --> 00:41:26,050 Quindi, ciò che effettivamente ha memorizzato nel non vi è nulla. 500 00:41:26,050 --> 00:41:30,810 L'altro modo per risolvere questo problema, invece di pensare fino in fondo, 501 00:41:30,810 --> 00:41:33,420 è quello di provare a stampare fuori. 502 00:41:33,420 --> 00:41:35,880 Questo è dove dicevo che l'utilizzo di GDB è grande, 503 00:41:35,880 --> 00:41:40,640 perché è possibile stampare tutte le variabili, tutti i valori che si desidera 504 00:41:40,640 --> 00:41:43,230 utilizzando questo pratico-dandy comando p. 505 00:41:43,230 --> 00:41:48,520 Quindi, se di tipo I p e poi digitare il valore di una variabile o il nome di una variabile, 506 00:41:48,520 --> 00:41:55,320 dire, argc, vedo che argc è 1. 507 00:41:55,320 --> 00:42:01,830 Se voglio stampare argv [0], posso farlo proprio così. 508 00:42:01,830 --> 00:42:04,840 E come abbiamo visto, argv [0] è sempre il nome del programma, 509 00:42:04,840 --> 00:42:06,910 sempre il nome del file eseguibile. 510 00:42:06,910 --> 00:42:09,740 Qui sotto potete vedere è ottenuto il percorso completo. 511 00:42:09,740 --> 00:42:15,920 Posso anche stampare argv [1] e vedere cosa succede. 512 00:42:15,920 --> 00:42:20,890 >> Qui abbiamo avuto questo tipo di valore mistico. 513 00:42:20,890 --> 00:42:23,890 Abbiamo ottenuto questo 0x0. 514 00:42:23,890 --> 00:42:27,850 Ricordate all'inizio del termine, quando abbiamo parlato di numeri esadecimali? 515 00:42:27,850 --> 00:42:34,680 O che piccola domanda alla fine del pset 0 su come rappresentare il 50 in esadecimale? 516 00:42:34,680 --> 00:42:39,410 Il nostro modo di scrivere i numeri esadecimali in CS, giusto per non confondere noi stessi 517 00:42:39,410 --> 00:42:46,080 con i numeri decimali, è che abbiamo sempre con prefisso 0x. 518 00:42:46,080 --> 00:42:51,420 Quindi questo prefisso 0x sempre significa solo interpretare il numero come un numero esadecimale, 519 00:42:51,420 --> 00:42:57,400 non come una stringa, non come un numero decimale, non come un numero binario. 520 00:42:57,400 --> 00:43:02,820 Dal momento che il numero di 5-0 è un numero valido in esadecimale. 521 00:43:02,820 --> 00:43:06,240 Ed è un numero decimale, 50. 522 00:43:06,240 --> 00:43:10,050 Quindi questo è solo il modo in cui evitare ambiguità. 523 00:43:10,050 --> 00:43:14,860 Così 0x0 mezzi esadecimale 0, che è anche decimale 0, binario 0. 524 00:43:14,860 --> 00:43:17,030 E 'solo il valore 0. 525 00:43:17,030 --> 00:43:22,630 Si scopre che questo è ciò che nulla è, in realtà, nella memoria. 526 00:43:22,630 --> 00:43:25,940 Null è solo 0. 527 00:43:25,940 --> 00:43:37,010 Qui, l'elemento memorizzato in argv [1] è nullo. 528 00:43:37,010 --> 00:43:45,220 Quindi stiamo cercando di confrontare la nostra "CS50 rocce" stringa in una stringa nulla. 529 00:43:45,220 --> 00:43:48,130 Così dereferencing null, tentando di accedere a nulla le cose, 530 00:43:48,130 --> 00:43:55,050 coloro che sono in genere andando a causare una sorta di errore di segmentazione o di altre cose brutte accadano. 531 00:43:55,050 --> 00:43:59,350 E si scopre che strcmp non controlla per vedere 532 00:43:59,350 --> 00:44:04,340 se non hai passato un valore che è null. 533 00:44:04,340 --> 00:44:06,370 Piuttosto, si va solo avanti, cerca di fare il suo dovere, 534 00:44:06,370 --> 00:44:14,640 e se seg difetti, seg difetti, ed è il tuo problema. Devi andare a risolvere il problema. 535 00:44:14,640 --> 00:44:19,730 Molto velocemente, come potremmo risolvere questo problema? Charlotte? 536 00:44:19,730 --> 00:44:23,540 [Charlotte] È possibile verificare con se. 537 00:44:23,540 --> 00:44:32,240 Quindi, se argv [1] è nullo, == 0, then return 1, o qualcosa del genere [incomprensibile]. 538 00:44:32,240 --> 00:44:34,590 Sì >>. Ecco, questo è un ottimo modo per farlo, come si può verificare, 539 00:44:34,590 --> 00:44:39,230 il valore che stiamo per passare in strcmp, argv [1], si è nullo? 540 00:44:39,230 --> 00:44:45,830 Se è null, allora possiamo dire bene, interrompere. 541 00:44:45,830 --> 00:44:49,450 >> Un modo più comune per farlo è quello di utilizzare il valore di argc. 542 00:44:49,450 --> 00:44:52,040 Potete vedere qui all'inizio del principale, 543 00:44:52,040 --> 00:44:58,040 abbiamo omesso che la prima prova che noi di solito facciamo quando utilizzare gli argomenti della riga di comando, 544 00:44:58,040 --> 00:45:05,240 che è quello di verificare se il nostro valore argc è quello che ci aspettiamo. 545 00:45:05,240 --> 00:45:10,290 In questo caso, ci aspettiamo almeno due argomenti, 546 00:45:10,290 --> 00:45:13,660 il nome del programma più altri uno. 547 00:45:13,660 --> 00:45:17,140 Dato che stiamo per usare il secondo argomento proprio qui. 548 00:45:17,140 --> 00:45:21,350 Quindi, avendo una sorta di test in anticipo, prima della nostra chiamata strcmp 549 00:45:21,350 --> 00:45:37,390 che i test o meno argv è almeno 2, anche fare la stessa cosa. 550 00:45:37,390 --> 00:45:40,620 Possiamo vedere se funziona eseguendo nuovamente il programma. 551 00:45:40,620 --> 00:45:45,610 È sempre possibile riavviare il programma all'interno di GDB, che è veramente bello. 552 00:45:45,610 --> 00:45:49,310 È possibile eseguire, e quando si passa gli argomenti al programma, 553 00:45:49,310 --> 00:45:53,060 li passare quando si chiama l'esecuzione, non quando si avvia GDB. 554 00:45:53,060 --> 00:45:57,120 In questo modo è possibile mantenere invocando il programma, con parametri diversi ogni volta. 555 00:45:57,120 --> 00:46:08,080 Correte, o ancora, posso digitare r, e vediamo cosa succede se si digita "ciao". 556 00:46:08,080 --> 00:46:11,140 Sarà sempre chiesto se si desidera avviare fin dall'inizio di nuovo. 557 00:46:11,140 --> 00:46:17,490 Di solito, si vuole avviarlo di nuovo dall'inizio. 558 00:46:17,490 --> 00:46:25,010 E a questo punto, si riavvia di nuovo, esso stampa 559 00:46:25,010 --> 00:46:28,920 il programma che si sta eseguendo, buggy1, con l'argomento ciao, 560 00:46:28,920 --> 00:46:32,720 e stampa questo fuori standard, si dice, "Si ottiene una D," faccia triste. 561 00:46:32,720 --> 00:46:37,610 Ma non abbiamo errore di segmentazione. Ha detto che il processo è terminato normalmente. 562 00:46:37,610 --> 00:46:39,900 In modo che sembra piuttosto buono. 563 00:46:39,900 --> 00:46:43,050 Nessuna anomalia più segmenti, abbiamo fatto passato, 564 00:46:43,050 --> 00:46:48,190 così sembra che il bug era davvero colpa segmento che ci stavamo. 565 00:46:48,190 --> 00:46:51,540 Purtroppo, ci dice che stiamo ottenendo un D. 566 00:46:51,540 --> 00:46:54,090 >> Siamo in grado di tornare indietro e guardare il codice e vedere cosa stava succedendo lì 567 00:46:54,090 --> 00:46:57,980 per capire cosa era - perché ci stava dicendo che abbiamo ottenuto un D. 568 00:46:57,980 --> 00:47:03,690 Vediamo, qui è stato questo printf dicendo che hai un D. 569 00:47:03,690 --> 00:47:08,540 Se digitiamo lista, come si mantiene elenco digitando, mantiene scorrendo verso il basso attraverso il programma, 570 00:47:08,540 --> 00:47:10,940 in modo che vi mostrerò le prime righe del programma. 571 00:47:10,940 --> 00:47:15,450 Poi vi mostrerò le prossime righe, e il blocco successivo e il blocco successivo. 572 00:47:15,450 --> 00:47:18,240 E continuerò cercando di andare verso il basso. 573 00:47:18,240 --> 00:47:21,180 E ora ci arriveremo "linea numero 16 non è compreso nell'intervallo." 574 00:47:21,180 --> 00:47:23,940 Perché ha solo 15 righe. 575 00:47:23,940 --> 00:47:30,310 Se si arriva a questo punto e la tua chiedersi: "Che cosa devo fare?" è possibile utilizzare il comando help. 576 00:47:30,310 --> 00:47:34,340 Utilizzare aiuto e poi dare il nome di un comando. 577 00:47:34,340 --> 00:47:36,460 E si vede il GDB ci dà tutto questo genere di cose. 578 00:47:36,460 --> 00:47:43,870 Dice: "Con nessun argomento, elenca dieci righe più dopo o intorno alla quotazione precedente. 579 00:47:43,870 --> 00:47:47,920 Elenco - elenca le dieci righe prima - " 580 00:47:47,920 --> 00:47:52,960 Quindi cerchiamo di provare a utilizzare meno lista. 581 00:47:52,960 --> 00:47:57,000 E che elenca le 10 righe precedenti, è possibile giocare con un elenco un po '. 582 00:47:57,000 --> 00:48:02,330 È possibile fare la lista, lista -, si può anche dare elencare un numero, come lista 8, 583 00:48:02,330 --> 00:48:07,500 e sarà un elenco delle 10 linee attorno alla riga 8. 584 00:48:07,500 --> 00:48:10,290 E si può vedere quello che sta succedendo qui è che hai un semplice if else. 585 00:48:10,290 --> 00:48:13,980 Se si digita CS50 rocce, esso stampa "Si ottiene una A." 586 00:48:13,980 --> 00:48:16,530 In caso contrario, esso stampa "Si ottiene una D." 587 00:48:16,530 --> 00:48:23,770 Bummer città. Bene. Sì? 588 00:48:23,770 --> 00:48:26,730 >> [Daniel] Così, quando ho provato a fare CS50 rocce senza le virgolette, 589 00:48:26,730 --> 00:48:29,290 si dice "È possibile ottenere una D." 590 00:48:29,290 --> 00:48:32,560 Avevo bisogno le virgolette per farlo funzionare, perché? 591 00:48:32,560 --> 00:48:38,490 Sì >>. Si scopre che, quando - questo è un altro bocconcino po 'di divertimento - 592 00:48:38,490 --> 00:48:47,900 quando si esegue il programma, se lo si esegue e digitare CS50 rocce, 593 00:48:47,900 --> 00:48:50,800 proprio come Daniele stava dicendo che ha fatto, e si preme Invio, 594 00:48:50,800 --> 00:48:52,870 si dice ancora abbiamo un D. 595 00:48:52,870 --> 00:48:55,580 E la domanda è: perché? 596 00:48:55,580 --> 00:49:02,120 E si scopre che sia il nostro terminale e GDB analizzare come due argomenti distinti. 597 00:49:02,120 --> 00:49:04,800 Perché quando c'è uno spazio, che è implicita 598 00:49:04,800 --> 00:49:08,730 il primo argomento chiuso, l'argomento successivo sta per iniziare. 599 00:49:08,730 --> 00:49:13,260 Il modo di combinare quelle in due, o mi dispiace, in un solo argomento, 600 00:49:13,260 --> 00:49:18,510 è quello di utilizzare le virgolette. 601 00:49:18,510 --> 00:49:29,560 Così ora, se lo mettiamo tra virgolette ed eseguirlo di nuovo, si ottiene una A. 602 00:49:29,560 --> 00:49:38,780 Quindi, solo per ricapitolare, senza virgolette, CS50 e rocce vengono analizzati come due argomenti distinti. 603 00:49:38,780 --> 00:49:45,320 Con le virgolette, è analizzato come un argomento del tutto. 604 00:49:45,320 --> 00:49:53,070 >> Possiamo vedere questo con un punto di interruzione. 605 00:49:53,070 --> 00:49:54,920 Finora siamo stati in esecuzione il nostro programma, ed è stato in esecuzione 606 00:49:54,920 --> 00:49:58,230 fino a quando non seg guasti o visite un errore 607 00:49:58,230 --> 00:50:05,930 o fino a quando è uscito e tutto è stato del tutto soddisfacente. 608 00:50:05,930 --> 00:50:08,360 Questo non è necessariamente la cosa più utile, perché a volte 609 00:50:08,360 --> 00:50:11,840 si dispone di un errore nel programma, ma non sta causando un errore di segmentazione. 610 00:50:11,840 --> 00:50:16,950 Non sta causando il vostro programma di fermarsi o di qualcosa di simile. 611 00:50:16,950 --> 00:50:20,730 Il modo per ottenere GDB per mettere in pausa il programma in un punto particolare 612 00:50:20,730 --> 00:50:23,260 è quello di impostare un punto di interruzione. 613 00:50:23,260 --> 00:50:26,520 È possibile eseguire questa operazione impostando un punto di interruzione su un nome di funzione 614 00:50:26,520 --> 00:50:30,770 oppure è possibile impostare un punto di interruzione su una particolare linea di codice. 615 00:50:30,770 --> 00:50:34,450 Mi piace impostare punti di interruzione su nomi di funzione, perché - facile da ricordare, 616 00:50:34,450 --> 00:50:37,700 e se effettivamente entrare e modificare il codice sorgente di un po ', 617 00:50:37,700 --> 00:50:42,020 allora il tuo punto di interruzione sarà effettivamente rimanere nello stesso posto all'interno del codice. 618 00:50:42,020 --> 00:50:44,760 Considerando che, se si sta utilizzando i numeri di riga, e modificare i numeri di riga 619 00:50:44,760 --> 00:50:51,740 perché aggiungere o eliminare un po 'di codice, quindi i punti di interruzione sono tutti completamente sbagliato. 620 00:50:51,740 --> 00:50:58,590 Una delle cose più comuni che fare è impostare un punto di interruzione sulla funzione principale. 621 00:50:58,590 --> 00:51:05,300 Spesso mi avvio GDB, ti tipo b principale, premere Invio, e che verrà impostato un punto di interruzione 622 00:51:05,300 --> 00:51:10,630 la funzione principale che dice solo: "Mettere in pausa il programma non appena si inizia a correre," 623 00:51:10,630 --> 00:51:17,960 e in questo modo, quando ho eseguito il mio programma con, diciamo, CS50 rocce come due argomenti 624 00:51:17,960 --> 00:51:24,830 e premere Invio, si arriva alla funzione principale e si ferma a destra alla prima riga, 625 00:51:24,830 --> 00:51:30,620 destra prima che valuta la funzione strcmp. 626 00:51:30,620 --> 00:51:34,940 >> Dal momento che sono in pausa, ora posso iniziare a pasticciare in giro e vedere cosa sta succedendo 627 00:51:34,940 --> 00:51:40,250 con tutte le variabili che sono passati nel mio programma. 628 00:51:40,250 --> 00:51:43,670 Qui posso stampare argc e vedere cosa sta succedendo. 629 00:51:43,670 --> 00:51:50,030 Vedere che argc è 3, perché è ottenuto 3 diversi valori in esso. 630 00:51:50,030 --> 00:51:54,060 E 'ottenuto il nome del programma, è ottenuto il primo argomento e il secondo argomento. 631 00:51:54,060 --> 00:52:09,330 Siamo in grado di stampare quelli fuori, cercando in argv [0], argv [1], argv [2]. 632 00:52:09,330 --> 00:52:12,030 Così ora si può anche capire perché questa chiamata strcmp sta per fallire, 633 00:52:12,030 --> 00:52:21,650 perché si vede che lo ha fatto dividere la CS50 e le rocce in due argomenti distinti. 634 00:52:21,650 --> 00:52:27,250 A questo punto, una volta che hai raggiunto un punto di interruzione, è possibile continuare a scorrere il programma 635 00:52:27,250 --> 00:52:32,920 riga per riga, al contrario di iniziare nuovamente il programma. 636 00:52:32,920 --> 00:52:35,520 Quindi, se non si desidera avviare di nuovo il programma e solo continuare a partire da qui, 637 00:52:35,520 --> 00:52:41,970 è possibile utilizzare il comando continue e continuare eseguirà il programma fino alla fine. 638 00:52:41,970 --> 00:52:45,010 Proprio come ha fatto qui. 639 00:52:45,010 --> 00:52:54,880 Tuttavia, se riavviare il programma, CS50 rocce, colpisce il mio punto di interruzione di nuovo, 640 00:52:54,880 --> 00:52:59,670 e questa volta, se non si vuole andare solo tutto il percorso attraverso il resto del programma, 641 00:52:59,670 --> 00:53:08,040 Posso usare il comando successivo, che ho anche abbreviare con n. 642 00:53:08,040 --> 00:53:12,960 E questo verrà descritto il programma riga per riga. 643 00:53:12,960 --> 00:53:17,530 Così si può vedere come le cose eseguire, come il cambiamento variabili, come le cose vengono aggiornate. 644 00:53:17,530 --> 00:53:21,550 Il che è piuttosto bella. 645 00:53:21,550 --> 00:53:26,570 L'altra cosa interessante è invece di ripetere lo stesso comando più e più e più volte, 646 00:53:26,570 --> 00:53:30,670 se si premere Invio - ecco vedi che non ho digitato nulla - 647 00:53:30,670 --> 00:53:33,780 se mi limito a premere Invio, si ripeterà il comando precedente, 648 00:53:33,780 --> 00:53:36,900 o il comando precedente GDB che ho appena messo dentro 649 00:53:36,900 --> 00:53:56,000 Posso tenere premendo invio e terrò passo attraverso il mio codice riga per riga. 650 00:53:56,000 --> 00:53:59,310 Vorrei incoraggiare voi ragazzi per andare a controllare i programmi buggy anche altri. 651 00:53:59,310 --> 00:54:01,330 Non abbiamo il tempo di passare attraverso tutti loro oggi in sezione. 652 00:54:01,330 --> 00:54:05,890 Il codice sorgente è lì, quindi è possibile tipo di vedere cosa sta succedendo 653 00:54:05,890 --> 00:54:07,730 dietro le quinte, se vi trovate in panne, 654 00:54:07,730 --> 00:54:11,940 ma per lo meno, basta praticare l'avvio GDB, 655 00:54:11,940 --> 00:54:13,940 l'esecuzione del programma fino a quando si rompe su di voi, 656 00:54:13,940 --> 00:54:18,260 ottenere il backtrace, cercando di capire quale funzione l'incidente era in, 657 00:54:18,260 --> 00:54:24,450 quale linea era su, la stampa di alcuni valori delle variabili, 658 00:54:24,450 --> 00:54:30,140 solo così si ottiene una sensazione di esso, perché questo aiuterà senz'altro a andare avanti. 659 00:54:30,140 --> 00:54:36,340 A questo punto, abbiamo intenzione di smettere di GDB, che si fa utilizzando uscire o semplicemente q. 660 00:54:36,340 --> 00:54:40,460 Se il programma si trova nel mezzo di correre ancora, e non è uscito, 661 00:54:40,460 --> 00:54:43,510 sarà sempre chiedere: "Sei sicuro sicuro di voler uscire?" 662 00:54:43,510 --> 00:54:48,770 Si può solo colpire sì. 663 00:54:48,770 --> 00:54:55,250 >> Ora stiamo andando a guardare il prossimo problema che abbiamo, che è il programma cat. 664 00:54:55,250 --> 00:54:59,880 Se si guarda il corto di reindirizzamento e tubi, vedrai che Tommy usa questo programma 665 00:54:59,880 --> 00:55:07,540 che consente di stampare praticamente tutto l'output di un file sullo schermo. 666 00:55:07,540 --> 00:55:12,660 Quindi, se corro gatto, questo è in realtà un built-in programma per l 'apparecchio, 667 00:55:12,660 --> 00:55:16,860 e se si dispone di Mac si può fare anche sul vostro Mac, se si apre il terminale. 668 00:55:16,860 --> 00:55:25,630 E noi - gatto, diciamo, cp.c, e premere Invio. 669 00:55:25,630 --> 00:55:29,640 Ciò fatto, se si scorre un po 'e vedere dove abbiamo fatto la linea, 670 00:55:29,640 --> 00:55:40,440 o dove abbiamo eseguito il comando cat, è letteralmente appena stampato il contenuto di cp.c al nostro schermo. 671 00:55:40,440 --> 00:55:44,140 Siamo in grado di farlo funzionare di nuovo e si può mettere in più file insieme. 672 00:55:44,140 --> 00:55:49,880 Così si può fare cp.c gatto, e allora possiamo anche concatenare il file Cat. C, 673 00:55:49,880 --> 00:55:53,250 che è il programma che stiamo per scrivere, 674 00:55:53,250 --> 00:55:58,140 e si metterà a stampare entrambi i file back to back al nostro schermo. 675 00:55:58,140 --> 00:56:05,490 Quindi, se si scorre un po ', si vede che quando abbiamo fatto questa cp.c gatto, Cat. C, 676 00:56:05,490 --> 00:56:17,110 prima stampato il file cp, e poi sotto, stampato il file di Cat. C fino qui. 677 00:56:17,110 --> 00:56:19,650 Stiamo andando a utilizzare questo per ottenere solo i nostri piedi bagnati. 678 00:56:19,650 --> 00:56:25,930 Giocare con semplice stampa al terminale, vedere come funziona. 679 00:56:25,930 --> 00:56:39,170 Se voi ragazzi aprono con gedit Cat. C, premere Invio, 680 00:56:39,170 --> 00:56:43,760 si può vedere il programma che stiamo per scrivere. 681 00:56:43,760 --> 00:56:48,980 Abbiamo incluso questo bel piatto della caldaia, in modo da non dover perdere tempo a digitare tutto ciò che fuori. 682 00:56:48,980 --> 00:56:52,310 Abbiamo anche controllare il numero di argomenti passati trovi 683 00:56:52,310 --> 00:56:56,910 Abbiamo stampare un bel messaggio di utilizzo. 684 00:56:56,910 --> 00:57:00,950 >> Questo è il genere di cose che, ancora una volta, come abbiamo parlato, 685 00:57:00,950 --> 00:57:04,490 è quasi come memoria muscolare. 686 00:57:04,490 --> 00:57:07,190 Basta ricordarsi di continuare a fare lo stesso tipo di cose 687 00:57:07,190 --> 00:57:11,310 e sempre stampare una sorta di messaggio utile 688 00:57:11,310 --> 00:57:17,670 in modo che la gente sappia come gestire il vostro programma. 689 00:57:17,670 --> 00:57:21,630 Con il gatto, è abbastanza semplice, stiamo solo andando a passare attraverso tutti i diversi argomenti 690 00:57:21,630 --> 00:57:24,300 che sono stati trasferiti al nostro programma, e abbiamo intenzione di stampare 691 00:57:24,300 --> 00:57:29,950 il loro contenuto fuori allo schermo uno alla volta. 692 00:57:29,950 --> 00:57:35,670 Per stampare i file verso lo schermo, che andremo a fare qualcosa di molto simile 693 00:57:35,670 --> 00:57:38,120 per quello che abbiamo fatto alla fine del quiz. 694 00:57:38,120 --> 00:57:45,350 Alla fine del quiz, che assumere programma, abbiamo dovuto aprire un file, 695 00:57:45,350 --> 00:57:48,490 e poi abbiamo dovuto stampare. 696 00:57:48,490 --> 00:57:54,660 In questo caso, abbiamo intenzione di aprire un file, e stiamo andando a leggere da esso, invece. 697 00:57:54,660 --> 00:58:00,630 Poi andiamo in stampa, invece di un file, che andremo a stampare sullo schermo. 698 00:58:00,630 --> 00:58:05,830 Modo che la stampa sullo schermo tutti voi avete fatto prima con printf. 699 00:58:05,830 --> 00:58:08,290 Quindi non è troppo pazzo. 700 00:58:08,290 --> 00:58:12,190 Ma la lettura di un file è un po 'strano. 701 00:58:12,190 --> 00:58:17,300 Andremo attraverso che un po 'alla volta. 702 00:58:17,300 --> 00:58:20,560 Se voi ragazzi tornare a quella ultimo problema sul tuo quiz, problema 33, 703 00:58:20,560 --> 00:58:27,280 la prima linea che stiamo andando a fare qui, l'apertura del file, è molto simile a quello che abbiamo fatto lì. 704 00:58:27,280 --> 00:58:36,370 Così Stella, che cosa fa quello sguardo linea come, quando si apre un file? 705 00:58:36,370 --> 00:58:47,510 [Stella] Capital * FILE, file - >> Ok. >> - È pari a fopen. Yup >>. 706 00:58:47,510 --> 00:58:55,980 Che in questo caso è? E 'nel commento. 707 00:58:55,980 --> 00:59:06,930 >> E 'nel commento? argv [i] e r? 708 00:59:06,930 --> 00:59:11,300 >> Esattamente. Proprio sulla. Così Stella del tutto giusto. 709 00:59:11,300 --> 00:59:13,720 Questo è ciò che la linea assomiglia. 710 00:59:13,720 --> 00:59:19,670 Stiamo per ottenere una variabile flusso di file, conservarlo in un FILE *, in modo che tutti i tappi, 711 00:59:19,670 --> 00:59:25,720 FILE, * e il nome di questa variabile sarà file. 712 00:59:25,720 --> 00:59:32,250 Potremmo chiamare tutto quello che vogliamo. Potremmo chiamarlo first_file, o file_i, tutto ciò che vuoi. 713 00:59:32,250 --> 00:59:37,590 E poi il nome del file è stato passato sulla riga di comando per questo programma. 714 00:59:37,590 --> 00:59:44,450 Quindi è memorizzato in argv [i,] e poi abbiamo intenzione di aprire il file in modalità di lettura. 715 00:59:44,450 --> 00:59:48,100 Ora che abbiamo aperto il file, qual è la cosa che dobbiamo sempre ricordare di fare 716 00:59:48,100 --> 00:59:52,230 ogni volta che abbiamo aperto un file? Chiuderlo. 717 00:59:52,230 --> 00:59:57,220 Quindi Missy, come facciamo a chiudere un file? 718 00:59:57,220 --> 01:00:01,020 [Missy] fclose (file) >> fclose (file). Esattamente. 719 01:00:01,020 --> 01:00:05,340 Grande. Va bene. Se guardiamo a questo commento da fare qui, 720 01:00:05,340 --> 01:00:11,940 si dice, "Apri argv [i] e stampare il suo contenuto su stdout." 721 01:00:11,940 --> 01:00:15,460 >> Fuori standard è un nome strano. Stdout è solo il nostro modo di dire 722 01:00:15,460 --> 01:00:22,880 si desidera stampare al terminale, vogliamo stampare nel flusso di output standard. 723 01:00:22,880 --> 01:00:26,450 Si può effettivamente sbarazzarsi di questo commento proprio qui. 724 01:00:26,450 --> 01:00:36,480 Ho intenzione di copiarlo e incollarlo dato che è quello che abbiamo fatto. 725 01:00:36,480 --> 01:00:41,290 A questo punto, ora dobbiamo leggere il bit per bit del file. 726 01:00:41,290 --> 01:00:46,300 Abbiamo discusso un paio di modi di lettura dei file. 727 01:00:46,300 --> 01:00:51,830 Quali sono i tuoi preferiti fino ad ora? 728 01:00:51,830 --> 01:00:57,960 Quali modi avete visto o ti ricordi, a leggere i file? 729 01:00:57,960 --> 01:01:04,870 [Daniel] fread? Fread >>? Così fread è uno. Jimmy, sai tutti gli altri? 730 01:01:04,870 --> 01:01:12,150 [Jimmy] No. >> Ok. Nope. Charlotte? Alexander? Tutti gli altri? Va bene. 731 01:01:12,150 --> 01:01:20,740 Così gli altri sono fgetc, è uno che useremo molto. 732 01:01:20,740 --> 01:01:26,410 C'è anche fscanf; voi vedere qualcosa qui? 733 01:01:26,410 --> 01:01:29,170 Tutti iniziano con f. Niente a che fare con un file. 734 01:01:29,170 --> 01:01:35,260 C'è fread, fgetc, fscanf. Queste sono tutte le funzioni di lettura. 735 01:01:35,260 --> 01:01:49,120 Per la scrittura abbiamo fwrite, abbiamo fputc invece di fgetc. 736 01:01:49,120 --> 01:01:58,250 Abbiamo anche fprintf come abbiamo visto sul quiz. 737 01:01:58,250 --> 01:02:01,680 Poiché questo è un problema che coinvolge la lettura da un file, 738 01:02:01,680 --> 01:02:04,940 abbiamo intenzione di usare una di queste tre funzioni. 739 01:02:04,940 --> 01:02:10,890 Non abbiamo intenzione di utilizzare queste funzioni qui. 740 01:02:10,890 --> 01:02:14,880 Queste funzioni si trovano tutti nella norma libreria I / O. 741 01:02:14,880 --> 01:02:17,510 Quindi, se si guarda nella parte superiore di questo programma, 742 01:02:17,510 --> 01:02:24,110 si può vedere che abbiamo già incluso il file di intestazione per l'I / O standard library. 743 01:02:24,110 --> 01:02:27,120 Se vogliamo capire quale si desidera utilizzare, 744 01:02:27,120 --> 01:02:29,690 possiamo sempre aprire le pagine man. 745 01:02:29,690 --> 01:02:34,350 Così possiamo digitare stdio uomo 746 01:02:34,350 --> 01:02:43,180 e leggere tutto l'input stdio e funzioni di uscita in C. 747 01:02:43,180 --> 01:02:49,870 E possiamo già vedere oh, guarda. E 'menzionare fgetc, è menzionare fputc. 748 01:02:49,870 --> 01:02:57,220 Così si può eseguire il drill down un po 'e guardare, per esempio, fgetc 749 01:02:57,220 --> 01:03:00,060 e guardare la sua pagina man. 750 01:03:00,060 --> 01:03:03,430 Si può vedere che va di pari passo con un sacco di altre funzioni: 751 01:03:03,430 --> 01:03:12,640 fgetc, fgets, getc, getchar, ottiene, ungetc, e la sua immissione di caratteri e stringhe. 752 01:03:12,640 --> 01:03:19,180 Quindi questo è come si legge in caratteri e stringhe da file dallo standard input, 753 01:03:19,180 --> 01:03:21,990 che è essenzialmente dall'utente. 754 01:03:21,990 --> 01:03:24,780 E questo è come lo facciamo in effettivo C. 755 01:03:24,780 --> 01:03:30,850 Quindi questo non utilizza il GetString e le funzioni getchar 756 01:03:30,850 --> 01:03:36,840 che abbiamo usato dalla libreria CS50. 757 01:03:36,840 --> 01:03:39,710 Stiamo andando a fare questo problema in un paio di modi 758 01:03:39,710 --> 01:03:43,430 in modo che si può vedere in due modi diversi di farlo. 759 01:03:43,430 --> 01:03:48,490 Sia la funzione fread che Daniel menzionato e fgetc sono buoni modi per farlo. 760 01:03:48,490 --> 01:03:53,790 Penso che fgetc è un po 'più facile, perché ha solo, come vedete, 761 01:03:53,790 --> 01:03:59,660 un argomento, il * file che stiamo cercando di leggere il carattere da, 762 01:03:59,660 --> 01:04:02,740 e il suo valore di ritorno è un int. 763 01:04:02,740 --> 01:04:05,610 E questo è un po 'di confusione, no? 764 01:04:05,610 --> 01:04:11,450 >> Perche 'e' un personaggio, quindi perché non questo ritorno un char? 765 01:04:11,450 --> 01:04:18,700 Voi ragazzi avete qualche idea sul perché questo potrebbe non restituire un char? 766 01:04:18,700 --> 01:04:25,510 [Risposte Missy, incomprensibile] >> Si '. Quindi Missy è totalmente ragione. 767 01:04:25,510 --> 01:04:31,570 Se è ASCII, allora questo numero intero può essere mappato a un carattere vero e proprio. 768 01:04:31,570 --> 01:04:33,520 Potrebbe essere un carattere ASCII, e che è di destra. 769 01:04:33,520 --> 01:04:36,220 Questo è esattamente ciò che sta accadendo. 770 01:04:36,220 --> 01:04:39,190 Stiamo utilizzando un int semplicemente perché ha più bit. 771 01:04:39,190 --> 01:04:44,750 E 'più grande di un char, il nostro char ha solo 8 bit, 1 byte che sulle nostre macchine a 32 bit. 772 01:04:44,750 --> 01:04:48,520 E un int ha un valore "tutti i 4 byte di spazio. 773 01:04:48,520 --> 01:04:50,940 E si scopre che il modo fgetc funziona, 774 01:04:50,940 --> 01:04:53,940 se scorrere verso il basso nella nostra sinossi in questa pagina uomo un po ', 775 01:04:53,940 --> 01:05:05,000 scorrere fino in fondo. Si scopre che usano questo valore speciale chiamato EOF. 776 01:05:05,000 --> 01:05:09,640 E 'una costante speciale come valore di ritorno della funzione fgetc 777 01:05:09,640 --> 01:05:14,570 ogni volta che si ha colpito la fine del file o se si verifica un errore. 778 01:05:14,570 --> 01:05:18,170 E si scopre che per fare questi confronti con EOF correttamente, 779 01:05:18,170 --> 01:05:24,060 si desidera avere tale importo supplementare di informazioni che si hanno in un int 780 01:05:24,060 --> 01:05:28,420 anziché utilizzare un char. 781 01:05:28,420 --> 01:05:32,130 Anche se fgetc è effettivamente ottenere un carattere da un file, 782 01:05:32,130 --> 01:05:38,450 si vuole ricordare che si sta tornando qualcosa che è di tipo int a voi. 783 01:05:38,450 --> 01:05:41,360 Detto questo, è abbastanza facile da usare. 784 01:05:41,360 --> 01:05:44,960 E 'intenzione di darci un personaggio, così tutto quello che dobbiamo fare è continuare a chiedere il file, 785 01:05:44,960 --> 01:05:48,440 "Dammi il carattere successivo, dammi il carattere successivo, dammi il carattere successivo," 786 01:05:48,440 --> 01:05:51,400 fino ad arrivare alla fine del file. 787 01:05:51,400 --> 01:05:54,730 E che farà rientrare un carattere alla volta da nostro file, 788 01:05:54,730 --> 01:05:56,250 e poi possiamo fare quello che ci pare. 789 01:05:56,250 --> 01:06:00,160 Possiamo memorizzare, possiamo aggiungere una stringa, possiamo stampare. 790 01:06:00,160 --> 01:06:04,630 Fare nulla di tutto ciò. 791 01:06:04,630 --> 01:06:09,600 >> Zoom indietro e tornare al nostro programma di Cat. C, 792 01:06:09,600 --> 01:06:16,170 se abbiamo intenzione di utilizzare fgetc, 793 01:06:16,170 --> 01:06:21,710 come potremmo affrontare questa riga di codice successiva? 794 01:06:21,710 --> 01:06:26,020 Stiamo per usare - fread farà qualcosa di leggermente diverso. 795 01:06:26,020 --> 01:06:32,600 E questa volta, stiamo solo andando a utilizzare fgetc per ottenere un carattere alla volta. 796 01:06:32,600 --> 01:06:40,910 Per elaborare un intero file, cosa potremmo fare? 797 01:06:40,910 --> 01:06:44,030 Quanti personaggi ci sono in un file? 798 01:06:44,030 --> 01:06:47,390 Ci sono un sacco. Quindi, probabilmente avrete bisogno di ottenere uno 799 01:06:47,390 --> 01:06:49,860 e quindi ottenere un altro e ottenere un altro e ottenere un altro. 800 01:06:49,860 --> 01:06:53,330 Che tipo di algoritmo pensi che potrebbe essere necessario usare qui? 801 01:06:53,330 --> 01:06:55,470 Che tipo di -? [Alexander] Un ciclo for? >> Esattamente. 802 01:06:55,470 --> 01:06:57,500 Alcuni tipi di loop. 803 01:06:57,500 --> 01:07:03,380 Un ciclo for è effettivamente grande, in questo caso. 804 01:07:03,380 --> 01:07:08,620 E come dicevi, suona come si desidera un loop sopra l'intero file, 805 01:07:08,620 --> 01:07:11,820 ottenere un carattere per volta. 806 01:07:11,820 --> 01:07:13,850 Qualche suggerimento su ciò che potrebbe apparire come? 807 01:07:13,850 --> 01:07:22,090 [Alexander, incomprensibile] 808 01:07:22,090 --> 01:07:30,050 >> Va bene, dimmi solo in inglese quello che stai cercando di fare? [Alexander, incomprensibile] 809 01:07:30,050 --> 01:07:36,270 Quindi, in questo caso, sembra che stiamo solo cercando di eseguire un loop l'intero file. 810 01:07:36,270 --> 01:07:45,330 [Alexander] Così ho > La dimensione di -? 811 01:07:45,330 --> 01:07:49,290 Credo che la dimensione del file, giusto? Le dimensioni - we'll basta scrivere in questo modo. 812 01:07:49,290 --> 01:07:57,470 Dimensione del file per il momento, i + +. 813 01:07:57,470 --> 01:08:04,610 Così si scopre che il modo in cui si esegue questa operazione utilizzando fgetc, e questa è una novità, 814 01:08:04,610 --> 01:08:10,460 è che non c'è un modo facile per ottenere solo la dimensione di un file 815 01:08:10,460 --> 01:08:16,979 con questo tipo "sizeof" di costrutto che hai visto prima. 816 01:08:16,979 --> 01:08:20,910 Quando si usa questa funzione fgetc, stiamo introducendo una sorta di 817 01:08:20,910 --> 01:08:29,069 nuovo, sintassi funky a questo ciclo for, dove invece di usare solo un contatore di base 818 01:08:29,069 --> 01:08:33,920 andare carattere per carattere, che andremo a tirare un carattere alla volta, 819 01:08:33,920 --> 01:08:37,120 un carattere alla volta, e il modo in cui sappiamo di essere alla fine 820 01:08:37,120 --> 01:08:41,290 non è quando abbiamo contato un certo numero di caratteri, 821 01:08:41,290 --> 01:08:49,939 ma quando il personaggio che tira fuori è che fine speciale di carattere file. 822 01:08:49,939 --> 01:08:58,689 Così siamo in grado di farlo - Io chiamo questo ch, e stiamo andando a inizializzarlo 823 01:08:58,689 --> 01:09:08,050 con la nostra prima chiamata per ottenere il carattere della prima del file. 824 01:09:08,050 --> 01:09:14,979 Quindi questa parte qui, questo sta andando per ottenere un carattere dal file 825 01:09:14,979 --> 01:09:20,840 e memorizzarlo nella variabile ch. 826 01:09:20,840 --> 01:09:25,420 Abbiamo intenzione di continuare a fare questo fino ad arrivare alla fine del file, 827 01:09:25,420 --> 01:09:41,170 che facciamo un test di tipo carattere non essere uguale a quello speciale carattere EOF. 828 01:09:41,170 --> 01:09:48,750 E poi invece di fare ch + +, che sarebbe solo aumentare il valore, 829 01:09:48,750 --> 01:09:52,710 quindi se si legge una A dal file, la A maiuscola, per esempio, 830 01:09:52,710 --> 01:09:56,810 ch + + ci darebbe b, e poi ci piacerebbe avere e poi c d. 831 01:09:56,810 --> 01:09:59,310 Non è chiaro quello che vogliamo. Quello che vogliamo qui 832 01:09:59,310 --> 01:10:05,830 in questo ultimo bit è che vogliamo ottenere il carattere successivo dal file. 833 01:10:05,830 --> 01:10:09,500 >> Così come potremmo ottenere il carattere successivo dal file? 834 01:10:09,500 --> 01:10:13,470 Come ottenere il primo carattere dal file? 835 01:10:13,470 --> 01:10:17,200 [Studente] fgetfile? Fgetc >>, o, mi dispiace, avevi completamente ragione. 836 01:10:17,200 --> 01:10:20,470 L'ho scritto male proprio lì. Quindi sì. 837 01:10:20,470 --> 01:10:26,240 Qui invece di fare ch + +, 838 01:10:26,240 --> 01:10:29,560 stiamo solo andando a chiamare fgetc (file) di nuovo 839 01:10:29,560 --> 01:10:39,180 e memorizzare il risultato nella nostra variabile cap stesso. 840 01:10:39,180 --> 01:10:43,730 [Domanda Studente, incomprensibile] 841 01:10:43,730 --> 01:10:52,390 >> Questo è dove questi ragazzi FILE * sono speciali. 842 01:10:52,390 --> 01:10:59,070 Il loro modo di lavorare che è - quando si apre - la prima volta che fare quella chiamata fopen, 843 01:10:59,070 --> 01:11:04,260 * il file serve efficacemente come puntatore all'inizio del file. 844 01:11:04,260 --> 01:11:12,830 E poi ogni volta che si chiama fgetc, si muove un personaggio attraverso il file. 845 01:11:12,830 --> 01:11:23,280 Così ogni volta che si chiama questo, si sta incrementando il puntatore al file di un carattere. 846 01:11:23,280 --> 01:11:26,210 E quando fgetc ancora una volta, si sta muovendo un altro personaggio 847 01:11:26,210 --> 01:11:28,910 e un altro carattere e un altro personaggio e un altro personaggio. 848 01:11:28,910 --> 01:11:32,030 [Domanda Studente, incomprensibile] >> E that's - yeah. 849 01:11:32,030 --> 01:11:34,810 È un po 'di questa magia sotto il cofano. 850 01:11:34,810 --> 01:11:37,930 Devi solo continuare a incrementare attraverso. 851 01:11:37,930 --> 01:11:46,510 A questo punto, siete in grado di lavorare effettivamente con un carattere. 852 01:11:46,510 --> 01:11:52,150 Così come potremmo stampata allo schermo, ora? 853 01:11:52,150 --> 01:11:58,340 Possiamo usare la stessa cosa printf che abbiamo usato prima. 854 01:11:58,340 --> 01:12:00,330 Che abbiamo usato tutto il semestre. 855 01:12:00,330 --> 01:12:05,450 Possiamo chiamare printf, 856 01:12:05,450 --> 01:12:21,300 e siamo in grado di passare il carattere proprio così. 857 01:12:21,300 --> 01:12:27,430 Un altro modo per farlo è invece di usare printf e di dover fare questa stringa di formato, 858 01:12:27,430 --> 01:12:29,490 possiamo anche utilizzare una delle altre funzioni. 859 01:12:29,490 --> 01:12:40,090 Possiamo usare fputc, che stampa un carattere sullo schermo, 860 01:12:40,090 --> 01:12:52,580 tranne se guardiamo fputc - fammi diminuire un po '. 861 01:12:52,580 --> 01:12:56,430 Vediamo ciò che è bello è che ci vuole nel carattere che abbiamo letto con l'ausilio fgetc, 862 01:12:56,430 --> 01:13:05,100 ma allora dobbiamo dare un flusso di stampare. 863 01:13:05,100 --> 01:13:11,850 Si può anche usare la funzione putchar, che metterà direttamente fuori standard. 864 01:13:11,850 --> 01:13:16,070 Quindi ci sono un sacco di diverse opzioni che possiamo usare per la stampa. 865 01:13:16,070 --> 01:13:19,580 Sono tutti nella norma libreria I / O. 866 01:13:19,580 --> 01:13:25,150 Ogni volta che si desidera stampare - così printf, per impostazione predefinita, verrà stampata la norma speciale fuori corso d'acqua, 867 01:13:25,150 --> 01:13:27,910 che è quello stdout. 868 01:13:27,910 --> 01:13:41,300 Quindi possiamo solo fare riferimento ad esso come una sorta di magia questo valore, stdout qui. 869 01:13:41,300 --> 01:13:48,410 Oops. Mettere il punto e virgola fuori. 870 01:13:48,410 --> 01:13:52,790 >> Questo è un sacco di nuove informazioni funky qui. 871 01:13:52,790 --> 01:13:58,600 Molto di questo è molto idiomatica, nel senso che questo è codice 872 01:13:58,600 --> 01:14:05,700 ciò che è scritto in questo modo solo perché è pulito da leggere, facile da leggere. 873 01:14:05,700 --> 01:14:11,520 Ci sono molti modi per farlo, molte funzioni che si possono usare, 874 01:14:11,520 --> 01:14:14,680 ma si tende a seguire solo questi modelli più e più volte. 875 01:14:14,680 --> 01:14:20,180 Quindi non stupitevi se vedete il codice come il prossimo di nuovo e di nuovo. 876 01:14:20,180 --> 01:14:25,690 Bene. A questo punto, abbiamo bisogno di rompere per la giornata. 877 01:14:25,690 --> 01:14:31,300 Grazie per essere venuto. Grazie per la visione, se sei online. E ci vediamo la prossima settimana. 878 01:14:31,300 --> 01:14:33,890 [CS50.TV]