[Review: Quiz 1] [Ali Nahm, Oreoluwa Barbarinsa, Lucas Freitas, Rob Bowden] [Universidade de Harvard] [Isto é CS50.] [CS50.TV] [Lucas Freitas] Sejam bem-vindos. Esta é uma revisão para questionário 1. Assim como um aviso, este é - quero dizer, vamos tentar cobrir tanto material quanto possível, mas isso não significa que nós vamos cobrir todas as coisas que podem ser em questionário 1. Então não se esqueça que você também dar uma olhada em aula, seções, tudo o que você puder. Teste 1 vai ser na quarta-feira, próxima quarta-feira. Então não deixe de estudar. Vai ser, praticamente, como o primeiro teste quanto ao seu formato, mas provavelmente vai ser muito mais difícil. Pelo menos, no ano passado, quando eu tirei 50, eu pensei que era muito mais difícil. Portanto, estude muito. Eu estou indo cobrir as estruturas de dados e código de Huffman. Isso é algo que um monte de gente acha que é complexo, mas eu vou tentar torná-lo tão fácil quanto possível. Primeiro de tudo, o que nós queremos que vocês conhecem para teste 1 é compreender as descrições conceituais de cada uma das estruturas de dados que eu vou apresentar. Isso significa que você não tem que realmente implementar uma tabela hash em seu questionário 1. Nós não queremos que você implemente uma tabela hash inteiro, talvez vamos tentar para fazer você implementar algumas funções, as operações mais comuns, mas não vai fazer você implementar tudo. Por isso, é importante que você entenda o conceito por trás de cada estrutura de dados e também que você é capaz de codificar em C, apenas as operações mais comuns que têm para cada estrutura de dados. E também ser capaz de analisar os ponteiros e estruturas, porque eles aparecem muito nestas estruturas de dados. Em primeiro lugar, as listas ligadas. Listas encadeadas são realmente muito semelhantes a arrays, mas a diferença entre uma lista encadeada e uma matriz, em primeiro lugar, que é uma lista encadeada tem um tamanho muito flexível, enquanto que em matrizes tem que quer escolher um tamanho muito grande para a matriz, para que você saiba que você vai ser capaz de armazenar todos os seus dados em que matriz, ou você tem que usar malloc para ter um comprimento flexível da matriz. Em listas ligadas é muito fácil, é só pegar mais elementos, colocar mais elementos na lista ligada ou remover elementos. E, na verdade, se você não quer que a lista ligada a serem classificados, você pode procurar e remover elementos em tempo constante, então O (1) tempo, por isso é muito conveniente. Você só tem que ter cuidado para se lembrar sempre de malloc e free os nós, apenas porque se você não fizer isso, você vai ter vazamentos de memória. Então listas ligadas - a definição de um nó é como o que nós temos aí. Eu coloquei int n, mas você pode armazenar todos os dados que você deseja. Então, se você deseja armazenar uma string, ela está bem. Se você deseja armazenar uma estrutura, está tudo bem, um duplo, o que quiser. Acabei de colocar int n para os exemplos aqui. E você tem um ponteiro para o próximo nó. Então, basicamente, uma lista ligada tem alguns dados, e, em seguida, ele aponta para o próximo nó. Se ele é o último elemento da lista ligada, ele vai apontar para NULL. Portanto, este é um exemplo de uma lista ligada. Ok, então agora vamos ver o que devemos fazer se eu quiser inserir um elemento em uma lista vinculada. Em primeiro lugar, uma inserção de função será do tipo void porque eu não quero retornar nada. E eu vou tomar um int como argumento, porque eu quero saber o que eu quero inserir. Então, qual é a primeira coisa que devo fazer? Bem, eu deveria malloc em newNode, de modo que é a primeira linha. Estou apenas a criação de um novo nó para colocar em uma lista encadeada. Então o que eu posso fazer? Bem, sabemos que em nossas implementações de listas ligadas em sala de aula, colocamos sempre a cabeça como uma variável global. Então, o que podemos fazer é mudar a cabeça. Eu posso fazer este novo nó ser o novo chefe, e ele vai apontar para a cabeça anterior. Como podemos fazer isso? A primeira coisa que eu tenho que fazer é mudar o 'n' no novo nó de valor, que foi passado para a função. Então newNode é o próximo vai ser o cabeça. A cabeça vai ser newNode. Por isso, é muito simples. Para excluir um nó, nós podemos fazê-lo como - Uma maneira que nós poderíamos fazer isto é, Tudo bem, se eu queria excluir, por exemplo, 3, o que eu poderia fazer é apenas apontar o nó anterior para o próximo nó de 3. Então, eu só iria fazer algo assim. Mas qual é o problema em fazer isso? Eu tenho um vazamento de memória, então eu não tenho acesso ao número 3 mais. O problema com isso é que eu não vou ser capaz de libertar aquele nó. Eu vou ter de vazamento de memória e (ininteligível) vai me odiar. Então, ao invés de fazer isso, eu provavelmente deveria ter um ponteiro temporário. Então eu coloquei temporária. Ele vai apontar para o nó que deseja excluir. E então eu posso mover os nós anteriores para apontar para o próximo nó do nó que deseja excluir. E, finalmente, eu posso liberar o ponteiro. Eu tenho que liberar o ponteiro que eu criei ali? Eu não tenho que, só porque - a diferença é que este nó foi criada usando malloc, por isso é na pilha, enquanto que este foi apenas declarado como um interruptor de NULL na pilha. Então, eu não tenho para libertá-la. Okay. Então, agora vamos falar sobre pilhas. As pilhas são bastante simples. Fizemos pilhas e filas na sala de aula apenas usando matrizes, mas você deve ser familiar - basta estar ciente que você também pode fazer pilhas em filas usando listas ligadas também. Então se você tem uma matriz, o que seria uma pilha? Uma pilha de, por um lado, terá de ter um tamanho. Você tem que armazenar o que é o tamanho da pilha que você tem agora. E também você teria um array, neste caso dos números, mas se você quiser, pode ser um array de cordas, uma matriz de struct, qualquer coisa que você deseja armazenar. Sobre a pilha: A diferença entre uma pilha e uma lista ligada é que na pilha só tem acesso ao elemento, que foi colocado na pilha. Chama-se em último lugar, primeiro a sair. Assim como você tem uma pilha de bandejas, se você colocar uma bandeja em cima da pilha, você tem que remover a bandeja primeiro a ter acesso às outras bandejas. É a mesma coisa com stacks. Então, se eu quiser, por exemplo, adicionar um elemento a uma pilha, o que devo fazer? É chamado de impulso, e é bastante simples. A primeira coisa que você tem a fazer é verificar se o tamanho da pilha não é maior ou igual à capacidade da pilha. Porque se você já estiver em plena capacidade, você não pode adicionar qualquer outra coisa. E, em seguida, se não, você só tem que adicionar o elemento à pilha. E, finalmente, incrementar o tamanho. Por isso, é bastante simples. Então, eu só adicionar o número 2. E se eu quiser aparecer, o que significa que eu quero remover o último elemento que foi adicionado e retornar o valor do elemento, a primeira coisa que tem que verificar é que a pilha não está vazia. Porque se ele está vazio, não posso retornar nada. Nesse caso, estou retornando -1. Caso contrário, eu vou diminuir o tamanho da especificação, e devolver os números (s.size). Por que eu diminuir o tamanho e, em seguida, retornar s.size? É porque, neste caso, a especificação tem tamanho 4, e eu quero devolver o quarto elemento, certo? Mas o que é o índice do quarto elemento? Três. Desde que eu size - vai ser 3, eu só posso retornar s.numbers (s.size) porque é 3. Então é só o índice. Agora filas. As filas são praticamente a mesma coisa. A única diferença é que em vez de ter passado in, first out, você tem first in, first out. Provavelmente, se você está esperando para ir a um concerto, você não seria feliz se você tivesse uma pilha ao invés de uma fila. Sendo a última pessoa a entrar seria a primeira pessoa a entrar no show. Você provavelmente não seria feliz. Na fila, a primeira pessoa a entrar é também a primeira pessoa a sair. Assim, na definição de uma fila de, além de ter o tamanho da matriz, você também tem que ter a cabeça, que é o índice para o chefe da pilha. Assim, o primeiro elemento no momento. Enqueue é a mesma coisa que o impulso para stacks. Se você fosse muito ingênuo, você teria apenas que dizer: bem, eu só posso fazer exatamente a mesma coisa que eu fiz por impulso. Eu posso apenas verificar se não é além da capacidade. Se for, eu return false, caso contrário, eu só posso exportar o novo valor e, em seguida, aumentar o tamanho. Mas por que isso é errado? Vejamos este exemplo. Estou tentando enfileirar um monte de coisas, e então eu vou para retirar da fila e enfileirar. Há um monte de comandos, mas é muito simples. Eu vou enfileirar 5, então adicionar 5 e 7, 1, 4, 6, e então eu quero desenfileirar alguma coisa, o que significa que eu estou indo para remover o primeiro elemento. Então, eu estou indo para remover o número 3, certo? O primeiro elemento. Okay. Agora, se eu tentar enfileirar outra coisa, o que vai acontecer? De acordo com a minha implementação, Eu ia colocar o próximo número na q.size índice. Neste caso, o tamanho é de 8, de modo que o índice de 8 estará aqui na última posição. Se eu tentar enfileirar um aqui, eu estaria substituindo a última posição para o número 1, o qual é completamente errado. O que eu quero fazer é embrulhar ao redor e ir para a primeira posição. Talvez você gostaria apenas de dizer, bem, eu só tenho que verificar se eu realmente pode colocar alguma coisa lá. Se não, eu acabei de dizer, oh, a nova capacidade total é realmente capacidade - 1, e você não pode colocar um elemento lá. Mas qual é o problema? O problema é que se eu apenas desenfileirar tudo aqui e depois eu tento acrescentar algo mais, seria apenas dizer: bem, você estava em plena capacidade, que é 0. Assim, a fila está desaparecido. Você tem que envolver em torno, e uma maneira de envolver em torno de que vocês aprenderam em Série de Exercícios visionários e outros estava usando mod. Você pode experimentá-lo em casa para entender por que você faria q.size + q.head capacidade de modificação, mas se você verificar aqui, podemos ver que ele funciona. Assim, no último exemplo, q.size foi de 8 e a cabeça foi de 1, porque foi aqui esta posição da matriz. Por isso, será 8 + 1, 9. Mod capacidade de 9 seria 0. Ele iria para o índice 0. Nós vamos estar na posição certa. E, em seguida, tentar a fila em casa. Algumas coisas importantes: tente entender a diferença entre uma pilha e uma fila. Em casa, para tentar obter muito familiarizado com a implementação de enfileiramento, dequeue, push e pop. E também entendo quando você usaria cada uma delas. Então vamos relaxar por 10 segundos, com um monte de Pokémons. E agora vamos voltar para estruturas de dados. Hash tabelas. Muitas pessoas estavam com medo de tabelas de hash. no conjunto de problemas 6, Corretor Ortográfico. As tabelas de hash e tentativas, muitas pessoas ficam com medo deles. Eles pensam que é tão difícil de entender. Sim? [Rob Bowden] Problema jogo 5. Problema ajuste 5, sim. Graças Rob. É. Seis era Huff n 'Puff, sim. Problema jogo 5 foi Ortográfico, e você tinha que usar uma tabela hash ou uma tentativa. Muita gente pensou que eles eram super difícil de entender, mas eles são realmente muito simples. O que é uma tabela hash, basicamente? Uma tabela é um conjunto de listas ligadas. A única diferença entre uma matriz e uma tabela hash é que na tabela de hash que você tem algo chamado de função hash. O que é uma função hash? Eu não sei se vocês podem ler aqui. Este é um exemplo de uma tabela de hash. Assim, você pode ver que você tem uma matriz com 31 elementos. E o que fazemos em uma tabela hash é ter uma função hash que vai traduzir uma chave, cada um int para um índice. Se, por exemplo, se eu quiser escolher para B. Harrison, Gostaria de colocar B. Harrison em minhas funções de hash, ea função de hash retornaria 24. Então eu sei que eu quero armazenar B. Harrison em 24. Então essa é a diferença entre ter apenas uma matriz e ter uma tabela hash. Na tabela hash você terá uma função que vai dizer onde armazenar os dados que você deseja armazenar. Para a função de hash, você quer olhar para uma função hash que é determinista e bem distribuída. Como você pode ver aqui, você vê que uma grande quantidade de dados que eu queria loja era na verdade 19 em vez de usar 31 e 30 e 29, que foram todos. Assim, a função de hash que eu usei não era muito bem distribuído. Quando dizemos bem distribuída, isso significa que queremos ter, aproximadamente, pelo menos, 1 ou 2 para cada uma das - como, uma diferença de 1 ou 2 para cada um dos índices nas matrizes. Você quer ter, aproximadamente, o mesmo número de elementos em cada lista encadeada na matriz. E é fácil de verificar se é válido na tabela de hash, ver como tabelas de hash. Então árvores. Esta é uma árvore. Árvores em ciência da computação estão de cabeça para baixo por algum motivo. Então, aqui você tem a raiz da árvore e, em seguida, as folhas. Você deve apenas saber a nomenclatura para os pais ea criança. Cada nó tem os seus filhos, que são os nós que estão abaixo do pai. Assim, por exemplo, 2, vai ser o pai para 3 e para a outra criança ali mesmo, enquanto 3 vai ser o pai de uma e as outras crianças que estão lá. E um vai ser 3 da criança, e assim por diante. Temos algo muito mais interessante, chamado de uma árvore de busca binária, em que todos os valores do lado direito de um nó vão estar à direita, aqui - na direita, vai ser maior do que o elemento da raiz. Então, se eu tenho o número 5 aqui, todos os elementos à direita vai ser maior que 5, e no lado esquerdo todos os elementos que vão ser inferior a 5. Por isso é útil? Bem, se eu quiser verificar se o número 7 está aqui, por exemplo, Acabei de ir a 5 primeiro e eu vou ver, é 7 maior ou menor que 5? É maior, então eu sei que vai ter que ser no lado direito da árvore. Então, eu tenho muito menos coisas para olhar. Na implementação de uma árvore de busca binária, o nó, eu só vou ter que ter dados, assim int n; você também pode ter uma string ou qualquer coisa que você queria. Você só tem que ter cuidado em definir o que é maior, o que for menor. Então se você tivesse cordas, por exemplo, você pode definir que todas essas coisas à direita vai ter comprimento maior, a esquerda vai ter comprimentos menores, por isso é realmente até você. Como posso implementar para encontrar BST? A primeira coisa que você tem a fazer é verificar se a raiz é NULL. Se for NULL, significa que a coisa não está lá porque você não tem sequer uma árvore, certo? Então eu retornar false. Caso contrário, eu vou verificar se o número é maior do que o valor da raiz. Vou tentar encontrar o elemento à direita da árvore. Você vê que eu estou usando recursão aqui. E então se for menos, eu vou olhar para a esquerda. E, finalmente, de outra forma, se não é menos ou não maior, isso significa que ele é o próprio valor. Então, eu só retornar true. Você pode ver aqui que eu usei, se, se, se. E lembre-se, no questionário 0, tivemos um problema que tinha, se, se, se, e você deveria encontrar a ineficiência, ea ineficiência foi que você usou se. Você deveria ter usado se, else if, else if e else. Então, eu deveria usar else if e else if e else aqui? Alguém - É mesmo? [Falando Student, inaudível] É ótimo. Então, ela está dizendo que não importa, só porque a ineficiência que tínhamos antes foi que, porque, talvez, se alguma condição foi satisfeita, para que você tenha realizado uma ação, mas então você ia verificar todas as outras condições. Mas, neste caso, ele retornou de imediato, por isso não importa. Então você não tem que usar else if. E, finalmente, vamos falar de tentativas, qual é o favorito de todos. A tentativa é uma árvore de matrizes. É muito rápido para procurar valores, mas usa muita memória. E é, geralmente, para filtrar as palavras, então quando você pretende implementar, por exemplo, eu não sei, como um livro de telefone em seu telefone e você quer ser capaz de tipo B e só tem nomes de pessoas que têm B. É muito fácil de implementar que o uso de uma tentativa, por exemplo. Como você define um nó em uma tentativa? Você apenas tem que ter um bool que vai ser is_word. Isso representa que a utilização de todos os personagens antes que o nó, que foram capazes de formar uma palavra, e então você vai ter uma matriz de ponteiros para os nós. Você pode ver que temos um conjunto de nós pai, então nó * array? Sim? Então, vamos ver como isso vai funcionar. Para a verificação ortográfica, temos uma matriz de 27 elementos, porque temos todas as letras mais o apóstrofo. Antes aqui eu só vou usar 2, porque eu quero ser capaz de escrever no quadro. Okay. Portanto, este é um exemplo de uma tentativa. Se eu definir o primeiro nó, eu vou ter uma matriz de dois elementos que são dois ponteiros para NULL, então eu só colocar 'a' e 'b'. E eu vou ter um booleano que diz is_word. Vai ser falso para o primeiro, apenas porque, antes de que você não tem quaisquer caracteres. Assim, uma palavra vazia não é uma palavra. Portanto, é falsa. Se eu quiser adicionar 'a' para este dicionário, o que eu tenho que fazer? Eu teria apenas que malloc um novo nó para 'a', e, em seguida, adicionar a sua palavra como verdadeira. Por isso, apenas representa que ter 'a' vai ser verdade. Faz sentido? Então, se eu quiser adicionar 'ba', eu vou ter que malloc 1 para 'b', e então eu vou para configurar o boolean como false, porque 'b', por si só não é uma palavra. Então eu estou indo para malloc outro para 'a', então 'ba', e então eu vou montar é uma palavra de verdade. Porque 'ba' é uma palavra. E então, se eu quero ver se 'b' é neste dicionário, Eu posso ir para o primeiro, 'b'. Eu descer, e eu olhar é palavra, e ela diz que falsa. Portanto, não é uma palavra. Se eu quiser conferir 'ba', Eu vou para o primeiro, 'b', e em seguida ir para 'a', e eu vejo verdade, por isso é uma palavra. Faz sentido? Muitas pessoas ficam confusas com tentativas. Não? Finalmente, codificação Huffman. Codificação de Huffman é muito útil para economizar memória e comprimir arquivos de texto, só porque um monte de vezes que você usa 'a' e 'e', ​​por exemplo, em seus documentos, mas eu não sei se vocês usam 'q' ou 'z' tanto. Tendo apenas 1 byte para cada personagem, cada - os 256 caracteres que temos na tabela ASCII não é muito melhor, só porque existem alguns personagens que você usa muito mais, então você provavelmente deve usar menos memória para aqueles. Como faço para usar o código de Huffman? Temos que fazer uma árvore de Huffman.  Uma árvore de Huffman tem nós que tem um símbolo que vai ser como, 'a', 'b', 'c', a carta, a letra que você tem, uma freqüência que é a freqüência com que a palavra aparece no texto, que você estava criando a árvore de Huffman para, e, em seguida, um nó que vai para apontar para a esquerda da árvore Huffman e outro nó que vai apontar para a direita. Assim como uma árvore. Como você constrói uma árvore de Huffman? Você vai escolher os dois nós que têm as freqüências mais baixas. Se você tem um laço que vai escolher os 2 nós que têm os valores mais baixos, bem ASCII. Em seguida, você vai criar uma nova árvore fora dessas 2 nós que vai ter a frequência combinados no nó pai. E então você está indo para remover os dois filhos da floresta e substituí-los com o pai. E você vai repetir isso até que você só tem uma árvore na floresta. Então, vamos ver como você faria uma árvore Huffman para ZAMYLA. Você pode ver aqui que todas as cartas têm freqüência 1, exceto para 'A'; que tem freqüência 2. Então, eu criei nós para todas as letras que eu coloquei em ordem de valor ASCII e frequência. Então, se eu quiser criar a primeira árvore, será com 'L' e 'M'. Então é aqui. A freqüência do par será 2 porque é 1 + 1, então o próximo 2 com as freqüências mais baixas são 'Y' e 'Z'. E então eu tenho todos eles ser - têm uma frequência de 2. Então, quais são os que têm o valor ASCII menor para o próximo? 'A' e 'L'. Então eu criar o novo nó, e, por fim, é 4 e 2, então 2 vai ser do lado esquerdo. E esta é a árvore de Huffman. Então, se eu quero escrever algum texto, como em binário para converter em texto, usando a árvore de Huffman é muito fácil. Por exemplo, se eu digo que a mudança para a esquerda é a 0 e se movendo para a direita é um 1, O que é que vai representar? Assim como 1, 1, portanto, direita, direita, e, em seguida, 0, de modo que seria deixado G, e, em seguida, 1, 0, 0. Então, 1, 0, assim apenas 1, 0, 'A'. E, em seguida, 0, 1, de modo que "Z". E, em seguida, 1, 0, 0 - nenhum. 0, 0 será 'Y', de modo preguiçoso. Então, isso é tudo para mim, Rob vai assumir. [Rob Bowden] Assim, a semana 7 coisas. Temos muito a passar por cima muito rápido. Operadores bit a bit, buffer overflow, Biblioteca CS50, em seguida, HTML, HTTP, CSS. Tudo como em 15 a 20 minutos. Operadores bit a bit. Há seis deles que você precisa saber. Bit a bit e, bit a bit OR, XOR, deslocamento à esquerda, deslocamento para a direita, e não. Direito mudar e não você mal viu em palestra em tudo. Nós vamos passar por isso rapidamente aqui, mas é bom saber que estes são os 6 que existe. Lembre-se que os operadores bit a bit é como quando você faz 3 + 4. Você não está lidando com o binário de 3 e 4. Com operadores bit a bit na verdade você está lidando com os bits individuais dos números 3 e 4. Então, o primeiro que vamos dizer é bit a bit não, e tudo que faz é inverter todos os bits. Então, aqui, se você está escrevendo isso em C, você não escrevê-lo como ~ 11011 ou qualquer outra coisa, você poderia escrevê-lo como ~ 4, e, em seguida, ele iria virar a representação binária de 4. Então, aqui, ~ de um número binário 1101101 vai virar exatamente todos os 1 do que 0 e todos os 0 de 1 de. Como eu disse lá, o uso freqüente desta, e nós vamos vê-lo em um pouco, é como nós queremos chegar a algum número onde todos os bits são 1, com exceção de um deles. Por isso, é geralmente mais fácil de expressar o número onde apenas aquele único bit é definido, e, em seguida, tomar o ~ dele, então todos os outros bit é definido, exceto por isso. Então é isso que nós vamos usar mais um pouco. OR bit a bit. Aqui estão dois números binários, e esses 2 números são bastante representativo, uma vez que representam todas as possíveis combinação de bits que você precisa para operar. Aqui, quando eu clicaria cada bit, nós apenas estamos indo para comparar diretamente para baixo. Assim, no lado esquerdo, temos um 1 e um 1. Quando eu bit a bit | aqueles, o que é que eu vou conseguir? Uma. Em seguida, bit a bit | 0 e 1 que vai me dar? Uma. Bit a bit 1 e 0, vai ser a mesma coisa, um. Bit a bit 0 | 0 vai me dar 0. Assim, o único caso em que eu recebo 0 é no 0 | 0 caso. E você pode pensar que, assim como seus prefeitos lógicas. Então, se você pensar em 1 como verdadeiro e 0 como falso, a mesma coisa se aplica aqui. Tão verdadeiro ou verdadeiro é verdadeiro, verdadeiro ou falso é verdadeiro. Falso ou verdadeiro é verdadeiro, falso ou falso é a única coisa que é realmente falso. Aqui está o exemplo que você deve saber como um bom exemplo de quando operadores bit a bit são usados. Aqui se ou 'A' maiúsculo com OX20, e vamos olhar para isso em um segundo, temos alguma coisa. E se nós ou minúsculas 'a' com OX20, temos alguma coisa. Então, vamos puxar para cima da tabela ASCII. Okay. Aqui vemos que 'A' é - aqui temos 'A' é decimal 65. Mas eu vou com hexadecimal, que é Ox41. Certeza que vimos em sala de aula. Eu acho que nós vimos em sala de aula que é muito fácil converter de hexadecimal para binário. Então, aqui, se eu quiser colocar 4 em binário, que só vai ser 0100. Este é um lugar de, lugar de 2, 4 do lugar, por isso este é 4. Então eu posso dividir 1 em binário, que vai ser 0001. E assim é que isto vai ser a representação de 'A' em binário. Levando em minúsculas 'a', é agora vai ser Ox61, onde, dividindo-se estes em seu binário, de modo a 6 - Vamos realmente fazê-lo - que não há borracha? Eraser. Ox61. Então, dividindo 6 em binário vai ser 0 + 4 + 2 + 0. E a divisão 1 vai ser 0001. Olhando para a diferença entre estes dois, vemos que a única diferença entre uma letra minúscula e um 'A' maiúsculo é este único bit. Então, voltando para aqui - tudo bem. Voltando aqui, se olharmos para o que o bit é OX20, OX20 assim dividindo-se em seu binário, é 0010, 0000. OX20, o único bit que está definido é este pouco que estamos preocupados com, com a alternância entre capitais e minúsculas 'a'. Se eu ou 'A', que é um presente, 'A', se eu ou 'A' com OX20, o que é que eu vou conseguir? [Student, inaudível] Minúsculas 'a', porque ele vai virar este bit para 1. E se eu ou 'a' com OX20, o que é que eu vou conseguir? Minúsculas um, porque só oring 'a' com OX20, Eu só vou ser oring este único bit para 1, que já está a 1, por isso não importa. Então, nós temos 'a' e 'a'. Bit a bit e. Mais uma vez, podemos pensar nisso como nossa contrapartida lógica e. No lado esquerdo temos verdadeiro e fiel. Vai ser verdade, e para todos os casos, falso e verdadeiro ou verdadeiro e falso, ou falso e falsa, nenhuma dessas coisas são verdadeiras. Então, o que acaba ficando é 1000. Então, agora, aqui, aqui é onde eu usei o bit a bit de confiança não, onde tivemos OX20. Portanto, esta é OX20. Agora o que eu quero fazer, bit a bit ~ de OX20. Isso vai inverter todos os bits. Então, eu tenho 1101, 1111. E assim 'A' anded com ~ OX20 vai me dar o que? A única parte que realmente precisamos pensar é um presente, uma vez que, se todos esses bits são definidos a 1, então nós estamos indo para obter exatamente o que 'A' é, exceto, talvez, o que isto é pouco. Porque se fosse a 1, agora que vai ser definido para 0, porque tudo o que isso é, anded com isso vai ser 0. Então o que é 'A' & ~ OX20 vai me dar? [Os estudantes respondem, inaudível] E o que é 'a' e - é 'A'. E o que é 'a' & ~ OX20 vai me dar? 'A.' Porque este é atualmente a 1. Anding com este 0 vai torná-lo um 0, e agora estamos indo para obter um 'A'. Ambos são 'A', e por último, mas não menos importante deste tipo, temos XOR. É muito parecido, ou, exceto que significa exclusivamente ou. Este é parecido com o que você costuma pensar em como ou no mundo real. Então você quer 'x' ou 'y', mas não ambos. Aqui 1 ^ 1 vai ser 0. Porque a verdadeira, isto é - ele não funciona tão bem com o lógico verdadeiro e falso como bit a bit & e ou fazer, mas é verdade ^ verdadeiro é falso. Porque nós só queremos retornar true se apenas um deles é verdadeiro. Assim, um ^ 1 é 0. E quanto a 0 ^ 1? É 1. 1 ^ 0 é de 1, 0 ^ 0 é 0. Assim, em todas as circunstâncias, bit a bit 0 0 algo vai ser 0. 1 bit a bit algo 0 ou 0 1 bit a bit, se é | ou ^, vai ser a 1, e se for e ele vai ser 0. E o único caso em que um bit a bit 1 não é um é com a exclusiva ou. Isso é 0110. Então, aqui, agora, usando XOR - então estamos de volta a 20. 'A' ^ OX20 é esses 2 bits que estamos comparando. Assim, a 1 ^ 0 vai me dar uma coisa? A uma. 'A' ^ OX20 vai me dar? Minúsculas a. 'A' ^ OX20 vai me dar? Capital A. Porque tudo o que isso está fazendo, este XORing com OX20 é efetivamente lançando tudo o que este bit é. Se este for um 0, ele agora vai se tornar um 1. Uma vez que este é um 1, 1 ^ 1 é 0. Portanto, a nossa 'a' tornou-se 'A', e nossa 'A' tornou-se 'a'. Então XOR é uma maneira muito conveniente de apenas lançando o caso. Você só quer iterar sobre uma seqüência de letras e alternar o caso de cada personagem, você só XOR tudo com OX20. Agora nos resta turno. Deslocamento à esquerda é apenas vai, basicamente, empurrar todos os números para, ou para a esquerda, e inserir 0 de trás deles. Portanto, temos aqui 00001101. Vamos empurrar 3 0 do da direita, e nós temos 01101000. Em termos não binários, vemos que isso está realmente lidando 13 com 3 deslocou-esquerda, que nos dá 104. Então deslocamento à esquerda, vemos aqui, x << y é basicamente x * 2 ^ y. 13 * 2 ^ 3, 2 ^ 3 a 8, de modo que 13 * 8 é 104. Se você só pensar em binário, em geral, como cada um dígito, se começarmos a partir da direita, é a 1 do lugar, então a 2 do lugar, então a 4 do lugar. Então, empurrando 0 do da direita, estamos apenas empurrando as coisas que estavam no 4 do lugar para o 8 de lugar, e as coisas que estavam no 8 de lugar para lugar, a 16 de. Cada turno apenas multiplica por 2. Sim? [Estudante] O que acontece se você desviado por 5? [Bowden] Se você desviado por 5, você só iria perder dígitos. Inevitavelmente, é a mesma coisa. Como, inteiros são apenas 32 bits por isso, se você adicionar dois realmente grandes inteiros, ele simplesmente não se encaixa em um inteiro. Então, é a mesma coisa aqui. Se você trocou por 5, teríamos apenas perder essa. E isso é o tipo de coisa que eu quero dizer com "mais ou menos", onde se você mudar muito, você perde bits. Mudança direito vai ser o oposto, onde vamos enfiar 0 de fora da final, e para os nossos propósitos, preencha 0 do da esquerda. Então, fazendo isso, estamos basicamente reverter o que já tinha feito. E nós vemos que os três 0 na direita acabaram caído, e nós ter empurrado o 1101 todo o caminho para a direita. Isto faz 104 3, que é, de forma eficaz, x / 2 ^ y. Então, agora, aqui, é uma idéia similar. Por que é apenas cerca de x / 2 ^ y, e na verdade não x / 2 ^ y? Porque se eu tinha mudado por 4, eu teria perdido a 1. Basicamente, o que você pensar, apenas pensar em divisão inteira em geral. Assim, como 5/2 é 2. Não é 2.5. É a mesma idéia aqui. Quando dividimos por 2, podemos perder pedaços estranhos ao longo do caminho. Então agora - é isso para bit a bit. Isso é tudo que você precisa saber. Lembre-se os casos de uso que vimos em sala de aula, como uma máscara de bits é útil para operadores bit a bit, ou você usá-los para máscaras de bits. As letras maiúsculas e minúsculas, conversões é um exemplo bastante protótipo. Ok, então ataques de buffer overflow. Alguém se lembra o que estava errado com esta função? Repare que nós declaramos um array de 12 bytes, 12 caracteres, e depois copiar para o nosso buffer de 12 caracteres de todo o bar string. Então, qual é o problema aqui? O número mágico 12 deve aparecer praticamente imediatamente como - por que 12? E se bar passa a ser mais de 12 caracteres? E se bar é milhões de personagens? Aqui a questão é memcpy. Se a barra é o suficiente, ela só vai completamente - 'c', 'c' não se importa que ele tinha apenas 12 caracteres; 'C' não se importa que ele não pode caber que muitos bytes. Ele irá substituir apenas completamente char, os 12 bytes que já alocados para ele, e tudo passado, na memória que na verdade não pertencem a esse tampão com o que o bar string é. Portanto, esta foi a imagem que vimos em sala de aula onde temos a nossa pilha crescendo. Você deve ser usado para estas imagens ou se familiarizar com eles novamente. Nós temos a nossa pilha crescendo, endereços de memória começam em 0 no topo e crescer até gosto 4 bilhões na parte inferior. Nós temos a nossa disposição 'c' em algum lugar na memória, então temos o nosso ponteiro para barrar direita por baixo, e então temos este ponteiro quadro salvos em nosso endereço de retorno e pilha da nossa rotina pai. Lembre-se que o endereço de retorno é? É quando principal chama uma função foo, chama uma barra de funções, inevitavelmente, barrar retornos. Então, quando a barra de volta, eles precisam saber que ele vai voltar para a foo que o chamou. Assim, o endereço de retorno é o endereço da função que ele tem que voltar para quando a função retorna. A razão pela qual isso é importante para ataques de estouro de buffer é porque, convenientemente, hackers gostam de mudar o endereço de retorno. Em vez de voltar para foo, eu vou voltar para onde quer que o hacker quer que eu vá voltar. E, convenientemente, onde o hacker freqüentemente quer voltar para é o início do buffer que tinha originalmente. Então, observe, novamente, Little Indian. O aparelho é um exemplo de um sistema indiano pequeno, assim um número inteiro ou um ponteiro é armazenado com os bytes invertidos. Então, vamos ver - é isso? É. Vemos Ox80, OxC0, Ox35, OxO8. Lembre-se dos dígitos hexadecimais? Nós não inverter os dígitos hexadecimais em Little Indian, porque dois dígitos hexadecimais compõem um único byte, e inverter os bytes. É por isso que não armazenam, como, 80530CO8. Nós armazenar, em vez disso, cada par de dois dígitos, a partir da direita. Esse endereço refere-se ao endereço do início do nosso buffer que nós realmente queria copiar para, em primeiro lugar. A razão que é útil porque, o que se o atacante aconteceu, em vez de ter uma sequência que era apenas uma seqüência de como inofensivo, o seu nome ou algo assim, E se, ao invés, essa seqüência foram apenas algumas de código arbitrário que fez tudo o que queria fazer? Assim, eles poderiam - Eu não posso pensar em nenhum código legal. Poderia ser qualquer coisa, no entanto. Qualquer código desastroso. Se eles quisessem, eles poderiam simplesmente fazer algo em falhas segmentos, mas isso seria inútil. Eles costumam fazer isso para invadir seu sistema. Okay. Biblioteca CS50. Isto é, basicamente, getInt, getString, todas essas funções que nós fornecemos para você. Portanto, temos de char string *, e essa é a abstração que surpreendeu em algum momento durante o semestre. Lembre-se que uma string é apenas um conjunto de caracteres. Então, vamos ver uma versão resumida do getString. Você deve olhar para trás, ele se lembrar de como ele é realmente implementado. Detalhes importantes são, observe que recebemos em um único caractere de cada vez de padrão em, que é como nós digitando no teclado. Assim, um único personagem de cada vez, e se conseguirmos muitos personagens, por isso, se n + 1 é maior do que a capacidade, então precisamos aumentar a capacidade do nosso buffer. Então, aqui estamos dobrando o tamanho do nosso buffer. E isso continua acontecendo, nós inserir o caractere em nosso buffer até que recebamos uma nova linha ou fim de arquivo ou qualquer outra coisa, neste caso, estamos a fazer com a corda e, em seguida, o verdadeiro getString encolhe a memória, como se nós alocados muita memória ele vai voltar e encolher um pouco. Então, nós não mostram isso, mas a idéia principal é ele tem que ler em um único personagem de cada vez. Ele não pode simplesmente ler em uma coisa toda de uma vez, porque o seu tampão é apenas de um certo tamanho. Então, se a string que ele tenta inserir em buffer é muito grande, então seria transbordar. Então vamos evitar isso por apenas lendo em um único caractere de cada vez e cada vez maior, sempre que precisar. Então getInt e as outras funções da biblioteca CS50 tendem a usar getString nas suas implementações. Então, eu destaquei as coisas importantes aqui. Ele chama getString para obter uma string. Se getString não conseguiu voltar para a memória, lembre-se que getString mallocs alguma coisa, então sempre que você chamar getString você não deve (ininteligível) grátis essa seqüência que você tem. Então, aqui, se ele não conseguiu malloc algo, voltamos INT_MAX como apenas uma bandeira que, hey, nós não estávamos realmente capaz de obter um número inteiro. Você deve ignorar o que eu voltar para você, ou você não deve tratar isso como uma entrada válida. Finalmente, assumindo que teve sucesso, nós usamos sscanf com essa bandeira especial, o que significa, em primeiro lugar corresponder a um número inteiro, então combinar quaisquer caracteres após esse inteiro. Então, observe que queremos igual a 1. Retornos Então sscanf quantos jogos se fez com sucesso? Ele irá retornar 1 se combinava com sucesso um número inteiro, ele irá retornar 0 se ele não corresponder a um número inteiro, e ele irá retornar 2 se correspondesse um número inteiro seguido por algum personagem. Então, observe que tenta novamente se nós combinamos nada, mas 1. Portanto, se entrou 1, 2, 3, C, ou 1, 2, 3, X, em seguida, 1, 2, 3 que são armazenados no número inteiro, X que ficam armazenados no personagem, sscanf voltaria 2, e gostaríamos de tentar novamente, porque nós só queremos um inteiro. Soprando rapidamente através de HTML, HTTP, CSS. HyperText Markup Language é a estrutura ea semântica da web. Aqui está o exemplo de aula onde temos tags HTML. Temos tags de cabeça, marcas no corpo, temos exemplos de tags vazias onde nós realmente não têm um começo e perto tag, só temos link e imagem. Não há tag de imagem de fechamento; há apenas uma única marca que realiza tudo o que a etiqueta deve fazer. O link é um exemplo, nós vamos ver como você vincular a CSS, o roteiro é um exemplo de como você ligar para um JavaScript externo. É bastante simples, e lembre-se, HTML não é uma linguagem de programação. Aqui, me lembro como você definiria uma forma ou pelo menos o que isso faria? Essa forma tem uma ação e um método. Os métodos que você só vai ver são GET e POST. Então GET é a versão em que a coisa é colocado na URL. POST é onde ele não é colocado na URL. Em vez disso, todos os dados do formulário é inserido mais escondido na solicitação HTTP. Então, aqui, a ação define onde a solicitação HTTP vai. Onde ele vai é google.com / search. Método. Lembre-se as diferenças entre GET e POST, e, diga apenas como um exemplo, se você deseja marcar alguma coisa. Você nunca será capaz de marcar um URL POST , porque os dados não são incluídos na URL. HTTP, agora, é HyperText Transfer Protocol. O Protocolo de Transferência de Hipertexto, você esperaria que transferir HyperText Markup Language, e ele faz. Mas também transfere todas as imagens que você encontra na Web, todos os downloads que você faz começar como uma solicitação HTTP. Então HTTP é apenas a linguagem da World Wide Web. E aqui é preciso reconhecer este tipo de uma solicitação HTTP. Aqui HTTP/1.1 no lado apenas diz que é a versão do protocolo que estou usando. É praticamente sempre vai ser HTTP/1.1, como você vai ver. Então nós vemos que isso era GET, a alternativa de ser POST, que você pode ver. E a URL que eu estava tentando visitar foi www.google.com/search?q = blah, blah, blah. Então lembre-se que este, o ponto de interrogação q = blá blá blá, é o tipo de material que é enviado por um formulário. A resposta que ele poderia voltar a me seria algo parecido com isso. Mais uma vez, começando com o protocolo, que vai ser isso, seguido pelo código de estado. Aqui é 200 OK. E, finalmente, a página da web que eu realmente pedi será seguido. A possível código de status que você pode ver, e você deve saber vários deles. 200 OK, você provavelmente já viu antes. 403 Proibido, 404 Not Found, Error 500 Internal Server geralmente é se você vai a um site e algo está quebrado ou seus acidentes de código PHP, enquanto que no aparelho, temos que grande caixa de laranja que vem e diz, como, algo está errado, este código não funciona ou isso é ruim função. Normalmente sites não querem que você saiba quais as funções são realmente ruins, assim, em vez eles vão apenas dar-lhe 500 Internal Server Errors. TCP / IP é uma camada sob HTTP. Lembre-se que não há Internet fora da World Wide Web. Como se você jogar um jogo online que não passa por HTTP, ele está passando por um diferente - ele ainda está usando a Internet, mas ele não usa o HTTP. HTTP é apenas um exemplo de protocolo construído sobre TCP / IP. IP significa Internet Protocol, literalmente. Cada computador tem um endereço IP, que são essas coisas de 4 dígitos como 192.168.2.1, ou o que, que tende a ser um local. Mas esse é o padrão de um endereço IP. Assim, o DNS, Domain Name Service, isso é o que se traduz coisas como google.com para um endereço IP real. Então, se você digitar esse endereço IP em uma URL, que iria levá-lo para o Google, mas você tende a não se lembrar dessas coisas. Você tende a se lembrar google.com em seu lugar. A última coisa que temos é portos, onde esta é a parte de TCP IP. TCP faz mais. Pense, como, você ter o seu navegador em execução web. Talvez você tenha algum aplicativo de e-mail está sendo executado; talvez você tem algum outro programa que utiliza a Internet em funcionamento. Todos eles precisam de acesso à Internet, mas o computador só tem uma placa Wi-Fi ou o que seja. Assim, os portos são a maneira que nós somos capazes de dividir como esses aplicativos são capazes de usar a Internet. Cada aplicativo obtém uma porta específica que possa escutar, e, por padrão, HTTP usa a porta 80. Alguns serviços de e-mail usar 25. Os de baixa de número tendem a ser reservados. Você geralmente são capazes de obter os com numeração mais alta para si mesmo. CSS, Cascading Style Sheets. Páginas web Nós estilo com CSS, não com HTML. Existem 3 lugares que você pode colocar o seu CSS. Ele pode ser in-line, entre marcas de estilo, ou em um arquivo separado e, em seguida, completamente ligado dentro E aqui é apenas um exemplo de CSS. Você deve reconhecer esse padrão, onde o primeiro exemplo é que estamos combinando a tag corpo, e aqui estamos centrando a tag body. O segundo exemplo, estamos combinando a coisa com ID de rodapé, e estamos aplicando alguns estilos para isso. Observe que o ID de rodapé de texto alinha à esquerda, enquanto alinha texto corpo central. Rodapé está dentro do corpo. Será, em vez disso, text-align esquerda, mesmo que o corpo diz centro text-align. Esta é toda a parte em cascata dela. Você pode ter - você pode especificar estilos para o corpo, e depois as coisas no corpo que você pode especificar estilos mais específicos, e as coisas funcionam como o esperado. Especificadores CSS mais específicas têm precedência. Eu acho que é isso. [Ali Nahm] Olá a todos. Se eu pudesse chamar sua atenção. Estou Ali e eu vou passar por PHP e SQL muito rápido. Assim, podemos começar. PHP é curto para PHP: Hypertext Preprocessor. E como todos vocês devem saber, é uma linguagem de script do lado do servidor, e usá-lo para o back-end de sites, e como ele faz um monte de cálculos, a parte por trás cenas. Syntax. Não é como C, surpresa, surpresa. Ele sempre tem que começar com a, se você pode ver, o - eu não posso seguir em frente. Você pode ver o que você precisa os novos tipos de aparelhos e, em seguida, você também precisa do? Php. Isso é sempre como você tem que enquadrar o texto PHP, seu código PHP. Portanto, não pode ser igual a C, onde o tipo de colocá-lo em primeiro lugar. Você precisa cercar-lo sempre. E agora, a maior sintaxe é que todas as variáveis ​​precisa para começar com o caractere $. Você precisa fazê-lo quando você está definindo-os, você precisa fazê-lo quando você está se referindo a eles mais tarde. Você sempre precisa que US $. É o seu novo melhor amigo, muito bonito. Você não - ao contrário de C, você não precisa colocar que tipo de tipo de variável que é. Então, enquanto você precisa fazer o $, você não precisa colocar, como, int x ou y corda, etc, etc. Então, uma pequena diferença. Como resultado disto, significa que o PHP é um tipo fracamente. PHP é uma linguagem de tipo fracamente, e tem variáveis ​​fracamente digitado. Em outras palavras, isso significa que você pode alternar entre os diferentes tipos de tipos de variáveis. Você pode armazenar seu número 1 como um int, você pode armazená-lo como uma string, e você pode armazená-lo como um float, e tudo o que vai ser o número 1. Mesmo que você esteja armazenando-o em diferentes formas, ainda é - os tipos de variáveis ​​ainda estão segurando no final. Então, se você olhar aqui, se você se lembrar de pset 7, muitos de vocês provavelmente teve problemas com isso. Dois sinais iguais, três sinais de igual, 4 sinais de igual. Ok, não há quatro sinais de igual, mas existem 2 e 3. Você pode usar dois sinais de igual para verificar os valores. É possível verificar em todos os tipos. Então, se você pode ver no primeiro exemplo, Tenho num_int num_string ==. Portanto, o seu int e sua seqüência são ambos, tecnicamente, 1, mas são tipos diferentes. Mas para os dois iguais, ainda vou passar. No entanto, para os três iguais, verifica valor, bem como os diferentes tipos. Isso significa que ele não vai passar nesse segundo caso aqui, onde você estiver usando três sinais de igual em seu lugar. Então, isso é uma grande diferença que você deve tudo têm mostrado agora. Concatenação de String é outra coisa poderosa que você pode usar em PHP. É basicamente esta a notação de ponto à mão, e é assim que você pode ligar cordas juntos. Então se você tem gato e você tem cão, e você quer colocar as duas cordas juntas, você pode usar o período, e isso é tipo de como ele funciona. Você também pode simplesmente colocá-los ao lado do outro, como você pode ver aqui no exemplo de fundo, onde eu eco seqüência 1, corda espaço 2. PHP saberá para substituí-los como tal. Arrays. Agora, em PHP, existem dois tipos diferentes de matrizes. Você pode ter matrizes regulares, e você também pode ter arrays associativos, e nós vamos passar por eles agora. Matrizes regulares são apenas isso em C, e por isso você tem índices que são numerados. Agora estamos indo só para criar um e colocá - então é assim que criar uma matriz vazia, então vamos posto no número de índice 0. Nós vamos colocar o número 6, o valor 6. Você pode vê-lo na parte inferior aqui. Where's - pelo número de índice 1, vamos colocar o número valor 4, e assim você pode ver que há um 6, há um 4, e então, como estamos imprimindo coisas, quando tentamos e imprimir o valor armazenado no número de índice 0, então vamos ver o valor 6 sendo impresso. Legal? Então, isso é matrizes regulares para você. Outra forma que você também pode adicionar coisas para matrizes regulares agora é que você pode simplesmente anexá-los no final. Isso significa que você não tem que especificar o índice específico. Você pode ver o número e, em seguida, entre colchetes não há nenhum índice especificado. E vai saber - PHP saberá apenas adicioná-lo ao final da lista, o próximo lugar livre. Assim você pode ver o 1 ali, naquele 0 spot, o 2 foi para a direita lá no primeiro lugar. O 3 vai - é adicionado lá também. Então, esse tipo de faz sentido. Você só está constantemente adicionando-lo, e então, quando estamos exibindo o índice de número 1, ele irá imprimir o valor 2. Então temos matrizes que são arrays associativos. As matrizes de associação, em vez de ter índices numéricos, o que eles fazem é, eles têm índices que estão por string. Você pode ver, em vez de - Eu me livrei de todos os índices numéricos, e agora é key1, key2, key3, e eles estão entre aspas para significar que eles estão todos os strings. Assim, podemos ter um exemplo disso. O exemplo disso é que temos o tf, e isso é o nome do índice. Vamos colocar "Ali", como o nome, no índice, calorias ingeridas, podemos colocar um int desta vez em vez de uma string, e depois para os gostos de índice, podemos colocar uma matriz inteira dentro dela. Portanto, esta é uma espécie de - é um conceito semelhante à forma como tivemos índices com números, mas agora nós podemos mudar os índices em torno de para tê-los como strings em vez. Você também pode fazer isso, além de apenas fazê-lo individualmente, você pode fazer tudo em um só pedaço. Assim você pode ver que tf desse array, e, então, colocá-los todos em um conjunto gigante colchete. Assim que pode acelerar as coisas. É mais do que uma escolha estilística que não. Temos também loops. Em C temos laços que trabalham assim. Tivemos a nossa matriz, e fomos de índice 0 para o final da lista, e nós imprimi-lo de tudo, certo? Exceto o problema é que, para arrays associativos, não necessariamente sabe aqueles índices numéricos porque agora temos os índices de cordas. Agora usamos loops foreach, que, mais uma vez, você esperançosamente usados ​​em pset 7. Loops foreach só vai saber cada parte da lista. E ele não tem que saber exatamente o índice numérico que você tem. Então você tem a sintaxe foreach, por isso é foreach, você coloca a matriz. Assim, a minha matriz é chamado pset, e depois como, a palavra como, e então você coloca esta variável temporária local que você vai usar apenas para a coisa específica que vai segurar o específico - uma instância ou uma seção da matriz. Pset num vai realizar 1, e então talvez ele vai segurar o número 6, e, em seguida, que irá realizar o número 2. Mas está garantido para passar por cada valor único que está na matriz. Funções úteis que você deve saber em PHP são o exigirem, de modo que torna-se de que você está incluindo determinados arquivos, eco, saída, vazio. Eu recomendo que você olhar para pset 7 e olhar para essas funções. Você pode ter que saber quem, então eu definitivamente sei o que, exatamente, aqueles que estão fazendo. E agora vamos passar por escopo muito rapidamente. Em âmbito, o PHP é um tipo de coisa funky, ao contrário de C, e por isso estamos indo só para passar por isso rapidamente. Então, digamos que começamos naquela seta que temos lá. E vamos começar com $ i. Assim, a variável 'i' vai ser 0, e nós apenas estamos indo para mantê-imprimi-lo na medida em que grande caixa branca por lá. Nós vamos começar com i0, e então nós estamos indo para representá-la. Portanto, há a 0. E então nós estamos indo para incrementa-o com o laço para, e, em seguida, ele vai ser o valor de 1. Um deles é menor do que 3, então ele vai passar por isso para loop, e, em seguida, vamos vê-lo impresso novamente. Nós estamos indo para incrementá-lo novamente a 2, e 2 é inferior a 3, por isso vou passar o loop for, e ele vai imprimir a 2. Em seguida, você vai notar que 3 não é inferior a 3, por isso vamos sair do loop for. Então, agora nós saiu, e então nós estamos indo para ir em AFunction. Okay. Então você tem que notar que esta variável que criamos, a variável 'i', não tem como escopo localmente. Isso significa que não é local para o loop, e essa variável ainda pode acessar e alterar depois, e ainda vai ser eficaz. Então, se você vai para a função de agora, você vai ver que nós também usamos o 'i' variável, e vamos incrementar 'i' + +. Você pensaria que, num primeiro momento, com base em C, que é uma cópia do 'i' variável. É uma coisa totalmente diferente, o que é correto. Então, quando nós imprimi-lo, vamos imprimir 'i' + +, que vai imprimir que 4, e, em seguida, vamos - desculpe. Então vamos acabar fora dessa função, e nós estamos indo para estar onde a seta é agora. Isso significa que, em seguida, no entanto, mesmo que a função alterado o valor de 'i', não se alterou fora da função, porque a função tem um escopo separado. Isso significa que quando nós echo 'i', não mudou no âmbito da função, e assim, em seguida, vamos para imprimir 3 novamente. Diferentes coisas sobre escopo em PHP do que em C. Agora em PHP e HTML. PHP é usada para tornar as páginas web dinâmicas. É algo que faz coisas diferentes. Nós temos que é diferente de HTML. Com HTML, que sempre só tem a mesma coisa estática, como a forma como Rob mostrou, enquanto o PHP, você pode mudar as coisas com base em quem é o usuário. Então, se eu tiver isso, eu, "Você está logado como -" e, em seguida, o nome, e eu posso mudar o nome. Então, agora o nome é José, e tem o "sobre mim", mas então eu também posso mudar o nome para ter Tommy. E isso seria uma coisa diferente. Então nós também podemos mudar as coisas diferentes sobre ele, e ele vai mostrar conteúdo diferente com base no nome. Então PHP pode tipo de mudar o que está acontecendo em seu site. O mesmo aqui. Ainda assim, note que eles têm conteúdo diferente, mesmo que você está tecnicamente ainda acessar essa mesma página da web na superfície. Gerando HTML. Existem 2 maneiras diferentes que você pode fazer isso. Então, nós vamos passar por isso agora. A primeira forma é, você tem - sim, muito. Então você acabou de ter o seu regular para laço em PHP, e então você ecoar em PHP e HTML echo fora. Usando o que Rob lhe mostrou de script HTML e em seguida, usando a impressão PHP apenas imprimi-lo para a página de web. O caminho alternativo é fazê-lo como se você separar o PHP e HTML. Assim, você pode ter uma linha de PHP que inicia o loop for, então você pode ter a linha do HTML em uma coisa separada, e então você terminar o loop, mais uma vez, com um PHP. Então, é uma espécie de separá-lo para fora. No lado esquerdo, você pode que você tem todo o - é apenas um pedaço de PHP. À direita, você pode ver que você tem uma linha de PHP, você tem uma linha de HTML, e você tem uma linha de PHP novamente. Assim, separando-o para fora o que estão fazendo. E você vai notar que de qualquer forma, para qualquer um deles, eles ainda imprimir a imagem, a imagem, a imagem, de modo que o HTML ainda é impresso da mesma forma. E então, você ainda vai ver as 3 imagens aparecem em seu site. Portanto, é de 2 maneiras diferentes de fazer a mesma coisa. Agora temos formas e solicitações. Como Rob mostrou você, existem formas de HTML, e vamos apenas brisa através deste. Você tem uma ação e você tem um método, e sua ação tipo de mostra onde você está indo para enviá-lo, eo método é se ele vai ser um GET ou um POST. E um pedido GET, como disse Rob, significa que você está indo para colocá-lo em uma forma e você vai vê-lo como uma URL, enquanto uma solicitação POST você não vai ver em uma URL. Então, uma pequena diferença. No entanto, uma coisa que é uma coisa semelhante é que POST e GET são igualmente inseguro. Assim, você pode pensar que, só porque você não vê-lo na URL, isso significa que o POST é mais seguro, mas você ainda pode vê-lo em seus cookies nas informações que você está enviando. Então, não acho que cerca de um ou de outro. Outra coisa a notar é que você também tem variáveis ​​de seção. Vocês usaram esta em pset 7 para obter a sua informação ID de usuário. O que aconteceu foi que você pode usar essa matriz associativa, o $ _SESSION, e então você é capaz de acessar coisas diferentes e armazenar coisas diferentes através das páginas. A última coisa é que temos SQL, Structured Query Language, e esta é uma linguagem de programação para gerenciar bancos de dados. O que, exatamente, são bancos de dados? Eles são coleções de tabelas, e cada tabela pode ter tipos semelhantes de objetos. Então, tivemos uma mesa de usuários em seu pset finanças. E por que eles são úteis? Porque é uma forma de armazenar permanentemente a informação. É uma maneira de rastrear coisas e administrar as coisas e realmente vê-lo em diferentes páginas e manter o controle. Enquanto que se você apenas armazená-lo em um momento que imediato e usá-lo mais tarde, você não será capaz de acessar qualquer coisa que você salvou. Temos 4 coisas importantes que utilizamos para comandos SQL. Temos select, insert, delete e update. Essas são realmente importante para vocês para saber para o seu quiz. Vamos rapidamente sobre selecione agora. Basicamente, você está selecionando linhas de um banco de dados. Então, se você tem, bem aqui - temos estas duas coisas diferentes, e queremos selecionar da tabela de aulas onde incrível - onde na coluna incrível o valor é 1. Assim você pode ver aqui, temos essas duas coisas do nome da classe, CS50 e Stat110, e temos os IDs de classe e do slogan. Por isso, queremos selecionar todas essas informações. Então você pode ver aqui que é uma espécie de escolher dessa coluna incrível, onde todas as coisas são um, e então ele tem a classe ID, nome da classe e slogan que ele pode escolher. Como exatamente você fazer isso no código? Você tem que usar PHP. Então, esse é o tipo de como PHP e SQL são relacionados uns aos outros. Agora temos o nosso código, e vamos usar a nossa função de consulta como fizemos no pset 7, e nós estamos indo para executar a consulta SQL. Então nós vamos ter - a gente sempre tem que verificar se o triplo igual de linha se falsa. Então, novamente, você quer verificar o tipo eo valor, e, em seguida, se não funcionar, então você quer se desculpar, como de costume, como fizemos no pset 7. Caso contrário, você quiser percorrer tudo com aqueles acessíveis foreach loop que nós apenas passou. Agora que estamos loop e temos conseguido vencer, vamos supor que a nossa consulta passou, agora temos o nosso loop foreach. E a primeira linha tem, então aqui está a linha, aqui, é encaixotado. Vai imprimir toda a informação que é chegado. Então, ele vai imprimir na parte inferior "Wanna Saiba HTML?" Então está indo para ir para a próxima linha, porque está concluído o primeiro ciclo for, e assim, em seguida, ele vai imprimir a segunda linha do mesmo, que vai ser STAT110, Localizar todos os momentos. Uma última coisa é sobre as vulnerabilidades de SQL. Eu sei que David tocou neste um pouco na aula. Você pode ler mais tarde. É muito engraçado. SQL Injection é um tipo de coisa complicada. Digamos que você se ater apenas essas variáveis ​​para a direita em sua consulta, como você pode ver nessa primeira linha. Assim, parece bem, certo? Você está apenas colocando o nome de utilizador e senha para sua consulta SQL, e você quer enviá-lo fora e conseguir tudo o que está na sua tabela de dados. Isso parece bastante simples. Então, digamos que alguém coloca em, para a senha, este ou texto aqui - realmente deve ser na caixa vermelha. Então, vamos dizer que eles colocaram essa senha em - que é o que eles entram. Então, eles estão colocando ou "1" = 1. Uma espécie de senha boba de ter. Agora vamos substituí-lo, e você vai notar que nessa consulta SQL agora, avalia para sempre verdadeiro, porque você vai notar que você pode consulta SQL selecionar todas essas informações ou você pode apenas ter 1 = 1. De modo que sempre vai avaliar para true. Isso não vai realmente funcionar, porque isso significa que o hacker pode invadir seu sistema. A solução para isso é que você tem que usar o sistema de DOP, o que significa que você tem que usar pontos de interrogação, que é o que vocês usados ​​na pset 7, onde você está indo para usar um ponto de interrogação no lugar de onde você quer colocar alguma coisa, e então você vai ter uma vírgula, e então você vai ter depois, depois de sua seqüência, as diferentes variáveis ​​que você deseja substituir no seu ponto de interrogação. Então, você vai notar que agora eu tenho esses pontos de interrogação vermelhos. Então eu coloquei as variáveis ​​após minhas cordas, então eu sei que substituí-los nessa ordem depois. Isso irá certificar-se de que, se alguém faz isso assim, e eles têm o ou 1 = 1 situação, que irá certificar-se, no final de volta, certifique-se que ele não vai realmente quebrar a consulta SQL. Ok, então isso é muito bonito isso, um turbilhão de PHP e SQL. Boa sorte para todos vocês, e agora para Oregon [Oreoluwatomiwa Babarinsa] todos Okay. Tempo para percorrer algumas JavaScript e algumas outras coisas muito rapidamente, então nós não prendê-lo esta noite. JavaScript. Sim. JavaScript é uma espécie de coisa legal, supostamente. As coisas que você realmente precisa saber sobre JavaScript, é mais ou menos como o fim do lado do cliente do que o seu aplicativo web vai estar fazendo. Há algumas coisas que você simplesmente não querem cuidar de todo o tempo no lado do servidor. Todas as pequenas interações, com destaque para uma coisa, fazer algo desaparecer. Você realmente não quero ter que falar com o seu servidor de todo o tempo para isso. E alguns que nem sequer é possível fazer no lado do servidor. É por isso que precisamos de algo como JavaScript. Coisas legais sobre JavaScript: Ele é digitado de forma dinâmica. O que isto significa é que o seu programa não precisa saber o que, exatamente, as variáveis ​​são quando você escrevê-lo. Vai apenas uma espécie de descobrir como ele está correndo. Outras coisas que são legais sobre isso: É uma linguagem de chaveta, o que significa que a sintaxe é semelhante a C e PHP. Você não tem que fazer muito retrabalho quando você está aprendendo JavaScript. Aqui temos um pouco de JavaScript. Uma coisa interessante aqui é que, se você olhar para ele, nós temos um pouco de JavaScript ali na marca de cabeça. O que é que é, basicamente, basta incluir um arquivo JavaScript. Esta é uma maneira que você pode incluir JavaScript em seu programa. Em seguida, o segundo pouco é realmente alguma JavaScript inline, muito semelhante a um estilo em linha com CSS, e você está apenas escrevendo alguns códigos muito rapidamente lá. JavaScript tem arrays. Apenas uma outra maneira de manter os dados ao redor, muito útil. Muito agradável e fácil de sintaxe. Você pode usar colchetes para acessar tudo e manter tudo junto. Nada muito complexo. A coisa legal sobre JavaScript e linguagens de script em geral é que você não precisa se preocupar com tamanhos de matriz. Você pode apenas usar array.length e manter o controle do mesmo, e também a matriz pode crescer ou encolher como você precisa dele. Assim, você não precisa nem se preocupar com qualquer tipo de, oh não, eu preciso alocar mais coisas, ou qualquer coisa assim. O legal aqui é que o JavaScript tem algo chamado objetos. É uma linguagem orientada a objeto, então o que ele tem é, essencialmente, uma maneira de você para agrupar dados em conjunto, algo semelhante a uma estrutura, mas você pode acessá-la como uma estrutura ou em uma sintaxe de array associativo. É muito simples e que você pode fazer com isso é agrupar dados juntos se você tem um monte de dados que está relacionado. Porque é tudo o que você precisa para descrever um carro, você não precisa tê-lo em um monte de lugares diferentes. Você pode simplesmente colocá-lo em um objeto em JavaScript. Como você provavelmente sabe, a iteração é uma daquelas tarefas tediosas. Você só faz isso através de uma outra vez. Você precisa falar com todos os objetos no carro, ou você precisa passar por cada item em uma lista ou algo parecido. Então tem JavaScript, semelhante ao PHP, uma sintaxe foreach. Neste caso, é um no loop. Você quer usar isto só em objetos. Existem alguns problemas que ocorrem se você usar isso em matrizes. De modo geral, é uma daquelas coisas que, no entanto, que é muito útil, porque você elimina um monte de sobrecarga porque você não tem que puxar tudo ao seu objeto por si mesmo. Você não tem que se lembrar de todos os nomes-chave. Você só tipo de levá-los de volta nesta sintaxe. Neste, por, você só quer lembrar que você está recebendo de volta todas as chaves, de uma forma muito semelhante ao de hash de tabela. Se você se lembrar de que, quando você iria colocar em uma string você pode tirar algo que tem um valor associado com ele. O que você pode fazer com isso é que você pode dizer, tudo bem, Eu coloquei em um carro, e eu chamei-lhe um Ferrari. Então você pode colocar na cadeia de Ferrari novamente mais tarde, e você pode tirar isso. E você pode fazer isso em um loop, com o no loop. Então, só mais sobre objetos. A principal coisa a partir desta é preciso lembrar é que você pode usar o objeto struct como sintaxe sempre que quiser com estes, exceto se o que você vai usar como uma string não é um nome de variável válido. Então, se você olhar para isso aí, temos chave com espaços. Bem, se você fosse para colocar object.key, espaço, com, espaço, espaços, que simplesmente não faria sentido sintaticamente. Assim, você só pode fazer isso com este tipo de sintaxe suporte. Além disso, JavaScript é muito âmbito-wise para PHP. Você tem duas formas de abordar escopo. Você não pode ter o var na frente de uma variável, e isso apenas significa que este é global. Você pode vê-lo de qualquer lugar. Mesmo se você colocar isso em uma instrução if, em qualquer outro lugar no seu código depois desse ponto, você poderia ver essa variável. Outra coisa, porém, é com a var, é limitada a qualquer função que você está dentro Se você não estiver em uma função, bem, é global. Mas se você estiver em uma função é apenas visível dentro dessa função. Eu não tenho um exemplo, mas, sim. É uma daquelas coisas onde você pode gerenciar o que as variáveis ​​que você quer ser global, que as variáveis ​​que você quer ser local, mas você precisa ter cuidado com isso, porque você não tem o tipo de controle de grão fino que você faz em C, onde se algo é declarado em um loop for, ele vai ficar nesse loop for. A única coisa que realmente se preocupam com o uso de JavaScript é a manipulação de páginas web, certo? Quero dizer, é por isso que estamos fazendo isso. Para fazer isso, usamos algo chamado DOM. O Document Object Model. Basicamente, o que ele faz é que leva todo o seu HTML e modelos lo para fora em um monte de objetos que são aninhados uns dentro dos outros. Você começa com algo como isto. Você tem, por certo, para mim, um monte de código lá fora, que é uma espécie de - Você poderia pensar que seria muito difícil de manipular, porque você estaria analisando através de um monte de texto e ter a peça à parte as coisas. E se não foi formatado corretamente? Coisas ruins aconteceriam. Então JavaScript cuida disso para você, e você terá uma estrutura de dados bom, como a que à minha esquerda, onde você só tem um documento, e dentro de que você tem algo chamado HTML, e dentro de que você tem uma cabeça e um corpo, e dentro dessa cabeça que você tem um título, etc, etc, etc. Isso simplifica a manipulação de uma página da web para que seja justo, oh, eu só quero falar com esse objeto. Espécie de uma forma muito semelhante você falaria para outro objeto que você fez a si mesmo. Como eu disse, tudo o DOM é o objeto de documento. Ou é apenas um lugar e então você pode ir dentro dele para encontrar as coisas, e você pode fazê-lo - este é o velho estilo de fazer isso, lá em cima, onde você faz document.getElementById, e, em seguida, o nome, e como você provavelmente pode dizer, isso fica muito pesado depois de um tempo. Então você provavelmente não quer fazer isso. É por isso que nós temos a próxima coisa que nós vamos falar sobre isso depois. O importante aqui é que, tudo bem, você tem todos esses elementos, certo? Então talvez eu possa mudar a cor de alguma coisa quando a página é carregada. Então o que? E se o meu usuário clica em alguma coisa? Eu quero que ele faça algo interessante quando clicam alguma coisa. É por isso que temos eventos. Você pode, basicamente, encontrar qualquer elemento em seu DOM, e depois dizer, hey. Quando este carrega ou alguém clica nele, ou quando do mouse sobre ele, fazer algo com ele. E o que você tem é, você tem funções que lidam com isso para você. Estas funções são manipuladores de eventos. O que eles - que é apenas uma maneira elegante de dizer, esta função só é executada quando o evento acontece. Então, ele lida com o evento que ocorre. Isto é como você colocar para fora um manipulador de eventos. Tenho alguma tecla, e quando você clicar nele, ele explode. Portanto, não clique no botão. Esta é uma maneira de abordá-lo, certo? Você tem uma marca de botão e clique em que você tem uma seqüência que diz: oh, a propósito, eu faço essa coisa explodindo para mim. Caso contrário, é como um botão regular, você acabou de fazer. Você também pode fazer isso de outra forma, agarrando o elemento DOM, mas vamos guardar isso depois falamos sobre jQuery. JQuery: É uma biblioteca que é cross-browser. Você pode usá-lo em praticamente qualquer coisa. E isso só lhe dá um monte de ferramentas para trabalhar. Porque JavaScript, enquanto poderoso, não tem todas as ferramentas que você precisa fora da caixa para realmente enfrentar uma aplicação web que você pode querer fazer. Assim, ele simplifica um monte de coisas, dá-lhe um monte de funções fora da caixa que você normalmente tem que escrever mesmo, uma e outra e outra vez. E só torna as coisas muito simples. Você também tem seletores, que permitem que você tirar todos esses elementos de seu DOM muito mais simples, em vez de ter que usar essas chamadas de função muito longos. Mais informações sobre esses seletores. Você tem, lá em cima você tem, digamos Eu quero começar um elemento com o ID "rock". Bem, em jQuery, que é de apenas US $ e, em seguida, uma seqüência que tenha um quilo, e, em seguida, "rock". É muito simples e muito mais rápido do que a maneira tradicional de JavaScript resolução deste problema. E você tem coisas semelhantes para as classes e tipos de elementos. jQuery é - um dos recursos interessantes é que você pode classificar de comprimir as suas dúvidas sobre o seu DOM muito, muito rápido. Agora estamos de volta para o tratamento de eventos, e isso é como você lidaria com um evento em jQuery. Então, o que vamos aqui é que estamos dizendo, tudo bem. Eu tenho uma tag script, certo? Então, eu tenho essa linha JavaScript. O que nós vamos fazer é que vai dizer, tudo bem. Quando o documento estiver pronto, o que significa que o documento foi carregado, estamos indo para ir a essa função, e vamos dizer, tudo bem, esta função está realmente fazendo alguma outra coisa. É basicamente dizendo, tudo bem, me o elemento com o ID "myid". E, em seguida, dar a este um manipulador função que é executado quando você clica nele. Basicamente o que isto significa é, diz, tudo bem. A página é carregada, por isso estou indo para dentro, encontrar este elemento, dar-lhe esse manipulador de eventos, e que basicamente define a sua página para você. E é assim que você quer pensar sobre a manipulação de eventos. Você só quer pensar, tudo bem, quando ocorre alguma coisa, o que eu quero que aconteça? Você não quer pensar, tudo bem, eu preciso ter certeza de que esta coisa fala com essa coisa, essa coisa de blá blá blá, porque você só quer falar coisa em termos de eventos. Quando isto acontece, isso acontece. Quando isso acontece, o que acontece. E se as coisas desencadear outras coisas, isso é ótimo. Mas você não quer tentar fazer código complicado onde você está provocando várias coisas ao mesmo tempo, porque você está indo só para dar-se uma dor de cabeça. Tudo bem. Agora podemos começar a nossa página de lidar com eventos, mas digamos que o meu usuário clica em um botão. E se eu quiser enviar o pedido de volta ao servidor, mas eu não quero recarregar a página, porque ter que recarregar uma nova página cada vez que fica meio entediante, e por que eu preciso para puxar para baixo o cabeçalho de novo, e de novo o rodapé, e todos os elementos da página de novo só para refrescar o cumprimento ou o tempo todo? Então é por isso que temos algo como Ajax. O que podemos fazer aqui com Ajax é que podemos dizer, tudo bem, Eu quero enviar alguns dados para o servidor, e eu quero ter uma resposta de volta para que eu possa atualizar minha página, ou talvez apenas fazer alguns cálculos algorítmicos que não necessariamente mostrar nada para o usuário. O que você precisa fazer isso? Bem, você precisa de um URL que você precisa para conversar. O servidor não pode magicamente ouvir do nada. Você precisa ter um lugar específico que você está enviando os dados para. E você também precisa de alguns dados para enviar, ou talvez seja uma consulta sem dados. Você só quer fazer o ping de volta para o servidor e dizer: ei, eu estou vivo, ou algo parecido. E então você quer uma função que lida basicamente com sucesso. Vamos dizer que você receber de volta algumas informações do seu servidor, e você quer mudar o título do usuário em sua página. Assim, você terá a informação de volta, e você teria que empurrar para a tela. O que acontece é que, quando a página está pronta, você criar um em função de clique para este botão chamado saudação. O que isto faz é então, quando esse botão é pressionado, você fala com greetings.php, você faz uma solicitação POST, e você diz, hey, me algo de sua página. Nós realmente não precisa descrever isso, mas greetings.php, vamos apenas dizer, dá de volta "Olá mundo". Assim que voltarmos este "Olá mundo", e no sucesso deste, assumindo nada der errado, então basta ir a este lugar-alvo que nós especificamos e se ater apenas a resposta lá. E esta é uma maneira muito simples de configurar uma consulta Ajax. Muito rapidamente, Rob tipo de mencionado isso já, as coisas podem dar errado, coisas ruins podem acontecer, assim que você quer para se familiarizar com esses códigos de resposta HTTP. O que são estes são apenas, como, 200, tudo correu bem. Outra coisa, as coisas ruins aconteceram. Em geral, é a coisa que você quer se lembrar. Mas é bom saber que todos estes. E, finalmente, uma vez que já passou por tudo isso, precisamos falar muito rapidamente sobre o projeto, e então podemos deixar que todos sair. Projeto. Coisas que você quer se lembrar. Pergunte a si mesmo estas perguntas: Quem vai usar isso? O que eles vão usá-lo para? O que meus usuários se preocupam? O que não se preocupam? Você só não quer fazer um aplicativo e deixá-lo apenas crescer e tornar-se este gigante, que tudo consome coisa que você não pode mesmo terminar. Você quer ter objetivos distintos planos e coisas que você quer abordar. Torná-lo sem esforço. Tudo isso, diz, basicamente, tornar mais fácil para o usuário a utilizá-la, não torná-lo uma bolha gigante de texto como este slide é, na verdade. Você só quer que ele seja algo que é muito fácil para alguém para ir em e fazer o que eles querem fazer. Você não quer que eles tenham para navegar 5 páginas para chegar ao seu principal função do seu site. Se o Google tinha 5 páginas antes mesmo que pudesse pesquisar alguma coisa, ninguém iria usá-lo. E, por último, o protótipo de papel, grupo focal. Tenha um bom design e práticas de teste. Só porque você acha que ele funciona para você, não significa que os outros pensam que funciona. Mas sim, é isso. [CS50.TV]