Mudanças entre as edições de "SOP-funcoes"

De MediaWiki do Campus São José
Ir para navegação Ir para pesquisar
Linha 5: Linha 5:
 
#'''Facilitar a reutilização de um algoritmo em diferentes partes de um programa:''' um exemplo são as funções [http://www.kernel.org/doc/man-pages/online/pages/man3/printf.3.html printf] e [http://www.kernel.org/doc/man-pages/online/pages/man3/scanf.3.html scanf], que fazem parte da [http://pt.wikipedia.org/wiki/Biblioteca_padr%C3%A3o_do_C biblioteca C padrão].
 
#'''Facilitar a reutilização de um algoritmo em diferentes partes de um programa:''' um exemplo são as funções [http://www.kernel.org/doc/man-pages/online/pages/man3/printf.3.html printf] e [http://www.kernel.org/doc/man-pages/online/pages/man3/scanf.3.html scanf], que fazem parte da [http://pt.wikipedia.org/wiki/Biblioteca_padr%C3%A3o_do_C biblioteca C padrão].
 
#'''Reduzir a complexidade de um programa, ao dividi-lo em algoritmos menores e mais simples''': a divisão de um programa em pequenos algoritmos especializados o torna mais fácil de ser escrito, de ser lido e entendido, de ser depurado (debug) e mantido, e também de ser modificado.
 
#'''Reduzir a complexidade de um programa, ao dividi-lo em algoritmos menores e mais simples''': a divisão de um programa em pequenos algoritmos especializados o torna mais fácil de ser escrito, de ser lido e entendido, de ser depurado (debug) e mantido, e também de ser modificado.
 +
 +
== ola, mundo ! ==
  
 
Uma forma simples de entender funções é vê-las como algoritmos, que podem ser usadom em diferentes partes de um programa, e mesmo em diferentes programas. Um primeiro exemplo é mostrado a seguir:
 
Uma forma simples de entender funções é vê-las como algoritmos, que podem ser usadom em diferentes partes de um programa, e mesmo em diferentes programas. Um primeiro exemplo é mostrado a seguir:
Linha 49: Linha 51:
 
  Ola, mundo !
 
  Ola, mundo !
 
  Ola, mundo !
 
  Ola, mundo !
 +
 +
== Funções com parâmetros e declaração de funções ==
  
 
Mas e se fosse desejável criar uma função que pudesse mostrar diferentes mensagens na tela ? O exemplo abaixo ilustra uma forma de fazer isto:
 
Mas e se fosse desejável criar uma função que pudesse mostrar diferentes mensagens na tela ? O exemplo abaixo ilustra uma forma de fazer isto:
Linha 98: Linha 102:
 
[[Image:Quadrado.png|300px]]
 
[[Image:Quadrado.png|300px]]
  
Esses são os elementos básicos para declarar, escrever e usar funções. Os próximos exemplos mostram outras situações em que se usam funções.
+
Esses são os elementos básicos para declarar, escrever e usar funções.  
 +
 
 +
== Valor de retorno de função ==
 +
 
 +
Os próximos exemplos mostram outras situações em que se usam funções.
 +
 
 +
=== Função para testar se um número é par ou ímpar ===
  
 
<syntaxhighlight lang=c>
 
<syntaxhighlight lang=c>
Linha 148: Linha 158:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Lembre que o operador ''!'' é equiavalente a NÃO lógico (negação de uma condição). Então a condição ''! eh_par(x)'' é verdadeira se ''x'' não for par.
+
Lembre que o operador ''!'' é equivalente a NÃO lógico (negação de uma condição). Então a condição ''! eh_par(x)'' é verdadeira se ''x'' não for par.
 +
 
 +
=== Função para testar se um número é primo ===
 +
 
 +
Um exemplo semelhante ao anterior trata da verificação se um número é primo:
 +
 
 +
<syntaxhighlight lang=c>
 +
#include <stdio.h>
 +
 
 +
int primo(int n) {
 +
  int x, ok;
 +
 
 +
  x = 2;
 +
  ok = 1;
 +
  while ((x <= (n/2)) && ok) {
 +
    if ((n % x) == 0) {
 +
      ok = 0;
 +
    } else x++;
 +
  }
 +
  return ok;
 +
}
 +
 
 +
int main() {
 +
  int n;
 +
 
 +
  printf("Numero: ");
 +
  scanf("%d", &n);
 +
  if (primo(n)) {
 +
    printf("%d eh primo\n", n);
 +
  } else {
 +
    printf("%d nao eh primo\n", n);
 +
  }
 +
}
 +
</syntaxhighlight>
 +
 
 +
A função ''int primo(int n)'' retorna 1 se o valor passado como parâmetro no argumento ''int n''for primo, e 0 caso contrário. Essa função possui um algoritmo mais elaborado que os exemplos anteriores, o qual utiliza uma estrutura de repetição com ''while (condição)'' (equivalente ao ''Enquanto condição'' do Portugol). Inclusive nessa função aparece um operador aritmético novo, usado para incrementar variáveis numéricas:
 +
 
 +
<syntaxhighlight lang=c>
 +
x++;
 +
</syntaxhighlight>
 +
 
 +
Isto é equivalente a:
 +
 
 +
<syntaxhighlight lang=c>
 +
x = x + 1;
 +
</syntaxhighlight>
 +
 
 +
De forma análoga, existe um operador parecido para decremento:
 +
 
 +
<syntaxhighlight lang=c>
 +
x--;
 +
</syntaxhighlight>
 +
 
 +
... equivalente a:
 +
 
 +
<syntaxhighlight lang=c>
 +
x = x - 1;
 +
</syntaxhighlight>
 +
 
 +
=== Função para fatorar um número ===
 +
 
 +
Esse exemplo para teste se números são primos pode ser aproveitado para criar um programa que fatore um número em seus divisores primos:
 +
 
 +
#include <stdio.h>
 +
 
 +
int primo(int n) {
 +
  int x, ok;
 +
 
 +
  x = 2;
 +
  ok = 1;
 +
  while ((x <= (n/2)) && ok) {
 +
    if ((n % x) == 0) {
 +
      ok = 0;
 +
    } else x++;
 +
  }
 +
  return ok;
 +
}
 +
 
 +
int main() {
 +
  int p, x;
 +
 
 +
  printf("Numero: ");
 +
  scanf("%d", &x);
 +
  p = 1;
 +
  while (x != 1) {
 +
    do {
 +
      p ++;
 +
    } while(!primo(p));
 +
 
 +
    while ((x % p) == 0) {
 +
      x = x /p;
 +
      printf("%d\n", p);
 +
    }
 +
  }
 +
}
 +
 
 +
</syntaxhighlight>
 +
 
 +
A função ''int primo(int n)'' foi reaproveitada para escrever esse novo programa, que mostra todos os fatores primos que dividem um número.
 +
 
 +
== Passagem de parâmetros ==
 +
 
 +
O próximo exemplo mostra uma função que torna maiúscula a primeira letra de uma ''string'':
 +
 
 +
<syntaxhighlight lang=c>
 +
#include <stdio.h>
 +
 
 +
void faz_primeira_letra_maiuscula(char * nome) {
 +
  if ((nome[0] >= 'a') && (nome[0] <= 'z')) {
 +
    nome[0] = nome[0] - 32;
 +
  }
 +
}
 +
 
 +
int main() {
 +
  char nome[32];
 +
 
 +
  printf("Digite um nome: ");
 +
  scanf("%s", nome);
 +
  faz_primeira_letra_maiuscula(nome);
 +
  printf("Nome: %s\n", nome);
 +
}
 +
</syntaxhighlight>
 +
 
 +
A função ''void faz_primeira_letra_maiuscula(char * nome)'' converte a primeira letra do parâmetro ''char * nome'' para maiúscula. A conversão se baseia na [http://pt.wikipedia.org/wiki/Ascii tabela ASCII], que associa códigos numéricos a caracteres. Mas a novidade nessa função é a possibilidade de modificar um valor passado como parâmetro, o que não acontecia nas funções vistas até então. Dependendo de como foi passado um parâmetro, modificações em seu valor dentro de uma função podem ou não refletir fora dessa função.
 +
 
 +
#*'''Passagem por valor:''' o valor da variável passada como parâmetro é copiado para uma variável local da função. Com isto, qualquer modificação feita na variável local da função não afeta a variável que foi passada como parâmetro. Ex:<syntaxhighlight lang=c>int incrementa_e_mostra(int x) {
 +
  x = x + 1;
 +
  printf("x=%d\n", x);
 +
}
 +
 
 +
int main() {
 +
  int contador = 0;
 +
 
 +
  incrementa_e_mostra(contador);
 +
  incrementa_e_mostra(contador);
 +
  incrementa_e_mostra(contador);
 +
  printf("Ao final, contador=%d\n", contador);
 +
}
 +
</syntaxhighlight>Ao executar este programa exemplo, o resultado na tela deve ser o seguinte:<br>''x=1''<br>''x=1''<br>''x=1''<br>''Ao final, contador=0''<br>... o que evidencia que o valor de ''contador'' não foi modificado dentro da função ''incrementa_e_mostra''.
 +
#*'''Passagem por referência:''' a própria variável é passada como parâmetro (quer dizer, a sua localização em memória, por isto se diz ''por referência''). Assim, qualquer modificação feita dentro da função chamada refletirá na variável que foi passada como parâmetro. Ex:<syntaxhighlight lang=c>int incrementa_e_mostra(int * x) {
 +
  *x = *x + 1;
 +
  printf("x=%d\n", *x);
 +
}
 +
 
 +
int main() {
 +
  int contador = 0;
 +
 
 +
  incrementa_e_mostra(&contador);
 +
  incrementa_e_mostra(&contador);
 +
  incrementa_e_mostra(&contador);
 +
  printf("Ao final, contador=%d\n", contador);
 +
}</syntaxhighlight>Ao se executar o exemplo acima, o resultado na tela deve ser:<br>''x=1''<br>''x=2''<br>''x=3''<br>''Ao final, contador=3''<br>Fica evidente que o valor da variável ''contador'' foi modificado dentro da função ''incrementa_e_mostra''. Repare que algumas diferenças de sintaxe existem quando se usa passagem por referência:
 +
#**A declaração do parâmetro na função deve ter um ''*'' (asterisco) antes do nome do parâmetro (ex: ''incrementa_e_mostra(int * x)'' )
 +
#**Dentro da função deve-se preceder com ''*'' (asterisco) o nome da variável do parâmetro (ex: ''*x = *x + 1;'')
 +
#***Quando a variável passada como parâmetro for do tipo ''struct'', ao invés de precedê-la por ''*'' (asterisco), deve-se usar a seguinte sintaxe: ''nome_variável->campo'' ao invés de ''nome_variável.campo''. Veja a função ''adiciona_pessoa'' do cadastro como exemplo.
 +
#**Na chamada da função, deve-se preceder com ''&'' o nome da variável passada como parâmetro (ex: ''incrementa_e_mostra(&contador);'' )
 +
#**As duas últimas regras de sintaxe acima não valem quando se passa uma variável ''string'' como parâmetro. Isto porque uma variável ''string'' por definição já é uma variável que contém um endereço de memória (quer dizer, ela já funciona como uma referência aos dados). Na verdade, isto vale para qualquer variável do tipo vetor (lembre que a ''string'' é um vetor de ''char''). Ex: <syntaxhighlight lang=c>void faz_primeira_letra_maiuscula(char * nome) {
 +
  if ((nome[0] >= 97) && (nome[0] <= 122)) {
 +
    nome[0] = nome[0] - 32;
 +
  }
 +
}
 +
 
 +
int main() {
 +
  char nome[32];
 +
 
 +
  printf("Digite um nome: ");
 +
  scanf("%s", nome);
 +
  faz_primeira_letra_maiuscula(nome);
 +
  printf("Nome: %s\n", nome);
 +
}</syntaxhighlight>
 +
#*'''No caso do exemplo do cadastro:''' para ver a diferença entre ''passagem de parâmetro por referência'' e ''por valor'' no caso do cadastro, veja [[media:Cadastro4.txt|esta versão do cadastro]] em que a função ''adiciona_pessoa'' faz passagem por valor.
 +
#*Veja no curso de linguagem C da UFMG uma discussão mais aprofundada sobre [http://www.sj.ifsc.edu.br/~msobral/SOP/docs/C_ufmg/aulas/c770.html passagem de parâmetros] e [http://www.sj.ifsc.edu.br/~msobral/SOP/docs/C_ufmg/aulas/c760.html escopo de variáveis].
 +
 
 +
== Reaproveitamento e especialização de funções ==
 +
 
 +
Uma função pode ser especializada para fazer uma tarefa mais limitada. Veja o exemplo da inicial maíuscula:
 +
 
 +
<syntaxhighlight lang=c>
 +
#include <stdio.h>
 +
 
 +
void faz_letra_maiuscula(char * nome, int pos) {
 +
  if ((nome[pos] >= 97) && (nome[pos] <= 122)) {
 +
    nome[pos] = nome[pos] - 32;
 +
  }
 +
}
 +
 
 +
void faz_primeira_letra_maiuscula(char * nome) {
 +
  faz_letra_maiuscula(nome, 0);
 +
}
 +
 
 +
int main() {
 +
  char nome[32];
 +
 
 +
  printf("Digite um nome: ");
 +
  scanf("%s", nome);
 +
  faz_primeira_letra_maiuscula(nome);
 +
  printf("Nome: %s\n", nome);
 +
}
 +
</syntaxhighlight>
 +
 
 +
Apesar de o resultado ser exatamente o mesmo do exemplo anterior, em que havia somente a função ''faz_primeira_letra_maiuscula'', esse novo exemplo mostra como especializar uma função mais geral. A função ''void faz_letra_maiuscula(char * nome, int posicao)'' torna maiúscula a letra contida na posição ''pos'' da ''string'' 'nome''. Quer dizer, ''faz_letra_maiuscula'' é capaz de tornar maiúscula qualquer letra da ''string'' contida em ''nome''. A função ''void faz_primeira_letra_maiuscula(char * nome)'' torna maiúscula a letra inicial da ''string'' contida em ''nome'', e para fazer isto agora foi usada a função ''faz_letra_maiuscula'', indicando-se que se quer mudar a letra na posição ''0''.
 +
 
 +
== Funções que usam tipos de dados definidos pelo usuário (ou ''struct'') ==

Edição das 20h04min de 8 de novembro de 2009

Linguagem C: funções

Mas afinal para que servem funções ? Para propósitos como:

  1. Facilitar a reutilização de um algoritmo em diferentes partes de um programa: um exemplo são as funções printf e scanf, que fazem parte da biblioteca C padrão.
  2. Reduzir a complexidade de um programa, ao dividi-lo em algoritmos menores e mais simples: a divisão de um programa em pequenos algoritmos especializados o torna mais fácil de ser escrito, de ser lido e entendido, de ser depurado (debug) e mantido, e também de ser modificado.

ola, mundo !

Uma forma simples de entender funções é vê-las como algoritmos, que podem ser usadom em diferentes partes de um programa, e mesmo em diferentes programas. Um primeiro exemplo é mostrado a seguir:

#include <stdio.h>

void ola() {
  printf("Ola, mundo !\n");
}

int main() {
  ola();
}

Ao se executar o programa acima, o resultado é aparecer na tela a mensagem "Ola, mundo !":

> gcc -o ola ola.c
> ./ola
Ola, mundo !

Se o exemplo for modificado da seguinte forma:

#include <stdio.h>

void ola() {
  printf("Ola, mundo !\n");
}

int main() {
  ola();
  ola();
  ola();
}

... sua execução dará como resultado:

> gcc -o ola ola.c
> ./ola
Ola, mundo !
Ola, mundo !
Ola, mundo !

Funções com parâmetros e declaração de funções

Mas e se fosse desejável criar uma função que pudesse mostrar diferentes mensagens na tela ? O exemplo abaixo ilustra uma forma de fazer isto:

#include <stdio.h>

void mostra_mensagem(char * mensagem) {
  printf("Sua mensagem: %s\n", mensagem);
}

int main() {
  mostra_mensagem("Ola, mundo");
  mostra_mensagem("testando ...");
  mostra_mensagem("");
  mostra_mensagem("testando de novo ...");
}

Se o programa acima for executado, dará este resultado:

> gcc -o mostra mostra.c
> ./mostra
Sua mensagem: Ola, mundo
Sua mensagem: testando ...
Sua mensagem:
Sua mensagem: testando de novo ...

A função mostra_mensagem apresenta na tela uma string que é especificada no momento em que essa função é chamada. A isto se chama parametrização: tornar um algoritmo independente de valores específicos de entrada, de forma que possa funcionar com qualquer valor de entrada compatível. O próximo exemplo aprofunda este conceito por meio de uma função que calcula o quadrado de um número:

#include <stdio.h>

int quadrado(int x) {
  int y;
 
  y = x*x;
  return y;
}

int main() {
  printf("O quadrado de 2 é %f\n", quadrado(2));
  printf("O quadrado de 3 é %f\n", quadrado(3));
}

Este segundo exemplo é mais elaborado do que os anteriores, pois a função quadrado possui um dado de entrada (o parâmetro int x, também chamado de argumento da função), tem uma variável local (int y, que existe somente dentro da função) e devolve um valor do tipo int como resultado. A declaração da função revela esses detalhes:

Quadrado.png

Esses são os elementos básicos para declarar, escrever e usar funções.

Valor de retorno de função

Os próximos exemplos mostram outras situações em que se usam funções.

Função para testar se um número é par ou ímpar

#include <stdio.h>

int eh_par(int numero) {
  int resto;

  resto = numero % 2;
  if (resto == 0) return 1;
  else return 0;
}

int main() {
  int x;

  printf("Digite um numero: ");
  scanf("%d", &x);
  if (eh_par(x)) {
    printf("%d eh par\n", x);
  } else {
    printf("%d eh impar\n", x);
  }

}

O exemplo acima mostra se um número é par ou ímpar. A função int eh_par(int numero) retorna 1 se o valor contido em numero for par, e 0 caso contrário. Veja como essa função é chamada dentro da função main:

if (eh_par(x)) {

A função é usada diretamente como uma condição do if .. else (equivalente ao se .. então .. senão do Portugol). Isto é possível porque na linguagem C o valor 0 é equivalente ao valor booleano FALSO, e qualquer valor diferente de 0 é VERDADEIRO. Assim, ao retornar 0 ou 1, a função eh_par está tendo um resultado equivalente a FALSO ou VERDADEIRO. Tanto que o programa poderia ser escrito assim, tendo o mesmo resultado final:

int main() {
  int x;

  printf("Digite um numero: ");
  scanf("%d", &x);
  if (! eh_par(x)) {
    printf("%d eh impar\n", x);
  } else {
    printf("%d eh par\n", x);
  }

}

Lembre que o operador ! é equivalente a NÃO lógico (negação de uma condição). Então a condição ! eh_par(x) é verdadeira se x não for par.

Função para testar se um número é primo

Um exemplo semelhante ao anterior trata da verificação se um número é primo:

#include <stdio.h>

int primo(int n) {
  int x, ok;

  x = 2;
  ok = 1;
  while ((x <= (n/2)) && ok) {
    if ((n % x) == 0) {
      ok = 0;
    } else x++;
  }
  return ok;
}

int main() {
  int n;

  printf("Numero: ");
  scanf("%d", &n);
  if (primo(n)) {
    printf("%d eh primo\n", n);
  } else {
    printf("%d nao eh primo\n", n);
  }
}

A função int primo(int n) retorna 1 se o valor passado como parâmetro no argumento int nfor primo, e 0 caso contrário. Essa função possui um algoritmo mais elaborado que os exemplos anteriores, o qual utiliza uma estrutura de repetição com while (condição) (equivalente ao Enquanto condição do Portugol). Inclusive nessa função aparece um operador aritmético novo, usado para incrementar variáveis numéricas:

x++;

Isto é equivalente a:

x = x + 1;

De forma análoga, existe um operador parecido para decremento:

x--;

... equivalente a:

x = x - 1;

Função para fatorar um número

Esse exemplo para teste se números são primos pode ser aproveitado para criar um programa que fatore um número em seus divisores primos:

  1. include <stdio.h>

int primo(int n) {

 int x, ok;
 x = 2;
 ok = 1;
 while ((x <= (n/2)) && ok) {
   if ((n % x) == 0) {
     ok = 0;
   } else x++;
 }
 return ok;

}

int main() {

 int p, x;
 printf("Numero: ");
 scanf("%d", &x);
 p = 1;
 while (x != 1) {
   do {
     p ++;
   } while(!primo(p));
   while ((x % p) == 0) {
     x = x /p;
     printf("%d\n", p);
   }
 }

}

</syntaxhighlight>

A função int primo(int n) foi reaproveitada para escrever esse novo programa, que mostra todos os fatores primos que dividem um número.

Passagem de parâmetros

O próximo exemplo mostra uma função que torna maiúscula a primeira letra de uma string:

#include <stdio.h>

void faz_primeira_letra_maiuscula(char * nome) {
  if ((nome[0] >= 'a') && (nome[0] <= 'z')) {
    nome[0] = nome[0] - 32;
  }
}

int main() {
  char nome[32];

  printf("Digite um nome: ");
  scanf("%s", nome);
  faz_primeira_letra_maiuscula(nome);
  printf("Nome: %s\n", nome);
}

A função void faz_primeira_letra_maiuscula(char * nome) converte a primeira letra do parâmetro char * nome para maiúscula. A conversão se baseia na tabela ASCII, que associa códigos numéricos a caracteres. Mas a novidade nessa função é a possibilidade de modificar um valor passado como parâmetro, o que não acontecia nas funções vistas até então. Dependendo de como foi passado um parâmetro, modificações em seu valor dentro de uma função podem ou não refletir fora dessa função.

    • Passagem por valor: o valor da variável passada como parâmetro é copiado para uma variável local da função. Com isto, qualquer modificação feita na variável local da função não afeta a variável que foi passada como parâmetro. Ex:
      int incrementa_e_mostra(int x) {
        x = x + 1;
        printf("x=%d\n", x);
      }
      
      int main() {
        int contador = 0;
      
        incrementa_e_mostra(contador);
        incrementa_e_mostra(contador);
        incrementa_e_mostra(contador);
        printf("Ao final, contador=%d\n", contador);
      }
      
      Ao executar este programa exemplo, o resultado na tela deve ser o seguinte:
      x=1
      x=1
      x=1
      Ao final, contador=0
      ... o que evidencia que o valor de contador não foi modificado dentro da função incrementa_e_mostra.
    • Passagem por referência: a própria variável é passada como parâmetro (quer dizer, a sua localização em memória, por isto se diz por referência). Assim, qualquer modificação feita dentro da função chamada refletirá na variável que foi passada como parâmetro. Ex:
      int incrementa_e_mostra(int * x) {
        *x = *x + 1;
        printf("x=%d\n", *x);
      }
      
      int main() {
        int contador = 0;
      
        incrementa_e_mostra(&contador);
        incrementa_e_mostra(&contador);
        incrementa_e_mostra(&contador);
        printf("Ao final, contador=%d\n", contador);
      }
      
      Ao se executar o exemplo acima, o resultado na tela deve ser:
      x=1
      x=2
      x=3
      Ao final, contador=3
      Fica evidente que o valor da variável contador foi modificado dentro da função incrementa_e_mostra. Repare que algumas diferenças de sintaxe existem quando se usa passagem por referência:
      • A declaração do parâmetro na função deve ter um * (asterisco) antes do nome do parâmetro (ex: incrementa_e_mostra(int * x) )
      • Dentro da função deve-se preceder com * (asterisco) o nome da variável do parâmetro (ex: *x = *x + 1;)
        • Quando a variável passada como parâmetro for do tipo struct, ao invés de precedê-la por * (asterisco), deve-se usar a seguinte sintaxe: nome_variável->campo ao invés de nome_variável.campo. Veja a função adiciona_pessoa do cadastro como exemplo.
      • Na chamada da função, deve-se preceder com & o nome da variável passada como parâmetro (ex: incrementa_e_mostra(&contador); )
      • As duas últimas regras de sintaxe acima não valem quando se passa uma variável string como parâmetro. Isto porque uma variável string por definição já é uma variável que contém um endereço de memória (quer dizer, ela já funciona como uma referência aos dados). Na verdade, isto vale para qualquer variável do tipo vetor (lembre que a string é um vetor de char). Ex:
        void faz_primeira_letra_maiuscula(char * nome) {
          if ((nome[0] >= 97) && (nome[0] <= 122)) {
            nome[0] = nome[0] - 32;
          }
        }
        
        int main() {
          char nome[32];
        
          printf("Digite um nome: ");
          scanf("%s", nome);
          faz_primeira_letra_maiuscula(nome);
          printf("Nome: %s\n", nome);
        }
        
    • No caso do exemplo do cadastro: para ver a diferença entre passagem de parâmetro por referência e por valor no caso do cadastro, veja esta versão do cadastro em que a função adiciona_pessoa faz passagem por valor.
    • Veja no curso de linguagem C da UFMG uma discussão mais aprofundada sobre passagem de parâmetros e escopo de variáveis.

Reaproveitamento e especialização de funções

Uma função pode ser especializada para fazer uma tarefa mais limitada. Veja o exemplo da inicial maíuscula:

#include <stdio.h>

void faz_letra_maiuscula(char * nome, int pos) {
  if ((nome[pos] >= 97) && (nome[pos] <= 122)) {
    nome[pos] = nome[pos] - 32;
  }
}

void faz_primeira_letra_maiuscula(char * nome) {
  faz_letra_maiuscula(nome, 0);
}

int main() {
  char nome[32];

  printf("Digite um nome: ");
  scanf("%s", nome);
  faz_primeira_letra_maiuscula(nome);
  printf("Nome: %s\n", nome);
}

Apesar de o resultado ser exatamente o mesmo do exemplo anterior, em que havia somente a função faz_primeira_letra_maiuscula, esse novo exemplo mostra como especializar uma função mais geral. A função void faz_letra_maiuscula(char * nome, int posicao) torna maiúscula a letra contida na posição pos da string 'nome. Quer dizer, faz_letra_maiuscula é capaz de tornar maiúscula qualquer letra da string contida em nome. A função void faz_primeira_letra_maiuscula(char * nome) torna maiúscula a letra inicial da string contida em nome, e para fazer isto agora foi usada a função faz_letra_maiuscula, indicando-se que se quer mudar a letra na posição 0.

Funções que usam tipos de dados definidos pelo usuário (ou struct)