quarta-feira, 15 de junho de 2016

Unidades 7 e 8 - Aprendendo a Programar. Apostila Gratuita em Construção

Ir para primeira unidade da apostila de aprendendo a programar


7. Exercitando nossa Capacidade de Programação

A seguir propomos uma série de desafios que estão no mesmo nível de complexidade dos exemplos que já trabalhamos. É importante que você faça os exercícios e tenha segurança na programação.

A medida que mais conteúdos forem apresentados, teremos desafios bem mais complexos para implementar.

7.1 Vamos Encontrar o Maior e Menor Número

Neste desafio, o usuário vai entrando com números, em sequência, e cada vez  que ele entrar com um novo número, o programa deve mostrar o maior e menor número de toda a sequência até então. Ao digitar “fim”, o programa encerra.


7.2 Cálculo do Fatorial

Entrando com um número, o sistema mostrar o fatorial deste número. Exemplo, ao entrar com o número 4, o sistema irá mostrar o resultado de 4 x 3 x 2 = 24.


7.3 Cálculo do Fatorial em um Loop

Neste exemplo, faça o mesmo código anterior, porém repita o processo até o usuário digitar “fim”. Ou seja, se o usuário digitar 3, o sistema retorna 6 (fatorial de 3), depois aguarda nova entrada do usuário e exibe seu fatorial, até que a entrada do usuário seja “fim”.

7.4 Resposta dos Exercícios

Confira e, caso não tenha completado algum, confira a resposta dos exercícios propostos. Se não tiver conseguido realizar nenhum dos exercícios, confira a resposta do primeiro, estude, e então tente fazer os dois restantes.

--------------------------MAIOR E MENOR NÚMERO---------------------------
var menorNumero = 0;
var maiorNumero = 0;
var entrada = prompt("entre com um número, ou ‘fim’ para encerrar");
alert("o maior número até agora é " + entrada + " e o menor número é " + entrada );
menorNumero = parseInt(entrada);
maiorNumero = menorNumero;
while (entrada != "fim") {
entrada = prompt("entre com um número, ou ‘fim’ para encerrar");
   var temp = parseInt(entrada);
   if (temp > maiorNumero)
maiorNumero = temp;
  if (temp < menorNumero)
menorNumero = temp;
  alert("o maior número até agora é " + maiorNumero + " e o menor número é " + menorNumero);
}
------------------------------------------------------------------------------------------


--------------------------FATORIAL ---------------------------
var entrada = parseInt(prompt("entre com o número"));
resultado = entrada;

while (entrada > 1) {
  entrada = entrada - 1;
  resultado = resultado * entrada;
}
alert("O fatorial é " + resultado);
------------------------------------------------------------------------------------------
Se você não conseguiu resolver os exercícios, tente ao menos fazer o terceiro exercício tomando por base a resposta acima e os exemplos que já montamos de loops.


--------------------------FATORIAL EM LOOP---------------------------
var entrada = prompt("entre com o número");
while (entrada != "fim") {
  resultado = entrada;
  while (entrada > 1) {
    entrada = entrada - 1;
    resultado = resultado * entrada;
  }
  alert("O fatorial é " + resultado);
  entrada = prompt("entre com o número");
}
------------------------------------------------------------------------------------------
Observe que fizemos um “while” dentro de outro “while”. Este tipo de construção é muito comum.
Entretanto, se você construir um código com 3, 4, 5 ou mais condições de loop umas  dentro das outras, seu código ficará muito confuso. Para evitar isso, podemos isolar os códigos dentro de funções, recurso que veremos na unidade seguinte.




8. Criando Funções

8.1 Uma Função que Calcula o IMC

Observe o código a seguir:
--------------------------------Função para IMC ------------------------------
function calculaIMC(peso, altura)
{
  imc = peso / (altura * altura);
  return imc;
}

peso = prompt("entre com seu peso");
altura = prompt("entre com sua altura");
imc = calculaIMC(peso,altura);
alert("Seu IMC ficou em: " + imc );
if (imc < 17)   alert("muito abaixo do peso");
if ( (imc >= 17) && (imc < 18.5) ) alert("abaixo do peso");
if ( (imc >= 18.5) && (imc < 25) ) alert("peso normal");
if ( (imc >= 25) && (imc < 30) ) alert("acima do peso");
if ( (imc >= 30) && (imc < 35) ) alert("obesidade I");
if ( (imc >= 35) && (imc < 40) ) alert("obesidade II");
if (imc >= 40) alert("obesidade III");
----------------------------------------------------------------------------

Nós já vimos este código antes, só que agora ele está escrito de uma forma ligeiramente diferente. O que nós fizemos foi isolar a parte que faz o cálculo do IMC em uma código separado, que vamos chamar de função.

Vamos agora discutir como se cria uma função, como ela trabalha, quais as vantagens e desvantagens de seu uso.


8.2 Parâmetros e Retornos de uma Função

Uma função, em linguagens de programação imperativas (que é o que trataremos nesta apostila), pode receber parâmetros e pode gerar um retorno. Por exemplo, no cálculo do IMC, temos dois parâmetros, o peso e a altura. Esta função tem um retorno que é o valor do IMC calculado.

Nós já conhecemos outras funções, que fazem parte da linguagem javascript. O “alert”, por exemplo, recebe uma string, que será exibida em uma janela. O “prompt”, além de exibir o parâmetro informado, também retorna uma string com o valor fornecido pelo usuário.

Observe como especificamos os parâmetros e o retorno. Os parâmetros são definidos entre parênteses, separados por vírgula, enquanto para o retorno, utilizamos o comando “return”:

function calculaIMC(peso, altura)
{
  imc = peso / (altura * altura);
  return imc;
}

8.3 Utilizamos Funções para Não Repetir Códigos

Uma das razões mais óbvias para utilizarmos funções é evitarmos a duplicação de código. Isso é mais fácil de exemplificar em códigos com uma complexidade maior do que os códigos que vamos ver nesta apostila, mas imagine que o cálculo do IMC fosse mais complexo, envolvendo diversas linhas de código. Imagine também que seu programa precisasse calcular o IMC em diversos momentos diferentes. Ao invés de repetir o cálculo em inúmeras partes do código, fazemos o código do cálculo uma única vez, na função IMC.

8.4 Utilizamos Funções para Facilitar a Manutenção e Tornar o Código Legível

Funções permitem agrupar códigos, facilitando sua localização e alteração. Por exemplo, vamos supor que você queira agora mudar a fórmula de cálculo do IMC. Mesmo que seja utilizada uma única vez em seu programa, é muito mais fácil localizar a função IMC e fazer as alterações nela, que tentar localizar o cálculo em meio ao código. Em códigos muito grandes, esta se torna uma questão relevante.


8.5 Funções Podem Ser Utilizadas Facilmente em Outros Programas

Já que é possível criar funções que executam determinadas tarefas, não poderíamos então criar uma série de funções muito úteis e disponibilizá-las para que qualquer um as utilize em seus códigos?

Se você teve esta ideia, parabéns, você acabou de reinventar as bibliotecas de funções. Pode-se criar, por exemplo, uma biblioteca para trabalhar com objetos 3D, ou uma biblioteca das funções utilizadas normalmente em sites, ou para construção de jogos, etc. Pesquisando na internet, você encontrará bibliotecas de funções, que são basicamente conjuntos de funções prontas que realizam estas e inúmeras outras funcionalidades.


8.6 Desafio: Vamos Criar uma Primeira Função

Vamos fazer um desafio muito simples, apenas para que você pratique a criação de funções:

Crie uma função “entradaInteiro”, que funcione exatamente como a função “prompt”, exceto que, ao invés de receber uma string, a função receberá um número inteiro.

8.7 Solução

Observe o código abaixo.
--------------------------CRIANDO UMA FUNÇÃO------------------
function entradaInteiro( mensagem )
{
   retornoString = prompt(mensagem);
   retornoInteiro = parseInt(retornoString);
   return retornoInteiro;
}
------------------------------------------------------------------------------------------

Espero que tenha conseguido resolver este primeiro desafio, mas mesmo que tenha tido dificuldade, o código em si deve ser relativamente óbvio de entender.


8.8 Funções podem ser utilizadas diretamente em Cálculos  e Parâmetros

Quando queremos utilizar o retorno de uma função em um único local, não precisamos necessariamente atribuir este retorno a uma variável, para então fazer uso da variável. Podemos utilizar diretamente a função, simplificando e reduzindo o código, e não criando uma variável que efetivamente não tem nenhuma necessidade de existir.

Observe as duas evoluções do código anterior, e perceba que realizam exatamente o mesmo resultado do código original.

--------------------------ESTE É UM EXEMPLO TÍPICO------------------
function entradaInteiro( mensagem )
{
   retornoString = prompt(mensagem);
   return parseInt(retornoString);
}
------------------------------------------------------------------------------------------


---ESTE É MAIS SOFISTICADO, MAS TAMBÉM MUITO COMUM----
function entradaInteiro( mensagem )
{
   return parseInt(prompt(mensagem));
}
------------------------------------------------------------------------------------------

Isso significa que, se tivermos uma longa lista de comandos em sequência, um como entrada do outro, podemos reduzir diversas linhas a uma única chamada de funções como parâmetros de outras funções, fazendo todo um código virar uma única linha enorme, da mesma forma que este parágrafo está rapidamente se tornando uma imensa frase, gramaticalmente correta, ou pelo menos eu assim espero, mas a cada momento mais confusa e complexa de entender, a tal ponto que, se eu estivesse lendo-o em voz alta, estaria começando a perder o fôleogo e talvez mesmo estivesse quase a esquecer que o ponto original do presente texto é a discussão sobre juntar inúmeros comandos em uma única função de uma linha, e, o mais importante, possivelmente por analogia mostrando ao leitor que, no momento que perdemos clareza na leitura, estamos ultrapassando o limite do razoável na construção do código da mesma forma que, penso, este parágrafo há muito ultrapassou o que seria um tamanho consistente para uma frase.

Resumindo, qual o limite para quanto código devemos juntar em uma linha, reduzindo o uso de variáveis? O bom senso.


8.9 Funções e Escopo de Variáveis

Se você já viu códigos javascript, pode ter visto um comando chamado “var”, utilizado na declaração de variáveis. Em muitos códigos javascript você encontra este comando nas variáveis utilizadas, da seguinte forma:

--------------------------------------------------------------------------------------
var x;
x = 1;
--------------------------------------------------------------------------------------
Ou simplesmente:
--------------------------------------------------------------------------------------
var x = 1;
--------------------------------------------------------------------------------------

Até o momento eu não o havia utilizado para evitar explicações do tipo ‘apenas coloque’, ou ‘você precisa declarar a variável com “var” antes de utilizar’. Minha preocupação tem sido dar explicações consistentes e ensinar o uso de comandos a medida que seu uso se torna necessário.

A declaração de variáveis, em algumas linguagens, é utilizada para definir o tipo de uma variável, ou seja, o tipo de dados que ela vai aceitar. Por exemplo, uma variável em diversas linguagens é declarada como “int x;” para dizer que ela só aceita números inteiros, e vai acontecer um erro se você tentar atribuir a ela uma string.

Tipicamente, nestas linguagens, você só pode utilizar uma variável depois de declará-la. Isso evita um erro comum em linguagens como javascript, em que, sem querer, você comete um erro de digitação ao escrever a variável, por exemplo trocando uma letra minúscula por maiúscula, e não percebe que o programa agora faz algo diferente do que você esperava.

A linguagem que estamos utilizando para ensinar programação, javascript, não tem ‘tipos de variáveis’ (isso tem um nome, se chama linguagem fracamente tipada, em oposição a linguagens fortemente tipadas).

Entretanto, existe um outro motivo que pode tornar necessário declarar uma variável: a definição de escopo.
Para entendermos, vamos olhar e comparar os dois códigos a seguir.

--------------------------------------------------------------------------------------
var i = 1; //vamos utilizar i como o número de vezes que nosso código é utilizado.

function calculoComplexoTresNumeros( a, b, c)
{
    i = a + b; //vamos somar a e b e colocar em uma varíavel temporária
    i = i / 2;
    i = i + c;
    return(i);
}

//nosso programa vai fazer um cálculo complexo com os números 1, 2 e 3
alert(“Esta é a execução de número “ + i);
alert(“Nosso resultado é “ + calculoComplexoTresNumeros(1,2,3) );
alert(“Terminamos a execução de número “ +i);
i++;
alert(“Vamos começar a execução de número “ + i);
--------------------------------------------------------------------------------------

Existem vários motivos para o código acima ser muito ruim, e espero que a esta altura vocês não estejam mais escrevendo códigos assim. Em especial, a variável que define o número da execução deveria se chamar algum nome que o programador facilmente entendesse, como “numeroExecucao”.

Mas o verdadeiro problema aparece quando o código é executado e não faz o que era esperado.

Por quê? Porque o valor da variável ‘i’ foi alterado dentro da função. “i” é o que chamamos de uma variável global, uma variável que foi criada fora de qualquer função, e, no entanto, seu conteúdo foi alterado dentro da função “calculoComplexoTresNumeros” com o comando “i = a + b”. Quem programou a função, porém, e pode nem ter sido a mesma pessoa que criou a variável “i”, estava apenas utilizando uma variável temporária qualquer.

Este problema estará resolvido se utilizarmos o comando “var” dentro da função. Ele faz com que uma nova variável (que pode ter o mesmo nome de uma variável existente, não importa) exista apenas dentro da função, e deixe de existir quando saímos da função. O mesmo código (ainda horrível) estará correto na forma a seguir:

--------------------------------------------------------------------------------------
var i = 1; //vamos utilizar i como o número de vezes que nosso código é utilizado.
function calculoComplexoTresNumeros( a, b, c)
{
    var i = a + b; //vamos somar a e b e colocar em uma varíavel temporária
    i = i / 2;
    i = i + c;
    return(i);
}
//nosso programa vai fazer um cálculo complexo com os números 1, 2 e 3
alert(“Esta é a execução de número “ + i);
alert(“Nosso resultado é “ + calculoComplexoTresNumeros(1,2,3) );
alert(“Terminamos a execução de número “ +i);
i++;
alert(“Vamos começar a execução de número “ + i);
--------------------------------------------------------------------------------------

Chamamos a isso de escopo. O “i” de fora da função, é uma variável de escopo global, ou simplesmente variável global, e o “i” de dentro da função é uma variável de escopo local, ou simplesmente variável local.

Questões de escopo e uso de variáveis são tão importantes que retomaremos na próxima unidade, que será exclusivamente dedicada ao uso de variáveis.


Nenhum comentário:

Postar um comentário