[Powered by Google Translate] Problema Seção Set 2: Edição Hacker Rob Bowden, Universidade de Harvard Este é CS50. CS50.TV Então, eu sou Rob. Eu sou um sênior em Kirkland. Este é o meu terceiro ano TFing CS50. É a primeira vez que estamos a mudar a partir da seção tradicional palestra de estilo, onde só tipo de rever o que aconteceu na aula e depois vocês fazem perguntas, agora a ser muito mais baseada em problemas, onde usamos os espaços, e - Ah, então a idéia é ir para o link que lhe enviei e então você vai estar no meu espaço. Será que ninguém tem um laptop? Okay. Então nós vamos estar usando isso, e nós vamos estar fazendo problemas viver em seção e discuti-los e descobrir o que está errado e eu poderia puxar um pouco do seu código, e eu poderia discutir suas idéias. Então, tem alguém tinha dificuldade? Você pode conversar sobre o lado, eu não sei se nós vamos ter razão para isso. Agora, como o supersection anterior, se você estava na classe, você sabe do que se trata. Em todos os conjuntos P não vai ser essas seções. Assim, a P-2 set, especificações, eu acho que você viu na P-1 conjunto já. Mas podemos olhar para a P-2 set para o que nós vamos estar passando por cima hoje. E você vai ver uma seção de perguntas. Então, isso vai ser em todos os P-sets, haverá uma seção de perguntas. Até agora, disse, "Considere isso uma oportunidade de praticar." Você não será convidado a apresentar este programa. A idéia é que estas se destinam a espécie de ajudar você a começar com o conjunto de problemas. Eu acho que na edição Hacker, muitos deles são supostos ser apenas coisas novas e interessantes para aprender. Eles podem não ser diretamente aplicável ao conjunto de problemas. E agora nós não estamos tendo de enviá-los, mas, em teoria, para conjuntos de problemas posteriores, você pode enviá-los e, assim, você pode vir a seção ou assistir a seção para obter as respostas, ou você pode simplesmente levá-los em seu próprio país se você não se sentir como desfrutar da minha presença. Assim, o - Eu acho que essa é a primeira. Oh. Além disso, nestas seções de perguntas também temos que fazer perguntas sobre os shorts. Então eu acho que, em teoria, você deveria prestar atenção a estes antes de chegar a seção, mas tudo bem se você não faz, nós vamos passar por cima deles de qualquer maneira. Assim, podemos começar com estas: "Como é que um loop while diferem de um loop do-tempo? Quando é o último particularmente útil? " Então, alguém tem alguma -? [Aluno] O do-while sempre executado pelo menos uma vez. Sim. Então essa é a diferença. Um loop while - eu só faço isso aqui - enquanto loop, temos a condição aqui, enquanto que um do-tempo, você não tem uma condição até chegarmos aqui. E assim, quando o programa está em execução, e fica para o loop while, imediatamente verifica se esta condição for verdadeira. Se essa condição não é verdade, ela só vai pular o ciclo completo. Do-while, como o programa é executado, ele chega ao "fazer". Nada acontece neste momento, apenas continua executando. Então, quando ele atinge o "tempo", se a condição for verdadeira, vai loop de volta e fazê-lo de novo e de novo e de novo até que a condição não é verdade e, em seguida, apenas através de quedas. Assim, a diferença é que este pode pular desde o início. Isto necessariamente executa uma vez e então poderá executar mais vezes se a condição ainda é verdade. Assim, o loop while irá fazê-lo apenas uma vez, ou - o loop while - não pode precisar fazê-lo em tudo, desde logo que chegar a ele, se a condição for falsa, vamos pular sobre ele. Considerando-enquanto loop, vamos executá-lo uma vez, necessariamente. Depois, quando chegarmos à condição, vamos verificar se é verdadeira ou falsa. Se é verdade, nós vamos fazer isso de novo, se ele é falso, vamos continuar indo. Então, quando é o último particularmente útil? Então eu posso dizer que no conjunto dos 4 anos, 3 anos, qualquer que seja, que eu tenho programado, eu usei isso, como, menos de 10 vezes. E, provavelmente, cinco deles estão em CS50 quando estamos introduzindo fazer enquanto-loops. Então, quando você usou loops do-while? Quando é o - sim? [Estudante] Quando você está tentando obter a entrada do usuário, ou algo que você deseja verificar - Sim. Então faça-while, a entrada do usuário é um dos grandes. É por isso que os conjuntos de problemas primeiro par, quando você quer perguntar ao usuário, como, "Dê-me uma corda," você não pode continuar até chegar essa cadeia. E para que você, necessariamente, precisa perguntar para a cadeia pelo menos uma vez. Mas então, se eles respondem algo ruim, então você precisa para fazer um loop para trás e perguntar novamente. Mas diferente do que a entrada do usuário, é muito raro que eu encontro um caso onde eu quero loop "pelo menos uma vez", mas possivelmente mais. Perguntas ou -? Alguém já usou um do-while em outro lugar? Okay. Então o próximo é: "O que não declarado identificador geralmente indicam se emitido pelo bumbum? " Então, que tipo de código que eu poderia escrever para obter 'identificador não declarado? [Estudante] que x = 2? Assim, podemos apenas experimentá-lo aqui, x = 2. Vamos fazer isso - oh, eu não clique nele. Então aqui nós temos - todos os direitos. "O uso de x identificador não declarado". Então esse é o identificador não declarado, uma variável. Ele vai com freqüência chamar um identificador de uma variável. Por isso, talvez não saiba é realmente uma variável, que não sabe o que é. Então, é um identificador. Então por que é não declarado? Sim. Então, para ser claro sobre a terminologia, a declaração de uma variável é quando você diz "int x" ou "y", seqüência que seja. A inicialização da variável, ou a atribuição de variável, é sempre que você diz "x = 2". Assim, podemos fazer isso em etapas separadas, int x, x = 2, e até - nós podemos ter um monte de coisas aqui dentro - mas até esta linha acontece, x ainda é inicializado, mas ele foi declarado. E assim podemos, obviamente, fazê-lo em uma linha, e agora estamos declarando e inicializando. Perguntas? E, finalmente, "Por que não é a cifra de César muito seguro?" Então, primeiro, que alguém quer dizer que a cifra de César é? [Estudante] Caesar Cipher apenas é que você mapear, você muda cada letra, um determinado número de letras passar por cima, e passar por cima, e não é muito seguro porque há apenas 26 opções possíveis e você só tem que tentar cada uma das pessoas, até você conseguir. Oh. Então, eu devo repetir? A cifra de César, é - Quero dizer, você estará lidando com ele sobre os problemas que você - ou eu acho que a edição padrão do conjunto de problemas que não está na edição hacker. Então, na edição padrão para o conjunto de problemas, você receberá uma mensagem do tipo: "Olá, mundo", e você também tem um número como 6, e você levar essa mensagem, e cada personagem individualmente, você girá-lo por seis posições no alfabeto. Assim, a 'h' em Olá ficaria h-i-j-k-l-m-n. Então, a primeira letra seria n. Nós fazemos a mesma coisa com e. Se temos um, como, z ou algo assim, então nós envolvemos a volta a 'um'. Mas cada personagem recebe ciclo 6 caracteres no final do alfabeto, e não é muito seguro uma vez que existem apenas 26 possibilidades de quantas maneiras você poderia envolver uma única letra. Então você pode apenas tentar todas as 26 deles e, presumivelmente, de uma mensagem suficientemente longo, apenas um desses possíveis 26 coisas vai ser legíveis, eo legível vai ser a mensagem original. Portanto, não é uma boa forma de criptografar nada. Alheios a essas shorts, "O que é uma função?" Então, o que é uma função? Sim. [Estudante] É como se um pedaço de código que você pode chamar para passar e, em seguida, obter o valor de retorno de qualquer coisa. Sim. Então, eu vou responder por também responder a seguinte - ou a repetição por também apenas responder a próxima. Você pode usar funções em vez de apenas copiar e colar o código uma e outra vez. Basta ter o código, coloque-o em um fuction, e então você pode apenas chamar a função onde quer que tenha sido copiar e colar. Assim, as funções são úteis. Então agora nós vamos fazer problemas reais. O primeiro. Assim, a idéia de que a primeira é, você passa uma string, e independentemente da - ou que ele diz em letras minúsculas? Ela não diz que todas as letras minúsculas. Portanto, a mensagem pode ser qualquer coisa, e - oh não. Ele faz. "Para simplificar, você pode assumir que o usuário apenas a entrada letras minúsculas e espaços." Então nós passar uma mensagem com apenas letras minúsculas e então alternar entre capital e minúsculas - que alterar a seqüência de ser capital e minúsculas, alternando. Então, antes de dar-lhe um segundo para até mergulhar no problema, qual é a primeira coisa que temos de fazer? Oh, o que eu basta clicar em? Oh, eu só clicou em um e-mail aqui. Então a primeira coisa que precisamos fazer - estou a olhar para a pessoa errada? Isso é parte de um presente? Não, essas são ainda está lá, no entanto. Ok, ainda está aqui. Agora não podemos assumir -? Sim. Aqui não podemos assumir que é apenas minúsculas e espaços. Então, agora temos que lidar com o fato de que as cartas pode ser o que nós queremos que eles sejam. E assim, a primeira coisa que queremos fazer é apenas receber a mensagem. Nós apenas precisamos de ter uma string, string s = GetString, ok. Agora este problema, existem algumas maneiras de fazê-lo. Mas vamos querer usar operadores bit a bit aqui. Há pessoas que ou não estavam no supersection, ou algo assim, e não sei o que são operadores bit a bit? Ou como eles se relacionam com ASCII de alguma forma? [Estudante] Eu não estava no supersection, mas eu sei o que os operadores bit a bit são. Okay. Então eu não tenho que passar por cima dos princípios deles, mas eu vou explicar o que vamos querer usar aqui. Então 'A': Representação binária de capital A, o número é de 65. Eu só vou olhar - 41 vai ser 01000001. De modo que deve ser de 65 em decimal, pelo que esta é a representação binária do caráter de capital A. Agora, a representação binária do personagem minúsculas 'a' vai ser a mesma coisa, ou quase. É que - 6, sim. Isso é certo. A capital de modo binário minúsculas, binário 'um'. Então, observe que a diferença entre A e 'a' é este único bit. E esta passa a ser a de 32 bits, o bit que representa o número 32. E isso faz sentido, já que A é de 65; 'a' é 97. A diferença entre eles é 32. Portanto, agora sabemos que podemos converter de A a 'a', tomando um e bit a bit ORing-lo, com - que se parece com um 1. Este é um OR bit a bit, com 00100000, e que vai nos dar "um". E podemos começar a partir de 'a' a A por bitwise AND com 11, 0 naquele lugar, 11111. Então, isso vai então dar-nos exatamente o que 'a', mas cancelar este bit individual, por isso vamos ter 01000001, eu não sei se eu contei direito. Mas esta técnica de bit a bit ORing para começar a partir de capital para minúsculas, e bit a bit AND para começar a partir de minúsculas para o capital não é exclusivo para A. Todas as letras, K vs k, Z vs z, todos eles estão indo só para variar por este único bit. E assim você pode usar isso para mudar de qualquer letra minúscula para qualquer letra maiúscula e vice-versa. Okay. Assim, uma maneira fácil de obter a partir deste - assim, em vez de ter que escrever o que quer que 1011111 é - uma maneira fácil de representar este número, e isso não é uma que eu fui no supersection, mas til (~) é outro operador bit a bit. O que faz é ~ olha para a representação de bits. Vamos dar qualquer número. Este é apenas um número binário, e que ~ não é apenas inverte todos os bits. Portanto, esta foi a 1, agora a 0, isto é um 0, agora um 1, 010,100. Então isso é tudo ~ faz. Então, 32, vai ser o número - livrar-se de que - 32 de modo que vai ser o número 00100000, e assim por ~ de esta vai ser este número até aqui que eu ANDed 'a' com. Será que todo mundo vê isso? Isso é muito comum, como quando você quer descobrir para coisas mais recentes que poderíamos estar vendo, quando queremos ver se - ou queremos tudo, cada conjunto único bit, exceto para um você tende a se ~ do pouco que nós não queremos definir. Então, não queremos que o conjunto de 32 bits, para que não ~ de 32. Okay. Assim, podemos usar todos aqueles aqui. Tudo bem, por isso é bom se você não estiver pronto, vamos andar lentamente ao longo juntos, ou andar sobre isso, então - por isso. Caminhe por isso. Portanto, temos nossa string, e queremos loop sobre cada personagem em que seqüência e fazer alguma coisa para ele. Então, como vamos varrer uma string? O que devemos usar? Eu não vou fazer isso aqui. Sim. Então, eu tenho o meu iterador, e ele disse isso, mas como eu sei quantos caracteres estão na cadeia? Strlen (s), então i + +. Então o que eu fiz aqui não é a melhor maneira de fazer as coisas. Alguém sabe por que? Porque você está verificando a linguagem da cadeia de cada vez. Então, nós vamos querer mover strlen, eu poderia dizer-se aqui, int tamanho = strlen (s), e, então, i > 1 bit. Pode ser mais do que 1 bit, desde que todos os bits abaixo desta posição são as mesmas. Então, precisamos de pelo menos 26 caracteres - ou, existem 26 caracteres. Então, precisamos de pelo menos 26 números para representar a diferença - A diferença entre A e 'a' tem que ser de pelo menos 26, ou então não teria representado todos os números de capitais. Isso significa que A, se começarmos a 1, que vai usar todos esses bits, todos estes primeiros 5 bits, para representar tudo a Z. É por isso que o próximo bit, ou este bit, a próxima é a que escolheu para distinguir entre um e 'um'. Isso é também porque, na tabela ASCII, há cinco símbolos que separam letras maiúsculas de minúsculas. Desde que esses são os símbolos, o 5 extra que traz a 32 sendo a diferença entre eles. [Estudante] Então, nós poderíamos fazer isso, porque ASCII é projetado dessa forma. Sim. Mas ASCII - a diferença podia também ser ambos destes bits. Como, se um era 10000001, e 'a' 11100001 - eu me esqueça, o que for. Mas se fosse isso, então nós ainda poderia usar 'a' - A. É apenas agora a diferença entre A e 'a' é ainda estes dois bits. Eu acho que está escrito 48. É 32 + 64? Eu acho que é? Seria ainda 2 bits; cada personagem, como, Z e Z, K e K, eles ainda teriam os mesmos bits exatas definidas exceto para os dois bits. Então, enquanto isso é sempre verdade, independentemente de se estamos usando ASCII ou algum outro sistema, enquanto há apenas um determinado número de bits que são diferentes para cada personagem, em seguida, que funciona bem. É que 32 foi criado porque é o primeiro que poderia usar. >> Cool. Eu tendem a preferir, caso você não tenha visto, se o bloco é somente uma única linha, você pode se livrar das chaves, de modo que tendem a preferir fazer isso. Além disso, você sabe como podemos fazer coisas como s [i] + = 1? Você também pode fazer s [i] bitwise E = 32. E bit a bit OR = 32. Além disso, contam mod 2 == 0. Então lembre-se que - eu não vou escrevê-lo - qualquer valor diferente de zero é verdadeiro, e 0 é falso. Assim, "se a contagem mod 2 == 0" é o mesmo que dizer "se não contar mod 2". Eu provavelmente teria apenas inverteu as linhas e disse: "se a contagem mod 2, que o OR 1, mais que o AND 1 ", de modo que eu não precisava do" não ". Mas isso funciona tão bem. E o que mais eu posso fazer aqui? Você pode combiná-los com ternário se você queria, mas, então, que tinha acabado de fazer as coisas mais confusas e provavelmente mais difícil de ler, por isso não vamos fazer isso. Alguém tem alguma sugestão? É que todo o problema pediu? Oh yeah. Então, se livrar dessas linhas vazias, agora vamos imprimir f,% s ser o único para cordas, Vamos imprimir f, s. Agora vamos executá-lo. Eu fiz algo de errado? Isso é um \ ", eu quero um n. Okay. Agora vamos executá-lo. Ele provavelmente vai gritar comigo. Strlen é string.h. Portanto, esta é a coisa agradável sobre Clang é mostra o que ele está, ao invés do GCC, que apenas diz: "Ei, você esqueceu algo, eu não sei o que era." Mas isso vai me dizer: "Você deve incluir string.h". Então eu não pedir nada, por isso não está dizendo nada. Mas vamos fazer o seu exemplo, "Obrigado 4 Adicione o". Isso parece certo. Hooray. Então, voltar para o seu principal, eu quase nunca fazem isso. É opcional. E principal é a única função para o qual é opcional. Se não retornar nada da principal, é assumido que você pretendia retornar 0. Perguntas? Okay. Portanto, agora o segundo problema. "Lembre-se da segunda palestra duas semanas de que a troca de valores 2 variáveis, passando essas duas variáveis ​​para uma função (mesmo se chamado swap) não é exatamente o trabalho, pelo menos não sem 'ponteiros' ". E ignorar os ponteiros até chegar a eles. Queremos trocar duas variáveis; nós não estamos usando uma função para fazer isso. Nós ainda vamos fazê-lo em principal como ele diz. Mas, para usar essas duas variáveis, não queremos usar uma variável temporária. Há duas maneiras de fazer isso. Você pode fazer isso usando seus operadores binários tradicionais. Então, alguém sabe uma maneira rápida e suja de fazer isso? Ele pode realmente ter um minuto de pensar. Se eu tiver - Vou definir o problema como se eles pedirem. Então, se eu tiver duas variáveis, A, que é apenas um inteiro que eles me dão, e B soma variável, que é um outro número inteiro que eu sou dado. Então, se eu tenho essas duas variáveis, agora eu quero trocá-los. O tradicional, usando seus operadores binários regulares, quer dizer, como +, -, ÷. Nem os operadores bitwise que atuam sobre binário. Então, usando -, +, ÷, e todos aqueles. Poderíamos trocar, fazendo algo como a = a + b, e b = a - b, a = a - b. Então, verificação de sanidade, e depois vamos ver por que isso funciona. Vamos dizer que a = 7, b = 3, então a + b que vai ser 10. Então, nós estamos agora definindo a = 10, e então nós estamos fazendo b = a - b. Então, nós estamos fazendo b = a - b, que vai ser 7, e b = a - b, novamente, ou a = a - b. Que vai ser 10-7 que é 3. Então, agora, corretamente, 'a' foi de 7, b foi de 3, e agora b é 7 e 'a' é 3. De modo que o tipo de faz sentido, 'a' é a combinação dos dois números. Neste ponto, 'a' é a combinação, e então nós estamos subtraindo a b original, e então nós estamos subtraindo o que era o original 'a'. Mas isso não funciona para todos os números. Para ver isto, vamos considerar um sistema, de modo que costumamos pensar em números inteiros como 32 bits. Vamos trabalhar em algo que é apenas como 4 bits. Espero que eu venha com um bom exemplo agora. Então, eu sei, isso vai ser fácil. Vamos dizer que os nossos dois números são 1111, e 1111, de modo que estamos em binário agora. Em decimais reais, se você quer pensar dessa forma, a. = 15 e b = 15 E então nós esperamos que, depois de trocá-los - eles não tem sequer a ser os mesmos números, mas eu fiz isso dessa maneira. Vamos fazer não lhes os mesmos números. Vamos fazer 1111 e 0001. Então, a = 15 e b = 1. Depois que trocá-los, esperamos que 'a' para ser 1 e b para ser 15. Então, nosso primeiro passo é a = a + b. Nossos números são apenas 4 bits de largura, então 'um', que é 1111, + b, que é de 0001, vai acabar sendo 10.000, mas temos apenas 4 bits. Então, agora a = 0. E agora queremos definir b = a - b - na verdade, isso ainda funciona perfeitamente. a = a - vamos ver se isso funciona perfeitamente - b. Então, em seguida, b = 0 - 1, o que ainda seria 15, e, em seguida, a = a - b, o que seria um. Talvez isso não funciona. Eu sinto que há uma razão para ele não funciona com regular. Ok, então trabalhando com a suposição de que ele não funciona com as operações de binários regulares, e eu vou procurar - Eu Google para ver se isso é verdade. Então, nós queremos fazê-lo usando os operadores bit a bit, ea pista aqui é XOR. Assim, a introdução de XOR (^) se você não viu ainda. É, mais uma vez, um operador bit a bit por isso age pouco a pouco, e é - Se você tem os bits 0 e 1, então este será um. Se você tem os bits 1 e 0, vai ser um, você tem os bits 0 e 0 que vai ser 0, e se você tem os bits 1 e um vai ser 0. Então, é como OR. Se qualquer um dos bits forem verdadeiros, isto é, 1, mas ao contrário de OR, ele não pode ser os dois bits que são verdadeiras. Ou teria esta ser de 1, XOR teria este ser 0. Então nós vamos querer usar XOR aqui. Pense nisso por um minuto, eu vou ao Google. Bem, você não pode ler isso, eu estou atualmente na página algoritmo XOR swap. Esperemos que isto irá explicar por que eu não posso - Este é exatamente o algoritmo que acabamos de fazer. Eu ainda não sei por que - eu devo ter apenas escolheu um mau exemplo, mas neste caso, onde 'a' aconteceu para se tornar 0, depois de chegar ao 5 bits, por isso agora 'a' é 0, que é o que é chamado de "estouro de inteiro." Segundo a Wikipedia, "Ao contrário da troca de XOR, esta variação exige que ele usa alguns métodos a garantia de que x + y não causa um excesso de número inteiro ". Portanto, este não tem problemas, o que foi excesso de número inteiro, mas eu fiz algo errado. Não tenho a certeza. Vou tentar chegar a um outro. [Estudante] Bem, não é excesso de número inteiro quando você está tentando colocar um número em que maior do que a quantidade de bits que você recebe? Sim. Nós temos 4 bits. Isto - que teve 4 bits, que tente adicionar um para ela, então vamos acabar com 5 bits. Mas o quinto bit só é cortada, sim. Ele pode, na verdade - [Estudante] Será que você jogue um erro, ou faz isso - teria que lançar um erro? Não. Então não há erro. Quando você chegar ao nível da montagem, um pouco especial em algum lugar está definido que disse que houve um estouro, mas em C você meio que simplesmente não lidar com isso. Você realmente não pode lidar com isso, a menos que você use instruções de montagem especiais em C. Vamos pensar sobre XOR troca. E eu acho que o artigo da Wikipedia também pode ter vindo a dizer que - Por isso, também trouxeram aritmética modular, então eu acho que era, em teoria, a aritmética modular quando eu disse que 0-1 é de 15 novamente. Para que possa, na verdade - em um processador regular que faz 0 - 1 = 15. Desde que acabar em 0, subtrair 1, assim então ele só enrola de volta em torno de 1111. Portanto, este algoritmo pode realmente funcionar, a a + b, a - b, b - a, que pode ser ótimo. Mas há alguns processadores que não fazer isso, e por isso não ficaria bem em aqueles específicos. Troca de XOR irá funcionar em qualquer processador. Okay. A idéia é que ele deveria ser o mesmo, no entanto. Onde estamos usando XOR de alguma forma obter as informações de ambos em uma das variáveis, e, em seguida, retirar as informações das variáveis ​​individuais novamente. Então, alguém tem idéias / a resposta? [Responder Estudante, ininteligível] Portanto, este deve funcionar, e também, XOR é comutativo. Independentemente de qual ordem estes dois números que ser em até aqui, este resultado será o mesmo. Então a ^ b é b ^ a. Você também pode ver este escrito como um ^ = b, b ^ = a, a ^ = b novamente. Então, isso é certo, e ver por que isso funciona, acho que dos bits. Usando um número pequeno, digamos 11001, e 01100. Portanto, esta é 'a', o que é b. Então a ^ = b. Nós vamos estar definindo "a" = a XOR destas duas coisas. Então, 1 ^ 0 é 1, 1 ^ 1 é 0, 0 ^ 1 é 1, e 0 ^ 0 é 0, 1 ^ 0 é 1. So 'uma', se você olhar o número decimal, que vai ser - você não vai ver muito de uma relação entre o original 'a' eo novo 'a', mas olhando para os bits, 'a' é agora como uma malha de informações de tanto o original 'a' e b original. Então, se tomarmos b ^ a, vemos que nós vamos acabar no original 'um'. E se tomarmos o original 'a' ^ o novo 'a', vemos que acabar no b original. Então, (a ^ b) ^ b = o original 'a'. E (a ^ b) ^ a = b original. Não há - outra forma de ver isso é XOR nada em si é sempre 0. Assim, 1101 ^ 1101, todos os bits vão ser os mesmos. Então nunca vai ser um caso em que um é um 0 eo outro é um. Portanto, este é 0000. O mesmo com este. (A ^ b) ^ b é como a ^ (b ^ b). (B ^ b) vai ser 0; a ^ 0 é apenas vai ser 'a', uma vez que todos os bits são 0. Assim, os únicos que estão indo para estar onde 'a' era originalmente um 1 - tinha uns. E a mesma idéia aqui, eu tenho certeza que ele também é comutativa. Sim. Eu disse antes que era comutativa. O ^ 'a,' e é associativa, por isso agora (b ^ a) ^ a. E nós podemos fazer b ^ (a ^ a). E então, novamente, nós temos a b original. Assim, 'a' é agora a combinação de 'a' e b em conjunto. Usando a nossa nova combinação 'a' dizemos b = combinação 'a' ^ b do original, nós temos o original 'a'. E agora um combo = 'a' ^ a b novo, que era o original - ou o que é agora o que era 'a' ou b. Isso é caso aqui. Este é = b, b idade. Então agora tudo está de volta na ordem trocada. Se nós realmente olhou para os bits, b = a ^ b, vai XOR estes dois, ea resposta vai ser isso, e então a = a ^ b é XORing estes dois ea resposta é esta. Perguntas? Okay. Assim, o último é um pouco significativamente mais difícil. [Estudante] Eu acho que ele tem uma pergunta sobre isso. >> Oh, desculpe. [Aluno] O que é realmente mais rápido? Se você usar este XOR, ou é se você declarar uma nova variável? Então, o que é realmente mais rápido, declarando uma nova variável ou usando XOR para trocar? A resposta é, com toda a probabilidade, uma variável temporária. E isso porque uma vez que é compilado para baixo - assim no nível da montagem, não há tal coisa como variáveis ​​locais ou quaisquer variáveis ​​temporárias ou qualquer dessas coisas. Eles são como - não há memória, e existem registros. Os registros são onde as coisas estão acontecendo ativamente. Você não adicionar duas coisas na memória, você adiciona duas coisas em registos. E você levar as coisas da memória para registros para depois adicioná-los, e então você pode colocá-los de volta na memória, mas toda a ação acontece em registros. Então, quando você estiver usando a abordagem temporária variável, geralmente o que acontece é esses dois números já estão em registros. E então, a partir desse ponto, depois de ter trocado eles, ele só vai começar a usar o outro registo. Em qualquer lugar que você estava usando b, ele só vai utilizar o registo que já estava armazenando 'a'. Por isso, não precisa fazer nada para realmente fazer a troca. Sim? [Estudante] Mas ele também tem mais memória, certo? Só vai ter mais memória, se ele precisa para armazenar a variável temporária. Como se você usar mais tarde que a variável temporária de novo em algum lugar, então - ou você atribui alguma coisa para essa variável temporária. Assim, se em qualquer ponto no tempo "a, 'b em temp têm valores distintos ou algo assim, em seguida, ele vai ter locais distintos na memória, mas é verdade que há muitas variáveis ​​locais, que só existem em registros. Nesse caso, ela nunca é colocada na memória, e assim você nunca está perdendo a memória. Okay. Última pergunta é um pouco mais. Então, aqui, neste aparelho CS50, há um dicionário. E a razão para isso é porque [? B66] é um corretor ortográfico onde você vai escrever o uso de tabelas de hash ou tenta ou alguma estrutura de dados. Você vai estar escrevendo um corretor ortográfico, e você vai estar usando este dicionário para fazer isso. Mas, para este problema, vamos apenas olhar para cima para ver se é uma única palavra no dicionário. Então, em vez de armazenar o dicionário inteiro em alguma estrutura de dados e, em seguida, olhando para um documento inteiro para ver se algo está incorreto, só queremos encontrar uma palavra. Assim, podemos apenas digitalizar sobre o dicionário inteiro e se nunca encontramos a palavra no dicionário inteiro, então ele não estava lá. Se a varredura sobre o dicionário inteiro e não ver a palavra, então estamos bem, nós o encontramos. Diz aqui que queremos começar a olhar para a função C de manipulação de arquivos, já que queremos ler o dicionário, mas vou dar a dica aqui, como para as funções que você deve pensar. Vou escrevê-los em espaços. Assim, os principais que você vai querer olhar para f são abertos e, então, inevitavelmente, f fechada, que vai no final de seu programa, e f f digitalização. Você também pode usar f ler, mas você provavelmente não quer porque isso - você não acabar precisando disso. F f varredura é o que você vai usar para digitalizar sobre o dicionário. E para que você não precisa codificar a solução, apenas tentar e como pseudo-código o seu caminho a uma solução, e depois nós vamos discutir isso. E, na verdade, desde que eu já te dei estes, se você entrar em qualquer terminal ou shell do seu aparelho, Eu - Eu normalmente - se você ainda não viu, eu não sei se você fez em classe, mas o homem, de modo que as páginas do manual, são bastante úteis para olhar para praticamente qualquer função. Então eu posso fazer, como, f homem, digitalização f. Esta é agora a informação sobre a família f varredura de funções. Eu também poderia fazer f homem, abertos, e que vai me dar mais detalhes do que isso. Então, se você sabe qual a função que você está usando, ou você está lendo código e você vê alguma função e você pensa, "O que isso faz?" Apenas um homem nome da função que. Há um par de exemplos estranhos, onde você pode ter a dizer gosto. homem 2, que o nome da função, ou o homem que 3 nome da função, mas você só tem que fazer isso se o nome de função de homem não acontecer a trabalhar pela primeira vez. [Estudante] Então, eu estou lendo a página man para aberto, mas ainda estou confuso sobre como usá-lo eo programa. Okay. Um monte de páginas de manual são menos do que útil. Eles são mais úteis se você já sabe o que fazer e então você só precisa se lembrar da ordem dos argumentos ou algo assim. Ou eles podem lhe dar uma visão geral, mas alguns deles são muito grande. Como f varredura f, também. Ele lhe dá a informação para todas estas funções, e uma linha de baixo aqui acontece a dizer, "F varredura f lê a partir do ponto de corda ou corrente." Mas f abrir. Então, como é que nós usamos f aberta? A idéia de um programa que precisa de fazer arquivo I / O é que primeiro você precisa abrir o arquivo que você quer fazer as coisas com e, inevitavelmente, ler coisas desse arquivo e fazer coisas com eles. F aberto é o que usamos para abrir o arquivo. A única coisa que voltar, então o arquivo que queremos abrir, dá-nos a - aqui ele diz que "usuário / / share dict / / palavras". Este é o arquivo que deseja abrir, e nós queremos abri-lo - temos que especificar explicitamente se queremos abri-lo para ler ou se queremos abri-lo a escrever. Há um par de combinações e outras coisas, mas queremos abrir este para leitura. Queremos ler a partir do arquivo. Assim que este retorno? Ele retorna um arquivo de estrela (*), e eu vou mostrar tudo na variável f, então *, novamente, é um ponteiro, mas não querem lidar com ponteiros. Você pode pensar em f como, f agora é a variável que você vai usar para representar o arquivo. Então, se você quiser ler o arquivo, você lê a partir de f. Se você quiser fechar o arquivo, você fecha f. Assim, no final do programa, quando nós inevitavelmente quer fechar o arquivo, o que devemos fazer? Queremos fechar f. Então, agora a função de último arquivo que vamos querer usar é varredura f, f f digitalização. E o que isso faz é que varre sobre o arquivo procurando um padrão para corresponder. Olhando para a página homem aqui, vemos int f f digitalização, ignorar o valor de retorno para agora. O primeiro argumento é o fluxo de arquivo *, de modo que o primeiro argumento que vamos querer passar é f. Estamos varredura sobre f. O segundo argumento é uma seqüência de formato. Eu vou dar-lhe uma seqüência de formato agora. Acho que acontecer a dizer, 127s \ n, um monte de que é desnecessário. A idéia de que essa seqüência de formato é, é que você pode pensar de f digitalização como o oposto de f impressão. Então f impressão, impressão f também usamos esse tipo de parâmetro formato, mas em f impressão que nós estamos fazendo é - vamos olhar para um equivalente. Assim imprimir f, e não há, na verdade também f impressão f, onde o primeiro argumento vai ser f. Ao imprimir f, poderíamos dizer algo como, "print 127s \ n" e depois se passar alguma corda, que vai imprimir essa string e então uma nova linha. O que 127 significa, eu tenho certeza, mas eu nunca me restrito a ele, Você não precisa nem dizer '127 'na f impressão, mas o que significa é imprimir os primeiros 127 caracteres. Então, eu tenho certeza que é o caso. Você pode Google para isso. Mas no próximo que eu tenho quase certeza que significa isso. Portanto, esta é imprimir os primeiros 127 caracteres, seguido por uma nova linha. F varredura f agora, em vez de olhar para uma variável e imprimi-lo, ele vai olhar para algumas cordas, e armazenar o padrão para a variável. Vamos realmente usar f verificação em um exemplo diferente. Então, vamos dizer que tivemos alguns int, x = 4, e queríamos criar uma cadeia de feitos - queria criar a cadeia que era como, este vai aparecer muito mais tarde, algo que é como 4.jpg. Portanto, este pode ser um programa onde você terá contador de soma, Resumindo combater i, e você deseja salvar um monte de imagens. Então você quer salvar i.jpg, onde i é alguma iteração do seu loop. Então, como vamos fazer essa seqüência para que o JPEG? Se você quiser imprimir 4.jpg, podemos apenas dizer f impressão, D.jpg%, e então ele iria imprimir para que o JPEG. Mas, se queremos salvar o 4.jpg string, usamos f digitalização. Assim string s - na verdade, nós não posso - personagem, char s, vamos 100. Então, eu só declarou alguma matriz de 100 caracteres, e é isso que nós estamos, inevitavelmente, vai estar armazenando que JPEG dentro Então, nós estamos indo para usar f, digitalização e do formato, como diríamos D.jpg% para imprimir 4.jpg, o formato deste vai ser D.jpg%. Assim, o formato é D.jpg%, o que queremos para substituir d% com é x, e agora precisamos armazenar essa string em algum lugar. E para onde estamos indo para armazenar esta string é na matriz s. Então, depois de esta linha de código, s, se imprimir f% s, de a variável s, que vai imprimir 4.jpg. Então f varredura f é o mesmo que f varredura, só que agora ele está a olhar para este arquivo para o que para armazenar em s. Isso é o que o último argumento é que vai ser. Nós queremos gravar - "família f digitalização de exames de funções tanto no acordo com o formato como tentou abaixo. Se qualquer são armazenados nos pontos de localização você pode retornar - " Não, pode ser bom. Deixe-me pensar por um segundo. Então varredura f não faz - o que diabos é a função que faz isso? Então varredura f não vai levar um inteiro e fazer ponto jpg. Vai [resmunga]. Salve variável int em string int C. O que é esta variável, ou o que é esta função chamada? Sim. Isto - sim. Então, o que eu estava definindo a você antes era s f de impressão, que - que faz muito mais sentido, por isso que eu disse que era muito mais como f impressão. Digitalização f ainda é tipo como de f impressão, mas s f impressão vai examiná-lo mais de e substituir as variáveis ​​e, agora, armazená-lo em uma corda. Em vez de imprimir, ele armazena em uma string. Assim, ignorar que inteiramente. Você ainda pode pensar em como o especificador de formato semelhante ao de f impressão. Então, agora, se quiséssemos fazer a coisa 4.jpg, faríamos s f impressão, x isso. Então, o que está fazendo varredura f - Qual foi a sua questão vai ser? [Estudante] Eu só estou confuso sobre o que estamos tentando fazer aqui com que o JPEG. Você pode explicar que um tempo mais? Portanto, este foi - é menos relevent para f varredura f agora, espero, vai amarrar de volta em algum tipo de caminho. Mas o que eu inicialmente tinha a intenção de mostrar era - esta é, na verdade, diretamente relevante para estes [? F5] Você vai estar usando s f de impressão, onde, dizer que temos 100 imagens, e você quer ler a imagem 1.jpg, 2.jpg, 3.jpg. Portanto, a fim de fazer isso, você precisa f aberta, e então você tem que passar a seqüência que você deseja abrir. Então, gostaria de abrir 1.jpg;, a fim de criar a cadeia que é 1.jpg, fazemos s f impressão de% D.jpg-não fizemos por int i = 0. i <40, i + +. Então s% f D.jpg impressão de i. Então, depois desta linha, agora a variável ou matriz s vai 1.jpg. Ou, 0.jpg, 1.jpg, 2.jpg. E assim podemos abrir, por sua vez, cada imagem para leitura. Então é isso que s imprimir f faz. Você vê o que s imprimir f está fazendo agora? [Estudante] Ok, então ele está tomando - ele cria uma string, something.jpg, e depois armazena. Sim. Ele cria - esta é uma outra seqüência de formato, assim como varredura F e F de impressão, onde se insere todas as variáveis ​​para o segundo argumento, pode ser s em oposição ao i. Talvez - eu quero dizer, esse é o caso. Mas qualquer que seja a ordem dos argumentos é. Vai para inserir todas as variáveis ​​para a cadeia de formato e depois armazenar em nosso buffer; chamamos isso de um buffer, que é onde estamos armazenando a string. Então, nós estamos armazenando dentro de s a string formatado corretamente, d%, tendo sido substituído por 4. [Estudante] Então, se fizéssemos isso, é a variável f apenas vai ser transferido? Sim. Assim, devemos fechar o original f antes de fazer isso. Mas - e então, também, se não houvesse um f abrir aqui, então seria preciso dizer - Sim. Mas seria abrir uma centena de arquivos diferentes. [Estudante] Mas não seria capaz de acessar ou - ok. Okay. Então varredura f, f varredura f, é uma espécie da mesma idéia, mas em vez de, em vez de armazená-lo em uma corda, é mais como você está agora passando por uma picada e casamento de padrões contra essa seqüência e armazenar os resultados em variáveis. Você pode usar f varredura para analisar sobre algo como 4.jpg, e armazenar a 4 inteiro em int x soma. Isso é o que podemos usar para f varredura. F varredura f vai fazer isso na linha de comando. Eu estou realmente certeza que isso é o que a biblioteca CS50 faz. Então, quando você diz, "obter int," é exame f-ing mais - f verificação é a maneira que você obter entrada do usuário. F varredura f vai fazer a mesma coisa, mas usando um arquivo de digitalizar mais. Então, aqui, estamos varredura sobre este arquivo. O padrão que estamos tentando combinar alguma string que é de 127 caracteres seguido por uma nova linha Então, eu tenho certeza que nós poderíamos mesmo dizer "corresponder s", já que no dicionário acontece que temos, estamos garantidos nenhuma palavra é muito tempo, e também f f scan, eu acho, vai parar na linha de novo, não importa o quê. Mas vamos incluir a linha nova no jogo, e - [Estudante] Se não incluir a nova linha, não seria encontrar partes de uma palavra? Ele - cada um - olhando para o dicionário - Assim, no dicionário, estas são todas as nossas palavras. Cada um está em uma nova linha. O f varredura vai pegar essa palavra. Se não incluir a linha nova, então é possível que o f próxima varredura só vai ler a nova linha. Mas incluindo nova linha então simplesmente ignorar a nova linha. Mas nós nunca vamos obter parte de uma palavra, uma vez que estamos sempre lendo-se para uma nova linha, não importa o quê. [Estudante] Mas e se você procurar a palavra "Cissa", como Cissa. Será que vai encontrar isso, e dizer que é um jogo? Então aqui estamos nós - ele irá ler a - este é realmente um bom ponto. Nós nunca está usando o atual - a palavra que estamos procurando é o primeiro argumento da linha de comando. Assim a palavra de corda, argv = 1. Assim que a corda que estamos procurando é uma argv. Não estamos à procura de uma palavra em tudo na nossa f digitalização. O que estávamos fazendo com varredura f está ficando cada palavra no dicionário, e, em seguida, uma vez que temos que palavra vamos usar strcmp para compará-los. Vamos comparar a nossa palavra eo que acabamos de ler dentro Então, inevitavelmente, nós vamos acabar fazendo um monte de varredura fs até que isso só acontece que f digitalização vai voltar - ela retorne um, desde que igualou uma nova palavra, e retornará algo mais, logo que falhou para coincidir com a palavra. Estamos lendo todo o dicionário, armazenar linha por linha em cada palavra variável s. Em seguida, nós estamos comparando com a palavra s e, se a comparação == 0, strcmp acontece para trazer 0 se um jogo foi feito. Então, se ele for 0, então podemos imprimir f, combinado, ou palavra é no dicionário, ou o que você deseja imprimir f. E então - nós não queremos f fechar uma e outra vez. Este é o tipo de coisa que nós queremos fazer, e não estamos apenas à procura de palavra no dicionário. Então, nós poderíamos fazer isso, se quisermos olhar para o seu padrão, Cissa, como você disse antes, se queria olhar para esse padrão, então ele iria falhar no caso porque isso não é realmente uma palavra, mas uma das palavras no dicionário acontece de ter que nele. Portanto, seria combinar essa palavra, mas este subconjunto da palavra não é uma palavra em si. Mas não é assim que estamos a usá-lo, estamos lendo cada palavra e depois comparando a palavra que temos com essa palavra. Então, nós estamos sempre comparando palavras completas. Eu posso enviar as soluções finalizados depois. Este é o tipo de quase a resposta certa, eu acho. [Comentário do estudante, ininteligível] Ah, eu se livrar do que antes? Char s, acho que disse 127 - eu esqueço o que o maior é. Nós vamos apenas fazer 128; agora s é o tempo suficiente. Nós não precisar imprimir nada. Nós também vamos querer ter que fechar o nosso arquivo, e que deve ser sobre a resposta certa. CS50.TV