Ameliara Freire [email protected] Dividir para Conquistar Situação Problema Parte 1 Parte 2 Parte 3 Parte 4 Solução Problema Parte 1 Parte 2 Parte 2 Parte 3 Parte 4 Parte 4 Parte 3 Solução Programa Subprograma Parte 1 1 Subprograma 2 Parte 2 Parte 3 Parte 4 Subprograma 4 Subprograma 3 A solução do problema original é implementada através da composição dos subprogramas. Subprogramas podem ser vistos como blocos de construção com os quais montamos um programa. Esta técnica de construção de programas é chamada de MODULARIZAÇÃO. Um bloco consiste em um conjunto de declarações e um conjunto de comandos delimitados por indicadores de início e fim de bloco. Em C, os delimitadores de bloco são { e }. Declarações de variáveis Comandos Um subprograma é um bloco de programa constituído por um conjunto de declarações e por um conjunto de comandos e identificado por um nome. Exemplo: Declarações de variáveis Comandos Existem dois tipos de subprograma: ◦ Procedimentos Executam tarefas ◦ Funções Calculam Valores Funções e Procedimentos ◦ Toda função ou procedimento deve ser pelo menos declarada antes da função principal main(). Declara a função/procedimento antes da main() e a implementa depois. Implementa a função/procedimento diretamente antes da main(). Funções e Procedimentos ◦ Exemplo: Procedimento que não recebe parâmetros e não retorna valor. Implementacao do procedimento #include <stdio.h> void desenha(); Assinatura ou protótipo do procedimento main() { printf(”Usando procedimento."); desenha( ); } void desenha() { int i; for (i = 0; i <= 10; i++) printf("--\n"); } Sintaxe: void nome_procedimento(lista_parâmetros) { declarações_de_variáveis_do_procedimento; lista_de_comandos_do_procedimento; } Exemplo: ◦ Exibir na tela uma linha com 20 asteriscos. void linha(){ int i; for (i = 1; i <= 20; i++) printf(‘*’); printf(‘\n’); } A definição de um procedimento associa um nome a um bloco de declarações e comandos. Os comandos que compõem o bloco do procedimento têm a “missão” de executar uma determinada tarefa para o programa. Exemplo de chamada a um procedimento void main(){ int i; linha(); /* escreve uma linha de asteriscos */ puts(“Numeros entre 1 e 5”); linha(); /* escreve outra linha de asteriscos */ } for(i = 1; i <= 5; i++) printf(“%d\n”, i); linha(); /* escreve outra linha de asteriscos */ Chamada (Execução) de um Procedimento ◦ Uma referência a um nome de procedimento dentro de um programa provoca a execução do bloco de comandos do procedimento. ◦ Ao término da execução do procedimento, a execução do programa continua a partir do ponto onde este foi chamado. Chamada (Execução) de um Procedimento void main(){ int i; linha(); puts(“Numeros entre 1 e 5”); linha(); } for(i = 1; i <= 5; i++) printf(“%d\n”, i); linha(); void linha(){ int i; for (i = 1; i <= 20; i++ printf(‘*’); printf(‘\n’); } #include <stdio.h> #include <conio.h> void linha(){ int i; for (i = 1; i <= 20; i++) printf("*"); printf("\n"); } main() { int i; linha(); puts("Numeros entre 1 e 5"); linha(); for(i = 1; i <= 5; i++) printf("%d\n", i); linha(); getche(); } Sintaxe: Exemplo: tipo_retorno nome_função (lista_parâmetros) { declarações_de_variáveis_da_função; lista_de_comandos_da_função; } ◦ Calcular o valor da soma de dois números reais. float soma(float a, float b) { float aux; aux = a + b; return aux; } Chamada a uma função float soma(float a, float b) { float aux; aux = a + b; return aux; } void main () { float x,y,z; printf(“Digite X:”); scanf (“%f”, &x); printf(“Digite Y:”); scanf (“%f”, &y); z = soma(x,y); printf(“Soma: %f”,z); } #include <stdio.h> #include <conio.h> float soma(float a, float b) { float aux; aux = a + b; return aux; } main () { float x,y,z; printf("Digite X:"); scanf ("%f", &x); printf("Digite Y:"); scanf ("%f", &y); z = soma(x,y); printf("Soma: %f",z); getche(); } Definição: ◦ A definição de uma função associa um nome a um bloco de declarações e comandos. ◦ Os comandos que compõem o bloco da função têm a “missão” de calcular um valor que deve ser retornado pela função. Chamada (execução) de Função: ◦ Uma referência a um nome de função dentro de um programa provoca a execução do bloco de comandos da função. ◦ Ao término da execução da função, a execução do programa continua a partir do ponto onde a função foi chamada. Definição de Escopo ◦ O escopo de uma variável é a parte do código do programa onde a variável é visível e, portanto, pode ser utilizada. ◦ Com relação ao escopo, as variáveis se dividem em: Globais Locais Variáveis Globais: ◦ São as variáveis declaradas fora dos procedimentos e das funções; ◦ São visíveis e podem ser utilizadas em toda a extensão do programa; Variáveis Locais: ◦ São as variáveis declaradas dentro dos procedimentos e das funções; ◦ São visíveis e podem ser utilizadas apenas dentro do subprograma que as declarou. Exemplo de Escopo em uma Função: Parâmetros são utilizados em computação para possibilitar a construção de subprogramas genéricos. Parâmetros Formais ◦ Parâmetros formais são as variáveis declaradas no cabeçalho do subprograma. Parâmetros Reais ◦ Parâmetros reais são as variáveis passadas no instante da chamada do subprograma. Exemplo: Parâmetros Formais Parâmetros Reais 1. Desenvolva uma função que recebe as três notas do aluno como parâmetro e retorne a sua média. 2. Desenvolva uma função que recebe dois números inteiros como parâmetro, e retorna o resto da divisão do primeiro parâmetro pelo segundo. 3. Desenvolva uma função que receba três números inteiros como parâmetros e retorne o menor valor. 4. Desenvolva uma função que recebe o ano de nascimento do usuário e retorna a sua idade. Faça o cálculo usando o ano atual. 5. Desenvolva uma função que recebe como parâmetro o mês atual e retorna quantos meses faltam para o final do ano. 6. Desenvolva uma função que recebe como parâmetros o dia do mês, o mês e o ano e retorna quantos dias faltam para o final do mês. Lembrem que os meses que têm 28, 29, 30 ou 31 dias. #include <stdio.h> #include <conio.h> float media(float nota1, float nota2, float nota3) { float aux; aux = (nota1 + nota2 + nota3)/3; return aux; } main () { float x,y,z, w; printf("Digite tres notas:"); scanf ("%f %f %f", &x, &y, &z); w = media(x,y,z); printf("Soma: %f",w); getch(); } int resto(int num1, int num2) { int aux; aux = num1 % num2; return aux; } main () { int x,y,w; printf("Digite dois numeros:"); scanf ("%d %d", &x, &y); w = resto(x,y); printf("resto da divisao: %d",w); getch(); } #include <stdio.h> #include <conio.h> int menor_valor(int a, int b, int c) { int aux; if((a == b) && (b == c) && (a == c)) aux = a-1; else { if ((a < b) && (a < c)) aux = a; else if ((b < a) && (b < c)) aux = b; else aux = c; } return aux; } main () { int x,y,z,w; printf("Digite tres numeros:"); scanf ("%d %d %d", &x, &y, &z); w = menor_valor(x,y,z); if(w == (x-1)) printf("\n os numeros sao iguais"); else printf("o menor numero eh: %d",w); getch(); } #include <stdio.h> #include <conio.h> int calcular_idade(int ano) { int aux; if (ano >= 2013 || ano < 1) aux = -1; else aux = 2013-ano; return aux; } main () { int x,y; printf("Digite o seu ano de nascimento:"); scanf ("%d", &x); y = calcular_idade(x); if(y == -1) printf("\n ano invalido"); else printf("a sua idade eh: %d",y); getch(); } #include <stdio.h> #include <conio.h> int meses_restantes(int mes) { int aux, mes_atual = 6; if (mes < mes_atual || mes > 12) aux = -1; else aux = 12-mes; return aux; } main () { int x,y; printf("Digite o mes do ano:"); scanf ("%d", &x); y = meses_restantes(x); if(y == -1) printf("\n mes invalido"); else printf("meses para o final do ano: %d",y); getch(); } #include <stdio.h> #include <conio.h> int dias_restantes_meses(int dia, int mes, int ano) { int aux; if (((mes == 1) || (mes == 3) || (mes == 5) || (mes == 7) || (mes == 8) || (mes == 9) || (mes == 10) || (mes == 12)) && (dia > 0) && (dia <= 31)) aux = 31 - dia; else if (((mes == 4) || (mes == 6) || (mes == 9) || (mes == 11)) && (dia > 0) && (dia <= 30)) aux = 30 - dia; else if ((mes == 2) && (dia > 0) && (dia <= 29)) { if ((ano % 4) == 0) aux = 29 - dia; else aux = 28 - dia; } else aux = -1; return aux; } main () { int x,y,z,w; printf("Digite o dia o mes e o ano:"); scanf ("%d/%d/%d", &x,&y,&z); w = dias_restantes_meses(x,y,z); if(w == -1) printf("\n data invalida"); else printf("dia para o final do mes: %d",w); getch(); } No instante da chamada do subprograma, o parâmetro formal recebe uma cópia do valor do parâmetro real correspondente. Alterações feitas nos parâmetros formais não refletem nos parâmetros reais correspondentes. Caracteriza-se por ser um mecanismo de entrada de dados para o subprograma. Exemplo: Organizacao da memória (variável inteira) int x; (0xFF02)x 0000000 Organizacao da memória (variável inteira) int x; x = 5; (0xFF02)x 5 Ponteiros (ou apontadores) são variáveis que, ao invés de guardar um dado (valor), guardam um endereço de memória, associada a outra variável; Dessa forma, ponteiros fazem referência a uma outra variável; x 0x3287AB Exemplo: 0x3287AB Abstração: x 4 Sintaxe: ◦ Variáveis que são ponteiros são representadas da seguinte forma: tipo *nome_variavel; ◦ Exemplo: int *x; x NULL Sintaxe: ◦ Variáveis que são ponteiros são representadas da seguinte forma: tipo *nome_variavel; ◦ Exemplo: int *x; int y = 5; x (0xAD036)y NULL 5 Sintaxe: ◦ Variáveis que são ponteiros são representadas da seguinte forma: tipo *nome_variavel; ◦ Exemplo: int *x; int y = 5; x = &y; x (0xAD036)y 0xAD036 5 Toda declaração de ponteiros, inicia o ponteiro com o valor default NULL; int *x; (0x3847CD)x NULL É sempre bom testar se o ponteiro na é NULL antes de acessá-lo; if (x != NULL) { ... –} representa p ponteiro; o endereço armazenado no int *x; printf(“Endereco da variavel x: %d”,&x); printf(“Endereco guardado em x: %d”,x); Atribuição de ponteiros. ◦ Só podemos jogar dentro do ponteiro um endereço; int *x; int y = 35; x = &y; (0x3847CD)x (0x32496)y 0x32496 35 *p – representa o conteúdo final do ponteiro; int *x; printf(“Conteudo final de x: %d”,*p); *x = 28; printf(“Conteudo final de x: %d”,*p); O que acontece no seguinte programa? int y = 5; int *x; x = &y; printf("Valor armazenado na variavel y: %d\n", y); printf("Endereco de y: %d\n",&y); printf("Valor do conteudo do ponteiro x: %d\n",*x); printf("Valor do endereco armazenado no ponteiro x: %d\n", x); printf("Valor do endereco de x: %d\n",&x); printf("Alterando o valor armazenado na variavel x\n"); *x = *x + 1; printf("Novo valor do conteudo do ponteiro x: %d\n",*x); printf("Valor do endereco armazenado no ponteiro x: %d\n", x); printf("Valor via y: %d\n",y); Toda variável vetor é um ponteiro! Exemplo: ponteiro para vetor de caracteres. char vetor[6]={‘a’,‘e’,‘i’,‘o’,‘u’}; char *c; c = vetor; printf(“%s”,c);//Saida: aeiou printf(“%c”,c[0]);//Saida: a ◦ E se tivéssemos feito c = &vetor[2]? Qual o efeito do seguinte código? char vetor[5]={‘a’,‘e’,‘i’,‘o’,‘u’}; char *c; c = &vetor[2]; printf(“Caractere: %c”,*c); c = c + 1; printf(“Caractere: %c”,*c); Operações aritméticas também podem ser feitas com endereços! Expressões com ponteiros: ◦ Os ponteiros podem aparecer normalmente no lugar das variáveis. ◦ O operador * dos ponteiros tem maior precedência que as operações matemáticas: //y recebe a soma de 1 ao conteúdo de *px y = *px + 1; // y recebe o conteúdo do ponteiro (px + 1) y = *(px + 1); Caracteriza-se por ser um mecanismo de comunicação bidirecional com o subprograma, ou seja, é um mecanismo de entrada e saída de dados. Qualquer modificação feita em um parâmetro formal implica em alteração no parâmetro real correspondente. Na passagem por referência utiliza-se um tipo de dados especial chamado ponteiro, que representa o endereço da variável passada por parâmetro. Representado pelo * após o tipo da variável e antes do seu nome. Exemplo: