DOUG LLOYD: Tudo bem. Então agora vamos enfrentar uma tópico realmente grande, as funções. Até agora, no curso, todo o programas que tenho escrito ter sido escrito dentro do principal. Eles são programas muito simples. Você não precisa ter todos estes ramos e coisas acontecendo. Podemos apenas caber tudo dentro de principal e não ficar terrivelmente esmagadora. Mas, como o curso vai sobre e quando você começa a desenvolver programas de forma independente, eles provavelmente vão a começar a ficar muito mais do que 10 ou 15 linhas. Você pode ter centenas ou milhares ou dezenas de milhares de linhas de código. E isso realmente não é que um pensamento louco. Como tal, ele provavelmente não é uma boa idéia para manter tudo dentro do principal. Pode ficar um pouco difícil de encontrar o que você está procurando se você fizer isso. Felizmente, porém C, e praticamente cada outra linguagem de programação que pode trabalhar, permite nós escrever funções. E eu estou indo só para tomar um rápido aparte aqui de mencionar que é funções uma área da ciência da computação. E você vai ver muitos mais deles em vários pontos ao longo do curso e se você continuar. Onde há um monte de sinónimos para a mesma palavra. Então, nós chamamos as funções. Mas você também pode ouvi-los referido como procedimentos, ou métodos, em particular, se você já feito qualquer programação orientada a objeto antes-- e não se preocupe se você não tiver, não uma grande mas em deal-- linguagens orientadas auditoria são freqüentemente chamados métodos. Às vezes, eles são chamados de sub-rotinas. Mas eles realmente se referem para a mesma ideia de base. Vamos ver o que é idéia. O que é uma função? Bem é realmente uma função nada mais do que uma caixa preta. A caixa preta que tem um conjunto de zero, ou mais entradas e um única saída. Assim, por exemplo, esta pode ser uma função. Esta é uma função chamada func. E leva três entradas a, b e c. E dentro dessa caixa preta, que Não sei exatamente o que ele faz, mas ele processa as entradas de alguma forma e então dá uma única saída, neste caso, Z. Agora, para torná-lo um pouco menos abstrata, nós poderia dizer que talvez nós têm uma função chamada acrescentar que leva três entradas a, b, e C e processa a saída de alguma maneira dentro da caixa preta para produzir uma única saída. Portanto, neste caso, se adicionar leva de 3, 6, e 7. Em algum lugar dentro do adicionar a função, faríamos esperar que eles sejam adicionados em conjunto para produzir a saída, que é 3 mais 6 mais 7 ou 16. Da mesma forma, você tem uma função chamada mult que leva duas entradas, a e b, processa-los de alguma forma, tais que a saída da função é o produto das duas entradas. As duas entradas multiplicados juntos. 4 e 5 sendo passado para mult, algo acontece, a saída esperamos é 20. Por que chamá-lo de uma caixa preta? Bem, se nós não estamos escrevendo o Funciona nós mesmos, o que nós fizemos um pouco até agora CS50. Nós vimos de impressão f, por exemplo, que é uma função que nós não escrevemos nós mesmos, mas nós usar o tempo todo. Se não estamos escrevendo as funções de nós mesmos, nós realmente não precisa saber como é realmente implementada sob o capô. Assim, por exemplo a caixa preta I acabei de mostrar para a multiplicação, mult a, b poderiam ser defined-- e este é apenas poderia ser algum pseudocode-- definida como uma saída vezes b. Isso faz sentido, certo. Se temos uma função chamada mult que leva duas entradas. Seria de esperar que a saída seria ser as duas entradas multiplicados juntos, um vezes b. Mas também podia ser mult implementado como este, temos uma variável de contador para prepare-se para dentro de mult a 0. E, depois, repetir este processo b vezes adicionar ao contador. Por exemplo, se multiplicarmos por 3a 5b, poderíamos dizer definir contador a 0, Repita cinco vezes, adicionar 3 a balcão. Então, vamos começar em 0 e então nós fazemos isso cinco vezes 3, 6, 9, 12, 15. É o mesmo resultado. Nós ainda obter 3 vezes apenas 5 a aplicação é diferente. Isso é o que queremos dizer quando dizemos que uma caixa preta. Significa apenas que nós realmente não me importo como ele é implementado sob o capô desde que a saída é o que se espera. Na verdade, isso é parte do contrato do uso de funções, particularmente funções que os outros escrevem. O comportamento é sempre vai ser típico, imprevisível com base no nome da função. E é por isso que é realmente importante quando você escrever funções ou quando outras pessoas escrever funções que você pode usar, aqueles que têm funções nomes claros e relativamente óbvias, e estão bem documentados. Que é certamente o caso para a função de impressão como f. Então, por que usar funções? Bem, como eu disse anteriormente, se escrevermos todo o nosso código dentro das coisas principais pode ficar muito pesado e realmente complicado. Funções-nos permitir que a capacidade para organizar as coisas e acabar com um problema muito complicado em um monte sub partes mais gerenciáveis. Funções também nos permitem simplificar o processo de codificação. É muito mais fácil de depurar a 10 função de linha versus uma linha 100 função ou uma função 1000 line. Se só temos de debug pequenos pedaços de cada vez, ou escrever pequenos pedaços no momento, faz que a experiência de programação muito melhor. Confie em mim sobre isso. Por último, se escrevermos funções que pode reutilizar essas várias partes. As funções podem ser reciclados. Eles podem ser utilizados em um ou outro programa. Você já escreveu a função, tudo que você precisa fazer é dizer que o programa onde encontrar essa função. Temos vindo a reciclagem e utilização de imprimir f há mais de 40 anos. Mas ela só foi escrita uma vez. Bastante útil, certo. Tudo certo. Assim, as funções são grandes. Nós sabemos isso. Agora vamos começar a escrevê-los. Vamos começar a receber -los em nossos programas. A fim de fazer isso, o primeiro coisa que fazemos é declarar a função. Quando você declarar uma função o que está fazendo, basicamente, está dizendo o compilador, hey, só para você saber, Estou indo para ser escrito uma função mais tarde e aqui está o que ele vai olhar como. A razão para isto é porque compiladores puder fazer algumas coisas estranhas, se eles vêem um conjunto de símbolos que eles não estão familiarizados. Então, nós apenas dar o compilador um heads-up, eu estou criando uma função e ele vai fazer isso. Declarações de função geralmente se você está organizando seu código de uma maneira que os outros será capaz de compreender e fazer uso, você geralmente deseja colocar tudo de suas declarações de função no topo do seu código, direita antes de começar a escrever principal mesmo. E convenientemente, há uma forma muito normal que cada declaração de função segue. Todos eles muito bem parecido com este. Há três partes para uma função declaração, tipo de retorno, nome, e lista de argumentos. Agora, o tipo de retorno é o tipo de variável a saída da função vontade. Assim, por exemplo, se pensarmos de volta um minuto atrás para a multiplicação de dois números de função, o que esperamos se multiplicarmos um número inteiro por um número inteiro a saída será provavelmente um número inteiro, certo. Multiplicado dois inteiros juntos, você obtém um número inteiro. Assim, o tipo de retorno que função seria int. Nome é o que você quer para chamar sua função. Este é provavelmente o menos importante parte da declaração de função, em termos de funcionalidade. Mas é, na verdade, provavelmente, um das partes mais importantes da declaração da função em termos de saber o que a função realmente faz. Se você nomear sua função f ou g ou h ou mistério ou algo parecido, você provavelmente vai conseguir um pouco tropeçou tentando para lembrar o que fazer essas funções. Por isso, é importante dar o seu nomes significativos da função. Por último, lista de argumentos está a lista separada por vírgulas de todas as entradas para a sua função, cada um dos quais tem um tipo e um nome. Portanto, não só você tem que especificar o tipo de variável a saída da função vontade, você também deseja especificar que tipo e tipos de variáveis ​​as função será aceitar como entradas. Então vamos fazer um exemplo aqui. Vamos apenas dar uma olhada em uma forma mais concreta. Então aqui está um exemplo de uma função declaração de que uma função gostaria de acrescentar dois inteiros juntos. A soma dos dois inteiros vai ser um inteiro também, como acabamos discutidos. E assim o tipo de retorno, aqui em verde, seria int. Isso só nos que adicionar dois ints diz vai, no final do dia, de saída, ou cuspir de volta para nós, um número inteiro. Dado que esta função faz nós quero dar-lhe um nome significativo. Adicione dois ints parece apropriada, considerando-se nós estamos levando dois inteiros como insumos e espero que juntá-las. Pode ser um pouco de um incómodo nome e, francamente, esta função Provavelmente não é necessário uma vez que temos a adição operador, se você se lembra da nossa discussão dos operadores, anteriormente. Mas vamos apenas dizer que por causa de argumento de que esta função é útil e por isso vamos chamá-lo de adicionar dois ints. Por último, esta função tem duas entradas. Cada um dos quais é um número inteiro. Então nós temos essa vírgula lista separada de entradas. Agora nós geralmente querem dar um nome de cada uma delas de modo que eles podem ser usados dentro da função. Os nomes não são terrivelmente importante. Neste caso, nós não necessariamente tem algum significado a elas associadas. Assim, podemos apenas chamar-lhes a e b. Isso é totalmente bom. Se, no entanto, você encontrar se em uma situação onde os nomes das variáveis pode ser realmente importante, você pode querer chamá-los algo que não seja a e b para dar-lhes algo mais simbolicamente significativa. Mas, neste caso, nós realmente não saber mais alguma coisa sobre a função. Nós só queremos adicionar dois inteiros. Então vamos chamá os números inteiros a e b. Isso é um exemplo. Por que você não tomar uma segunda para pensar sobre este, como você escrever uma função declaração de que uma função Multiplica dois números de ponto flutuante? Você se lembra o que um número de ponto flutuante é? O que seria essa função declaração parece? Na verdade, eu recomendo que você pausar o vídeo aqui e levar quanto tempo você precisa. Pense sobre o que esta declaração de função seria? Qual seria o tipo de retorno ser? O que seria um nome significativo ser? Quais seriam as entradas de ser? Então, por que você não interromper o vídeo aqui e escrever-se uma declaração de função para uma função que multiplicaria dois números de ponto flutuante em conjunto. Esperamos que você parou o vídeo. Então vamos dar uma olhada em um exemplo de uma declaração possível. Float mult dois reais flutuam x, y flutuador. O produto de dois números de ponto flutuante, recordar que são como nós representam números reais ou números com valores decimais em c, vai ser um número de ponto flutuante. Quando você multiplica um decimal por um decimal, provavelmente você está indo para obter um decimal. Você quer dar-lhe um nome relevante. Multiplique dois reais parece bem. Mas você poderia realmente chamá-lo mult dois carros alegóricos, ou flutuadores mult. Qualquer coisa assim, contanto que deu algum significado real ao que essa caixa preta ia fazer. E mais uma vez, neste caso, nós não parece ter qualquer significado ligado para os nomes dos variáveis ​​que estamos passando em, por isso, só chamá-los de x e y. Agora, se você chamá-los de algo outra coisa, isso é totalmente bom. Na verdade, se você fez esta declaração em vez usando em vez de duplas de carros alegóricos, se você se lembra duplos que são uma diferente maneira a mais precisamente especificar números reais ou flutuante variáveis ​​de ponto. Isso é totalmente bem também. Ou um daqueles seria ótimo. Na verdade, existem vários combinações diferentes de maneiras de declarar esta função. Mas estes são dois muito bons. Temos declarada uma função, isso é ótimo. Dissemos o que o compilador é, o que vamos fazer. Agora vamos realmente escrever essa função. Vamos dar-lhe uma definição, de modo que dentro da caixa preta comportamento previsível está acontecendo. Na verdade, estamos multiplicando dois reais números, ou acrescentando números juntos, ou fazendo o que quer que seja que pedimos a nossa função fazer. Então, na verdade, vamos tentar definir multiplicar dois reais que acabamos falou sobre um segundo atrás. Agora, o início de a definição de função parece quase exatamente o mesmo como uma declaração de função. Eu tenho os dois aqui. No topo está a declaração de função, tipo, nome, argumento separados por vírgulas lista, ponto e vírgula. A vírgula indica que que é uma declaração de função. O início da função definição parece quase exatamente o mesmo, tipo, nome, separados por vírgulas lista de argumentos, sem ponto e vírgula, abrir chaveta. A chave de abertura, assim como temos vindo a fazer com o principal, significa que estamos agora começando a definir o que acontece no interior da caixa preta que nós decidimos chamar mult dois reais. Aqui está uma maneira de implementá-lo. Poderíamos dizer, poderíamos declarar uma nova variável do tipo float chamado produto e atribuir essa variável para o valor x vezes y. E, em seguida, devolver o produto. O que significa retorno aqui. Bem retorno é o caminho que indicam que é assim nós estamos passando a saída de volta para fora. Assim retornar algo, é o mesmo que, esta é a saída da caixa preta. Então, isso é como fazê-lo. Aqui está outra maneira de implementá-lo. Nós poderíamos apenas retornar x vezes y. x é um float. y é um float. Então x vezes y também é um float. Nós nem sequer precisa criar uma outra variável. Então essa é uma maneira diferente de implementar a mesma caixa preta exata. Agora pegue um momento, pausar o vídeo novamente, e tentar definir adicionar dois ints, que é a outra função que nós falou sobre um momento atrás. Mais uma vez aqui, eu coloquei a função declaração, e assim o ponto e vírgula, e uma chaveta aberta e um encaracolado fechado cinta para indicar onde vamos encher no conteúdo de adicionar dois ints, de modo que se define o particular comportamento dentro da caixa negra. Então, pausar o vídeo. E tirar o máximo de tempo você precisa tentar e definir uma implementação de adicionar dois ints, tais que quando da função gera um valor, isso acontece, na verdade, de retorno a soma das duas entradas. Assim como no exemplo anterior, há várias maneiras diferentes que você poderia implementar adicionar dois ints. Aqui está um. Em aqui em laranja tenho só tinha alguns comments-- Eu apenas adicionei alguns Comentários para indicar o que está acontecendo em cada linha de código. Então eu declarar uma variável chamada soma do tipo int. Eu digo soma é igual a mais b. É aí que está realmente fazendo a adição de um trabalho e B em conjunto. E eu voltar soma. E isso faz sentido, porque soma é uma variável do tipo int. E qual é o tipo de dados que este função diz-me que vai para a saída? Int. Então, eu estou voltando soma, que é uma variável inteira. E isso faz sentido, dado o que nós temos declarada e definida a nossa função fazer. Agora você também pode definir a função desta forma, int soma é igual a um plus B-- pular essa step-- primeiro e, em seguida, retornar soma. Agora você pode ter também implementou-lo desta maneira, que eu altamente não recomendo. Isso é ruim para um estilo coisa muito ruim e design, mas ele faz, de fato, o trabalho. Se você tomar este código, que é int adicionar ruim víbora ponto c, e usá-lo. Ele realmente não adicionar dois inteiros juntos. É uma aplicação muito pobre deste comportamento particular. Mas ele não funciona. É apenas para ilustrar o ponto que nós realmente não importo com o que acontece dentro a caixa preta, contanto uma vez que tem a saída que esperamos. Esta é uma caixa preta mal projetado. Mas no final do dia, ele faz saída ainda a soma de a mais b. Tudo certo. Então, nós temos funções declarou. E nós função definida. Então, isso é muito bom. Agora vamos começar a usar as funções que já declarou e nós definimos. Para chamar um function-- é realmente muito easy-- tudo o que você precisa fazer é passá-lo argumentos apropriados, argumentos do tipo de dados que espera, e em seguida, atribuir o retorno valor dessa função e isto-- desculpa me-- atribuir o valor de retorno dessa função a algo do tipo correto. Então vamos dar uma olhada isso na prática em um arquivo chamado víbora 1 ponto c, que Eu tenho no meu CS50 IDE. Então aqui está víbora 1 ponto c. No início vedes que eu tenho minha inclui, libra incluem, IO padrão, e CS50 dot h. E então eu tenho a minha declaração de função. Este é o lugar onde eu estou dizendo que eu sou o compilador vai estar escrevendo um função chamada adicionar dois ints. Vai uma saída variável do tipo integer. Isso é o que esta parte é aqui mesmo. E então eu tenho duas entradas para que uma e b, cada um dos quais é um número inteiro. Dentro do principal, eu perguntar ao usuário entrada dizendo, me dar um inteiro. E eles são solicitados para esquecer int, que é uma função que está incluída na biblioteca CS50. E isso fica armazenado em x, uma variável inteira. Em seguida, levá-los para um outro número inteiro. Ficamos com outro inteiro e armazenar que em y. E então, aqui na linha 28, é onde fazemos a nossa chamada de função. Estamos dizendo, iguais int z adicionar 2 ints x vírgula y. Você percebe por que isso faz sentido? x é uma variável do tipo inteiro e y é uma variável do tipo inteiro. Então, isso é bom. Isso faz sentido com o que a nossa função declaração na linha 17 parece. A lista de entrada separados por vírgulas espera dois números inteiros, a e b. Nesse caso, podemos chamá- eles o que nós queremos. Ele só espera dois números inteiros. E X é um número inteiro e y é um número inteiro. Isso funciona. E nós sabemos que a função está acontecendo para produzir um inteiros bem. E assim estamos armazenando o saída da função, adicionar dois ints, em um tipo inteiro variável, que estamos chamando z. E então podemos dizer, a soma de i por cento por cento e é por cento i i. x, y e z, respectivamente, preenchendo os i de por cento. Qual é a definição de adicionar dois ints parece? É muito simples. É um dos nós só vi um segundo atrás, int soma é igual a um montante acrescido b retorno. Isto funciona? Vamos salvar o arquivo. E, em seguida, para baixo aqui no meu terminal Eu vou fazer uma víbora, e eu limpar minha tela. Eu estou indo para aumentar o zoom, porque eu sei é um pouco difícil de ver. Então, nós compilar este programa como uma víbora. Então o que podemos fazer dot barra víbora 1. Dê-me um número inteiro, 10. Dê-me outro inteiro, 20. A soma de 10 e 20 é de 30. Por isso, fizemos uma chamada de função bem sucedida. Você pode executar a função novamente, negativo 10, 17 soma negativa de 10 e 17 é de 7. Esta função funciona. Tem o comportamento que esperamos que ele. E assim fizemos uma bem-sucedida função, definição, declaração, e uma chamada de função bem sucedida. Casal variado pontos sobre funções antes de concluir esta seção. Recordar da nossa discussão de tipos de dados, anteriormente, que funciona às vezes pode demorar há entradas. Se for esse o caso, declarar a função como tendo uma lista de argumentos vazio. Você se lembra o que o mais função comum temos visto até agora que leva uma lista de argumentos é nulo? É principal. Lembre-se também que a função às vezes realmente não tem uma saída. Nesse caso, nós declaramos a função como tendo um tipo de retorno void. Vamos concluir esta seção enfrentar um problema prática. Então aqui está o problema colocado para fora. Eu quero que você escrever uma função chamado triângulo válido. O que esta função deve fazer é tomar três números reais que representam os comprimentos dos três lados de um triângulo como os seus parâmetros, ou seus argumentos, ou a sua Insumos outro conjunto de sinônimos que você pode encontrar. Esta função deve quer saída de verdadeiro ou falso dependendo se estes três comprimentos são capazes de fazer um triângulo. Você se lembra do tipo de dados que nós usado para indicar verdadeiro ou falso? Agora, como você implementar isso? Bem sei que há um casal de regras relativas triângulos que são realmente úteis para saber. Um triângulo só pode ter lados com comprimento positivo. Isso faz sentido. Você provavelmente está dizendo, duh. A outra coisa a notar no entanto, é que a soma dos comprimentos de qualquer dois lados do triângulo tem de ser maior do que o comprimento do terceiro lado. Isso é realmente verdade. Você não pode ter um triângulo de lados 1, 2 e 4, por exemplo, por 1 mais 2 não é maior do que 4. Portanto, estas são as regras que determinar se ou não a três entradas podem concebivelmente formar um triângulo. Então, tome um par de minutos e declarar e, em seguida, definir esta função chamada válido triângulo, de tal modo que ela realmente tem o comportamento especificado aqui. Ele irá imprimir verdadeira se esses três lados são capazes de que compreende um triângulo, e falso caso contrário Pronto para ver como você fez? Aqui está uma implementação triângulo de válido. Não é o único. O seu pode variar um pouco. Mas isso se faz, de fato, têm o comportamento que esperamos. Declaramos nossa função no topo, bool triângulo válido flutuar x flutuador flutuador y z. Então, novamente, esta função leva três números reais como seus argumentos, flutuante variáveis ​​de valor ponto, e emite um verdadeiro ou falso valor, que é um valor booleano, recall. É por isso que o tipo de retorno é bool. Em seguida, definir a função. A primeira coisa que fazemos é verificar para se certificar que todos os lados são positivos. Se X é menor ou igual a 0, ou, se y é igual a 0, ou, se Z for inferior ou igual a 0, que não pode possivelmente ser um triângulo. Eles não têm lados positivos. E assim podemos voltar false nessa situação. Em seguida, vamos verificar para se certificar que cada par de entradas é maior do que a terceira. Assim, se x mais y é menos que ou igual a Z, ou, se x mais z é menos que ou igual a Y, ou, se y mais z é menor do que ou igual a X, que também não pode ser um triângulo válido. Então, nós return false novamente. Supondo que nós passamos tanto dos controlos embora, então podemos retornar true. Porque esses três lados são capazes de returning-- de criar um triângulo válido. E é isso. Você já declarada e definida. E você pode ser capaz de agora usar e chamar essa função. Bom trabalho. Eu sou Doug Lloyd. Este é CS50.