Uma função só pode retornar um valor. Mas este valor pode ser de qualquer tipo.
Subalgoritmos são como pequenos programas internos à um programa. Também chamados de “funções”, por lembrarem funções matemáticas.
Esses subalgoritmos são definidos 1 vez no programa e podem ser usados tantas vezes quanto forem necessárias.
As funções ajudam a organizar um código que seja muito extenso, facilitando sua manutenção e leitura, uma vez que seria muito complicado entender um código de 1000+ linhas com tudo escrito na int main()
Auxiliam na modularização do código
Repetir códigos (CTRL+C CTRL+V) diminui a legibilidade do programa;
Código copiado com erro precisa ser consertado em múltiplos lugares do programa;
Mais linhas de código do que seriam necessárias causa maior dificuldade de manutenção;
O programador fica perdido no código;
Mais difícil de fazer o debugging.
Cabeçalho - declaração da função. Inclui tipo de retorno, nome e lista de parâmetros. Como boa prática é imediatamente precedida de um comentário explicando o que a função faz.
Corpo da função - Define a implementação e funcionamento da função. Idealmente não é muito extenso.
Escopo da função - Marcam a abertura e o fechamento da função, “separando-a” do resto do programa.
Toda função precisa de um tipo. O tipo da função informa ao compilador se a função irá retornar alguma coisa, e qual o tipo dessa coisa, ou se a função não deve retornar nada.
O tipo da função precede o nome dela no cabeçalho. Uma função pode ser de qualquer tipo: int, float, double, etc.
O escopo de uma função define quais linhas de código serão executadas quando a função for invocada, e também separa as variáveis locais da função do resto do programa.
Os escopos são marcados por chaves (i.e. {}). Cada chave { abre um escopo e a cada chave } fecha o último escopo aberto. Obviamente toda chave { precisa de uma chave } correspondente.
Não são apenas funções que possuem escopo, estruturas de repetição e condicionais também possuem. Por exemplo:
... if (a > b){ /* Escopo do if marcado por chaves. A variável local tmp só existe dentro do escopo */ int tmp = a; a = b; b = tmp; } else { /* Escopo do else. A variável tmp não existe neste escopo. */ } ...
Uma função só pode retornar um valor. Mas este valor pode ser de qualquer tipo.
Algumas funções podem precisar de variáveis auxiliares enviadas de fora da função. Essas variáveis são os parâmetros. Parâmetros precisam ser definidos no cabeçalho da função, incluindo seu tipo.
Pense neles como os parâmetros de uma função matemática. Por exemplo, a função f(x) = x2 recebe um parâmetro x e calcula o quadrado dele. Em C podemos escrever a mesma função como:
int f(int x){ return x*x; }
Note que ambas as funções fazem a mesma coisa: retornam o quadrado do parâmetro. Para executar uma função, basta chamá-la passando o valor do parâmetro entre parênteses, por exemplo:
int a = f(5); /* a recebe 25 */ int sq_a = f(a); /* sq_a recebe 625 */ printf("%d\n", f(2)); /* Imprime 4*/
Existem algumas particularidades sobre parâmetros de função em C que serão vistos em mais detalhes na próxima aula.
Esta função não possui retorno nem parâmetros.
Ela pode ser usada se for necessário mostrar as opções várias vezes.
/* Simples função para mostrar um menu. */ #ifdef _WIN32 #define CLEAR "cls" #else #define CLEAR "clear" #endif void options(){ int i; /* clear screen*/ system(CLEAR); /* Show options*/ printf("Choose your option\n"); printf("(1) First options\n"); printf("(2) Second options\n"); printf("(3) Third options\n"); } int main(){ int option; do{ options(); scanf("%d", &option); }while(option < 1 or option > 3); return 0; }Download Code
Esta função novamente não possui retorno (pois é void) porém desta vez possui parâmetros
Possui 2 parâmetros, uma variável h e w para altura e largura, respectivamente
void printSquare(int h, int w){ int i,j; /* Print first line */ for(i = 0; i < w; i++) printf("#"); printf("\n"); /* Print left & right columns */ for(i = 1; i < h-1; i++){ for(j = 0; j < w; j++){ if(!j || j == w-1) printf("#"); else printf(" "); } printf("\n"); } /* Print last line if exist */ if(h > 1){ for(i = 0; i < w; i++) printf("#"); printf("\n"); } } int main(){ printf("What's rectangle size?\n"); int x,y; scanf("%d %d", &x, &y); printSquare(x,y); return 0; }Download Code
Exemplo no terminal
APC$ gcc -Wall -ansi -o rectangle rectangle.c APC$ ./rectangle What's rectangle size? 5 9 ######### # # # # # # #########
Programa mostra quais dos 100 primeiros números são primos.
Note os returns na função.
/* Retorna 1 (true) se o numero for primo e 0 (false) caso contrário*/ int primo(int n){ int i; int m = (int) sqrt(n); for(i = 2; i <= m; i++){ if(n%i == 0){ return 0; } } return 1; } int main(){ int i; for(i = 2; i <= 100; i++){ if(primo(i) == 1) printf("%d eh primo\n", i); else printf("%d nao eh primo\n", i); } return 0; }Download Code
Exemplo no terminal
APC$ gcc -Wall -ansi -o prime prime.c -lm APC$ ./prime 2 eh primo 3 eh primo 4 nao eh primo 5 eh primo 6 nao eh primo 7 eh primo 8 nao eh primo 9 nao eh primo 10 nao eh primo . . .
Vimos que variáveis locais são as declaradas dentro de um escopo. As variáveis globais são aquelas cujo escopo é o programa inteiro.
Elas são declaradas fora de qualquer função (incluindo a função main)
#include <stdio.h> int a = 10; /* variavel global */ void print(){ printf("a = %d\n", a); /* variaveis globais podem ser acessadas em qualquer lugar do programa */ } int main(){ printf("a = %d\n", a); a += 10; /* variaveis globais podem ser alteradas em qualquer lugar do programa */ print(); return 0; }
Se tivermos uma variável global e outra local com o mesmo nome, qual terá preferência?
Vamos ver qual escopo tem preferência através de um exemplo.
Independente da resposta, nunca é uma boa prática ter 2 variáveis com o mesmo nome!
#include <stdio.h> /* variavel global */ int a = 0; void question(){ /* variavel local de question */ int a = 50; printf("a: %d\n", a); } int main(){ printf("global a: %d\n", a); /* variavel local em main */ int a = 10; if(a == 10){ printf("Variavel local tem preferencia.\n"); } else{ printf("Variavel global tem preferencia.\n"); } printf("a: %d\n", a); printf("Agora em outro escopo - question\n"); question(); printf("A variavel na main foi alterada?\n"); printf("a: %d\n", a); return 0; }Resposta
Agora que aprendemos sobre escopo, qual será o valor impresso em cada saída?
#include <stdio.h> int y = 20; int max(int a, int b){ y += 15; if (a >= b) return a; else return b; } int main(){ int x = 5; y = 10; printf("x = %d\n", x); printf("y = %d\n", y); printf("max(x,y) = %d\n", max(x,y)); printf("y = %d\n", y); return 0; }Resposta