PRÁTICA - SUBPROGRAMAS
Uma das características mais importantes da linguagem C são as funções, pois são nelas que ocorrem todas as atividades de um programa. Cada função equivale a um bloco de instruções, o qual pertence exclusivamente à mesma, não podendo ser acessado por nenhuma outra, exceto por meio de uma chamada à esta função.
Dividindo o programa em várias funções, torna-se mais fácil a detecção de erros e organização do código. É importante observar que na linguagem C não existe distinção entre funções (possui um único retorno) e procedimentos (não possui retorno algum).
<tipo de dado> <identificador> (lista de parâmetros)
Tipo de dado: especifica o tipo de valor que o comando return devolve á função, consistindo do seu único valor de retorno. Quando este campo não foi informado, o compilador interpreta como seu tipo de dado padrão int (inteiro).
Identificador: corresponde ao nome dado a função, respeitando todas as regras de dar nomes a objetos (variáveis e constantes) na programação computacional.
Lista de parâmetros: compreende valores que serão enviados pela chamada da função que necessita enviar alguns dados para dentro dela, de forma que ela possa resolver corretamente o que lhe é solicitado.
É similar a uma "lista de variáveis" separadas por vírgula e entre os parênteses da função, com seus respectivos tipos de dados totalmente compatíveis com os definidos em sua declaração (protótipo da função). Uma função pode ter vários parâmetros ou nenhum, mas sempre deve possuir seus parênteses: ( - abrir e ) - fechar.
Exemplos - observe alguns protótipos a seguir:
float media (float nota1,float nota2); //função //float com 2 parâmetros float int soma (int valor1, int valor2); //função int com //2 parâmetros int char mostra ( ); //função char sem nenhum parâmetro potencia (int exp, float base, char resp);
A função deve ser declarada no início do programa a ser elaborado por meio do seu protótipo. Após a criação da função principal (função main), o corpo da função desejada, e já declarada pelo seu protótipo, deve ser definido, consistindo ele na cópia de sua declaração (protótipo), sem o ponto e vírgula (;) no final. Em seguida, similar a função principal, o corpo da nova função começa a ser definido, sempre entre chaves: { - abrir e } - fechar.
Exemplo - observe o corpo da função MEDIA que teve seu protótipo (declaração) realizado no exemplo anterior:
float media (float nota1, float nota2) { //Declarações float resultado; //criação de uma nova variável, sendo ela local //Instruções resultado = (nota1 + nota2) / 2; return (resultado); }
Este exemplo mostra uma função que calcula a média entre duas notas e retorna o resultado deste cálculo. Observe qual seria o algoritmo desta função e veja a similaridade da criação de ambos.
funcao real media (real nota1, real nota2) //corpo da função real resultado; //criação da variável local resultado resultado = (nota1 + nota2) / 2; retorna resultado; fimFuncao
Todo programa em C consiste em uma ou mais funções, sendo a main a única função que necessariamente precisa estar presente em qualquer programa, pois ela é a primeira a ser chamada quando a execução do programa começa. Por se tratar de uma função, a main segue as mesmas regras de declaração de uma função. Também é chamada de função principal.
Existem duas maneiras de se passar dados para dentro de uma função, sendo elas conhecidas como: passagem por VALOR ou por REFERÊNCIA.
Quando uma função é chamada, a mesma função faz cópias dos valores enviados como parâmetros, dessa forma os valores originais não são alterados, pois a função manipula apenas as cópias dos mesmos.
Os valores existentes na função que foi chamada não podem ser acessados por outras funções, a menos que estes valores sejam enviados por parâmetros para outras funções, a partir da mesma, ou ainda retornados por ela. Todos os valores de uma função são apagados com o término da execução da mesma.
Ao invés de se fazer uma cópia dos valores existentes na função principal, a função que é chamada leva como parâmetro o endereço de memória original das variáveis que ela manipulará durante sua execução, por meio dos parâmetros enviados a ela.
Neste tipo de passagem de parâmetros, o valor original da variável pode ser alterado, já que a função tem acesso ao seu endereço original, onde o dado manipulado esta realmente armazenado na memória do computador. Quando esta função é encerrada, o conteúdo enviado para ela não é destruído, pois ela somente recebeu o endereço original pertencente a outra função, normalmente a função principal, que só permitirá sua destruição quando ela for encerrada. Porém, quando uma função principal é encerrada o programa termina.
Exemplo:
& - o "E comercial" na linguagem C é o operador de endereço e indica a
O comando return é usado na execução de duas ações na função, similar ao que já foi estudado no comando retorna em algoritmo. Este comando finaliza a função fazendo com que sua execução retorne à função chamadora e devolva um único valor existente dentro desta função para a função chamadora.
Todas as funções, com exceção as do tipo de dado void, retornam um único valor. Caso não exista nenhum comando return presente, o valor de retorno será tecnicamente indefinido (na maioria dos casos, os compiladores C devolvem ZERO quando não há nenhum valor de retorno especificado, mas isto não é recomendado para elaboração de programas eficientes). Uma função pode ter vários comandos return, mas somente um será executado realmente, pois após a sua execução ele encerra a função em execução e retorna para função chamadora, imediatamente.
Na linguagem C, procedimento corresponde a uma função sem retorno, como em algoritmo. Nesta linguagem não existe distinção entre função e procedimento, sendo ambos tratados como função, ou seja, um subprograma com lógica bem definida que pode ser acionada quantas vezes sejam necessárias para solucionar um problema.
O procedimento corresponde a uma função do tipo void (tipo de dado indefinido) que não possui o comando return devolvendo algum valor para a função chamadora. Desta forma se for preciso armazenar os dados coletados durante a execução da função pode-se recorrer a passagem de parâmetros por referência, uso de variáveis globais ou ainda alguns outros métodos que serão estudados mais adiante sobre esta linguagem de programação computacional.
As variáveis locais são variáveis que são declaradas dentro das funções. Somente as funções que as criaram podem utilizá-las, sendo que após o término da função, estas variáveis são destruídas (apagadas da memória do computador).
Exemplo:
/* SÍNTESE Objetivo: Determinar se um estudante foi aprovado ou reprovado Entrada: Média Saída: Mensagem informativa de "Aprovado" ou "Reprovado" */ #include <stdio.h> #include <conio.h> //de acordo com a versão do Dev-C pode ser usada <conio.c> void main (void) { //Declarações int situacao (float val); //declaração de outra função (seu protótipo) float media; int verifica; //Início printf("Informe a media do aluno"); scanf("%f",&media); //lê a média do aluno verifica = situacao(media); //verifica recebe o resultado da função if(verifica == 1) puts("APROVADO"); else puts("REPROVADO"); getch(); return(0); } //Corpo da função situacao (descrição do que a função situacao faz int situacao (float val) //parâmetro VAL só existe dentro da função { //funcionando como uma variável local // Declarações int auxiliar; //declaração de variável local - só existe dentro da função //Instruções if(val >= 7) auxiliar=1; else auxiliar=2; return(auxiliar); //valor de auxiliar é retornado para função chamadora } /* Após a execução do comando return a variável auxiliar e o parâmetro val são apagados da memória, ou seja, são destruidos */
Supondo uma execução, onde o usuário tenha informado o valor 8.9 para a variável media, observe o resultado do programa acima na tela a seguir:
As variáveis globais, ao contrário das locais, são declaradas fora de qualquer função (inclusive da função main), sendo seu conteúdo acessado por todas as funções que compõem o programa como um todo, pois tal variável (ou constante) é global e só será destruída da memória quando o programa terminar, ou seja, somente quando a função principal encerrar sua execução.
Exemplo:
/* SÍNTESE Objetivo: Ler o nome e país de uma pessoa Entrada: Nome da pessoa e nome do país Saída: Mensagem com o nome e país da pessoa */ #include <stdio.h> #include <conio.h> char nome[100], pais[100]; //declarações globais int main (void) { //Declarações void leitura (void); //declaração do procedimento leitura localmente //Instruções leitura( ); //chamada do procedimento LEITURA sem parâmetro algum printf("Ola %s! Voce mora no pais de nome %s!!", NOME, PAIS); getch(); return(0); } //Corpo da função LEITURA void leitura (void) { //Declarações //Instruções puts("Informe o seu nome:"); gets(nome); //lê o nome da pessoa puts("Informe o seu país:"); gets(pais); //lê o país da pessoa } /* Mesmo após o término da execução da função, o conteúdo de nome e pais continua disponível na memória, pois estas variáveis são globais */
Supondo que o usuário informou o nome Carlos Henrique e o país Argentina, o resultado da execução seria:
O uso de variáveis globais não é recomendado, pois facilita a ocorrência de alguns problemas e dificulta a localização de erros no código fonte, além de não contribuir com a segurança no uso de funções (subprogramas em geral) devido as variáveis serem públicas durante toda a execução do programa, podendo serem alteradas a qualquer momento no mesmo.
Uma função pode chamar outras funções durante o seu funcionamento. Quando isso acontece, o funcionamento da função que chamou é interrompido e a função chamada entra em execução. Após seu término, o programa continua a execução de onde parou, neste caso, logo após a chamada de função.
Exemplo:
/* Síntese Objetivo: Calcular o Índice de Massa Corporal (IMC) de uma pessoa. Entrada: peso e altura. Saída: Valor do IMC e sua situação (abaixo, acima ou no peso correto). */ #include <stdio.h> #include <stdlib.h> int situacao (float valor1, float valor2); //protótipo da função int main(void) { //Declarações float peso, altura; int opcao; //Instruções printf("Informe o peso e a altura:"); scanf("%f%f",&peso,&altura); opcao = situacao (peso, altura); switch(opcao) { case 1: printf("Você está abaixo do peso."); break; case 2: printf("Você está com o peso adequado para sua altura."); break; case 3: printf("Você está acima do peso."); break; case 4: printf("Você está obeso."); } getch(); return(0); } //Corpo da função int situacao (float valor1, float valor2) { //Declarações float resultado; float imc(float peso1, float alt); //declaração de outra função local //Instruções resultado = imc(valor1,valor2); if(resultado < =18.5) return(1); else if(resultado <= 24.9) return(2); else if(resultado <= 29.9) return(3); else return(4); } float imc(float peso1, float alt) { //Declarações float total; //Instruções total = peso / (alt * alt); return(total); }
Assim como as variáveis, as funções também podem ser globais e locais, onde as funções locais só podem ser acessadas pelas funções nas quais estão declaradas, enquanto as funções globais podem ser utilizadas por todas as funções que compõem o programa. As regras de declaração das variáveis aplicam-se também às funções e/ou procedimentos.
Observe no exemplo anterior que a função denominada SITUACAO esta declarada fora de qualquer outra função, sendo ela então uma função global, porém a função IMC esta declarada dentro da função SITUACAO, o que faz dela uma função local podendo ser acionada somente a partir da função SITUACAO e seu retorno será também para ela (a função SITUACAO).
No intuito de fixar a aprendizagem iniciada por meio deste módulo e verificar como seu entendimento sobre este conteúdo está, estão sendo sugeridos alguns exercícios de fixação para serem resolvidos. Clique no link de exercícios ao lado, pois será por meio dele iniciada a lista de exercícios sobre os conteúdos estudados até este momento nesta disciplina.