Resumo da Aula 7

Sumário

Ciclos

1.1  Estrutura típica de um ciclo

inic
while(G) {
    acção
    prog
}

Onde:

1.2  Equivalências entre ciclos

inic
while(G) {
    acção
    prog
}
é equivalente a for(inic; G; prog)
    acção
inic
while(G)
    passo
é equivalente a for(inic; G;)
    passo
inic
while(G)
    passo
é equivalente a // Má ideia...
inic
if(G)
    do
        passo
    while(G);
do
    passo
while(G);
é equivalente a passo
while(G)
    passo

Válidas em geral, estas equivalências não são verdadeiras se as instruções controladas incluírem as instruções return, break, continue, ou goto.  Também há diferença quanto ao âmbito de variáveis definidas nestas instruções.

1.3  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 só ocasionalmente é verdadeiramente útil.

Prova de correcção de um ciclo

Admitindo a estrutura típica de um ciclo:

inic
while(G) {
    acção
    prog
}

2.1  Definições

2.2  Estrutura de um ciclo com asserções

// PC: admite-se ser verdadeira neste ponto.

inic // inicialização do ciclo.

// CI: deve ser verdadeira neste ponto.

while(G) {
    // CI e G são verdadeiras neste ponto, por construção.

    passo // acção seguida de prog.
    // devem implicar que CI seja verdadeira neste ponto.
}

// CI e ¬G são verdadeiras neste ponto, por construção e
// devem implicar que CO seja verdadeira neste ponto.

2.3  Demonstrar a correcção de um ciclo

  1. Provar que, dada a PC, após a inicialização inic a CI é verdadeira;
  2. provar que se CI é verdadeira no antes do passo também o é após o passo;
  3. provar que CI e ¬G implica CO; e
  4. provar que o ciclo termina.

2.4  Demonstração de asserções

É comum haver necessidade de demonstrar que

// PC
instrução
//
CO

Ou seja, que, sabendo que a pré-condição PC se verifica, então depois da instrução instrução também se verifica a condição objectivo CO.

Por exemplo:

// PC: 10 <= x.
x = x + 1;
//
CO: 0 <= x.

2.4.1  Demonstração directa

A demonstração é feita partindo da pré-condição:

// PC: 10 <= x.
x = x + 1;
//
Logo, depois de aumentar x de uma unidade: 11 <= x.

// CO: 0 <= x.

e verificando que a asserção deduzida implica a condição objectivo CO:

// PC: 10 <= x.
x = x + 1;
//
11 <= x implica 
// CO: 0 <= x.

2.4.1  Demonstração inversa

A demonstração é feita partindo da condição objectivo, deduzindo a pré-condição mais fraca da instrução que conduz à veracidade da condição objectivo CO:

// PC: 10 <= x.

// Pré-condição mais fraca: 0 <= x + 1, ou seja, -1 <= x.
x = x + 1;

//
CO: 0 <= x.

e verificando que a pré-condição PC implica a pré-condição mais fraca deduzida:

// PC: 10 <= x implica
// -1 <= x.
x = x + 1;

//
CO: 0 <= x.

Exemplo de utilização de um ciclo

// Programa que "adivinha" a sua idade:
#include <iostream>

using namespace std;

int main()
{
    int maxima = 150;
    int minima = 0;

    while(minima <= maxima) {
        int idade = (minima + maxima) / 2;
        cout << "Você tem " << idade << " anos? ";
        char resposta;
        cin >> resposta;
        if(resposta == 's' or resposta == 'S') {
            cout << "Acertei!" << endl;
            return 0;
        } else {
            cout << "É mais nova(o)? ";
            cin >> resposta;
            if(resposta == 's' or resposta == 'S')
                maxima = idade - 1;
            else
                minima = idade + 1;
        }
    }
    cout << "Você enganou-me! Alguma idade há-de ter..."
         << endl;
}