SUBPROGRAMAS

 

A identificação de problemas mais complexos resultará no desenvolvimento de algoritmos também mais complexos para resolvê-los.

 

Uma abordagem eficiente para este tipo de problema é a divisão do problema mais complexo em problemas mais simples de serem resolvidos.

 

Este método é conhecido como modularização, onde um grande problema é divido em problemas menores e a solução destes problemas menores resultará na solução do problema maior (mais complexo). Estes programas menores são denominados sub-rotinas, módulos, subprogramas ou sub-algoritmos.

 

Um subprograma é um trecho de um algoritmo (futuro programa) maior (mais complexo) que realiza qualquer operação computacional estudada até agora (entrada, processamento, saída). Ele efetua parte de uma tarefa que um algoritmo maior deverá executar. O algoritmo que aciona um subprograma é chamado de algoritmo principal daquele subprograma.

 

Observe a seguir a representação da lógica funcional de uma algoritmo elaborado com alguns subprogramas ou módulos.

 
 

O funcionamento de um subprograma corresponde a implementação de uma função, no sentido matemático da expressão, pois um subprograma também retorna um único valor, de um ou mais valores manipulados em uma ou mais operações realizadas por esta função.

 

A expressão "função" também é usada na elaboração de um subprograma, onde ela identifica a disponibilização de um ou mais subprogramas para um algoritmo principal, sendo a expressão funcao uma palavra reservada.

 
Função
 

É um subprograma iniciado pela palavra reservada funcao, seguida do tipo de dado referente ao seu resultado, um identificador que fornece um nome à função além de uma lista de parâmetros.

 

A lista de parâmetros consiste nos valores que o algoritmo principal possui e o subprograma precisa usar para obter, ou gerar, outro dado importante na solução almejada pelo algoritmo.

 

O acionamento de qualquer subprograma ocorre por meio da especificação do seu nome, seguido da lista de parâmetros a serem manipulados pelo subprograma (função).

 

Esta lista tem a sua representação opcional ao programador, pois pode não existir nenhum valor do algoritmo que seja necessário ao subprograma.

 
Forma geral de uma função
 

Uma função possui somente dois momentos importantes no algoritmo:

 

  1. Primeiro momento é da declaração e especificação das tarefas/operações (seu corpo) que a função deverá executar;

  2. Segundo momento é a utilização ou acionamento da função que pode acontecer várias vezes depois da sua criação e dentro do algoritmo no qual ela também faz parte.

 

Sintaxe:

 
// Obejtivo:
// Parâmetro:
// Retorno:
funcao <tipo de dado> <identificador> (<lista de parâmetros>)
    
  <tipo de dado> <identificador>;
  
  instrução 1
  instrução 2
        :
  instrução n
  retorna(<valor>)
fimFuncao
 

onde:

 
  • funcao é a palavra reservada que identifica um tipo de subprograma

  • <tipo de dado> é um tipo de dado válido (inteiro, real, caracter, lógico)

  • <identificador> é o nome atribuído a função, aos parâmetros e variáveis

  • <lista de parâmetros> são os parâmetros usados no subprograma

  • <valor> representa o único valor que a função retorna para seu acionador (ou chamador)

 
Parâmetros da função
 

Os parâmetros de uma função são dados fundamentais que a função deve ter acesso para alcançar seu objetivo. Por exemplo, se você tem uma função denominada media que calcula a média aritmética de dois números, é essencial que essa função "saiba" quais são os números que serão usados para o cálculo da média, do contrário, ela não pode efetuar os cálculos. Pois bem, esses dois números serão disponibilizados à função por meio de parâmetros.

 

Portanto, a estrutura descritiva dessa função media seria:

 
// Objetivo: Calcular a média de dois números
// Parâmetro: numeros que terão sua média calculada
// Retorno: valor da média dos dois números          
funcao real media(real num_1, real num_2)
	real resultado;
	resultado = ((num_1 + num_2) / 2);
	retorna (resultado);
fimFuncao
 

onde num_1 e num_2 são parâmetros da função media descrita anteriormente.

 

A sintaxe de criação da função exige o cabeçalho da mesma, coerente com as suas características, onde o nome, seus parâmetros e o retorno sejam corretamente pensados e elaborados de forma a resolver o problema a que ela se propõe.

 

Na identificação ou descrição das tarefas/operações realizadas pela função (definição do seu corpo) são descritas as declarações de variáveis internas da função (variáveis locais), as constantes e outros subprogramas que possam também ser declarados dentro da função. A partir da palavra reservada funcao inicias-se a elaboração do subprograma (função) até a expressão fimFuncao, onde o cabeçalho da função é elaborado e seu corpo também é descrito (desenvolvido).

 

Na utilização, também denominada acionamento ou chamada da função, o algoritmo que declarou a função pode acioná-la por meio do seu nome e seus parâmetros, efetuando a chamada ou acionamento da função. Este acionamento tem a similaridade com a chamada de uma colega que está distante. Para que ela te ouça você deve chamá-la pelo seu nome e ela estará "acionada" (com atenção) para ver o que você deseja lhe falar (passar seus parâmetros para ela saber o que fazer para te atender).

 

Exemplo:

 

O algoritmo abaixo calcula a média aritmética de cada aluno em uma turma de 50 estudantes. O interessante é que o cálculo de cada média é feito por uma única função, que recebe como parâmetros dois números e retorna a média de cada um dos integrantes desta turma, ou seja, a mesma função é acionada 50 vezes e resolve o problema corretamente.

 
algoritmo mediaPorAluno;
// Síntese
//  Objetivo: calcular a média para cada aluno da turma
//  Entrada : duas notas para cada aluno
//  Saída   : média de cada aluno da turma de 50 alunos


principal
	// Declarações
	inteiro qtde;
	real nota_1, nota_2, total;
	inteiro contador;
	// Instruções
	
	qtde = 50; // confirmação da constante com 50 alunos na turma
	para (contador de 1 ate qtde passo 1) faca
		escreval("Informe as notas do ", contador, " aluno: ");
		leia(nota_1);
		leia(nota_2);
		total = media(nota_1,nota_2); //chamando a função
		escreval(""); // saltando duas linhas para apresentar resultado
		escreva("Média Final = ", total);
		// lembrando que a apresentação de total:3:1 mostra o valor de total
		// usando 3 casas numéricas, sendo 2 inteiras e 1 decimal no mínimo
	fimPara
	
fimPrincipal

funcao real media(real num_1, real num_2)
	real resultado;
	resultado = ((num_1 + num_2) / 2);
	retorna (resultado);
fimFuncao
 

Observe no exemplo anterior que existe um subprograma para o algoritmo principal que aciona 50 vezes este mesmo subprograma (função media). Em cada acionamento desta função foram enviados parâmetros com valores possivelmente diferentes, o que resultará em um cálculo de média diferente para cada acionamento.

 
 
Aspectos de Execução dos Subprogramas
 

Um algoritmo em execução deve obedecer a sequência das instruções, a menos que existam comandos (instruções) específicos que alterem esta ordem sequencial (comandos de seleção ou repetição, por exemplo).

 

Porém, a chamada do subprograma desloca a sequência de execução do algoritmo para o corpo da função que também obedecerá a sequência de execução, respeitando as instruções existentes em seu corpo.

 

Quando o subprograma (função) chegar ao seu final, ele retornará um único valor para o algoritmo que o acionou, continuando a execução do mesmo a partir da próxima instrução a ser realizada.

 

Um algoritmo possui uma estrutura bem organizada, onde subprogramas executam tarefas bem determinadas. Esta divisão facilita a legibilidade e a manutenção corretiva e/ou evolutiva sobre os mesmos.

 

Um subprograma só pode ser acionado pelo algoritmo que o contém, ou seja, que o declara, podendo ele também possuir outros subprogramas.

 

Todo algoritmo com subprograma deve possuir uma estrutura similar a representada, de forma simples, abaixo:

 

Síntese do problema

Declarações

Algoritmo Principal

Subprogramas

 

Fluxograma:

 

A representação do subprograma em uma técnica gráfica, como o fluxograma, é apresentado a seguir.

 
 

Por meio do nome do subprograma e seus parâmetros, se houverem, o local do acionamento do subprograma é identificado, deslocando a sua execução para um outro fluxograma, o fluxograma do subprograma acionado.

 

Este outro fluxograma deverá ser elaborado, representando exatamente o que este subprograma executa, ou seja, as tarefas/operações existentes no corpo do subprograma, ou seja, exatamente o que ele realiza após seu acionamento.

 

As elipses de Início e Fim do algoritmo acionador (principal) são inseridas da mesma forma, porém no diagrama que especifica o corpo da função a elipse inicial é substituída pelo nome do subprograma e sua lista de parâmetros, enquanto que a elipse final contém a palavra reservada retorna e a informação que será retornada.

 
Instrução de Retorno
 

Um subprograma sempre retorna um valor ao algoritmo que o aciona, por isso ele possui um tipo de dado declarado, retornando ao acionador um dado exatamente deste tipo.

 

Exemplo:

 

/// Objetivo: Calcular a média de dois numeros
// Parâl;metro: Dois valores que terão sua média calculada
// Retorno: Média dos dois numeros
funcao real media(real valor_1, real valor_2)	
	//Declarações
	real resultado;
	//Instruções
	resultado = ((valor_1 + valor_2) / 2);
	retorna (resultado);
fimFuncao
 

A instrução retorna executa o encerramento do subprograma, retornando imediatamente um único  valor desejado a instrução acionadora da função. Esta instrução só pode retornar um único valor ao acionador.

 
Escopo dos objetos
 

Aplicando o processo de modularização, todos os objetos (variáveis ou constantes) pertencem ao contexto em que são declarados e só podem ser utilizadas por quem as declara, ou seja, todos os objetos são locais ao algoritmo principal ou aos sub-algoritmos.

 

O valor de uma variável declarada no algoritmo principal/sub-algoritmo, pode ser utilizada dentro de um ou mais sub-algoritmos através da passagem de parâmetros.

 
Passagem de Parâmetros
 

A criação de sub-algoritmos nem sempre significa que o desenvolvimento do algoritmo irá diminuir o trabalho do programador.


Exemplo

Suponha a leitura de 3 variáveis de tipos diferentes. Neste caso haveria a necessidade da criação de 3 sub-algoritmos, um para cada leitura de cada tipo de variável, no entanto, estes mesmos 3 algoritmos poderiam ser utilizados para a leitura de 100 ou 1000 variáveis diferentes dos três tipos mencionados.

 
Características Relevantes da Programação Modular
 
  • Reutilização de código com aproveitamento da lógica existente no subprograma;

  • Subprogramas devem ser genéricos o bastante para se adaptarem às diversas situações, visando justamente essa reutilização;

  • A passagem de parâmetros possibilita o envio de diferentes valores para um mesmo subprograma, que realizará as operações necessárias sobre estes dados;

  • A passagem de parâmetros pode ocorrer de duas formas

 
  1. Passagem por valor

  2. Passagem por referência

 
Passagem por Valor
 
  • Subprograma usa uma cópia do valor existente no algoritmo acionador;

  • Não altera o valor original existente no algoritmo acionador, trabalhando somente sobre o valor local copiado do acionador;

  • Valor existente no subprograma não pode ser acessado pelo algoritmo principal, a menos que este seja retornado ao algoritmo acionador;

  • Com a finalização do subprograma, todos os parâmetros e componentes locais são destruídas, ou seja, deixam de existir na memória do computador.

 
Passagem por Referência
 
  • Subprograma usa o valor original existente no algoritmo acionador por meio do acesso ao mesmo endereço de memória;

  • A manipulação desse tipo de parâmetro altera o valor existente no algoritmo acionador, ou seja, o valor original sofre alteração;

  • Com a finalização do subprograma o valor do parâmetro passado por referência não é destruído, pois ele alterou o valor original existente no algoritmo acionador.

 


 
Procedimento
 

Consiste em um subprograma iniciado pela palavra reservada procedimento, seguida de um identificador que lhe fornece um nome e sua lista de parâmetros.

 

Nenhum procedimento possui tipo de dado de retorno, como em uma função, pois este tipo de subprograma não retorna nenhum valor ao seu chamador (acionador).

 

Como em uma função, sua lista de parâmetros consiste em valores que o algoritmo principal, ou outro subprograma, possui e o procedimento necessita de seus conteúdos para obter ou gerar outro dado importante para o algoritmo alcançar seu êxito.

 

O acionamento do procedimento também ocorre por meio da especificação do seu nome, seguido da lista de parâmetros a serem manipulados pelo próprio procedimento. No entanto, esta lista tem sua representação opcional ao programador, pois pode não existir nenhum valor do algoritmo que seja necessário a este subprograma.

 
Forma geral de um procedimento
 

Um procedimento possui dois momentos no algoritmo:

 
  1. Primeiro momento é o da declaração, onde é elaborado o cabeçalho da função coerente com as suas necessidades e a descrição das tarefas/operações que ele realizará quando for acionado (seu corpo);

  2. Segundo momento é a utilização ou acionamento do procedimento que pode acontecer várias vezes depois da sua criação e dentro do algoritmo no qual ela também faz parte.

 

Sintaxe:

 
// Objetivo:
// Parâmetro:
// Retorno: Sem retorno.         
procedimento <identificador>(<lista de parâmetros>)
  //Desclarações
  <tipo de dado> <identificador>;

  //Instruções
  instrução 1
  instrução 2
     :
  instrução n
fimProcedimento
 

onde:

 
  • procedimento palavra reservada que identifica este tipo de subprograma;

  • <identificador> nome atribuído ao procedimento, aos parâmetros e componentes locais quando existirem;

  • <lista de parâmetros> são os parâmetros usados no procedimento;

  • <tipo de dado> é um tipo de dado válido (inteiro, real, caracter, texto, lógico).

 
Parâmetros do procedimento
 

Os parâmetros de um procedimento são dados fundamentais que este tipo de subprograma deve acessar para realizar seu objetivo. Por exemplo, se você deseja indicar se uma pessoa é "maior de idade" ou não, poderá empregar um procedimento que faça tal identificação, porém este procedimento precisará ter conhecimento da idade desta pessoa. Caso contrário, o procedimento não conseguirá analisar a situação de maioridade da pessoa desejada. Assim, a idade desta pessoa deverá ser disponibilizada ao procedimento por meio da passagem de parâmetros.

 

Portanto, a estrutura descritiva desse procedimento seria:

 
// Objetivo: Indicar se a pessoa é alcançou a maioridade
// Parâl;metro: Idade da pessoa
// Retorno: Sem Retorno.
procedimento maioridade(inteiro idadeAuxiliar)
	//Declarações
	// sem necessidade da criação de componentes locais
	
	//Instruções
	
	se (idadeAuxiliar < 18) entao
		escreva("Indivíduo menor de idade.");
	senao
		escreva("Indivíduo maior de idade.");
	fimSe
fimProcedimento
 

onde: idadeAuxiliar é um parâmetro do procedimento maioridade descrito acima.

 

Na identificação e descrição das tarefas/operações realizadas pelo procedimento são declaradas suas variáveis, constantes e outros subprogramas internos a este procedimento, ou seja, seus componentes locais. A partir da palavra reservada procedimento inicias-se a elaboração do subprograma (do tipo procedimento) até a expressão fimProcedimento.

 

Na utilização, também denominada acionamento ou chamada do procedimento, o algoritmo que o declarou pode acioná-lo por meio do seu nome e seus parâmetros, efetuando seu acionamento (ou chamada). Este acionamento é similar à chamada de um amigo que está distante. Para que ele o ouça, você deve chamá-lo pelo seu nome (gritando se ele estiver bem distante). Isso provocará o seu acionamento, onde ele lhe dará mais atenção até descobrir o que você deseja (fornecer as informações desejadas como na passagem de parâmetros).

 

Exemplo:

 

O algoritmo a seguir calcula a média aritmética de um aluno por meio da função mediaAritmetica e apresenta a situação deste aluno em uma disciplina no semestre corrente através do procedimento situacaoAluno.

 
algoritmo resultadoDisciplina;
// Síntese
//  Objetivo: calcular a média aritmética para um aluno
//  Entrada : três notas parciais do aluno
//  Saída   : média final de um aluno e sua situação na disciplina


principal
	// Declarações
	inteiro qtde;
	real nota, soma, media;
	inteiro contador;
	// Instruções
	
	qtde = 3; // constante com 3 notas por aluno
	soma = 0;
	para (contador de 1 ate qtde passo 1) faca
		escreval("Informe a ", contador, " nota do aluno: ");
		faca
			leia(nota);
			se (nota < 0 ou nota > 10) entao
				escreval("  Nota inválida! Informe novamente: ");
			senao
				soma = (soma + nota);
			fimSe
			
		enquanto (nota < 0 e nota > 10); // garante notas válidas
	fimPara
	
	media = mediaAritmetica(soma,qtde); // chamando a função
	situacaoAluno(media); // chamando o procedimento
	
	
fimPrincipal


funcao real mediaAritmetica(real notas , inteiro quantidade)
	//Declarações
	real resultado;
	
	//Instruções
	resultado = (notas / quantidade);
	retorna (resultado);
fimFuncao

// Objetivo:
// Parâl;metro:
// Retorno: Sem retorno.
procedimento situacaoAluno(real total)
	
	// sem declaração de componente local ao procedimento
	
	escreval("");
	escreval("");
	escreval("Média Final = ", total);
	se (total < 7) entao
		escreva("Aluno Reprovado.");
	senao
		escreva("Aluno Aprovado.");
	fimSe
fimProcedimento
 

Observe no exemplo anterior que existem dois subprogramas no algoritmo principal, sendo cada um deles acionados no momento mais oportuno. Após a leitura das três notas válidas de um determinado aluno, a função mediaAritmetica é acionada para o cálculo da média aritmética final deste aluno. Em seguida é acionado o procedimento situacaoAluno que apresentará o resultado da média calculada e a situação deste aluno na devida disciplina.

 

É importante observar que foram enviados parâmetros coerentes para os dois subprogramas, o que resultou em uma avaliação correta, de acordo com as notas válidas obtidas por este aluno. Caso isso não fosse garantido os subprogramas poderiam apresentar valores inválidos a este contexto, como por exemplo uma média final de 21,3.

 

Na solução proposta pelo exemplo acima seria possível informar as notas parciais válidas de 5,4; 7,8 e 8,1, sendo o resultado calculado apresentado na figura abaixo.

 
 
Atividade de Fixação
   

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.