A linguagem C tem a
característica de ser uma linguagem do tipo estruturada, onde os dados são
executados segundo a ordem na qual escrevemos o código. Pois bem, pensemos em
um exemplo onde temos um código em C com mil linhas! Você há de convir que pode
ser complicado entender o código, embora utilizemos os comentários. Também pode
haver repetições de comandos que poderiam ser evitados. Para resolver esses e
outros problemas, a Linguagem C permite a criação de blocos de comandos, que
são as funções e os procedimentos.
Dessa forma, podemos afirmar que o uso de blocos de comandos com as funções e procedimentos trazem os seguintes benefícios:
1. Simplificação do código – uma vez que o código de um
programa é estruturado em blocos com funcionalidades específicas fica mais
simples a leitura do código;
2. Reaproveitamento do código – você pode reaproveitar tudo
que foi organizado em blocos, os comandos
específicos, e chamar diversas
vezes ao longo do programa;
3. Evita repetições – pois o código de um bloco pode ser
chamado em qualquer parte do programa, evitando ter de reescrever novamente
vários comandos;
4. Manutenção do código mais fácil – pois as funcionalidades
estarão dispostas em blocos específicos, facilitando
encontrar erros e alterar o
código com maior facilidade.
A principal diferença entre a
função e o procedimento é que o procedimento não envia uma resposta ao comando
que o chama, já a função tem um retorno ao comando que o chamou. Porém, na
Linguagem C não existe diferença entre um procedimento e uma função em termos
práticos.
Com tantas vantagens,
apresentaremos agora tais técnicas mais detalhadamente.
Os procedimentos são blocos
declarados no programa os qual podem ser chamados durante a execução de um
programa. Segue a sintaxe para a criação de um procedimento em Linguagem C:
void
<nome_do_procedimento>(parâmetros){ Comandos;
}
Um procedimento deve iniciar pela
declaração de seu tipo como void. A palavra void é uma declaração de um tipo de
variável, que não é de nenhum tipo especifico. Assim, void significa um tipo de
variável que não tem valor. Diferentemente da função, um procedimento não
retorna valores, por isso a definição do tipo void para os procedimentos.
O nome de uma função obedece as
normas de declaração de variáveis. Quanto aos parâmetros, estes são valores que
as funções podem receber da função principal main(). Caso o procedimento não
receba nenhum valor, este terá de ser do tipo void. Segue um exemplo de um
procedimento para imprimir um “olá mundo” na tela.
#include <stdio.h>
void Olamundo (void){
printf ("ola mundo
:)");
}
void main (){
printf ("Aqui vamos chamar a
funcao \n\n\n"); Olamundo();
}
Note que no código fonte, primeiro declaramos o procedimento para depois chamá-lo no corpo do
programa.
Um procedimento também pode ser
escrito depois da função main(), sendo que para podermos compilar
um programa na Linguagem C
devemos declarar um procedimento ou
função antes de chama-lo,
semelhante a uma variável.
Vejamos o programa abaixo que ilustra essa situação:
#include <stdio.h> void
imprimitexto (); void main(){
char texto[20];
printf("Digite um texto
\n\n"); gets (texto); imprimitexto(texto);
}
void imprimitexto (char tx[20]){
printf ("\n imprimindo o
texto \n\n %s", tx);
Descrição dos comandos do
procedimento que deve receber um valor do tipo char.
}
No programa anterior, informamos
que teríamos um procedimento, mas o código do mesmo (bloco de comandos) está
descrito abaixo da função principal, isso facilita bastante a leitura de um
código em C, em especial se o mesmo tiver muitas linhas de comandos.
Quanto ao recebimento de parâmetros, um procedimento pode receber tantos parâmetros quantos se deseje passar, e estes podem ser de diversos tipos. Neste caso, estamos trabalhando a passagem de parâmetro por Valor, ou seja, passamos para a função apenas o valor de uma variável, que é recebida pela função e armazenada em uma nova variável. Vejamos a ilustração dessa operação que acontece no exemplo acima:
No programa principal, entramos
com um valor para a variável texto:
“ASSSSSS”
O procedimento recebe o valor e armazena em uma nova variável tx, assim temos:
Ao final, existem duas variáveis, que estão com o mesmo valor:
A esse tipo de operação
denominamos de passagem de valor. Caso desejássemos alterar o valor em uma das
variáveis, como no exemplo acima na variável “tx”, essa alteração não afetaria
a variável “texto”.
Quanto às variáveis, podemos ter
variáveis criadas dentro do próprio procedimento ou função. Tais variáveis são
denominadas de variáveis locais e só existirão dentro do procedimento ou
função. As variáveis recebidas por parâmetros são desse tipo, locais, pois
podem ser modificadas apenas dentro do procedimento ou função.
Já as variáveis definidas na
função main() são variáveis do tipo global e o seu valor não pode ser alterado
dentro de um procedimento ou função, apenas dentro de main(). Assim, é comum
trabalharmos com variáveis locais dentro dos procedimentos ou funções de um
programa a fim de preservar o valor de uma variável do tipo global.
Detalhe: há sim uma forma de
alterar o valor de uma variável do tipo global, ensinaremos isso mais adiante.
Abaixo veremos o exemplo de um
programa em C em que um procedimento recebe três valores a ser impresso, que
são o nome, a idade e a altura de uma pessoa. Temos:
#include <stdio.h>
void imprimeinfo (char nme[20],
int ida, float alt); void main(){
char nome[20]; int idade;
float altura;
printf("Digite o nome da
pessoa \n\n"); gets(nome);
printf("Digite a idade da
pessoa \n\n"); scanf ("%d", &idade);
printf("Digite a altura da pessoa \n\n"); scanf ("%f", &altura); imprimeinfo(nome, idade, altura);
}
void imprimeinfo (char nme[20],
int ida, float alt){ printf ("\n %s", nme);
printf ("\n %d", ida);
printf ("\n %f", alt);
}
Neste exemplo, como recebemos
mais de um parâmetro no procedimento, temos de declarar o procedimento com
todos os parâmetros para evitar erro de compilação e receber os valores
passados de forma correta.
Notemos que a variável nome,
idade e altura são do tipo global, criadas na função principal do programa. Já
as variáveis nme, ida e alt são variáveis locais que recebem valores das variáveis
globais para imprimir as mesmas.
Funções
A principal diferença entre uma
função e um procedimento é que a função deve retornar um valor, embora que esse
valor seja void. Esse valor é retornado pela função através da função return.
Vejamos a sintaxe de uma função:
Tipo <nome_da função>(lista
de parâmetros){
comandos;
return();
}
Uma função pode ser do tipo void,
que não retorna nenhum valor. Nesse caso, é dispensável o uso do comando
return, embora isso a deixe caracterizada como um procedimento. Porém, já
dissemos antes que a Linguagem C não distingue, na prática, um procedimento de
uma função.
Como tudo em C é função e sabemos
agora que toda a função tem de ter um tipo e um retorno, a função main() não é
diferente. Acontece que muitos compiladores já aceitam que a função main() não
tenha um tipo nem retorno, até o momento se você estiver utilizando o DEV C++
não percebeu isso. Porém, a forma correta de escrever um programa em C é
declarando o tipo da função main() e o retorno desta, através do comando
return, e por padrão, toda função main() é do tipo inteiro , caso não a seja
declarada de outro tipo. Vejamos o código abaixo:
#include <stdio.h> int
main(){
printf("ola mundo");
return 0;
}
Assim, quando usamos a expressão
void main() estamos declarando que a função principal não tem retorno a quem a
chama, no caso não há retorno para o sistema operacional.
Vejamos um exemplo de um programa
em C que usa uma função para execução de uma operação de soma. No exemplo,
iremos trabalhar um programa que recebe dois números fornecidos pelo usuário e
utiliza uma função para somar os dois números recebidos. A soma é executada na
função específica que retorna o valor somado à função principal.
#include <stdio.h>
int soma (int n1, int n2); void
main (){
int num1, num2, result;
printf ("entre com o valor
1"); scanf ("%d", &num1);
printf ("entre com o valor
2"); scanf ("%d", &num2); result=soma(num1,num2);
printf ("a soma dos dois
numeros foi %d ", result);
}
/*função para somar dois numeros
retornando o valor*/ int soma (int n1, int n2){
int s; s=n1+n2; return(s);
}
No exemplo acima, podemos
perceber o uso do comando return passando um valor a ser armazenado na variável
result que está na função principal e chama função soma.
Quando trabalhamos com funções,
só podemos usar as variáveis definidas na função. Ou seja, não tem como
trabalharmos a questão de uma variável global, definida na função main(), em
uma função ou procedimento.