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;
cin >> n1 >> d1 >> n2 >> d2;
reduzFracção(n1, d1);
reduzFracção(n2, d2);
Traçado
main()
n1 : int
?
d1 : int
?
Traçado
main()
reduzFracção()
n : int
n1 : int
6
6
d : int
d1 : int
9
9
k : int {frozen}
3
Traçado
main()
reduzFracção()
n : int
n1 : int
2
6
d : int
d1 : int
9
9
k : int {frozen}
3
Traçado
main()
reduzFracção()
n : int
n1 : int
2
6
d : int
d1 : int
9
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;
cin >> n1 >> d1 >> n2 >> d2;
reduzFracção(n1, d1);
reduzFracção(n2, d2);
Traçado
main()
n1 : int
?
d1 : int
?
Traçado
main()
reduzFracção()
n : int&
n1 : int
6
d : int&
d1 : int
9
k : int {frozen}
3
Traçado
main()
reduzFracção()
n : int&
n1 : int
2
d : int&
d1 : int
9
k : int {frozen}
3
Traçado
main()
reduzFracção()
n : int&
n1 : int
2
d : int&
d1 : int
3
k : int {frozen}
3
Traçado
main()
reduzFracção()
n : int&
n1 : int
2
d : int&
d1 : int
3
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



Instâncias globais



Definidas dentro de rotinas
Pertencem ao contexto do bloco de instruções
onde foram definidas
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


Instância global


Zona de programa na qual o nome da instância
é visível
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ções
Âmbito e permanência (II)

Permanência


Instâncias globais


Do princípio ao fim do programa: estáticas
Instâncias locais


Período de tempo durante o qual a instância existe
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;
cin >> n1 >> d1 >> n2 >> d2;
reduzFracção(n1, d1);
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
m : int {frozen}
6
6
d1 : int
n : int {frozen}
9
9
k : int
r : int
?
?
Construção e destruição
main()
mdc()
n1 : int
m : int {frozen}
6
6
d1 : int
n : int {frozen}
9
9
k : int
r : int
?
6
Construção e destruição
main()
mdc()
n1 : int
m : int {frozen}
6
6
d1 : int
n : int {frozen}
9
9
k : int
r : int
?
5
Construção e destruição
main()
mdc()
n1 : int
m : int {frozen}
6
6
d1 : int
n : int {frozen}
9
9
k : int
r : int
?
4
Construção e destruição
main()
mdc()
n1 : int
m : int {frozen}
6
6
d1 : int
n : int {frozen}
9
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


Instâncias booleanas


Acção (verbo) no imperativo e complementos
Funções


Afirmação que pode ser verdadeira ou falsa
Procedimentos


Substantivo ou frase substantiva: aquilo que é guardado
Substantivo ou frase substantiva: aquilo que é devolvido
Funções booleanas ou predicados

Afirmação que pode ser verdadeira ou falsa
Nomes

Instâncias


Instâncias booleanas


Este procedimento …
Funções


Esta instância indica se …
Procedimentos


Esta instância guarda …
Esta função devolve …
Funções booleanas ou predicados

Esta função devolve um valor que indica se …
Grafismo

Instâncias


Separar palavras com _
Rotinas


Nã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


Normal


até 10 linhas
Em casos extremos


1 a 3 linhas
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.
Download

Aula teórica - iscte-iul