Introdução à programação e aos algoritmos

João Araujo Ribeiro · Capítulo 49 de 103

Páginas do PDF

Introdução à programação e aos algoritmos

4.1 Fluxo de Execução

Da mesma forma que bibliotecas do mundo real guardam livros, bibliotecas de programas guardam trechos de código que resolvem problemas já encontrados antes. Você pode criar sua própria biblioteca de soluções!

Neste capítulo você aprenderá como dividir sua solução em subalgoritmos e como utilizar o conhecimento acumulado de soluções de pequenos e grandes problemas.

 

4.1 FLUXO DE EXECUÇÃO

Antes de falar dos subalgoritmos, vamos pensar um pouco sobre o fluxo de execução dos programas.

Como o seu programa executa? Até agora o programa sempre seguiu um fluxo: começa no início e percorre cada linha, executando uma única ação que a linguagem de programação sabe como fazer.

O programa pode repetir ações em laços, mas sempre é um bloco de execução. Uma vez terminado o laço, o fluxo de execução deve voltar à linha principal. Ao final, o conjunto dessas ações resolve o seu problema, ou deveria resolver!

O método dos refinamentos sucessivos, ou top-down (Seção 3.1), ensinou-o a dividir um problema em pequenas partes, cada uma mais simples que o problema original. Ao final desse processo, você pode ter que resolver diversas vezes o mesmo tipo de subproblema. O que fazer? Codificar cada vez que precisar dessa solução? Repetir o mesmo trecho, com um simples copiar-colar? Não seria nada prático. Podemos ter outra saída: encapsular essa solução em um subalgoritmo e usá-lo sempre que necessário. Como? Mudando o fluxo de execução do programa.

Antes vamos dar uma olhada em um programa simples. Vou repetir aqui o programa de fatorial 3.17 para facilitar, mas agora com as linhas numeradas.

1 n = int(input(‘Qual o número para calcular o fator ial? ‘))

2 fat = 1

3 for i in range(1,n+1):

4 fat = fat * i

5 print (‘O fatorial de’, n, ‘é’, fat

 

■ Programa 4.1: Retomando fatorial.py (Programa 3.17).

 

O fluxo de execução do programa segue as linhas 1, 2, (3, 4), 5.

As linhas 3 e 4 formam um laço, então estou considerando-as uma só entidade, ou seja, um bloco.

Mas será que foi esse mesmo o fluxo de execução deste

programa? Note que na linha 1 temos int e input que são o que chamamos de funções, na realidade subalgoritmos que quebram o fluxo de execução. A função input vai executar ações que leem do teclado. Para nosso estudo do momento, não importa como. Basta saber que em algum lugar da memória de seu computador existe uma função que sabe como ler do teclado, escrevendo uma mensagem na tela. Isso foi um desvio. Se fôssemos olhar em detalhes, veríamos que o fluxo não foi bem de 1 a 5. Foi muito mais complexo. Destrinchando o que aconteceu:

1. Um subalgoritmo chamado input escreveu na tela e leu o

que foi digitado no teclado, retornando uma resposta.

2. Outro subalgoritmo chamado int transformou esta resposta

em um número inteiro.

3. O valor retornado por int foi atribuído à variável n.

Tudo isso aconteceu apenas na linha 1. Podemos fazer o mesmo

raciocínio para a linha 3 e para a função range(1,n+1) que aparece. Sim, range() também é um subalgoritmo. E na linha 5 temos a função print() que recebe valores para escrever na tela do computador.

A Figura 4.1 mostra que o fluxo de execução se comporta como

um rio que sempre avança, mas que tem seus desvios de curso, seus redemoinhos, porém sempre voltando ao fluxo principal.

Figura 4.1 Fluxo de execução de um programa.

 

 

Você se lembra de que falei que programar era gerenciar entidades abstratas? A “entidade” abstrata do programa principal “chama” uma outra entidade que é o subalgoritmo. O subalgoritmo, “executa”, ou seja, faz aquilo para o qual foi criado e então “retorna” ao fluxo principal. Perceba que este retorno pode também trazer informações para a linha do fluxo principal.

Esses subalgoritmos são chamados de funções ou procedimentos. As funções deste exemplo foram input(), int(), range() e print(). Cada uma tem um propósito específico dentro do programa:

input() vai ler alguma informação do teclado;

int() vai converter o que recebe para um número inteiro;

range() vai gerar uma sequência de números; e finalmente

print() vai escrever algo na tela.

Note que as funções podem receber uma informação para ser

processada: input() recebe uma string que vai ser apresentada ao usuário, de modo que ele saiba que tem de digitar um número. Essa função também poderia ser chamada sem nenhum parâmetro, mas, neste caso, o usuário veria simplesmente um cursor na tela de seu computador esperando-o digitar um número. Se não souber que tem de fazer isso, nunca vai digitar nada. O texto digitado pelo usuário é retornado ao fluxo principal, mas este espera um número. Então é necessário mais um desvio para transformar o texto que veio de input() em um número, para que o fluxo principal continue.

A função int() recebe o que input() leu do teclado e

transforma em um número inteiro. Perceba que uma função pode ser o parâmetro de outra.

Cada um recebe um dado e devolve outro. A função print()

recebe o que deve escrever na tela.

Você se lembra do conceito de função na matemática? Aqui é

bem parecido, no sentido que uma função sempre retorna um único elemento. “Ah!”, você vai dizer: “range() retorna mais de um número”. É verdade, mas range() retorna uma sequência de números. O que é retornado é empacotado em um único elemento. A função print() não retorna nada. Como você percebe, temos diversas possibilidades.

Todas essas são funções que já vêm com Python. Cada

linguagem de programação tem seu próprio leque básico de funções que resolvem problemas comuns do programador. Quem criou a linguagem pensou: “Quais problemas são comuns à grande maioria dos programadores que vão usar a linguagem?” Escrever na tela e ler do teclado são funções evidentes. Seria muito ruim exigir que cada programador criasse suas próprias funções de escrita e leitura, e muitas dessas funções nem seriam possíveis usando apenas a linguagem Python. De fato, essas funções básicas, para serem eficientes, são implementadas em linguagem C ou mesmo em linguagem de baixo nível dos computadores.

O que não for da linguagem tem que ser criado. Olhando esse programa, você pode imaginar qual seria uma função boa para ser criada? Uma função que calcule o fatorial de um número seria bem útil. Fatorial é um cálculo que aparece em diversas situações e podemos criar nossa própria função.

Sendo assim, o programa seria reescrito com todas as funções já mencionadas mais uma: a função que calcula o fatorial, que chamaremos de fatorial().

Você deve ter notado que sempre que escrevo o nome de uma função coloco parênteses logo em seguida. Não é obrigatório, mas serve para o leitor identificar rapidamente que estou falando de uma função e não de uma variável qualquer. O código seria o do Programa 4.2.

1 n = int(input(‘Qual o número para calcular o fator ial? ‘))

2 fat = fatorial(n)

3 print (‘O fatorial de’, n, ‘é’, fat)

 

■ Programa 4.2: Fatorial como função.

 

Ou, de uma forma ainda mais compacta:

1 n = int(input(‘Qual o número para calcular o fator ial? ‘))

2 print (‘O fatorial de’, n, ‘é’, fatorial(n))

 

■ Programa 4.3: Fatorial como função, segunda versão.

 

A chamada de uma função pode ser usada no lugar no qual você poderia usar uma variável do mesmo tipo do resultado da função. Como a função fatorial() tem como resultado um número inteiro, uma chamada a fatorial() pode ser usada no lugar de um número inteiro.