1 00:00:00,000 --> 00:00:03,000 [Powered by Google Translate] [Semana 4] 2 00:00:03,000 --> 00:00:05,000 [David J. Malan] [Harvard University] 3 00:00:05,000 --> 00:00:08,000 [Esta é CS50.] [CS50.TV] 4 00:00:08,000 --> 00:00:12,000 >> Tudo bem, isso é CS50, e este é o começo da semana 4, 5 00:00:12,000 --> 00:00:16,000 e este é um dos algoritmos de classificação mais lenta possível. 6 00:00:16,000 --> 00:00:19,000 Qual era que apenas assistiu lá? 7 00:00:19,000 --> 00:00:24,000 Que era uma espécie de bolha, em ordem grande O (n ^ 2) + soma, 8 00:00:24,000 --> 00:00:28,000 e na verdade não são os únicos no mundo a parecem saber 9 00:00:28,000 --> 00:00:30,000 que tipo de bolha é ou seu tempo de execução. 10 00:00:30,000 --> 00:00:33,000 Na verdade, esta foi uma entrevista com Eric Schmidt, do Google 11 00:00:33,000 --> 00:00:45,000 eo ex-senador Barack Obama apenas alguns anos atrás. 12 00:00:45,000 --> 00:00:48,000 >> Agora, o senador, que está aqui no Google, 13 00:00:48,000 --> 00:00:54,000 e eu gosto de pensar a presidência como uma entrevista de emprego. 14 00:00:54,000 --> 00:00:58,000 Agora, é difícil conseguir um trabalho como presidente, e você está passando os rigores agora. 15 00:00:58,000 --> 00:01:00,000 Também é difícil conseguir um emprego no Google. 16 00:01:00,000 --> 00:01:05,000 Nós temos perguntas, e fazemos perguntas nossos candidatos, 17 00:01:05,000 --> 00:01:10,000 e este é de Larry David Schwimmer. 18 00:01:10,000 --> 00:01:14,000 Vocês pensam que eu estou brincando? É aqui mesmo. 19 00:01:14,000 --> 00:01:18,000 O que é a maneira mais eficiente para classificar um milhão de inteiros de 32 bits? 20 00:01:18,000 --> 00:01:21,000 [Risos] 21 00:01:21,000 --> 00:01:24,000 Bem- 22 00:01:24,000 --> 00:01:26,000 Sinto muito. >> Não, não, não, não. 23 00:01:26,000 --> 00:01:34,000 Eu acho que o bubble sort seria o caminho errado para ir. 24 00:01:34,000 --> 00:01:39,000 >> Vamos, que lhe disse isso? 25 00:01:39,000 --> 00:01:43,000 Na semana passada, lembro que teve uma quebra de código, pelo menos por um dia, 26 00:01:43,000 --> 00:01:46,000 e passaram a se concentrar em algumas idéias de nível superior e de resolução de problemas de modo mais geral 27 00:01:46,000 --> 00:01:49,000 no contexto de pesquisa e classificação, 28 00:01:49,000 --> 00:01:53,000 e introduziu algo que não tapa este nome na semana passada, 29 00:01:53,000 --> 00:01:56,000 mas a notação assintótica, o Big O, o Omega Grande, 30 00:01:56,000 --> 00:02:00,000 e às vezes a notação Big Theta, e estes eram simplesmente formas 31 00:02:00,000 --> 00:02:02,000 de descrever o tempo de execução de algoritmos, 32 00:02:02,000 --> 00:02:05,000 quanto tempo leva para um algoritmo para ser executado. 33 00:02:05,000 --> 00:02:08,000 >> E você deve se lembrar que você falou sobre o tempo de execução em termos de tamanho 34 00:02:08,000 --> 00:02:11,000 da entrada, que geralmente chamamos de n, qualquer que seja o problema pode ser, 35 00:02:11,000 --> 00:02:13,000 onde n é o número de pessoas na sala, 36 00:02:13,000 --> 00:02:17,000 o número de páginas de um livro de telefone, e começamos a escrever as coisas 37 00:02:17,000 --> 00:02:21,000 como O (n ^ 2) ou O (n) ou O (n log n), 38 00:02:21,000 --> 00:02:24,000 e mesmo quando a matemática não deu muito certo tão perfeitamente 39 00:02:24,000 --> 00:02:28,000 e foi n ² - n / 2, ou algo assim 40 00:02:28,000 --> 00:02:31,000 nós, ao invés, apenas jogar fora alguns dos termos de ordem mais baixa, 41 00:02:31,000 --> 00:02:34,000 ea motivação lá é que realmente queremos uma 42 00:02:34,000 --> 00:02:37,000 tipo de forma objetiva de avaliar 43 00:02:37,000 --> 00:02:39,000 o desempenho de programas ou o desempenho de algoritmos 44 00:02:39,000 --> 00:02:42,000 que, no final do dia, nada tem a ver, por exemplo, 45 00:02:42,000 --> 00:02:45,000 com a velocidade de seu computador hoje. 46 00:02:45,000 --> 00:02:47,000 >> Por exemplo, se você implementar bubble sort 47 00:02:47,000 --> 00:02:50,000 ou você implementar merge sort tipo ou seleção no computador de hoje, 48 00:02:50,000 --> 00:02:53,000 um computador 2 GHz, e executá-lo, 49 00:02:53,000 --> 00:02:56,000 e isso leva algum número de segundos, no próximo ano, há um 3 GHz 50 00:02:56,000 --> 00:02:59,000 ou um computador 4 GHz, e você poderia, então, afirmar que "Uau, meu algoritmo 51 00:02:59,000 --> 00:03:03,000 é agora duas vezes mais rápido ", quando na realidade que obviamente não é o caso. 52 00:03:03,000 --> 00:03:06,000 É só o hardware ficou mais rápido, mas o seu computador 53 00:03:06,000 --> 00:03:10,000 não tem, e assim nós realmente queremos jogar fora coisas como 54 00:03:10,000 --> 00:03:13,000 múltiplos de 2 ou múltiplos de 3, quando se trata de descrever 55 00:03:13,000 --> 00:03:17,000 quão rápido ou lento como um algoritmo é realmente e se concentrar apenas 56 00:03:17,000 --> 00:03:20,000 em n ou algum factor º, 57 00:03:20,000 --> 00:03:24,000 algum poder do mesmo, como no caso dos tipos de na última semana. 58 00:03:24,000 --> 00:03:27,000 E lembrar que, com a ajuda de merge sort 59 00:03:27,000 --> 00:03:31,000 fomos capazes de fazer muito melhor do que o bubble sort e tipo de seleção 60 00:03:31,000 --> 00:03:33,000 e tipo de inserção mesmo. 61 00:03:33,000 --> 00:03:36,000 >> Temos até n log n, e, novamente, 62 00:03:36,000 --> 00:03:39,000 Recordamos que log n geralmente se refere a algo que cresce 63 00:03:39,000 --> 00:03:43,000 mais lentamente então n, então n log n, até agora, era bom 64 00:03:43,000 --> 00:03:45,000 porque era menos de ² n. 65 00:03:45,000 --> 00:03:47,000 Mas para alcançar n log n com merge sort 66 00:03:47,000 --> 00:03:51,000 qual foi o germe de uma idéia básica que tivemos para alavancar 67 00:03:51,000 --> 00:03:54,000 que também alavancou de volta na semana 0? 68 00:03:54,000 --> 00:03:58,000 Como nós enfrentar o problema de ordenação inteligente com merge sort? 69 00:03:58,000 --> 00:04:04,000 Qual foi a chave da compreensão, talvez? 70 00:04:04,000 --> 00:04:07,000 Ninguém. 71 00:04:07,000 --> 00:04:09,000 Ok, vamos dar um passo atrás. 72 00:04:09,000 --> 00:04:11,000 Descreva merge sort em suas próprias palavras. 73 00:04:11,000 --> 00:04:15,000 Como isso funciona? 74 00:04:15,000 --> 00:04:17,000 Ok, vamos remar de volta para 0 semanas. 75 00:04:17,000 --> 00:04:19,000 Ok, sim. 76 00:04:19,000 --> 00:04:22,000 [Inaudível-aluno] 77 00:04:22,000 --> 00:04:26,000 Ok, bom, então dividimos o conjunto de números em dois pedaços. 78 00:04:26,000 --> 00:04:29,000 Nós classificada cada uma dessas peças, e então fundiu-os, 79 00:04:29,000 --> 00:04:33,000 e temos visto essa idéia antes de tomar um problema que é tão grande 80 00:04:33,000 --> 00:04:36,000 e cortar-lo em um problema que é tão grande ou tão grande. 81 00:04:36,000 --> 00:04:38,000 >> Lembre-se do exemplo do livro de telefone. 82 00:04:38,000 --> 00:04:42,000 Lembre-se o algoritmo de auto-contagem de semanas atrás, 83 00:04:42,000 --> 00:04:45,000 tipo assim fundir foi resumida por este pseudocódigo aqui. 84 00:04:45,000 --> 00:04:48,000 Quando você está determinado n elementos, primeiro era verificar a sanidade. 85 00:04:48,000 --> 00:04:51,000 Se n <2, então não fazer nada 86 00:04:51,000 --> 00:04:55,000 porque se n <2, então n é 0 ou 1, obviamente, 87 00:04:55,000 --> 00:04:57,000 e assim se é 0 ou 1 não há nada para resolver. 88 00:04:57,000 --> 00:04:59,000 Você está feito. 89 00:04:59,000 --> 00:05:01,000 Sua lista já está trivialmente classificados. 90 00:05:01,000 --> 00:05:04,000 Mas caso contrário, se você tem dois ou mais elementos de ir em frente e dividi-los 91 00:05:04,000 --> 00:05:06,000 em duas metades, direita e esquerda. 92 00:05:06,000 --> 00:05:09,000 Classificar cada uma dessas metades, e em seguida, mesclar as metades classificados. 93 00:05:09,000 --> 00:05:13,000 Mas o problema aqui é que, à primeira vista isso parece que estamos punting. 94 00:05:13,000 --> 00:05:17,000 Esta é uma definição circular em que se eu lhe pedi para classificar estes elementos n 95 00:05:17,000 --> 00:05:22,000 e você está me dizendo "Tudo bem, tudo bem, vamos classificar os elementos n / 2 e os n / 2", 96 00:05:22,000 --> 00:05:27,000 então minha próxima pergunta vai ser "Tudo bem, como você classificar a n / 2 elementos?" 97 00:05:27,000 --> 00:05:30,000 >> Mas, devido à estrutura do presente programa, 98 00:05:30,000 --> 00:05:33,000 porque não é este o caso base, por assim dizer, 99 00:05:33,000 --> 00:05:39,000 Neste caso especial, que diz que, se n é 00:05:42,000 Não responderemos com esta mesma resposta circular. 101 00:05:42,000 --> 00:05:46,000 Este processo, este ciclicidade acabará. 102 00:05:46,000 --> 00:05:50,000 Se eu lhe perguntar "Classificar estes elementos n", e você diz: "Muito bem, classificar estes n / 2", 103 00:05:50,000 --> 00:05:53,000 então você diz, "tipo, Fine estes n / 4, n / 8, n/16" 104 00:05:53,000 --> 00:05:56,000 eventualmente, você vai dividir por um número grande o suficiente 105 00:05:56,000 --> 00:05:59,000 que você vai ter apenas um elemento de esquerda, em que ponto você pode dizer: 106 00:05:59,000 --> 00:06:02,000 "Aqui, aqui é um elemento classificado único". 107 00:06:02,000 --> 00:06:06,000 Em seguida, o brilho deste algoritmo aqui é derivar do fato de 108 00:06:06,000 --> 00:06:09,000 que uma vez que você tem todas estas listas individualmente classificados, 109 00:06:09,000 --> 00:06:12,000 todos os quais são de tamanho 1, o que parece ser inútil, 110 00:06:12,000 --> 00:06:15,000 uma vez que você começar a fundi-las e mesclá-los 111 00:06:15,000 --> 00:06:19,000 você construir, finalmente, como Rob fez no vídeo, finalmente, uma lista ordenada. 112 00:06:19,000 --> 00:06:22,000 >> Mas essa idéia vai muito além de classificação. 113 00:06:22,000 --> 00:06:26,000 Esta é a idéia incorporado neste programa conhecido como recursão, 114 00:06:26,000 --> 00:06:29,000 a idéia em que você é um programa, 115 00:06:29,000 --> 00:06:32,000 e para resolver algum problema que chama a si mesmo, 116 00:06:32,000 --> 00:06:36,000 ou colocar no contexto de linguagens de programação você é uma função, 117 00:06:36,000 --> 00:06:39,000 e, a fim de resolver um problema, você a função de chamar a si mesmo 118 00:06:39,000 --> 00:06:42,000 de novo e de novo e de novo, mas a função 119 00:06:42,000 --> 00:06:44,000 não pode chamar-se infinitas vezes. 120 00:06:44,000 --> 00:06:47,000 Eventualmente, você tem para baixo para fora, por assim dizer, 121 00:06:47,000 --> 00:06:49,000 e ter alguma condição de base embutida que diz 122 00:06:49,000 --> 00:06:53,000 neste momento parar de chamar a si mesmo de modo que todo o processo 123 00:06:53,000 --> 00:06:56,000 finalmente, se de fato parar. 124 00:06:56,000 --> 00:06:58,000 O que isso realmente significa, para recurse? 125 00:06:58,000 --> 00:07:01,000 >> Vamos ver, se é que podemos fazer um exemplo simples, trivial com, digamos, 126 00:07:01,000 --> 00:07:03,000 3 pessoas comigo aqui em cima no palco, se alguém é confortável. 127 00:07:03,000 --> 00:07:06,000 Um, vamos para cima, 2 e 3. 128 00:07:06,000 --> 00:07:09,000 Se você 3 quer vir até aqui. 129 00:07:09,000 --> 00:07:12,000 Se você quer estar ao meu lado aqui em uma linha, vamos supor que o problema na mão 130 00:07:12,000 --> 00:07:15,000 é muito trivialmente contar o número de pessoas que estão aqui. 131 00:07:15,000 --> 00:07:18,000 Mas, francamente, estou cansado de todos esses exemplos de contagem. 132 00:07:18,000 --> 00:07:21,000 Isso vai levar algum tempo, 1, 2, e ponto, ponto, ponto. 133 00:07:21,000 --> 00:07:23,000 Vai demorar uma eternidade. 134 00:07:23,000 --> 00:07:25,000 Eu prefiro apenas punt este problema completamente com a ajuda de-qual é o seu nome? 135 00:07:25,000 --> 00:07:27,000 Sara. >> Sara, tudo bem. 136 00:07:27,000 --> 00:07:29,000 Kelly. >> Kelly e? 137 00:07:29,000 --> 00:07:31,000 >> Willy. >> Willy, Sara, Kelly e Willy. 138 00:07:31,000 --> 00:07:34,000 Agora eu tenho a pergunta por alguém 139 00:07:34,000 --> 00:07:37,000 quantas pessoas estão-se neste palco, e eu não tenho idéia. 140 00:07:37,000 --> 00:07:40,000 Esta é uma lista muito longa, e assim ao invés disso eu vou fazer este truque. 141 00:07:40,000 --> 00:07:43,000 Eu vou pedir para a pessoa ao meu lado para fazer a maior parte do trabalho, 142 00:07:43,000 --> 00:07:46,000 e uma vez que ela é feita fazendo a maioria do trabalho 143 00:07:46,000 --> 00:07:49,000 Eu vou fazer o mínimo de trabalho possível e apenas adicionar uma 144 00:07:49,000 --> 00:07:51,000 para o que a sua resposta é, então aqui vamos nós. 145 00:07:51,000 --> 00:07:54,000 Já me perguntaram quantas pessoas estão no palco. 146 00:07:54,000 --> 00:07:57,000 Quantas pessoas estão no palco à esquerda de você? 147 00:07:57,000 --> 00:08:00,000 A esquerda de mim? >> Ok, mas não enganar. 148 00:08:00,000 --> 00:08:04,000 Isso é bom, isso é correto, mas se queremos continuar esta lógica 149 00:08:04,000 --> 00:08:08,000 vamos supor que você quer igualmente punt este problema à esquerda de você, 150 00:08:08,000 --> 00:08:11,000 então ao invés de responder diretamente ir em frente e passar a bola. 151 00:08:11,000 --> 00:08:14,000 Ah, quantas pessoas estão à esquerda de mim? 152 00:08:14,000 --> 00:08:16,000 Quantas pessoas estão para a esquerda? 153 00:08:16,000 --> 00:08:18,000 1. 154 00:08:18,000 --> 00:08:27,000 [Risos] 155 00:08:27,000 --> 00:08:30,000 Ok, então 0, então o que agora Willy fez 156 00:08:30,000 --> 00:08:33,000 é você voltou a sua resposta neste sentido dizendo 0. 157 00:08:33,000 --> 00:08:36,000 Agora, o que você deve fazer? >> 1. 158 00:08:36,000 --> 00:08:39,000 Ok, então você é o 1, então você diz: "Tudo bem, eu estou indo para adicionar um 159 00:08:39,000 --> 00:08:41,000 para qualquer contagem de Willy era, "para 1 + 0. 160 00:08:41,000 --> 00:08:43,000 Você está agora 1 para a sua resposta para a direita é agora 161 00:08:43,000 --> 00:08:45,000 1. >> E a minha seria 2. 162 00:08:45,000 --> 00:08:48,000 Bom, então você está tomando a resposta anterior de 1, 163 00:08:48,000 --> 00:08:51,000 adicionando a quantidade mínima de trabalho que você quer fazer, o que é um. 164 00:08:51,000 --> 00:08:55,000 Você agora tem dois, e você em seguida, entregá-me qual o valor? 165 00:08:55,000 --> 00:08:57,000 3, eu quero dizer, desculpe, 2. 166 00:08:57,000 --> 00:08:59,000 Bom. 167 00:08:59,000 --> 00:09:02,000 >> Bem, nós tivemos 0 para a esquerda. 168 00:09:02,000 --> 00:09:05,000 Então nós tivemos um, e então adicionar 2, 169 00:09:05,000 --> 00:09:07,000 e agora você está me dando o número 2, 170 00:09:07,000 --> 00:09:10,000 e assim que eu estou dizendo, tudo bem, uma, 3. 171 00:09:10,000 --> 00:09:13,000 Há de fato três pessoas que estavam ao meu lado nesta fase, 172 00:09:13,000 --> 00:09:16,000 para que pudéssemos ter feito isso, obviamente, muito linear, 173 00:09:16,000 --> 00:09:19,000 muito na moda óbvio, mas o que realmente fazer? 174 00:09:19,000 --> 00:09:21,000 Pegamos um problema de tamanho 3 inicialmente. 175 00:09:21,000 --> 00:09:24,000 Em seguida, partiu-se em um problema de tamanho 2, 176 00:09:24,000 --> 00:09:27,000 então um problema de tamanho 1 e, em seguida, finalmente, caso a base 177 00:09:27,000 --> 00:09:29,000 Foi muito, oh, não há ninguém lá, 178 00:09:29,000 --> 00:09:33,000 altura em que Willy voltou efetivamente uma resposta codificado um par de vezes, 179 00:09:33,000 --> 00:09:36,000 ea segunda foi então borbulhava, borbulhava, borbulhava, 180 00:09:36,000 --> 00:09:39,000 e, em seguida, adicionando a este um um adicional 181 00:09:39,000 --> 00:09:41,000 temos implementado essa idéia básica de recursão. 182 00:09:41,000 --> 00:09:44,000 >> Agora, neste caso, realmente não resolver um problema 183 00:09:44,000 --> 00:09:46,000 mais eficazmente, em seguida temos visto até agora. 184 00:09:46,000 --> 00:09:48,000 Mas pense sobre os algoritmos que fizemos no palco até o momento. 185 00:09:48,000 --> 00:09:51,000 Tivemos oito pedaços de papel no quadro-negro, 186 00:09:51,000 --> 00:09:55,000 em vídeo quando Sean estava olhando para o número 7, eo que ele realmente faz? 187 00:09:55,000 --> 00:09:58,000 Bem, ele não fez qualquer tipo de dividir e conquistar. 188 00:09:58,000 --> 00:10:01,000 Ele não fez qualquer tipo de recursão. 189 00:10:01,000 --> 00:10:03,000 Ao contrário, ele só fez este algoritmo linear. 190 00:10:03,000 --> 00:10:07,000 Mas, quando introduziu a idéia de números classificados no palco ao vivo na semana passada 191 00:10:07,000 --> 00:10:09,000 depois tivemos esse instinto de ir para o meio, 192 00:10:09,000 --> 00:10:13,000 em que ponto nós tivemos uma pequena lista de tamanho 4 ou outra lista de tamanho 4, 193 00:10:13,000 --> 00:10:17,000 e depois tivemos o mesmo problema, por isso, repete, repete, repete. 194 00:10:17,000 --> 00:10:19,000 Em outras palavras, nós recursed. 195 00:10:19,000 --> 00:10:24,000 Muito obrigado aos nossos três voluntários aqui para demonstrar recursão conosco. 196 00:10:24,000 --> 00:10:28,000 >> Vamos ver se não podemos fazer isso agora um pouco mais concreto, 197 00:10:28,000 --> 00:10:30,000 resolver um problema que novamente podemos fazer muito facilmente, 198 00:10:30,000 --> 00:10:34,000 mas vamos usá-lo como um trampolim para a aplicação desta ideia básica. 199 00:10:34,000 --> 00:10:37,000 Se eu quiser calcular a soma de um monte de números, 200 00:10:37,000 --> 00:10:39,000 por exemplo, se você passar o número 3, 201 00:10:39,000 --> 00:10:42,000 Eu quero dar-lhe o valor de 3 sigma, 202 00:10:42,000 --> 00:10:46,000 então a soma de 3 + 2 + 1 + 0. 203 00:10:46,000 --> 00:10:48,000 Eu quero voltar a resposta 6, 204 00:10:48,000 --> 00:10:51,000 então vamos implementar esta função sigma, esta função soma 205 00:10:51,000 --> 00:10:54,000 que, mais uma vez, leva a entrada e, em seguida, retorna a soma 206 00:10:54,000 --> 00:10:57,000 desse número até o fim a 0. 207 00:10:57,000 --> 00:10:59,000 Nós poderíamos fazer isso bastante simples, certo? 208 00:10:59,000 --> 00:11:01,000 Nós poderíamos fazer isso com algum tipo de estrutura de loop, 209 00:11:01,000 --> 00:11:04,000 então deixe-me ir em frente e começar com isso. 210 00:11:04,000 --> 00:11:07,000 >> Incluir stdio.h. 211 00:11:07,000 --> 00:11:09,000 Deixe-me me meter principal para trabalhar aqui. 212 00:11:09,000 --> 00:11:12,000 Vamos guardá-lo como sigma.c. 213 00:11:12,000 --> 00:11:14,000 Então eu vou entrar aqui, e eu vou declarar um int n, 214 00:11:14,000 --> 00:11:18,000 e eu vou fazer o seguinte, enquanto o usuário não cooperar. 215 00:11:18,000 --> 00:11:22,000 Enquanto o usuário não tenha me dado um número positivo 216 00:11:22,000 --> 00:11:26,000 deixe-me ir em frente e levá-los para n = GetInt, 217 00:11:26,000 --> 00:11:28,000 e deixe-me dar-lhes algumas instruções sobre o que fazer, 218 00:11:28,000 --> 00:11:33,000 assim printf ("inteiro positivo, por favor"). 219 00:11:33,000 --> 00:11:39,000 Apenas algo relativamente simples como este para que no momento em que atingiu a linha 14 220 00:11:39,000 --> 00:11:42,000 agora temos um número inteiro positivo, presumivelmente, no n. 221 00:11:42,000 --> 00:11:44,000 >> Agora vamos fazer algo com ele. 222 00:11:44,000 --> 00:11:50,000 Deixe-me ir em frente e calcular a soma, então int soma = sigma (n). 223 00:11:50,000 --> 00:11:54,000 Sigma é apenas soma, então eu só estou escrevendo-a na forma mais extravagante. 224 00:11:54,000 --> 00:11:56,000 Vamos chamar-lhe apenas sigma lá. 225 00:11:56,000 --> 00:11:58,000 Essa é a soma, e agora eu vou imprimir o resultado, 226 00:11:58,000 --> 00:12:08,000 printf ("A soma é% d \ n" soma). 227 00:12:08,000 --> 00:12:11,000 E então eu vou retornar 0 para uma boa medida. 228 00:12:11,000 --> 00:12:15,000 Fizemos tudo o que este programa requer, exceto a parte interessante, 229 00:12:15,000 --> 00:12:18,000 que é para realmente implementar a função sigma. 230 00:12:18,000 --> 00:12:22,000 >> Deixe-me ir até aqui para a parte inferior, e deixe-me declarar função sigma. 231 00:12:22,000 --> 00:12:26,000 Tem que ter uma variável que é do tipo inteiro, 232 00:12:26,000 --> 00:12:30,000 e que tipo de dados que eu quero voltar presumivelmente de sigma? 233 00:12:30,000 --> 00:12:34,000 Int, porque eu quero que corresponder as minhas expectativas na linha 15. 234 00:12:34,000 --> 00:12:37,000 Em aqui, deixe-me ir em frente e implementar esta 235 00:12:37,000 --> 00:12:41,000 de uma forma bastante simples. 236 00:12:41,000 --> 00:12:45,000 >> Vamos em frente e dizer soma int = 0, 237 00:12:45,000 --> 00:12:47,000 e agora eu vou ter um pouco de loop aqui 238 00:12:47,000 --> 00:12:50,000 que vai dizer algo como isso, 239 00:12:50,000 --> 00:13:01,000 for (int i = 0; I <= número; i + +) soma + = i. 240 00:13:01,000 --> 00:13:05,000 E então eu vou voltar soma. 241 00:13:05,000 --> 00:13:07,000 Eu poderia ter implementado este em qualquer número de maneiras. 242 00:13:07,000 --> 00:13:09,000 Eu poderia ter usado um loop while. 243 00:13:09,000 --> 00:13:11,000 Eu poderia ter pulado usando a variável de soma, se eu realmente queria, 244 00:13:11,000 --> 00:13:15,000 mas em suma, só temos uma função que se eu não goof declara soma é 0. 245 00:13:15,000 --> 00:13:18,000 Em seguida, ele itera de 0 em cima através do número, 246 00:13:18,000 --> 00:13:23,000 e em cada iteração acrescenta que o valor atual de soma e retorna soma. 247 00:13:23,000 --> 00:13:25,000 >> Agora, há uma otimização de leve aqui. 248 00:13:25,000 --> 00:13:29,000 Este é provavelmente um passo desperdiçado, mas que assim seja. Isso é bom para agora. 249 00:13:29,000 --> 00:13:32,000 Estamos pelo menos vai ser completa e 0 todo o caminho em cima. 250 00:13:32,000 --> 00:13:34,000 Não é muito difícil e bastante simples, 251 00:13:34,000 --> 00:13:37,000 mas acontece que, com a função de sigma temos a mesma oportunidade 252 00:13:37,000 --> 00:13:39,000 como fizemos aqui no palco. 253 00:13:39,000 --> 00:13:42,000 No palco nós apenas contou quantas pessoas estavam ao meu lado, 254 00:13:42,000 --> 00:13:47,000 mas em vez disso se quisermos contar o número 3 + 2 + 1 255 00:13:47,000 --> 00:13:51,000 em até 0 poderíamos igualmente punt para uma função 256 00:13:51,000 --> 00:13:55,000 que eu vou descrever em vez de ser recursiva. 257 00:13:55,000 --> 00:13:57,000 Aqui vamos fazer um rápido check sanidade e ter certeza que eu não fiz brincadeira. 258 00:13:57,000 --> 00:14:00,000 >> Eu sei que há pelo menos uma coisa neste programa que eu fiz de errado. 259 00:14:00,000 --> 00:14:04,000 Quando eu bati entrar eu estou indo para obter qualquer tipo de gritar comigo? 260 00:14:04,000 --> 00:14:06,000 O que é que eu vou ser gritado sobre? 261 00:14:06,000 --> 00:14:11,000 Sim, eu esqueci o protótipo, então eu estou usando uma função chamada sigma na linha 15, 262 00:14:11,000 --> 00:14:16,000 mas não é declarada até a linha 22, então eu melhor forma proativa subir aqui 263 00:14:16,000 --> 00:14:22,000 e declarar um protótipo, e eu vou dizer int sigma (número inteiro), e é isso. 264 00:14:22,000 --> 00:14:24,000 É implementada na parte inferior. 265 00:14:24,000 --> 00:14:27,000 >> Ou de outra maneira que eu poderia resolver isso, 266 00:14:27,000 --> 00:14:30,000 Eu poderia mover a função lá em cima, o que não é ruim, 267 00:14:30,000 --> 00:14:32,000 mas pelo menos quando seus programas começam a ficar longo, francamente, 268 00:14:32,000 --> 00:14:35,000 Eu acho que há algum valor em ter sempre principal no topo 269 00:14:35,000 --> 00:14:38,000 para que você em que o leitor pode abrir o arquivo e logo em seguida ver 270 00:14:38,000 --> 00:14:40,000 o que o programa está fazendo sem ter que procurar por ele 271 00:14:40,000 --> 00:14:42,000 procurando que a principal função. 272 00:14:42,000 --> 00:14:49,000 Vamos até a minha janela de terminal aqui, tente fazer sigma fazer sigma, 273 00:14:49,000 --> 00:14:51,000 e eu estraguei tudo aqui também. 274 00:14:51,000 --> 00:14:55,000 Declaração implícita de GetInt função significa que eu esqueci de fazer o que mais? 275 00:14:55,000 --> 00:14:57,000 [Inaudível-aluno] 276 00:14:57,000 --> 00:15:00,000 Bom, então, aparentemente, um erro comum, então vamos colocar isso aqui, 277 00:15:00,000 --> 00:15:04,000 cs50.h, e agora vamos voltar para a minha janela de terminal. 278 00:15:04,000 --> 00:15:08,000 >> Eu vou limpar a tela, e eu vou fazer reprise sigma. 279 00:15:08,000 --> 00:15:11,000 Parece ter compilado. Deixa-me correr sigma. 280 00:15:11,000 --> 00:15:15,000 Eu vou digitar o número 3, e eu tive 6, de modo que não verificar um rigoroso 281 00:15:15,000 --> 00:15:18,000 mas pelo menos ele parece estar funcionando, à primeira vista, mas agora vamos destruí-la, 282 00:15:18,000 --> 00:15:21,000 e vamos realmente alavancar a idéia de recursividade, de novo, 283 00:15:21,000 --> 00:15:24,000 em um contexto muito simples, para que, no tempo de algumas semanas 284 00:15:24,000 --> 00:15:27,000 quando começar a explorar estruturas mais elegantes de dados de matrizes 285 00:15:27,000 --> 00:15:30,000 temos outra ferramenta no conjunto de ferramentas com as quais a 286 00:15:30,000 --> 00:15:33,000 manipular essas estruturas de dados, como veremos. 287 00:15:33,000 --> 00:15:36,000 Esta é a abordagem iterativa, a abordagem baseada em loop. 288 00:15:36,000 --> 00:15:39,000 >> Deixe-me em vez agora fazer isso. 289 00:15:39,000 --> 00:15:44,000 Deixe-me dizer que, em vez da soma do número 290 00:15:44,000 --> 00:15:48,000 em até 0 é realmente a mesma coisa que 291 00:15:48,000 --> 00:15:53,000 + número sigma (número - 1). 292 00:15:53,000 --> 00:15:57,000 Em outras palavras, assim como no palco eu punted a cada uma das pessoas próximas a mim, 293 00:15:57,000 --> 00:16:00,000 e eles, por sua vez, manteve punting até que finalmente ao fundo do poço em Willy, 294 00:16:00,000 --> 00:16:03,000 que teve de retornar uma resposta codificada como 0. 295 00:16:03,000 --> 00:16:07,000 Aqui, agora, estamos igualmente punting para sigma 296 00:16:07,000 --> 00:16:10,000 a mesma função que originalmente foi chamado, mas o insight chave aqui 297 00:16:10,000 --> 00:16:12,000 é que nós não estamos chamando sigma idêntica. 298 00:16:12,000 --> 00:16:14,000 Nós não estamos passando no n. 299 00:16:14,000 --> 00:16:17,000 Nós estamos claramente passando em número - 1, 300 00:16:17,000 --> 00:16:20,000 assim um problema um pouco menor, problema um pouco menor. 301 00:16:20,000 --> 00:16:23,000 >> Infelizmente, esta não é uma solução bastante ainda, e antes de corrigir 302 00:16:23,000 --> 00:16:26,000 o que pode ser tão óbvia saltar menos alguns de vocês 303 00:16:26,000 --> 00:16:28,000 deixe-me ir em frente e fazer executar novamente. 304 00:16:28,000 --> 00:16:30,000 Parece compilar tudo bem. 305 00:16:30,000 --> 00:16:32,000 Deixe-me reprise sigma com 6. 306 00:16:32,000 --> 00:16:37,000 Opa, deixe-me reprise sigma com 6. 307 00:16:37,000 --> 00:16:42,000 Nós já vimos isso antes, embora o tempo acidentalmente passado também. 308 00:16:42,000 --> 00:16:48,000 Por que eu recebo essa falha de segmentação enigmática? Sim. 309 00:16:48,000 --> 00:16:50,000 [Inaudível-aluno] 310 00:16:50,000 --> 00:16:53,000 Não há nenhum caso base, e mais especificamente, o que provavelmente aconteceu? 311 00:16:53,000 --> 00:16:58,000 Este é um sintoma de que o comportamento? 312 00:16:58,000 --> 00:17:00,000 Dizem que um pouco mais alto. 313 00:17:00,000 --> 00:17:02,000 [Inaudível-aluno] 314 00:17:02,000 --> 00:17:05,000 É um ciclo infinito de forma eficaz, e que o problema com loops infinitos 315 00:17:05,000 --> 00:17:08,000 quando envolvem recursão neste caso, uma função de chamada em si, 316 00:17:08,000 --> 00:17:10,000 o que acontece cada vez que você chamar uma função? 317 00:17:10,000 --> 00:17:13,000 Bem, acho que voltar a ser como que estabeleceu a memória de um computador. 318 00:17:13,000 --> 00:17:16,000 Nós dissemos que não há este pedaço de memória chamado de pilha que está no fundo, 319 00:17:16,000 --> 00:17:19,000 e cada vez que você chamar uma função de memória um pouco mais é colocado 320 00:17:19,000 --> 00:17:24,000 sobre esta pilha chamada contendo variáveis ​​locais que função ou parâmetros, 321 00:17:24,000 --> 00:17:27,000 por isso, se sigma Chamadas sigma sigma chama sigma 322 00:17:27,000 --> 00:17:29,000  chama sigma de onde vem essa história termina? 323 00:17:29,000 --> 00:17:31,000 >> Bem, ele acabou derrapagens o montante total 324 00:17:31,000 --> 00:17:33,000 de memória que você tem disponível para o seu computador. 325 00:17:33,000 --> 00:17:37,000 Você ultrapassou o segmento que você deveria ficar dentro, 326 00:17:37,000 --> 00:17:40,000 e você tem essa falha de segmentação, o núcleo despejado, 327 00:17:40,000 --> 00:17:43,000 e que do núcleo despejado significa é que agora eu tenho um arquivo chamado núcleo 328 00:17:43,000 --> 00:17:46,000 que é um arquivo contendo zeros e uns 329 00:17:46,000 --> 00:17:49,000 que, na verdade, no futuro, será útil para diagnóstico. 330 00:17:49,000 --> 00:17:52,000 Se não é óbvio para você, onde o bug é 331 00:17:52,000 --> 00:17:54,000 você pode realmente fazer um pouco de análise forense, por assim dizer, 332 00:17:54,000 --> 00:17:58,000 neste arquivo dump de memória, que, novamente, é apenas um monte de zeros e uns 333 00:17:58,000 --> 00:18:02,000 que, essencialmente, representa o estado de seu programa na memória 334 00:18:02,000 --> 00:18:05,000 no momento em que deixou de funcionar desta maneira. 335 00:18:05,000 --> 00:18:11,000 >> A correção aqui é que não podemos simplesmente voltar cegamente sigma, 336 00:18:11,000 --> 00:18:14,000 o número + sigma de um problema um pouco menor. 337 00:18:14,000 --> 00:18:16,000 Nós precisamos ter algum tipo de caso base aqui, 338 00:18:16,000 --> 00:18:19,000 e qual deve ser o caso base, provavelmente, ser? 339 00:18:19,000 --> 00:18:22,000 [Inaudível-aluno] 340 00:18:22,000 --> 00:18:25,000 Ok, desde que o número é positivo que deve realmente voltar isso, 341 00:18:25,000 --> 00:18:29,000 ou dito de outra forma, se o número é, digamos, <= a 0 342 00:18:29,000 --> 00:18:32,000 você sabe, eu vou em frente e retornar 0, 343 00:18:32,000 --> 00:18:36,000 bem como Willy fez, e mais, eu estou indo para a frente 344 00:18:36,000 --> 00:18:41,000 e devolver o presente, por isso não é muito menor do que 345 00:18:41,000 --> 00:18:44,000 do que a versão iterativa que instigou o primeiro a utilizar um loop for, 346 00:18:44,000 --> 00:18:48,000 de notar que há este tipo de elegância a ele. 347 00:18:48,000 --> 00:18:51,000 Em vez de retornar algum número e realizando toda a matemática esta 348 00:18:51,000 --> 00:18:54,000 e adicionando as coisas com as variáveis ​​locais 349 00:18:54,000 --> 00:18:57,000 você está em vez dizendo: "Ok, se este é um problema super fácil, 350 00:18:57,000 --> 00:19:01,000 como o número é <0, deixe-me imediatamente retornar 0. " 351 00:19:01,000 --> 00:19:03,000 >> Nós não vamos incomodar de apoio números negativos, 352 00:19:03,000 --> 00:19:05,000 então eu vou código rígido o valor de 0. 353 00:19:05,000 --> 00:19:08,000 Mas caso contrário, para implementar esta idéia de somar 354 00:19:08,000 --> 00:19:11,000 todos estes números juntos, você pode efetivamente dar uma pequena mordida 355 00:19:11,000 --> 00:19:14,000 fora do problema, assim como fizemos aqui no palco, 356 00:19:14,000 --> 00:19:18,000 então punt o resto do problema para a próxima pessoa, 357 00:19:18,000 --> 00:19:20,000 mas neste caso a pessoa próxima é a si mesmo. 358 00:19:20,000 --> 00:19:22,000 É uma função de nome idêntico. 359 00:19:22,000 --> 00:19:25,000 Apenas passar um problema cada vez menor e menor de cada vez, 360 00:19:25,000 --> 00:19:28,000 e mesmo que não temos coisas muito formalizados em código aqui 361 00:19:28,000 --> 00:19:33,000 isso é exatamente o que estava acontecendo na semana 0 com o livro de telefone. 362 00:19:33,000 --> 00:19:36,000 Este é exatamente o que estava acontecendo nas últimas semanas, com Sean 363 00:19:36,000 --> 00:19:39,000 e com as nossas demonstrações de busca de números. 364 00:19:39,000 --> 00:19:42,000 É tomar um problema e dividi-lo novamente e novamente. 365 00:19:42,000 --> 00:19:44,000 >> Em outras palavras, há uma maneira de traduzir agora 366 00:19:44,000 --> 00:19:47,000 esta construção mundo real, esta construção nível superior 367 00:19:47,000 --> 00:19:51,000 de dividir e conquistar e fazer algo de novo e de novo 368 00:19:51,000 --> 00:19:56,000 no código, então isso é algo que vamos ver novamente ao longo do tempo. 369 00:19:56,000 --> 00:20:00,000 Agora, como um aparte, se você é novo para a recursividade você deve pelo menos entender agora 370 00:20:00,000 --> 00:20:02,000 por que isso é engraçado. 371 00:20:02,000 --> 00:20:05,000 Eu estou indo para ir a google.com, 372 00:20:05,000 --> 00:20:17,000 e eu vou procurar algumas dicas e truques sobre recursão, entrar. 373 00:20:17,000 --> 00:20:21,000 Diga a pessoa ao seu lado, se eles não estavam rindo agora. 374 00:20:21,000 --> 00:20:23,000 Você quis dizer recursão? 375 00:20:23,000 --> 00:20:25,000 Queria dizer-ah, lá vamos nós. 376 00:20:25,000 --> 00:20:28,000 Ok, agora que está o resto de todos. 377 00:20:28,000 --> 00:20:30,000 Um ovo de Páscoa pequeno embutido em algum lugar lá no Google. 378 00:20:30,000 --> 00:20:33,000 Como um aparte, um dos links que colocamos no site do curso 379 00:20:33,000 --> 00:20:36,000 por hoje é só essa grade de vários algoritmos de ordenação, 380 00:20:36,000 --> 00:20:39,000 alguns dos quais nós olhamos na semana passada, mas o que é agradável sobre esta visualização 381 00:20:39,000 --> 00:20:43,000 como você tenta envolver sua mente em torno de várias coisas relacionadas a algoritmos 382 00:20:43,000 --> 00:20:46,000 saber que você pode muito facilmente agora começar com diferentes tipos de insumos. 383 00:20:46,000 --> 00:20:50,000 As entradas de todos invertidos, as entradas ordenadas na maior parte, as entradas aleatória e assim por diante. 384 00:20:50,000 --> 00:20:53,000 Como você tenta, mais uma vez, distinguir estas coisas em sua mente 385 00:20:53,000 --> 00:20:57,000 perceber que essa URL no site do curso na página de Palestras 386 00:20:57,000 --> 00:21:00,000 pode ajudá-lo a razão por meio de algum desses. 387 00:21:00,000 --> 00:21:05,000 >> Hoje nós finalmente começar a resolver este problema de um tempo atrás, 388 00:21:05,000 --> 00:21:08,000 o que foi que esta função swap simplesmente não funciona, 389 00:21:08,000 --> 00:21:12,000 e qual foi o problema fundamental com esta troca de função, 390 00:21:12,000 --> 00:21:15,000 cujo objetivo foi, novamente, para trocar um valor aqui e aqui 391 00:21:15,000 --> 00:21:17,000 de tal forma que isso acontece? 392 00:21:17,000 --> 00:21:20,000 Isso realmente não funciona. Por quê? 393 00:21:20,000 --> 00:21:22,000 Sim. 394 00:21:22,000 --> 00:21:28,000 [Inaudível-aluno] 395 00:21:28,000 --> 00:21:31,000 Exatamente, a explicação para este notam 396 00:21:31,000 --> 00:21:34,000 simplesmente foi porque quando você chamar funções em C 397 00:21:34,000 --> 00:21:38,000 e essas funções recebem argumentos, como a e b aqui, 398 00:21:38,000 --> 00:21:42,000 você está passando em cópias de qualquer valor que você está fornecendo a essa função. 399 00:21:42,000 --> 00:21:46,000 Você não está fornecendo os valores originais próprios, 400 00:21:46,000 --> 00:21:49,000 então vimos isso no contexto de buggyc, 401 00:21:49,000 --> 00:21:52,000 buggy3.c, que parecia um pouco algo como isto. 402 00:21:52,000 --> 00:21:57,000 >> Recorde-se que tínhamos x e y inicializado com 1 e 2, respectivamente. 403 00:21:57,000 --> 00:21:59,000 Em seguida, imprimiu o que eles eram. 404 00:21:59,000 --> 00:22:03,000 Eu, então, disse que eu estava trocando-os chamando troca de x, y. 405 00:22:03,000 --> 00:22:06,000 Mas o problema era que a troca funcionou, 406 00:22:06,000 --> 00:22:10,000 mas apenas no âmbito da permuta própria função. 407 00:22:10,000 --> 00:22:13,000 Assim que bateu linha 40 esses valores trocados 408 00:22:13,000 --> 00:22:16,000 foram jogados fora, e assim nada 409 00:22:16,000 --> 00:22:21,000 na função de principal original foi realmente mudou em tudo, 410 00:22:21,000 --> 00:22:26,000 por isso, se você acha que volta em seguida, como o que isso parece em termos de nossa memória 411 00:22:26,000 --> 00:22:29,000 se este lado esquerdo do conselho representa- 412 00:22:29,000 --> 00:22:33,000 e eu vou fazer o meu melhor para todo mundo ver esta-se esse lado esquerdo do conselho 413 00:22:33,000 --> 00:22:37,000 representa, por exemplo, a sua memória RAM, ea pilha vai crescer em cima dessa forma, 414 00:22:37,000 --> 00:22:43,000 e chamamos uma função como principal, e principal tem duas variáveis ​​locais, X e Y, 415 00:22:43,000 --> 00:22:48,000 vamos descrever aqueles que x aqui, e vamos descrever estes como y aqui, 416 00:22:48,000 --> 00:22:55,000 e vamos colocar em valores 1 e 2, de modo que este aqui é principal, 417 00:22:55,000 --> 00:22:58,000 e quando chama a principal função de troca do sistema operacional 418 00:22:58,000 --> 00:23:02,000 dá a função swap sua faixa própria de memória na pilha, 419 00:23:02,000 --> 00:23:04,000 seu próprio quadro na pilha, por assim dizer. 420 00:23:04,000 --> 00:23:08,000 Também aloca 32 bits para estes ints. 421 00:23:08,000 --> 00:23:11,000 Acontece a chamá-los a e b, mas isso é totalmente arbitrário. 422 00:23:11,000 --> 00:23:13,000 Poderia ter chamado o que quer, mas o que acontece quando principal 423 00:23:13,000 --> 00:23:19,000 troca de chamadas é que leva este 1, coloca uma cópia lá, coloca uma cópia lá. 424 00:23:19,000 --> 00:23:23,000 >> Há uma outra variável local em troca, porém, o que chamou? Tmp. >> 425 00:23:23,000 --> 00:23:27,000 Tmp, então deixe-me dar-me mais 32 bits aqui, 426 00:23:27,000 --> 00:23:29,000 eo que foi que eu fiz nesta função? 427 00:23:29,000 --> 00:23:34,000 Eu disse tmp int recebe um, então um tem um, então eu fiz isso quando jogou pela última vez com este exemplo. 428 00:23:34,000 --> 00:23:39,000 Então um fica b, então b é 2, e agora isso se torna 2, 429 00:23:39,000 --> 00:23:42,000 e agora b recebe temp, de modo temporário é 1, 430 00:23:42,000 --> 00:23:44,000 agora se torna presente b. 431 00:23:44,000 --> 00:23:46,000 Isso é ótimo. Funcionou. 432 00:23:46,000 --> 00:23:49,000 Mas então, logo que o retorno da função 433 00:23:49,000 --> 00:23:52,000 memória swap efectivamente desaparece de modo que ele pode ser reutilizado 434 00:23:52,000 --> 00:23:58,000 por alguma outra função no futuro, e principal é obviamente completamente inalterada. 435 00:23:58,000 --> 00:24:00,000 Precisamos de uma maneira de resolver este problema, fundamentalmente, 436 00:24:00,000 --> 00:24:03,000 e hoje nós vamos finalmente ter uma maneira de fazer isso através do qual 437 00:24:03,000 --> 00:24:06,000 podemos introduzir algo chamado um ponteiro. 438 00:24:06,000 --> 00:24:09,000 Acontece que podemos resolver este problema 439 00:24:09,000 --> 00:24:12,000 não passando em cópias de x e y 440 00:24:12,000 --> 00:24:18,000 mas em vez passando o que, você acha que, para a função de troca? 441 00:24:18,000 --> 00:24:20,000 Sim, o que o endereço? 442 00:24:20,000 --> 00:24:22,000 Nós realmente não temos falado sobre endereços em muitos detalhes, 443 00:24:22,000 --> 00:24:25,000 mas se este quadro representa a memória do meu computador 444 00:24:25,000 --> 00:24:28,000 certamente poderíamos iniciar a numeração dos bytes na minha memória RAM 445 00:24:28,000 --> 00:24:31,000 e dizer que isso é byte # 1, este é byte # 2, byte # 3, 446 00:24:31,000 --> 00:24:35,000 byte # 4, # byte ... 2000000000 se eu tiver 2 gigabytes de memória RAM, 447 00:24:35,000 --> 00:24:38,000 para que pudéssemos certamente chegar a algum esquema de numeração arbitrária 448 00:24:38,000 --> 00:24:41,000 para todos os bytes individuais na memória do meu computador. 449 00:24:41,000 --> 00:24:43,000 >> E se em vez quando eu chamo de swap 450 00:24:43,000 --> 00:24:47,000 em vez de passar em cópias de x e y 451 00:24:47,000 --> 00:24:51,000 por que não me vez passar o endereço de x aqui, 452 00:24:51,000 --> 00:24:55,000 o endereço de y aqui, essencialmente, o endereço postal 453 00:24:55,000 --> 00:24:59,000 de X e Y, porque então trocar, se ele está informado 454 00:24:59,000 --> 00:25:01,000 do endereço na memória de x e y, 455 00:25:01,000 --> 00:25:04,000 em seguida, trocar, se treinou um pouco, 456 00:25:04,000 --> 00:25:07,000 ele poderia potencialmente levar a esse endereço, por assim dizer, 457 00:25:07,000 --> 00:25:11,000 x, e alterar o número lá, então dirigir para o endereço de y, 458 00:25:11,000 --> 00:25:16,000 alterar o número de lá, mesmo se não estiver realmente recebendo cópias de si mesmo esses valores, 459 00:25:16,000 --> 00:25:19,000 por isso mesmo que nós conversamos sobre isso como memória principal 460 00:25:19,000 --> 00:25:23,000 e memória esta troca como sendo de poderosos e parte perigosa da C 461 00:25:23,000 --> 00:25:28,000 é que qualquer função pode tocar em qualquer parte da memória do computador, 462 00:25:28,000 --> 00:25:32,000 e este é poderoso em que você pode fazer coisas muito extravagantes com programas de computador em C. 463 00:25:32,000 --> 00:25:36,000 Isso é perigoso, porque você também pode estragar muito facilmente. 464 00:25:36,000 --> 00:25:39,000 Na verdade, uma das formas mais comuns para os programas estes dias a ser explorado 465 00:25:39,000 --> 00:25:42,000 ainda não é para um programador para realizar 466 00:25:42,000 --> 00:25:45,000 que ele ou ela está permitindo que um conjunto de dados 467 00:25:45,000 --> 00:25:49,000 a ser escrito em um local na memória que não se destinava. 468 00:25:49,000 --> 00:25:51,000 >> Por exemplo, ele ou ela declara uma matriz de tamanho 10 469 00:25:51,000 --> 00:25:56,000 mas então acidentalmente tenta colocar 11 bytes em que a matriz de memória, 470 00:25:56,000 --> 00:25:59,000 e você começar a tocar partes da memória que não são mais válidos. 471 00:25:59,000 --> 00:26:02,000 Só para contextual isso, alguns de vocês podem saber que 472 00:26:02,000 --> 00:26:06,000 software muitas vezes pede-lhe para números de série ou chaves de registro, 473 00:26:06,000 --> 00:26:08,000 Photoshop Word e e programas como este. 474 00:26:08,000 --> 00:26:12,000 Existem rachaduras, como alguns de vocês sabem, on-line onde você pode rodar um pequeno programa, 475 00:26:12,000 --> 00:26:14,000 e pronto, mais um pedido de número de série. 476 00:26:14,000 --> 00:26:16,000 Como é que funciona? 477 00:26:16,000 --> 00:26:21,000 Em muitos casos, essas coisas são simplesmente encontrar nos computadores 478 00:26:21,000 --> 00:26:24,000 segmentos de texto em zeros reais do computador e entes 479 00:26:24,000 --> 00:26:28,000 onde é que a função onde o número de série é solicitado, 480 00:26:28,000 --> 00:26:31,000 e você substituir esse espaço, ou enquanto o programa está sendo executado 481 00:26:31,000 --> 00:26:33,000 você pode descobrir onde a chave é armazenado 482 00:26:33,000 --> 00:26:37,000 usando algo chamado um depurador, e você pode quebrar maneira de software que. 483 00:26:37,000 --> 00:26:40,000 Isso não quer dizer que este é o nosso objetivo para o próximo par de dias, 484 00:26:40,000 --> 00:26:42,000 mas tem muito do mundo real ramificações. 485 00:26:42,000 --> 00:26:45,000 Isso acontece para envolver um roubo de software, 486 00:26:45,000 --> 00:26:47,000 mas há também comprometimento de máquinas inteiras. 487 00:26:47,000 --> 00:26:50,000 >> Na verdade, quando sites estes dias são exploradas 488 00:26:50,000 --> 00:26:53,000 e comprometida e os dados são vazou e senhas são roubados 489 00:26:53,000 --> 00:26:58,000 isso muitas vezes se refere à má gestão de sua memória, 490 00:26:58,000 --> 00:27:01,000 ou, no caso dos bancos de dados, a incapacidade de prever 491 00:27:01,000 --> 00:27:03,000 entrada de contraditório, de modo mais sobre isso nas próximas semanas, 492 00:27:03,000 --> 00:27:07,000 mas por agora apenas uma prévia do sneak de o tipo de dano que você pode fazer 493 00:27:07,000 --> 00:27:11,000 por não entender muito bem como funcionam as coisas debaixo do capô. 494 00:27:11,000 --> 00:27:14,000 Vamos sobre a compreensão de por que isso está quebrado 495 00:27:14,000 --> 00:27:17,000 com uma ferramenta que irá tornar-se cada vez mais útil 496 00:27:17,000 --> 00:27:19,000 como os nossos programas se tornam mais complexas. 497 00:27:19,000 --> 00:27:21,000 Até agora, quando você teve um bug em seu programa 498 00:27:21,000 --> 00:27:23,000 como você foi cerca de depurá-lo? 499 00:27:23,000 --> 00:27:25,000 O que suas técnicas sido, até agora, se ensinado por seu TF 500 00:27:25,000 --> 00:27:27,000 ou apenas autodidata? 501 00:27:27,000 --> 00:27:29,000 [Estudante] printf. 502 00:27:29,000 --> 00:27:31,000 Printf, assim printf provavelmente foi o seu amigo em que, se você quer ver 503 00:27:31,000 --> 00:27:33,000 o que está acontecendo dentro do seu programa 504 00:27:33,000 --> 00:27:36,000 você acabou de colocar printf aqui, printf aqui, printf aqui. 505 00:27:36,000 --> 00:27:38,000 Então você executá-lo, e você terá um monte de coisas na tela 506 00:27:38,000 --> 00:27:43,000 que você pode usar para, então, deduzir o que realmente está acontecendo de errado em seu programa. 507 00:27:43,000 --> 00:27:45,000 >> Printf tende a ser uma coisa muito poderosa, 508 00:27:45,000 --> 00:27:47,000 mas é um processo muito manual. 509 00:27:47,000 --> 00:27:49,000 Você tem que colocar um printf aqui, um printf aqui, 510 00:27:49,000 --> 00:27:51,000 e se você colocá-lo dentro de um loop que você pode obter de 100 linhas 511 00:27:51,000 --> 00:27:53,000 de saída que então você tem que peneirar. 512 00:27:53,000 --> 00:27:58,000 Não é um mecanismo muito user-friendly ou interativo para programas de depuração, 513 00:27:58,000 --> 00:28:00,000 mas felizmente existe alternativas. 514 00:28:00,000 --> 00:28:03,000 Há um programa, por exemplo, chamada GDB, o GNU Debugger, 515 00:28:03,000 --> 00:28:06,000 que é um arcano pouco em como usá-lo. 516 00:28:06,000 --> 00:28:08,000 É um pouco complexo, mas, francamente, 517 00:28:08,000 --> 00:28:11,000 esta é uma daquelas coisas que, se você colocar nesta semana e na próxima 518 00:28:11,000 --> 00:28:14,000 a hora extra para entender algo como GDB 519 00:28:14,000 --> 00:28:18,000 você vai economizar provavelmente dezenas de horas, a longo prazo, 520 00:28:18,000 --> 00:28:21,000 Então, com isso, deixe-me dar-lhe um teaser de como essa coisa funciona. 521 00:28:21,000 --> 00:28:23,000 >> Eu estou na minha janela de terminal. 522 00:28:23,000 --> 00:28:26,000 Deixe-me ir em frente e compilar este programa, buggy3. 523 00:28:26,000 --> 00:28:28,000 Já é até à data. 524 00:28:28,000 --> 00:28:31,000 Deixe-me executá-lo assim como fizemos um tempo atrás, e de fato, está quebrado. 525 00:28:31,000 --> 00:28:34,000 Mas por que isso? Talvez eu estraguei a função swap. 526 00:28:34,000 --> 00:28:37,000 Talvez seja a e b. Eu não estou muito movendo-os corretamente. 527 00:28:37,000 --> 00:28:39,000 Deixe-me ir em frente e fazer isso. 528 00:28:39,000 --> 00:28:43,000 Ao invés de apenas executar buggy3 deixe-me em vez de executar este programa GDB, 529 00:28:43,000 --> 00:28:48,000 e eu vou dizer a ele para executar buggy3, 530 00:28:48,000 --> 00:28:52,000 e eu vou incluir um argumento de linha de comando,-tui, 531 00:28:52,000 --> 00:28:55,000 e vamos colocar isso em problemas futuros em especificação para lembrar. 532 00:28:55,000 --> 00:28:57,000 E agora esta interface preto e branco apareceu que, novamente, 533 00:28:57,000 --> 00:28:59,000 é um pouco esmagadora na primeira porque não é tudo isso 534 00:28:59,000 --> 00:29:02,000 informações sobre a garantia aqui, mas pelo menos há algo familiar. 535 00:29:02,000 --> 00:29:04,000 Na parte superior da janela é o código real, 536 00:29:04,000 --> 00:29:08,000 e se eu rolar por aqui, deixe-me ir para o topo do meu arquivo, 537 00:29:08,000 --> 00:29:11,000 e, de fato, há buggy3.c e observe na parte inferior da janela 538 00:29:11,000 --> 00:29:13,000 Eu tenho esse aviso GDB. 539 00:29:13,000 --> 00:29:16,000 >> Este não é o mesmo que o meu normal, John Harvard prompt. 540 00:29:16,000 --> 00:29:19,000 Este é um aviso de que vai me permitir controlar GDB. 541 00:29:19,000 --> 00:29:21,000 GDB é um depurador. 542 00:29:21,000 --> 00:29:24,000 Um depurador é um programa que lhe permite percorrer 543 00:29:24,000 --> 00:29:27,000 execução de seu programa linha a linha por linha, 544 00:29:27,000 --> 00:29:30,000 ao longo do caminho fazendo o que quiser com o programa, 545 00:29:30,000 --> 00:29:33,000 mesmo chamar funções, ou à procura, mais importante, 546 00:29:33,000 --> 00:29:35,000 em valores de variáveis ​​vário. 547 00:29:35,000 --> 00:29:37,000 Vamos em frente e fazer isso. 548 00:29:37,000 --> 00:29:40,000 Eu estou indo para ir em frente e digitar run no prompt do GDB, 549 00:29:40,000 --> 00:29:43,000 Então, observe na parte inferior esquerda da tela eu digitei correr, 550 00:29:43,000 --> 00:29:45,000 e eu aperte enter, e que o que fazer? 551 00:29:45,000 --> 00:29:50,000 É, literalmente, correu meu programa, mas eu realmente não vejo muito continuar aqui 552 00:29:50,000 --> 00:29:55,000 porque eu realmente não tenho disse o depurador 553 00:29:55,000 --> 00:29:57,000 para fazer uma pausa em um determinado momento no tempo. 554 00:29:57,000 --> 00:29:59,000 Apenas digitando run executa o programa. 555 00:29:59,000 --> 00:30:01,000 Eu realmente não vejo nada. Eu não posso manipulá-lo. 556 00:30:01,000 --> 00:30:03,000 >> Em vez disso, deixe-me fazer isso. 557 00:30:03,000 --> 00:30:08,000 Neste prompt GDB deixe-me em vez tipo de quebra, entrar. 558 00:30:08,000 --> 00:30:10,000 Isso não é o que eu quis escrever. 559 00:30:10,000 --> 00:30:13,000 Vamos ao invés tipo de quebra principal. 560 00:30:13,000 --> 00:30:15,000 Em outras palavras, eu quero definir algo chamado um ponto de interrupção, 561 00:30:15,000 --> 00:30:18,000 que é apropriadamente chamado porque ele vai quebrar ou pausar 562 00:30:18,000 --> 00:30:21,000 execução de seu programa naquele determinado lugar. 563 00:30:21,000 --> 00:30:23,000 Principal é o nome da minha função. 564 00:30:23,000 --> 00:30:25,000 Observe que o GDB é muito inteligente. 565 00:30:25,000 --> 00:30:28,000 Ele descobriu que acontece principal para começar a aproximadamente na linha 18 566 00:30:28,000 --> 00:30:32,000 de buggy3.c, e depois observar aqui no canto superior esquerdo 567 00:30:32,000 --> 00:30:34,000 b + é bem próximo à linha 18. 568 00:30:34,000 --> 00:30:38,000 Isso está me lembrando que eu definir um ponto de interrupção na linha 18. 569 00:30:38,000 --> 00:30:42,000 Desta vez, quando eu digito corrida, eu vou executar o meu programa 570 00:30:42,000 --> 00:30:45,000 até que ela atinge ponto de interrupção, 571 00:30:45,000 --> 00:30:48,000 para que o programa fará uma pausa para mim na linha 18. 572 00:30:48,000 --> 00:30:50,000 Aqui vamos nós, correr. 573 00:30:50,000 --> 00:30:53,000 Nada parece ter acontecido, mas aviso no canto inferior esquerdo 574 00:30:53,000 --> 00:30:58,000 programa de partida, buggy3, ponto de interrupção em um principal no buggy3.c linha 18. 575 00:30:58,000 --> 00:31:00,000 O que posso fazer agora? 576 00:31:00,000 --> 00:31:03,000 >> Repare que eu possa começar a escrever coisas como impressão, 577 00:31:03,000 --> 00:31:08,000 Não printf, print x, e agora que é estranho. 578 00:31:08,000 --> 00:31:11,000 Os US $ 1 é apenas uma curiosidade, como veremos 579 00:31:11,000 --> 00:31:14,000 cada vez que você imprimir algo que você começa um novo valor R $. 580 00:31:14,000 --> 00:31:18,000 Isso é para que você possa se referir a valores anteriores para o caso, 581 00:31:18,000 --> 00:31:21,000 mas por agora o que está me dizendo impressão é que o valor de x, neste ponto da história 582 00:31:21,000 --> 00:31:26,000 é aparentemente 134514032. 583 00:31:26,000 --> 00:31:29,000 O quê? Onde foi que mesmo vem? 584 00:31:29,000 --> 00:31:31,000 [Inaudível-aluno] 585 00:31:31,000 --> 00:31:34,000 Na verdade, isso é o que vamos chamar um valor de lixo, e nós não falamos sobre isso ainda, 586 00:31:34,000 --> 00:31:37,000 mas a razão que você inicializar variáveis 587 00:31:37,000 --> 00:31:40,000 é, obviamente, para que eles tenham algum valor que você quer que eles tenham. 588 00:31:40,000 --> 00:31:44,000 Mas o problema é lembrar que você pode declarar variáveis 589 00:31:44,000 --> 00:31:46,000 como eu fiz há pouco no meu exemplo sigma 590 00:31:46,000 --> 00:31:48,000 sem realmente dando-lhes um valor. 591 00:31:48,000 --> 00:31:50,000 Lembre-se o que eu fiz aqui no sigma. 592 00:31:50,000 --> 00:31:52,000 Eu declarei n, mas o valor eu dar? 593 00:31:52,000 --> 00:31:56,000 Nenhum, porque eu sabia que nas próximas linhas 594 00:31:56,000 --> 00:31:59,000 GetInt iria cuidar do problema de colocar um valor dentro de n. 595 00:31:59,000 --> 00:32:02,000 >> Mas, neste ponto da história da linha 11 596 00:32:02,000 --> 00:32:05,000 e 12 de linha e linha 13 e linha 14 597 00:32:05,000 --> 00:32:08,000 ao longo dessas linhas de várias qual é o valor de n? 598 00:32:08,000 --> 00:32:10,000 Em C você simplesmente não sabe. 599 00:32:10,000 --> 00:32:14,000 É geralmente algum valor lixo, um número completamente aleatório 600 00:32:14,000 --> 00:32:17,000 que sobrou essencialmente de alguma função anterior 601 00:32:17,000 --> 00:32:21,000 tendo sido executado, assim como seu programa é executado 602 00:32:21,000 --> 00:32:24,000 lembrar que a função recebe, função, função. 603 00:32:24,000 --> 00:32:27,000 Todos esses quadros se colocar em memória, e depois aqueles retorno funções, 604 00:32:27,000 --> 00:32:31,000 e, assim como eu sugeri com a borracha a sua memória, eventualmente, é reutilizada. 605 00:32:31,000 --> 00:32:37,000 Bem, acontece que esta variável x neste programa 606 00:32:37,000 --> 00:32:41,000 parece ter contido algum valor lixo como 134514032 607 00:32:41,000 --> 00:32:44,000 de alguma função anterior, não um que eu escrevi. 608 00:32:44,000 --> 00:32:47,000 Poderia ser algo que vem de forma eficaz com o sistema operativo, 609 00:32:47,000 --> 00:32:49,000 alguma função debaixo do capô. 610 00:32:49,000 --> 00:32:52,000 >> Ok, tudo bem, mas vamos agora avançar para a próxima linha. 611 00:32:52,000 --> 00:32:55,000 Se eu digitar "next" no meu GDB pronta e eu bati entrar, 612 00:32:55,000 --> 00:32:58,000 notar que o realce move para baixo a linha 19, 613 00:32:58,000 --> 00:33:01,000 mas a implicação lógica é que a linha 18 614 00:33:01,000 --> 00:33:06,000 já terminou de executar, então se eu digitar novamente "print x" 615 00:33:06,000 --> 00:33:10,000 I deve ver agora uma, e na verdade, eu faço. 616 00:33:10,000 --> 00:33:14,000 Mais uma vez, as coisas $ é uma forma de lembrá-lo GDB 617 00:33:14,000 --> 00:33:17,000 o que a história de impressões são de que você fez. 618 00:33:17,000 --> 00:33:21,000 Agora deixe-me ir em frente e imprimir y, e, na verdade, y é um valor louco, bem como, 619 00:33:21,000 --> 00:33:24,000 mas não é grande coisa, porque na linha 19 que estamos prestes a atribuí-lo 620 00:33:24,000 --> 00:33:27,000 o valor 2, então deixe-me escrever "próximo" novamente. 621 00:33:27,000 --> 00:33:29,000 E agora estamos na linha printf. 622 00:33:29,000 --> 00:33:31,000 Deixe-me fazer x impressão. 623 00:33:31,000 --> 00:33:34,000 Deixe-me fazer y impressão. Francamente, estou ficando um pouco cansado de imprimir este. 624 00:33:34,000 --> 00:33:38,000 Deixe-me em vez tipo "display x" e "y exibição" 625 00:33:38,000 --> 00:33:41,000 e agora cada vez que eu digitar um comando no futuro 626 00:33:41,000 --> 00:33:45,000 Eu vou ser lembrado de que é x e y, o que é X e Y, o que é x e y. 627 00:33:45,000 --> 00:33:48,000 >> Eu também podem, como um aparte, digite "moradores de informação." 628 00:33:48,000 --> 00:33:50,000 Info é um comando especial. 629 00:33:50,000 --> 00:33:52,000 Moradores significa que ele me mostra as variáveis ​​locais. 630 00:33:52,000 --> 00:33:55,000 Apenas no caso de eu esquecer ou esta é uma função, louco complicado 631 00:33:55,000 --> 00:33:57,000 que eu ou alguém escreveu moradores informações vai dizer 632 00:33:57,000 --> 00:34:00,000 que são todas as variáveis ​​locais dentro desta função local 633 00:34:00,000 --> 00:34:03,000 que você pode preocupar se você quiser bisbilhotar. 634 00:34:03,000 --> 00:34:07,000 Agora, printf está prestes a executar, então deixe-me ir em frente e apenas um tipo "próximo". 635 00:34:07,000 --> 00:34:10,000 Porque nós somos neste ambiente não estamos realmente vendo isso 636 00:34:10,000 --> 00:34:14,000 executar aqui, mas percebe que está ficando um pouco mutilado aqui. 637 00:34:14,000 --> 00:34:17,000 Mas note que está substituindo o ecrã de lá, 638 00:34:17,000 --> 00:34:21,000 portanto, não é um programa perfeito aqui, mas tudo bem, porque eu sempre pode fuçar 639 00:34:21,000 --> 00:34:23,000 usando de impressão, se eu quiser. 640 00:34:23,000 --> 00:34:26,000 >> Deixe-me próximo tipo de novo, e agora aqui é a parte interessante. 641 00:34:26,000 --> 00:34:29,000 Neste ponto na história y é 2, e x é 1, 642 00:34:29,000 --> 00:34:32,000 como aqui sugerido, e de novo, 643 00:34:32,000 --> 00:34:35,000 A razão é automaticamente exibir agora é porque eu usei o comando 644 00:34:35,000 --> 00:34:40,000 display x e y de exibição, então o momento próximo digito 645 00:34:40,000 --> 00:34:43,000 na teoria X e Y devem ser trocados. 646 00:34:43,000 --> 00:34:45,000 Agora, já sabemos que não vai ser o caso, 647 00:34:45,000 --> 00:34:49,000 mas vamos ver em um momento como podemos mergulhar mais fundo para descobrir por que isso é verdade. 648 00:34:49,000 --> 00:34:54,000 Em seguida, e, infelizmente, ainda é y 2 e x ainda é um, e posso confirmar tanto. 649 00:34:54,000 --> 00:34:56,000 Print x, y de impressão. 650 00:34:56,000 --> 00:34:59,000 Na verdade, nenhuma troca que realmente aconteceu, então vamos recomeçar isso. 651 00:34:59,000 --> 00:35:01,000 Claramente swap é quebrado. 652 00:35:01,000 --> 00:35:04,000 Vamos em vez digite "Executar" novamente. 653 00:35:04,000 --> 00:35:07,000 Deixe-me dizer que sim, que eu quero para reiniciá-lo desde o início, entrar. 654 00:35:07,000 --> 00:35:09,000 >> Agora estou de volta para a linha 18. 655 00:35:09,000 --> 00:35:11,000 Agora notar x e y são os valores de lixo novo. 656 00:35:11,000 --> 00:35:15,000 Next, next, next, next. 657 00:35:15,000 --> 00:35:17,000 Se eu ficar entediado eu também pode simplesmente digitar n para a próxima. 658 00:35:17,000 --> 00:35:21,000 Você pode abreviar-lo para o mais curto possível seqüência de caracteres. 659 00:35:21,000 --> 00:35:23,000 Swap é agora quebrado. 660 00:35:23,000 --> 00:35:25,000 Vamos mergulhar, então ao invés de digitar seguinte, 661 00:35:25,000 --> 00:35:30,000 agora eu vou escrever passo para que eu estou pisando dentro desta função 662 00:35:30,000 --> 00:35:33,000 para que eu possa atravessá-la, então eu acertar passo e depois entrar. 663 00:35:33,000 --> 00:35:37,000 Repare que os saltos destacando mais para baixo no meu programa para a linha 36. 664 00:35:37,000 --> 00:35:39,000 Agora, quais são as variáveis ​​locais? 665 00:35:39,000 --> 00:35:41,000 Informações locais. 666 00:35:41,000 --> 00:35:43,000 Nada apenas porque ainda não tenha chegado a essa linha, 667 00:35:43,000 --> 00:35:47,000 então vamos em frente e dizer "próximo". 668 00:35:47,000 --> 00:35:50,000 Agora parece que temos tmp tmp impressão. 669 00:35:50,000 --> 00:35:52,000 Valor de lixo, certo? Acho que sim. 670 00:35:52,000 --> 00:35:55,000 Que tal imprimir uma, imprimir b, 1 e 2? 671 00:35:55,000 --> 00:35:58,000 Em um momento, assim como eu escreva seguinte novamente 672 00:35:58,000 --> 00:36:02,000 tmp vai assumir um valor de 1, espera-se, 673 00:36:02,000 --> 00:36:05,000 tmp porque vai ser atribuído o valor de um. 674 00:36:05,000 --> 00:36:08,000 >> Agora vamos fazer imprimir a, b de impressão, 675 00:36:08,000 --> 00:36:11,000 mas agora imprimir tmp, e é de fato um. 676 00:36:11,000 --> 00:36:14,000 Deixe-me fazer a seguir. Deixe-me fazer a seguir. 677 00:36:14,000 --> 00:36:16,000 Eu terminei a função swap. 678 00:36:16,000 --> 00:36:19,000 Eu ainda estou dentro dela na linha 40, então deixe-me imprimir um, 679 00:36:19,000 --> 00:36:22,000 b impressão, e eu não me importo com o tmp é. 680 00:36:22,000 --> 00:36:27,000 Parece que swap é correto quando se trata de trocar a e b. 681 00:36:27,000 --> 00:36:31,000 Mas se eu agora digitar seguinte, eu pular de volta para a linha 25, 682 00:36:31,000 --> 00:36:34,000 e, claro, se eu digitar x e y de impressão 683 00:36:34,000 --> 00:36:38,000 eles ainda estão inalterados, por isso não ter corrigido o problema. 684 00:36:38,000 --> 00:36:41,000 Mas agora talvez diagnóstico com este programa GDB 685 00:36:41,000 --> 00:36:44,000 temos, pelo menos, ficou um passo mais perto de compreender 686 00:36:44,000 --> 00:36:47,000 o que está acontecendo de errado sem ter que lixo nosso código, colocando um printf aqui, 687 00:36:47,000 --> 00:36:50,000 printf aqui, printf aqui e depois executá-lo novamente e novamente 688 00:36:50,000 --> 00:36:52,000 tentando descobrir o que está acontecendo de errado. 689 00:36:52,000 --> 00:36:55,000 >> Eu estou indo para ir em frente e sair fora deste conjunto com saia. 690 00:36:55,000 --> 00:36:57,000 Vai então dizer: "Sair mesmo assim?" Sim. 691 00:36:57,000 --> 00:37:00,000 Agora estou de volta ao meu prompt normal, e eu estou feito usando GDB. 692 00:37:00,000 --> 00:37:03,000 Como um aparte, você não precisa usar este tui-bandeira. 693 00:37:03,000 --> 00:37:07,000 Na verdade, se você omiti-lo você tem, essencialmente, a metade inferior da tela. 694 00:37:07,000 --> 00:37:11,000 Se eu digite intervalo principal e execute 695 00:37:11,000 --> 00:37:15,000 Ainda posso correr o meu programa, mas o que ele vai fazer é mais textualmente 696 00:37:15,000 --> 00:37:18,000 apenas mostrar-me a uma corrente de linha de cada vez. 697 00:37:18,000 --> 00:37:21,000 O tui-, interface de usuário textual, 698 00:37:21,000 --> 00:37:25,000 apenas mostra mais do programa de uma só vez, o que é provavelmente um pouco conceitualmente mais fácil. 699 00:37:25,000 --> 00:37:27,000 Mas, na verdade, eu só posso fazer em seguida, avançar, avançar, 700 00:37:27,000 --> 00:37:30,000 e eu vou ver uma linha de cada vez, e se eu realmente quero ver o que está acontecendo 701 00:37:30,000 --> 00:37:35,000 Eu posso tipo de lista e ver um monte de linhas vizinhas. 702 00:37:35,000 --> 00:37:39,000 >> Há um vídeo que pedimos que você vê para o problema define três 703 00:37:39,000 --> 00:37:43,000 em que Nate abrange alguns dos meandros do GDB, 704 00:37:43,000 --> 00:37:46,000 e esta é uma daquelas coisas que, sinceramente, onde alguns dos não-trivial de você 705 00:37:46,000 --> 00:37:49,000 nunca vai tocar GDB, e que vai ser uma coisa ruim 706 00:37:49,000 --> 00:37:53,000 porque literalmente você vai acabar gastando mais tempo ainda este semestre 707 00:37:53,000 --> 00:37:56,000 perseguir erros então você teria se você colocar em que meia hora / hora 708 00:37:56,000 --> 00:38:00,000 esta semana e aprendizagem seguinte para se sentir confortável com o GDB. 709 00:38:00,000 --> 00:38:02,000 Printf era seu amigo. 710 00:38:02,000 --> 00:38:05,000 GDB deve agora ser seu amigo. 711 00:38:05,000 --> 00:38:08,000 >> Qualquer dúvida sobre o GDB? 712 00:38:08,000 --> 00:38:12,000 E aqui está uma breve lista de alguns dos comandos mais poderosas e úteis. 713 00:38:12,000 --> 00:38:15,000 Sim. >> É possível imprimir uma string? 714 00:38:15,000 --> 00:38:17,000 É possível imprimir uma string? Absolutamente. 715 00:38:17,000 --> 00:38:19,000 Ele não tem que ser apenas números inteiros. 716 00:38:19,000 --> 00:38:22,000 Se uma variável s é uma seqüência de apenas um tipo de s de impressão. 717 00:38:22,000 --> 00:38:24,000 Ela vai mostrar o que é variável de cadeia. 718 00:38:24,000 --> 00:38:26,000 [Inaudível-aluno] 719 00:38:26,000 --> 00:38:28,000 Ele vai te dar o endereço eo string. 720 00:38:28,000 --> 00:38:32,000 Ela vai mostrar tanto. 721 00:38:32,000 --> 00:38:34,000 E uma última coisa, só porque estes são bom saber também. 722 00:38:34,000 --> 00:38:37,000 Backtrace e armação, deixe-me mergulhar em uma última vez, 723 00:38:37,000 --> 00:38:39,000 programa exatamente o mesmo com o GDB. 724 00:38:39,000 --> 00:38:44,000 Deixe-me ir em frente e correr a versão de interface de usuário textual, 725 00:38:44,000 --> 00:38:46,000 quebrar principal. 726 00:38:46,000 --> 00:38:49,000 Deixe-me ir em frente e correr novamente. Aqui estou. 727 00:38:49,000 --> 00:38:55,000 Agora deixe-me ir em seguida, next, next, next, next, passo, entrar. 728 00:38:55,000 --> 00:39:00,000 >> E agora acho que eu sou agora, em troca de propósito, mas eu sou assim "Porra, qual foi o valor de x?" 729 00:39:00,000 --> 00:39:02,000 Eu não posso fazer mais x. 730 00:39:02,000 --> 00:39:05,000 Eu não posso fazer y porque eles não estão no escopo. 731 00:39:05,000 --> 00:39:07,000 Eles não estão no contexto, mas não há problema. 732 00:39:07,000 --> 00:39:09,000 Eu posso digitar backtrace. 733 00:39:09,000 --> 00:39:13,000 Que me mostra todas as funções que tenham firmado até este momento. 734 00:39:13,000 --> 00:39:16,000 Observe que o um na parte inferior, principal, alinha com principal 735 00:39:16,000 --> 00:39:18,000 estar no fundo da nossa imagem aqui. 736 00:39:18,000 --> 00:39:22,000 O fato de que acima de swap é que seja alinhado com swap estar acima dele na memória aqui, 737 00:39:22,000 --> 00:39:26,000 e se eu quiser voltar ao principal temporariamente posso dizer "frame". 738 00:39:26,000 --> 00:39:30,000 Qual o número? Principal é o quadro # 1. 739 00:39:30,000 --> 00:39:32,000 Eu estou indo para ir em frente e dizer "1 quadro". 740 00:39:32,000 --> 00:39:36,000 >> Agora estou de volta na principal, e eu posso imprimir x, e eu posso imprimir y, 741 00:39:36,000 --> 00:39:40,000 mas eu não posso imprimir a ou b. 742 00:39:40,000 --> 00:39:43,000 Mas eu posso, se eu digo: "Ok, espere um minuto. Onde estava o swap?" 743 00:39:43,000 --> 00:39:46,000 Deixe-me ir em frente e dizer "0 quadro." 744 00:39:46,000 --> 00:39:48,000 Agora estou de volta onde eu quero ser, e como um aparte, 745 00:39:48,000 --> 00:39:52,000 há também outros comandos, como se você está realmente ficando entediado digitação next, next, next, next, 746 00:39:52,000 --> 00:39:56,000 geralmente você pode dizer coisas como "10 next", e que irá percorrer os próximos 10 linhas. 747 00:39:56,000 --> 00:39:59,000 Você também pode escrever "continuar" quando você realmente se alimentado com a depuração através dela. 748 00:39:59,000 --> 00:40:05,000 Continuar irá executar o programa sem interrupção até atingir outro ponto de interrupção, 749 00:40:05,000 --> 00:40:07,000 se em um loop ou mais abaixo em seu programa. 750 00:40:07,000 --> 00:40:11,000 >> Neste caso, continuou até o fim, eo programa saiu normalmente. 751 00:40:11,000 --> 00:40:13,000 Esta é uma maneira extravagante, processo inferior. 752 00:40:13,000 --> 00:40:16,000 Apenas seu programa saiu normalmente. 753 00:40:16,000 --> 00:40:24,000 Mais sobre isso no vídeo e em sessões de depuração para vir. 754 00:40:24,000 --> 00:40:26,000 Isso foi muito. 755 00:40:26,000 --> 00:40:35,000 Vamos dar o nosso intervalo de 5 minutos aqui, e nós vamos voltar com structs e ficheiros. 756 00:40:35,000 --> 00:40:38,000 >> Se você mergulhou pset desta semana já 757 00:40:38,000 --> 00:40:41,000 você sabe que nós usamos no código de distribuição, 758 00:40:41,000 --> 00:40:45,000 o código-fonte que oferecemos a você como um ponto de partida, algumas técnicas novas. 759 00:40:45,000 --> 00:40:50,000 Em particular, introduziu esta nova palavra-chave chamada struct, para a estrutura, 760 00:40:50,000 --> 00:40:53,000 para que possamos criar variáveis ​​personalizadas de sortes. 761 00:40:53,000 --> 00:40:57,000 Nós também introduziu a noção de arquivo de entrada de arquivo I / O, e de saída, 762 00:40:57,000 --> 00:41:00,000 e isto é para que possamos salvar o estado 763 00:41:00,000 --> 00:41:03,000 de sua placa Scramble para um arquivo em disco 764 00:41:03,000 --> 00:41:06,000 para que os companheiros de ensino e posso entender 765 00:41:06,000 --> 00:41:09,000 o que está acontecendo dentro do seu programa sem ter que manualmente jogar 766 00:41:09,000 --> 00:41:11,000 dezenas de jogos de corrida. 767 00:41:11,000 --> 00:41:13,000 Podemos fazer isso mais automatedly. 768 00:41:13,000 --> 00:41:18,000 >> Essa idéia de uma estrutura resolve um problema bastante convincente. 769 00:41:18,000 --> 00:41:21,000 Suponha que queremos implementar algum programa 770 00:41:21,000 --> 00:41:25,000 que de alguma forma mantém o controle das informações sobre os alunos, 771 00:41:25,000 --> 00:41:28,000 e os alunos podem ter, por exemplo, um ID, um nome 772 00:41:28,000 --> 00:41:31,000 e uma casa em um lugar como Harvard, assim que estes são três peças de informação 773 00:41:31,000 --> 00:41:34,000 queremos manter ao redor, então deixe-me ir em frente e começar a escrever um pequeno programa aqui, 774 00:41:34,000 --> 00:41:38,000 incluir stdio.h. 775 00:41:38,000 --> 00:41:42,000 Deixe-me fazer incluem cs50.h. 776 00:41:42,000 --> 00:41:44,000 E então começar a minha função principal. 777 00:41:44,000 --> 00:41:46,000 Eu não vou preocupar com quaisquer argumentos de linha de comando, 778 00:41:46,000 --> 00:41:49,000 e aqui eu quero ter um estudante, então eu vou dizer 779 00:41:49,000 --> 00:41:54,000 um aluno tem um nome, então eu vou dizer "nome de cadeia." 780 00:41:54,000 --> 00:41:59,000 Então eu vou dizer uma estudante também tem um ID, ID para int, 781 00:41:59,000 --> 00:42:03,000 e um aluno tem uma casa, então eu também vou dizer "casa corda". 782 00:42:03,000 --> 00:42:06,000 Então eu vou pedir um pouco esses mais limpa como este. 783 00:42:06,000 --> 00:42:11,000 Ok, agora eu tenho três variáveis ​​com que representam um estudante, portanto, "um estudante." 784 00:42:11,000 --> 00:42:15,000 >> E agora eu quero para preencher esses valores, então deixe-me ir em frente e dizer algo como 785 00:42:15,000 --> 00:42:18,000 "ID = 123". 786 00:42:18,000 --> 00:42:21,000 Nome vai ficar David. 787 00:42:21,000 --> 00:42:24,000 Digamos casa vai ficar Mather, 788 00:42:24,000 --> 00:42:31,000 e então eu vou fazer algo arbitrariamente como printf ("% s, 789 00:42:31,000 --> 00:42:37,000 cuja identificação é% d, vive em% s. 790 00:42:37,000 --> 00:42:41,000 E agora, o que eu quero ligar aqui, um após o outro? 791 00:42:41,000 --> 00:42:47,000 Nome, ID de casa,; retorno 0. 792 00:42:47,000 --> 00:42:50,000 Ok, a menos que eu estraguei tudo em algum lugar aqui 793 00:42:50,000 --> 00:42:54,000 Eu acho que nós temos um programa muito bom, que armazena um estudante. 794 00:42:54,000 --> 00:42:57,000 É claro que isso não é tudo o que interessante. E se eu quiser ter dois alunos? 795 00:42:57,000 --> 00:42:59,000 Isso não é grande coisa. Eu posso suportar 2 pessoas. 796 00:42:59,000 --> 00:43:03,000 Deixe-me ir em frente e destacar isso e ir até aqui, 797 00:43:03,000 --> 00:43:09,000 e posso dizer "id = 456" para alguém como Rob que mora em Kirkland. 798 00:43:09,000 --> 00:43:12,000 >> Ok, espere, mas não posso chamá-los a mesma coisa, 799 00:43:12,000 --> 00:43:15,000 e parece que vou ter que copiar isso, 800 00:43:15,000 --> 00:43:19,000 então deixe-me dizer que estas serão as variáveis ​​de Davi, 801 00:43:19,000 --> 00:43:23,000 e deixe-me algumas cópias destes para o Rob. 802 00:43:23,000 --> 00:43:27,000 Vamos chamar essas Rob, mas isso não vai funcionar agora 803 00:43:27,000 --> 00:43:33,000 porque eu, espere, vamos mudar-me para id1, name1 e house1. 804 00:43:33,000 --> 00:43:35,000 Rob será de 2, 2. 805 00:43:35,000 --> 00:43:42,000 Eu tenho que mudar isso aqui, aqui, aqui, aqui, aqui, aqui. 806 00:43:42,000 --> 00:43:45,000 Espere, o que acontece com Tommy? Vamos fazer isso de novo. 807 00:43:45,000 --> 00:43:49,000 Obviamente, se você ainda acha que isso é uma boa maneira de fazer isso, não é, 808 00:43:49,000 --> 00:43:52,000 para copiar / colar ruim. 809 00:43:52,000 --> 00:43:55,000 Mas nós resolvemos isso há uma semana. 810 00:43:55,000 --> 00:43:59,000 >> Qual foi a nossa solução, quando queria ter várias instâncias do mesmo tipo de dados? 811 00:43:59,000 --> 00:44:01,000 [Os alunos] Uma matriz. 812 00:44:01,000 --> 00:44:03,000 Uma matriz, então deixe-me tentar limpar isso. 813 00:44:03,000 --> 00:44:07,000 Deixe-me fazer algumas para mim mesmo no topo, e deixe-me em vez fazer isso aqui. 814 00:44:07,000 --> 00:44:12,000 Vamos chamar essas pessoas, e ao invés disso eu vou dizer "ids int", 815 00:44:12,000 --> 00:44:14,000 e eu estou indo para suportar 3 de nós agora. 816 00:44:14,000 --> 00:44:18,000 Eu vou dizer "nomes de cadeia", e eu vou apoiá-3 de nós, 817 00:44:18,000 --> 00:44:22,000 e então eu vou dizer "casas seqüência," e eu vou apoiar a 3. 818 00:44:22,000 --> 00:44:26,000 Agora aqui em lugar de Davi recebendo suas próprias variáveis ​​locais 819 00:44:26,000 --> 00:44:28,000 podemos nos livrar deles. 820 00:44:28,000 --> 00:44:30,000 Isso é bom que estamos limpar isso. 821 00:44:30,000 --> 00:44:35,000 Posso, então, dizer que David vai ser [0] e nomes [0] 822 00:44:35,000 --> 00:44:38,000 e casas [0]. 823 00:44:38,000 --> 00:44:41,000 E, em seguida, Rob podemos igualmente economizar no presente. 824 00:44:41,000 --> 00:44:46,000 Vamos colocar isso aqui, então ele vai ser arbitrariamente ids [1]. 825 00:44:46,000 --> 00:44:50,000 Ele vai ser nomes [1], 826 00:44:50,000 --> 00:44:53,000 e, em seguida, finalmente, casas [1]. 827 00:44:53,000 --> 00:44:57,000 >> Ainda um pouco entediante, e agora eu tenho que descobrir isso, 828 00:44:57,000 --> 00:45:03,000 então vamos dizer "nomes [0], id [0], casas [0], 829 00:45:03,000 --> 00:45:06,000 e vamos pluralizar isso. 830 00:45:06,000 --> 00:45:09,000 Ids, ids, ids. 831 00:45:09,000 --> 00:45:12,000 E novamente, eu estou fazendo isso, por isso novamente, eu já estou recorrendo para copiar / colar de novo, 832 00:45:12,000 --> 00:45:14,000 assim as probabilidades são de que há uma outra solução aqui. 833 00:45:14,000 --> 00:45:18,000 Eu provavelmente pode limpar isso ainda mais com um laço ou algo assim, 834 00:45:18,000 --> 00:45:21,000 Então, em suma, é um pouco melhor, mas ainda se sente como 835 00:45:21,000 --> 00:45:24,000 Estou recorrendo para copiar / colar, mas mesmo isso, eu afirmo, 836 00:45:24,000 --> 00:45:27,000 não é realmente a solução certa fundamentalmente porque 837 00:45:27,000 --> 00:45:29,000 E se algum dia decidirmos que você sabe o que? 838 00:45:29,000 --> 00:45:32,000 Realmente deve ter sido armazenar endereços de e-mail para David e Rob 839 00:45:32,000 --> 00:45:34,000 e todos os outros neste programa. 840 00:45:34,000 --> 00:45:36,000 Devemos também armazenar números de telefone. 841 00:45:36,000 --> 00:45:39,000 Devemos também armazenar números de contato de emergência. 842 00:45:39,000 --> 00:45:41,000 Nós temos todas essas peças de dados que deseja armazenar, 843 00:45:41,000 --> 00:45:43,000 então como você vai fazer sobre isso? 844 00:45:43,000 --> 00:45:46,000 >> Você declara uma outra matriz, na parte superior, e então você adicionar manualmente 845 00:45:46,000 --> 00:45:49,000 um endereço de e-mail [0] endereço, e-mail [1] 846 00:45:49,000 --> 00:45:51,000 para David e Rob e assim por diante. 847 00:45:51,000 --> 00:45:56,000 Mas há realmente apenas uma suposição subjacente a este projeto 848 00:45:56,000 --> 00:45:59,000 que eu estou usando o sistema de honra saber que 849 00:45:59,000 --> 00:46:03,000 [I] em cada um dos vários arrays 850 00:46:03,000 --> 00:46:06,000 Acontece para se referir à mesma pessoa, 851 00:46:06,000 --> 00:46:10,000 assim [0] no IDS é o número 123, 852 00:46:10,000 --> 00:46:13,000 e eu vou assumir que os nomes [0] 853 00:46:13,000 --> 00:46:16,000 é o nome da mesma pessoa e casas [0] 854 00:46:16,000 --> 00:46:21,000 é casa da mesma pessoa e assim por diante para todas as matrizes diferentes que crio. 855 00:46:21,000 --> 00:46:24,000 Mas note que não há nenhuma ligação fundamentais 856 00:46:24,000 --> 00:46:27,000 entre essas três peças de informação, identificação, nome e casa, 857 00:46:27,000 --> 00:46:32,000 mesmo que a entidade que estamos tentando modelo neste programa não é matrizes. 858 00:46:32,000 --> 00:46:35,000 Matrizes são exatamente dessa forma programática de fazer isso. 859 00:46:35,000 --> 00:46:38,000 O que realmente queremos para modelar em nosso programa é uma pessoa 860 00:46:38,000 --> 00:46:41,000 como Davi, uma pessoa como Rob dentro do qual 861 00:46:41,000 --> 00:46:46,000 ou encapsulamento é um nome e ID e uma casa. 862 00:46:46,000 --> 00:46:49,000 >> Será que podemos expressar essa idéia de encapsulamento 863 00:46:49,000 --> 00:46:52,000 pelo qual uma pessoa tem um ID, um nome e uma casa 864 00:46:52,000 --> 00:46:55,000 e não recorrer a este truque realmente qual nós apenas 865 00:46:55,000 --> 00:46:58,000 confiar que algo suporte 866 00:46:58,000 --> 00:47:02,000 refere-se a uma mesma pessoa humana em cada uma dessas matrizes diferentes? 867 00:47:02,000 --> 00:47:04,000 Nós podemos realmente fazer isso. 868 00:47:04,000 --> 00:47:08,000 Deixe-me ir acima principal para agora, e deixe-me criar o meu próprio tipo de dados 869 00:47:08,000 --> 00:47:10,000 para realmente pela primeira vez. 870 00:47:10,000 --> 00:47:14,000 Usamos esta técnica em Scramble, 871 00:47:14,000 --> 00:47:17,000 mas aqui eu estou indo para ir em frente e criar um tipo de dados, 872 00:47:17,000 --> 00:47:19,000 e você sabe, eu vou chamá-lo de estudante ou pessoa, 873 00:47:19,000 --> 00:47:23,000 e eu vou usar typedef para definir um tipo. 874 00:47:23,000 --> 00:47:25,000 Eu vou dizer que esta é uma estrutura, 875 00:47:25,000 --> 00:47:29,000 e então esta estrutura vai ser de estudante tipo, vamos dizer, 876 00:47:29,000 --> 00:47:31,000 mesmo que seja um pouco datado agora para mim. 877 00:47:31,000 --> 00:47:33,000 Nós vamos dizer "int id". 878 00:47:33,000 --> 00:47:35,000 Nós vamos dizer "nome de cadeia." 879 00:47:35,000 --> 00:47:37,000 Então, vamos dizer "casa corda", 880 00:47:37,000 --> 00:47:40,000 agora até o final de estas poucas linhas de código 881 00:47:40,000 --> 00:47:45,000 Acabo ensinou bumbum que não existe 882 00:47:45,000 --> 00:47:49,000 um tipo de dados além de ints, além de cordas, além de duplas, além de carros alegóricos. 883 00:47:49,000 --> 00:47:54,000 >> A partir deste momento, em vez da linha 11, existe agora um novo tipo de dados chamado estudantes, 884 00:47:54,000 --> 00:47:58,000 e agora eu posso declarar uma variável aluno em qualquer lugar que eu quero, 885 00:47:58,000 --> 00:48:01,000 então deixe-me ir até aqui para as pessoas. 886 00:48:01,000 --> 00:48:05,000 Agora eu posso me livrar disso, e eu posso ir de volta para David aqui, 887 00:48:05,000 --> 00:48:10,000 e para David eu posso realmente dizer que David, 888 00:48:10,000 --> 00:48:13,000 podemos literalmente nomear a variável depois de mim, 889 00:48:13,000 --> 00:48:16,000 vai ser de estudante tipo. 890 00:48:16,000 --> 00:48:18,000 Isso pode parecer um pouco estranho, mas isto não é assim tão diferente 891 00:48:18,000 --> 00:48:22,000 de declarar algo como um int ou uma string ou uma bóia. 892 00:48:22,000 --> 00:48:24,000 Isso só acontece a ser chamado de estudante, 893 00:48:24,000 --> 00:48:28,000 e se eu quiser colocar algo dentro desta estrutura 894 00:48:28,000 --> 00:48:31,000 Eu agora tenho que usar uma nova peça de sintaxe, mas é bastante simples, 895 00:48:31,000 --> 00:48:39,000 david.id = 123, david.name = "David" na capital D, 896 00:48:39,000 --> 00:48:42,000 e david.house = "Mather," 897 00:48:42,000 --> 00:48:46,000 e agora eu posso me livrar dessas coisas aqui. 898 00:48:46,000 --> 00:48:51,000 Repare que temos agora redesenhado nosso programa em realmente uma maneira muito melhor 899 00:48:51,000 --> 00:48:54,000 em que agora o nosso programa espelha o mundo real. 900 00:48:54,000 --> 00:48:57,000 >> Há uma noção do mundo real de uma pessoa ou um estudante. 901 00:48:57,000 --> 00:49:02,000 Aqui nós temos agora uma versão C de uma pessoa ou, mais especificamente, um estudante. 902 00:49:02,000 --> 00:49:05,000 Dentro dessa pessoa são essas características relevantes, 903 00:49:05,000 --> 00:49:10,000 ID, nome e casa, por isso Rob torna-se essencialmente a mesma coisa aqui, 904 00:49:10,000 --> 00:49:14,000 então estudante Rob, e agora rob.id = 456, 905 00:49:14,000 --> 00:49:17,000 rob.name = "Rob". 906 00:49:17,000 --> 00:49:20,000 O fato de que a variável é chamado Rob é uma espécie de sentido. 907 00:49:20,000 --> 00:49:22,000 Poderíamos ter chamado x ou y ou z. 908 00:49:22,000 --> 00:49:25,000 Nós só nomeou Rob para ser semanticamente consistente, 909 00:49:25,000 --> 00:49:28,000 mas realmente o nome está dentro do próprio campo, 910 00:49:28,000 --> 00:49:30,000 então agora eu tenho isso. 911 00:49:30,000 --> 00:49:33,000 Isso também não se sente como o melhor projeto em que eu codificado David. 912 00:49:33,000 --> 00:49:35,000 Eu codificado Rob. 913 00:49:35,000 --> 00:49:39,000 E eu ainda tenho que recorrer a algum copiar e colar cada vez que eu quero novas variáveis. 914 00:49:39,000 --> 00:49:43,000 Além disso, eu tenho que dar, aparentemente, cada uma dessas variáveis ​​de um nome, 915 00:49:43,000 --> 00:49:46,000 mesmo que eu prefiro descrever essas variáveis 916 00:49:46,000 --> 00:49:48,000  alunos mais genericamente como. 917 00:49:48,000 --> 00:49:52,000 >> Agora podemos mesclar as ideias que têm vindo a trabalhar bem para nós 918 00:49:52,000 --> 00:49:56,000 e, em vez dizer: "Você sabe o que, dá-me um estudantes variável chamada, 919 00:49:56,000 --> 00:50:01,000 e vamos ter que ser de tamanho 3 ", então agora eu posso refinar este ainda mais, 920 00:50:01,000 --> 00:50:04,000 livrar-se do David manualmente declarou, 921 00:50:04,000 --> 00:50:08,000 e eu posso dizer alguma coisa em vez como estudantes [0] aqui. 922 00:50:08,000 --> 00:50:11,000 Posso, então, dizer que os alunos [0] aqui, 923 00:50:11,000 --> 00:50:14,000 alunos [0] aqui, e assim por diante, e eu posso sair por aí 924 00:50:14,000 --> 00:50:16,000 e limpar isso para Rob. 925 00:50:16,000 --> 00:50:19,000 Eu também poderia ir sobre agora talvez adicionando um loop 926 00:50:19,000 --> 00:50:23,000 e usando GetString e GetInt para realmente obter esses valores do usuário. 927 00:50:23,000 --> 00:50:27,000 Eu poderia ir sobre como adicionar uma constante, porque esta é geralmente má prática 928 00:50:27,000 --> 00:50:29,000 rígido código algum número arbitrário como 3 aqui 929 00:50:29,000 --> 00:50:33,000 e lembre-se que você deve colocar mais de 3 alunos na mesma. 930 00:50:33,000 --> 00:50:36,000 Provavelmente seria melhor usar # define no topo do meu arquivo 931 00:50:36,000 --> 00:50:40,000 e fator que fora, assim, de fato, deixe-me ir em frente e generalizar isso. 932 00:50:40,000 --> 00:50:43,000 >> Deixe-me abrir um exemplo que está entre os de hoje 933 00:50:43,000 --> 00:50:46,000 exemplos de antecedência, structs1. 934 00:50:46,000 --> 00:50:49,000 Este é um programa mais completo que utiliza # define-se aqui 935 00:50:49,000 --> 00:50:51,000 e diz que vamos ter 3 alunos por padrão. 936 00:50:51,000 --> 00:50:54,000 Aqui eu estou declarando um valor classe de estudantes, 937 00:50:54,000 --> 00:50:57,000 para uma sala de aula de alunos, e agora estou usando um loop 938 00:50:57,000 --> 00:51:00,000 apenas para tornar o código um pouco mais elegante, preencher a classe 939 00:51:00,000 --> 00:51:05,000 com a entrada do usuário, de modo iterar a partir de i = 0 em cima para os alunos, que é 3. 940 00:51:05,000 --> 00:51:07,000 E então eu solicitar que o usuário nesta versão 941 00:51:07,000 --> 00:51:10,000  o que é o ID do aluno, e eu fico com GetInt. 942 00:51:10,000 --> 00:51:13,000 Qual é o nome do aluno, e então eu começo com GetString. 943 00:51:13,000 --> 00:51:15,000 O que é a casa do aluno? Recebo-o com GetString. 944 00:51:15,000 --> 00:51:19,000 E então no fundo aqui, eu simplesmente decidi mudar 945 00:51:19,000 --> 00:51:22,000 como eu estou imprimindo estes para fora e realmente usar um loop, 946 00:51:22,000 --> 00:51:24,000 E quem sou eu imprimir? 947 00:51:24,000 --> 00:51:27,000 De acordo com o comentário que eu estou imprimindo qualquer um em Mather, 948 00:51:27,000 --> 00:51:30,000 e é isso para Rob e Tommy e assim por diante, na verdade Tommy em Mather. 949 00:51:30,000 --> 00:51:34,000 Tommy e David seria impresso no caso, mas como é que isto funciona? 950 00:51:34,000 --> 00:51:40,000 Nós não vimos essa função antes, mas dar um palpite sobre o que isso faz. 951 00:51:40,000 --> 00:51:42,000 Compara strings. 952 00:51:42,000 --> 00:51:45,000 >> É um pouco não-óbvio como ele se compara cordas pois verifica-se 953 00:51:45,000 --> 00:51:49,000 se ele retorna 0 que significa que as cordas são iguais. 954 00:51:49,000 --> 00:51:53,000 Se ela retorna a -1 que significa um vem antes do outro em ordem alfabética, 955 00:51:53,000 --> 00:51:57,000 e se ele retorna um que significa a palavra outro vem em ordem alfabética 956 00:51:57,000 --> 00:52:00,000 antes do outro, e você pode procurar on-line ou na página do homem 957 00:52:00,000 --> 00:52:04,000 para ver exatamente qual é qual, mas tudo isso está fazendo agora é que está dizendo 958 00:52:04,000 --> 00:52:09,000 se o [i]. casa é igual a "Mather" 959 00:52:09,000 --> 00:52:13,000 então vá em frente e imprimir assim e assim é em Mather. 960 00:52:13,000 --> 00:52:16,000 Mas aqui está algo que não tenha visto antes, e nós vamos voltar a este. 961 00:52:16,000 --> 00:52:21,000 Não me lembro de alguma vez ter que fazer isso em qualquer um dos meus programas. 962 00:52:21,000 --> 00:52:24,000 Livre é, aparentemente referindo-se a memória, liberando memória, 963 00:52:24,000 --> 00:52:31,000 mas o que a memória aparentemente estou liberando neste loop na parte inferior do programa? 964 00:52:31,000 --> 00:52:34,000 Parece que eu estou liberando nome de uma pessoa 965 00:52:34,000 --> 00:52:37,000 e da casa de uma pessoa, mas por que isso? 966 00:52:37,000 --> 00:52:41,000 >> Acontece que todas essas semanas que você está usando GetString 967 00:52:41,000 --> 00:52:45,000 temos vindo a introduzir tipo de um bug em cada um de seus programas. 968 00:52:45,000 --> 00:52:51,000 GetString pela memória aloca projeto para que ele possa retornar a você uma string, 969 00:52:51,000 --> 00:52:55,000 como Davi, ou Rob, e então você pode fazer o que quiser 970 00:52:55,000 --> 00:52:59,000 com essa seqüência em seu programa porque temos a memória reservada para você. 971 00:52:59,000 --> 00:53:02,000 O problema é todo esse tempo a cada vez que você chamar GetString 972 00:53:02,000 --> 00:53:05,000 nós, os autores de GetString, têm vindo a pedir o sistema operacional 973 00:53:05,000 --> 00:53:07,000 para nos dar um pouco de memória RAM para esta cadeia. 974 00:53:07,000 --> 00:53:09,000 Dê-nos um pouco de memória RAM para esta próxima corda. 975 00:53:09,000 --> 00:53:11,000 Dê-nos um pouco mais de memória RAM para essa seqüência seguinte. 976 00:53:11,000 --> 00:53:13,000 O que você, programador, nunca foram fazendo 977 00:53:13,000 --> 00:53:15,000 está nos dando de volta a memória, 978 00:53:15,000 --> 00:53:17,000 assim para estas várias semanas todos os programas que você escreveu 979 00:53:17,000 --> 00:53:20,000 ter o que é chamado um salto de memória em que eles continuam usando 980 00:53:20,000 --> 00:53:24,000 mais memória e mais a cada vez que você chamar GetString, e isso é bom. 981 00:53:24,000 --> 00:53:27,000 Nós deliberadamente fazer isso nas primeiras semanas, porque não é tão interessante 982 00:53:27,000 --> 00:53:29,000 ter que se preocupar com onde a corda está vindo. 983 00:53:29,000 --> 00:53:34,000 Tudo que você quer é a palavra Rob para voltar quando o usuário digita-lo dentro 984 00:53:34,000 --> 00:53:38,000 >> Mas avançar agora temos de começar a ficar mais sofisticada sobre isso. 985 00:53:38,000 --> 00:53:42,000 A qualquer momento que alocar memória é melhor, eventualmente, entregá-lo de volta. 986 00:53:42,000 --> 00:53:45,000 Caso contrário, no mundo real no seu Mac ou PC, você pode ter ocasionalmente experiente 987 00:53:45,000 --> 00:53:50,000 sintomas onde o computador está a ponto de paralisar eventualmente 988 00:53:50,000 --> 00:53:54,000 ou a bola de praia estúpido fiação está apenas ocupando o do computador 989 00:53:54,000 --> 00:53:56,000 toda a atenção e você não pode fazer as coisas. 990 00:53:56,000 --> 00:54:00,000 Isso pode ser explicado por uma série de bugs, mas entre os possíveis erros 991 00:54:00,000 --> 00:54:03,000 são coisas chamadas vazamentos de memória em que alguém que escreveu esse pedaço de software 992 00:54:03,000 --> 00:54:07,000 que você está usando não se lembrar de memória livre 993 00:54:07,000 --> 00:54:10,000 que ele ou ela perguntou o sistema operacional para, 994 00:54:10,000 --> 00:54:14,000 não usar GetString, porque isso é uma coisa CS50, mas usando funções similares 995 00:54:14,000 --> 00:54:16,000 que pedem o sistema operacional para a memória. 996 00:54:16,000 --> 00:54:19,000 Se você ou estragar e nunca realmente voltar que a memória 997 00:54:19,000 --> 00:54:24,000 um sintoma de que pode ser um programa que retarda e reduz e retarda 998 00:54:24,000 --> 00:54:26,000 a menos que você se lembrar de chamar livre. 999 00:54:26,000 --> 00:54:28,000 >> Nós vamos voltar para quando e por que você chamaria de livre, 1000 00:54:28,000 --> 00:54:32,000 mas vamos em frente apenas para uma boa medida e tente executar este programa em particular. 1001 00:54:32,000 --> 00:54:35,000 Isto foi chamado structs1, entrar. 1002 00:54:35,000 --> 00:54:40,000 Deixe-me ir em frente e correr structs1, 123, David Mather, 1003 00:54:40,000 --> 00:54:47,000 456, Rob Kirkland, 789, 1004 00:54:47,000 --> 00:54:50,000 Tommy Mather, e vemos Davi em Mather, Tommy em Mather. 1005 00:54:50,000 --> 00:54:53,000 Este é apenas um teste de sanidade de que o programa está funcionando. 1006 00:54:53,000 --> 00:54:56,000 Agora, infelizmente, este programa é um pouco frustrante, em que 1007 00:54:56,000 --> 00:55:00,000 Eu fiz todo esse trabalho, eu digitei em nove diferentes seqüências, aperte enter, 1008 00:55:00,000 --> 00:55:04,000 foi dito que estava em Mather, mas, obviamente, eu sabia que estava em Mather, porque eu já digitou. 1009 00:55:04,000 --> 00:55:07,000 Seria bom se, pelo menos, este programa é mais como um banco de dados 1010 00:55:07,000 --> 00:55:10,000 e ele realmente se lembra do que eu ter digitado 1011 00:55:10,000 --> 00:55:12,000 então eu nunca mais ter de introduzir estes registros dos alunos. 1012 00:55:12,000 --> 00:55:15,000 Talvez seja como um sistema registrarial. 1013 00:55:15,000 --> 00:55:21,000 >> Podemos fazer isso usando esta técnica conhecida como arquivo de entrada de arquivo I / O, e de saída, 1014 00:55:21,000 --> 00:55:24,000 uma forma muito genérica de dizer qualquer momento que você quer ler arquivos ou escrever arquivos 1015 00:55:24,000 --> 00:55:26,000 você pode fazer isso com um determinado conjunto de funções. 1016 00:55:26,000 --> 00:55:29,000 Deixe-me ir em frente e abrir este structs2.c exemplo, 1017 00:55:29,000 --> 00:55:33,000 que é quase idêntico, mas vamos ver o que ele faz agora. 1018 00:55:33,000 --> 00:55:36,000 No topo do arquivo eu declaro uma classe de alunos. 1019 00:55:36,000 --> 00:55:38,000 Eu, então, preencher a classe com a entrada do usuário, 1020 00:55:38,000 --> 00:55:41,000 para as linhas de código são exatamente como antes. 1021 00:55:41,000 --> 00:55:45,000 Então, se eu rolar aqui eu imprimir todos os que estão em Mather arbitrariamente como antes, 1022 00:55:45,000 --> 00:55:47,000 mas esta é uma novidade interessante. 1023 00:55:47,000 --> 00:55:51,000 Estas linhas de código são novos, e eles introduzem algo aqui, 1024 00:55:51,000 --> 00:55:55,000 Arquivo, todas as tampas, e tem * aqui também. 1025 00:55:55,000 --> 00:55:58,000 Deixe-me passar isso aqui, a * por aqui também. 1026 00:55:58,000 --> 00:56:00,000 >> Esta função não vimos antes, fopen, 1027 00:56:00,000 --> 00:56:03,000 mas significa arquivo aberto, então vamos percorrer estes, 1028 00:56:03,000 --> 00:56:05,000 e isso é algo que nós vamos voltar a Série de Exercícios no futuro, 1029 00:56:05,000 --> 00:56:10,000 mas esta linha aqui, essencialmente, abre um arquivo chamado banco de dados, 1030 00:56:10,000 --> 00:56:13,000 e especificamente abre-a de tal forma que ele pode fazer o que com ele? 1031 00:56:13,000 --> 00:56:15,000 [Inaudível-aluno] 1032 00:56:15,000 --> 00:56:19,000 Certo, então "w" significa apenas que ele está dizendo o sistema operacional 1033 00:56:19,000 --> 00:56:21,000 abrir este arquivo de tal forma que eu possa escrever para ele. 1034 00:56:21,000 --> 00:56:23,000 Eu não quero lê-lo. Eu não quero só olhar para ele. 1035 00:56:23,000 --> 00:56:26,000 Eu quero mudar isso e adicionar coisas potencialmente a ele, 1036 00:56:26,000 --> 00:56:28,000 eo arquivo vai ser chamado de banco de dados. 1037 00:56:28,000 --> 00:56:30,000 Isto poderia ser chamado nada. 1038 00:56:30,000 --> 00:56:32,000 Isto poderia ser database.txt. Isto poderia ser. Db. 1039 00:56:32,000 --> 00:56:37,000 Esta poderia ser uma palavra como tal, mas eu arbitrariamente escolheu o nome do banco de dados de arquivo. 1040 00:56:37,000 --> 00:56:42,000 Este é um teste de sanidade de que vamos voltar a em grande detalhe ao longo do tempo, 1041 00:56:42,000 --> 00:56:47,000 se fp, para ponteiro de arquivo, não NULL igual significa que tudo está bem. 1042 00:56:47,000 --> 00:56:51,000 >> Longa história curta, funções como fopen às vezes falham. 1043 00:56:51,000 --> 00:56:53,000 Talvez o arquivo não existe. Talvez você esteja fora do espaço de disco. 1044 00:56:53,000 --> 00:56:55,000 Talvez você não tem permissão para essa pasta, 1045 00:56:55,000 --> 00:56:58,000 por isso, se fopen retorna algo nulo de ruim aconteceu. 1046 00:56:58,000 --> 00:57:02,000 Por outro lado, se fopen não retornar nulo tudo está bem 1047 00:57:02,000 --> 00:57:04,000 e eu posso começar a escrever para este arquivo. 1048 00:57:04,000 --> 00:57:06,000 Aqui está um truque novo. 1049 00:57:06,000 --> 00:57:08,000 Este é um loop de que está interagindo sobre cada um dos meus alunos, 1050 00:57:08,000 --> 00:57:10,000 e isso parece tão semelhante ao que fizemos antes, 1051 00:57:10,000 --> 00:57:15,000 mas esta função é um primo do printf chamado fprintf para arquivo printf, 1052 00:57:15,000 --> 00:57:18,000 e perceber que é diferente em apenas dois caminhos. 1053 00:57:18,000 --> 00:57:20,000 Um deles, que começa com f em vez de p, 1054 00:57:20,000 --> 00:57:23,000 mas então seu primeiro argumento é aparentemente o que? 1055 00:57:23,000 --> 00:57:25,000 [Os alunos] do arquivo. >> É um arquivo. 1056 00:57:25,000 --> 00:57:30,000 Essa coisa chamada fp, que vai finalmente destrinçar o que é um ponteiro de arquivo, 1057 00:57:30,000 --> 00:57:35,000 mas por agora fp simplesmente representa o arquivo que eu abri, 1058 00:57:35,000 --> 00:57:41,000 fprintf assim aqui está dizendo imprimir ID do usuário para o arquivo, não para a tela. 1059 00:57:41,000 --> 00:57:44,000 Imprimir o nome do usuário para o arquivo, e não para a tela, 1060 00:57:44,000 --> 00:57:47,000 a casa para o arquivo, e não para a tela, e depois para baixo aqui, obviamente, 1061 00:57:47,000 --> 00:57:50,000 feche o arquivo, e depois para baixo aqui livre da memória. 1062 00:57:50,000 --> 00:57:53,000 >> A única diferença entre esta versão ea versão 2 1 1063 00:57:53,000 --> 00:57:58,000 é a introdução de fopen e este arquivo com * 1064 00:57:58,000 --> 00:58:01,000 e essa noção de fprintf, então vamos ver o que o resultado final é. 1065 00:58:01,000 --> 00:58:03,000 Deixe-me ir para a minha janela de terminal. 1066 00:58:03,000 --> 00:58:06,000 Deixa-me correr structs2, entrar. 1067 00:58:06,000 --> 00:58:09,000 Parece que tudo está bem. Vamos executar novamente structs2. 1068 00:58:09,000 --> 00:58:15,000 123, David Mather, 456, Rob Kirkland, 1069 00:58:15,000 --> 00:58:19,000 789, Tommy Mather, entrar. 1070 00:58:19,000 --> 00:58:23,000 Parece que ele se comportou o mesmo, mas se eu faço agora ls 1071 00:58:23,000 --> 00:58:28,000 perceber o que está no arquivo aqui entre todo o meu código, banco de dados, 1072 00:58:28,000 --> 00:58:32,000 então vamos abrir esse, olhar gedit de banco de dados, e para isso. 1073 00:58:32,000 --> 00:58:34,000 Não é o mais sexy de formatos de arquivo. 1074 00:58:34,000 --> 00:58:38,000 É realmente um pedaço de linha de dados por linha por linha, 1075 00:58:38,000 --> 00:58:42,000 mas aqueles de vocês que usam arquivos do Excel ou CSV, valores separados por vírgula, 1076 00:58:42,000 --> 00:58:47,000 Eu certamente poderia ter usado fprintf ao invés talvez fazer algo assim 1077 00:58:47,000 --> 00:58:50,000 para que eu pudesse realmente criar o equivalente a um arquivo do Excel 1078 00:58:50,000 --> 00:58:53,000 separando as coisas com vírgulas, e não apenas as novas linhas. 1079 00:58:53,000 --> 00:58:56,000 >> Neste caso, se eu tivesse usado em vez vírgulas em vez de novas linhas 1080 00:58:56,000 --> 00:59:01,000 Eu poderia literalmente abrir este arquivo de banco de dados no Excel, se eu, em vez fez parecer assim. 1081 00:59:01,000 --> 00:59:03,000 Em suma, agora que temos o poder de gravar arquivos 1082 00:59:03,000 --> 00:59:07,000 agora podemos começar a persistência de dados, mantendo-a em torno de disco 1083 00:59:07,000 --> 00:59:10,000 para que possamos manter as informações de novo e de novo. 1084 00:59:10,000 --> 00:59:14,000 Observe um par de outras coisas que são agora um pouco mais familiar. 1085 00:59:14,000 --> 00:59:16,000 No topo deste arquivo C temos um typedef 1086 00:59:16,000 --> 00:59:21,000 porque queríamos criar um tipo de dados que representa uma palavra, 1087 00:59:21,000 --> 00:59:25,000 de modo que este tipo é chamado de palavra, e dentro desta estrutura 1088 00:59:25,000 --> 00:59:27,000 é um pouco amador agora. 1089 00:59:27,000 --> 00:59:30,000 Porque é uma palavra composta de, aparentemente, uma matriz? 1090 00:59:30,000 --> 00:59:33,000 O que é uma palavra apenas de forma intuitiva? 1091 00:59:33,000 --> 00:59:35,000 >> É uma matriz de caracteres. 1092 00:59:35,000 --> 00:59:37,000 É uma sequência de caracteres de costas para trás. 1093 00:59:37,000 --> 00:59:41,000 Letras em todas as tampas acontece de ser nós arbitrariamente dizer o comprimento máximo 1094 00:59:41,000 --> 00:59:44,000 de qualquer palavra no dicionário que estamos usando para Scramble. 1095 00:59:44,000 --> 00:59:46,000 Por que eu tenho um 1? 1096 00:59:46,000 --> 00:59:48,000 O personagem nulo. 1097 00:59:48,000 --> 00:59:51,000 Lembre-se de quando nós fizemos o exemplo Bananagrams precisávamos de um valor especial 1098 00:59:51,000 --> 00:59:55,000 no fim da palavra, a fim de manter a par 1099 00:59:55,000 --> 00:59:59,000 de onde as palavras realmente acabou, e como a especificação do conjunto de problemas diz 1100 00:59:59,000 --> 01:00:03,000 aqui estamos associando com uma determinada palavra um valor booleano, 1101 01:00:03,000 --> 01:00:05,000 uma bandeira, por assim dizer, verdadeira ou falsa. 1102 01:00:05,000 --> 01:00:09,000 Você já encontrou esta palavra já, porque percebemos 1103 01:00:09,000 --> 01:00:13,000 nós realmente precisamos de uma maneira de lembrar não só o que a palavra está no Scramble 1104 01:00:13,000 --> 01:00:15,000 mas se está ou não, o ser humano, têm encontrado 1105 01:00:15,000 --> 01:00:20,000 de modo que se você não encontrar a palavra "o" você não pode simplesmente digitar o, entra, a, entre, a, insira 1106 01:00:20,000 --> 01:00:23,000 e obter 3 pontos, 3 pontos, 3 pontos, 3 pontos. 1107 01:00:23,000 --> 01:00:26,000 Queremos ser capazes de barrar essa palavra definindo um bool 1108 01:00:26,000 --> 01:00:29,000 a verdade se você já encontrou, e é por isso que nós 1109 01:00:29,000 --> 01:00:31,000 encapsulado em sua estrutura. 1110 01:00:31,000 --> 01:00:35,000 >> Agora, aqui no Scramble há essa outra struct chamado dicionário. 1111 01:00:35,000 --> 01:00:39,000 Ausente aqui é a palavra typedef porque neste caso 1112 01:00:39,000 --> 01:00:43,000 precisávamos para encapsular a idéia de um dicionário, 1113 01:00:43,000 --> 01:00:46,000 e um dicionário contém um monte de palavras, 1114 01:00:46,000 --> 01:00:49,000 como implicado por esta matriz, e quantas dessas palavras estão lá? 1115 01:00:49,000 --> 01:00:51,000 Bem, qualquer que seja deste tamanho variável chamada diz. 1116 01:00:51,000 --> 01:00:53,000 Mas só precisamos de um dicionário. 1117 01:00:53,000 --> 01:00:55,000 Nós não precisamos de um tipo de dados chamado dicionário. 1118 01:00:55,000 --> 01:00:58,000 Nós só precisamos de um deles, por isso acaba em C 1119 01:00:58,000 --> 01:01:03,000 que, se você não diz typedef, você acabou de dizer struct, em seguida, dentro das chaves 1120 01:01:03,000 --> 01:01:05,000 você colocar suas variáveis, então você colocar o nome. 1121 01:01:05,000 --> 01:01:09,000 Este é declarar uma variável chamada dicionário 1122 01:01:09,000 --> 01:01:11,000 que se parece com isso. 1123 01:01:11,000 --> 01:01:16,000 Por outro lado, estas linhas são a criação de uma estrutura de dados reutilizável chamado palavra 1124 01:01:16,000 --> 01:01:19,000 que você pode criar várias cópias, assim como nós criamos 1125 01:01:19,000 --> 01:01:22,000 várias cópias de alunos. 1126 01:01:22,000 --> 01:01:24,000 >> O que isso finalmente permitir que façamos? 1127 01:01:24,000 --> 01:01:30,000 Deixe-me voltar para, digamos, um exemplo mais simples a partir de tempos mais simples, 1128 01:01:30,000 --> 01:01:34,000 e deixe-me abrir-se, digamos, compare1.c. 1129 01:01:34,000 --> 01:01:38,000 O problema aqui em mãos é realmente casca de volta 1130 01:01:38,000 --> 01:01:41,000 a camada de uma corda e começar a tirar essas rodinhas 1131 01:01:41,000 --> 01:01:44,000 pois verifica-se que uma seqüência de todo esse tempo 1132 01:01:44,000 --> 01:01:47,000 é como prometemos na semana 1 apenas um apelido, 1133 01:01:47,000 --> 01:01:51,000 um sinônimo da biblioteca CS50 por algo que parece um pouco mais crítico, 1134 01:01:51,000 --> 01:01:53,000 char *, e vimos essa estrela antes. 1135 01:01:53,000 --> 01:01:55,000 Vimo-lo no contexto de arquivos. 1136 01:01:55,000 --> 01:01:59,000 >> Vamos ver agora porque estamos escondendo esse detalhe já há algum tempo. 1137 01:01:59,000 --> 01:02:02,000 Aqui está um arquivo chamado compare1.c, 1138 01:02:02,000 --> 01:02:07,000 e, aparentemente, pede ao usuário para duas cordas, s e t, 1139 01:02:07,000 --> 01:02:11,000 e então ele tenta comparar essas cordas de igualdade na linha 26, 1140 01:02:11,000 --> 01:02:14,000 e se eles são iguais ele diz: "Você digitou a mesma coisa", 1141 01:02:14,000 --> 01:02:17,000 e se eles não são iguais ele diz: "Você digitou coisas diferentes." 1142 01:02:17,000 --> 01:02:19,000 Deixe-me ir em frente e executar este programa. 1143 01:02:19,000 --> 01:02:23,000 Deixe-me ir para o meu diretório de origem, fazer uma compare1. Ele compilou tudo bem. 1144 01:02:23,000 --> 01:02:25,000 Deixa-me correr compare1. 1145 01:02:25,000 --> 01:02:27,000 Eu vou aumentar o zoom, entrar. 1146 01:02:27,000 --> 01:02:29,000 Diga alguma coisa. OLÁ. 1147 01:02:29,000 --> 01:02:32,000 Eu vou dizer algo de novo. OLÁ. 1148 01:02:32,000 --> 01:02:34,000 Eu definitivamente não escreva coisas diferentes. 1149 01:02:34,000 --> 01:02:37,000 >> Deixe-me tentar de novo. BYE BYE. 1150 01:02:37,000 --> 01:02:40,000 Definitivamente não é diferente, por isso o que está acontecendo aqui? 1151 01:02:40,000 --> 01:02:44,000 Bem, o que realmente está sendo comparado na linha 26? 1152 01:02:44,000 --> 01:02:46,000 [Inaudível-aluno] 1153 01:02:46,000 --> 01:02:49,000 Sim, então verifica-se que uma string, tipo de dados, é um tipo de mentira. 1154 01:02:49,000 --> 01:02:53,000 Uma string é um char *, mas o que é um char *? 1155 01:02:53,000 --> 01:02:56,000 A * char, como eles dizem, é um ponteiro, 1156 01:02:56,000 --> 01:03:00,000 e um ponteiro é efetivamente um endereço, 1157 01:03:00,000 --> 01:03:05,000 soma um local na memória, e se acontecer de você ter digitado uma palavra como OLÁ, 1158 01:03:05,000 --> 01:03:08,000 lembro de discussões passadas de cordas 1159 01:03:08,000 --> 01:03:16,000 isto é como a palavra OLÁ. 1160 01:03:16,000 --> 01:03:19,000 Lembre-se que uma palavra como OLÁ pode ser representado 1161 01:03:19,000 --> 01:03:22,000 como uma matriz de caracteres como esta 1162 01:03:22,000 --> 01:03:25,000 e depois com um caractere especial no final chamou o caractere nulo, 1163 01:03:25,000 --> 01:03:27,000 como o denota \. 1164 01:03:27,000 --> 01:03:29,000 O que é realmente uma cadeia? 1165 01:03:29,000 --> 01:03:32,000 Note-se que isto é vários pedaços de memória, 1166 01:03:32,000 --> 01:03:36,000 e, de fato, o fim do que é conhecido somente quando você olhar através de toda a cadeia 1167 01:03:36,000 --> 01:03:38,000 olhando para o caractere nulo especial. 1168 01:03:38,000 --> 01:03:41,000 Mas se este é um pedaço da memória da memória do meu computador, 1169 01:03:41,000 --> 01:03:44,000 vamos arbitrariamente dizer que essa seqüência de apenas teve sorte, 1170 01:03:44,000 --> 01:03:47,000 e ele foi colocado no início de RAM do meu computador. 1171 01:03:47,000 --> 01:03:54,000 Este é o byte 0, 1, 2, 3, 4, 5, 6 ... 1172 01:03:54,000 --> 01:04:02,000 >> Quando eu digo algo como GetString e eu string s = GetString 1173 01:04:02,000 --> 01:04:04,000 o que realmente está sendo devolvido? 1174 01:04:04,000 --> 01:04:08,000 Para estas últimas semanas, o que realmente está sendo armazenado em s 1175 01:04:08,000 --> 01:04:13,000 não é essa seqüência de per se, mas neste caso o que está sendo armazenado é 1176 01:04:13,000 --> 01:04:18,000 o número 0, porque o que realmente faz GetString 1177 01:04:18,000 --> 01:04:20,000 é que fisicamente não retornar uma string. 1178 01:04:20,000 --> 01:04:22,000 Que nem sequer realmente faz sentido conceitual. 1179 01:04:22,000 --> 01:04:24,000 O que ele faz de retorno é um número. 1180 01:04:24,000 --> 01:04:28,000 Esse número é o endereço da OLÁ na memória, 1181 01:04:28,000 --> 01:04:32,000 e string s, em seguida, se descascar esta camada, cadeia não existe realmente. 1182 01:04:32,000 --> 01:04:35,000 É apenas uma simplificação na biblioteca CS50. 1183 01:04:35,000 --> 01:04:38,000 >> Isso realmente é algo chamado char *. 1184 01:04:38,000 --> 01:04:41,000 Char faz sentido, porque o que é uma palavra, como OLÁ? 1185 01:04:41,000 --> 01:04:44,000 Bem, é uma série de caracteres, uma série de personagens. 1186 01:04:44,000 --> 01:04:47,000 Char * significa que o endereço de um personagem, 1187 01:04:47,000 --> 01:04:50,000 Então, o que isso significa para retornar uma string? 1188 01:04:50,000 --> 01:04:53,000 Uma forma agradável, simples de retornar uma string 1189 01:04:53,000 --> 01:04:57,000 é melhor do que tentar descobrir como eu voltar para 5 ou 6 bytes diferentes 1190 01:04:57,000 --> 01:05:01,000 deixe-me voltar para o endereço que byte? 1191 01:05:01,000 --> 01:05:03,000 O primeiro. 1192 01:05:03,000 --> 01:05:06,000 Em outras palavras, deixe-me dar-lhe o endereço de um personagem na memória. 1193 01:05:06,000 --> 01:05:10,000 Isso é o que representa char *, o endereço de um único caractere na memória. 1194 01:05:10,000 --> 01:05:12,000 Chame isso é variável. 1195 01:05:12,000 --> 01:05:15,000 Loja em s que determinado endereço, o que eu disse é arbitrariamente 0, 1196 01:05:15,000 --> 01:05:19,000 apenas para manter as coisas simples, mas na realidade ele é geralmente um número maior. 1197 01:05:19,000 --> 01:05:21,000 >> Espere um minuto. 1198 01:05:21,000 --> 01:05:23,000 Se você só está me dando o endereço do primeiro caractere, como eu sei que o endereço é 1199 01:05:23,000 --> 01:05:25,000 do segundo personagem, o terceiro, o quarto eo quinto? 1200 01:05:25,000 --> 01:05:27,000 [Inaudível-aluno] 1201 01:05:27,000 --> 01:05:31,000 Você só sabe que o fim da seqüência é por meio deste truque prático, 1202 01:05:31,000 --> 01:05:35,000 Então, quando você usar algo como printf, o que printf literalmente toma como argumento, 1203 01:05:35,000 --> 01:05:39,000 Recordamos que usamos este espaço reservado% s, e então você passa 1204 01:05:39,000 --> 01:05:41,000 a variável que está armazenando uma string. 1205 01:05:41,000 --> 01:05:47,000 O que realmente está passando é o endereço do primeiro caractere dessa seqüência. 1206 01:05:47,000 --> 01:05:50,000 Printf então usa um laço ou um loop while, ao receber esse endereço, 1207 01:05:50,000 --> 01:05:53,000 por exemplo, 0, então deixe-me fazer isso agora, 1208 01:05:53,000 --> 01:06:02,000 printf ("% s \ n", s); 1209 01:06:02,000 --> 01:06:07,000 Quando eu chamo printf ("% s \ n", s), o que eu realmente estou fornecendo printf com 1210 01:06:07,000 --> 01:06:13,000 é o endereço do primeiro caracter em s, o qual, neste caso, é arbitrária H. 1211 01:06:13,000 --> 01:06:16,000 >> Como se sabe exatamente o que printf para exibir na tela? 1212 01:06:16,000 --> 01:06:19,000 A pessoa que implementou printf implementou um loop while ou um loop 1213 01:06:19,000 --> 01:06:23,000 que diz que este personagem igualar o caractere nulo especial? 1214 01:06:23,000 --> 01:06:25,000 Se não, imprimi-lo. Que tal um presente? 1215 01:06:25,000 --> 01:06:28,000 Se não imprimi-lo, imprimi-lo, imprimi-lo, imprimi-lo. 1216 01:06:28,000 --> 01:06:32,000 Oh, este é especial. Interromper a impressão e retornar para o utilizador. 1217 01:06:32,000 --> 01:06:35,000 E isso é, literalmente, tudo o que está acontecendo debaixo do capô, 1218 01:06:35,000 --> 01:06:38,000 e isso é muita coisa para digerir, no primeiro dia de uma classe, 1219 01:06:38,000 --> 01:06:43,000 mas por agora é realmente o alicerce de tudo compreensão 1220 01:06:43,000 --> 01:06:46,000 que está acontecendo dentro da memória do nosso computador, 1221 01:06:46,000 --> 01:06:49,000 e, finalmente, nós vamos provocar este apart com uma pequena ajuda 1222 01:06:49,000 --> 01:06:51,000 de um de nossos amigos em Stanford. 1223 01:06:51,000 --> 01:06:56,000 >> Professor Nick Parlante em Stanford fez esta seqüência maravilhoso vídeo 1224 01:06:56,000 --> 01:06:58,000 de todos os tipos de línguas diferentes que introduziram 1225 01:06:58,000 --> 01:07:00,000 Binky este pequeno personagem Claymation. 1226 01:07:00,000 --> 01:07:03,000 A voz que você está prestes a ouvir em apenas alguns prévia segunda 1227 01:07:03,000 --> 01:07:05,000 é a de um professor de Stanford, e você está ficando 1228 01:07:05,000 --> 01:07:07,000 apenas 5 ou 6 segundos de isso agora, 1229 01:07:07,000 --> 01:07:09,000 mas esta é a nota em que vamos concluir hoje 1230 01:07:09,000 --> 01:07:11,000 e começar na quarta-feira. 1231 01:07:11,000 --> 01:07:15,000 Eu dar-lhe Fun Pointer com Binky, a visualização. 1232 01:07:15,000 --> 01:07:18,000 [♪ ♪ Música] [Professor Parlante] Ei, Binky. 1233 01:07:18,000 --> 01:07:21,000 Acordar. É hora de diversão ponteiro. 1234 01:07:21,000 --> 01:07:24,000 [Binky] O que é isso? Saiba mais sobre ponteiros? 1235 01:07:24,000 --> 01:07:26,000 Ah, bom! 1236 01:07:26,000 --> 01:07:29,000 >> Vamos vê-lo na quarta-feira. 1237 01:07:29,000 --> 01:07:32,000 [CS50.TV]