Prévia do material em texto
Funções e procedimentos
Apresentação
Seja bem-vindo!
Dividir programas em blocos menores, ou subprogramas, faz parte das melhores práticas no
desenvolvimento de sistemas. Na linguagem C++, essa divisão é realizada por meio de funções e
procedimentos. Entre os principais benefícios de funções e procedimentos, destacam-se a
legibilidade e o reuso de códigos-fonte, que proporcionam maior facilidade de manutenção nos
programas e ganho de produtividade.
Nesta Unidade de Aprendizagem, você vai estudar sobre declaração e chamada de funções, bem
como fazer uso de variáveis locais e globais.
Bons estudos.
Ao final desta Unidade de Aprendizagem, você deve apresentar os seguintes aprendizados:
Definir funções e procedimentos.•
Criar chamada de funções e procedimentos.•
Usar variáveis locais e globais.•
Desafio
O aprendizado no desenvolvimento de programas de computador envolve a resolução de diversos
problemas que auxiliam a desenvolver o raciocínio e a lógica de programação. Uma boa parte
desses exercícios, por mais simples que pareçam, pode acabar, um dia, integrando a rotina de um
programador profissional.
Nesse contexto, o desafio apresenta uma questão que proporciona a elaboração de um algoritmo
que põe em prática alguns dos principais conceitos abordados nesta Unidade de Aprendizagem.
Elabore um algoritmo que implemente uma função que recebe dois parâmetros numéricos, sendo o
primeiro passado por referência e o segundo por valor. O objetivo da função é acrescentar o valor
do segundo número no primeiro, fazendo-o modificar o valor original do primeiro parâmetro.
Para testar a função, crie um laço de repetição que produza 10 números aleatórios para o primeiro
parâmetro e outros 10 para o segundo. Imprima os dois números antes de chamar a função e o
primeiro número novamente após a chamada da função, conforme o seguinte exemplo:
Número Aleatório 1 Número Aleatório 2
Número aleatório 1 após
a chamada da função
3 2 5
2 4 6
7 1 8
... ... ...
Leve em consideração que a função não precisa realizar retorno e que os números aleatórios
podem pertencer à faixa de 1 a 9.
Infográfico
Quebrar os programas em pedaços menores é uma técnica de desenvolvimento de sistemas que
facilita a manutenção e proporciona maior legibilidade do código escrito, pois é mais fácil encontrar
e resolver problemas em trechos menores. Além disso, usar funções permite reutilizar código, uma
vez que as funções são escritas uma única vez, mas podem ser chamadas diversas vezes ao longo
dos programas, proporcionando eficiência e ganho de produtividade.
Veja no Infográfico a seguir a importância de usar funções nos programas.
Conteúdo do livro
Escrever programas legíveis e de fácil manutenção está entre os principais objetivos de qualquer
programador de computador. Na prática, não raras vezes encontramos programas grandes que
repetem trechos de código. A experiência tem mostrado que programas grandes são difíceis de
entender e que dividir os programas em módulos menores pode facilitar a legibilidade e o
entendimento, bem como aumentar a produtividade por meio do reuso de código.
Para saber mais, leia o capítulo Funções e procedimentos, da obra Linguagem de programação, base
teórica desta Unidade de Aprendizagem.
Boa leitura.
LINGUAGEM DE
PROGRAMAÇÃO
Maurício de Oliveira Saraiva
Funções e procedimentos
Objetivos de aprendizagem
Ao final deste texto, você deve apresentar os seguintes aprendizados:
� Definir funções e procedimentos.
� Criar a chamada de funções e procedimentos.
� Usar variáveis locais e globais.
Introdução
Escrever programas legíveis e de fácil manutenção está entre os prin-
cipais objetivos de qualquer programador de computador. Na prática,
não raras vezes, encontra-se programas grandes, os quais geralmente
repetem trechos de código, e a experiência tem mostrado que eles são
difíceis de entender e que dividi-los em módulos menores pode facilitar
a legibilidade e o entendimento, bem como aumentar a produtividade
por meio do reuso de código.
Neste capítulo, você estudará a declaração e a chamada de funções,
bem como o uso de variáveis locais e globais.
Funções e procedimentos
Ao longo dos anos, analistas e programadores têm percebido que dividir
programas em blocos menores facilita o entendimento e a manutenção dos
códigos escritos, uma vez que resolver os problemas de pequenos módulos é
mais fácil que de programas inteiros (DEITEL; DEITEL, 2011).
No âmbito das linguagens de programação, como C e C++, os programas
são divididos em módulos ou subprogramas por meio de funções ou procedi-
mentos, que proporcionam diversas vantagens a eles, sendo uma das principais
a reutilização de código, pois pode ser aproveitado em várias partes de um ou
outros programas, evitando a repetição de comandos e instruções (VOTRE,
2016). Com isso, os programadores escrevem blocos de comandos que realizam
determinadas atividades de forma independente, como um cálculo matemático.
A função deve ser concisa, objetiva e executar apenas uma atividade ou funcionalidade.
Assim, caso haja dificuldade de nomeá-la, significa que ela poderá ser subdividida em
outras funções mais especializadas (DEITEL; DEITEL, 2011).
De modo geral, o procedimento e a função podem ser conceituados da
seguinte forma (SILVA FILHO, 2010).
� Procedimento: é um conjunto de instruções que desviam o fluxo de
sequência de um programa, podendo ou não receber parâmetros, po-
rém, não retorna nenhum valor. Por exemplo, uma rotina que inclui o
cabeçalho e o rodapé com dados da empresa em uma tela do sistema.
� Função: é um conjunto de instruções que desviam o fluxo de execução
de um programa, podendo ou não receber parâmetros. No entanto, uma
função deve, obrigatoriamente, retornar um valor após a sua execução.
Por exemplo, calcular o imposto de cada produto de uma nota fiscal.
Com a linguagem C++, é comum os programadores referenciarem as
funções e os procedimentos como se fossem funções, porém, a diferença
entre eles está no tipo do valor do retorno, pois o primeiro retorna um valor,
já o segundo não retorna nada.
A declaração de uma função é realizada da mesma forma, tanto na lingua-
gem C como na C++ e segue o seguinte modelo, conforme explicam Deitel
e Deitel (2011):
tipo de valor de retorno + nome da função + (lista de parâmetros)
Em que:
� Tipo de valor de retorno: especifica o tipo do retorno. Para função,
ele geralmente é um tipo primitivo, como int, float, char, etc., mas
pode ser uma estrutura, um ponteiro, um objeto ou algum outro. Já
para procedimento, ele se define pela palavra reservada void, que não
possui retorno.
Funções e procedimentos2
� Nome da função: define o nome pelo qual a função pode ser invocada
ou chamada.
� Lista de parâmetros: compreende os dados que são transferidos e
podem ser utilizados e modificados dentro da função. Esse item é
opcional, uma vez que a função não precisa ter parâmetros, por isso,
nesse caso, pode-se usar a palavra reservada void para indicar que não
existem parâmetros ou, simplesmente, deixar vazio.
Escolher os nomes de funções e parâmetros significativos torna os programas mais
legíveis e ajuda a evitar o uso excessivo de comentários (DEITEL; DEITEL, 2011).
Veja o exemplo de uma função que recebe dois números do tipo double
por parâmetro, efetua sua soma e retorna um valor, cujo tipo é double e se
define pela palavra reserva return, que devolve a variável soma no final da
execução. Já as variáveis n1 e n2 são passadas por parâmetro juntamente ao
seu tipo de dados (double). Note que essa função define o tipo do seu retorno,
assim, a instrução return deve, obrigatoriamente, devolver um valor do mesmo
tipo de dados.
Em um exemplo semelhante, vê-se uma função que não retorna valor (um
procedimento) e, nesse caso, deseja-se imprimir a subtração na tela, em vez
de retornar o valor da soma. Na declaração da função, as diferenças estão na
troca do tipo double por void e, na ausência da instrução, return.3Funções e procedimentos
O terceiro exemplo apresenta uma função que não recebe parâmetros,
nem devolve algum retorno. Por isso, ela imprime na tela o valor da cons-
tante matemática PI (M_PI), que está disponível na biblioteca da
linguagem C++.
Na linguagem C++, as funções e os procedimentos podem passar parâ-
metros de duas formas distintas, por valor e referência, sendo que, em uma
mesma função, é possível passa-los apenas por um ou por outro, ou ambos
simultaneamente (SILVA FILHO, 2010).
A passagem de parâmetros por valor se trata do modo mais usual, no qual
uma cópia das variáveis é passada para a função e qualquer modificação
nelas não produz alteração nas que foram passadas como parâmetro, porque a
linguagem C++ cria outro endereço de memória para alocar, temporariamente,
esses parâmetros usados apenas durante a execução da função. Quando a
função se encerra, essas variáveis são liberadas da memória.
Já na passagem de parâmetros por referência, a função recebe o endereço
de memória das variáveis que são passadas. Assim, qualquer modificação
nelas produz alteração no seu conteúdo original, pois, em vez de alocar outra
área na memória para os parâmetros, ela utiliza a mesma área da variável.
Para receber o endereço de memória das variáveis passadas como parâmetro
por referência, é preciso que a função utilize ponteiros, pois, por meio deles,
ela consegue acessar o endereço e modificar o valor original dessas variáveis.
Você pode ver exemplos de passagem de parâmetros por valor e referência no
tópico de chamadas de funções.
Chamada de funções e procedimentos
Você já viu como declarar funções e procedimentos, porém, ainda não apren-
deu como são realizadas as chamadas desses elementos. Para entender como
isso funciona, deve-se rever a execução de um programa na linguagem C++.
A execução de um programa em C++ se inicia pelo método main, que é o
primeiro a ser executado. Já o seu fluxo se realiza comando por comando, até
que a última instrução seja executada e o programa se encerre (AGUILAR,
2008). No entanto, quando se executa uma função, o fluxo de sequência pula
Funções e procedimentos4
para as suas instruções e, ao final, retorna ao método principal ou ao que
realizou a chamada para dar seguimento ao fluxo de execução do programa
(AGUILAR, 2008).
Para realizar a chamada de uma função, é preciso conhecer o seu funciona-
mento, identificar se possui ou não retorno e quais os parâmetros requeridos,
bem como conhecer os tipos de dados desses itens. Essa chamada é realizada
pelo seu nome, e se a função retorna um valor, este pode ser atribuído a uma
variável ou diretamente à outra função, como cout. O exemplo a seguir realiza
a chamada das funções mostradas anteriormente.
Veja no método main que a chamada da função somar se realiza por meio
da instrução que recebe dois parâmetros do tipo double (1.3 e 1.4) e retorna
a soma à variável resultado, cujo valor é 2.7, conforme apresentado a seguir.
Na sequência, o programa realiza a chamada da função imprimePI, a qual
não possui parâmetros, nem fornece nenhum retorno.
No exemplo apresentado, as funções estão implementadas acima do método
main e, portanto, quando a main é executada, essas funções já são conhecidas.
5Funções e procedimentos
Contudo, deve-se inserir anteriormente o seu protótipo quando uma função é
implementada depois do método que realiza a sua chamada.
O protótipo de uma função deve ser utilizado quando ela está implementada
abaixo do método que realiza a sua chamada. Nesse caso, ele é colocado acima
desse método para indicar o comportamento da função, o seu tipo de valor
de retorno e os seus parâmetros — podendo indicar apenas o tipo de dado ou
também as variáveis, conforme o seguinte exemplo.
Como mencionado anteriormente, existem duas formas de passar parâ-
metros para uma função: valor e referência. Para explicar as diferenças entre
elas, serão apresentadas duas funções que recebem dois números inteiros e
invertem seus valores.
Funções e procedimentos6
A função invertePorValor recebe os números 2 e 3 pelas variáveis a e b,
respectivamente, e inverte os valores com o auxílio de uma variável auxiliar.
No entanto, a mudança dos valores de a e b, por meio das variáveis n1 e n2, é
refletiva apenas dentro da função e deixa os valores originais de a e b como
2 e 3.
Já a função invertePorReferencia, que recebe os números 2 e 3 pelo caractere
&, utiliza ponteiros para referenciar o endereço de memória das variáveis a e
b por meio das variáveis *n1 e *n2. Assim, quando inverte os valores dentro
da função, reflete essa modificação nas variáveis que estão fora dela, no mé-
todo main. Na Figura 1, você pode ver o resultado da execução do algoritmo
apresentado.
Figura 1. Resultado da execução do algoritmo.
Em um programa C++, é possível fazer uma função reali-
zar sua própria chamada, esse recurso se chama função
recursiva ou recursividade. Para saber mais sobre isso, veja
o link ou o código a seguir.
https://goo.gl/iBYuAS
7Funções e procedimentos
Uso de variáveis locais e globais
As variáveis são expressões que podem armazenar valores temporariamente
na memória, e seu conteúdo deve estar de acordo com o tipo de dado de sua
declaração, por exemplo, uma variável do tipo int precisa armazenar um número
inteiro. Além do tipo de dado, uma variável segue uma regra de escopo, na qual
sua visibilidade varia conforme o local do programa em que foi declarada. Na
linguagem C++, existem dois tipos, locais e globais (VOTRE, 2016).
Variáveis locais
As variáveis locais são declaradas dentro de uma função ou de um bloco de
comandos e, por isso, apenas as instruções que estão na estrutura possuem
acesso a elas. Assim, declarar e usar uma variável dentro de uma função ou
de um bloco faz parte das melhores práticas, pois economizam recursos ao
utilizar dados temporários de curta duração (VOTRE, 2016).
Para ilustrar que uma variável local e declarada não pode ser acessada fora
do escopo, apresenta-se o seguinte exemplo, o qual tenta imprimir o conteúdo
de uma variável declarada dentro de uma função.
Note que a variável x foi declarada dentro da função acessaVariavel e não
pode ser acessada fora do seu escopo — da função apresentada. Nesse caso, ao
tentar acessar o conteúdo de x pela instrução cout no método main, o seguinte
erro será apresentado: ‘x’ was not declared in this scope.
Ainda em relação ao escopo, é possível declarar uma variável local com
o mesmo nome de outra, desde que elas pertençam a escopos diferentes.
Assim, ao utilizar uma delas, o programa usará sempre aquela que pertence
ao escopo atual.
Funções e procedimentos8
No próximo exemplo, tem-se a criação de uma variável local chamada x,
do tipo int, dentro da função escopo, com valor 10. Na sequência, verifica-se
se ela é par e, caso seja positivo, atribui-se 3 a ela e cria-se outra variável
com o mesmo nome, porém, do tipo float. Por fim, imprime-se o valor das
variáveis, cujo resultado é 1.2 e 3.
Na linguagem C++, também se conhece uma variável local como automá-
tica. A instrução auto pode ser inserida antes do seu tipo de dado, porém, é
opcional e, geralmente, a maioria dos programadores não a utiliza. Um exemplo
de declaração de variável local automática está apresentado a seguir, em que
ambas as declarações possuem o mesmo significado (DEITEL; DEITEL, 2011).
O armazenamento automático se trata de um meio de economizar memória, pois
as variáveis automáticas existem somente quando necessárias. Elas são criadas ao se
acionar a função na qual foram declaradas, e destruídas quando a função é encerrada
(DEITEL; DEITEL, 2011).
Portanto, uma variável local armazena seus dados apenas durante a exe-
cução das instruções do escopo definido. No entanto, é possível declarar uma
variável local estática na função e manter as informações que ela manipulou
anteriormente (SILVA FILHO, 2010).
9Funções e procedimentos
No exemplo apresentado a seguir, a variável ve é declaradacomo estática,
por isso, mesmo que ela seja local dentro da função incrementa, seu conteúdo
se mantém em todas as chamadas, diferentemente da variável vn que se reinicia
a cada execução.
Na Figura 2, você pode visualizar o resultado da execução do algoritmo
anterior.
Figura 2. Resultado da execução do algoritmo.
Variáveis globais
Diferentemente das variáveis locais, as globais podem ser acessadas de qualquer
local do programa, pois se declaram fora de qualquer definição de função ou
Funções e procedimentos10
de blocos de comandos (SILVA FILHO, 2010). Por isso, os dados armazenados
nelas são conservados durante toda a execução do programa. A declaração
de uma variável global deve ser realizada antes de ser utilizada no programa,
portanto, se uma função precisa fazer uso dela, essa variável deve ser declarada
antes da respectiva função.
Geralmente, as variáveis globais são declaradas no início dos programas, o que permite
aos programadores terem uma visão geral delas, pois todas ficam agrupadas em um
mesmo local.
Na linguagem C++, é possível realizar a inclusão de código-fonte externo
pela instrução include, com a qual os trechos de códigos localizados em ou-
tros arquivos são inseridos, proporcionando reuso e ganho de produtividade,
porém, pode acontecer um erro se ambos possuírem a mesma variável global
declarada (SILVA FILHO, 2010). Para resolver essa questão, pode-se usar a
instrução extern no arquivo que fará a inclusão de código-fonte, pois, assim,
o programa saberá que a variável está declarada em outro arquivo e, caso
contrário, realizará a sua declaração inicial se ela não for importada.
A declaração de uma variável extern pode ser realizada da seguinte forma
em C++:
Ao declarar uma variável no escopo global, permite-se que o programa
modifique-a em alguma função ou algum bloco de comandos durante a sua
execução, o que pode ser um problema se uma modificação acidental alterar
o seu valor. Dessa forma, a boa prática de programação define o uso restrito e
limitado dessas variáveis, em que se deve usá-las apenas em situações especiais
e realmente necessárias (DEITEL; DEITEL, 2011).
11Funções e procedimentos
1. Marque a alternativa que
apresenta o comportamento de
funções em linguagem C++.
a) Deve-se, necessariamente,
retornar um valor a quem
realizou a chamada por
meio da instrução return.
b) Pode-se, opcionalmente,
retornar um valor, pois a função
e o procedimento possuem
o mesmo comportamento.
c) É necessária a passagem
de parâmetros em funções,
uma vez que é a finalidade
de sua existência.
d) É possível retornar mais de
uma variável a uma função.
e) Deve-se declarar os protótipos de
funções em todos os programas
que possuem funções.
2. A linguagem C++ fornece duas
formas de passar parâmetros para
funções e procedimentos, sendo
elas por valor e referência. Nesse
contexto, é correto afirmar que:
a) a passagem de parâmetros
por referência é o modo
mais usual e não precisa
indicar qualquer diferença na
declaração, exceto os tipos
das variáveis e seus nomes.
b) a passagem de parâmetros por
valor utiliza ponteiros para se
referenciar ao valor das variáveis
que são passadas para a função.
c) na mesma função, é possível
passar parâmetros por valor e
referência simultaneamente.
d) todos os parâmetros precisam
ser passados da mesma
forma, se um da função for
por valor ou por referência.
e) o programa faz uma cópia
da variável na memória
para garantir que seu valor
original não seja modificado,
quando um parâmetro é
passado por referência.
3. Dada a seguinte função
implementada na linguagem
C++, indique a alternativa que
realiza a chamada da função:
a) maior().
b) maior(3, 5).
c) int resultado= maior(3, 5).
d) float resultado= maior().
e) cout n2)
3)
return n1;
else
return n2;
}
A) maior();
B) maior(3, 5);
C) int resultado= maior(3, 5);
D) float resultado= maior();
E) coutlocal estática se comporta como uma variável global.
E) Uma variável local criada dentro de uma instrução condicional não pode ser acessada fora
desse bloco de comandos.
Dada a seguinte função implementada na linguagem C++, indique a alternativa que
apresenta corretamente o resultado exibido na tela:
void funcao(float a, float b){
a= b;
b= a;
}
int main(){
float a= 3, b= 2;
funcao(a, b);
5)
cout