Baixe o app para aproveitar ainda mais
Prévia do material em texto
AGRUPAMENTO DE ESCOLAS HENRIQUES NOGUEIRA CURSO PROFISSIONAL DE TÉCNICO DE GESTÃO E PROGRAMAÇÃO DE SISTEMAS INFORMÁTICOS 2020-2021 PROGRAMAÇÃO E SISTEMAS DE INFORMAÇÃO MÓDULO 3 – PROGRAMAÇÃO ESTRUTURADA Objetivos do módulo: Adquirir a noção de subprograma; Conhecer as regras de declaração de subprogramas; Conhecer as regras de execução de subprogramas; Utilizar corretamente parâmetros; Distinguir os diferentes tipos de subprogramas; Elaborar programas com recurso a subprogramas; Conhecer as regras para a criação de bibliotecas de subprogramas; Conhecer os mecanismos de utilização de bibliotecas de subprogramas; Conteúdos do módulo: Variáveis globais e locais; Passagem por Parâmetros (por valor e por referência); Estrutura do subprograma; Retorno de valores; Recursividade; Construção de Bibliotecas de funções; Versão C Estrutura de um programa Como já sabemos do módulo anterior um programa em C tem a seguinte estrutura: ( Exemplo-1 #include <stdio.h> int main(int argc,char *argv[]) { printf ( “Olá mundo \ n”); return 1; } ) ( Página 1 de 9 ) Resumindo: primeiro as instruções do pré-processador (#include e/ou #define) depois a main e dentro desta as instruções. Este método de programar é muito limitado e não pode ser aplicado no desenvolvimento de aplicações complexas, além disso não permite a reutilização do código, algo fundamental para permitir a colaboração na programação. Assim este módulo introduz a criação de funções/instruções criadas pelo programador. Uma função é um grupo de instruções que são executadas quando são chamadas num determinado ponto do programa. O formato é o seguinte: tipo_dados nome(valor,valor,…){ Instruções; } Em que: tipo_dados - refere-se ao tipo de dados devolvido pela função nome - é um identificador, é o nome atribuído à função valor - são valores passados, ou fornecidos à função, podem não existir instruções - são os comandos que são executados dentro da função ( Exempl o-2 #include < stdio.h > int soma( int n1,int n2) { int r; r=n1+n2; return r; } int main(int argc,char *argv[]) { int z; z= soma( 5,3); printf ( “ Soma %d\ n” ,z ); return 1; } A variável z guarda o valor devolvido pela função Quando a execução do programa chega a este ponto “salta” para dentro do código da função chamada. Esta linha termina a execução do código da função e devolve o valor da variável r n1 e n2 recebem os valores passados, neste exemplo 5 e 3. ) Estudando detalhadamente a execução do código podemos dizer que: 1. A execução começa na função main; 2. Depois de definir a variável z a execução chega à linha z=soma(5,3); 3. Nessa linha a execução na função main para à espera que a função soma faça o que tem a fazer; 4. Assim a função soma é chamada e as variáveis n1 e n2 são declaradas e inicializadas com 5 e 3 respetivamente. 5. Estas variáveis são também chamadas de parâmetros; 6. Dentro da função declaramos outra variável (int r); 7. Esta variável só pode ser utilizada dentro da função onde é declarada; 8. Depois é executada a soma e o resultado guardado na variável r; 9. Por fim termina a execução da função com a instrução return; 10. Mas como estamos dentro da função soma que, por sua vez, foi chamada a partir da função main o programa não termina, uma vez que a execução volta para o ponto onde tinha parado na função main; 11. Nessa linha guardamos o valor devolvido pela função na variável z, que é local à função main e por isso não pode ser utilizada dentro de outra função; 12. Por fim temos o printf e outro return; 13. Na função main o return termina o programa uma vez que terminada a função main não existe mais nenhuma função a executar e a execução volta ao sistema operativo. Muito importante: É preciso deixar bem claro ao que acontece sempre que uma função é chamada. Quando um programa é executado a primeira função a ser chamada é a main. No computador, sempre que uma função é chamada, ela é colocada no topo de uma pilha de funções a serem executadas, ou seja, a main está na base dessa pilha e sempre que se chama outra função essa é colocada sobre a main ou sobre a função que a chamou. Sempre que o computador encontra a função return para a execução dentro da função e retira da pilha essa função. O modo como o computador sabe para onde deve voltar processa-se de modo muito simples, antes de saltar para dentro da função a posição de memória de retorno é guardada numa área de memória denominada stack, também é nesta parte da memória em que são declaradas as variáveis que são declaradas dentro da função. ( Pilha de funções main ( ) )Situação 1: Execução dentro da função main ( Pilha de funções soma( ) main ( ) )Situação 2: Durante a execução na função main é chamada a função soma. Nesta situação, a única maneira de parar a execução do programa é terminando as duas funções, um programa só termina quando não existe nenhuma função a ser executada. Também não existe nenhuma maneira de terminar a função main sem antes terminar a função soma. Situação 3: ( Pilha de funções main ( ) )Durante a execução da função soma é executada a função return, sendo retirada da memória a função soma e voltando a execução para a linha onde esta tinha sido chamada. A memória que tinha sido utilizada com as variáveis desta função é libertada e a informação que estas tinham é perdida. Argumentos Como já vimos as funções podem receber valores, o modo como se processa é muito simples, quando definimos a função indicamos entre parêntesis o nome das variáveis locais que vão receber esses valores. Por exemplo: ( Exemplo-3a #include <stdio.h> #i nclude “psi_tools.h” void mostrar(int x,int y,char *texto) { goto_xy(x,y); printf(“%s”,texto); return; } int main(int argc,char *argv[]) { mostrar( 5,1,“Olá mundo”); return 1; } Chama a função e passa os valores entre parêntesis Os argumentos recebem os valores pela mesma ordem em que são passados: x ← 5 y ← 1 texto ← Olá mundo ) ( Exemplo-3b … void mostrar(int x,int y,char *texto) { … } int main(int argc,char *argv[]) { Int c,l ; c=5; l=1; mostrar( c,l,“Olá mundo”); return 1; } ) Nestes exemplos os argumentos são passados por valor, o que significa que os argumentos recebem os valores não ficando com nenhuma ligação aos dados ou variáveis que são utilizadas quando a função é chamada. Isto quer dizer que se as variáveis forem alteradas dentro das funções nada acontece às variáveis que tinham os dados originais que lhe foram passados. Comparando este exemplo com o anterior podemos verificar que quando uma função não devolve nenhum valor o tipo de dados da função é void e o return não tem nada a devolver. ( #include <stdio.h> int par(int x) { 2 x=x%2; 3 if(x==0) return 1; else return 0; } int main(int argc,char *argv[]) { int n=5; if (par(n)) 1 printf (“PAR \ n”); else printf ( “IMPAR \ n”); return 1; } Exemplo-4 Quanto a função par é chamada n tem o valor 5 Dentro da função par o argumento x recebe o valor 5 Apesar de x ser alterado não afeta a variável n que tinha o valor original, esta continua a ter 5 ) Passagem por referência Por vezes é necessário devolver mais do que um valor, ou pretendemos alterar um dos parâmetros utilizados, assim passamos os argumentos por referência. ( Exemplo-5 #include < stdio.h > void troca( int n1,int n2) { int t; t=n1; n1=n2; n2=t; return ; } int main(int argc,char *argv[]) { int x=2,y=5; troca(x,y); printf(“%d - %d”,x,y); return 1; } ) Se executarmos o exemplo anterior podemos verificar que as variáveis x e y mantêm o mesmo valor após a execução da função, isto porque utilizamos a passagem por valor. ( Exemplo-6 #include < stdio.h > void troca( int &n1,int &n2) { int t; t=n1; n1=n2; n2=t; return ; } int main(int argc,char *argv[]) { int x=2,y=5; troca(x,y); printf(“%d - %d”,x ,y); return 1; } Colocando um & antes de cada parâmetro este passa a receber o endereço da variável utilizada quando a função é chamada e assim qualquer alteração no valor do parâmetro vai afetar também a variável ) Assim com esta alteraçãoao alterar o valor de n1 e n2 dentro da função troca alteramos também os valores de x e y na função main. Outro método de definir e utilizar passagem por referência pode ser o do exemplo seguinte: ( Exemplo-7 #include < stdio.h > void troca( int *n1,int *n2) { int t; t=*n1; *n1=*n2; *n2=t; return ; } int main(int argc,char *argv[]) { int x=2,y=5; troca(&x,&y); printf(“%d - %d”,x,y); return 1; } Colocando um * antes de cada parâmetro definimos um ponteiro assim quando chamamos a função temos de passar um endereço para a variável com um &. De notar os * antes das variáveis dentro da função. ) É claro que para um parâmetro passado por referência não podemos utilizar uma constante. Variáveis globais e locais Olhando para o exemplo anterior podemos verificar que todas as variáveis estão definidas dentro de funções, umas na função main outras na função troca. A este tipo de variáveis dá-se o nome de variáveis locais, ou seja, são variáveis que só “existem” dentro da função onde é definida. Se na função main tentarmos alterar o valor da variável t, que foi declarada dentro da função troca, o compilador dá um erro a indicar que a variável não foi declarada. Também é muito importante lembrar que estas variáveis são destruídas quando a função termina, perdendo, assim, os dados que continham. Além de variáveis locais podemos ter variáveis globais, estas são declaradas fora das funções e podem ser utilizadas em qualquer parte do programa. A utilização de variáveis globais deve ser limitada ao mínimo necessário, pois são uma possível fonte de problemas difíceis de detetar. Variáveis static ( Exemplo-8 #include <stdio.h> #include <conio.h> void mostrar_contagem ( void ) { int t=0; t++; printf ( "Contagem em %d\ n",t ); return; } int main(int argc,char *argv[]) { int i; for(i= 0;i <5;i++) mostrar_contagem (); return 1; } Variável local por isso quando a função termina torna a ser redefinida. ) Este exemplo mostra sempre o valor 1 no ecrã. ( Exemplo-9 #include <stdio.h> #include <conio.h> void mostrar_contagem(void) { Static int t=0; t++; printf ( "Contagem em %d\ n",t ); return ; } Variável local mas uma variável static por isso só é definida uma vez, a primeira vez que a função é executada. Assim mantém o valor da útil execução. ) Com o modificador static definimos variáveis locais que só são definidas na primeira que a função é executada não perdendo os dados quando a função termina. Assim com esta alteração aparece 1,2,3,4,5. Protótipos de funções ( Exemplo-10 #include <stdio.h> #include <conio.h> void mostrar_menu ( void ) { printf ("1.Abrir\n2.Fechar\n3.Sair\n"); return; } int main(int argc,char *argv[]) { mostrar_ menu ( ); getch (); return 1; } Código da função aparece antes do código da main ) Até agora todas as funções que utilizamos são criadas antes da função main, isto devesse ao facto de que durante a compilação do programa o compilador tem de “conhecer” a função antes de esta ser chamada, daí que os include dos header files estão também no início do programa. Quando os programas começam a ser grandes é natural querer manter a main no local fácil de encontrar, assim podemos definir só a função antes da main e inserir o código da função depois, o modo como definimos as funções é através de protótipos das funções. ( Exemplo-11 #include <stdio.h> #include <conio.h> void mostrar_menu(void); int main(int argc,char *argv[]) { mostrar_ menu ( ); getch (); return 1; } void mostrar_menu ( void ) { printf ("1.Abrir\n2.Fechar\n3.Sair\n"); return ; } Código da função já pode estar depois da main permitindo um rápido acesso a esta. Protótipo da função, só o cabeçalho, permite ao compilador conhecer o valor de retorno e os parâmetros. ) Recursividade Em C, e na maior parte das linguagens de programação, as funções podem se chamar a si próprias. Assim uma função que utiliza a recursividade é uma função cujo seu próprio código invoca a função. ( Exemplo-12 )Um exemplo de recursividade para calcular uma potência. #include <stdio.h> #include <conio.h> int potencia(int base,int expoente) { int resultado; Recursi chama vidade – dentro da função potencia mos a função potencia if(expoente==1) return base; else resultado=base*potencia(base,expoente-1); return resultado; } int main(int argc,char *argv[]) { printf("2 elevado a 10 = %d",potencia(2,10)); return 1; } Header files Agora que sabemos como criar funções podemos juntar as funções em bibliotecas de funções que depois podemos reutilizar em diferentes programas. Para isso criamos um ficheiro com a extensão h que tem a mesma estrutura de um programa à exceção da main que não existe no header file. Os header files pode conter variáveis locais e globais bem como pode incluir outros header files.
Compartilhar