[Música tocando] ROB BODEN: Tudo bem. Então, a primeira coisa em primeiro lugar, de vídeo a partir de um rosto familiar. [REPRODUÇÃO] -Tudo bem. Este é CS50, e este é o início da semana três. Me desculpe, eu não poderia estar lá com você hoje, mas permita-me apresentar Próprio Rob Boden do CS50. [FIM REPRODUÇÃO DE VÍDEO] [Aplausos e exclamações] ROB BODEN: A filmografia em esse vídeo é fantástico. Tudo bem. Então, primeiro, há um outro almoço. É amanhã às 1:15. Não há almoço nesta sexta-feira. É com Quora. E Tommy não está aqui ainda, mas um dos as pessoas de lá é o ex-CF cabeça, Tommy McWilliam. Então, ele é um cara divertido. Você deve vir. Tudo bem. Então, na semana passada, começamos quebrando sobre o que uma seqüência realmente é. Nós nos conhecemos desde o início que é uma seqüência de caracteres. Mas na semana passada, que investigou o fato que o que é realmente uma seqüência de caracteres, bem, agora temos arrays de caracteres. E nós sabemos que uma seqüência, é uma matriz de caracteres, no final, temos este byte especial nulo, este invertida 0, que indica o final de a corda. E assim uma string é um array de caracteres, mas podemos ter mais do que apenas uma matriz de caracteres, que pode ter uma matriz de qualquer tipo de coisa que nós queremos. Então, se você se lembra da semana passada, o Programa Idade que David introduziu muito rapidamente. Então a primeira coisa que vamos fazer é pedir ao usuário para um número inteiro, o número de pessoas na sala. Uma vez que temos esse inteiro, estamos declarando um array. Observe esta sintaxe suporte. Você vai se acostumar com isso. Então, nós estamos declarando um array de inteiros chamado idades, e existem n inteiros nessa matriz. Portanto, este padrão aqui, este 4 int i é igual a 0, i é menos do que n, i além plus, que também vai ser um padrão que você começa muito acostumado. Porque isso é muito bonito como você está sempre vai iterar sobre matrizes. Assim lembrar que n é o comprimento da nossa matriz. E aqui, estamos pedindo repetidamente para a idade da pessoa i na sala. Depois disso, nós vamos para baixo, e por qualquer razão arbitrária, que, em seguida, imprimir quantos anos eles vão ser um ano a partir de agora. E correr esse programa, vamos fazer as idades, dot idades Slash. Assim, o número de pessoas na sala, digamos que há três. E dizem, a primeira pessoa é de 13, em seguida é 26, e o último é 30. Então ele vai interagir sobre os três pessoas, imprima 14, 27 e 31. Então lembre-se que, quando se declarar um matriz de tamanho n, em que os índices matriz, a matriz tem valores e índices de 0, 1, 2, todo o caminho até n menos 1. Assim, quando nos disse que havia três pessoas na sala, e nós colocamos aqui a primeira iteração através desta loop, i vai ser 0. Assim, no índice 0. Estamos atribuindo o primeiro idade que o usuário digita. Então, na próxima, estamos entrando na segundo n o usuário digita, e em ao lado de dois, os últimos n. Então percebe que uma matriz de tamanho três não tem nada no índice de três. Este não é válido. Tudo bem. Então, vamos voltar aqui. Portanto, agora que você lidou com matrizes, temos alguma familiaridade. Agora vamos passar para o comando argumentos de linha, que vão ser muito relevante para este conjunto de problemas. Então, até agora, sempre que você tem declarou a sua principal função, temos disse void main int. Então vazio significa apenas que não estamos passando qualquer argumentos para esta função. Agora vamos ver que o principal pode levar alguns argumentos. Aqui vamos chamá-los int argc e cordas suportes argv. Os suportes, mais uma vez, indicando que estamos lidando com matrizes. Então, aqui, suportes de corda argv, estamos lidar com um conjunto de cordas. Então argc, que vai indicar quantos argumentos temos passado para este programa. E para ver o que isso significa, vamos fechar isso. OK. Então, até agora, nós funcionamos todos programa como idades de barra de pontos. Podemos também, na linha de comando, o passado passar argumentos, assim, a prazo, de comando argumentos de linha. Assim, o primeiro argumento, Olá mundo. Então, aqui, argc seria três. É a contagem dos argumentos na linha de comando. Argc é sempre pelo menos um, uma vez que do ponto reduzir as idades, em si, é considerada como um dos os argumentos de linha de comando. Então Olá é a primeira. Se as idades barra de pontos é o zeroth, então Olá é a primeira, e é o mundo segundo argumento de linha de comando. Assim, o argv corda, vamos ver, contém a cordas, barra dot idades, Olá, e do mundo. E, ao pedido de Davi, vamos para reproduzir um vídeo introduzindo isso. [REPRODUÇÃO] -Até agora, em programas que já escrito, nós declaramos principal void main como int. E todo esse tempo, esse vazio tem simplesmente foi especificando que a programa não tomar qualquer Argumentos da linha de comando. Em outras palavras, quando um usuário executa um programa, ele ou ela pode fornecer comando argumentos de linha escrevendo adicional palavras ou frases depois do programa nome no prompt. Bem, se você quer que seu programa para ter argumentos de linha de comando, um ou mais dessas palavras, precisamos substituir anular com um par de argumentos. Então, vamos fazer isso. Incluir CS50.h. Incluir io.h. padrão Int principal. E agora, em vez de vazio, eu vou especificar um int argc chamado, e um matriz de strings chamado argv. Agora, argc e argv são simplesmente convenções. Poderíamos ter chamado esses argumentos mais qualquer coisa que quisermos. Mas o que é importante é que argc é um int porque, por definição, é indo para conter o número de argumentos, a número de palavras no total, que o usuário digitou em seu alerta. argv, entretanto, o argumento do vetor, é vai realmente ser uma matriz armazenar todas as palavras que o usuário tem digitado no seu alerta. Vamos continuar a fazer algo agora com uma ou mais destas Argumentos da linha de comando. Em particular, vamos em frente e imprimir qualquer palavra que o usuário digita após o nome do programa no prompt. Abrir suporte. Fechar suporte. Por cento Printf s barra invertida e vírgula. E agora eu preciso dizer que valor printf para ligar a esse espaço reservado. Eu quero que a primeira palavra que o usuário tem digitado após o nome do programa, e então eu vou para especificar argv suporte 1, perto parênteses, ponto e vírgula. Agora, por um suporte e não o suporte 0? Bem, ao que parece, armazenados automaticamente em argv 0 vai ser o nome real do programa. Assim, a primeira palavra que o usuário digita após o nome do programa é, por convenção, vai ser armazenado em argv 1. Vamos agora compilar e executar este programa. Faça argv 0, ponto barra argv 0. E agora uma palavra como Olá. Enter. E aí temos que, Olá. [FIM REPRODUÇÃO DE VÍDEO] ROB BODEN: Tudo bem. Feche essa. Então, dando uma olhada no que o programa que nós apenas apresentado a nós, bem, apenas para mostrar, se imprimir argv 0, fazer, agora o que é isso, argv 0, ponto barra argv 0. Então, como seria de esperar, está imprimindo a nome do programa, uma vez que argv 0 é sempre vai ser o nome do programa. Mas vamos fazer algo um pouco mais interessante. Assim, no conjunto de problemas, você será introduzida para esta função, atoi. Então o que vamos usar atoi para? Isso vai converter um string para um inteiro. Então, se eu passar a corda, um, dois, três, para atoi, que vai converter esse para o número inteiro, um, dois, três. Então, nós estamos indo para converter o primeiro argumento de linha de comando para um inteiro, e depois é só imprimir esse inteiro. Então, basicamente, nós somos tipo de reimplementar getInt, apenas o inteiro é inserido no comando linha, em vez de no programa interativamente. Então, fazendo argv 0, vamos fazer ele aqui, e fechar isso. Então, correndo argv 0, e vamos entrar no inteiro, um, dois, três, quatro, um, dois. Então, ele vai imprimir o número inteiro, um dois, três, quatro, um, dois. Há algumas sutilezas para que atoi ele vai parar de se preocupar com nada além de um caractere numérico válido, mas isso não importa. Então, o que você acha que acontece se eu fizer isso? Falha de segmentação. Então, por que isso? Se você olhar para trás, o nosso programa, estamos convertendo argv 1, o primeiro argumento após o nome do programa, para um inteiro. Mas não há nenhum argumento passado após o nome do programa. Então, aqui, vemos que este é um buggy programa, uma vez que, se tentar executá-lo sem nenhum argumento, ela só vai falhar. Então, um outro padrão comum você verá é algo como, se argc é menos do que dois, o que indica que não houve , pelo menos, o nome do programa e uma primeiro argumento, então vamos fazer alguma coisa como printf, não o suficiente Argumentos da linha de comando. Isso provavelmente não é uma boa para imprimir, provavelmente é alguma coisa, como você deve digitar um número inteiro na linha de comando. Eu vou acabar com ela lá. E, em seguida, retornar 1. Então lembre-se que no final da nossa programa, se retornar 0, esse tipo de indica sucesso. E principal também automaticamente retorna 0 se não o fizer. Então, aqui, estamos afinando novamente 1 para indicar que isso não é sucesso. E você pode devolver o que quiser, apenas, 0 indica sucesso, e qualquer outra coisa que indica falha. Então, vamos executar esta versão das coisas. Então, agora, se não entrar em uma linha de comando argumento, ele vai dizer corretamente nós, não é suficiente linha de comando. Não terminou a frase. Outra coisa, se realmente passar um, ele pode completar o programa. Então é assim que você usaria em argc Para validar o número de argumentos de linha de comando que são realmente passou. Então, vamos tornar este programa um pouco mais complicado, e olhar para a segunda iteração das coisas. Então, agora, nós não estamos apenas a impressão do primeiro argumento de linha de comando. Aqui, nós estamos interagindo de iguais i int 0, i é menos de argc, i além plus, e impressão argv, o índice i. Portanto, este padrão, mais uma vez, este é o mesmo padrão como antes, exceto em vez de chamar a variável n, estamos usando argc. Portanto, esta é a iteração sobre cada índice na matriz, e imprimindo cada elemento dessa matriz. E assim, quando executar este programa, bem como, Eu não entrar em qualquer linha de comando argumentos, por isso apenas impressões o nome do programa. Se eu entrar em um monte de coisas, ele vai imprimir um, cada um em sua própria linha. OK. Então, vamos dar um passo adiante. E em vez de imprimir cada argumento em sua própria linha, vamos imprimir cada caráter de cada argumento em sua própria linha. Então lembre-se que é argv uma matriz de strings. Então, o que é uma string, mas um conjunto de caracteres? Então isso significa que argv é realmente uma de uma matriz de caracteres. Então, aproveitando que, vamos ignorar isso por enquanto. Vamos considerar apenas a string argv 0. Portanto, se queremos trazer cada personagem de argv 0 em sua própria linha, então eu quero de fazer o padrão que estamos acostumados a, i é menos do que o comprimento da matriz, que aqui, é de strlen, isso é não o que eu quero fazer, corda s é igual a 0 argv. Assim, i é inferior ao comprimento do nosso matriz, que neste caso é uma matriz de caracteres, i plus plus. E assim, como vimos na semana passada, é ideal se mover que strlen fora da condição, uma vez que n vai adicionar o strlen de s cada vez que vamos através do laço, e é não vai estar mudando. Então, vamos defini-lo igual a n aqui. OK. Então, agora, nós estamos interagindo sobre cada índice do array. E assim, se queremos imprimir cada caráter nesse array, cento c é a bandeira que queremos usar para os personagens. E agora eu suporte vai ser o corda, personagem índice i, por isso, se o corda foram Olá. então s 0 vai ser h, s suporte 1 e será, e assim por diante. Então, agora queremos combinar essas duas coisas. Queremos imprimir cada personagem de cada argumento de linha de comando. Então, nós vamos ter um aninhados para loop. E convencionalmente, o primeiro contador é i, o próximo vai ser j, n será o strlen de argv i, i é menor do que n, i, mais além. E agora em vez de imprimir argv i, então argv suporte i vai para o índice - que vai ser a linha de comando i-th argumento, argv i, j vai ser o personagem de jth o argumento de i-th. Vou me livrar desse aqui agora uma vez que colocá-lo em que loop. Então, é equivalente a iguais string s argv i, e, em seguida, s suporte j. Bem, não precisa declarar este s variável. Em vez disso, vamos combinar estes dois em o que tínhamos, argv i, j. Speaker 1: [inaudível]. ROB BODEN: Boa chamada. Portanto, este é quebrado. Se eu realmente correu, teríamos já perceberam isso. Assim, o contador que me interessa neste particular, para loop é j, o iterador. Então você teria corrido em questões, provavelmente um loop infinito, se nós Não tinha fixado que. É por isso que também estamos falando sobre depuração de hoje. OK. Então, vamos executar este programa. E vamos realmente adicionar um printf separado aqui que só vai imprimir uma outra linha, uma vez que isso significa que quando executar o programa, haverá um espaço em branco linha entre cada personagem do cada argumento de linha de comando. Bem, vamos ver o que isso significa. Oop. Tem algum bug. Erro implicitamente declarando função de biblioteca strlen. Então, voltando para o nosso programa, eu esqueci de botar incluem string.h. Então string.h vai ser o arquivo de cabeçalho que declara a função strlen. OK, ele compila. Agora, vamos executá-lo. Então, só isso. Vai imprimir a nossa nome do programa, Olá mundo. Vai imprimir cada coisa, cada um personagem, em sua própria linha. OK. Então, vamos realmente tomar esta um passo adiante. E em vez de usar string.h, vamos pensar sobre como iríamos implementar nossa própria função strlen. Então, eu vou dar imediatamente a assinatura da função. Então, vamos chamar my_strlen, e é vai levar uma string como argumento, e esperamos para voltar a comprimento dessa corda. Então, onde é esse cara? Sim. OK. Então lembre-se a partir do slide anterior que Foi também a partir da semana passada, que um array de caracteres, bem, uma string, então vamos dizer que esta é a nossa cadeia s. Portanto, se s é a string, Olá, então, H-E-L-L-O, na memória, que vai ser, em seguida, esta barra invertida 0 caráter. Então, como podemos obter o comprimento de s? Bem, o truque é olhar para este repercutiria 0 personagem, este nulo terminator. Assim, o algoritmo Vai para ser algo como poucos caracteres suficientes que - vamos ter esta mão representam alguns contador, vamos chamar isso de comprimento int. Assim, a partir de aqui, nós somos vai interagir sobre nossa string. Assim, o primeiro personagem, é H, e ele não está de volta reduzir 0, portanto, o comprimento é 1. Iterate para o próximo caractere, E, e não é barra invertida 0. O comprimento é 2. G, 3. L, 4. Ó, 5. E, finalmente, chegamos a barra invertida 0, e assim que isso significa, também, esta string é longo. Então, vamos voltar 5. Então, na verdade, a implementação que, em primeiro lugar, meu comprimento n é igual a 0, a minha mão direita. E vamos fazer uma iteração - COLUNA 1: [inaudível] ROB BODEN: Oh, atirar. Boa chamada. Lança. Assim, o comprimento n igual a 0. Então, agora, comprimento, enquanto S não igual e, em seguida, barra invertida 0. Então lembre-se, esta barra invertida 0, é uma personagem real, e indica o fim da string. Assim como, também, de barra invertida n é um personagem real. Barra invertida 0 vai para indicar o fim da nossa string. Eu não quero colocar isso lá. E enquanto s indexados pelo comprimento não é igual ao terminador nulo, então nós apenas estamos indo para incrementar comprimento. Então, no final do nosso programa, comprimento é, eventualmente, vai 5 ser neste caso. E nós vamos comprimento basta retornar. OK. Então, agora aqui, eu não fazer my_strlen. Vamos compilá-lo para certificar-se tudo corra bem. Eu estava fazendo em 2? Ou foi um? Isso deve fazer. Tudo bem. Portanto, esta é argv 2. Funciona como previsto, embora foi a de que o que eu fiz isso em? Sim. OK. Esta versão das coisas que não tinha a nova linha printf depois, mas não faz qualquer diferença. OK. Assim funcionou como esperado. Agora podemos até combinar um passo mais longe, onde aviso aqui, bem, primeiro, nós estamos pegando o strlen de argv i, e então nós estamos iterando cada personagem nessa string. Então, ao invés de fazer isso, o que se apenas combinar essa lógica de esperar até chegarmos barra invertida 0 direito neste loop for? Então iteração enquanto argv i, j faz não é igual barra invertida 0. Então, vamos executá-lo pela primeira vez. Tudo bem. Então, aqui, esta condição está dizendo - vamos esclarecer isso. Então, agora, que este seja o nosso argv. Então, quando eu apenas corri esse programa antes, argv é uma matriz de strings. E assim, se eu executá-lo com um ponto argv barra 2, Olá mundo, então o argv si é comprimento 3, para argv zero, Olá, e mundo. E no interior de cada um destes índices é, também uma matriz, onde esta vai ser ponto, isso vai ser barra, eu não sei se essa era a direção certa, eu Não acho que era. A-R-V traço, precisa de mais espaço. Vamos cortar a esta matriz. Traço 0 e barra invertida 0 A-R-V. E então em desordem será Olá. Digamos, H-E barra invertida 0. E, finalmente, o W-O invertida 0. Assim, o algoritmo que acabou de escrever, o aninhados para loops, o que eles estão fazendo é, primeiro temos o contador i e, em seguida, j. Isto seria mais fácil com o código do tela, Vamos voltar a isso. OK. Então percebe que i é o iterador que é iteração sobre cada comando argumento de linha. E j é a iteração iterador sobre cada personagem em que argumento de linha de comando. Então, o que este printf íntimo está fazendo é, temos printf argv 0 0, printf argv 0 1, printf argv 0 2 0 3 0 4, 0 5, 0 6, mas agora, argv 0 7 vai igual barra invertida 0. Então saímos para que loop, e agora eu repete a 1. E agora nós estamos indo para impressão argv 1 0, argv 1 1 - bem, agora, uma vez que eu cortei Olá suma, argv 1 2 é novamente será barra invertida 0. E assim, incrementar i e continuar, e assim por diante, até que imprimir todos mundo, e essas são três de linha de comando argumentos, e nós vamos sair do o circuito externo, e terminar nosso programa. OK. Então, vamos voltar aqui. Então, você vai ganhar alguma familiaridade com argumentos de linha de comando nesta determinado conjunto de problemas. Agora, a depuração. Então, provavelmente você já teve que fazer alguma depuração com o seu anterior conjunto de problemas. E uma maneira muito fácil de depuração, em primeiro lugar, vamos olhar para um programa de buggy. Bem, andando por este programa, vamos pedir ao usuário para um inteiro, pegue esse inteiro, e em seguida, arbitrariamente, temos um loop while que é só ir a diminuir i até que seja igual a 10. Vamos supor que eu estou entrando um número inteiro maior do que 10. Então diminuir i até que seja igual a 10. E então nós temos um outro loop while que, apesar de i não é igual a 0, estamos vai diminuir i por 3. Então, se você ver a intenção do bug aqui, é que isso vai diminuir i para ser 10, e depois esta vontade loop while decremento i de 10, a 7, a 4, a 1, a 2 negativo, para negativo 5, e assim por diante, ao infinito negativo, uma vez que eu vou na verdade, nunca igual a 0. E depois, no final do presente programa, que têm a função foo que é acontecendo impressão que eu. Portanto, este é um programa curto e trivial, eo erro for óbvio, especialmente depois de eu disse que o erro era. Mas a intenção aqui é, bem, este pode realmente parecido com algumas de suas soluções de ávida da última conjunto de problemas e, talvez, você tem algum loop infinito em seu programa, e você não tem idéia o que está causando isso. Assim, uma técnica de depuração muito útil é só adicionar printfs todo o seu código. Então, aqui eu quero um printf fora primeiro loop while. E aqui eu quero um printf, e eu vou imprimir i. Eu mesmo vou fazer em primeiro lugar, enquanto loop, i. Lá fora, segundo loop while. Mais uma vez, imprimir dentro daqui, o valor i. E vamos executar este. Debug barra Assim ponto. Digite um número inteiro. Vamos fazer 13. E boom. Vemos que estamos loop infinito dentro do segundo circuito, enquanto. Portanto, agora sabemos qual é o erro. Mas printf depuração é perfeitamente grande, mas uma vez que os seus programas de obter mais longo e complicado, existem soluções mais sofisticadas para fazer as coisas funcionando. Portanto, vamos remover todas essas printfs. E vamos ter certeza que eu não fiz quebrar nada. OK. Assim, o programa que vamos introduzir é chamado GDB, para o GNU Debugger. Bem, na verdade, vamos remover depuração para um segundo, e fazer debug de novo. Bem, na verdade em primeiro lugar, uma boa lição em argumentos de linha de comando. Observe que este comando Clang que é compilando tudo está sendo passado na linha de comando, estes Argumentos da linha de comando. Então, exatamente como você está indo estar usando argumentos de linha de comando, como nós fez antes, e como você vai em PSET 2, que é como Clang é usá-los. Então, observe que esta primeira bandeira, traço ggdb3, o que está dizendo é que, Clang, você deve compilar este arquivo com o intenção que acabará precisa depurá-lo. Então, enquanto você tem essa bandeira, então podemos GDB depuração. E vai abrir o depurador GNU. Portanto, há um monte de comandos que você precisa para se acostumar. Primeiro que você provavelmente vai imediatamente precisamos é Executar. Então o que está Executar vai fazer? Vai começar o nosso programa. Então corra, o programa de partida, o programa de pede-nos para um inteiro de 13. E então é infinito looping como esperado, exceto eu removi o printfs, por isso nem sequer ver isso. Saiu normalmente. Oh. É possível que ele envolveu toda a volta, volta para - ignorando isso. Suponha que não sair normalmente. Há uma resposta complicada para isso. Então, agora, que não é muito útil. Então, basta executar o nosso programa no interior de este depurador não nos ajuda em qualquer forma, uma vez que poderia ter feito dot cortar depuração de fora GDB. Assim, o comando que você provavelmente vai - e eu vou sair desta. Control-d ou sair, tanto trabalho. Então, vamos abri-lo novamente. Outro comando que você, provavelmente, quer imediatamente para habituar-se é Break. Então, vamos quebrar a principal, por agora, e então eu vou explicar isso. Bem, aqui nós vemos que definir um ponto de interrupção nesta linha em debug.c. Então, o que significa quebra é que quando eu tipo de execução, o programa vai continuar a funcionar até Eu bati um ponto de interrupção. Então, quando eu bati prazo, o programa é iniciado, e depois se rompe, logo que ele entra a função principal. Quebre principal vai ser algo você muito comumente fazem. E agora, para apresentá-lo para mais alguns comandos. Observe aqui, que ele está dizendo que quebraram na linha 11, que é printf, insira um número inteiro. Assim, o comando seguinte vai ser como vamos para a próxima linha de código. Isso vai permitir-nos para a etapa através da nossa linha de programa por linha. Assim, na próxima. Agora a linha 12, nós vamos para obter o número inteiro. Avançar. E se você apenas pressione Enter novamente, ele vai refazer a última coisa que você fez. Então eu não preciso digitar ao lado de cada vez. Então, insira um número inteiro de 13. Então, agora, linha 14, enquanto i é maior de 10, e eu vou fazer a seguir. E vemos que vamos diminuir i. Então, nós estamos indo para diminuir i novamente. Então, agora, outro útil comando é Imprimir. Assim Imprimir está indo para imprimir o valor da variável. Vamos trazer o valor de i variável. Vamos imprimir i. Vai dizer que eu é 11. Agora nós Avançar novamente enquanto i é maior do que 10. Então, eu ainda é maior do que 10, uma vez que tem 11 anos. i menos de menos. Vamos imprimir i novamente. Como esperado, ele tem 10 anos. Então, agora, ao lado. Ele vai voltar para a condição, i é superior a 10, mas agora é i 10, de modo não é maior que 10, por isso, esperamos que caia fora do loop while. E agora estamos abaixo dessa linha de código. E um outro comando, List, é só ir para exibir o anterior eo próximo par de linhas de código, em Caso você se perdeu. Então nós só saiu este loop while, e agora nós entramos neste enquanto loop, linha 18. Assim, enquanto i não é igual a 0. E, em seguida, i é igual a i menos 3, e nós vamos notar, este só vai continuar. E podemos imprimir i. Cada comando tem uma espécie de atalhos. Então p é curto para Imprimir. Então podemos p i. Basta manter segurando n, ou continuar fazendo Avançar. Imprimir i novamente. Você vê agora é negativo 167. Então, isso vai durar para sempre, mas não realmente para sempre, uma vez que você acabou de ver, é vai realmente acabar em algum momento. Assim que começa GDB. Mas vamos fazer mais uma coisa em GDB. Uh, depuração. Assim, neste caso particular, o loop infinito passou a ser dentro de a função principal. E, por enquanto, apenas aceitar que que eu sou vai mover o ciclo infinito em a função foo. Basta lembrar que, no final do presente programa, bem, este era originalmente chamar foo, que era apenas indo para imprimir i. Mas agora nós estamos chamando foo, que é vai diminuir i até que seja 0, e em seguida, imprimir essa variável. OK. Guarde isso. Faça debug. E agora, gdb depuração. OK. Então, se eu apenas correr, então eu não vou ser capaz de realmente passar por minha linha por linha do programa. Então, vamos quebrar a principal, e digite prazo. Então, passar por isso, printf, insira um inteiro, obter o número inteiro de 13. Então, nós estamos indo para mantê-decremento até i é maior do que 10. Então vamos a cair até o while, e chegar à linha - Vamos abri-lo em uma janela separada. Então, nós diminuída até que eu já não era superior a 10, e então nós chamou a função, foo. Então o que aconteceu assim que eu bati função foo, bem, eu liguei para foo, e então eu não tinha mais controle sobre o GDB. Assim, logo que eu bati seguida nesta linha, coisas continuou até que isso aconteceu, onde o programa saiu quando - assumir que não existia eventualmente. Você viu uma pausa para um pouco embora. Então, por que eu perdi o controle sobre o programa em que ponto? Bem, quando eu digito seguinte, que vai para a próxima linha de código que literal será executado. Assim, após a linha 21, a próxima linha de código que será executada é a linha 22, que é, saindo da principal. Então, eu não quero apenas ir para a próxima linha de código. Eu quero ir para a função, foo, e depois também percorrer essas linhas de código. Então, para isso, temos uma alternativa. Vamos parar com isso de novo. Quebre principal. Uh, 1, next, next, 13, ao lado, next, next, com cuidado, antes de bater linha foo. OK. Então, agora, estamos na linha 21, onde chamamos foo. Nós não queremos que digitar próximo, uma vez que só vai chamar a função foo, e ir para a próxima linha de código. O que queremos usar é Step. Portanto, há uma diferença entre a Passo e no próximo, onde passo as etapas para o funcionar, e na próxima vai sobre a função. Ele apenas executa a totalidade de a função e continua indo. Então Passo vai trazer-nos na função, foo. E vemos aqui, agora, estamos de volta ao esse loop while que é, em teoria, vai continuar para sempre. E se você bater Step, quando não é mesmo uma função para chamar, então é idêntica à seguida. Então, é só quando você está em uma linha que está chamando uma função que o passo vai diferir em Avançar. Então Passo vai nos trazer aqui. Passo, passo, passo, passo, passo, passo, e vamos Infinite Loop para sempre. Então, você pode se acostumar com isso como sua maneira de identificar loops infinitos, é apenas segurando esta tecla Enter para ver onde você ficar preso. Há maneiras melhores de fazer isso, mas por enquanto, isso é perfeitamente suficiente. E estilisticamente, em conformidade com Estilo 50, eu deveria ter feito isso. OK. Então, um último comando a introduzir. Bem, vamos gdb debug dentro Então, ao invés de quebrar a principal, se eu conhecer a função foo é também o problema, então eu poderia ter apenas disse, quebrar a foo, em seu lugar. Vamos dizer que eu quebrar a ambos principal e foo. Assim, você pode definir como muitos pontos de interrupção como você quer. Quando eu digito prazo, que vai parar na - ooh, vamos recompilar, desde Eu mudei as coisas. Você verá esta linha, Aviso fonte arquivo é mais recente do que executável. Então isso significa que eu só fui aqui e mudou-los para estar de acordo com Estilo 50, mas eu não recompilar o programa. Então GDB me faz consciente disso. Eu vou parar de fumar, fazer debug de novo, bater gdb depuração. OK. Então, agora, voltar ao que eu estava fazendo. Quebre principal, foo pausa. Agora, se eu executar o programa, por isso é vai continuar até que atinge uma breakpoint. Essa interrupção acontece a ser o primeiro a principal. Agora, em vez de fazer next, next, next, next, next, até que eu bati foo, eu pode escrever continuar, que continuará até chegar ao próximo ponto de interrupção. Eu tenho que entrar no primeiro número inteiro. Continuar continuará até que eu bati o próximo ponto de interrupção, o que é que função de foo. Então Run será executado até que você bata um breakpoint, mas você só digitar run quando você está começando o programa, e em seguida, a partir de então, é continuar. Se eu só fiz quebrar principal e em seguida, correu, ele vai quebrar a principal, e em seguida continuar. Desde que eu não tenho um ponto de ruptura em foo, inserir o número inteiro, então agora eu estou não vai quebrar a foo. É só ir ao infinito loop até que. OK. Então, isso é Introdução à GDB. Você deve começar a usá-lo em seus conjuntos de problemas. Pode ser muito útil para identificar bugs. Se você realmente apenas, linha por linha, vá através de seu código, e comparar o que é realmente acontecendo com o que você espera acontecer, então é muito difícil perder seus bugs. OK. Então, na semana passada, David trouxe presente coisas criptografia de chave secreta para o primeira vez, onde nós não queremos senhas apenas ser armazenado em nosso computador em algum arquivo de texto simples, onde alguém pode vir e apenas abri-lo e lê-los. Idealmente, eles seriam criptografados de algum modo. E no Conjunto de Problemas 2, você estará lidando com um método de criptografia, ou, bem, dois métodos, mas eles não são tão grandes. Se você fizer a edição hacker, você está também vai estar lidando com descriptografar algumas coisas. Assim, a questão agora é, bem, mesmo se temos a criptografia mais forte algoritmo do mundo, se você escolher um particularmente pobre senha, então ele não vai ajudar muito, pois as pessoas ainda será capaz de descobrir isso. Mesmo vendo a string encriptada e ele se parece com uma confusão de lixo que não significa nada para eles, se eles ainda só precisa tentar algumas senhas para descobrir isso, então você não são muito seguros. Então, assistindo a um vídeo que faz esse ponto. [REPRODUÇÃO] -Helmet, você demônio. O que está acontecendo? O que você está fazendo com a minha filha? -Permita-me apresentar o brilhante jovem cirurgião plástico, Dr. Phillip Schlotkin, o maior nariz homem do trabalho em todo o universo, e Beverly Hills. -Sua Alteza. -Nariz trabalho? Não estou entendendo. Ela já tinha uma plástica no nariz. Era um doce dezesseis presente. -No. Não é o que você pensa. É muito, muito pior. Se você não me der a combinação de o escudo do ar, Dr. Schlotkin vontade dar a sua filha de volta seu antigo nariz. -No. De onde você tirou isso? -Tudo bem. Eu vou te dizer. Eu vou te dizer. Não, papai. Não, você não deve. -Você está bem, minha querida. Vou sentir falta de seu novo nariz. Mas eu não vou dizer-lhe a combinação, não importa o que. -Muito bem. Dr. Schlotkin, faça o seu pior. -O prazer é meu. [TOOLS sendo afiadas] -No. Espere. Espere. Eu vou te dizer. Eu vou te dizer. -Eu sabia que ele iria trabalhar. Tudo bem. Dê-me isso. -A combinação é um. -One. -One. -Two. -Two. -Two. -Três. -Três. -Três. -Quatro. -Quatro. -Quatro. -Five. -Five. -Five. -Assim, a combinação é um, dois, três, quatro, cinco. Essa é a combinação mais estúpida Que eu já ouvi na minha vida. Esse é o tipo de coisa que um idiota teria em sua bagagem. -Obrigado, sua Alteza. -O que você fez? -Eu desliguei a parede. -Não, você não fez. Você desligou o filme inteiro. -Devo ter apertado o botão errado. -Bem, colocá-lo novamente. Coloque o filme novamente. -Sim, senhor. Sim, senhor. -Vamos, Arnold. Venha, Gretchen. Claro, você sabe que eu ainda vou tem que cobrá-lo por isso. [FIM REPRODUÇÃO DE VÍDEO] ROB BODEN: Tudo bem. Portanto, agora que já estamos a falar de segurança, de certa forma, agradável pouco poster do filme, portanto, em recente dia, estas questões com o NSA monitorando tudo. Pode ser difícil de se sentir como você ter algum tipo de privacidade no mundo on-line, embora eu não poderia dizer te a maioria dos detalhes de Prism. Então, indo além PRISM, nós não vamos estar falando sobre isso, agora pensar sobre o seu laptop. Então, aqui, eu quero mudar para a minha conta real, com o meu pequeno pinguim. Então, eu tenho um conjunto de senha, e que senha é o que eu quiser que ele seja. Mas lembre-se de que o que eu estou entrando com, assim que este login alerta, é algum programa. É algum programa que foi escrito por uma pessoa. E por isso, que a pessoa, se forem particularmente mal-intencionado, que puderam já disse, tudo bem, por isso, se a senha que eu entro é igual ao meu senha real, ou é igual para alguma senha especial - David é incrível, ou algo assim - em seguida, deixá-los dentro Assim, um programador mal-intencionado poderia ter acesso a todos os seus Macs, ou Do Windows, ou qualquer coisa. De modo que não é muito de uma preocupação, uma vez que, Quero dizer, isso é programa de login que é fornecido com o OS X, centenas ou milhares de pessoas têm Revisei este código. E assim, se, no seu código em algum lugar, você dizer se esta string é igual a iguais David é incrível, login, então alguém está vai ser, tipo, esperar. Isso não está certo. Isso não deveria estar aqui. Então, isso é uma maneira de fazer as coisas para ser uma espécie de seguro. Mas pense até mesmo programas que você escreve. Vamos dizer que você escreveu o programa de login. Portanto, este programa de login que você escreveu, então, obviamente, você é um bom programador. Você não vai colocar qualquer mal-intencionado se x é igual a igual David é incrível em seu código. Mas este programa, o que você faz usar para compilar este programa? Algo como Clang. Assim que se a pessoa que passou a escrever Clang especial encaixotado em Clang algo como, se estou compilando o sessão do programa, em seguida, digite o código para o programa de login que diz que, se x é igual a igual David é incrível? Portanto, não muito ainda, mas temos o mesmo emitir aqui, onde Clang, bem, milhares, se não dezenas de milhares de pessoas, ter olhado para Clang, têm olhou para as suas linhas de código, e disse: tudo bem, não há nada de ruim aqui. Obviamente, ninguém está fazendo qualquer coisa esta mal-intencionado. Mas o que é próprio bumbum, como, e se eu compilar Clang? E se eu tiver algum compilador que compila Clang que insere Clang esse truque especial que diz, tudo bem, quando eu compilar Clang, então o executável Recebo deve especialmente olhar dentro do programa de login e inserção essa senha, é igual a iguais Dave é impressionante? Então lembre-se de que o seu próprio compilador precisa ser compilado em algum ponto. Portanto, se o que você escolher para compilar Clang com, em si é mal-intencionado, então você pode ser aparafusada a todo caminho para baixo da linha. Então, aqui, temos Ken Thompson e Dennis Ritchie. Portanto, esta é uma foto icônica. Dennis Ritchie está à direita. Ele é um grande - praticamente escreveu C. Assim, você pode agradecê-lo por esta classe. Ken Thomson é do lado esquerdo. Os dois basicamente escreveu UNIX. Bem, eles foram grandes contribuintes em UNIX. Havia alguns outros. Então, Ken Thompson, em algum momento, ele ganha o Prêmio Turing. E o prêmio Turing, eu sempre ouvi ele referenciada desta forma, é o Prêmio Nobel de ciência da computação. Então, o Prêmio Turing, ele tem que dar seu discurso de aceitação. E ele dá esta muito famoso discurso agora, chamado Reflexões sobre Confiança Trust, que temos ligados no site do curso. E, neste discurso, ele diz, tudo bem, então eu escrevi UNIX, e agora todos você as pessoas estão usando UNIX. Agora, lembre-se, hoje, que o Linux é um descendente direto do UNIX. OS X usa diretamente UNIX. Windows não faz muito, mas muito de idéias foram tiradas de UNIX. Assim, ele vai até o palco e diz: tudo bem, eu escrevi UNIX. E só assim vocês sabem, eu sou capaz de fazer logon em cada um único de seus computadores. Desde que eu colocar um desses especial se x é igual a igual Ken Thomson é incrível, então eu tenho permissão para entrar. Então, as pessoas são como, bem, Como você faz isso? Olhamos para o programa de login e nada está lá. Ele é como, bem, eu modifiquei o compilador para entrar no programa de login para que o programa de login terá agora que x é igual a igual Ken Thompson é incrível. E eles dizem, bem, isso não é verdade. Nós estamos olhando para o compilador, eo compilador não possui linhas de código como esse. Ele é como, OK, mas o que você está compilar o compilador com? E eles pensam, e ele é, como, bem, Eu sou o único que lhe deu o compilador você está usando para compilar o compilador, por isso você está compilando um compilador, que em si é mal-intencionado, e vontade quebrar o programa de login. Então, basicamente, nesse ponto, não há nenhuma maneira que você pode olhar para a fonte código do programa de login para ver o que está errado. Você não podia nem olhar na código-fonte do compilador para ver o que está errado. Você precisa olhar para a máquina de código, o binário efectivo da compilado compilador para ver, esperar, estes linhas de código não deveria estar aqui. Mas Ken Thompson deu um passo mais longe e disse, bem, há estes programas especiais que efectivamente ajudá-lo a ler o binário de programas, e por isso, se alguém usou esse programa para ler o binário, veriam estes linhas de código. Ele modificou esses programas para dizer, tudo bem, se você está olhando para o compilador, não mostram este particular conjunto de binário. Então, então você precisa dar um passo ainda mais e, basicamente, que poderia ter tomadas vários níveis de engano, e em algum momento, ninguém é realmente vai estar verificando. Assim, a moral da história é, você é não vai ser escrito Clang nesta classe. Você vai estar usando escalada Tinido muito nesta classe. Para todos sabem, Clang é um malicioso programa que está sabotando cada único programa que você já compilado. E para deixá-lo naquele mesmo sinistro notar, vê-lo na quarta-feira. [Aplausos] COLUNA 2: Na próxima CS50. COLUNA 3: Não se atreva a dizer isso. Você pode fazer isso. Você já fez isso antes, você pode fazer isso hoje em dia, você pode fazer isso amanhã. Você tem feito isso há anos. Basta ir até lá e fazer isso. Você pode fazer isso. [Música tocando]