introdução à computação - intranet.ifs.ifsuldeminas.edu.brkleber.rezende/anterior... · de...

Post on 09-Dec-2018

215 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Sub Rotinas

Estrutura de Dados

Prof. Kleber Rezende

Considerações Iniciais

Uma dos métodos mais comuns e

amplamente utilizados em programação

de computadores é o Top-Down.

Nesta abordagem um problema é

dividido em problemas menores.

Após sua divisão em um número

adequado de partes, chamadas de

subproblemas ou sub-rotinas.

Considerações Iniciais

Estes subproblemas são resolvidos

individualmente, levando a solução do

problema completo.

O processo é bastante simples.

Inicialmente deve-se definir o que deve

ser feito, sem levar em consideração

como será feito.

Considerações Iniciais

Se os subproblemas gerados com a

pergunta “o que” forem suficientemente

simples, deve-se então pensar em como

resolver cada um deles, considerando os

aspectos de algoritmos ou uma

linguagem de programação específica.

Exemplo

Crie um algoritmo que leia o nome o

número de filhos e o salário bruto de

uma pessoa. Em seguida o programa

deve calcular e imprimir o nome e o

salário final do funcionário. O salário

final é calculado descontando o imposto

de renda do salário bruto e adicionando

um auxílio de acordo com o número de

filhos desta pessoa (auxílio família).

Exemplo

As taxas de desconto do imposto de renda e o

valor do auxílio família são dados abaixo.

Imposto de Renda:

Salário até R$ 1000,00 – Isento.

De R$ 1000,01 a R$ 1800,00 – 15%.

Acima de 1800,00 – 27,5%.

Auxílio Família:

1 filho – R$ 100,00

2 filhos – R$ 180,00

3 ou mais filhos – R$ 240,00

Possível Solução

1. Cálculo do Salário

1.1 Ler os dados de entrada

1.2 Calcular o desconto do imposto de renda

1.2.1 Verificar faixa salarial

1.2.2 Fazer o desconto

1.3 Calcular o Auxílio Família

1.3.1 Verificar o número de filhos

1.3.2 Calcular o abono

1.4 Calcular o Salário Líquido

1.5 Imprimir os resultados

Possível Solução

Considerações Iniciais

A partir deste momento o programador

deve se preocupar com cada um dos

problemas individualmente, tornando

assim o processo de resolução mais

simples.

Considerações Iniciais

É importante observar que neste caso a

divisão do problema principal apenas

uma vez não foi suficiente, já que os

dois subproblemas gerados (Desconto

de Imposto de Renda e Cálculo do

Auxílio Família) ainda não eram tão

simples de serem resolvidos.

Considerações Iniciais

Desta forma, o processo de divisão foi

repetido até que o programador

considerasse que todos os subproblemas

gerados fossem suficientemente simples.

Considerando que cada pessoa possui

características próprias para resolver

problemas, vale destacar que não existe

uma única quantidade de divisões que

pode ser considerada correta.

Considerações Iniciais

É importante que cada pessoa

desenvolva este processo de forma a

facilitar ao máximo o processo de

codificação, sem se preocupar se o

número de subproblemas gerados por

ele é igual ao apresentado por outras

pessoas.

Codificando ...

main ()

{

char nome[15];

int nfilhos;

float IR=0, auxilio, sliquido, sb, desconto;

//LER OS DADOS DE ENTRADA

printf("digite o nome da pessoa: ");

scanf("%s", nome);

printf("Entre com o numero de filhos: ");

scanf ("%d", &nfilhos);

printf("Entre com o salario bruto: ");

scanf ("%f", &sb);

//continua ...

Codificando ...

//...continuação

//CÁLCULO DO IMPOSTO DE RENDA

//VERIFICAR A FAIXA SALARIAL

if ((1000 < sb) && (sb <= 1800))

IR = sb * 0.15;

else if (sb > 1800)

IR = sb * 0.275;

//continua ...

Codificando ...

//...continuação

//CÁLCULO DO AUXÍLIO

//VERIFICACAO DO NUMERO DE FILHOS

switch (nfilhos)

{

case 0: auxilio = 0; break;

case 1: auxilio = 100; break;

case 2: auxilio = 180; break;

default: auxilio = 240; break;

}

//continua ...

Codificando ...

//...continuação

//CÁLCULO DO SALÁRIO LÍQUIDO

sliquido = sb - IR + auxilio;

//IMPRESSÃO DOS RESULTADOS

printf ("%s, ", nome);

printf ("o salario liquido eh: %.2f", sliquido);

} //FIM DA ROTINA MAIN

Modularização

É a divisão de um programa em partes gerenciáveis

(módulos) e, em seguida, na montagem destas

partes em um fluxo coerente e lógico.

A modularização em conjunto com a abordagem

Top-Down, são de extrema importância à medida

que o tamanho dos programas desenvolvidos

aumenta.

Nestes casos, a resolução de todo o problema em

um único bloco de código é praticamente inviável

pois torna o programa “ilegível” o que dificulta a

manutenção e atualização do mesmo.

Modularização

Além disto a modularização possibilita que:

1. Partes dos programas sejam construídas e

testadas separadamente;

2. Trechos de códigos que aparecem várias vezes

dentro do programa sejam implementados e

testados uma única vez;

3. Bibliotecas sejam construídas com módulos que

podem ser utilizados em diferentes programas.

Modularização

As ferramentas utilizadas para modularizar um

programa são as sub-rotinas.

Quando um programa é desenvolvido

utilizando a modularização, o mesmo é

composto por um, e apenas um, programa

principal, e por uma série de módulos (sub-

rotinas).

Esta técnica é conhecida como Programação

Estruturada.

Modularização

Programa Principal é o bloco de código por

onde um programa inicia sua execução. Este

pode conter os comandos de controle de um

programa (sequência, seleção e repetição),

bem como a chamada para as suas sub-

rotinas. Apesar de ser mais fácil desenvolver

primeiro o programa principal e em seguida os

módulos necessários, em linguagens como

ANSI C ele deve ser o último bloco do

programa.

Modularização

Sub-rotinas são blocos de código utilizados

para resolver pequenas partes do problema.

Eles podem conter os mesmos elementos do

programa principal, inclusive declaração de

tipo e variáveis próprias, chamadas para

outras sub-rotinas, etc.

Sua diferença, está no fato de que as sub-

rotinas não são executadas automaticamente

quando o programa é iniciado, e sim, apenas

quando são chamadas.

Modularização

Portanto, o simples fato de declarar uma sub-

rotina não implica na execução da mesma.

Para que a execução seja efetuada a sub-

rotina deve ser chamada pelo programa

principal ou por outro módulo.

Modularização

Uma sub-rotina deve sempre retornar um

valor ao módulo que a chamou em seu próprio

nome.

Este valor é lido ou calculado dentro da sub-

rotina (função) e utilizado no programa

principal no cálculo de alguma expressão ou

simplesmente atribuindo-o a uma outra

variável.

Modularização

Na declaração de uma sub-rotina deve-se

sempre definir o tipo do valor que ela retorna

em seu nome.

Esta definição deve ser feita antes de seu

nome.

Caso a sub-rotina não retorne valor, deve-se

usar a palavra reservada void como tipo de

retorno.

Modularização

Na declaração de uma sub-rotina deve-se

sempre definir o tipo do valor que ela retorna

em seu nome.

Esta definição deve ser feita antes de seu

nome.

Caso a sub-rotina não retorne valor, deve-se

usar a palavra reservada void como tipo de

retorno.

Voltando ao exemplo anterior

Resolva o problema anterior (cálculo do

salário líquido) utilizando as estruturas de

modularização (sub-rotinas)

Codificando ...

char nome[15];

int nfilhos;

float IR=0, auxilio, sliquido, sb, desconto;

void LerDados ()

{

//LER OS DADOS DE ENTRADA

printf("digite o nome da pessoa: ");

scanf("%s", nome);

printf("Entre com o numero de filhos: ");

scanf ("%d", &nfilhos);

printf("Entre com o salario bruto: ");

scanf ("%f", &sb);

}

Codificando ...

float CalculaImposto ()

{

//CÁLCULO DO IMPOSTO DE RENDA

//VERIFICAR A FAIXA SALARIAL

if ((1000 < sb) && (sb <= 1800))

return sb * 0.15;

else if (sb > 1800)

return sb * 0.275;

else

return 0;

}

Codificando ...

float CalculaAuxilio ()

{

//CÁLCULO DO AUXÍLIO

//VERIFICAÇÃO DO NÚMERO DE FILHOS

switch (nfilhos)

{

case 0: return 0; break;

case 1: return 100; break;

case 2: return 180; break;

default: return 240; break;

}

}

Codificando ...

float CalculaLiquido ()

{

//CÁLCULO DO SALÁRIO LÍQUIDO

return sb - IR + auxilio;

}

void ImprimeResultados ()

{

//IMPRESSÃO DOS RESULTADOS

printf ("%s, ", nome);

printf ("o salario liquido eh: %.2f", sliquido);

}

Codificando ...

main ()

{

LerDados ();

IR = CalculaImposto ();

auxilio = CalculaAuxilio ();

sliquido = CalculaLiquido ();

ImprimeResultados ();

} //FIM DA ROTINA MAIN

Escopo de Variáveis

Define-se como Escopo de uma variável a

abrangência que a mesma tem dentro de um

programa.

Com relação a este aspecto as variáveis

podem ser Globais ou Locais.

Se uma variável é declarada fora de qualquer

sub rotina, esta é chamada de variável global

e pode ser referenciada (utilizada) em

qualquer parte do programa (programa

principal, procedimentos e funções).

Escopo de Variáveis

Quando uma variável é declarada dentro de

uma função, esta é conhecida como uma

variável local e só pode ser referenciada

dentro da função em que foi declarada, ou em

funções que tenham sido criadas dentro do

módulo onde a variável foi declarada.

Isto permite que uma grande quantidade de

memória seja economizada em programas

com muitas variáveis.

Escopo de Variáveis

Variável global é uma das ferramentas

utilizadas para comunicação (passagem de

valores) entre diferentes módulos do

programa.

Exemplo

int base, expoente, resultado;

void LerDados ()

{

//LER OS DADOS DE ENTRADA

printf("digite a base: ");

scanf("%d", &base);

printf("digite o expoente: ");

scanf ("%d", &expoente);

}

Fazer um programa que leia dois números

(BASE e EXPOENTE) e retorne como resultado

o valor de BASE elevado ao EXPOENTE..

Exemplo

void Calcule_Potencia()

{

int i;

resultado = 1;

for (i=1; i <= expoente; i++)

resultado = resultado * base;

}

void Escreva_Dados ()

{

//IMPRESSÃO DOS RESULTADOS

printf ("O número %d elevado a potencia %d é

igual a %d.", base, expoente, resultado);

}

Exemplo

main ()

{

LerDados ();

Calcule_Potencia ();

Escreva_Dados ();

} //FIM DA ROTINA MAIN

Escopo de Variáveis

Apesar de possível, não é aconselhado utilizar

variáveis globais para passar valores entre

diferentes módulos do programa.

Isto, além de em muitos casos alocar memória

desnecessariamente, faz com que a

modularidade do programa não seja tão

eficiente, gerando erros e dificultando a

depuração e manutenção dos programas.

Escopo de Variáveis

Alguns exemplos de problemas decorrentes

da utilização de variáveis globais dentro de

funções são:

pode-se perder o controle de quais módulos estão

acessando uma determinada variável;

é mais difícil aproveitar uma função já prontos em

outros programas.

Tipos de Parâmetros

Para enviar dados de um módulo para outro

devem ser utilizados Parâmetros.

É através deles que os dados necessários

para a resolução de um problema dentro de

uma função são passados para as mesmas,

bem como valores são retornados destes

módulos para o programa principal.

Tipos de Parâmetros

Mesmo não sendo obrigatório, aconselha-se

que toda variável global seja utilizada apenas

no programa principal.

Quando esta precisar ser referenciada dentro

de uma função, ela deve ser passada como

parâmetro, a fim de evitar erros na lógica do

programa.

Tipos de Parâmetros

Existem dois tipos de parâmetros: os

parâmetros formais e os atuais.

Parâmetros formais são aqueles declarados

em uma função específica, que recebem os

valores vindos do módulo (programa principal

ou outro módulo) que o chamou.

Tipos de Parâmetros

Os parâmetros formais ficam armazenados na

memória apenas enquanto a sub rotina na

qual foram declarados está sendo executada.

Após isto, estas variáveis deixam de existir e o

seu valor é apagado, assim como as variáveis

locais daquele módulo.

Tipos de Parâmetros

Os parâmetros atuais são as variáveis cujos

valores são passados para os parâmetros

formais no início da execução de uma sub

rotina e que, em alguns casos, recebem de

volta os valores dos parâmetros formais ao

término da execução da mesma.

O fato de um parâmetro atual receber de volta

o valor do parâmetro formal ao final da

execução de um módulo depende da forma

com que o este foi declarado.

Formas de declaração de

Parâmetros Formais

Os parâmetros formais podem ser declarados

de duas maneiras.

A primeira forma de passagem de parâmetros

é a passagem por valor.

Nela é feita uma cópia do valor da variável

(parâmetro atual) que é armazenado no

parâmetro formal dentro da sub rotina

chamada.

Formas de declaração de

Parâmetros Formais Desta forma, qualquer alteração feita no

parâmetro formal dentro da sub rotina, não

terá efeito na variável original (parâmetro

atual).

Este tipo de passagem é utilizado quando se

deseja enviar algum valor para as funções,

sendo desnecessário o seu retorno para o

bloco chamador (parâmetros de entrada).

Neste caso qualquer alteração nos

parâmetros formais não afetaria os

parâmetros atuais.

Formas de declaração de

Parâmetros Formais

A segunda forma é a passagem por

referência.

Nela, o endereço da variável (parâmetro atual)

é enviada do bloco chamador (este pode ser o

programa principal ou qualquer função do

programa), para o bloco chamado.

Formas de declaração de

Parâmetros Formais

Neste caso, o parâmetro formal não é uma

variável comum que armazena um valor.

Ele armazena uma referência para o

parâmetro atual.

Assim, qualquer alteração feita no parâmetro

formal dentro da sub rotina chamada afetará a

variável (parâmetro atual) no bloco chamador.

Formas de declaração de

Parâmetros Formais

Este tipo de passagem de parâmetros é

comum quando se deseja que o módulo

chamado, retorne alguma informação através

daquele parâmetro (parâmetro de saída).

Na linguagem C, para declarar que um

parâmetro é passado por referência deve ser

adicionado o caractere * antes do nome do

parâmetro formal.

Formas de declaração de

Parâmetros Formais

Na linguagem C, para chamar uma função

necessite que um parâmetro seja passado por

referência deve ser adicionado o caractere &

antes do nome do parâmetro atual.

Exemplo:

void funcao_exemplo (int *parFormal)

{ }

void main ()

{ int parAtual;

funcao_exemplo (&parAtual); }

Exercícios

1) Crie um programa que calcule o fatorial de dois

números e imprima a soma destes números. Utilize

funções para a modularização da solução.

2) Crie uma função que retorne o MENOR entre dois

valores inteiros.

3) Elaborar um programa que utilize uma sub rotina

para calcular a serie de Fibonacci de N termos. A

série de Fibonacci é formada pela sequência : 1, 2, 3,

5, 8, 13, 21, 34, ..., etc. Esta série caracteriza-se pela

soma de um termo posterior com o seu subsequente,

e ela deve ser impressa até que o último elemento

não ultrapasse o valor de entrada N.

Exercícios

4) Um programa que leia o nome o número de filhos e o

salário bruto de uma pessoa. Em seguida o programa

deve calcular e imprimir o nome e o salário final do

funcionário. O salário final é calculado descontando o

imposto de renda do salário bruto e adicionando um

auxílio de acordo com o número de filhos desta

pessoa (auxílio família). Faça a passagem de

parâmetros por valor e por referência ao invés de

utilizar variáveis globais.

As taxas de desconto do imposto de renda e o valor

do auxílio família são as mesmas informadas

anteriormente.

Exercícios

5) Faça um algoritmo que sorteie um número entre 1 e

50*. O usuário terá direito a três palpites, e a cada

tentativa o programa deve dizer se o número

sorteado é maior ou menor que o número digitado

pelo usuário. A execução do programa deve terminar

quando o usuário acertar o número ou tiver feito as

três tentativas sem sucesso. No final, o programa

deve emitir uma mensagem parabenizando o

usuário, caso tenha acertado, ou dizendo que ele não

obteve sucesso.

Exercícios

* O comando 1 + rand() % 50; sorteia um número entre 1

e 50. E o comando srand( (unsigned)time(NULL) );

renova o sorteio e evita que seja sempre sorteado o

mesmo número.

6) Continuando com o exercício anterior, aprimore o

programa para caso o usuário não tenha acertado.

Faça com que o programa dê mais uma chance para

o usuário, sendo que essa chance será calculada

pelo próprio programa através da média (inteira) dos

três palpites do usuário. No final, o programa deve

emitir uma mensagem parabenizando o usuário, caso

tenha acertado, ou dizendo que ele não obteve

sucesso.

Exercícios

7) Elaborar um programa que utilize uma sub-rotina

(função) que recebe um número e retorna esse

número sempre positivo.

8) Faça uma função que recebe por parâmetro o raio de

uma esfera e calcula o seu volume (v = 4/3.P.R3)

9) Faça uma função que receba a idade de uma pessoa

em anos, meses e dias e retorne essa idade

expressa em dias (Considere que os anos possuam

365 dias, e que os meses possuam 30 dias).

top related