Prévia do material em texto
Modularização Profa. Marluce Rodrigues Pereira Necessidade Problemas simples podem ser resolvidos diretamente em um algoritmo, mas em geral a realização de uma determinada tarefa envolve a decomposição em uma sequência de passos. Em geral, é possível dividir problemas maiores em uma sequência de problemas menores. Conforme uma tarefa cresce e se torna mais complexa, surge uma série de situações a serem resolvidas para que este problema possa ser solucionado. Novos moradores na república Imagine que três dos cinco moradores da república que você mora acabaram de se formar e agora você terá que arrumar novos companheiros para a moradia. Para divulgar as vagas, é ideal que você possa indicar qual a média de gastos geral da casa com a maior precisão possível. Dessa forma, você precisa calcular a média de gastos com energia, com água e com despesas com alimentação nos últimos cinco meses. Novos moradores na república O algoritmo para essa tarefa poderia ser: - leia os valores gastos com energia nos últimos cinco meses. - calcule a média de gastos com energia. - leia os valores gastos com água nos últimos cinco meses. - calcule a média de gastos com água. - leia os valores gastos com alimentação nos últimos cinco meses. - calcule a média de gastos com alimentação. - informe a média de gastos com água, com energia e com alimentação. Modularização - i Um algoritmo que envolve um problema grande pode ser dividido em subalgoritmos ou módulos, com o objetivo de: ● reduzir a complexidade do código; ● diminuir o tamanho do código; ● modificações podem ser feitas apenas nos subalgoritmos, com reflexo no programa como um todo. Modularização - ii A modularização envolve o uso de técnicas como subprogramas, métodos, rotinas, módulos, unidades, bibliotecas, etc.. 👉Iremos nos focar em funções e procedimentos. Visão Geral Algoritmo Grandão: SubAlgoritmo1( ); SubAlgoritmo2( ); SubAlgoritmo3( ); Fim Algoritmo Grandão; Os subalgoritmos são implementados fora do algoritmo principal. Exemplo - Média - i Considere o problema do cálculo de gastos na república. Você precisa fazer o cálculo da médias dos gastos com água nos últimos cinco meses. float mes1, mes2, mes3, mes4, mes5; cin>>mes1>>mes2>>mes3>>mes4>>mes5; float mediaAgua; mediaAgua = (mes1 + mes2 + mes3 + mes4 + mes5)/5; 🙈 Repetir o código não é prático! 😒 E imagine ter que fazer isso para vários polinômios!!! Exemplo - Média - ii O cálculo precisa ser repetido para os gastos com energia e com alimentação. Mas poderia ter outras despesas ainda a serem consideradas. 🙈 Repetir o código não é prático! 😒 E imagine ter que fazer isso para várias despesas!!! Subprogramas (módulos/rotinas) Em C/C++ é possível definir subprogramas (módulos/rotinas) da seguinte forma: tipo r rotina (tipo 1 parâmetro 1 , ... , tipo n parâmetro n ) { // código da rotina ... ... return valor_retorno; } Subprogramas (módulos/rotinas) Em C/C++ é possível definir subprogramas (módulos/rotinas) da seguinte forma: tipo r rotina (tipo 1 parâmetro 1 , ... , tipo n parâmetro n ) { // código da rotina ... ... return valor_retorno; } tipo r Parâmetro x argumento tipo r rotina (tipo 1 parâmetro 1 , ... , tipo n parâmetro n ) { // código da rotina ... ... return valor_retorno; } Como? Podemos definir então uma função media()da seguinte forma: float media (float m1, float m2, float m3, float m4, float m5) { float m; m = (m1 + m2 + m3 + m4 + m5)/5; return m; } Para usar, basta chamar dentro do programa principal. #include <iostream> using namespace std; float media (float m1, float m2, float m3, float m4, float m5) { float m; m = (m1 + m2 + m3 + m4 + m5)/5; return m; } int main() float mediaAgua; float mes1, mes2, mes3, mes4, mes5; cin>>mes1>>mes2>>mes3>>mes4>>mes5; mediaAgua = media(mes1,mes2,mes3,mes4,mes5); cout << mediaAgua << endl; return 0; } Vantagens 1. Ajuda a resolver o problema, dividindo-o 2. Reusabilidade 3. Permite delimitar o escopo de variáveis, economizando memória 4. Evita repetição de código Chamada de Subprograma Para usar um subprograma, usamos seu nome junto com a sua lista de parâmetros (valores). O subprograma precisa ser declarado antes de ser utilizado. Um subprograma deve ser declarado fora de outros subprogramas, inclusive a main(). Um subprograma pode ser chamado de dentro de outros subprogramas. Fluxo de Execução int main ( ) { int x, y, z; comandos; a = foo(x, y, z); comandos; return 0; } int foo(int m, int n, int p){ comando_1; comando_2; ... comando_n; return valor; } Execução de Subprograma ● Cada argumento da lista de parâmetros é avaliado; ● Seus tipos são analisados e os valores passados na chamada são atribuídos aos parâmetros formais do subprograma; ● O corpo do subprograma é executado; ● Ao término, o fluxo de execução retorna imediatamente após o ponto de chamada do subprograma. Execução de Subprogama Os comandos no corpo do subprograma são executados até que: ● Se encontre um comando de retorno (return); ● Não existam mais comandos no corpo da função para serem executados. O valor da expressão return, se ele existir, é avaliado e retornado como valor da função ao programa que chamou sua execução. Funções e Procedimentos Um subprograma que não retorna, isto é, não produz nenhum valor, tem tipo de retorno void. Em termos de nomenclatura formal, subprogramas com retorno recebem o nome de função. Subprogramas sem retorno recebem o nome de procedimento. Função main O main(), como vocês já devem ter percebido é também uma função, a função principal, responsável por iniciar o programa. int main(){ return 0; } int main( int argc, char *argv[ ] ) { return 0; } Escopo de Variáveis O escopo de uma variável define o conjunto de sentenças (instruções) no qual a variável é visível (acessível). Uma variável é visível em uma sentença se ela pode ser referenciada nesta sentença. As regras de escopo de uma linguagem determinam como uma ocorrência em particular de um nome é associada com uma variável. Variáveis Locais e Globais Uma variável é local a uma unidade ou a um bloco de programa se ela for lá declarada. Variáveis declaradas dentro de subprogramas são visíveis apenas dentro do subprograma. Variáveis do programa, isto é, aquelas que não são declaradas dentro de nenhuma sub-rotina, são chamadas de variáveis globais e podem ser acessadas em qualquer parte do código. O uso não é recomendado! Exemplo - Escopo Não há problemas em ter um código com as seguintes funções: int max(int A, int B) { if (A > B) { return A; } else { return B; } } int maxTres(int A, int B, int C) { int maior = A; maior = max(maior, B); maior = max(maior, C); return maior; } Escopo Diferente Passagem de Parâmetros - Cópia ou Valor Passagem por cópia ou por valor: as variáveis passadas como parâmetro não têm seu valor modificado dentro da função. Quando uma função recebe um argumento, ela faz uma cópia. O parâmetro contém uma cópia do valor da variável original. Mudar o parâmetro não muda a variável original. Passagem de Parâmetros - Referência Passagem por referência: não é feita uma cópia da variável. Um parâmetro que seja alterado internamente na função irá refletir essa alteração no código externo à função. Para indicar que um parâmetro está sendo passado por referência, em C++ utiliza-se o símbolo &. Exemplo: Passagem por Valor void troca(int a, int b) { int aux = a; a = b; b = aux; } int main() { int x= 10, y = 5; troca(x,y); //x e y inalterados!!! return 0; } Exemplo: Passagem por Referência void troca(int& a, int& b) { int aux = a; a = b; b = aux; } int main() { int x= 10, y = 5; troca(x,y); //x e y alterados!!! return 0; } Exemplo de uso - i Juros compostos são aplicações de juros sobre juros, isto é,os juros compostos são aplicados no montante de cada período. Para entender melhor, veja como fica a aplicação mês a mês dos juros: Primeiro mês: M= C × (1+i) Segundo mês: M= C × (1+i) × (1+i) Para simplificar, obtemos a fórmula a seguir: M = C × (1+i)t, em que: ● M é o montante final ● i é a taxa de juros aplicada ● C é a capital ou valor inicial ● t é o tempo de investimento Faça um programa que receba os valores necessários e, com uma função, faça as devidas contas e retorne um float como resultado. #include <iostream> #include <cmath> using namespace std; float juroComposto (float taxa, float capital, int periodo){ float montante; montante = capital * pow((1+taxa), periodo); return montante; } int main(){ float M, i, C; int t; //a taxa deve ser inserida em porcentagem, por exemplo, 2.5 //representa a taxa de 2.5% cin >> i >> C >> t; i/=100; M = juroComposto(i,C,t); cout <<M; return 0; } Exemplo de uso - ii Escreva um programa que receba dez pontos no plano, descritos por suas coordenadas x e y, e imprima qual o ponto mais próximo do primeiro ponto lido. A distância entre dois pontos (X1, Y1) e (X2, Y2) é dada por: Execução Entrada 2.3 4.1 2.2 9.8 1.1 3.2 0.9 12.4 5.8 6.3 0.0 0.0 9.9 9.9 1.0 1.0 9.8 9.8 10.1 10.1 Saída 1.1 3.2 Para praticar Faça um programa que leia um conjunto de valores em polegadas. Em seguida, converta cada valor para centímetros e depois pés. O seu programa deve ter duas funções: 1 - conversão entre polegadas e centímetros; 2 - conversão entre metros e pés. Cada chamada de função realiza uma conversão. A função principal será responsável pela leitura e impressão dos dados. Os valores devem ser lidos até que se encontre uma entrada negativa. 1 pol → 2,54 cm 1 m → 3,281 pés Execução 10 10 : 25.4 : 0.833374 3.2 3.2 : 8.128 : 026668 5.9 5.9 : 14.986 : 0.491691 9.6 9.6 : 24.384 : 0.800039 13.4 13.4 : 34.036 : 1.11672 -1 Sobre o material Material produzido coletivamente, principalmente pelos seguintes professores do DCC/UFLA: ● Janderson Rodrigo de Oliveira ● Joaquim Quinteiro Uchôa ● Juliana Galvani Greghi ● Renato Ramos da Silva ● Marluce Rodrigues Pereira Inclui contribuições de outros professores do setor de Fundamentos de Programação do DCC/UFLA. Esta obra está licenciado com uma Licença Creative Commons Atribuição 4.0 Internacional. http://creativecommons.org/licenses/by/4.0/