Aula 4 Modularização: funções e procedimentos (continuação)

Post on 17-Apr-2015

106 views 0 download

Transcript of Aula 4 Modularização: funções e procedimentos (continuação)

Aula 4

Modularização: funções e procedimentos (continuação)

Somador de fracções

#include <iostream> using namespace std;

/** … */int mdc(int const m, int const n){ ...}

/** … */void escreveFracção(int const n, int const d){ ...}

int main() { ...}

Máximo divisor comum

/** Devolve o máximo divisor comum dos inteiros positivos passados como argumento. @pre 0 < m e 0 < n. @post o valor r devolvido é o mdc de m e n. */ int mdc(int const m, int const n){ assert(0 < m); assert(0 < n);

int r;

if(m < n) r = m; else r = n;

while(m % r != 0 or n % r != 0) --r;

assert(0 < r); assert(m % r == 0); assert(n % r == 0);

return r;}

Escreve fracção

/** Escreve no ecrã uma fracção, no formato usual, que

lhe é passada na forma de dois argumentos inteiros positivos.

@pre nenhuma.

@post o ecrã contém n/d em que n e d são os valores de

n e d em base decimal. */void escreveFracção(int const n, int const d){ cout << n; if(d != 1) cout << ‘/’ << d;}

Principal: Ler fracções

// Ler fracções: cout << "Introduza duas fracções (numerador denominador): "; int n1, d1, n2, d2; cin >> n1 >> d1 >> n2 >> d2; int k = mdc(n1, d1); n1 /= k; d1 /= k; k = mdc(n2, d2); n2 /= k; d2 /= k;

Principal:Calcular fracção soma reduzida

// Calcular fracção soma reduzida:

int n = d2 * n1 + d1 * n2;int d = d1 * d2;k = mdc(n, d);n /= k;d /= k;

Principal: Escrever resultado

// Escrever resultado:

cout << "A soma de "; escreveFracção(n1, d1); cout << " com "; escreveFracção(n2, d2); cout << " é "; escreveFracção(n, d); cout << '.' << endl;

Redução de fracções

// Reduz fracção:

k = mdc(n, d);n /= k;d /= k;

Módulo reduzFracção()

/** Reduz a fracção recebida como argumento. @pre 0 < n e 0 < d. @post mdc(n, d) = 1 (e n/d representa o mesmo racional que originalmente). */ void reduzFracção(int n, int d) { assert(0 < n); assert(0 < d);

int const k = mdc(n, d); n /= k; d /= k;

assert(mdc(n, d) == 1);}

Principal:Calcular fracção soma reduzida

// Calcular fracção soma reduzida:

int n = d2 * n1 + d1 * n2;int d = d1 * d2;reduzFracção(n, d);

Principal: Ler fracções

// Ler fracções:cout << "Introduza duas fracções (numerador denominador): "; int n1, d1, n2, d2;cin >> n1 >> d1 >> n2 >> d2;reduzFracção(n1, d1);reduzFracção(n2, d2);

Principal: Ler fracções

// Ler fracções:cout << "Introduza duas fracções (numerador denominador): "; int n1, d1, n2, d2, n2, d2;cin >> n1 >> d1 >> n2 >> d2>> n2 >> d2;reduzFracção(n1, d1);reduzFracção(n2, d2);reduzFracção(n2, d2);

Traçado

main()

n1 : int

?

d1 : int

?

Traçado

main() reduzFracção()

n1 : int

6

d1 : int

9

n : int

6

d : int

9

k : int {frozen}

3

Traçado

main() reduzFracção()

n1 : int

6

d1 : int

9

n : int

2

d : int

9

k : int {frozen}

3

Traçado

main() reduzFracção()

n1 : int

6

d1 : int

9

n : int

2

d : int

3

k : int {frozen}

3

Traçado

main()

n1 : int

6

d1 : int

9

Passagem por referência

Parâmetros são sinónimos de argumentos Argumentos não podem ser literais Parâmetros referências servem de entradas e de

saídas

Módulo reduzFracção()

/** Reduz a fracção recebida como argumento. @pre 0 < n e 0 < d. @post mdc(n, d) = 1 (e n/d representa o mesmo racional que originalmente). */ void reduzFracção(int& n, int& d) { assert(0 < n); assert(0 < d);

int const k = mdc(n, d); n /= k; d /= k;

assert(mdc(n, d) == 1);}

Parâmetro é referência!

Principal: Ler fracções

// Ler fracções:cout << "Introduza duas fracções (numerador denominador): "; int n1, d1, n2, d2, n2, d2;cin >> n1 >> d1 >> n2 >> d2>> n2 >> d2;reduzFracção(n1, d1);reduzFracção(n2, d2);reduzFracção(n2, d2);

Traçado

main()

n1 : int

?

d1 : int

?

Traçado

main() reduzFracção()

n1 : int

6

d1 : int

9

n : int&

d : int&

k : int {frozen}

3

Traçado

main()

n1 : int

2

d1 : int

9

reduzFracção()

n : int&

d : int&

k : int {frozen}

3

Traçado

main()

n1 : int

2

d1 : int

3

reduzFracção()

n : int&

d : int&

k : int {frozen}

3

Traçado

main()

n1 : int

2

d1 : int

3

reduzFracção()

n : int&

d : int&

k : int {frozen}

3

Traçado

main()

n1 : int

2

d1 : int

3

Blocos de instruções

Âmbito e permanência

Bloco de instruções

Bloco de instruções (ou instrução composta): Conjunto de instruções agrupadas Funcionam como uma só instrução

{ // Instruções:

...

}

Exemplo

int const j = 1; int main() { // Bloco 1. int i = 2; if(0 < i) { // Bloco 2. int j = i; int const i = 3; cout << i << j << endl; } }

Tipos de instâncias (para já)

Instâncias locais Definidas dentro de rotinas Pertencem ao contexto do bloco de instruções

onde foram definidas Instâncias globais

Definidas fora das rotinas Pertencem ao contexto global

Dentro do mesmo contexto não podem ser definidas duas instâncias com o mesmo nome

Definições erradas

int const j = 1; int j = 11; // erro!int main() { int i = 2; int i = 22; // erro! if(0 < i) { int j = i; int const i = 3; int const i = 33; // erro! cout << i << ' ' << j << endl; } }

Âmbito e permanência (I)

Âmbito Zona de programa na qual o nome da instância

é visível

Instância global Visível desde definição até fim do ficheiro

Instância local Visível desde definição até fim do seu bloco,

incluindo blocos embutidos

Linhas de visibilidade

int const j = 1; int main() { // Bloco 1. int i = 2; if(0 < i) { // Bloco 2. int j = i; int const i = 3; cout << i << j << endl; } }

Ocultação

int const j = 1; int main() { // Bloco 1. int i = 2; if(0 < i) { // Bloco 2. int j = i; int const i = 3; cout << i << j << endl; } }

OcultaçõesOcultações

Âmbito e permanência (II)

Permanência Período de tempo durante o qual a instância existe

Instâncias globais Do princípio ao fim do programa: estáticas

Instâncias locais Desde a execução da definição até saída do bloco: automáticas

Diz-se que as instâncias são construídas e destruídas

Principal: Ler fracções

// Ler fracções:cout << "Introduza duas fracções (numerador denominador): "; int n1, d1, n2, d2, n2, d2;cin >> n1 >> d1 >> n2 >> d2>> n2 >> d2;reduzFracção(n1, d1);reduzFracção(n1, d1);reduzFracção(n2, d2);reduzFracção(n2, d2); int k = mdc(n1, d1);

Construção e destruição

main()

n1 : int

?

d1 : int

?

k : int

?

Construção e destruição

main() mdc()

n1 : int

6

d1 : int

9

m : int {frozen}

6

n : int {frozen}

9

k : int

?

r : int

?

Construção e destruição

main() mdc()

n1 : int

6

d1 : int

9

m : int {frozen}

6

n : int {frozen}

9

k : int

?

r : int

6

Construção e destruição

main() mdc()

n1 : int

6

d1 : int

9

m : int {frozen}

6

n : int {frozen}

9

k : int

?

r : int

5

Construção e destruição

main() mdc()

n1 : int

6

d1 : int

9

m : int {frozen}

6

n : int {frozen}

9

k : int

?

r : int

4

Construção e destruição

main() mdc()

n1 : int

6

d1 : int

9

m : int {frozen}

6

n : int {frozen}

9

k : int

?

r : int

3

Construção e destruição

main()

n1 : int

6

d1 : int

9

k : int

3

Variáveis globais

Vantagens Não há!!!!!

Desvantagens Rotinas sem significado evidente Alterar nomes das variáveis implica alterar todo

o programa Reaproveitamento de código mais difícil

Constantes globais

Muito úteis!

#include <iostream>

using namespace std;

double const π = 3.14159;

double perímetroDeCircunferênciaCom(double const raio){ return 2.0 * π * raio;}

int main(){ cout << "Insira o raio: "; double raio; cin >> raio;

cout << "Perímetro: “ << perímetroDeCircunferênciaCom(raio) << endl; cout << “Área: “ << π * raio * raio << endl;}

Constantes globais

Muito úteis!

#include <iostream>

using namespace std;

Double const pi = 3.14159;

double perímetroDeCircunferênciaCom(double const raio){ return 2.0 * pi * raio;}

int main(){ cout << "Insira o raio: "; double raio; cin >> raio;

cout << "Perímetro: “ << perímetroDeCircunferênciaCom(raio) << endl; cout << “Área: “ << pi * raio * raio << endl;}

Declarações

#include <iostream> using namespace std;

int main() {     void escreveFracção(int n, int d); void reduzFracção(int& n, int& d); ...}void escreveFracção(int const n, int const d){ ...}

void reduzFracção(int& n, int& d){    int mdc(int m, int n); ...}

int mdc(int const m, int const n){ ...}

Declaração

Definição

Nomes

Instâncias Substantivo ou frase substantiva: aquilo que é guardado

Instâncias booleanas Afirmação que pode ser verdadeira ou falsa

Procedimentos Acção (verbo) no imperativo e complementos

Funções Substantivo ou frase substantiva: aquilo que é devolvido

Funções booleanas ou predicados Afirmação que pode ser verdadeira ou falsa

Nomes

Instâncias Esta instância guarda …

Instâncias booleanas Esta instância indica se …

Procedimentos Este procedimento …

Funções Esta função devolve …

Funções booleanas ou predicados Esta função devolve um valor que indica se …

Grafismo

InstânciasSeparar palavras com _

RotinasNão separar palavras Iniciar palavras excepto primeira com

maiúsculas

Exemplos

int número_de_alunos = 20;

bool hoje_há_aulas = true;

void escreveFracção(int const numerador, int const denominador)

double quadradoDe(double const valor)

bool sãoIguais(char const a, char const b)

Tamanho das rotinas

Ideal 1 a 3 linhas

Normal até 10 linhas

Em casos extremos até 60 linhas

Nunca mais!

Aula 4: Sumário

Passagem de argumentos por valor e referência. Blocos de instruções. Blocos embutidos. Instâncias locais e globais: âmbito, permanência e

ocultação. Regra da definição única. Perigos das variáveis globais. Uso de constantes

globais. Parâmetros como instâncias locais. Declaração vs. definição. Noções sobre nomes de instâncias, funções e

procedimentos. Comprimento típico de rotinas.