Anda di halaman 1dari 14

Programar em C/Funes

Programar em C/Funes
Este mdulo precisa ser revisado por algum que conhea o assunto (discuta).

Bsico
O que funo
Uma funo um pedao de cdigo que faz alguma tarefa especfica e pode ser chamado de qualquer parte do programa quantas vezes desejarmos. Utilizamos funes para obter: Clareza do cdigo: separando pedaos de cdigo da funo main(), podemos entender mais facilmente o que cada parte do cdigo faz. Alm disso, para procurarmos por uma certa ao feita pelo programa, basta buscar a funo correspondente. Isso torna muito mais fcil o ato de procurar por erros. Reutilizao: muitas vezes queremos executar uma certa tarefa vrias vezes ao longo do programa. Repetir todo o cdigo para essa operao muito trabalhoso, e torna mais difcil a manuteno do cdigo: se acharmos um erro nesse cdigo, teremos que corrig-lo em todas as repeties do cdigo. Chamar uma funo diversas vezes contorna esses dois problemas. Independncia: uma funo relativamente independente do cdigo que a chamou. Uma funo pode modificar variveis globais ou ponteiros, mas limitando-se aos dados fornecidos pela chamada de funo. A idia de uma funo est, naturalmente, permitir voc encapsular uma idia ou operao, dando um nome a ela, ento chamar que operao de vrias partes do resto de seu programa simplesmente usando o seu nome. Estando corretamente projetado e estruturado o programa, em uma situao ideal, dever ser possvel modificar as funes sem efeito no resto do programa.

Definindo uma funo


Uma funo pode necessitar de alguns dados para que possa realizar alguma ao baseada neles. Esses dados so chamados parmetros da funo. Alm disso, a funo pode retornar um certo valor, que chamado valor de retorno. Os parmetros (e seus tipos) devem ser especificados explicitamente, assim como o tipo do valor de retorno. A forma geral da definio de uma funo : [tipo de retorno da funo] [nome da funo] (1 parmetro, 2 parmetro, ) { //cdigo } Para o nome da funo e dos parmetros valem as mesmas regras que foram dadas para os nomes de variveis. No podemos usar o mesmo nome para funes diferentes em um programa. Todas as funes devem ser definidas antes da funo main, ou deve ser feito o prottipo da funo, que veremos mais adiante. O cdigo deve estar obrigatoriamente dentro das chaves e funciona como qualquer outro bloco.

Programar em C/Funes

Valor de retorno
Freqentemente, uma funo faz algum tipo de processamento ou clculo e precisa retornar o resultado desse procedimento. Em C, isso se chama valor de retorno e pode ser feito com a instruo return. Para poder retornar um valor, precisamos especificar seu tipo (char, int, float, double e variaes). Para efetivamente retornar um valor, usamos a instruo return seguida do valor de retorno, que pode ou no vir entre parnteses. Um exemplo bem simples de funo que retorna um valor inteiro: int tres() { return 3; }

// poderia tambm ser return (3);

O tipo de retorno, alm dos tipos normais de variveis (char, int, float, double e suas variaes), pode ser o tipo especial void, que na verdade significa que no h valor de retorno. Nota Muitos livros dizem que a funo main tem tipo de retorno void, o que no est correto. Segundo o padro da linguagem C, a funo main deve ter retorno do tipo int. Compiladores como o gcc daro mensagens de erro caso a funo main() no seja definida corretamente.

Parmetros
Como j foi dito, um parmetro um valor que fornecido funo quando ela chamada. comum tambm chamar os parmetros de argumentos, embora argumento esteja associado ao valor de um parmetro. Os parmetros de uma funo podem ser acessados da mesma maneira que variveis locais. Eles na verdade funcionam exatamente como variveis locais, e modificar um argumento no modifica o valor original no contexto da chamada de funo, pois, ao dar um argumento numa chamada de funo, ele copiado como uma varivel local da funo. A nica maneira de modificar o valor de um parmetro usar ponteiros, que sero introduzidos mais adiante. Para declarar a presena de parmetros, usamos uma lista de parmetros entre parnteses, com os parmetros separados por vrgulas. Cada declarao de parmetro feita de maneira semelhante declarao de variveis: a forma geral tipo nome. Por exemplo: int funcao (int a, int b) float funcao (float preco, int quantidade) double funcao (double angulo) Para especificar que a funo no usa nenhum parmetro, a lista de parmetros deve conter apenas a palavra-chave void. No entanto, ela freqentemente omitida nesses casos. Portanto, voc poderia escrever qualquer uma destas duas linhas: void funcao (void) void funcao () Note que os nomes dos parmetros so usados apenas na prpria funo (para distinguir os argumentos); eles no tm nenhuma relao com as variveis usadas para chamar a funo.

Programar em C/Funes

Chamadas de funes
Para executar uma funo, fazemos uma chamada de funo, que uma instruo composta pelo nome da funo, seguido pela lista de argumentos entre parnteses: nome_da_funo (arg1, arg2, ...); Os argumentos podem ser qualquer tipo de expresso: podem ser variveis, valores constantes, expresses matemticas ou at mesmo outras chamadas de funo. Lembre que voc deve sempre dar o mesmo nmero de argumentos que a funo pede. Alm disso, embora algumas converses de tipo sejam feitas automaticamente pelo compilador, voc deve atender aos tipos de argumentos. Note que o valor dos argumentos copiado para a funo, de maneira que as variveis originais ficam inalteradas mesmo que na funo tentemos alter-las. A isso chamamos passagem de argumentos por valor (ao contrrio de por referncia). Veremos como modificar as variveis originais na seo Ponteiros. A prpria chamada de funo tambm uma expresso cujo valor o valor de retorno da funo, bastando coloc-la no lado direito de um sinal de igual para guardar o valor numa varivel. Por exemplo, se a funo "quadrado" retorna o quadrado de um nmero inteiro, podemos fazer assim para calcular o quadrado de 11 na varivel x: int x = quadrado (11);

Dois exemplos
#include <stdio.h> int quadrado (int x) { return (x * x); } void saudacao (void) { printf ("Ol!\n"); } void despedida (void) { printf ("Fim do programa.\n"); } int main () { int numero, resultado; saudacao (); printf ("Digite um nmero inteiro: "); scanf ("%d", &numero); resultado = quadrado (numero); printf ("O quadrado de %d %d.\n", numero, resultado);

Programar em C/Funes despedida (); return 0; } Voc veria na tela, ao executar o programa: Ol! Digite um nmero inteiro: 42 O quadrado de 42 1764. Fim do programa. Repare que, ao chegar na chamada de uma funo, o programa passa o controle para essa funo e, aps seu trmino, devolve o controle para a instruo seguinte na funo original. Mais um exemplo, com uma funo de 3 argumentos: #include <stdio.h> /* Multiplica 3 numeros */ void mult (float a, float b, float c) { printf ("%f",a*b*c); } int main () { float x, y; x = 23.5; y = 12.9; mult (x, y, 3.87); return 0; }

Prottipo ou Declarao de funo


Quando um programa C est sendo compilado e uma chamada de funo encontrada, o compilador precisa saber o tipo de retorno e os parmetros da funo, para que ele possa manipul-los corretamente. O compilador s tem como saber isso se a funo j tiver sido definida. Portanto, se tentarmos chamar uma funo que est definida abaixo da linha onde estamos fazendo a chamada, ou mesmo em outro arquivo, o compilador dar uma mensagem de erro, pois no conseguiu reconhecer a funo. //Exemplo de erro de chamada de funo int main() { int a = 1; int b = 2; soma(a,b); // erro: a funo est definida abaixo desta linha! } void soma(int a, int b) { printf("%d", a+b);

Programar em C/Funes } Nesses casos, podemos declarar uma funo antes de defini-la. Isso facilita o trabalho de usar diversas funes: voc no precisar se importar com a ordem em que elas aparecem nos arquivos. A declarao de funo (tambm chamada de prottipo de funo) nada mais que a definio da funo sem o bloco de cdigo. Como uma instruo, ela deve ser seguida de um ponto-e-vrgula. Portanto, para declarar a funo: int quadrado (int x) { return (x * x); } escreveramos: int quadrado (int x); Numa declarao, tambm podemos omitir os nomes dos parmetros, j que estes so ignorados por quem chama a funo: int quadrado (int); Poderamos, por exemplo, reorganizar o incio do programa-exemplo dado um pouco acima, o que permitiria colocar as funes em qualquer ordem mesmo que houvesse interdependncia entre elas: #include <stdio.h> int quadrado (int x); void saudacao (void); void despedida (void); // seguem as funes do programa Note que a definio da funo no deve contradizer a declarao da mesma funo. Se isso ocorrer, uma mensagem de erro ser dada pelo compilador.

Variveis locais versus globais


Quando declaramos as variveis, ns podemos faz-lo Dentro de uma funo Fora de todas as funes inclusive a main(). As primeiras so as designadas como locais: s tm validade dentro do bloco no qual so declaradas. As ltimas so as globais, elas esto vigentes em qualquer uma das funes. Quando uma funo tem uma varivel local com o mesmo nome de uma varivel global a funo dar preferncia varivel local. Daqui conclui-se e bem que, podemos ter variveis com o mesmo nome, o que contradiz o que ns dissemos no capitulo das variveis. Ento reformulamos: apenas na situao em que temos 2 variveis locais que colocada a restrio de termos nomes diferentes caso contrrio no conseguiramos distinguir uma da outra. Exemplo: Ento aonde estvamos?? Sim ,aqui "largo" e "alto" sao variveis internas fazem parte de "minhaFuncion()". /*espanhol para incultos :)*/ <== Comentrios da funo void minhaFuncion()

Programar em C/Funes { double largo = 5; double alto = 6; } As variveis largo e alto no esto definidas aqui abaixo, isto quer dizer que elas nao tem nem um valor. E no podemos usar os valores definido dentro da "minhaFuncion", pois no h nenhuma instruo que defina que valor usar! Lembre-se: O computador no vai adivinhar qual valor usar. Deve-se definir cada instruo. void calcular() /*No houve definio de valor entre parenteses*/ { long surface = largo * alto; /*Error bip bip valor nao definido*/ return(surface); } Nesse exemplo abaixo, poderemos usar o valor das variveis externas dentro de todas as funoes : Exemplo:
#include <stdio.h> /*Variavel externa*/ long largo = 10; long alto { /*variavel interna*/ long somma = largo + alto ; } long calcular() { long surface = largo * alto; } int main(void) { long reslt = calcular(); printf("A surface e:%ld\n",reslt); return 0 ; } /*Aqui ele pode enxegar a varivel "externa" (global)*/ = 20; void minhaFuncion()

Curiosidade
Em C++ existe a palavra reservada "auto", que serve para dizer que uma varivel local. Mas intil pois as variveis declaradas dentro de um bloco j so consideradas locais.

Programar em C/Funes

Lista de argumentos
Na linguagem C tambm possvel funes como "printf" aonde o numero de argumentos podem variar. As reticncias ( ... ) indicam um numero varivel de argumentos ou argumentos com tipos varivel. Ex: void f_erro(int n, char *fmt, ...); Essa declaraao indica que se deve fornecer pelo menos dois argumentos, um do tipo int e um do tipo char mais pode se fornecer argumentos suplementares. Ou seja, "no h limites para sua criatividade"! Ex: f_erro( 3, "Erro: misso impossvel "); f_erro( valor, "%s %d\n", mensagem, errno); E necessrio ter pelo menos um argumento antes dos pontos.Veja um exemplo incorreto. void erreur(...); O arquivo de cabealho stdarg.h declara um tipo va_list e define trs macros para manipular uma lista de argumentos cuja quantidade e tipos so desconhecidos pela funo. va_start, va_arg et va_end (va como variable argument)

#include <stdio.h> #include <stdarg.h> void meu_printf(char *fmt, ...) { va_list pa; int n; char *s, c; float f; va_start(pa, fmt); while (*fmt != '\0') { if ( *fmt == '%' ) { /* (*++fmt) equivale a (*fmt = *fmt + 1 )*/ switch (*++fmt) { case '%' : putchar('%'); break; case 'c' : /* char*/ c = va_arg(pa, int); putchar(c); break; case 'd' : /* int */ n = va_arg(pa, int); printf("%d", n); break; case 'f' : /* float */ f = va_arg(pa, double); /* !!!!! */ printf("%f", f); break; case 's' : /* string */ s = va_arg(pa, char *);

Programar em C/Funes for ( ; *s != '\0'; s++ ) putchar( *s ); break; } /* end switch */ } else putchar( *fmt ); /*incrementa o ponteiro*/ fmt++; } va_end(pa); } main() { meu_printf("float = %f\n", (float) 1.2345); meu_printf("int = %d char = %c String = %s\n", 123, 'A', "C is beautiful !" ); return 0; }

Passagem de parmetros por valor e por referncia


O que ns temos feito quando chamamos uma funo a dita chamada por valor. Quer dizer, quando chamamos uma funo e passamos parmetros para a funo prottipo e depois para a funo definio, o valor dos argumentos passados so copiados para os parmetros da funo. Estes existem independentemente das variveis que foram passadas. Eles tomam apenas uma cpia do valor passado, e se esse valor for alterado o valor dos argumentos passados no so alterados. Ou seja, no so alterados os valores dos parmetros fora da funo. Este tipo de chamada de funo denominado chamada (ou passagem de parmetros) por valor. Dito de outra maneira. Passamos a varivel a, ela entra na definio da funo como copia de a e entra como varivel b. Se a varivel b for alterada no decorrer da funo, o valor de a no alterado. #include <stdio.h> float quadrado(float num); //prottipo da funo quadrado() int main () { float num, res; //declaro 2 variveis: num , res printf("Entre com um numero: "); scanf("%f", &num); //associo o valor inserido varivel num res = quadrado(num); //chamo a funo quadrado e passo o parmetro num printf("\n\nO numero original e: %f\n", num); printf("e seu quadrado vale: %f\n", res); getchar(); return 0; } float quadrado (float num) //descrio da funo quadrado {

Programar em C/Funes return num * num; //retorna num ao quadrado } Quando a funo main() executada, ela chega a meio e v uma chamada para a funo quadrado() e onde passado o parmetro "num". Ela j estava a espera, pois "viu" o prottipo. Ela ento vai executar a funo que est depois da funo do main(). E o que acontece que o "num", vai ficar com o dobro do valor. Esse valor do main() vai entrar novamente no main(). E associado varivel "res". Depois temos a impresso da varivel "num" e "res". Ora o que acontece que o valor do "num" fica igual ao valor antes de entrar na funo. Fazemos a mesma coisa agora com a varivel "a" e "b", e vemos que agora a funo a alterada. Resumindo, o valor varivel quando entra numa outra funo no alterado (na passagem por valor). Quando o valor do parmetro alterado denominamos chamada (ou passagem) por referncia. O C no faz chamadas por referncia. Mas podemos simular isto com outra arma do C que so os ponteiros, que sero melhor explicados mais adiante.

Os argumentos argc e argv


A funo main(), como dissemos antes, uma funo especial. Introduzimo-la como uma funo sem parmetros; no entanto, ela tambm pode receber parmetros formais. No entanto, o programador no pode escolher quais sero. Eles devem ser os seguintes: int main (int argc, char *argv[]) argc (argument count) um inteiro e possui o nmero de argumentos com os quais o programa foi chamado na linha de comando. Ele no mnimo 1, pois o nome do programa contado como sendo o primeiro argumento. argv (argument values) um ponteiro para uma matriz de strings (conceitos que sero abordados mais frente). Cada string desta matriz um dos parmetros da linha de comando. argv[0] sempre aponta para o nome do programa (que, como j foi dito, considerado o primeiro argumento). para saber quantos elementos temos em argv que temos argc. Como pode se imaginar, os nomes dos parmetros "argc" e "argv" podem ser mudados, mas por questo de padronizao no se costuma modific-los. S no vamos ilustrar aqui o uso de argc e argv pois ainda no foram apresentadas as matrizes.

Avanado
VOID
Como dissemos, uma funo retorna um valor. E pode receber parmetros. O void utilizado da seguinte forma: void funo(void) { //codigo } No exemplo acima, a palavra void define que: no vai receber parmetros; e no vai retornar qualquer valor. Ou melhor, void uma explicitao do programador que aquela funo no vai receber ou retornar nenhum valor. O valor da funo ignorado, mas a funo realmente retorna um valor, por isso para que o resultado no seja interpretado como um erro e bom declarar void.

Programar em C/Funes
IMPORTANTE No se pode utilizar void na funo principal main, apesar de existirem exemplos com void em algumas bibliografias. Infelizmente, alguns compiladores aceitam void main(). O main() especial e tem de retornar um int. Uma execuo bem sucedida do programa costuma retornar 0 (zero) e, em caso de erro, retorna 1 (um).

10

Recursividade
Uma funo pode chamar a si prpria. Uma funo assim chamada funo recursiva. H vrias operaes matemticas recursivas, das quais exemplos bem conhecidos so a seqncia de Fibonacci e o fatorial. Daremos o exemplo do clculo do fatorial de um nmero, definido como o produto de todos os nmeros naturais (no nulos) menores ou iguais a ele por exemplo, 5! (l-se "cinco fatorial") igual a . Ateno conveno . Uma maneira de definir o algoritmo de fatorial :

E a implementao correspondente seria esta: #include <stdio.h> int fatorial(int n) { if (n >= 2) return n * fatorial(n - 1); else return 1; } int main() { int n; printf("Digite um valor para n: "); scanf("%d", &n); printf("\nO fatorial de %d %d", n, fatorial(n)); return 0; }

Programar em C/Funes

11

Parmetros default (padro)


Aqui a funao "funDefa()" contida na funo "main()" contem um valor default "nfunDefa( k,30)". Isto indica ao compilador que na ausncia de argumento definido deve usar este valor. Parmetros default no fazem parte da linguagem "C" , mais sim da "linguagem C++" . Por exemplo: Na linha 16 aonde esta escrito a funo nfunDefa() , coloque nfunDefa(50,25). Concluso este e um exemplo intil na "linguagem C" .
#include <stdio.h> #include <stdlib.h> /*-----------------------------Cabealho--------------------------------*/ /*Definimos uma funao*/ void nfunDefa(int pr,int se) { printf("Meu Primeiro argumento:%d\n",pr ); printf("Meu Segundo argumento :%d\n",se ); } int main (void) { int k=20,n=30; /*Na linguagem "C" a chamada de uma funao *Deve conter a mesma quantidade de argumentos *Nao podemos colocar so k ou so n*/ nfunDefa( k,30); } /*chamada "normal"*/ que a funao que esta esperando

Na linguagem "C" os argumentos contido na funo que faz a chamada deve ser equivalente ao nmero de argumentos definidos em a funo que esta a esperar. Por exemplo:
funcion(int a,int b) ------> Dois parmetros funcion(30) funcion (25,58) ---------> incorreto ou correto so na linguagem C++ ---------> Dois parmetros Correto nas duas linguagens "C" e C++

Ento dentro da "funo main" na funo "funDefa()" no podemos definir s "n" ou s "k". A linguagem C++ por ser mais verstil nos permite.

Sobrecarga de funes
Em C++ duas funes podem ter o mesmo nome se: Tiverem um n diferente de parmetros e/ou Se os parmetros forem de tipos diferentes (ints floats,..) A funo no pode ser overloaded apenas com diferentes tipo de retorno de funo (ie, uma funo retornar ints e a outra retornar floats) ento os parmetros que interessam. #include <iostream> using namespace std; void ConvertFToC(double f, double &c); void ConvertFToC(float f, float &c); void ConvertFToC(int f, int &c); int main()

Programar em C/Funes { double df, dc; float ff, fc; int i_f,i_c; //if is a reserved word df = 75.0; ff = 75.0; i_f = 75; // The compiler resolves the correct // version of ConvertFToC based on // the arguments in each call cout << "Calling ""double"" version" << endl; ConvertFToC(df,dc); cout << df << " == " << dc << endl << endl; cout << "Calling ""float"" version" << endl; ConvertFToC(ff,fc); cout << ff << " == " << fc << endl << endl; cout << "Calling ""int"" version" << endl; ConvertFToC(i_f,i_c); cout << i_f << " == " << i_c << endl << endl; system ("pause"); } void ConvertFToC(double f, double &c) { cout << "In ""double"" version" << endl; c = (f - 32.0) * 5. / 9.; } void ConvertFToC(float f, float &c) { cout << "In ""float"" version" << endl; c = (f - 32.0) * 5. / 9.; } void ConvertFToC(int f, int &c) { cout << "In ""int"" version" << endl; c = (f - 32) * 5. / 9.; } O que que acontece se tivermos um n diferente de argumentos entre a chamada e a definio? A soluo aqui proposta quando no sabemos a quantidade de parmetros que a funo vai ser chamada ou mesmo a tipologia desses argumentos, o que se sugere fazer vrias definies para a funo e dar a todas elas o mesmos nome, que o compilador vai saber escolher a definio correcta atravs do n e tipologia de argumentos. Entretanto, por boa prtica, as funes no devem ser sobrecarregadas se fizerem operaes distintas.

12

Programar em C/Funes

13

inline
Uma funo inline, em vez de ser chamada, ser movida para o local de chamada no momento da compilao. Se fizermos um paralelismo com as directivas de compilao, como #define, ela vai substituir cada chamada da funo pela prpria funo, como fosse uma macro. Mas isto s tem vantagens para, primeiro para cdigos pequenos, e para quem necessite muito da velocidade no processamento. Alguns compiladores j fazem isto automaticamente. Para tornar uma funo inline basta preceder a declarao da funo com o nome inline. inline [tipo_de_retorno] [nome_da_funo] (argumentos) { //cdigo }

Fontes e Editores da Pgina

14

Fontes e Editores da Pgina


Programar em C/Funes Fonte: http://pt.wikibooks.org/w/index.php?oldid=237456 Contribuidores: Albmont, Awillian, Edudobay, EvertonS, Hycesar, Rogerboff, Victor Aurlio, Wbrito, 25 edies annimas

Fontes, Licenas e Editores da Imagem


Imagem:Searchtool.svg Fonte: http://pt.wikibooks.org/w/index.php?title=Ficheiro:Searchtool.svg Licena: GNU Lesser General Public License Contribuidores: David Vignoni, Ysangkok

Licena
Creative Commons Attribution-Share Alike 3.0 Unported //creativecommons.org/licenses/by-sa/3.0/