1 00:00:00,000 --> 00:00:02,730 [Powered by Google Translate] [SEÇÃO 5: menos confortável] 2 00:00:02,730 --> 00:00:05,180 [Nate Hardison, Harvard University] 3 00:00:05,180 --> 00:00:08,260 [Esta é CS50.] [CS50.TV] 4 00:00:08,260 --> 00:00:11,690 Então bem-vindo de volta, rapazes. 5 00:00:11,690 --> 00:00:16,320 Bem-vindo à secção 5. 6 00:00:16,320 --> 00:00:20,220 Neste ponto, tendo completado questionário 0 e tendo visto como você fez, 7 00:00:20,220 --> 00:00:25,770 espero que você se sentir realmente bem, porque eu estava muito impressionado com a pontuação nesta seção. 8 00:00:25,770 --> 00:00:28,050 Para os nossos espectadores on-line, nós tivemos um par de perguntas 9 00:00:28,050 --> 00:00:33,680 sobre os dois últimos problemas no conjunto de problemas - ou no questionário, em vez. 10 00:00:33,680 --> 00:00:39,690 Então, nós estamos indo ir sobre os muito rapidamente, de modo que toda a gente vê o que aconteceu 11 00:00:39,690 --> 00:00:45,060 e como ir através da solução real e não apenas visualizar a solução em si. 12 00:00:45,060 --> 00:00:50,330 Nós vamos passar por cima o último par de problemas muito rapidamente, 32 e 33. 13 00:00:50,330 --> 00:00:53,240 Assim, mais uma vez, para que os espectadores online pode ver isso. 14 00:00:53,240 --> 00:00:59,080 >> Se você ligar para o seu problema 32, que está na página 13, 15 00:00:59,080 --> 00:01:02,730 13 de 16, problema 32 é tudo sobre swaps. 16 00:01:02,730 --> 00:01:05,010 Era tudo sobre a troca de dois inteiros. 17 00:01:05,010 --> 00:01:08,740 É o problema que tinha ido ao longo de um par de vezes em palestra. 18 00:01:08,740 --> 00:01:13,590 E aqui, o que estávamos pedindo para você fazer é um traço de memória rápida. 19 00:01:13,590 --> 00:01:17,000 Para preencher os valores das variáveis ​​que estão na pilha 20 00:01:17,000 --> 00:01:20,250 como o código passa por esta função swap. 21 00:01:20,250 --> 00:01:24,500 Em particular, o que nós estamos olhando - eu vou colocar esse iPad para baixo - 22 00:01:24,500 --> 00:01:29,650 em particular, o que estamos vendo é esta linha numerada 6 aqui. 23 00:01:29,650 --> 00:01:36,740 E é numerada 6 por apenas contiguidade com o problema anterior. 24 00:01:36,740 --> 00:01:41,720 O que queremos fazer é mostrar ou rotular o estado da memória 25 00:01:41,720 --> 00:01:46,090 como é na altura em que se executa este número da linha 6, 26 00:01:46,090 --> 00:01:52,540 que é efetivamente um retorno de nossa função swap aqui. 27 00:01:52,540 --> 00:01:59,450 Se rolar aqui, vimos que os endereços de tudo na memória foi fornecido por nós. 28 00:01:59,450 --> 00:02:02,540 Isso é muito fundamental, nós vamos voltar a ele em apenas um momento. 29 00:02:02,540 --> 00:02:09,240 E então, aqui em baixo, na parte inferior, tivemos um diagrama de pouca memória que vamos referir. 30 00:02:09,240 --> 00:02:12,490 Eu realmente fiz isso no meu iPad. 31 00:02:12,490 --> 00:02:20,720 Então, eu estou indo para alternar rapidamente entre o iPad e este código apenas para referência. 32 00:02:20,720 --> 00:02:26,540 >> Vamos começar. Primeiro, vamos nos concentrar no primeiro par de linhas de principal aqui. 33 00:02:26,540 --> 00:02:30,220 Para começar, vamos inicializar x e y a 1 para 2. 34 00:02:30,220 --> 00:02:33,040 Portanto, temos duas variáveis ​​inteiras, ambos estão indo para ser colocado na pilha. 35 00:02:33,040 --> 00:02:36,050 Nós vamos colocar um 1 e um 2 neles. 36 00:02:36,050 --> 00:02:43,150 Então, se eu virar para o meu iPad, esperamos, vamos ver - 37 00:02:43,150 --> 00:02:48,660 A Apple espelhamento de TV, e lá vamos nós. Okay. 38 00:02:48,660 --> 00:02:51,670 Então, se eu virar para o meu iPad, 39 00:02:51,670 --> 00:02:56,220 Eu quero inicializar x e y a 1 para 2. 40 00:02:56,220 --> 00:03:00,580 Fazemos isso simplesmente escrevendo um 1 na caixa marcada x 41 00:03:00,580 --> 00:03:07,730 e um 2 na caixa marcada y. Bastante simples. 42 00:03:07,730 --> 00:03:11,620 Então agora vamos voltar para o laptop, ver o que acontece. 43 00:03:11,620 --> 00:03:15,810 Então esta linha seguinte é onde as coisas ficam complicadas. 44 00:03:15,810 --> 00:03:28,110 Nós passar o endereço de x e y o endereço de como os parâmetros a e b para a função de troca. 45 00:03:28,110 --> 00:03:32,380 O endereço de x e o endereço de y são coisas que não podemos calcular 46 00:03:32,380 --> 00:03:36,360 sem se referir a estes bala aponta para a direita aqui. 47 00:03:36,360 --> 00:03:39,750 E, felizmente, os dois primeiros pontos de bala nos dizer exatamente quais são as respostas. 48 00:03:39,750 --> 00:03:44,740 O endereço de memória de x é 10, e o endereço na memória de y é 14. 49 00:03:44,740 --> 00:03:51,870 Então esses são os valores que são passados ​​como a e b em cima da nossa função swap. 50 00:03:51,870 --> 00:04:00,760 Então, novamente, retornar para o nosso diagrama, eu posso escrever um 10 em um 51 00:04:00,760 --> 00:04:07,400 e 14 um em b. 52 00:04:07,400 --> 00:04:11,610 Agora, este ponto é onde nós prosseguir com a troca. 53 00:04:11,610 --> 00:04:14,520 Então, lançando de volta para o laptop de novo, 54 00:04:14,520 --> 00:04:21,079 vemos que a forma como o swap funciona é que eu dereference primeiro uma loja e o resultado em tmp. 55 00:04:21,079 --> 00:04:27,650 Assim, o operador dereference diz, "Hey. Tratar o conteúdo de uma variável como um endereço. 56 00:04:27,650 --> 00:04:33,830 Vá para o que está armazenado naquele endereço, e carregá-lo. " 57 00:04:33,830 --> 00:04:41,720 O que você carrega para fora da variável que vai ser armazenado em nossa variável tmp. 58 00:04:41,720 --> 00:04:45,150 Lançando de volta para o iPad. 59 00:04:45,150 --> 00:04:51,690 Se formos para tratar 10, sabemos que é o endereço de 10 x varible 60 00:04:51,690 --> 00:04:55,480 porque foi dito pelo nosso ponto de bala que o endereço de x em memória é 10. 61 00:04:55,480 --> 00:05:00,180 Então, nós podemos ir lá, pegar o valor do mesmo, o que é um, como podemos ver em nosso iPad, 62 00:05:00,180 --> 00:05:06,300 e carregar isso em tmp. 63 00:05:06,300 --> 00:05:08,250 Novamente, isto não é o conteúdo final. 64 00:05:08,250 --> 00:05:14,350 Nós vamos caminhar e nós vamos chegar ao nosso estado final do programa no final. 65 00:05:14,350 --> 00:05:17,210 Mas, agora, temos o valor armazenado em um tmp. 66 00:05:17,210 --> 00:05:19,210 >> E há uma pergunta rápida aqui. 67 00:05:19,210 --> 00:05:23,980 [Alexander] é o operador dereference - que é apenas o direito de estrela na frente da variável? 68 00:05:23,980 --> 00:05:27,600 Sim >>. Assim, o operador dereference, como virar de volta para o nosso laptop, mais uma vez, 69 00:05:27,600 --> 00:05:33,780 é esta estrela em frente. 70 00:05:33,780 --> 00:05:37,460 Nesse sentido, ele é - você compará-lo com o operador de multiplicação 71 00:05:37,460 --> 00:05:42,400 que requer duas coisas: o operador dereference é um operador unário. 72 00:05:42,400 --> 00:05:46,130 Apenas aplicada a um valor, por oposição a um operador binário, 73 00:05:46,130 --> 00:05:48,810 onde você aplica a dois valores diferentes. 74 00:05:48,810 --> 00:05:52,080 Então, isso é o que acontece nesta linha. 75 00:05:52,080 --> 00:05:58,390 Nós carregamos o valor 1 e é armazenado em nosso variável temporária inteiro. 76 00:05:58,390 --> 00:06:05,800 A próxima linha, armazenamos o conteúdo de b em - 77 00:06:05,800 --> 00:06:12,630 ou, em vez disso, armazenar o conteúdo que b está apontando para o lugar onde um está apontando. 78 00:06:12,630 --> 00:06:17,690 Se analisarmos este da direita para a esquerda, vamos b dereference, 79 00:06:17,690 --> 00:06:23,580 vamos abordar 14, vamos pegar o número inteiro que está lá, 80 00:06:23,580 --> 00:06:26,900 e então nós estamos indo para ir para o endereço 10, 81 00:06:26,900 --> 00:06:34,240 e vamos jogar o resultado da nossa dereference de b em que o espaço. 82 00:06:34,240 --> 00:06:40,080 Lançando de volta ao nosso iPad, onde podemos fazer isso um pouco mais concreto, 83 00:06:40,080 --> 00:06:44,070 que poderia ajudar se eu escrever números em todos os endereços aqui. 84 00:06:44,070 --> 00:06:53,820 Então, nós sabemos que, y, estamos no endereço 14, x está no endereço 10. 85 00:06:53,820 --> 00:07:00,180 Quando começamos a b, b dereference, vamos pegar o valor 2. 86 00:07:00,180 --> 00:07:08,320 Nós vamos pegar esse valor porque esse é o valor que vive no endereço 14. 87 00:07:08,320 --> 00:07:15,700 E nós vamos colocá-lo na variável que vive no endereço 10, 88 00:07:15,700 --> 00:07:19,160 que está ali, correspondente à nossa variável x. 89 00:07:19,160 --> 00:07:21,810 Assim, podemos fazer um pouco de sobrescrever aqui 90 00:07:21,810 --> 00:07:35,380 onde vamos nos livrar de nosso 1 e em vez disso, escreva uma 2. 91 00:07:35,380 --> 00:07:39,560 Então está tudo bem e bom no mundo, mesmo que tenhamos x sobrescritos agora. 92 00:07:39,560 --> 00:07:44,890 Temos armazenados valor antigo de x em nossa variável tmp. 93 00:07:44,890 --> 00:07:50,210 Assim, podemos completar a troca com a linha seguinte. 94 00:07:50,210 --> 00:07:53,030 Lançando de volta para o nosso laptop. 95 00:07:53,030 --> 00:07:58,150 Agora tudo o que resta é levar o conteúdo de nossa variável temporária inteiro 96 00:07:58,150 --> 00:08:05,630 e armazená-los na variável que vive no endereço que b está segurando. 97 00:08:05,630 --> 00:08:10,230 Então, nós vamos efetivamente b dereference para obter acesso à variável 98 00:08:10,230 --> 00:08:14,340 isto é, no endereço que b tem nele, 99 00:08:14,340 --> 00:08:19,190 e nós vamos encher o valor que tmp está segurando para ele. 100 00:08:19,190 --> 00:08:23,280 Lançando de volta para o iPad mais uma vez. 101 00:08:23,280 --> 00:08:31,290 Eu posso apagar este valor aqui, 2, 102 00:08:31,290 --> 00:08:41,010 e em vez disso vamos copiar o direito um para ele. 103 00:08:41,010 --> 00:08:43,059 Em seguida, a próxima linha que executa, é claro - 104 00:08:43,059 --> 00:08:47,150 se jogarmos de volta para o laptop - é este o ponto 6, 105 00:08:47,150 --> 00:08:52,500 que é o ponto em que nós queríamos ter o nosso diagrama completamente preenchido. 106 00:08:52,500 --> 00:08:58,940 Então, lançando de volta para o iPad, uma vez mais, só assim você pode ver o diagrama completo, 107 00:08:58,940 --> 00:09:06,610 você pode ver que temos um 10 em um, 14 em um b, a 1 em tmp, um 2 em x, e um 1 em y. 108 00:09:06,610 --> 00:09:11,000 Há alguma dúvida sobre isso? 109 00:09:11,000 --> 00:09:14,640 Será que isto faz mais sentido, tendo orientado por ela? 110 00:09:14,640 --> 00:09:24,850 Fazer menos sentido? Esperemos que não. Okay. 111 00:09:24,850 --> 00:09:28,230 >> Os ponteiros são um assunto muito complicado. 112 00:09:28,230 --> 00:09:33,420 Um dos caras que trabalham com tem um ditado muito comum: 113 00:09:33,420 --> 00:09:36,590 "Para entender os ponteiros, você deve primeiro entender os ponteiros". 114 00:09:36,590 --> 00:09:40,530 Que eu acho que é muito verdadeiro. Ele faz demorar um pouco para se acostumar com isso. 115 00:09:40,530 --> 00:09:45,360 Sorteio de fotos, sorteio de diagramas de memória como esta são muito útil, 116 00:09:45,360 --> 00:09:49,480 e depois de andar por exemplo após exemplo após exemplo, 117 00:09:49,480 --> 00:09:54,450 ele vai começar a fazer sentido um pouco mais e sentido um pouco mais e um pouco mais de sentido. 118 00:09:54,450 --> 00:10:01,560 Finalmente, um dia, você vai ter tudo completamente dominado. 119 00:10:01,560 --> 00:10:13,800 Quaisquer dúvidas, antes de passar para o próximo problema? Tudo bem. 120 00:10:13,800 --> 00:10:18,840 Então virar para trás para o laptop. 121 00:10:18,840 --> 00:10:23,300 O próximo problema que temos é o problema número 33 no arquivo de I / O. 122 00:10:23,300 --> 00:10:26,350 Zoom sobre isso um pouco. 123 00:10:26,350 --> 00:10:28,710 Problema 33 - Sim? 124 00:10:28,710 --> 00:10:32,110 >> [Daniel] Eu só tinha uma pergunta rápida. Esta estrela, ou o asterisco, 125 00:10:32,110 --> 00:10:35,590 ele é chamado dereferencing quando você usa um asterisco antes. 126 00:10:35,590 --> 00:10:38,820 Como se chama quando você usa o comercial antes? 127 00:10:38,820 --> 00:10:43,140 >> O comercial antes é o endereço do operador. 128 00:10:43,140 --> 00:10:45,880 Então, vamos rolar de volta. 129 00:10:45,880 --> 00:10:49,310 Oops. Eu estou no modo de zoom, então não posso realmente rolagem. 130 00:10:49,310 --> 00:10:52,780 Se olharmos para esse código realmente rápido aqui, 131 00:10:52,780 --> 00:10:54,980 novamente, a mesma coisa acontecendo. 132 00:10:54,980 --> 00:10:59,180 Se olharmos para este código aqui, nesta linha onde fazemos a chamada para trocar, 133 00:10:59,180 --> 00:11:10,460 o comercial é apenas dizer "obter o endereço em que vive a variável x." 134 00:11:10,460 --> 00:11:14,460 Quando o compilador compila seu código, 135 00:11:14,460 --> 00:11:20,590 tem que fisicamente marcar um lugar na memória de todos os seus variáveis ​​para viver. 136 00:11:20,590 --> 00:11:24,910 E assim o que o compilador pode então fazer uma vez que é compilado tudo, 137 00:11:24,910 --> 00:11:31,110 ele sabe, "Oh, eu coloquei no endereço x 10. coloquei y no endereço 14." 138 00:11:31,110 --> 00:11:34,640 Ele pode, então, preencher estes valores para você. 139 00:11:34,640 --> 00:11:44,740 Assim, você pode então - ele pode passar este e passe & y no bem. 140 00:11:44,740 --> 00:11:50,730 Esses caras obter o endereço, mas também, quando você passá-los para a função swap, 141 00:11:50,730 --> 00:11:55,690 este tipo de informação, este int * aqui, diz o compilador, 142 00:11:55,690 --> 00:12:01,350 "Ok, nós vamos estar interpretando esse endereço como um endereço de uma variável inteira." 143 00:12:01,350 --> 00:12:05,900 Como um endereço de um inteiro, que é diferente do endereço de uma variável de caracteres 144 00:12:05,900 --> 00:12:09,930 porque um int toma-se, em uma máquina de 32 bits, ocupa 4 bytes de espaço, 145 00:12:09,930 --> 00:12:13,310 enquanto um único personagem ocupa 1 byte de espaço. 146 00:12:13,310 --> 00:12:17,310 Por isso, é importante saber também o que é - o que vive, que tipo de valor 147 00:12:17,310 --> 00:12:20,340 está a viver no endereço que foi passado dentro 148 00:12:20,340 --> 00:12:22,020 Ou o endereço que você está lidando. 149 00:12:22,020 --> 00:12:29,020 Dessa forma, você sabe quantos bytes de informações para realmente carregar de sua memória RAM. 150 00:12:29,020 --> 00:12:31,780 E então, sim, este operador dereference, como se estivesse perguntando: 151 00:12:31,780 --> 00:12:37,200 vai e acessa informações em um endereço particular. 152 00:12:37,200 --> 00:12:42,820 Por isso, diz, com esta variável um aqui, tratar o conteúdo de um como endereço, 153 00:12:42,820 --> 00:12:47,880 ir para esse endereço, e puxar, carregar no processador, a carga em um registrador 154 00:12:47,880 --> 00:12:56,340 os valores reais ou os conteúdos que vivem naquele endereço. 155 00:12:56,340 --> 00:12:59,620 Mais alguma pergunta? Essas são boas perguntas. 156 00:12:59,620 --> 00:13:01,650 É um monte de nova terminologia também. 157 00:13:01,650 --> 00:13:09,800 É também uma espécie de funk, vendo & * e em lugares diferentes. 158 00:13:09,800 --> 00:13:13,180 >> Tudo bem. 159 00:13:13,180 --> 00:13:18,530 Então, de volta para o problema de 33, arquivo I / O. 160 00:13:18,530 --> 00:13:22,540 Este foi um daqueles problemas que eu acho que um par de coisas aconteceu. 161 00:13:22,540 --> 00:13:25,400 Um, é um tema relativamente novo. 162 00:13:25,400 --> 00:13:30,590 Ele foi apresentado logo antes do teste, 163 00:13:30,590 --> 00:13:33,400 e então eu acho que foi mais ou menos como um daqueles problemas de palavras em matemática 164 00:13:33,400 --> 00:13:39,720 onde eles dão-lhe um monte de informações, mas você realmente não acabar tendo que usar uma tonelada do mesmo. 165 00:13:39,720 --> 00:13:44,060 A primeira parte deste problema está descrevendo o que é um arquivo CSV. 166 00:13:44,060 --> 00:13:50,620 Agora, um arquivo CSV, de acordo com a descrição, é um arquivo separado por vírgulas valores. 167 00:13:50,620 --> 00:13:55,300 A razão, são em tudo interessante, ea razão pela qual você nunca usá-los, 168 00:13:55,300 --> 00:14:00,800 é, pois, como muitos de vocês já usou o material como o Excel? 169 00:14:00,800 --> 00:14:03,240 Figura maioria de vocês, provavelmente, ou vai usar em algum momento de sua vida. 170 00:14:03,240 --> 00:14:06,430 Você vai usar algo como o Excel. 171 00:14:06,430 --> 00:14:10,940 A fim de obter os dados de uma planilha do Excel ou fazer qualquer tipo de tratamento com ele, 172 00:14:10,940 --> 00:14:17,240 se você queria escrever um programa em C ou Python programa, o programa Java, 173 00:14:17,240 --> 00:14:20,070 para lidar com os dados armazenados lá, 174 00:14:20,070 --> 00:14:23,170 uma das formas mais comuns para tirá-lo está em um arquivo CSV. 175 00:14:23,170 --> 00:14:26,850 E você pode abrir o Excel e quando você vai para a 'Salvar como' o diálogo, 176 00:14:26,850 --> 00:14:32,840 você pode sair um arquivo CSV real. 177 00:14:32,840 --> 00:14:35,890 >> Útil para saber como lidar com essas coisas. 178 00:14:35,890 --> 00:14:42,010 O modo como funciona é que ele é semelhante a - Quero dizer, ele é essencialmente imitando uma planilha, 179 00:14:42,010 --> 00:14:47,590 onde, como vemos aqui, na peça muito mais à esquerda, 180 00:14:47,590 --> 00:14:49,910 temos todos os últimos nomes. 181 00:14:49,910 --> 00:14:54,670 Assim, temos Malan, então Hardison, e, em seguida, Bowden, MacWilliam, e, em seguida, Chan. 182 00:14:54,670 --> 00:14:59,470 Todos os sobrenomes. E então uma vírgula separa os sobrenomes dos primeiros nomes. 183 00:14:59,470 --> 00:15:02,970 David, Nate, Rob, Tommy, e Zamyla. 184 00:15:02,970 --> 00:15:06,850 Eu sempre misturar Robby e Tom. 185 00:15:06,850 --> 00:15:10,940 E, em seguida, finalmente, a terceira coluna é os endereços de e-mail. 186 00:15:10,940 --> 00:15:18,500 Depois de entender isso, o resto do programa é bastante simples de implementar. 187 00:15:18,500 --> 00:15:23,850 O que temos feito, a fim de imitar essa mesma estrutura em nosso programa C 188 00:15:23,850 --> 00:15:27,510 é que usei uma estrutura. 189 00:15:27,510 --> 00:15:30,520 Vamos começar a jogar com estes mais um pouco também. 190 00:15:30,520 --> 00:15:35,790 Vimo-los para o primeiro bit pouco no conjunto de problemas 3, quando estávamos lidando com os dicionários. 191 00:15:35,790 --> 00:15:40,290 Mas essa estrutura pessoal armazena um último nome, um primeiro nome e um e-mail. 192 00:15:40,290 --> 00:15:44,500 Assim como o nosso arquivo CSV foi guardar. 193 00:15:44,500 --> 00:15:47,950 Portanto, esta é apenas a conversão de um formato para outro. 194 00:15:47,950 --> 00:15:54,630 Temos de converter, neste caso, uma estrutura pessoal para uma linha, 195 00:15:54,630 --> 00:15:59,060 uma linha separada por vírgulas, apenas como aquele. 196 00:15:59,060 --> 00:16:01,500 Isso faz sentido? Vocês têm todos levados ao questionário, 197 00:16:01,500 --> 00:16:07,680 então eu imagino que você tenha pelo menos teve algum tempo para pensar sobre isso. 198 00:16:07,680 --> 00:16:16,410 >> Na função de aluguer, o problema nos pede para tomar - zoom em we'll sobre isso um pouco - 199 00:16:16,410 --> 00:16:22,480 tomar em uma estrutura de pessoal, uma estrutura de pessoal, com o nome de s, 200 00:16:22,480 --> 00:16:30,900 e anexar o seu conteúdo para o nosso arquivo staff.csv. 201 00:16:30,900 --> 00:16:34,230 Acontece que isso é bastante simples de usar. 202 00:16:34,230 --> 00:16:37,430 Vamos tipo de brincar com essas funções hoje um pouco mais. 203 00:16:37,430 --> 00:16:44,510 Mas, neste caso, a função fprintf é realmente a chave. 204 00:16:44,510 --> 00:16:51,960 Assim, com fprintf, podemos imprimir, assim como vocês têm vindo a utilizar este termo printf todo. 205 00:16:51,960 --> 00:16:55,050 Você pode printf uma linha de um arquivo. 206 00:16:55,050 --> 00:16:59,030 Então, em vez de apenas fazer a chamada de costume printf onde você dá a ele a cadeia de formato 207 00:16:59,030 --> 00:17:05,380 e depois de substituir todas as variáveis ​​com os seguintes argumentos, 208 00:17:05,380 --> 00:17:11,290 com fprintf, seu argumento é muito primeira vez o arquivo que você deseja gravar. 209 00:17:11,290 --> 00:17:21,170 Se estivéssemos a olhar para isso no aparelho, por exemplo, o homem fprintf, 210 00:17:21,170 --> 00:17:25,980 podemos ver a diferença entre o printf e fprintf. 211 00:17:25,980 --> 00:17:28,960 Eu vou ampliar um pouco aqui. 212 00:17:28,960 --> 00:17:33,140 Assim, com printf, nós dar-lhe uma seqüência de formato, e depois os argumentos subseqüentes 213 00:17:33,140 --> 00:17:37,580 são todas as variáveis ​​para reposição ou substituição em nossa cadeia de formato. 214 00:17:37,580 --> 00:17:47,310 Considerando que, com fprintf, o primeiro argumento é de fato esse * arquivo chamado um córrego. 215 00:17:47,310 --> 00:17:51,800 >> Voltando aqui para a nossa contratação, 216 00:17:51,800 --> 00:17:54,550 nós já temos o nosso fluxo * arquivo aberto para nós. 217 00:17:54,550 --> 00:17:57,810 Isso é o que faz esta primeira linha, que abre o arquivo staff.csv, 218 00:17:57,810 --> 00:18:01,690 ele abre em modo incremental, e tudo o que resta para nós é 219 00:18:01,690 --> 00:18:08,640 escrever a estrutura de pessoal para o arquivo. 220 00:18:08,640 --> 00:18:10,870 E, vamos ver, eu quero usar o iPad? 221 00:18:10,870 --> 00:18:17,900 Vou usar o iPad. Temos vazio - vamos colocar isso na mesa para que eu possa escrever um pouco melhor - 222 00:18:17,900 --> 00:18:33,680 anular a contratação e que leva, em um argumento, uma estrutura de equipe chamado s. 223 00:18:33,680 --> 00:18:44,120 Temos os nossos aparelhos, temos a nossa * arquivo chamado arquivo, 224 00:18:44,120 --> 00:18:48,380 nós temos nossa linha fopen dada a nós, 225 00:18:48,380 --> 00:18:51,890 e eu vou escrevê-lo como pontos, uma vez que já está no pedia. 226 00:18:51,890 --> 00:19:00,530 E então, em nossa próxima linha, vamos fazer uma chamada para fprintf 227 00:19:00,530 --> 00:19:03,700 e vamos passar o arquivo que deseja imprimir, 228 00:19:03,700 --> 00:19:10,290 e então nossa cadeia de formato, que - 229 00:19:10,290 --> 00:19:14,300 Eu vou deixar vocês me dizer o que parece. 230 00:19:14,300 --> 00:19:20,500 E você, Stella? Você sabe o que a primeira parte da cadeia de formato parece? 231 00:19:20,500 --> 00:19:24,270 [Stella] Eu não tenho certeza. Sinta-se livre para >> pedir Jimmy. 232 00:19:24,270 --> 00:19:27,690 Sabe, Jimmy? 233 00:19:27,690 --> 00:19:31,000 [Jimmy] Seria apenas ser o último? Eu não sei. Eu não estou totalmente certo. 234 00:19:31,000 --> 00:19:39,020 Ok >>. Que tal, será que alguém receber este correta no exame? 235 00:19:39,020 --> 00:19:41,770 Não. Tudo bem. 236 00:19:41,770 --> 00:19:47,920 Acontece que aqui tudo o que temos a fazer é que queremos cada parte de nosso quadro de pessoal 237 00:19:47,920 --> 00:19:53,290 para ser impresso como uma string em nosso arquivo. 238 00:19:53,290 --> 00:19:59,900 Nós só usar o personagem substituição corda três vezes diferentes, porque temos um sobrenome 239 00:19:59,900 --> 00:20:07,160 seguido por vírgula, um primeiro nome seguido de uma vírgula, 240 00:20:07,160 --> 00:20:12,430 e, finalmente, o endereço de e-mail que é seguido - o que não é 241 00:20:12,430 --> 00:20:15,140 encaixando na minha tela - mas é seguido por um caractere de nova linha. 242 00:20:15,140 --> 00:20:20,060 Então eu vou escrever isso só lá em baixo. 243 00:20:20,060 --> 00:20:23,560 E então, após a nossa seqüência de formato, 244 00:20:23,560 --> 00:20:27,880 só temos as substituições, que temos acesso usando a notação de ponto 245 00:20:27,880 --> 00:20:31,370 que vimos no conjunto de problemas 3. 246 00:20:31,370 --> 00:20:48,820 Podemos usar s.last, s.first e s.email 247 00:20:48,820 --> 00:20:58,990 para substituir nos três valores em nossa cadeia de formato. 248 00:20:58,990 --> 00:21:06,190 Então, como foi isso? Faz sentido? 249 00:21:06,190 --> 00:21:09,700 Sim? Não? Possivelmente? Okay. 250 00:21:09,700 --> 00:21:14,180 >> A última coisa que fazemos depois que nós impresso e depois abrimos o nosso arquivo: 251 00:21:14,180 --> 00:21:17,370 sempre que você abriu um arquivo, temos sempre que lembrar de fechá-lo. 252 00:21:17,370 --> 00:21:19,430 Porque, do contrário vamos acabar vazando a memória, 253 00:21:19,430 --> 00:21:22,500 utilizando-se descritores de arquivos. 254 00:21:22,500 --> 00:21:25,950 Então, para fechá-lo, qual a função que vamos usar? Daniel? 255 00:21:25,950 --> 00:21:30,120 [Daniel] fclose? >> Fclose, exatamente. 256 00:21:30,120 --> 00:21:37,520 Assim, a última parte deste problema era fechar corretamente o arquivo, usando a função fclose, 257 00:21:37,520 --> 00:21:40,370 que apenas se parece com isso. 258 00:21:40,370 --> 00:21:43,880 Não é muito louco. 259 00:21:43,880 --> 00:21:46,990 Cool. 260 00:21:46,990 --> 00:21:49,520 Então, isso é problema de 33 no questionário. 261 00:21:49,520 --> 00:21:52,480 Nós vamos ter de arquivo definitivamente mais I / O chegando. 262 00:21:52,480 --> 00:21:55,130 Vamos fazer um pouco mais em palestra hoje, ou na seção de hoje, 263 00:21:55,130 --> 00:22:01,710 porque é isso que vai formar a maior parte deste pset próximo. 264 00:22:01,710 --> 00:22:05,020 Vamos seguir em frente a partir do questionário neste momento. Sim? 265 00:22:05,020 --> 00:22:10,880 >> [Charlotte]] Por que fclose (arquivo) em vez de fclose (staff.csv)? 266 00:22:10,880 --> 00:22:19,100 Ah >>. Porque acontece que - para a questão, que é um grande, 267 00:22:19,100 --> 00:22:27,800 é por isso que, quando escrevemos fclose, estamos escrevendo fclose estrela variável (arquivo) 268 00:22:27,800 --> 00:22:33,680 em oposição ao nome do arquivo, staff.csv? Isso está correto? Sim. 269 00:22:33,680 --> 00:22:39,570 Então, vamos dar uma olhada. Se eu voltar para o meu laptop, 270 00:22:39,570 --> 00:22:45,040 e vamos olhar para a função fclose. 271 00:22:45,040 --> 00:22:51,460 Assim, a função fclose fecha um córrego e leva no ponteiro para o fluxo que deseja fechar 272 00:22:51,460 --> 00:22:57,010 em oposição ao nome real do arquivo que deseja fechar. 273 00:22:57,010 --> 00:23:01,620 E isto porque, nos bastidores, quando você faz uma chamada para fopen, 274 00:23:01,620 --> 00:23:12,020 quando você abrir um arquivo, você está, na verdade, a alocação de memória para armazenar informações sobre o arquivo. 275 00:23:12,020 --> 00:23:16,380 Então você tem um ponteiro de arquivo que contém informações sobre o arquivo, 276 00:23:16,380 --> 00:23:23,080 como ele é aberto, seu tamanho, onde está atualmente no arquivo, 277 00:23:23,080 --> 00:23:29,100 de modo que você pode fazer chamadas de leitura e escrita para aquele lugar especial dentro do arquivo. 278 00:23:29,100 --> 00:23:38,060 Você acaba de fechar o ponteiro em vez de fechar o nome do arquivo. 279 00:23:38,060 --> 00:23:48,990 >> Sim? [Daniel] Portanto, a fim de usar de aluguer, você diria que - como se obter a entrada do usuário? 280 00:23:48,990 --> 00:23:53,830 O fprintf agir como GetString no sentido de que ele só vai esperar a entrada do usuário 281 00:23:53,830 --> 00:23:57,180 e pedir-lhe para escrever isso - ou esperar para você digitar essas três coisas em? 282 00:23:57,180 --> 00:24:00,480 Ou você precisa de usar algo para implementar aluguer? 283 00:24:00,480 --> 00:24:04,100 Sim >>. Então, nós não somos - a questão foi, como é que vamos chegar a entrada do usuário 284 00:24:04,100 --> 00:24:09,220 a fim de implementar aluguer? E o que temos aqui é o chamador de aluguer, 285 00:24:09,220 --> 00:24:17,690 passaram neste struct pessoal com todos os dados armazenados na estrutura já. 286 00:24:17,690 --> 00:24:22,990 Então fprintf é capaz de escrever apenas que os dados diretamente para o arquivo. 287 00:24:22,990 --> 00:24:25,690 Não há espera para a entrada do usuário. 288 00:24:25,690 --> 00:24:32,110 O usuário já está dada a entrada corretamente por colocá-lo nessa estrutura de pessoal. 289 00:24:32,110 --> 00:24:36,510 E as coisas, é claro, iria quebrar se algum desses ponteiros foram nulos, 290 00:24:36,510 --> 00:24:40,370 para que rolar para trás até aqui e olhamos para a nossa estrutura. 291 00:24:40,370 --> 00:24:43,640 Temos string string ultimo primeiro, e-mail string. 292 00:24:43,640 --> 00:24:48,530 Agora sabemos que todos aqueles realmente, sob o capô, são variáveis ​​char *. 293 00:24:48,530 --> 00:24:53,470 Isso pode ou não pode estar apontando para nulo. 294 00:24:53,470 --> 00:24:55,800 Eles podem estar apontando para a memória na pilha, 295 00:24:55,800 --> 00:24:59,650 talvez memória na pilha. 296 00:24:59,650 --> 00:25:04,580 Nós realmente não sei, mas se qualquer um desses ponteiros são nulos ou inválidos, 297 00:25:04,580 --> 00:25:08,120 que isso definitivamente vai falhar a nossa função de aluguer. 298 00:25:08,120 --> 00:25:11,050 Isso era algo que estava meio fora do escopo do exame. 299 00:25:11,050 --> 00:25:16,440 Nós não está se preocupando com isso. 300 00:25:16,440 --> 00:25:22,170 Grande. Okay. Então passar do quiz. 301 00:25:22,170 --> 00:25:25,760 >> Vamos fechar esse cara, e nós estamos indo olhar pset 4. 302 00:25:25,760 --> 00:25:34,700 Então, se vocês olhar para a especificação pset, uma vez que você pode acessá-lo, cs50.net/quizzes, 303 00:25:34,700 --> 00:25:42,730 vamos passar por alguns dos problemas de hoje da seção. 304 00:25:42,730 --> 00:25:52,240 Estou a rolagem para baixo - seção de perguntas começa na terceira página da especificação pset. 305 00:25:52,240 --> 00:25:57,800 E a primeira parte pede-lhe para ir e assistir o curta em redirecionando e canos. 306 00:25:57,800 --> 00:26:02,820 Que era uma espécie de curto legal, mostra-lhe alguns truques novos, frescos comando de linha que você pode usar. 307 00:26:02,820 --> 00:26:06,050 E então nós temos algumas perguntas para você também. 308 00:26:06,050 --> 00:26:10,860 Esta primeira pergunta sobre fluxos, para que printf escreve por padrão, 309 00:26:10,860 --> 00:26:15,920 que tipo de tocada em apenas um pouco de um momento atrás. 310 00:26:15,920 --> 00:26:22,380 Este fprintf que nós estávamos discutindo leva em um fluxo de arquivo * como seu argumento. 311 00:26:22,380 --> 00:26:26,580 fclose leva em um fluxo de arquivo *, bem como, 312 00:26:26,580 --> 00:26:32,660 eo valor de retorno de fopen lhe dá um fluxo de arquivo * também. 313 00:26:32,660 --> 00:26:36,060 A razão que nós não vimos antes, quando aqueles que lidou com printf 314 00:26:36,060 --> 00:26:39,450 é porque printf tem um fluxo de padrão. 315 00:26:39,450 --> 00:26:41,810 E o fluxo padrão para o qual ele escreve 316 00:26:41,810 --> 00:26:45,190 você vai descobrir mais sobre a curto. 317 00:26:45,190 --> 00:26:50,080 Então, definitivamente, dar uma olhada. 318 00:26:50,080 --> 00:26:53,010 >> Na seção de hoje, vamos falar um pouco sobre o GDB, 319 00:26:53,010 --> 00:26:57,720 pois quanto mais você está familiarizado com ele, mais prática você começa com ele, 320 00:26:57,720 --> 00:27:01,390 o mais capaz você será realmente descobrir os erros no seu próprio código. 321 00:27:01,390 --> 00:27:05,540 Isso acelera o processo de depuração-se tremendamente. 322 00:27:05,540 --> 00:27:09,230 Então, usando printf, cada vez que você faz que você tem que recompilar seu código, 323 00:27:09,230 --> 00:27:13,000 você tem que executá-lo novamente, às vezes você tem que mover a chamada printf redor, 324 00:27:13,000 --> 00:27:17,100 comente o código, ele só leva um tempo. 325 00:27:17,100 --> 00:27:20,850 Nosso objetivo é tentar convencê-lo de que, com o GDB, você pode essencialmente 326 00:27:20,850 --> 00:27:26,810 nada printf em qualquer ponto do seu código e você nunca tem que recompilá-lo. 327 00:27:26,810 --> 00:27:35,120 Você nunca tem que iniciar e manter adivinhar onde printf seguinte. 328 00:27:35,120 --> 00:27:40,910 A primeira coisa a fazer é copiar essa linha e obter o código da seção fora da web. 329 00:27:40,910 --> 00:27:47,530 Estou copiando esta linha de código que diz: "http://cdn.cs50.net wget". 330 00:27:47,530 --> 00:27:49,510 Eu estou indo para copiá-lo. 331 00:27:49,510 --> 00:27:55,950 Eu estou indo para ir para o meu aparelho, zoom out para que você possa ver o que eu estou fazendo, 332 00:27:55,950 --> 00:28:01,890 colá-lo lá, e quando eu aperte Enter, esse comando wget é literalmente uma teia obter. 333 00:28:01,890 --> 00:28:06,210 Vai puxar para baixo este arquivo fora da Internet, 334 00:28:06,210 --> 00:28:11,790 e ele vai salvá-lo para o diretório atual. 335 00:28:11,790 --> 00:28:21,630 Agora, se eu listar meu diretório atual, você pode ver que eu tenho esse arquivo section5.zip bem ali. 336 00:28:21,630 --> 00:28:25,260 A maneira de lidar com esse cara é descompactá-lo, 337 00:28:25,260 --> 00:28:27,650 que você pode fazer na linha de comando, assim como este. 338 00:28:27,650 --> 00:28:31,880 Section5.zip. 339 00:28:31,880 --> 00:28:36,980 Isso vai descompactá-lo, criar a pasta para mim, 340 00:28:36,980 --> 00:28:40,410 inflar todo o conteúdo, colocá-los lá dentro. 341 00:28:40,410 --> 00:28:47,410 Então agora eu posso ir para o meu diretório seção 5 usando o comando cd. 342 00:28:47,410 --> 00:28:58,310 Limpar a tela usando claro. Então, limpar a tela. 343 00:28:58,310 --> 00:29:02,280 Agora eu tenho um terminal limpo agradável de lidar. 344 00:29:02,280 --> 00:29:06,200 >> Agora, se eu listar todos os arquivos que eu vejo neste diretório, 345 00:29:06,200 --> 00:29:12,270 você vê que eu tenho quatro arquivos: buggy1, buggy2, buggy3 e buggy4. 346 00:29:12,270 --> 00:29:16,180 Eu também tenho os arquivos correspondentes. C. 347 00:29:16,180 --> 00:29:20,400 Nós não vamos olhar para os arquivos. C por agora. 348 00:29:20,400 --> 00:29:24,140 Em vez disso, vamos usá-los quando abrimos GDB. 349 00:29:24,140 --> 00:29:28,220 Mantivemos-los em torno de modo que temos acesso ao código fonte real quando estamos usando GDB, 350 00:29:28,220 --> 00:29:32,740 mas o objetivo desta parte da seção é de mexer volta com o GDB 351 00:29:32,740 --> 00:29:40,370 e ver como podemos usá-lo para descobrir o que está acontecendo de errado com cada um dos quatro programas de buggy. 352 00:29:40,370 --> 00:29:43,380 Então, estamos apenas indo ao redor da sala muito rapidamente, 353 00:29:43,380 --> 00:29:47,000 e eu vou pedir a alguém para executar um dos programas de buggy, 354 00:29:47,000 --> 00:29:54,730 e depois vamos em grupo através de GDB, e vamos ver o que podemos fazer para corrigir esses programas, 355 00:29:54,730 --> 00:29:58,460 ou, pelo menos, identificar o que está acontecendo de errado em cada um deles. 356 00:29:58,460 --> 00:30:04,760 Vamos começar aqui com Daniel. Você vai correr buggy1? Vamos ver o que acontece. 357 00:30:04,760 --> 00:30:09,470 [Daniel] Ele diz que há uma falha de aplicação. Sim >>. Exatamente. 358 00:30:09,470 --> 00:30:12,460 Então, se eu executar buggy1, eu recebo uma falha de seg. 359 00:30:12,460 --> 00:30:16,210 Neste ponto, eu poderia ir e abrir buggy1.c, 360 00:30:16,210 --> 00:30:19,450 tentar descobrir o que está acontecendo de errado, 361 00:30:19,450 --> 00:30:22,000 mas uma das coisas mais irritantes sobre este erro de falha de seg 362 00:30:22,000 --> 00:30:27,610 é que ele não diz em que linha das coisas programa realmente deu errado e quebrou. 363 00:30:27,610 --> 00:30:29,880 Você meio que tem que olhar para o código 364 00:30:29,880 --> 00:30:33,990 e descobrir usando palpite e marque ou printf para ver o que está acontecendo de errado. 365 00:30:33,990 --> 00:30:37,840 Uma das coisas mais legais sobre o GDB é que ele é muito, muito fácil 366 00:30:37,840 --> 00:30:42,170 para descobrir a linha em que trava o programa. 367 00:30:42,170 --> 00:30:46,160 É totalmente vale a pena usá-lo, mesmo que apenas por isso. 368 00:30:46,160 --> 00:30:56,190 Então, para arrancar GDB, eu digito GDB, e então eu dar-lhe o caminho para o executável que eu quero correr. 369 00:30:56,190 --> 00:31:01,960 Aqui eu estou escrevendo gdb ./buggy1. 370 00:31:01,960 --> 00:31:06,600 Pressione Enter. Me dá toda essa informação de direitos autorais, 371 00:31:06,600 --> 00:31:13,000 e aqui você vai ver esta linha que diz: "a leitura de símbolos / home / 372 00:31:13,000 --> 00:31:17,680 jharvard/section5/buggy1 ". 373 00:31:17,680 --> 00:31:22,060 E, se tudo correr bem, você vai ver que imprimir uma mensagem parecida com esta. 374 00:31:22,060 --> 00:31:25,500 Ele vai ler símbolos, ele vai dizer: "Eu estou lendo símbolos de seu arquivo executável", 375 00:31:25,500 --> 00:31:29,900 e então ele vai ter esse "feito" mensagem aqui. 376 00:31:29,900 --> 00:31:35,410 Se você ver alguma outra variação deste, ou você ver que não conseguia encontrar os símbolos 377 00:31:35,410 --> 00:31:41,460 ou algo assim, o que isso significa é que você simplesmente não ter compilado o executável corretamente. 378 00:31:41,460 --> 00:31:49,980 Quando compilar programas para uso com o GDB, temos que usar a bandeira especial-g, 379 00:31:49,980 --> 00:31:54,540 e isso é feito por padrão, se você compilar seus programas, apenas digitando fazer 380 00:31:54,540 --> 00:31:59,320 ou fazer buggy ou fazer recuperar, qualquer um desses. 381 00:31:59,320 --> 00:32:07,800 Mas se você está compilando manualmente com Clang, então você vai ter que ir e que incluem flag-g. 382 00:32:07,800 --> 00:32:10,310 >> Neste ponto, agora que temos o nosso GDB prompt, 383 00:32:10,310 --> 00:32:12,310 é muito simples de executar o programa. 384 00:32:12,310 --> 00:32:19,740 Nós pode digitar run, ou podemos simplesmente digitar r. 385 00:32:19,740 --> 00:32:22,820 A maioria dos comandos do GDB pode ser abreviado. 386 00:32:22,820 --> 00:32:25,940 Normalmente, para apenas um ou dois cartas, o que é bastante agradável. 387 00:32:25,940 --> 00:32:30,980 Então Saad, se você digitar r e pressione Enter, o que acontece? 388 00:32:30,980 --> 00:32:39,390 [Saad] Eu tenho SIGSEGV, falha de segmentação, e então todo este jargão. 389 00:32:39,390 --> 00:32:43,650 Sim >>. 390 00:32:43,650 --> 00:32:47,990 Como estamos vendo na tela, agora, e como Saad disse, 391 00:32:47,990 --> 00:32:53,430 quando digitamos corrida ou R e aperte Enter, nós ainda recebemos a falha seg mesmo. 392 00:32:53,430 --> 00:32:55,830 Então, usando o GDB não resolve o nosso problema. 393 00:32:55,830 --> 00:32:59,120 Mas dá-nos alguns gobbledygook, e verifica-se que este gobbledygook 394 00:32:59,120 --> 00:33:03,080 na verdade, diz-nos onde ele está acontecendo. 395 00:33:03,080 --> 00:33:10,680 Para analisar isso um pouco, este primeiro bit é a função em que tudo está acontecendo de errado. 396 00:33:10,680 --> 00:33:20,270 Há essa __ strcmp_sse4_2, e diz-nos que está acontecendo neste arquivo 397 00:33:20,270 --> 00:33:29,450 chamado sysdeps/i386, tudo isso, de novo, uma espécie de confusão - mas a linha 254. 398 00:33:29,450 --> 00:33:31,670 Isso é meio difícil de analisar. Normalmente, quando você vê coisas como esta, 399 00:33:31,670 --> 00:33:38,770 o que significa que ele está seg falha de uma das bibliotecas de sistema. 400 00:33:38,770 --> 00:33:43,220 Então, alguma coisa a ver com strcmp. Vocês têm visto strcmp antes. 401 00:33:43,220 --> 00:33:52,730 Não é muito louco, mas isso significa que strcmp está quebrado ou que há um problema com strcmp? 402 00:33:52,730 --> 00:33:57,110 O que você acha, Alexandre? 403 00:33:57,110 --> 00:34:04,890 [Alexander] É que - é de 254 a linha? E o - não binário, mas não é os seus tectos, 404 00:34:04,890 --> 00:34:10,590 e depois há uma outra língua para cada função. É que 254 em que a função, ou -? 405 00:34:10,590 --> 00:34:21,460 É >> linha 254. Parece que neste arquivo s., Por isso, provavelmente código de montagem. 406 00:34:21,460 --> 00:34:25,949 >> Mas, eu acho que a coisa mais urgente é, porque nós temos tido uma falha de seg, 407 00:34:25,949 --> 00:34:29,960 e parece que ele está vindo a função strcmp, 408 00:34:29,960 --> 00:34:38,030 isso implica, então, que strcmp está quebrado? 409 00:34:38,030 --> 00:34:42,290 Não deveria, espero. Então, só porque você tem uma falha de segmentação 410 00:34:42,290 --> 00:34:49,480 em uma das funções do sistema, normalmente isso significa que você simplesmente não tê-lo chamado corretamente. 411 00:34:49,480 --> 00:34:52,440 O mais rápido coisa a fazer para descobrir o que está realmente acontecendo 412 00:34:52,440 --> 00:34:55,500 quando você vê algo louco como esse, sempre que você vê uma falha seg, 413 00:34:55,500 --> 00:34:59,800 especialmente se você tem um programa que está usando mais do que apenas principal, 414 00:34:59,800 --> 00:35:03,570 é a utilização de um registo de chamadas. 415 00:35:03,570 --> 00:35:13,080 I abreviar backtrace escrevendo bt, em oposição à palavra backtrace completo. 416 00:35:13,080 --> 00:35:16,510 Mas Charlotte, o que acontece quando você digita bt e pressione Enter? 417 00:35:16,510 --> 00:35:23,200 [Charlotte] Ele me mostra duas linhas, a linha 0 e linha 1. 418 00:35:23,200 --> 00:35:26,150 Sim >>. Assim linha 0 e linha 1. 419 00:35:26,150 --> 00:35:34,560 Estes são os quadros de pilha reais que estavam atualmente no jogo quando o programa deixou de funcionar. 420 00:35:34,560 --> 00:35:42,230 A partir do quadro superior, quadro 0, e indo para o fundo mais, que é uma armação. 421 00:35:42,230 --> 00:35:45,140 Nosso quadro de nível superior é o quadro strcmp. 422 00:35:45,140 --> 00:35:50,080 Você pode pensar nisso como semelhante ao problema que só estavam fazendo no questionário com os ponteiros, 423 00:35:50,080 --> 00:35:54,890 onde tínhamos trocar quadro de pilha em cima de quadro de pilha principal, 424 00:35:54,890 --> 00:35:59,700 e tivemos as variáveis ​​que troca estava usando em cima das variáveis ​​que principal estava usando. 425 00:35:59,700 --> 00:36:08,440 Aqui a nossa queda aconteceu em nossa função strcmp, que foi chamado pela nossa função principal, 426 00:36:08,440 --> 00:36:14,370 backtrace e está nos dando não apenas as funções em que as coisas falharam, 427 00:36:14,370 --> 00:36:16,440 mas também está nos dizendo que tudo foi chamado. 428 00:36:16,440 --> 00:36:18,830 Então, se eu rolar um pouco mais para a direita, 429 00:36:18,830 --> 00:36:26,110 podemos ver que, sim, nós estávamos na linha 254 do arquivo strcmp-sse4.s. 430 00:36:26,110 --> 00:36:32,540 Mas a chamada foi feita em buggy1.c, linha 6. 431 00:36:32,540 --> 00:36:35,960 Então isso significa que podemos fazer - é que podemos apenas ir verificar e ver o que estava acontecendo 432 00:36:35,960 --> 00:36:39,930 em buggy1.c, linha 6. 433 00:36:39,930 --> 00:36:43,780 Novamente, existem algumas maneiras de fazer isso. Um deles é para sair do GDB 434 00:36:43,780 --> 00:36:49,460 ou ter seu código aberto em outra janela e referência cruzada. 435 00:36:49,460 --> 00:36:54,740 Isso, por si só, é bastante útil, porque agora se você está em horário de expediente 436 00:36:54,740 --> 00:36:57,220 e você tem uma falha seg e seu TF está se perguntando onde tudo estava quebrando, 437 00:36:57,220 --> 00:36:59,710 você pode apenas dizer: "Oh, linha 6. que eu não sei o que está acontecendo, 438 00:36:59,710 --> 00:37:03,670 mas algo sobre a linha 6 está causando o meu programa para quebrar ". 439 00:37:03,670 --> 00:37:10,430 A outra maneira de fazer isso é que você pode usar este comando chamada lista em GDB. 440 00:37:10,430 --> 00:37:13,650 Você também pode abreviar com l. 441 00:37:13,650 --> 00:37:18,910 Então, se nós batemos l, o que temos aqui? 442 00:37:18,910 --> 00:37:21,160 Nós temos um monte de coisas estranhas. 443 00:37:21,160 --> 00:37:26,030 Este é o código de montagem real 444 00:37:26,030 --> 00:37:29,860 que está em strcmp_sse4_2. 445 00:37:29,860 --> 00:37:32,440 Isso parece tipo de funky, 446 00:37:32,440 --> 00:37:36,520 ea razão que estamos recebendo é porque agora, 447 00:37:36,520 --> 00:37:40,160 GDB nos tem em quadro 0. 448 00:37:40,160 --> 00:37:43,070 >> Então, quando nós olhamos para as variáveis, toda vez que olhar para o código-fonte, 449 00:37:43,070 --> 00:37:50,530 nós estamos olhando para o código-fonte que pertence ao quadro de pilha que estamos atualmente dentro 450 00:37:50,530 --> 00:37:53,200 Portanto, a fim de obter alguma coisa significativa, temos que 451 00:37:53,200 --> 00:37:57,070 mover-se para um quadro de pilha que faz mais sentido. 452 00:37:57,070 --> 00:38:00,180 Neste caso, o quadro de pilha principal faria sentido um pouco mais, 453 00:38:00,180 --> 00:38:02,680 porque esse era realmente o código que escreveu. 454 00:38:02,680 --> 00:38:05,330 Não o código strcmp. 455 00:38:05,330 --> 00:38:08,650 A maneira como você pode mover-se entre os quadros, neste caso, porque temos dois, 456 00:38:08,650 --> 00:38:10,430 temos 0 e 1, 457 00:38:10,430 --> 00:38:13,650 você faz isso com o para cima e para baixo comandos. 458 00:38:13,650 --> 00:38:18,480 Se eu subir um quadro, 459 00:38:18,480 --> 00:38:21,770 agora eu estou no quadro de pilha principal. 460 00:38:21,770 --> 00:38:24,330 Eu posso mover para baixo para voltar para onde eu estava, 461 00:38:24,330 --> 00:38:32,830 ir para cima de novo, ir para baixo de novo, e ir para cima de novo. 462 00:38:32,830 --> 00:38:39,750 Se você sempre faz o programa no GDB, você tem uma queda, você começa a backtrace, 463 00:38:39,750 --> 00:38:42,380 e você vê que ele está em algum arquivo que você não sabe o que está acontecendo. 464 00:38:42,380 --> 00:38:45,460 Você tenta lista, o código não parece familiar para você, 465 00:38:45,460 --> 00:38:48,150 dar uma olhada em seus quadros e descobrir onde você está. 466 00:38:48,150 --> 00:38:51,010 Você provavelmente está no quadro de pilha errada. 467 00:38:51,010 --> 00:38:58,760 Ou, pelo menos você está em um quadro de pilha que não é aquele que você pode realmente depurar. 468 00:38:58,760 --> 00:39:03,110 Agora que estamos no quadro de pilha adequada, estamos em principal, 469 00:39:03,110 --> 00:39:08,100 agora podemos usar o comando lista para descobrir o que a linha estava. 470 00:39:08,100 --> 00:39:13,590 E você pode vê-lo, imprimi-lo para nós aqui. 471 00:39:13,590 --> 00:39:19,470 Mas podemos acertar listar todos o mesmo, e lista nos dá esta impressão agradável 472 00:39:19,470 --> 00:39:23,920 do código-fonte real que está acontecendo aqui. 473 00:39:23,920 --> 00:39:26,420 >> Em particular, podemos olhar para a linha 6. 474 00:39:26,420 --> 00:39:29,330 Nós podemos ver o que está acontecendo aqui. 475 00:39:29,330 --> 00:39:31,250 E parece que nós estamos fazendo uma comparação de string 476 00:39:31,250 --> 00:39:41,050 entre a string "CS50 pedras" e argv [1]. 477 00:39:41,050 --> 00:39:45,700 Alguma coisa sobre isso foi bater. 478 00:39:45,700 --> 00:39:54,120 Então Missy, você tem alguma opinião sobre o que pode estar acontecendo aqui? 479 00:39:54,120 --> 00:39:59,400 [Missy] Eu não sei por que ele está falhando. >> Você não sabe por que está batendo? 480 00:39:59,400 --> 00:40:02,700 Jimmy, todos os pensamentos? 481 00:40:02,700 --> 00:40:06,240 [Jimmy] eu não estou totalmente certo, mas a última vez que usou cadeia de comparar, 482 00:40:06,240 --> 00:40:10,260 ou strcmp, tivemos algo como três casos diferentes sob ele. 483 00:40:10,260 --> 00:40:12,800 Nós não temos um ==, eu não acho que, mesmo em que a primeira linha. 484 00:40:12,800 --> 00:40:16,700 Em vez disso, foi separada em três, e uma era == 0, 485 00:40:16,700 --> 00:40:19,910 um foi <0, eu acho, e foi um> 0. 486 00:40:19,910 --> 00:40:22,590 Então talvez algo assim? Sim >>. Então há essa questão 487 00:40:22,590 --> 00:40:27,200 de que estamos fazendo a comparação corretamente? 488 00:40:27,200 --> 00:40:31,660 Stella? Todos os pensamentos? 489 00:40:31,660 --> 00:40:38,110 [Stella] Eu não tenho certeza. >> Não tenho certeza. Daniel? Pensamentos? Okay. 490 00:40:38,110 --> 00:40:44,770 Acontece que o que está acontecendo aqui é quando executamos o programa 491 00:40:44,770 --> 00:40:48,370 e temos a culpa seg, quando o programa foi executado pela primeira vez, Daniel, 492 00:40:48,370 --> 00:40:50,800 você deu a ela quaisquer argumentos de linha de comando? 493 00:40:50,800 --> 00:40:58,420 [Daniel] Não. Não. >> Nesse caso, o que é o valor de argv [1]? 494 00:40:58,420 --> 00:41:00,920 >> Não há nenhum valor. >> Direito. 495 00:41:00,920 --> 00:41:06,120 Bem, não há valor de seqüência apropriada. 496 00:41:06,120 --> 00:41:10,780 Mas há algum valor. Qual é o valor que fica armazenado ali? 497 00:41:10,780 --> 00:41:15,130 Um valor >> lixo? >> É tanto um valor de lixo, ou, neste caso, 498 00:41:15,130 --> 00:41:19,930 o final da matriz argv sempre é terminada com null. 499 00:41:19,930 --> 00:41:26,050 Então, o que realmente foi armazenado lá é nulo. 500 00:41:26,050 --> 00:41:30,810 A outra maneira de resolver isso, em vez de pensar nisso, 501 00:41:30,810 --> 00:41:33,420 é tentar mostrá-lo. 502 00:41:33,420 --> 00:41:35,880 Este é o lugar onde eu estava dizendo que o uso de GDB é grande, 503 00:41:35,880 --> 00:41:40,640 porque você pode imprimir todas as variáveis, todos os valores que você deseja 504 00:41:40,640 --> 00:41:43,230 usando este prático-dandy comando p. 505 00:41:43,230 --> 00:41:48,520 Então, se eu digitar p e depois digite o valor de uma variável ou o nome de uma variável, 506 00:41:48,520 --> 00:41:55,320 dizer, argc, vejo que argc é 1. 507 00:41:55,320 --> 00:42:01,830 Se eu quiser imprimir argv [0], eu posso fazê-lo assim. 508 00:42:01,830 --> 00:42:04,840 E, como vimos, argv [0] é sempre o nome do seu programa, 509 00:42:04,840 --> 00:42:06,910 sempre o nome do executável. 510 00:42:06,910 --> 00:42:09,740 Aqui você vê que tem o nome completo do caminho. 511 00:42:09,740 --> 00:42:15,920 Eu também pode imprimir argv [1] e ver o que acontece. 512 00:42:15,920 --> 00:42:20,890 >> Aqui temos este tipo de valor místico. 513 00:42:20,890 --> 00:42:23,890 Temos este 0x0. 514 00:42:23,890 --> 00:42:27,850 Lembre-se, no início do mandato, quando nós falamos sobre números hexadecimais? 515 00:42:27,850 --> 00:42:34,680 Ou que pequena pergunta ao final de pset 0 sobre como representar 50 em hexadecimal? 516 00:42:34,680 --> 00:42:39,410 A nossa forma de escrever números hexadecimais em CS, apenas para não confundir-nos 517 00:42:39,410 --> 00:42:46,080 com números decimais, é sempre prefixo-los com 0x. 518 00:42:46,080 --> 00:42:51,420 Portanto, este prefixo 0x sempre significa apenas interpretar o seguinte número como um número hexadecimal, 519 00:42:51,420 --> 00:42:57,400 não como uma string, não como um número decimal, não como um número binário. 520 00:42:57,400 --> 00:43:02,820 Uma vez que o número de 5-0 é um número válido em hexadecimal. 521 00:43:02,820 --> 00:43:06,240 E é um número decimal, 50. 522 00:43:06,240 --> 00:43:10,050 Portanto, este é apenas como nós disambiguate. 523 00:43:10,050 --> 00:43:14,860 Então 0x0 meios 0 hexadecimal, que também é decimal, binário 0 0. 524 00:43:14,860 --> 00:43:17,030 É apenas o valor 0. 525 00:43:17,030 --> 00:43:22,630 Acontece que isso é o que nulo é, na verdade, na memória. 526 00:43:22,630 --> 00:43:25,940 Nulo é apenas 0. 527 00:43:25,940 --> 00:43:37,010 Aqui, o elemento armazenado em argv [1] é nulo. 528 00:43:37,010 --> 00:43:45,220 Então, estamos tentando comparar o nosso "CS50 rochas" string para uma string nula. 529 00:43:45,220 --> 00:43:48,130 Então dereferencing nulo, tentando acessar coisas ao nulo, 530 00:43:48,130 --> 00:43:55,050 aqueles são normalmente vai causar algum tipo de falha de segmentação ou de outras coisas ruins aconteçam. 531 00:43:55,050 --> 00:43:59,350 E acontece que strcmp não verifique 532 00:43:59,350 --> 00:44:04,340 ou não que você passou em um valor que é nulo. 533 00:44:04,340 --> 00:44:06,370 Em vez disso, ele simplesmente vai em frente, tenta fazer a sua coisa, 534 00:44:06,370 --> 00:44:14,640 e se seg defeitos, ela seg falhas, e é o seu problema. Você tem que ir consertar. 535 00:44:14,640 --> 00:44:19,730 Muito rapidamente, como podemos resolver este problema? Charlotte? 536 00:44:19,730 --> 00:44:23,540 [Charlotte] Você pode verificar se usando. 537 00:44:23,540 --> 00:44:32,240 Então, se argv [1] é nulo, == 0, em seguida, retornar 1, ou alguma coisa [ininteligível]. 538 00:44:32,240 --> 00:44:34,590 Sim >>. Então essa é uma ótima maneira de fazê-lo, como se pode verificar, 539 00:44:34,590 --> 00:44:39,230 o valor que estamos prestes a passar para o strcmp, argv [1], não é nulo? 540 00:44:39,230 --> 00:44:45,830 Se é nulo, então podemos dizer bem, abortar. 541 00:44:45,830 --> 00:44:49,450 >> A maneira mais comum de fazer isso é usar o valor argc. 542 00:44:49,450 --> 00:44:52,040 Você pode ver aqui no início do principal, 543 00:44:52,040 --> 00:44:58,040 omitimos que primeiro teste que nós normalmente fazemos quando usar argumentos de linha de comando, 544 00:44:58,040 --> 00:45:05,240 que é para testar se ou não o nosso valor argc é o que esperamos. 545 00:45:05,240 --> 00:45:10,290 Neste caso, estamos esperando pelo menos dois argumentos, 546 00:45:10,290 --> 00:45:13,660 o nome do programa mais um outro. 547 00:45:13,660 --> 00:45:17,140 Porque nós estamos prestes a usar o segundo argumento aqui. 548 00:45:17,140 --> 00:45:21,350 Então, ter algum tipo de teste com antecedência, antes de nossa chamada strcmp 549 00:45:21,350 --> 00:45:37,390 que os testes ou não argv é pelo menos duas, também faria o mesmo tipo de coisa. 550 00:45:37,390 --> 00:45:40,620 Podemos ver se isso funciona, executando o programa novamente. 551 00:45:40,620 --> 00:45:45,610 Você sempre pode reiniciar o programa dentro do GDB, que é muito bom. 552 00:45:45,610 --> 00:45:49,310 Você pode correr, e quando você passar argumentos para o seu programa, 553 00:45:49,310 --> 00:45:53,060 você passá-los quando você chamar executar, não quando você arrancar GDB. 554 00:45:53,060 --> 00:45:57,120 Dessa forma, você pode manter invocando o seu programa com argumentos diferentes a cada vez. 555 00:45:57,120 --> 00:46:08,080 Então corra, ou ainda, eu posso digitar r, e vamos ver o que acontece se digitar "Olá". 556 00:46:08,080 --> 00:46:11,140 Será sempre perguntar se você deseja iniciá-lo desde o início novamente. 557 00:46:11,140 --> 00:46:17,490 Normalmente, você quer começar desde o início novamente. 558 00:46:17,490 --> 00:46:25,010 E, neste ponto, ele reinicia-lo novamente, ele imprime 559 00:46:25,010 --> 00:46:28,920 o programa que nós estamos correndo, buggy1, com o argumento Olá, 560 00:46:28,920 --> 00:46:32,720 e imprime isso padrão, ele diz, "Você tem um D," face triste. 561 00:46:32,720 --> 00:46:37,610 Mas nós não seg culpa. Ele disse que o processo saiu normalmente. 562 00:46:37,610 --> 00:46:39,900 De modo que parece muito bom. 563 00:46:39,900 --> 00:46:43,050 Nenhuma falha mais seg, conseguimos passado, 564 00:46:43,050 --> 00:46:48,190 então parece que esse era realmente o bug culpa seg que estávamos recebendo. 565 00:46:48,190 --> 00:46:51,540 Infelizmente, ele nos diz que nós estamos começando um D. 566 00:46:51,540 --> 00:46:54,090 >> Nós podemos ir para trás e olhar para o código e ver o que estava acontecendo lá 567 00:46:54,090 --> 00:46:57,980 para descobrir o que era - por isso que estava nos dizendo que temos um D. 568 00:46:57,980 --> 00:47:03,690 Vamos ver, aqui foi este printf dizendo que você tem um D. 569 00:47:03,690 --> 00:47:08,540 Se tipo de lista, como você manter a lista de digitar, ele mantém a iteração através de seu programa, 570 00:47:08,540 --> 00:47:10,940 por isso vai mostrar-lhe as primeiras linhas do seu programa. 571 00:47:10,940 --> 00:47:15,450 Em seguida, ele vai mostrar-lhe as próximas linhas, eo pedaço seguinte eo próximo pedaço. 572 00:47:15,450 --> 00:47:18,240 E vai continuar tentando ir para baixo. 573 00:47:18,240 --> 00:47:21,180 E agora nós vamos começar a "linha de número 16 está fora de alcance." 574 00:47:21,180 --> 00:47:23,940 Porque só tem 15 linhas. 575 00:47:23,940 --> 00:47:30,310 Se você chegar a este ponto e seu perguntando: "O que eu faço?" você pode usar o comando de ajuda. 576 00:47:30,310 --> 00:47:34,340 Use a ajuda e, em seguida, dar-lhe o nome de um comando. 577 00:47:34,340 --> 00:47:36,460 E você vê o GDB nos dá todo este tipo de coisa. 578 00:47:36,460 --> 00:47:43,870 Ela diz: "Sem argumento, lista dez linhas mais após ou em torno da listagem anterior. 579 00:47:43,870 --> 00:47:47,920 Lista - lista as 10 linhas antes - " 580 00:47:47,920 --> 00:47:52,960 Então, vamos tentar usar menos lista. 581 00:47:52,960 --> 00:47:57,000 E que lista as 10 linhas anterior, você pode brincar com uma lista pouco. 582 00:47:57,000 --> 00:48:02,330 Você pode fazer a lista, lista -, você pode até dar listar um número, como a lista de 8, 583 00:48:02,330 --> 00:48:07,500 e ele vai listar as 10 linhas em torno da linha 8. 584 00:48:07,500 --> 00:48:10,290 E você pode ver o que está acontecendo aqui é que você tem um simples, se outra coisa. 585 00:48:10,290 --> 00:48:13,980 Se você digitar CS50 rochas, ela mostra "Você tem um A." 586 00:48:13,980 --> 00:48:16,530 Caso contrário, ele imprime "Você tem um D." 587 00:48:16,530 --> 00:48:23,770 Cidade chatice. Tudo bem. Sim? 588 00:48:23,770 --> 00:48:26,730 >> [Daniel] Então, quando eu tentei fazer CS50 rochas sem as aspas, 589 00:48:26,730 --> 00:48:29,290 ele diz "Você tem um D." 590 00:48:29,290 --> 00:48:32,560 Eu precisava das aspas para fazê-lo funcionar, por que isso? 591 00:48:32,560 --> 00:48:38,490 Sim >>. Acontece que quando - este é outro petisco pouco de diversão - 592 00:48:38,490 --> 00:48:47,900 quando você executar o programa, se executá-lo e digitar CS50 rochas, 593 00:48:47,900 --> 00:48:50,800 apenas como Daniel estava dizendo que ele fez, e você aperte Enter, 594 00:48:50,800 --> 00:48:52,870 ele ainda diz que obter um D. 595 00:48:52,870 --> 00:48:55,580 E a pergunta é, por que é isso? 596 00:48:55,580 --> 00:49:02,120 E verifica-se que o terminal nosso e GDB analisar estes como dois argumentos distintos. 597 00:49:02,120 --> 00:49:04,800 Porque quando há um espaço, que está implícito como 598 00:49:04,800 --> 00:49:08,730 o primeiro argumento terminou, o próximo argumento está prestes a começar. 599 00:49:08,730 --> 00:49:13,260 A maneira de combinar os em dois, ou muito, em um argumento, 600 00:49:13,260 --> 00:49:18,510 é usar as aspas. 601 00:49:18,510 --> 00:49:29,560 Então, agora, se colocá-lo entre aspas e executá-lo novamente, temos um A. 602 00:49:29,560 --> 00:49:38,780 Então, só para recapitular, sem aspas, CS50 e rochas são analisados ​​como dois argumentos distintos. 603 00:49:38,780 --> 00:49:45,320 Com aspas, é analisado como um argumento completamente. 604 00:49:45,320 --> 00:49:53,070 >> Podemos ver isso com um ponto de interrupção. 605 00:49:53,070 --> 00:49:54,920 Até agora temos sido executado o nosso programa, e está sendo executado 606 00:49:54,920 --> 00:49:58,230 até que ela seg falhas ou acertos um erro 607 00:49:58,230 --> 00:50:05,930 ou até que ele saiu e tudo tem sido totalmente bem. 608 00:50:05,930 --> 00:50:08,360 Isso não é necessariamente a coisa mais útil, porque às vezes 609 00:50:08,360 --> 00:50:11,840 você tem um erro no seu programa, mas ele não está causando uma falha de segmentação. 610 00:50:11,840 --> 00:50:16,950 Ele não está causando o seu programa para parar ou qualquer coisa assim. 611 00:50:16,950 --> 00:50:20,730 O caminho para chegar GDB para pausar o seu programa em um determinado ponto 612 00:50:20,730 --> 00:50:23,260 é definir um ponto de interrupção. 613 00:50:23,260 --> 00:50:26,520 Você pode fazer isso através da criação de um ponto de interrupção em um nome de função 614 00:50:26,520 --> 00:50:30,770 ou você pode definir um ponto de interrupção em uma determinada linha de código. 615 00:50:30,770 --> 00:50:34,450 Eu gosto de definir pontos de interrupção em nomes de função, porque - fácil de lembrar, 616 00:50:34,450 --> 00:50:37,700 e se você realmente entrar e alterar seu código fonte se um pouco, 617 00:50:37,700 --> 00:50:42,020 então o seu ponto de interrupção vai realmente ficar no mesmo lugar dentro de seu código. 618 00:50:42,020 --> 00:50:44,760 Considerando que se você estiver usando números de linha, e os números de linha mudar 619 00:50:44,760 --> 00:50:51,740 porque você adicionar ou excluir algum código, em seguida, os pontos de interrupção estão totalmente asneira. 620 00:50:51,740 --> 00:50:58,590 Uma das coisas mais comuns que fazer é definir um ponto de interrupção na função principal. 621 00:50:58,590 --> 00:51:05,300 Muitas vezes, eu vou arrancar o GDB, eu vou digitar b principal, aperte Enter, e que vai definir um ponto de interrupção 622 00:51:05,300 --> 00:51:10,630 sobre a função principal, que apenas diz: "Pause o programa assim que você começar a correr", 623 00:51:10,630 --> 00:51:17,960 e de que maneira, quando eu executar o meu programa com, digamos, CS50 rochas como dois argumentos 624 00:51:17,960 --> 00:51:24,830 e pressione Enter, ele fica com a função principal e pára na primeira linha, 625 00:51:24,830 --> 00:51:30,620 direita antes que avalia a função strcmp. 626 00:51:30,620 --> 00:51:34,940 >> Desde que eu estou uma pausa, agora posso começar a perder tempo e ver o que está acontecendo 627 00:51:34,940 --> 00:51:40,250 com todas as diferentes variáveis ​​que são passados ​​para o meu programa. 628 00:51:40,250 --> 00:51:43,670 Aqui eu posso imprimir argc e ver o que está acontecendo. 629 00:51:43,670 --> 00:51:50,030 Veja que argc é 3, porque tem três valores diferentes nela. 630 00:51:50,030 --> 00:51:54,060 Tem o nome do programa, ele tem o primeiro argumento eo segundo argumento. 631 00:51:54,060 --> 00:52:09,330 Nós podemos imprimir os para fora, olhando para argv [0], argv [1], e argv [2]. 632 00:52:09,330 --> 00:52:12,030 Então, agora você também pode ver por esta chamada strcmp vai falhar, 633 00:52:12,030 --> 00:52:21,650 porque você vê que o fez dividir o CS50 e as rochas em dois argumentos distintos. 634 00:52:21,650 --> 00:52:27,250 Neste ponto, uma vez que você tenha atingido um ponto de interrupção, você pode continuar a percorrer o seu programa 635 00:52:27,250 --> 00:52:32,920 linha por linha, em vez de começar o programa novamente. 636 00:52:32,920 --> 00:52:35,520 Então, se você não quer começar o seu programa novamente e apenas continuar a partir daqui, 637 00:52:35,520 --> 00:52:41,970 você pode usar o comando continue e continuar o programa será executado até o fim. 638 00:52:41,970 --> 00:52:45,010 Assim como ele fez aqui. 639 00:52:45,010 --> 00:52:54,880 No entanto, se eu reiniciar o programa, CS50 rochas, que bate no meu ponto de interrupção de novo, 640 00:52:54,880 --> 00:52:59,670 e desta vez, se eu não quero apenas ir até o fim com o restante do programa, 641 00:52:59,670 --> 00:53:08,040 Eu posso usar o comando seguinte, o que eu também abreviar com n. 642 00:53:08,040 --> 00:53:12,960 E isso vai percorrer o programa linha a linha. 643 00:53:12,960 --> 00:53:17,530 Assim, você pode ver como as coisas executar, como mudança de variáveis, como as coisas se atualizado. 644 00:53:17,530 --> 00:53:21,550 O que é muito bom. 645 00:53:21,550 --> 00:53:26,570 A outra coisa legal é, em vez de repetir o mesmo comando mais e mais e mais uma vez, 646 00:53:26,570 --> 00:53:30,670 se você apenas pressione Enter - por isso aqui você vê que eu não ter digitado nada - 647 00:53:30,670 --> 00:53:33,780 se eu apenas aperte Enter, ele vai repetir o comando anterior, 648 00:53:33,780 --> 00:53:36,900 ou o comando GDB anterior que eu só colocar dentro 649 00:53:36,900 --> 00:53:56,000 Eu posso continuar batendo Enter e ele vai manter percorrendo meu código linha por linha. 650 00:53:56,000 --> 00:53:59,310 Gostaria de incentivar vocês para ir verificar os programas de buggy outros também. 651 00:53:59,310 --> 00:54:01,330 Não temos tempo para passar por todos eles hoje em seção. 652 00:54:01,330 --> 00:54:05,890 O código fonte está lá, então você pode tipo de ver o que está acontecendo 653 00:54:05,890 --> 00:54:07,730 nos bastidores se você ficar muito preso, 654 00:54:07,730 --> 00:54:11,940 mas, no mínimo, apenas a prática de arrancar GDB, 655 00:54:11,940 --> 00:54:13,940 a execução do programa até que se rompe em você, 656 00:54:13,940 --> 00:54:18,260 recebendo o backtrace, descobrir qual a função do acidente estava, 657 00:54:18,260 --> 00:54:24,450 que linha era em, imprimindo alguns valores variáveis, 658 00:54:24,450 --> 00:54:30,140 só para você ter uma idéia para ele, porque isso vai realmente ajudá-lo daqui para frente. 659 00:54:30,140 --> 00:54:36,340 Neste ponto, nós estamos indo para sair fora do GDB, que você parar de usar ou apenas q. 660 00:54:36,340 --> 00:54:40,460 Se o seu programa está no meio da execução, ainda assim, e não foi encerrado, 661 00:54:40,460 --> 00:54:43,510 ele sempre perguntar: "Você tem certeza de que você realmente deseja sair?" 662 00:54:43,510 --> 00:54:48,770 Você pode apenas bater sim. 663 00:54:48,770 --> 00:54:55,250 >> Agora vamos olhar para o próximo problema que temos, que é o programa de gato. 664 00:54:55,250 --> 00:54:59,880 Se você assistir o curta em redirecionando e tubos, você vai ver que Tommy usa este programa 665 00:54:59,880 --> 00:55:07,540 que, basicamente, imprime toda a saída de um arquivo para a tela. 666 00:55:07,540 --> 00:55:12,660 Então, se eu executar gato, este é realmente um programa embutido no aparelho, 667 00:55:12,660 --> 00:55:16,860 e se você tem Macs você pode fazer isso no seu Mac também, se você abrir o terminal. 668 00:55:16,860 --> 00:55:25,630 E nós - gato, vamos dizer, cp.c, e pressione Enter. 669 00:55:25,630 --> 00:55:29,640 O que este fez, se rolar um pouco e ver onde nós corremos a linha, 670 00:55:29,640 --> 00:55:40,440 ou em que executou o comando gato, literalmente impressa o conteúdo do cp.c a nossa tela. 671 00:55:40,440 --> 00:55:44,140 Nós podemos correr de novo e você pode colocar em vários arquivos juntos. 672 00:55:44,140 --> 00:55:49,880 Assim você pode fazer cp.c gato, e então também podemos concatenar o arquivo cat.c, 673 00:55:49,880 --> 00:55:53,250 que é o programa que estamos prestes a escrever, 674 00:55:53,250 --> 00:55:58,140 e ele vai imprimir ambos os arquivos de volta para fazer a nossa tela. 675 00:55:58,140 --> 00:56:05,490 Então, se rolar um pouco, vemos que, quando rodamos este cp.c gato, cat.c, 676 00:56:05,490 --> 00:56:17,110 primeiro-lo impresso o arquivo cp, e depois abaixo, ele imprimiu o arquivo cat.c bem aqui. 677 00:56:17,110 --> 00:56:19,650 Nós vamos usar isso para apenas molhar os pés. 678 00:56:19,650 --> 00:56:25,930 Brinque com impressão simples ao terminal, ver como é que funciona. 679 00:56:25,930 --> 00:56:39,170 Se vocês se abrir com gedit cat.c, pressione Enter, 680 00:56:39,170 --> 00:56:43,760 você pode ver o programa que estamos prestes a escrever. 681 00:56:43,760 --> 00:56:48,980 Nós incluímos esta placa de caldeira nice, portanto, não tem que gastar tempo digitando tudo isso. 682 00:56:48,980 --> 00:56:52,310 Nós também verificar o número de argumentos passado dentro 683 00:56:52,310 --> 00:56:56,910 Nós imprimir uma mensagem de uso agradável. 684 00:56:56,910 --> 00:57:00,950 >> Este é o tipo de coisa que, mais uma vez, como temos vindo a falar, 685 00:57:00,950 --> 00:57:04,490 é quase como se a memória muscular. 686 00:57:04,490 --> 00:57:07,190 Apenas lembre-se de continuar a fazer o mesmo tipo de material 687 00:57:07,190 --> 00:57:11,310 e sempre imprimir algum tipo de mensagem útil 688 00:57:11,310 --> 00:57:17,670 para que as pessoas saibam como executar o seu programa. 689 00:57:17,670 --> 00:57:21,630 Com o gato, é muito simples, nós só vamos passar por todos os diferentes argumentos 690 00:57:21,630 --> 00:57:24,300 que foram passadas para o nosso programa, e nós estamos indo para imprimir 691 00:57:24,300 --> 00:57:29,950 o seu conteúdo para fora para o ecrã de um de cada vez. 692 00:57:29,950 --> 00:57:35,670 Para imprimir arquivos para a tela, vamos fazer algo muito semelhante 693 00:57:35,670 --> 00:57:38,120 ao que fizemos no final do questionário. 694 00:57:38,120 --> 00:57:45,350 Ao final do questionário, que contratem programa, tivemos que abrir um arquivo, 695 00:57:45,350 --> 00:57:48,490 e depois tivemos de imprimir nela. 696 00:57:48,490 --> 00:57:54,660 Neste caso, vamos abrir um arquivo, e vamos lê-lo em seu lugar. 697 00:57:54,660 --> 00:58:00,630 Então nós vamos para imprimir, em vez de um arquivo, vamos imprimir na tela. 698 00:58:00,630 --> 00:58:05,830 Assim, a impressão para a tela que todos fizemos antes com printf. 699 00:58:05,830 --> 00:58:08,290 Então, isso não é muito louco. 700 00:58:08,290 --> 00:58:12,190 Mas a leitura de um arquivo é meio estranho. 701 00:58:12,190 --> 00:58:17,300 Nós vamos passar por isso um pouco de cada vez. 702 00:58:17,300 --> 00:58:20,560 Se vocês voltar a esse último problema em seu questionário, problema 33, 703 00:58:20,560 --> 00:58:27,280 a primeira linha que nós vamos fazer aqui, abrir o arquivo, é muito semelhante ao que fizemos lá. 704 00:58:27,280 --> 00:58:36,370 Então, Stella, o que faz aquele olhar linha como, quando abrir um arquivo? 705 00:58:36,370 --> 00:58:47,510 [Stella] FILE * Capital, arquivo - >> Okay. >> - É igual a fopen. >> Yup. 706 00:58:47,510 --> 00:58:55,980 Que neste caso é? É no comentário. 707 00:58:55,980 --> 00:59:06,930 >> É no comentário? argv [i] e r? 708 00:59:06,930 --> 00:59:11,300 >> Exatamente. Certo. Então, Stella é totalmente certo. 709 00:59:11,300 --> 00:59:13,720 Isto é o que a linha parece. 710 00:59:13,720 --> 00:59:19,670 Nós estamos indo para obter uma variável fluxo de arquivo, armazená-lo em um FILE *, então todas as tampas, 711 00:59:19,670 --> 00:59:25,720 FILE, *, eo nome desta variável será de arquivo. 712 00:59:25,720 --> 00:59:32,250 Poderíamos chamá-lo de tudo o que gosta. Nós poderíamos chamar isso first_file, ou file_i, tudo o que gostaria. 713 00:59:32,250 --> 00:59:37,590 E então o nome do arquivo foi passado na linha de comando para este programa. 714 00:59:37,590 --> 00:59:44,450 Então, ele é armazenado em argv [i] e, em seguida, vamos abrir este arquivo em modo de leitura. 715 00:59:44,450 --> 00:59:48,100 Agora que abriu o arquivo, o que é a coisa que nós sempre temos que lembrar de fazer 716 00:59:48,100 --> 00:59:52,230 sempre que você abriu um arquivo? Fechá-lo. 717 00:59:52,230 --> 00:59:57,220 Então Missy, como é que vamos fechar um arquivo? 718 00:59:57,220 --> 01:00:01,020 [Missy] fclose (arquivo) >> fclose (arquivo). Exatamente. 719 01:00:01,020 --> 01:00:05,340 Grande. Okay. Se olharmos para este fazer comentário aqui, 720 01:00:05,340 --> 01:00:11,940 ele diz, "Open argv [i] e imprimir o seu conteúdo para stdout." 721 01:00:11,940 --> 01:00:15,460 >> Saída padrão é um nome estranho. Stdout é apenas uma maneira de dizer 722 01:00:15,460 --> 01:00:22,880 queremos imprimir ao terminal, queremos imprimi-lo para o fluxo de saída padrão. 723 01:00:22,880 --> 01:00:26,450 Podemos realmente se livrar deste comentário aqui. 724 01:00:26,450 --> 01:00:36,480 Eu estou indo para copiá-lo e colá-lo, já que é o que nós fizemos. 725 01:00:36,480 --> 01:00:41,290 Neste ponto, agora temos que ler o arquivo de pouco a pouco. 726 01:00:41,290 --> 01:00:46,300 Nós discutimos algumas formas de leitura de arquivos. 727 01:00:46,300 --> 01:00:51,830 Quais são os seus favoritos até agora? 728 01:00:51,830 --> 01:00:57,960 Que forma você já viu ou não se lembra, para ler arquivos? 729 01:00:57,960 --> 01:01:04,870 [Daniel] fread? Fread >>? Então fread é um deles. Jimmy, você conhece algum outro? 730 01:01:04,870 --> 01:01:12,150 [Jimmy] Não. >> Okay. Nope. Charlotte? Alexander? Quaisquer outros? Okay. 731 01:01:12,150 --> 01:01:20,740 Assim, os outros são fgetc, é um que nós vamos usar muito. 732 01:01:20,740 --> 01:01:26,410 Há também fscanf; vocês ver um padrão aqui? 733 01:01:26,410 --> 01:01:29,170 Todos eles começam com f. Nada a ver com um arquivo. 734 01:01:29,170 --> 01:01:35,260 Há fread, fgetc, fscanf. Estas são todas as funções de leitura. 735 01:01:35,260 --> 01:01:49,120 Para escrever temos fwrite, temos fputc vez de fgetc. 736 01:01:49,120 --> 01:01:58,250 Temos também fprintf como vimos no questionário. 737 01:01:58,250 --> 01:02:01,680 Uma vez que este é um problema que envolve a leitura de um ficheiro, 738 01:02:01,680 --> 01:02:04,940 vamos usar uma dessas três funções. 739 01:02:04,940 --> 01:02:10,890 Nós não estamos indo para usar estas funções aqui. 740 01:02:10,890 --> 01:02:14,880 Estas funções são encontradas na biblioteca de I / O padrão. 741 01:02:14,880 --> 01:02:17,510 Então, se você olhar para o topo do programa, 742 01:02:17,510 --> 01:02:24,110 você pode ver que nós já incluído o arquivo de cabeçalho para a biblioteca de I / O padrão. 743 01:02:24,110 --> 01:02:27,120 Se quisermos descobrir qual queremos usar, 744 01:02:27,120 --> 01:02:29,690 podemos sempre abrir as páginas man. 745 01:02:29,690 --> 01:02:34,350 Assim, podemos digitar stdio homem 746 01:02:34,350 --> 01:02:43,180 e ler tudo sobre a entrada stdio e funções de saída em C. 747 01:02:43,180 --> 01:02:49,870 E já podemos ver oh, olha. É mencionar fgetc, é mencionar fputc. 748 01:02:49,870 --> 01:02:57,220 Assim, você pode se aprofundar um pouco e olhar para, digamos, fgetc 749 01:02:57,220 --> 01:03:00,060 e olhar para sua página do homem. 750 01:03:00,060 --> 01:03:03,430 Você pode ver que ele vai junto com um monte de outras funções: 751 01:03:03,430 --> 01:03:12,640 fgetc, fgets, getc, getchar, fica, ungetc, e sua entrada de caracteres e strings. 752 01:03:12,640 --> 01:03:19,180 Portanto, esta é a maneira como lemos em caracteres e strings de arquivos de entrada padrão, 753 01:03:19,180 --> 01:03:21,990 que é, essencialmente, a partir do utilizador. 754 01:03:21,990 --> 01:03:24,780 E é assim que fazemos em C. real 755 01:03:24,780 --> 01:03:30,850 Portanto, este não está usando o GetString e funções getchar 756 01:03:30,850 --> 01:03:36,840 que foi utilizada a partir da biblioteca de CS50. 757 01:03:36,840 --> 01:03:39,710 Nós vamos fazer esse problema em um par de formas 758 01:03:39,710 --> 01:03:43,430 de modo que você pode ver duas maneiras diferentes de fazê-lo. 759 01:03:43,430 --> 01:03:48,490 Tanto a função fread que Daniel mencionado e fgetc são boas maneiras de fazê-lo. 760 01:03:48,490 --> 01:03:53,790 Eu acho que fgetc é um pouco mais fácil, porque ele só tem, como se vê, 761 01:03:53,790 --> 01:03:59,660 um argumento, o FILE * que estamos tentando ler o personagem, 762 01:03:59,660 --> 01:04:02,740 e seu valor de retorno é um int. 763 01:04:02,740 --> 01:04:05,610 E isso é um pouco confuso, né? 764 01:04:05,610 --> 01:04:11,450 >> Porque nós estamos começando um personagem, então por que não faz isso um retorno char? 765 01:04:11,450 --> 01:04:18,700 Vocês têm alguma idéia sobre por que isso não pode retornar um char? 766 01:04:18,700 --> 01:04:25,510 [Respostas Missy, ininteligível] >> sim. Então, Missy é totalmente certo. 767 01:04:25,510 --> 01:04:31,570 Se for ASCII, então este inteiro poderia ser mapeado para um caractere real. 768 01:04:31,570 --> 01:04:33,520 Poderia ser um caractere ASCII, e isso é certo. 769 01:04:33,520 --> 01:04:36,220 Isso é exatamente o que está acontecendo. 770 01:04:36,220 --> 01:04:39,190 Estamos usando um int simplesmente porque tem mais bits. 771 01:04:39,190 --> 01:04:44,750 É maior do que um char, o nosso carvão tem apenas 8 bits, 1 byte que em nossas máquinas de 32 bits. 772 01:04:44,750 --> 01:04:48,520 E um int tem valor todos os 4 bytes 'do espaço. 773 01:04:48,520 --> 01:04:50,940 E acontece que a maneira fgetc funciona, 774 01:04:50,940 --> 01:04:53,940 se deslocar para baixo na nossa sinopse nesta página do manual um pouco, 775 01:04:53,940 --> 01:05:05,000 percorrer todo o caminho para baixo. Acontece que eles usam esse valor especial chamado EOF. 776 01:05:05,000 --> 01:05:09,640 É uma constante especial como o valor de retorno da função fgetc 777 01:05:09,640 --> 01:05:14,570 sempre que você atingiu no final do arquivo ou se você receber um erro. 778 01:05:14,570 --> 01:05:18,170 E verifica-se que para fazer estas comparações com EOF corretamente, 779 01:05:18,170 --> 01:05:24,060 você quer ter essa quantidade extra de informações que você tem em um int 780 01:05:24,060 --> 01:05:28,420 em vez de usar uma variável char. 781 01:05:28,420 --> 01:05:32,130 Mesmo que fgetc é efetivamente começar um personagem de um arquivo, 782 01:05:32,130 --> 01:05:38,450 você quer se lembrar que ele está retornando algo que é do tipo int para você. 783 01:05:38,450 --> 01:05:41,360 Dito isso, é bastante fácil de usar. 784 01:05:41,360 --> 01:05:44,960 Vai nos dar um caráter, por isso tudo o que temos a fazer é continuar fazendo o arquivo, 785 01:05:44,960 --> 01:05:48,440 "Dê-me o próximo personagem, dá-me o próximo personagem, dá-me o próximo personagem", 786 01:05:48,440 --> 01:05:51,400 até chegarmos ao final do arquivo. 787 01:05:51,400 --> 01:05:54,730 E que irá puxar um personagem em um momento do nosso arquivo, 788 01:05:54,730 --> 01:05:56,250 e então nós podemos fazer o que quiser com ele. 789 01:05:56,250 --> 01:06:00,160 Nós podemos armazená-lo, podemos adicioná-lo a uma corda, que pode imprimi-lo. 790 01:06:00,160 --> 01:06:04,630 Fazer nada disso. 791 01:06:04,630 --> 01:06:09,600 >> Zoom de volta e voltar ao nosso programa cat.c, 792 01:06:09,600 --> 01:06:16,170 se vamos usar fgetc, 793 01:06:16,170 --> 01:06:21,710 como podemos abordar esta próxima linha de código? 794 01:06:21,710 --> 01:06:26,020 Nós vamos usar - fread vai fazer alguma coisa um pouco diferente. 795 01:06:26,020 --> 01:06:32,600 E, desta vez, estamos indo só para usar fgetc para obter um personagem de cada vez. 796 01:06:32,600 --> 01:06:40,910 Para processar um arquivo inteiro, o que poderia nós temos que fazer? 797 01:06:40,910 --> 01:06:44,030 Quantos personagens estão lá em um arquivo? 798 01:06:44,030 --> 01:06:47,390 Há uma grande quantidade. Então você provavelmente quer obter um 799 01:06:47,390 --> 01:06:49,860 e depois pegar outro e começar outro e começar outro. 800 01:06:49,860 --> 01:06:53,330 Que tipo de algoritmo que você acha que pode ter que usar aqui? 801 01:06:53,330 --> 01:06:55,470 Que tipo de -? [Alexander] Um loop for? >> Exatamente. 802 01:06:55,470 --> 01:06:57,500 Algum tipo de laço. 803 01:06:57,500 --> 01:07:03,380 Um laço for é realmente grande, neste caso. 804 01:07:03,380 --> 01:07:08,620 E como você estava dizendo, parece que você quer um laço sobre o arquivo inteiro, 805 01:07:08,620 --> 01:07:11,820 obtenção de um personagem de cada vez. 806 01:07:11,820 --> 01:07:13,850 Sugestões sobre o que pode parecer? 807 01:07:13,850 --> 01:07:22,090 [Alexander, ininteligível] 808 01:07:22,090 --> 01:07:30,050 >> Ok, diga-me em Inglês o que você está tentando fazer? [Alexander, ininteligível] 809 01:07:30,050 --> 01:07:36,270 Portanto, neste caso, parece que estamos apenas tentando varrer o arquivo inteiro. 810 01:07:36,270 --> 01:07:45,330 [Alexander] Então i > O tamanho de -? 811 01:07:45,330 --> 01:07:49,290 Eu acho que o tamanho do arquivo, certo? O tamanho - nós apenas escrever assim. 812 01:07:49,290 --> 01:07:57,470 Tamanho do arquivo para o momento, i + +. 813 01:07:57,470 --> 01:08:04,610 Assim, verifica-se que a maneira de fazer isso usando fgetc, e isso é novo, 814 01:08:04,610 --> 01:08:10,460 é que não há nenhuma maneira fácil de obter apenas o tamanho de um arquivo 815 01:08:10,460 --> 01:08:16,979 com este "sizeof" tipo de construção que você já viu antes. 816 01:08:16,979 --> 01:08:20,910 Quando usamos essa função fgetc, estamos introduzindo algum tipo de 817 01:08:20,910 --> 01:08:29,069 sintaxe, novo funky para este loop, onde em vez de usar apenas um contador básico 818 01:08:29,069 --> 01:08:33,920 ir caractere por caractere, vamos puxar um personagem de cada vez, 819 01:08:33,920 --> 01:08:37,120 um personagem de cada vez, e da maneira que sabemos que estamos no fim 820 01:08:37,120 --> 01:08:41,290 não é quando temos contado um determinado número de caracteres, 821 01:08:41,290 --> 01:08:49,939 mas quando o personagem que retire é esse fim específico do arquivo de caracteres. 822 01:08:49,939 --> 01:08:58,689 Assim, podemos fazer isso - Eu chamo isso de pc, e nós estamos indo para o inicializar 823 01:08:58,689 --> 01:09:08,050 com a nossa primeira chamada para obter o primeiro caractere fora do arquivo. 824 01:09:08,050 --> 01:09:14,979 Então, essa parte aqui, isso vai obter um personagem fora do arquivo 825 01:09:14,979 --> 01:09:20,840 e armazená-lo no ch variável. 826 01:09:20,840 --> 01:09:25,420 Nós vamos continuar fazendo isso até chegarmos ao final do arquivo, 827 01:09:25,420 --> 01:09:41,170 o que fazemos por meio de testes para o personagem não ser igual ao que o personagem EOF especial. 828 01:09:41,170 --> 01:09:48,750 E, em seguida, em vez de fazer o ch + +, o que apenas aumentar o valor, 829 01:09:48,750 --> 01:09:52,710 por isso, se lemos um fora A do arquivo, uma capital de um, digamos, 830 01:09:52,710 --> 01:09:56,810 ch + + nos daria b, e então teríamos c e d. 831 01:09:56,810 --> 01:09:59,310 Isso claramente não é o que queremos. O que nós queremos aqui 832 01:09:59,310 --> 01:10:05,830 neste último bit é que queremos obter o próximo personagem a partir do arquivo. 833 01:10:05,830 --> 01:10:09,500 >> Então, como podemos obter o próximo caractere do arquivo? 834 01:10:09,500 --> 01:10:13,470 Como podemos obter o primeiro caractere do arquivo? 835 01:10:13,470 --> 01:10:17,200 [Estudante] fgetfile? Fgetc >>, ou, desculpe, você estava totalmente certo. 836 01:10:17,200 --> 01:10:20,470 Eu grafada aí. Então, sim. 837 01:10:20,470 --> 01:10:26,240 Aqui, em vez de fazer ch + +, 838 01:10:26,240 --> 01:10:29,560 nós apenas estamos indo para chamar fgetc (arquivo) novamente 839 01:10:29,560 --> 01:10:39,180 e armazenar o resultado em nossa variável ch mesmo. 840 01:10:39,180 --> 01:10:43,730 [Pergunta do estudante, ininteligível] 841 01:10:43,730 --> 01:10:52,390 >> Este é onde esses caras arquivo * são especiais. 842 01:10:52,390 --> 01:10:59,070 A forma de trabalhar é que - quando você abre pela primeira vez - quando você fazer essa chamada fopen, 843 01:10:59,070 --> 01:11:04,260 o FILE * eficazmente serve como um ponteiro para o início do processo. 844 01:11:04,260 --> 01:11:12,830 E então, cada vez que você chamar fgetc, move-se um personagem através do arquivo. 845 01:11:12,830 --> 01:11:23,280 Assim, sempre que você chama isso, você está incrementando o ponteiro de arquivo por um caractere. 846 01:11:23,280 --> 01:11:26,210 E quando você fgetc novamente, você está movendo-outro personagem 847 01:11:26,210 --> 01:11:28,910 e outro personagem e outro personagem e outro personagem. 848 01:11:28,910 --> 01:11:32,030 [Pergunta do estudante, ininteligível] >> E isto - sim. 849 01:11:32,030 --> 01:11:34,810 É uma espécie de esta magia debaixo do capô. 850 01:11:34,810 --> 01:11:37,930 Você simplesmente continua incrementando através. 851 01:11:37,930 --> 01:11:46,510 Neste ponto, você é capaz de realmente trabalhar com um personagem. 852 01:11:46,510 --> 01:11:52,150 Então, como podemos imprimir isso para a tela, agora? 853 01:11:52,150 --> 01:11:58,340 Podemos usar a mesma coisa printf que usamos antes. 854 01:11:58,340 --> 01:12:00,330 Que temos vindo a utilizar todo o semestre. 855 01:12:00,330 --> 01:12:05,450 Podemos chamar printf, 856 01:12:05,450 --> 01:12:21,300 e podemos passar o personagem assim. 857 01:12:21,300 --> 01:12:27,430 Outra maneira de fazer isso é em vez de usar printf e ter que fazer essa seqüência de formato, 858 01:12:27,430 --> 01:12:29,490 também podemos usar uma das outras funções. 859 01:12:29,490 --> 01:12:40,090 Podemos usar fputc, que imprime um caráter para a tela, 860 01:12:40,090 --> 01:12:52,580 exceto se olharmos para fputc - deixe-me afastar um pouco. 861 01:12:52,580 --> 01:12:56,430 Nós vemos o que é bom é que leva no caráter que lemos, utilizando fgetc, 862 01:12:56,430 --> 01:13:05,100 mas então temos de dar-lhe um fluxo para imprimir. 863 01:13:05,100 --> 01:13:11,850 Podemos também utilizar a função putchar, que irá colocar diretamente para saída padrão. 864 01:13:11,850 --> 01:13:16,070 Portanto, há um monte de opções diferentes que podemos usar para impressão. 865 01:13:16,070 --> 01:13:19,580 Eles estão todos na biblioteca de I / O padrão. 866 01:13:19,580 --> 01:13:25,150 Sempre que você deseja imprimir - assim printf, por padrão, irá imprimir à norma especial saída de fluxo, 867 01:13:25,150 --> 01:13:27,910 que é a saída padrão. 868 01:13:27,910 --> 01:13:41,300 Assim, podemos apenas se referem a ele como uma espécie de magia este valor, stdout aqui. 869 01:13:41,300 --> 01:13:48,410 Oops. Coloque o ponto e vírgula fora. 870 01:13:48,410 --> 01:13:52,790 >> Esta é uma grande quantidade de informação nova, funk aqui. 871 01:13:52,790 --> 01:13:58,600 Uma grande parte destas é muito idiomática, no sentido de que este é o código 872 01:13:58,600 --> 01:14:05,700 que é escrito desta forma só porque é limpo de ler, fácil de ler. 873 01:14:05,700 --> 01:14:11,520 Há muitas maneiras diferentes de fazer isso, muitas funções diferentes que você pode usar, 874 01:14:11,520 --> 01:14:14,680 mas nós só tendem a seguir estes mesmos padrões mais e mais. 875 01:14:14,680 --> 01:14:20,180 Portanto, não se surpreenda se você ver um código como este vindo de novo e de novo. 876 01:14:20,180 --> 01:14:25,690 Tudo bem. Neste ponto, é preciso quebrar para o dia. 877 01:14:25,690 --> 01:14:31,300 Obrigado por vir. Obrigado por assistir, se você estiver online. E nós vamos vê-lo na próxima semana. 878 01:14:31,300 --> 01:14:33,890 [CS50.TV]