Resumo da Aula 3

Sumário

Rotinas

Funções

Procedimentos

Declaração (só cabeçalho)
tipo_devolução nome(lista_de_parâmetros);

Exemplo:

int soma(int x, int y);

void nome(lista_de_parâmetros);

Exemplo:

void imprime(int a, char b);

Definição (cabeçalho e corpo)
tipo_devolução nome(lista_de_parâmetros)
{
    ... // instruções.
    return expressão;
}

Exemplo:

int soma(int x, int y)
{
   return x + y;
}

void nome(lista_de_parâmetros)
{
    ... // instruções.
}

Exemplo:

void imprime(int a, char b)
{
    cout << a << b << endl;
}

Invocação ou chamada
variável = nome(lista_de_argumentos);

Exemplo:

int x = 3;
int s = soma(2, x);

nome(lista_de_argumentos);

Exemplo:

int x = 3;
char b = '$';
imprime(x, b);

Parâmetros são as variáveis locais à rotina declaradas entre () no seu cabeçalho.

Argumentos são as expressões colocadas entre () na invocação de uma rotina e servem para inicializar os parâmetros.

As rotinas são um mecanismo importante na programação.  Permitem (entre outras coisas):

Importante:  Uma rotina tem de ser declarada e/ou definida antes de ser invocada.

Contratos e asserções

As rotinas possuem um contrato: comprometem-se a produzir um determinado resultado se os seus parâmetros verificarem uma dada condição.  Para exprimir o resultado pretendido usa-se a chamada condição objectivo.  Para exprimir o que se assume à partida acerca dos parâmetros usa-se a chamada pré-condição.  Ao conjunto de ambas chama-se o contrato da rotina, uma vez que estabelecem um contrato entre o produtor e o consumidor da rotina.  Todas as rotinas devem possuir um comentário de documentação com o seguinte aspecto (onde @pre significa "pré-condição" e @post significa "pós-condição" ou "condição objectivo"):

/** Esta função devolve o máximo divisor comum dos inteiros 
    positivos passados como argumento.
    @pre 0 < m e 0 < n.
    @post mdc = mdc(m, n), ou seja,
          o valor x devolvido é o máximo divisor comum de m e n. */
int mdc(int const m, int const n)
{
    int x;

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

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

    return x;
}

Por outro lado, deve-se sempre que possível explicitar o contrato das rotinas no próprio código C++ através da utilização de instruções de asserção:

// Esta linha tem de estar no topo do ficheiro:
#include <cassert>

...

using namespace std;

...

/** Esta função devolve o máximo divisor comum dos inteiros 
    positivos passados como argumento.
    @pre 0 < m e 0 < n.
    @post mdc = mdc(m, n), ou seja,
          o valor x devolvido é o máximo divisor comum de m e n. */
int mdc(int const m, int const n)
{
    assert(0 < m and 0 < n);

    int mdc;

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

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

    // Neste caso é difícil fazer melhor para verificar a condição objectivo:
    assert(0 < mdc and m % mdc == 0 and n % mdc == 0);

    return mdc;
}

A instrução de iteração do while

É possível escrever ciclos utilizando a instrução de iteração do while:

3.1  Sintaxe

Instrução while:

do
    instrução
while(expressão_booleana);

ou

do {
    instruções
} while(expressão_booleana);

Importante:  O ciclo do while executa pelo menos uma vez a instrução controlada, pois a condição só é verificada depois de executada a instrução controlada.

Importante:  É sempre possível converter um ciclo de modo a usar qualquer das instruções de iteração.  No entanto, a maior parte dos problemas resolvem-se de um modo mais óbvio e mais legível com uma destas instruções do que com as outras.

3.2  Exemplo

Exemplo de um ciclo para mostrar no ecrã os inteiros de 0 a 9 (inclusive) construído usando cada uma das três instruções.

while:

int i = 0;
while(i != 10) {
    cout << i << endl;
    ++i;
}
// Neste ponto i é visível.

for:

for(int i = 0; i != 10; ++i)
   cout << i << ' ';
// Neste ponto i não está definida.

ou

int i = 0;
for(; i != 10; ++i)
   cout << i << ' ';
// Neste ponto i é visível.

do while (má ideia!):

int i = 0;
do {
    cout << i << ' ';
    ++i;
} while(i != 11);

A instrução do while raramente é útil.