Mudanças entre as edições de "SOP-funcoes"
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 ''!'' é | + | 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:
- 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.
- 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:
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:
- 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:Ao executar este programa exemplo, o resultado na tela deve ser o seguinte:
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); }
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:Ao se executar o exemplo acima, o resultado na tela deve ser:
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); }
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.
- 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:
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.