X 214 Função Definição matemá>ca Uma relação entre elementos de um conjunto (entrada) e elementos de outro conjunto (saída), com a propriedade que cada elemento da entrada relaciona-se com exatamente um elemento da saída. Definição computacional Uma unidade autônoma de código definida para executar um processamento específico. Outra definição Um conjunto de instruções agrupados em um bloco que recebe um nome e, através deste, pode ser executado. 215
Vantagens do uso de funções Dividir um único programa em unidades menores, mais fáceis de codificar e corrigir. cada um no seu quadrado Facilitar a compreensão e depuração do programa-fonte. Evitar a repe>ção de trechos de código. Permi>r a reu>lização de código já construído (por você ou por outros programadores.) Desenvolver a construção de programas complexos a par>r de módulos mais simples (o todo é a soma das partes). 216 Paradigma de programação modular em C programa... função 1 função 2 função n função 3 função 4 217
Execução de funções Quando uma função é chamada, o fluxo do programa é interrompido e desviado para a execução do bloco de instruções da função. Quando a execução a>nge o final do bloco da função, o fluxo do programa retorna ao ponto do programa onde a função foi chamada. Função Programa... Programa 218 E você nem desconfiava... Todo programa em C é formado por um conjunto de funções: printf(), scanf(), if(), while(), gets(), puts(), eita(),... A também é uma função!!! A execução de todo programa em C inicia pela função. Como todas as outras en>dades de um programa em C...... toda função deve ser declarada antes de ser usada. 219
A biblioteca math.h Contém a definição de diversas funções matemá>cas. função sin(x) cos(x) tan(x) fabs(x) sqrt(x) log(x) log10(x) exp(x) pow(x,y) retorna seno de x cosseno de x tangente de x x x ln x log 10 x e x x y Funções da biblioteca math.h Geralmente usam argumentos do >po double e retornam valores do >po double. 220 Forma geral de funções em C definidas pelo usuário O >po de valor produzido pela função (primi>vo ou definido pelo usuário) A lista de variáveis (>po e iden>ficador) u>lizadas pela função, separadas por vírgulas O nome da função O bloco da função tipo identificador(tipo arg1,..., tipo argn) declaração de variáveis; As variáveis internas da função corpo da função; Os comandos da função 221
Passagem de argumentos A declaração de uma função estabelece a lista >pada de argumentos necessários para seu processamento. As variáveis que compõem a lista de argumentos de uma função são conhecidas como parâmetros formais da função. Na chamada à função, apenas os valores (variáveis ou constantes) necessários para o processamento da função devem ser informados entre parênteses, na mesma ordem em que foram declarados na definição da função. Se uma função não precisar de argumentos para realizar o processamento, a lista de parâmetros será vazia. 222 O comando return() Após o processamento, uma função poderá produzir algum valor que poderá será u>lizado pelo programa. O comando return() é u>lizado para retornar para o programa um único valor resultante do processamento de uma função. O valor retornado pela função será uma variável de um dos seguintes >pos: primi>vos: char, int, float ou double (ou ponteiros desses >pos); definidos pelo usuário (ou ponteiros desses >pos). Atenção! Se uma função deve retornar múl>plos valores, então ela deverá ser redefinida em múl>plas funções, cada uma retornando apenas um valor. 223
Função definida pelo usuário Exemplo: Exibir os valores da função f(x) = 3x 3 5x 2 x + 5, num intervalo [a, b] informado pelo usuário. double F(double X) return(3*x*x*x 5*X*X X + 5); double a, b, x, y; printf("informe os extremos do intervalo: "); scanf("%f %f", &a, &b); for (x = a; x <= b; x = x + 0.1) y = F(x); printf("f(%f) = %f\n", x, y); primeiro calcula a expressão e depois retorna o resultado COMECE AQUI! chamada à função F(): x será copiado em X 224 Função definida pelo usuário Exemplo: Calcular y = x 2 : double Sqr(double x) double y; y é variável interna da função y = x*x; return(y); depois do processamento da função, y será copiado em resultado double valor, resultado; COMECE AQUI! printf("informe um numero: "); scanf("%lf", &valor); resultado = Sqr(valor); printf("%f^2 = %f\n", valor, resultado); chamada à função sqr(): valor será copiado em x 225
Função definida pelo usuário Exemplo: Calcular o fatorial de um número inteiro posi>vo. double Fatorial(int n) int i; double fat = 1; for (i = 1; i <= n; i++) fat = fat * i; return(fat); int n; printf("informe um número inteiro positivo: "); scanf("%d", &n); printf("%d! = %.0f\n", n, Fatorial(n)); COMECE AQUI! o resultado retornado pela função será exibido aqui. 226 Função definida pelo usuário Exemplo: Apresentar um menu e ler a opção do usuário. char Menu() char opc; UIA!? Uma função sem parâmetros! printf("escolha a operacao a ser realizada\n"); printf("[+] Adicao\n[-] Subtracao\n[*] Multiplicacao\n[/] Divisao\n"); printf("opcao: "); scanf("%c", &opc); return(opc); O valor lido dentro desta função será retornado para a função main() float a, b; char op; printf("informe os operandos: "); scanf("%f %f", &a, &b); op = Menu();... COMECE AQUI! O valor retornado pela função será atribuído à uma variável. 227
Função definida pelo usuário Exemplo: Calcular a soma de 2 números complexos. typedef struct double Re; double Im; complexo; complexo CpxSoma(complexo z1, complexo z2) complexo z; z.re = z1.re + z2.re; z.im = z1.im + z2.im; return(z); complexo x, y, w; printf("primeiro numero complexo: "); scanf("%lf %lf", &x.re, &x.im); printf("segundo numero complexo: "); scanf("%lf %lf", &y.re, &y.im); w = CpxSoma(x, y); printf("resultado: %f + %fi\n", w.re, w.im); 228 Retornando valores A definição de funções que retornam vetores de algum >po primi>vo (char, int, float ou double) ou definido pelo usuário é feita usandose ponteiros. Retornando uma string: char *NomeFuncao(...) Retornando um vetor de inteiros: int *NomeFuncao(...) Retornando uma matriz de valores reais de dupla precisão: double **NomeFuncao(...) 229
Retornando uma string Exemplo: Gerar uma senha usando n caracteres aleatórios da tabela ASCII. char *GeraString(int n) int i; char *s; ATENÇÃO: n deverá ser informado antes da chamada à função // alocar memoria para a string s = (char *) calloc(n + 1, sizeof(char)); // gerar a string elemento a elemento for (i = 0; i < n; i++) s[i] = 33 + rand()%(126-33 + 1); // usar os caracteres do intervalo [33, 126] s[n] = '\0'; return(s); Atenção! Em programas que u>lizam números aleatórios, a inicialização do gerador da semente através do comando srand(time(0)); deverá ser feita na função. 230 Retornando um vetor Exemplo: Gerar apostas na Mega-Sena com n dezenas (n informado pelo usuário.) int *Aposta(int n) int *v; // vetor de apostas int i, pos; // alocar memoria para o vetor de apostas v = (int *) calloc(60, sizeof(int)); // sortear as dezenas for (i = 0; i < n; i++) pos = rand()%60; // posição sorteada if (v[pos] == 1) // se a posição já havia sido sorteada, escolha outra i--; else v[pos] = 1; return(v); 231
Retornando uma matriz Exemplo: Criar uma matriz de Hilbert de ordem n. double **Hilbert(int n) double **a; int i, j; // alocar memória para os elementos da matriz a = (double **) calloc(n, sizeof(double *)); for (i = 0; i < n; i++) a[i] = (double *) calloc(n, sizeof(double)); // elementos da matriz de Hilbert for (i = 0; i < n; i++) for (j = 0; j < n; j++) a[i][j] = 1.0/(i + j + 1); return(a); 232 O >po primi>vo void O >po void é u>lizado apenas para definir funções que não retornam nenhum valor para a função que a chamou. void Menu() printf("escolha a operacao a ser realizada\n"); printf("[+] Adicao\n[-] Subtracao\n[*] Multiplicacao\n[/] Divisao\n"); printf("opcao: "); float a, b; char op; printf("informe os operandos: "); scanf("%f %f", &a, &b); Menu(); scanf( %c, &op);... Atenção! Funções do >po void não usam o comando return(). 233
O >po primi>vo void Calcular e exibir a tabuada do 7. int i, j; for (j = 0; j < 16; j++) printf("-"); printf("\n"); printf(" Tabuada do 7 \n"); for (j = 0; j < 16; j++) printf("-"); printf("\n"); for (i = 1; i <= 10; i++) printf( %2d X 7 = %2d\n, i, 7*i); for (j = 0; j < 16; j++) printf("-"); printf("\n"); void Linha(int n, char ch) int j; for (j = 0; j < n; j++) printf("%c", ch); printf("\n"); int i; Linha(16, '-'); printf(" Tabuada do 7 "); Linha(16, '-'); for (i = 1; i <= 10; i++) printf( %2d X 7 = %2d\n", i, 7*i); Linha(16, '-'); 234 Escopo de variáveis Existem dois >pos de variáveis em um programa em C: Variáveis locais São aquelas definidas dentro do bloco de alguma função. São visíveis apenas pela função onde foram declaradas e não podem ser usadas ou modificadas por outras funções do programa (nem pela função main()). Os parâmetros formais também são variáveis locais da função. Existem apenas enquanto a função es>ver sendo executada. Variáveis globais São aquelas definidas fora do bloco de alguma função. São visíveis por qualquer função e podem ser usadas ou modificadas por qualquer função do programa. Existem durante todo o tempo de execução do programa. Importante! Se houverem variáveis locais e globais com o mesmo nome, a função irá u>lizar apenas a variável local. 235
Escopo de variáveis int i; int F1(int n) j = n;... float F2(int i) int j; i = 2*i j = F1(i);... float j; // i é variável global // F1() tem uma variável local chamada n // erro: j não foi declarada como variável global ou local de f1() // F2() tem uma variável local chamada i // F2() tem uma variável local chamada j // alterando a variável local i // alterando a variável local j // COMECE AQUI! // j é variável local de main() i = 1; j = F2(i);... // alterando a variável global i // j recebe o resultado retornado pela função F2() 236 Escopo de variáveis O uso de variáveis globais permite trabalhar com funções sem argumentos. #include <stdio.h> #include <stdlib.h> float nota1, nota2, nota3, media; void LeNotas() printf("informe as notas das 3 provas: "); printf("1a prova = "); scanf("%f", ¬a1); printf("2a prova = "); scanf("%f", ¬a2); printf("3a prova = "); scanf("%f", ¬a3); LeNotas(); media = (nota1 + nota2 + nota3)/3; printf("media aritmetica = %f\n", media); 237
Passagem de parâmetros A chamada à uma função pode conter uma lista de variáveis que serão u>lizadas no processamento da função. Cada variável da lista pode ser passada de duas formas: Passagem por valor O valor da variável é copiado para o respec>vo parâmetro formal da função. As alterações realizadas dentro da função não modificam o valor original da variável. Passagem por referência O endereço da variável é passado para o respec>vo parâmetro formal da função. As alterações realizadas dentro da função modificam o valor original da variável. 238 Exemplo: Passagem por valor void Troca(int a, int b) int aux; aux = a; a = b; b = aux; printf("funcao: %d %d\n", a, b); int i = 2, j = 5; Execução: Main: 2 5 Funcao: 5 2 Main: 2 5 Pressione... printf("main: %d %d\n", i, j); Troca(i,j); printf("main: %d %d\n", i, j); OOOPS! A troca não modificou os valores originais. 239
Exemplo: Passagem por referência void Troca(int *a, int *b) int aux; aux = *a; *a = *b; *b = aux; printf("funcao: %d %d\n", *a, *b); int i = 2, j = 5; Execução: Main: 2 5 Funcao: 5 2 Main: 5 2 Pressione... printf("main: %d %d\n", i, j); Troca(&i,&j); printf("main: %d %d\n", i, j); TCHÃÃÃ! A troca modificou os valores originais. 240 Passagem de parâmetros Atenção! Na declaração de funções que u>lizam strings, vetores e matrizes como parâmetros devem ser u>lizados ponteiros. Logo, essas variáveis são sempre passadas por referência, ou seja, as modificações realizadas dentro da função alteram o valor original. Exemplo: Inverter uma string. void Inverte(char *str) int i, n; char tmp; n = strlen(str); // determina o tamanho da string for (i = 0; i < n/2; i++) tmp = str[i]; str[i] = str[n - 1 - i]; str[n - 1 - i] = tmp; 241
Passagem de parâmetros Exemplo: Cruzar 2 vetores binários com n elementos, usando os p primeiros elementos do 1º vetor e os n-p seguintes do 2º vetor. int *Cruzamento(int *v1, int *v2, int n, int p) int i; int *v; v = (int *) calloc(n, sizeof(int)); for (i = 0; i < n; i++) if (i < p) v[i] = v1[i]; else v[i] = v2[i]; return(v); 242 Estratégias de programação Exemplo: Calcular a soma dos n primeiros números naturais. Função fechada Estabelece uma seqüência de comandos onde o problema original não aparece. S(n) = n * ( (n + 1) / 2 ) Função recursiva Depende do valor da própria função, calculada para um caso reduzido. S(n) = n + S(n 1) 243
Funções recursivas São funções que fazem chamadas a si mesmas. A cada chamada, cria-se na memória uma nova ocorrência da função, com comandos e variáveis próprios, isolados das chamadas anteriores. A função será executada até que todas as ocorrências sejam resolvidas. Exemplo: n! = n * (n 1)! = n * (n 1) * (n 2)! =... double Fatorial(int n) double valor; if ( n <= 1 ) return (1); else valor = n * Fatorial(n - 1); return (valor); 244 Funções recursivas Exemplo: Cálculo de 3!. main: fat = Fatorial(3); retorna 6 Fatorial(3): valor = 3 * Fatorial(2); return (valor); retorna 2 Fatorial(2): valor = 2 * Fatorial(1); return (valor); Fatorial(1): return (1); retorna 1 245