




































Estude fácil! Tem muito documento disponível na Docsity
Ganhe pontos ajudando outros esrudantes ou compre um plano Premium
Prepare-se para as provas
Estude fácil! Tem muito documento disponível na Docsity
Prepare-se para as provas com trabalhos de outros alunos como você, aqui na Docsity
Encontra documentos específicos para os exames da tua universidade
Prepare-se com as videoaulas e exercícios resolvidos criados a partir da grade da sua Universidade
Responda perguntas de provas passadas e avalie sua preparação.
Ganhe pontos para baixar
Ganhe pontos ajudando outros esrudantes ou compre um plano Premium
Uma abordagem algorítmica para a programação em c, com exemplos de funções, algoritmos e subprogramas. O documento aborda conceitos como passagem de parâmetros por valor e por referência, declaração de identificadores, cálculo de médias e descontos, e criação de funções para resolver problemas específicos.
Tipologia: Esquemas
1 / 44
Esta página não é visível na pré-visualização
Não perca as partes importantes!





































“ Não se mede o valor de um homem pelas suas roupas ou pelos seus bens, o verdadeiro valor de um homem é o seu carácter, suas ideias e a nobreza de seus ideais. ”
- Charles Chaplin -
Este capítulo tem por objectivo ensinar a desenvolver subprogramas para serem incorporados em programas de médio porte, tornando desse modo, o desenvolvimento do software mais fácil e fléxivel. No seu término o leitor deverá ser capaz de: Justificar as vantagens de desenvolver programas com subprogramas; Saber escolher as acções que devem ser escritas como subprogramas; Definir os vários tipos de subprogramas; Saber utilizar de forma correcta os vários tipos de subprogramas; Definir os métodos de comunicação entre subproblemas; Conhecer as vantagens e desvantagens dos métodos de comunicação; Conhecer as vantegens e desvantagens da visibilidade das variáveis; Dominar as técnicas de documentação de programas. 6.1- Motivação Um dos aspectos fundamentais da programação é a decomposição de um programa em vários subprogramas. Essa decomposição tem por objectivo diminuir a complexidade do problema, partindo-o em partes mais simples. Cada subprograma tem por finalidade resolver um problema específico, que será posteriormente integrado no programa atravêz de um subprograma principal. Todos os programas desenvolvidos com essa estratégia são mais confiáveis e flexiveis. Para além disso, possuem a propriedade de serem mais simples de compreender, de desenvolver e de testar. Vamos mostrar atravéz de um exemplo como funciona esse princípio de decomposição. Pretendemos calcular a combinação de m elementos p à p que é descrita pela seguinte fórmula: (
m! p!(m−p)! Pelo método de refinamento sucessivo, numa primeira abordagem temos os seguintes passos: Versão 1 1 - Calcular m! 2 - Calcular p! 3 - Calcular (m-p)! 4 - Calcular a combinação Nos próximos passos, vamos detalhar as acções para calcular os factoriais de m, p e m-p. Fácilmente se constacta que teremos três segmentos de código
Fazem parte das boas prácticas de programação desenvolver programas como um conjunto de pequenos subprogramas independentes entre si. Os subprogramas em C são chamados de funções e o programa que junta esses subprogramas é chamado de função principal. Geralmente, os programas em C são escritos como uma combinação de funções desenvolvidas pelo programador e funções disponíveis na biblioteca padrão dessa linguagem. Qualquer sequência de instruções que aparece mais do que uma vez num programa é um forte candidato para ser um subprograma. Segundo Deitel ( 2011 ), as funções não devem ser maior do que uma página. O ideal é que elas tenham no máximo o tamanho de meia página. Essa práctica de programação facilita a reutilização do software. 6.3- Estrutura de um Programa Um programa com funções em C, possuir a seguinte estrutura. Directivas de pré-processamento Declaração das funções Definição das funções Função principal onde cada componente, com a excepção das directizes de pré-processamento, será objecto de estudo nas próximas secções. 6. 4 - Definição de Funções A definição das funções é uma area do programa onde o programador irá desenvolver as suas funções. Toda a função possui a seguinte sintaxe: < tipo >
Declaração dos argumentos: São os mecanismos de comunicação com o exterior. Cada argumento é identificado pelo seu tipo, seguido do nome e de uma vírgula. Em termos formais: tipo 1 argumento 1 , tipo 2 argumento 2 , … , tipon argumenton; Declaração dos Identificadores: São as variáveis e as constantes que serão utilizadas no corpo da função. Comandos da função: São as instruções que resolvem um problema específico. Valor de retorno será objecto de estudo nas próximas linhas. Por exemplo, a função que descrevemos em seguida, recebe como argumento, um determinado valor em graus centígrados e devolve via valor de retorno, o correspondente valor em graus Fahrenheit. float fahrenheit( int c) /* cabeçalho da função / { float f; f = 9.0/5.0c + 32; return f; } Para efeitos de notação utilizaremos as palavras recebe ou devolve quando a comunicação for feita pelos argumentos e retorna quando a comunicação for feita pelo valor de retorno. Os argumentos que aparecem no cabeçalho da função são chamados de parâmetros formais porque durante a execução do programa, eles serão substituídos por variáveis, valores ou expressões. 6.5- Declaração de Funções A Declaração de Funções , que passaremos a denominar por Protótipo de Funções é uma área do programa onde o programador declara as funções que vai utilizar no programa. Esta declaração consiste na definição do tipo da função e nos argumentos que ela recebe. Por exemplo, no protótipo da função float fahrenheit( in t c); informamos ao compilador, que a função de nome fahrenheit é do tipo real e recebe um valor do tipo inteiro. A declaração de qualquer função no protótipo de funções é obrigatória e deve terminar com um ponto-e-vírgula.
int impar( int numero) { if (numero%2 == 0) return 1; return 0; } O tipo de dados de uma função deve ser igual ao tipo de dados retornado pelo comando return. O tipo de dados do valor retornado é que determina o tipo de dados de uma função e não ao contrário. 6.7- Função Principal Em C, o programa principal é uma função especial denominada por função principal que é indicada pela sentença int main(). Quando essa sentença for accionada o programa entra em funcionamento. Constitui um padrão de programação em C retornar zero se o programa funcionou correctamente ou um outro número no caso contrário. Por causa desse padrão de programação, retornamos zeros em todos os programas que desenvolvemos nos capítulos anteriores.
6. 8 - Chamada de uma Função Uma função pode ser chamada (invocada ou acionada) por uma função principal ou por uma outra função. Tradicionalmente, a chamada de uma função é feita por um comando de atribuição de valor. Por exemplo: float grausFahr; . . grausFahr = fahrenheit (32); /* Chamada da função */ . ou, por uma acção de impressão, por exemplo: printf ("\n Valor em graus Fahrenheit = %.2f", fahrenheit (32)); Para garantir o funcionamento da troca de informações, na chamada de qualquer função, existe um mecanismo de ligação entre os argumentos da
chamada e os argumentos da função. Esse mecanismo verifica se cada argumento da chamada está relacionado a um e apenas um argumento da função. Para além disso, também verifica se esses argumentos são do mesmo tipo e estão na mesma posição relativa. Por exemplo, dada a função: int soma ( int x, int y) { int z; z = x + y; return z; } que pode ser chamada pelo segmento de código int main() { int r, s; printf ("\n Entre com um numero inteiro r: "); scanf ("%d%,&r); printf ("\n Entre com um numero real s:"); scanf ("%f",&s); printf ("\n valor da soma %f", soma(r,s)); /* chamada da função */ return 0; } O mecanismo de comunicação verifica em primeiro lugar se o número de argumentos na chamada soma(r,s) é igual ao número de argumentos do cabeçalho da função int soma( int x, floa t y). Se essa comparação for verdadeira, verifica em seguida, se esses argumentos são do mesmo tipo e estão na mesma posição relativa, ou seja: se o tipo de r é igual ao tipo de x; se o tipo de s é igual ao tipo de y; se r e x estão na primeira posição e se s e y estão na segunda posição. Os argumentos da chamada da função são normalmente denominados por parâmetros reias , porque substituem os argumentos da função (parâmetros formais) durante a execução do programa. Essa substituição pode ser feita por variáveis, valores ou expressões. No exemplo anterior, a função soma, pode ser chamada pelas seguintes instruções: soma ( 4 , 3.14); soma ( a + 3 , (b + 7)/ 2); Na primeira chamada os argumentos da função x e y são substituídos pelos valores 4 e 3.14, enquanto na segunda, os argumentos da função são substituídos pelas expressões a+3 e (b+7) / 2.
6. 9 - Parâmetros Os parâmetros ou argumentos são os canais de comunicação entre a função e o exterior. Que tipo de informações devem circular nesses canais?
No próximo passo vamos identificar as acções, que devem ser escritas como subprogramas. Para cada subprograma, a metodologia prevê o estudo da comunicação com o exterior e o algoritmo que implementa esse subprograma. O subprograma, ler lado1, que denominamos por lerLado1(), não recebe nenhum argumento e retorna o valor de um lado do retângulo. O algoritmo que resolve essa função é descrito pelos seguintes passos: 1 - declarar lado; 2 - imprimir (" Entre um lado do retangulo : "); ler (lado); 3 - retorna r lado; O subprograma, ler lado 2, que denominamos por lerLado 2 (), não recebe nenhum argumento e retorna o valor do outro lado do retângulo. O algoritmo que resolve essa função é descrito pelos seguintes passos: 1 - declarar lado; 2 - imprimir (" Entre com o outro lado do retangulo:"); ler (lado); 3 - retorna r lado; Observe que esses subprogramas têm a mesma finalidade e que os seus segmentos de código são practicamente iguais. Logo faz sentido desenvolver um único subprograma e reutiliza-lo sempre que for necessário. O subprograma lerLado() tem essa finalidade. Ele recebe como argumento o número do lado do retângulo e retorna o valor desse lado. Algoritmo que resolve essa função é descrito pelos seguintes passos: 1 - declarar lado; 2 - se numeroDoLado = 1 então 3 - imprimir ( "Entre com um lado do retangulo:"); 4 - senão 5 - imprimir ( "Entre com outro lado do retangulo:"); 6 - ler (lado); 7 - retorna r lado; O subprograma, calcular área, que denominamos por calcularArea(), recebe como argumento o comprimento dos lados do retângulo e retorna o valor da área. O algoritmo que implementa essa função é descrito pelos seguintes passos: 1 - declarar area; 2 - calcular area = lado1 * lado2; 3 - retornar area; O subprograma, calcular perímetro, que denominamos por calcularPerimetro(), recebe como argumento o comprimento dos lados do retângulo e retorna o valor do perímetro. O algoritmo que implementa essa função é descrito pelos seguintes passos:
1 - declarar perimetro; 2 - calcular perimetro = 2 x ( lado1 + lado2); 3 - retornar perimetro; Como todas as linhas do nosso algoritmo são claras e precisas, vamos converte-lo para um programa em C. /-------------------------------------------------------------------------------------------------------- Objectivo: Calcular a área e o perímetro de um retângulo. --------------------------------------------------------------------------------------------------------/ #include <stdio.h> /* incluir a função printf() scanf() / #include <stdlib.h> / incluir a funcao stdlib.h / #define SENTINELA 0 /-------------------------------------------------------------------------------------------------------- Protótipo de funções --------------------------------------------------------------------------------------------------------/ int lerLado( int numeroDoLado); float calcularArea( floa t lado1, float lado2); float calcularPerimetro( float lado1, float lados2); /------------------------------------------------------------------------------------------------------- Objectivo: Ler um lado do retângulo Recebe: Número do lado Retorna: Valor do lado digitado pelo utilizador --------------------------------------------------------------------------------------------------------/ int lerDado( int numeroDoLado) { int lado; if (numeroDoLado == 1) printf ("\n Entre com um lado do retangulo :"); else printf ("\n Entre com outro lado do retangulo :"); scanf ("%d",&lado); return lado; } /------------------------------------------------------------------------------------------------------- Objectivo: Calcular a área do retângulo Recebe: Lados do retângulo Retorna: Área --------------------------------------------------------------------------------------------------------/ float calcularArea( float lado1, float lado2) { return (lado1 * lado2); } /------------------------------------------------------------------------------------------------------- Objectivo: Calcular o perímetro Recebe: Lados do retângulo
7 - calcular hormónico do número; 8 - imprimir resultados; 9 - fim Pelo enunciado, temos como entidade de entrada um número inteiro positivo e como entidade de saída o harmónico desse número. Isso permite-nos declarar às seguintes variáveis: int n; float h; No próximo passo vamos identificar as acções que devem ser escritas como subprogramas e implementa-las de forma independente. O subprograma, ler um número inteiro, que denominamos por lerNumero(), não recebe nenhum argumento e retorna um número inteiro. Deixamos como exercício o algoritmo que resolve essa função. O subprograma, calcular harmônico de um número, que denominamos por harnomico(), recebe como argumento um número inteiro positivo e retorna o valor do harmônico desse número. O algoritmo que resolve essa função é descrito pelos seguintes passos: 1 - declarar h, i; 2 - inicializar h com zeros; 3 - para i de n até 1 passo - 1 faça 4 - calcular h = h + 1/i; 2 - retornar h; Como todas as linhas do nosso algoritmo são claras e precisas, vamos converte-lo para um programa em C. /-------------------------------------------------------------------------------------------------------- Objectivo: Calcular o valor da Série Harmónica --------------------------------------------------------------------------------------------------------/ #include <stdio.h> /* incluir a função printf() scanf() / #include <stdlib.h> / incluir a funcao stdlib.h / /-------------------------------------------------------------------------------------------------------- Protótipo de funções --------------------------------------------------------------------------------------------------------/ int lerNumero(); float harmonico( int n); /------------------------------------------------------------------------------------------------------- Objectivo: Calcular o valor da série harmónica Recebe: Número inteiro positivo Retorna: Valor da série --------------------------------------------------------------------------------------------------------*/ int harmonico( int n)
floa t h= 0.0; int i; for ( i = n; i >= 1; i--) h += 1/i; return h; } /------------------------------------------------------------------------------------------------------- Objectivo: Ler um número inteiro Recebe: Nada Retorna: Número digitado pelo utilizador --------------------------------------------------------------------------------------------------------/ int lerNumero() { int numero; printf ("\n Entre com um numero inteiro positivo:"); scanf ("%d",&numero); return numero; } /-------------------------------------------------------------------------------------------------------- Função principal --------------------------------------------------------------------------------------------------------/ int main() { float h; int n; n = lerNumero(); if ( n < 1) printf (“\n Erro: Numero invalido”); else { h = harmonico(n); printf (“\n Valor harmonico de %d igual a %f ”,n, h); } system (“PAUSE”); return 0; } É importante salientar que podemos optimizar a função principal. Essa optimização consiste em escrever numa única linha a leitura do número e a sua validação. Para além disso podemos activar a função harmónico no interior do comando de impressão. int main() { int n; if ( n = lerNumero() < 1) printf (“\n Erro: Numero invalido”); else
O subprograma, ler um número inteiro n, que denominamos por lerNumero(), não recebe nenhum argumento e retorna um número inteiro. Como exercício, desenvolva o algoritmo que implementa essa função. O subprograma, calcular o factorial de um número, que denominamos por factorial(), recebe como argumento um número inteiro positivo e retorna o factorial desse número. O algoritmo que resolve essa função é descrito pelos seguintes passos: 1 - declarar fat, i; 2 - inicializar fat com 1; 3 - para i de 1 até n passo 1 faça 4 - Multiplicar fat por i; 5 - retornar fat; Agora, vamos pegar nesse algoritmo para desenvolver um algoritmo que calcula a combinação de n p a p. O subprograma, calcular a combinação de n p a p , que denominamos por combinacao(), recebe como argumento um número inteiro positivo n e um número inteiro positivo p. Retorna o valor da combinação de n p a p. O algoritmo que resolve essa função é descrito pelos seguintes passos: 1 - declarar comb; 2 - calcular comb = factorial(n) / (factorial(p) * factorial (n-p)); 3 - retornar comb; Como todas as linhas do nosso algoritmo são claras e precisas, vamos converte-lo para um programa em C. /-------------------------------------------------------------------------------------------------------- Objectivo: Calcular as combinações de n p a p --------------------------------------------------------------------------------------------------------/ #include <stdio.h> /* incluir a função printf() scanf() / #include <stdlib.h> / incluir a funcao stdlib.h / /-------------------------------------------------------------------------------------------------------- Protótipo de funções --------------------------------------------------------------------------------------------------------/ int lerNumero(); int factorial ( int n); float combinacao ( int n, int p); /------------------------------------------------------------------------------------------------------- Objectivo: Calcular o factorial de um número inteiro Recebe: Número inteiro Retorna: Factorial desse número --------------------------------------------------------------------------------------------------------*/ int factorial( int n)
int i, fat; for ( fat = 1, i = 1; i <= n; i++) fat += i; return fat; } /------------------------------------------------------------------------------------------------------- Objectivo: Ler um número inteiro Recebe: Nada Retorna: Valor do número inteiro --------------------------------------------------------------------------------------------------------/ int lerNumero() { int numero; printf ("\n Entre com um numero inteiro positivo:"); scanf ("%d",&numero); return numero; } /------------------------------------------------------------------------------------------------------- Objectivo: Calcular a combinação de n p a p Recebe: Valor de n e valor de p Retorna: Combinação de n p a p --------------------------------------------------------------------------------------------------------/ float combinacao( int n, int p) { return (factorial(n)/(factorial(r)factorial(n-r))); } /-------------------------------------------------------------------------------------------------------- Função principal --------------------------------------------------------------------------------------------------------*/ int main() { int n, p; if ( n = lerNumero() <= 0 ) printf (" \n Erro: Numero deve ser positivo "); else { for (p = 0; p <= n; p++) printf (" \n %d ",combinacao(n,p)); } system ("PAUSE"); return 0; } Fazem parte das boa prática de programação, definir em primeiro lugar as funções que são chamadas por outras funções.
int passe, minutoEntrada, minutoSaida, tempoNoServico, hora, minutos; Como não definimos o número de trabalhadores que iremos processar, vamos associar um sentinela de fim de leitura ao número do passe do trabalhador. #define SENTINELA 0 No próximo passo vamos implementar os subprogramas de forma independente. O subprograma, ler o passe do trabalhador, que denominamos por lerPasse(), não recebe nenhum argumento e retorna o valor de um número inteiro positivo. Como exercício desenvolva o algoritmo que implementa essa função. O subprograma, converter horas para minutos, que denominamos por converteTempo(), recebe como argumento as horas e os minutos. Retorna o correspondente tempo em minutos. O algoritmo que resolve essa função é descrito pelos seguintes passos: 1 - declarar tempoEmMinutos; 2 - calcular tempoEmMinutos = horas* 60 + minutos; 3 - retornar tempoEmMinutos; O subprograma, calcular à diferença de preço, que denominamos por diferencaTempo(), recebe como argumento o tempo de entrada e o tempo de saída em minutos. Retorna a diferença de tempo. O algoritmo que resolve essa função é descrito pelos seguintes passos: 1 - declarar diferencaTempo; 2 - calcular diferencaTempo = tempoSaida - tempoEntrada; 3 - retornar diferencaTempo; O subprograma, imprimir resultados, que denominamos por imprimir(), recebe como argumento o número do passe e a diferença de tempo. Não devolve nenhuma informação. O algoritmo que resolve esse procedimento é descrito pelos seguintes passos: 1 - imprimir (passe); 2 - imprimir (diferencaTempo); Como todas as linhas do nosso algoritmo são claras e precisas, vamos converte-lo para um programa em C. /-------------------------------------------------------------------------------------------------------- Objectivo: Calcular o número de horas de trabalho por dia de cada empregado. --------------------------------------------------------------------------------------------------------/ #include <stdio.h> /* incluir a função printf() scanf() / #include <stdlib.h> / incluir a funcao stdlib.h */
Protótipo de funções --------------------------------------------------------------------------------------------------------/ int lerNumeroPasse(); int converteTempo( int h, int m); int diferencaTempo( int entrada, int saida); void imprimir( int passe, int diferencatempo); /------------------------------------------------------------------------------------------------------- Objectivo: Ler um número do passe do funcionário Recebe: Nada Retorna: Número do passe --------------------------------------------------------------------------------------------------------/ int lerNumeroPasse() { int numero; printf ("\n Entre com um numero inteiro positivo:"); scanf ("%d",&numero); return numero; } /------------------------------------------------------------------------------------------------------- Objectivo: Converter as horas e os minutos para minutos Recebe: Horas e minutos Retorna: Minutos --------------------------------------------------------------------------------------------------------/ int converteTempo( int h, int m) { return ( h 60 + m); } /------------------------------------------------------------------------------------------------------- Objectivo: Calcular os minutos de trabalho Parâmetros: Minutos de entrada e minutos e saída Valor de retorno: Tempo em minutos --------------------------------------------------------------------------------------------------------/ int diferencaTempo( int entrada, int saida) { return saida - entrada; } /------------------------------------------------------------------------------------------------------- Objectivo: Imprimir a assiduidade do empregado Parâmetros : Passe do trabalhador e horas no serviço --------------------------------------------------------------------------------------------------------/ void imprimir( int passe, int horasNoServico) { printf ("\n Trabalhador com o passe %d :", passe); printf ("\n esteve na Empresa %d:",horasNoServico); }