Baixe o app para aproveitar ainda mais
Prévia do material em texto
SI 200 – Algoritmos e Programac¸a˜o de Computadores II Prof. Cla´udio Alessandro de Carvalho Silva cacs@ft.unicamp.br Aula 02 Modularizac¸a˜o Conteu´do U¨bersicht Modularizac¸a˜o de Programas Modularizar: dividir em partes menores que compo˜em o todo original quando combinadas. Programas reais sa˜o muito maiores que os programas desenvolvidos no primeiro curso de programac¸a˜o: Gerenciamento. Reutilizac¸a˜o. Evitar repetic¸a˜o de co´digo. Modularizac¸a˜o em C: Func¸o˜es. Programas multi-arquivos. Bibliotecas. Exemplo // Criando e usando um funcao #include <stdio.h> int square( int y ); // prototipo de funcao int main() { int x; for (x = 1; x <= 10; x++ ){ printf("%d␣", square( x ) ); // chamada de funcao } puts( ""); return 0; // execucao correta! } // fim do programa principal int square( int y ) //y e’ copia do argumento { return y*y; // retorna o quadrado } // fim da funcao square Declarac¸a˜o de func¸a˜o tipo_de_retorno nome_da_funcao( lista_de_parametros ) { corpo_da_funcao } Lista de para^metros tipo1 nome1, tipo2 nome2, ..., tipoN nomeN Tipo da func¸a˜o e lista de para^metros Na˜o e´ obrigato´rio que a func¸a˜o retorne algum valor. Nesse caso, seu tipo de retorno e´ void. Na˜o e´ obrigato´rio ter uma lista de para^metros. Proto´tipos de func¸o˜es Se a func¸a˜o na˜o for definida antes do main, e´ necessa´rio passar informac¸o˜es suficientes para o funcionamento do compilador. Proto´tipo de func¸a˜o e´ a definic¸a˜o de uma func¸a˜o, declarando o tipo e o nu´mero de para^metros da mesma. Deve vir antes do main para o compilador fazer as verificac¸o˜es de tipo de retorno e tipo e quantidade de para^metros. Se o proto´tipo foi declarado, a func¸a˜o pode ser definida depois do main ou em outro arquivo. Exemplo // Criando e usando um funcao #include <stdio.h> int square( int y ); // prototipo de funcao int main() { int x; for (x = 1; x <= 10; x++ ){ printf("%d␣", square( x ) ); // chamada de funcao } puts( ""); return 0; // execucao correta! } // fim do programa principal int square( int y ) //y e’ copia do argumento { return y*y; // retorna o quadrado } // fim da funcao square Retorno de uma func¸a˜o Uma func¸a˜o retorna ao escopa que a chamou de duas maneiras 1 Retorno sem nenhum valor na chamada (func¸a˜o do tipo void): Execuc¸a˜o da u´ltima linha do corpo da func¸a˜o e encontra }. Comando return sem para^metros: return; 2 Retorno fornecendo valor de seu tipo de dado declarado na chamada: Comando return com para^metro: return valor; Observac¸o˜es As func¸o˜es void podem retornar valores atrave´s da lista de para^mentros. Existem func¸o˜es cujo propo´sito principal e´ retornar valores: sin(), sqrt(). Existem func¸o˜es cujo propo´sito princial na˜o e´ retornar valores, e os valores retornados sa˜o acesso´rios (sucesso/erro, dados adicionais, etc.): printf(), fwrite() O valor retornado pelo return pode ser desconsiderado no escopo que chama a func¸a˜o. Podem haver va´rios comandos return na mesma func¸a˜o, um para cada ramo de execuc¸a˜o. Convenc¸a˜o: se o programa retornar zero, significa que terminou normalmente. Exemplos de uso do return #include <stdio.h> int par(int); // Proto´tipo da func¸~ao int main() { int num; printf ("Entre␣com␣numero␣inteiro:␣"); scanf ("%d",&num); if (par(num) == 1) printf ("\nO␣numero␣e’␣par."); else printf ("\nO␣numero␣e’␣impar."); return 0; } int par(int a) { if (a%2 == 0) // Verifica se a e´ divisı´vel por dois return 1; // Um return por ramo de execucao else return 0; } Escopo // Escopo das varia´veis #include <stdio.h> int z; // variavel global int square( int y ); // prototipo de funcao int main() { int x; // variavel restrita ao main() for (x = 1; x <= 10; x++ ){ int a = square( x ); // variavel local ao bloco printf("%d␣", a ); } puts( ""); return 0; // execucao correta! } // fim do programa principal int square( int y ) // Identificador y e’ valido apenas na funcao { z = y*y; // VA´LIDO MAS *MUITO* RUIM!!!! return z; // retorna o quadrado } // fim da funcao square Tipo de Para^metros – Conceitual Para^metros de Entrada: valores estabelecidos apenas fora do mo´dulo. Para^metros de Sa´ıda: valores estabelecidos apenas dentro do mo´dulo. Para^metros de Entrada-Sa´ıda: valores estabelecidos fora mas que podem ser alterados dentro do mo´dulo. Modos de passar para^metros em C Por valor: os valores das varia´veis fornecidas como para^metros sa˜o copiados para o escopo da func¸a˜o. Por resultado: o valor retornado via return e´ copiado em varia´vel do escopo externo a` func¸a˜o.. Por refere^ncia: alterac¸o˜es feitas nos para^metros sa˜o feitas diretamente nas varia´veis reais. Exemplo: para^metro passado por valor // Criando e usando um funcao #include <stdio.h> int square( int y ); int main() { int x; for (x = 1; x <= 10; x++ ){ printf("%d␣=␣%d^2\n", square( x ), x ); // } puts( ""); return 0; } int square( int y ) //parametro passado por valor { y = y*y; // apenas para mostrar que altera apenas copia return y; } Exemplo: para^metro passado por refere^ncia #include <stdio.h> void troca( int*, int* ); int main() { int x, y; x = 20; y = 30; printf( "Antes␣da␣troca:␣x␣=␣%d,␣y␣=␣%d", x, y ); troca( &x, &y ); printf("Depois␣da␣troca:␣x␣=␣%d,␣y␣=␣%d", x, y); return 0; } void troca( int* a, int* b ) // parametros do tipo ponteiro passam // variaveis por referencia { int aux; aux = *a; // armazena o valor de a em aux *a = *b; // armazena o valor de b em a *b = aux; // armazena o valor de aux em b } Exemplo: vetor passado por refere^ncia #include <stdio.h> void StrCpy( char*, char*); //vetor e’ sempre passado por referencia int main() { char str1[100], str2[100], str3[100]; printf ("Entre␣com␣uma␣string:␣"); gets (str1); StrCpy(str2, str1); StrCpy(str3,"Voce␣digitou␣a␣string␣"); printf ("\n%s%s", str3, str2); } void StrCpy (char* destino, char* origem) { while (*origem != ’\0’) { *destino=*origem; origem++; destino++; } *destino=’\0’; } U¨bersicht Modularizac¸a˜o em Arquivos Conjuntos de func¸o˜es podem ser movidas para arquivos diferentes do arquivo contendo o main(). Assim sa˜o feitas as bibliotecas: Os proto´tipos sa˜o colocados em arquivos *.h (headers). As implementac¸o˜es em arquivos *.c. Praticamente todos os programas em C usam bibliotecas externas. As func¸o˜es padra˜o do C esta˜o na C Standard Library, biblioteca inclu´ıda como padra˜o pelo compilador se alguma func¸a˜o e´ chamada. Vide Deitel, cap. 5. Exemplo: compilac¸a˜o multi-arquivo $ gcc -c main.c $ gcc -c file1.c $ gcc -o prog main.o file1.o Conteu´do de Makefile simples prog: main.o file1.o gcc $(CFLAGS) -o prog main.o file1.o main.o: main.c file1.h gcc $(CFLAGS) -c main.c file1.o: file1.c file1.h gcc $(CFLAGS) -c file1.c clean: rm -f *.o prog Usando o Makefile $ make $ make clean $ make CFLAGS=-O2 $ make CFLAGS=-g Bibliotecas Conjuntos de arquivos *.c contendo func¸o˜es, ja´ compilados e “agrupados”, juntamente com os respectivos *.h em direto´rio dispon´ıvel compo˜em uma biblioteca. As bibliotecas podem ser criadas para ligac¸a˜o: Esta´tica Dina^mica Bibliotecas esta´ticas Equivalente a um .LIB do Windows. Colec¸a˜o de arquivos *.o armazenados como um u´nico arquivo. Criadas a partir do comando ar: $ ar cr libtest.a teste1.o teste2.o $ gcc -o app app.o -L. -ltest Bibliotecas dina^micas Equivalente a um .DLL do Windows. Compartilhadas. Na˜o e´ apenas uma colec¸a˜ode arquivos *.o armazenados como um u´nico arquivo. A compilac¸a˜o de cada arquivo deve ser diferente e a biblioteca e´ criada com o GCC: $ gcc -c -fPIC test1.c $ gcc -c -fPIC test2.c $ gcc -shared -fPIC -o libtest.so test1.o test2.o $ gcc -o app app.o -L. -ltest Usando LD LIBRARY PATH O executa´vel na˜o conte´m o caminho completo de uma biblioteca dina^mica. O default do sistema e´ procurar apenas em /lib e /usr/lib. Deve-se ajustar a varia´vel de ambiente LD LIBRARY PATH do arquivo /.bashrc: LD_LIBRARY_PATH=/usr/local/lib:/novo/dir export LD_LIBRARY_PATH U¨bersicht U¨bersicht Exerc´ıcio: separac¸a˜o de d´ıgitos Escreva mo´dulos que fac¸am o seguinte: 1 Calcule a parte inteira do quociente quando o inteiro a e´ dividido pelo inteiro b. 2 Calcule o resto inteiro quando o inteiro a e´ dividido pelo inteiro b. Use os mo´dulos desenvolvidos em 1) e 2) para escrever uma func¸a˜o que receba um nu´mero inteiro no intervalo [1, 32767] e o imprima como uma se´rie de d´ıgitos, com dois espac¸os entre cada d´ıgito. Por exemplo, o nu´mero 4562 seria impresso como 4 5 6 2 Exerc´ıcio: lanc¸amento de moeda Escreva um programa que simule o lanc¸amento de uma moeda. Paras cada lanc¸amento, o programa deve imprimir Cara ou Coroa. Fac¸a o programa lanc¸ar a moeda 100 vezes e conte o nu´mero de cada ocorre^ncia. Imprima o resultado. O programa deve conte ruma func¸a˜o lance que na˜o recebe nenum argumento e retorna 0 para coroa e 1 para cara. U¨bersicht Refere^ncias DEITEL, H. M., DEITEL, P. J., Como Programar em C. Rio de Janeiro: LTC, 1999. Cap. 5, 6. BAIOCO, G. B, Modularizac¸a˜o de Programas, Subprogramas em C, Parte 2 – Para^metros, Unicamp, 2014.
Compartilhar