Desenvolver algoritmos
Apresentação
Esta sebenta apoia o estudo da unidade de competência UC00245 — Desenvolver algoritmos, com 25 horas de duração e 2,25 pontos de crédito, integrada na componente tecnológica dos cursos profissionais Técnico/a de Desenvolvimento de Software (481RA116), Técnico/a de Sistemas de Computação e Redes (481RA118) e Técnico/a de Multimédia (213RA104), publicados no Catálogo Nacional de Qualificações da ANQEP em outubro de 2025.
O documento segue rigorosamente o referencial oficial: os conhecimentos, realizações e critérios de desempenho apresentados são os que constam da base de dados pública do SNQ. Os exemplos, esquemas, exercícios resolvidos e comentários pedagógicos foram desenvolvidos pela equipa Aulify para apoiar a aprendizagem em sala de aula e o estudo autónomo.
A unidade tem por finalidade fornecer os alicerces conceptuais do pensamento algorítmico — não a programação numa linguagem específica. Os algoritmos aqui apresentados são posteriormente implementados em linguagens reais (Python, C, JavaScript) nas unidades de competência subsequentes. Quem dominar bem esta unidade adquire uma vantagem desproporcionada nas seguintes: a programação torna-se transcrição mecânica de um plano já feito.
Como usar esta sebenta. Cada capítulo combina exposição teórica, exemplos resolvidos, esquemas visuais e exercícios propostos. Recomenda-se a leitura sequencial dos capítulos 1 a 7 e a resolução prática dos capítulos 8 e 9 a par dos slides e fichas de trabalho disponíveis no portal Aulify.
Pensamento computacional
1.1 · Conceito e origem
O termo computational thinking foi popularizado por Jeannette Wing num artigo seminal publicado em 2006 na revista Communications of the ACM, no qual a autora propõe a sua adopção como competência fundamental do século XXI, ao nível da leitura, escrita e aritmética. Wing define-o como:
«O conjunto de processos de pensamento envolvidos na formulação de um problema e na expressão da sua solução, de tal forma que tanto um computador (humano ou máquina) possa eficazmente executá-la.» Jeannette Wing, Carnegie Mellon University, 2006
A definição é deliberadamente ampla. Pensamento computacional não é o domínio do software corrente (Word, Photoshop, Excel) — essa competência é designada por literacia digital. Tão pouco se confunde com a programação numa linguagem específica. O pensamento computacional é uma forma estruturada de raciocinar sobre problemas, independente do meio de execução. Um chef que organiza a mise en place da cozinha, um engenheiro que decompõe um projecto em fases, ou um médico que segue um protocolo clínico, estão a aplicar pensamento computacional, mesmo sem qualquer computador presente.
1.2 · Os quatro pilares
Embora diferentes autores proponham variantes, a divisão mais consensual na literatura pedagógica (em particular nos materiais da Computer Science Teachers Association e da BBC) identifica quatro pilares:
| Pilar | Definição operativa |
|---|---|
| Decomposição | Dividir um problema complexo em sub-problemas mais pequenos e tratáveis. |
| Reconhecimento de padrões | Identificar semelhanças entre o problema actual e problemas previamente resolvidos. |
| Abstração | Ignorar detalhes irrelevantes e focar apenas no essencial; construir modelos simplificados da realidade. |
| Algoritmo | Definir uma sequência ordenada, finita e executável de passos para resolver o problema. |
Decomposição
Permite enfrentar problemas grandes. Em vez de resolver «construir uma casa», decompõe-se em fundações, estrutura, telhado, instalações, acabamentos. Cada sub-problema pode ser atribuído a uma equipa diferente, executado em paralelo, e testado isoladamente. Em informática, a decomposição é a base da modularização (funções, módulos, micro-serviços).
Reconhecimento de padrões
Permite reutilizar conhecimento. Quem aprendeu a ordenar uma lista de números por ordem crescente pode adaptar o algoritmo para ordenar palavras por ordem alfabética: o padrão de comparação-e-troca é o mesmo, muda apenas o critério. Reconhecer padrões poupa tempo e reduz a probabilidade de erros.
Abstração
Permite gerir complexidade. Um mapa do metro de Lisboa ignora distâncias reais, ruas, edifícios, altimetria — preserva apenas as paragens e as ligações entre elas, porque é essa informação que o utilizador precisa. Em programação, a abstração manifesta-se em conceitos como variáveis (que abstraem endereços de memória), funções (que abstraem sequências de instruções) e classes (que abstraem entidades do mundo real).
Algoritmo
É a síntese dos três pilares anteriores. Depois de decompor, reconhecer padrões e abstrair, expressa-se a solução como uma sequência precisa de instruções executáveis.
1.3 · Caso aplicado · localizar um livro numa biblioteca
Problema. Encontrar o exemplar de Os Lusíadas numa biblioteca municipal com cerca de 50 000 volumes.
Aplicação dos pilares.
- Decomposição: o problema reparte-se em (1) chegar à secção certa do edifício, (2) localizar o corredor, (3) localizar a estante, (4) localizar a prateleira, (5) identificar o exemplar.
- Reconhecimento de padrões: a biblioteca está organizada segundo um sistema de classificação (Classificação Decimal Universal, ou por autor/título). Reconhecer o sistema permite navegar eficientemente.
- Abstração: ignoram-se cor da capa, formato, idade do exemplar — usa-se apenas autor (Camões) e título (Os Lusíadas).
- Algoritmo:
INICIO
Identificar autor: Camões, Luís de
Localizar secção "Literatura Portuguesa"
Localizar estante "C"
PARA cada livro na prateleira FAÇA
SE título = "Os Lusíadas" ENTÃO
retirar livro
SAIR DO CICLO
FIM SE
FIM PARA
SE livro não encontrado ENTÃO
pedir ajuda à bibliotecária
FIM SE
FIM
Este exemplo, embora simples, já contém três estruturas de controlo que estudaremos formalmente no capítulo 4: sequência (passos numerados), iteração (PARA cada livro) e selecção (SE título = ...).
1.4 · Pensamento computacional em profissões não-informáticas
A literatura recente em didáctica das ciências documenta a aplicação produtiva do pensamento computacional em domínios diversos:
- Medicina. Protocolos de triagem em urgências (algoritmo de Manchester) determinam, com base em sintomas mensuráveis, a prioridade de atendimento.
- Direito. Fluxogramas de decisão para classificar processos judiciais (cível vs criminal, instâncias).
- Cozinha profissional. Receitas estandardizadas garantem reprodutibilidade em cadeia (qualquer cozinheiro produz o mesmo prato).
- Logística. Algoritmos de rota mínima e gestão de armazém.
Esta omnipresença justifica o estatuto de competência transversal do pensamento computacional, mesmo para alunos que não venham a exercer profissões directamente ligadas à informática.
O conceito de algoritmo
2.1 · Definição formal
A definição mais consolidada na literatura é a de Donald Knuth (The Art of Computer Programming, 1968):
«Um algoritmo é uma sequência finita, ordenada e não-ambígua de instruções, formalmente bem definida, que resolve um problema ou executa uma tarefa em tempo finito.»
Esta definição condensa cinco propriedades que constituem o teste de validade de qualquer algoritmo. Se alguma delas falha, não estamos perante um algoritmo, mas perante uma heurística, um procedimento informal ou uma simples descrição.
2.2 · As cinco características essenciais
| Característica | Significado |
|---|---|
| Finitude | Termina ao fim de um número finito de passos. |
| Definição | Cada passo é claro e sem ambiguidade. |
| Eficácia | Cada passo é executável com os meios disponíveis. |
| Determinismo | A mesma entrada produz sempre a mesma saída. |
| Entrada e Saída | Recebe zero ou mais entradas, produz uma ou mais saídas. |
Finitude
«Calcular todos os números primos» não constitui algoritmo, porque os números primos são infinitos e o procedimento nunca termina. «Calcular todos os números primos menores que mil» constitui algoritmo, porque o conjunto de candidatos é finito.
Definição
A instrução «misture bem» não é definida — depende da interpretação subjectiva. A instrução «agite vigorosamente durante trinta segundos» é definida. Em programação, esta característica traduz-se na escolha cuidadosa de operadores, palavras-chave e nomes não ambíguos.
Eficácia
Cada passo tem de ser computável com os meios disponíveis. «Dividir por zero», «calcular a raiz quadrada de um número negativo no domínio dos reais» ou «escolher aleatoriamente um número irracional» não são eficazes — o passo não pode ser executado.
Determinismo
Para a mesma entrada, o algoritmo produz sempre a mesma saída. Esta propriedade é fundamental para a reprodutibilidade e para a depuração. Note-se, contudo, que existem algoritmos não-determinísticos úteis, como os algoritmos probabilísticos (criptografia, simulação de Monte Carlo, jogos), nos quais a aleatoriedade é uma escolha de design, não uma falha.
Entrada e Saída
Alguns algoritmos não recebem entrada explícita («calcular os primeiros dez números pares»), mas todos devem produzir alguma saída útil — caso contrário, não cumprem qualquer função.
2.3 · Acção, instrução e estado
Cada acção (ou instrução) de um algoritmo provoca uma transição no estado do sistema. O estado é o conjunto completo de valores que descrevem a situação do programa num dado instante — fundamentalmente, os valores das variáveis em memória, mas também ficheiros abertos, posições de cursor, conexões de rede, etc.
A execução de um algoritmo pode ser modelada como uma máquina de estados: parte de um estado inicial (E₀), e através de uma sequência de transições atinge um estado final (E_n). Esta visão é fundamental para a depuração: quando algo corre mal, identifica-se em que estado o sistema entrou indevidamente.
Exemplo · estados sucessivos
E₀: x = 0, y = 0 (estado inicial)
x ← 5
E₁: x = 5, y = 0
y ← x * 2
E₂: x = 5, y = 10
ESCREVER y
E₃: x = 5, y = 10 (estado final — y permanece, mas é exibido)
2.4 · Algoritmo versus programa
Esta distinção é das mais importantes de toda a programação:
| Algoritmo | Programa |
|---|---|
| Abstracto — linguagem natural, pseudocódigo ou fluxograma | Concreto — código numa linguagem específica |
| Independente da linguagem de programação | Específico de uma linguagem (Python, C, JavaScript, Java) |
| Independente do hardware | Específico de uma plataforma |
| Pode ser executado por uma pessoa | Executado por uma máquina |
| Vida útil potencialmente longa (décadas) | Vida útil tipicamente curta (anos) |
O mesmo algoritmo de ordenação quicksort dá origem a programas distintos em Python, C, Java ou JavaScript — programas com sintaxes muito diferentes, mas todos implementando a mesma lógica. Os algoritmos de Euclides, formulados no século III a.C., continuam a ser implementados em programas modernos de criptografia (cálculo do máximo divisor comum em chaves RSA). O algoritmo persiste; os programas evoluem.
Daí a precedência conceptual: pensar primeiro, codificar depois. Um bom algoritmo dá origem a programas correctos em qualquer linguagem; um mau algoritmo dá origem a bugs em todas elas.
2.5 · Algoritmos do quotidiano
O quadro seguinte ilustra a presença de lógica algorítmica em actividades quotidianas. Em cada caso, é possível identificar entradas, sequência ordenada de acções, condições explícitas e estado final claro.
| Cenário | Entrada | Acções principais | Saída |
|---|---|---|---|
| Preparar chá | Água, saqueta, chávena | Aquecer 2 min · Pôr saqueta · Aguardar 4 min · Retirar | Chá pronto |
| Atravessar a passadeira | Posição inicial | Olhar à esquerda · Olhar à direita · Esperar se houver veículo · Atravessar | Posição no outro lado |
| Levantar dinheiro na ATM | Cartão, PIN, valor pretendido | Inserir cartão · Marcar PIN · Indicar valor · Receber notas e talão | Dinheiro em mão |
| Iniciar sessão num portal | Email, palavra-passe | Validar formato do email · Validar palavra-passe · Iniciar sessão · Redireccionar | Acesso à área pessoal |
Os exemplos digitais (ATM, login) são versões formalizadas, auditadas e executadas por máquinas dos exemplos físicos. A diferença não é de natureza mas de rigor.
Dados e operações
3.1 · Tipos de dados primitivos
Antes de poder formular operações, é preciso classificar os valores manipulados pelo algoritmo. Os tipos de dados primitivos mais comuns são:
| Tipo | Domínio | Exemplos | Operações típicas |
|---|---|---|---|
| Inteiro | ℤ (números inteiros) | 0, 42, −17, 1024 | adição, subtracção, multiplicação, divisão inteira (DIV), resto (MOD) |
| Real | ℝ (números reais) | 3.14, −0.5, 2.71828 | as anteriores, mais divisão real, potenciação |
| Carácter | Unicode | 'A', '?', 'ç' | comparação, conversão para inteiro (código) |
| Cadeia (string) | sequência de caracteres | "Aulify", "olá mundo" | concatenação, indexação, comprimento |
| Lógico (boolean) | {Verdadeiro, Falso} | V, F | conjunção (E), disjunção (OU), negação (NÃO) |
Cada linguagem de programação adopta nomes próprios para estes tipos (int, float, str, bool em Python; int, double, char, string, bool em C++), mas a essência conceptual é universal.
Um aspecto subtil mas importante é a distinção entre inteiro e real: a divisão 10 ÷ 3 produz resultados diferentes consoante o tipo. Em divisão inteira, 10 DIV 3 = 3 (resto 1); em divisão real, 10 / 3 = 3.333... A linguagem natural não distingue, mas em pseudocódigo e em programação a distinção é obrigatória.
A escolha do tipo certo para cada valor não é puramente técnica — tem consequências:
- O número de telefone deve ser cadeia, não inteiro, porque pode começar por zero (que se perderia num inteiro).
- O código postal português (
1234-567) deve ser cadeia, porque contém hífen. - O número de irmãos deve ser inteiro, não real, porque não há sentido em ter 2,5 irmãos.
- O salário mensal deve ser real (com duas casas decimais), porque pode incluir cêntimos.
3.2 · Constantes e variáveis
Os algoritmos manipulam dois tipos de identificadores: constantes e variáveis.
Constante. Identificador associado a um valor que não muda durante a execução. Convenciona-se escrevê-la em maiúsculas. Exemplos típicos: PI = 3.14159, IVA = 0.23, MAX_TENTATIVAS = 3. O uso de constantes em vez de literais espalhados pelo código melhora a legibilidade e facilita a manutenção (alterar a taxa de IVA num único ponto).
Variável. Identificador associado a um valor que pode mudar durante a execução. Convenciona-se escrevê-la em minúsculas, com nomes descritivos (numAlunos, não n; precoUnitario, não p).
3.3 · Atribuição
A operação de atribuição associa um valor a uma variável. Em pseudocódigo português usa-se o símbolo ← (seta para a esquerda) ou, em alternativa, :=:
total ← 0
nome ← "Maria"
idade ← 17
total ← total + 10
A última linha causa confusão habitual em alunos com formação matemática sólida. Em matemática, x = x + 10 é uma contradição (implicaria 0 = 10). Em programação, a atribuição não é igualdade: é uma instrução com efeito sequencial. A leitura correcta é: «calcula a expressão à direita usando o valor actual de total, e guarda o resultado na mesma variável». Pode-se ler como «total recebe total mais 10».
A metáfora habitual é a da gaveta etiquetada: a variável é uma gaveta com um rótulo; a atribuição é abrir a gaveta, retirar o que lá está, fazer alguma operação e voltar a guardar.
3.4 · Entrada e saída de dados
Os algoritmos comunicam com o exterior através de operações de entrada (LER) e saída (ESCREVER):
LER idade
LER nome, apelido
ESCREVER "Olá, ", nome
ESCREVER "Tem ", idade, " anos."
Em programação real, estas operações correspondem a input() e print() em Python, a scanf e printf em C, a Scanner.nextLine() e System.out.println() em Java. Em pseudocódigo permanecemos no nível abstracto.
3.5 · Operadores
Aritméticos
| Operador | Significado | Exemplo | Resultado |
|---|---|---|---|
+ |
adição | 5 + 3 | 8 |
− |
subtracção | 5 − 3 | 2 |
* ou × |
multiplicação | 5 * 3 | 15 |
/ |
divisão real | 7 / 2 | 3.5 |
DIV |
divisão inteira | 7 DIV 2 | 3 |
MOD |
resto da divisão inteira | 7 MOD 2 | 1 |
^ |
potenciação | 2 ^ 5 | 32 |
Os operadores DIV e MOD são particularmente úteis. Para testar se um número n é par, escreve-se n MOD 2 = 0. Para extrair os dígitos das unidades de um número, calcula-se n MOD 10. Para contar minutos numa duração em segundos, usa-se segundos DIV 60.
Relacionais
| Operador | Significado |
|---|---|
= |
igual a |
≠ ou <> |
diferente de |
< |
menor que |
> |
maior que |
≤ ou <= |
menor ou igual a |
≥ ou >= |
maior ou igual a |
Os operadores relacionais produzem sempre um valor lógico (Verdadeiro ou Falso). Por exemplo, a expressão idade ≥ 18 avalia a Verdadeiro quando a variável idade contém um valor maior ou igual a 18.
Lógicos
| Operador | Significado |
|---|---|
E (AND) |
conjunção — Verdadeiro se ambos os operandos forem Verdadeiros |
OU (OR) |
disjunção — Verdadeiro se pelo menos um operando for Verdadeiro |
NÃO (NOT) |
negação — inverte o valor lógico |
Estes operadores combinam expressões lógicas para formar condições complexas:
pode_votar ← (idade ≥ 18) E (nacionalidade = "PT")
pode_assistir ← (idade ≥ 16) OU acompanhado
indisponivel ← NÃO disponivel
3.6 · Precedência de operadores
À semelhança da matemática, os operadores têm uma ordem de avaliação definida. Em pseudocódigo (e na generalidade das linguagens):
- Parênteses
- Potenciação (
^) - Multiplicação, divisão,
DIV,MOD - Adição e subtracção
- Operadores relacionais
NÃOEOU
Em caso de dúvida, usar parênteses. A clareza ganha-se sempre.
Estruturas lógicas básicas
4.1 · Teorema da programação estruturada
Em 1966, Corrado Böhm e Giuseppe Jacopini publicaram um teorema fundamental: qualquer algoritmo computável pode ser expresso usando apenas três estruturas de controlo de fluxo:
- Sequência — execução de instruções uma após outra.
- Selecção (alternativa) — escolha entre dois ou mais caminhos consoante uma condição.
- Iteração (repetição) — execução repetida de um bloco enquanto uma condição se mantiver.
Este resultado é a fundação teórica da programação estruturada, paradigma dominante no ensino e nas linguagens modernas. Tudo o que estudaremos nesta unidade combinará estas três estruturas.
4.2 · Estrutura sequencial
A mais simples e a default. As instruções são executadas exactamente pela ordem em que aparecem.
Exemplo · cálculo do preço com IVA
INICIO
LER preco
LER quantidade
total ← preco * quantidade
iva ← total * 0.23
total_com_iva ← total + iva
ESCREVER total_com_iva
FIM
4.3 · Estrutura alternativa · SE-ENTÃO-SENÃO
Permite que o algoritmo tome diferentes caminhos consoante o valor de uma condição lógica.
Forma simples (sem alternativa):
SE idade ≥ 18 ENTÃO
ESCREVER "Pode votar"
FIM SE
Forma composta (com alternativa):
SE idade ≥ 18 ENTÃO
ESCREVER "Maior de idade"
SENÃO
ESCREVER "Menor de idade"
FIM SE
Forma encadeada (várias alternativas):
SE media ≥ 18 ENTÃO
ESCREVER "Muito Bom"
SENÃO SE media ≥ 14 ENTÃO
ESCREVER "Bom"
SENÃO SE media ≥ 10 ENTÃO
ESCREVER "Suficiente"
SENÃO
ESCREVER "Insuficiente"
FIM SE
A condição é sempre uma expressão que avalia a Verdadeiro ou Falso. Quando há muitas alternativas mutuamente exclusivas, algumas linguagens (e variantes de pseudocódigo) oferecem uma estrutura mais legível conhecida por selecção múltipla, equivalente ao switch/case de C ou ao match de Python 3.10+. Não é objecto deste módulo.
4.4 · Estrutura repetitiva
A iteração permite executar um bloco de instruções múltiplas vezes, evitando a duplicação de código e habilitando o processamento de quantidades arbitrárias de dados. Existem três variantes principais.
ENQUANTO (while) — pré-teste
Avalia a condição antes de executar o bloco. Se a condição for falsa logo no início, o bloco não chega a ser executado.
i ← 1
ENQUANTO i ≤ 10 FAÇA
ESCREVER i
i ← i + 1
FIM ENQUANTO
PARA (for) — contador
Usada quando o número de iterações é conhecido à partida.
PARA i DE 1 ATÉ 10 FAÇA
ESCREVER i
FIM PARA
A variável i é automaticamente inicializada e incrementada. Alguns dialectos permitem definir um passo (DE 1 ATÉ 100 PASSO 5 percorre 1, 6, 11, …).
REPETIR-ATÉ (do-while) — pós-teste
Executa o bloco pelo menos uma vez, e só depois avalia a condição.
REPETIR
ESCREVER "Insira a sua idade:"
LER idade
ATÉ idade ≥ 0 E idade ≤ 120
Útil para validação de dados — pede-se sempre, e só se sai do ciclo quando o utilizador insere um valor válido.
4.5 · Combinação de estruturas
As três estruturas combinam-se livremente e podem aninhar-se. O exemplo seguinte combina iteração, selecção e sequência:
Exemplo · contar pares e ímpares
INICIO
pares ← 0
impares ← 0
PARA i DE 1 ATÉ 20 FAÇA
SE i MOD 2 = 0 ENTÃO
pares ← pares + 1
SENÃO
impares ← impares + 1
FIM SE
FIM PARA
ESCREVER "Pares: ", pares
ESCREVER "Ímpares: ", impares
FIM
A indentação não é decorativa: torna explícito o aninhamento das estruturas e é fundamental para a legibilidade.
Pseudocódigo
O pseudocódigo é uma notação textual que combina elementos da linguagem natural com convenções de programação. Não é executável por uma máquina, mas é precisa o suficiente para servir de especificação completa de um algoritmo, a partir da qual qualquer programador consegue produzir um programa numa linguagem real.
5.1 · Sintaxe portuguesa
Não existe norma oficial única; diferentes manuais usam variantes. A versão adoptada nesta sebenta é a mais comum nos materiais técnicos portugueses para os cursos profissionais.
| Categoria | Palavras-chave |
|---|---|
| Delimitação | INICIO … FIM |
| Entrada / Saída | LER, ESCREVER |
| Atribuição | ← (ou :=) |
| Selecção | SE … ENTÃO … SENÃO … FIM SE |
Iteração while |
ENQUANTO … FAÇA … FIM ENQUANTO |
Iteração for |
PARA … DE … ATÉ … FAÇA … FIM PARA |
Iteração do-while |
REPETIR … ATÉ |
| Saída antecipada | SAIR DO CICLO (ou INTERROMPER) |
| Comentários | // linha · /* … */ bloco |
5.2 · Boas práticas
- Palavras-chave em maiúsculas, identificadores em minúsculas. A distinção visual ajuda a leitura.
- Indentação consistente (dois ou quatro espaços) por nível de aninhamento.
- Nomes descritivos para variáveis (
numAlunos,mediaTurma), nunca uma letra solta excepto para índices triviais (i,j,k). - Comentários explicam o porquê, não o quê. O quê já se vê no código.
- Uma instrução por linha. Evitar instruções compostas que escondam complexidade.
- Constantes para valores que se repetem (
IVA = 0.23,MAX = 100). - Delimitar blocos sempre com
FIM SE,FIM PARA, etc. — mesmo quando há só uma instrução no interior.
Exemplo · cálculo da nota final de um aluno
INICIO
// Lê três notas e calcula a média ponderada (50%, 30%, 20%)
LER teste, ficha, oral
// Validação básica
SE teste < 0 OU teste > 20 OU ficha < 0 OU ficha > 20 OU oral < 0 OU oral > 20 ENTÃO
ESCREVER "Notas inválidas — devem estar entre 0 e 20"
SENÃO
media ← teste * 0.5 + ficha * 0.3 + oral * 0.2
SE media ≥ 10 ENTÃO
ESCREVER "Aprovado com ", media
SENÃO
ESCREVER "Reprovado com ", media
FIM SE
FIM SE
FIM
Fluxograma
O fluxograma é a representação visual de um algoritmo, recorrendo a símbolos geométricos normalizados ligados por setas. Foi consagrado pela norma ISO 5807 (1985).
6.1 · Símbolos normativos
| Símbolo | Significado | Exemplo |
|---|---|---|
| Elipse / stadium | Terminal — início ou fim do algoritmo | INÍCIO · FIM |
| Rectângulo | Processo — operação ou cálculo | total ← preco * qtd |
| Losango | Decisão — pergunta com resposta binária | idade ≥ 18 ? |
| Paralelogramo | Entrada ou Saída — interacção com utilizador | LER nome · ESCREVER total |
| Rectângulo com bordas laterais | Sub-processo — chamada a sub-algoritmo ou função | calcularMedia() |
| Círculo com letra | Conector — liga partes distantes do diagrama | A, B, C… |
| Seta | Fluxo — define a sequência | → |
6.2 · Convenções de leitura
- Leitura de cima para baixo e da esquerda para a direita.
- Cada decisão tem duas saídas rotuladas (V/F ou Sim/Não).
- O fluxo principal desce; os ramos alternativos saem para o lado e voltam a juntar-se.
- Evitar cruzamentos de setas — recorrer a conectores quando necessário.
- Todos os caminhos terminam num símbolo de fim.
6.3 · Ferramentas
- draw.io (também conhecido por diagrams.net) — gratuito, web-based, ficheiros guardados localmente ou na cloud.
- Lucidchart — versão web comercial, com plano gratuito limitado.
- Mermaid — sintaxe textual que se converte em diagramas, útil para integrar em documentação Markdown.
- Microsoft Visio — ferramenta tradicional do ecossistema Office.
A escolha entre pseudocódigo e fluxograma depende do contexto. Para algoritmos pequenos (até cerca de vinte instruções), o fluxograma é mais intuitivo, especialmente para audiências não-programadoras. Para algoritmos grandes, o pseudocódigo é mais económico — um fluxograma de cem nós torna-se ilegível.
6.4 · Conversão lado-a-lado
O mesmo algoritmo representado em pseudocódigo e em fluxograma — verificar se um número é par ou ímpar:
INICIO
LER n
SE n MOD 2 = 0 ENTÃO
ESCREVER "Par"
SENÃO
ESCREVER "Ímpar"
FIM SE
FIM
Técnicas de construção · padrões reutilizáveis
Os algoritmos não-triviais combinam tipicamente um conjunto restrito de padrões que se repetem em milhares de problemas. Identificá-los economiza tempo e reduz erros. Esta secção apresenta os padrões mais frequentes em algoritmia básica.
7.1 · Contador
Conta ocorrências de um evento — quantos elementos satisfazem uma condição, quantas iterações foram feitas, etc.
Inicialização: n ← 0
Operação no ciclo: n ← n + 1
Exemplo · contar quantas notas são positivas
positivas ← 0
PARA i DE 1 ATÉ 10 FAÇA
LER nota
SE nota ≥ 10 ENTÃO
positivas ← positivas + 1
FIM SE
FIM PARA
ESCREVER "Notas positivas: ", positivas
7.2 · Acumulador
Acumula um valor — tipicamente a soma ou o produto de uma sequência.
Soma: inicializa a 0; operação soma ← soma + valor
Produto: inicializa a 1; operação prod ← prod * valor
A escolha do valor inicial não é arbitrária: é o elemento neutro da operação (0 para a soma, 1 para o produto). Inicializar o produto a 0 seria fatal — todos os produtos seguintes dariam 0.
Exemplo · calcular o factorial de n
LER n
fact ← 1
PARA i DE 1 ATÉ n FAÇA
fact ← fact * i
FIM PARA
ESCREVER "n! = ", fact
7.3 · Máximo e mínimo
Determina o maior (ou menor) elemento de uma sequência.
Estratégia recomendada: assumir que o primeiro elemento é o máximo (ou mínimo) provisório, e percorrer os restantes actualizando sempre que encontrar um valor maior (ou menor).
Exemplo · maior de n números lidos
LER n
LER primeiro
maior ← primeiro
PARA i DE 2 ATÉ n FAÇA
LER valor
SE valor > maior ENTÃO
maior ← valor
FIM SE
FIM PARA
ESCREVER "Maior valor: ", maior
7.4 · Sentinela
Valor especial que sinaliza o fim de uma sequência de comprimento indeterminado. Usa-se quando não se sabe à partida quantos elementos serão lidos.
Requisito: a sentinela tem de ser distinguível dos valores válidos. Para idades positivas, −1 é boa sentinela; para temperaturas (que podem ser negativas), há que escolher outro valor.
Exemplo · ler idades até aparecer −1 e calcular a média
soma ← 0
contador ← 0
LER idade
ENQUANTO idade ≠ -1 FAÇA
soma ← soma + idade
contador ← contador + 1
LER idade
FIM ENQUANTO
SE contador > 0 ENTÃO
ESCREVER "Média: ", soma / contador
SENÃO
ESCREVER "Nenhuma idade lida"
FIM SE
7.5 · Validação de dados
Repete a leitura até que o valor introduzido satisfaça os critérios de validade. Implementa-se naturalmente com REPETIR-ATÉ.
Exemplo · validar uma nota entre 0 e 20
REPETIR
ESCREVER "Insira a nota (0-20):"
LER nota
SE nota < 0 OU nota > 20 ENTÃO
ESCREVER "Valor fora do intervalo. Tente outra vez."
FIM SE
ATÉ nota ≥ 0 E nota ≤ 20
7.6 · Tabela-resumo
| Padrão | Quando usar | Inicialização | Operação |
|---|---|---|---|
| Contador | Contar ocorrências | n ← 0 |
n ← n + 1 |
| Acumulador (soma) | Somar valores | soma ← 0 |
soma ← soma + valor |
| Acumulador (produto) | Multiplicar valores | prod ← 1 |
prod ← prod * valor |
| Máximo | Maior valor visto | primeiro elemento | SE valor > max ENTÃO max ← valor |
| Mínimo | Menor valor visto | primeiro elemento | SE valor < min ENTÃO min ← valor |
| Sentinela | Parar leitura | valor especial fora do domínio | ENQUANTO valor ≠ SENTINELA |
| Validação | Garantir entrada válida | — | REPETIR … ATÉ condição |
Casos resolvidos
Esta secção apresenta cinco problemas completos, cada um desenvolvido em três etapas: análise, algoritmo em pseudocódigo e implementação em Python. O leitor é convidado a tentar resolver cada problema antes de consultar a solução.
8.1 · Caso 1 · Maior de N números
Enunciado. Ler n números reais e indicar o maior.
Análise. Padrão «máximo». Lemos primeiro o n; depois o primeiro valor (que assumimos como provisório máximo); depois os restantes n − 1, actualizando o máximo sempre que encontramos um valor superior.
Pseudocódigo.
INICIO
LER n
SE n ≤ 0 ENTÃO
ESCREVER "n tem de ser positivo"
SAIR
FIM SE
LER primeiro
maior ← primeiro
PARA i DE 2 ATÉ n FAÇA
LER valor
SE valor > maior ENTÃO
maior ← valor
FIM SE
FIM PARA
ESCREVER "Maior: ", maior
FIM
Implementação em Python.
n = int(input("Quantos numeros? "))
if n <= 0:
print("n tem de ser positivo")
else:
maior = float(input("Numero 1: "))
for i in range(2, n + 1):
valor = float(input(f"Numero {i}: "))
if valor > maior:
maior = valor
print(f"Maior: {maior}")
Teste. Para n = 4 e entradas 3.5, 7.2, 1.8, 5.0, a saída é Maior: 7.2.
8.2 · Caso 2 · Média com validação e sentinela
Enunciado. Ler notas (valores reais entre 0 e 20) até o utilizador introduzir −1. Calcular a média, ignorando notas inválidas e tratando o caso de não ter sido lida nenhuma nota válida.
Análise. Combinamos os padrões «sentinela», «validação», «contador» e «acumulador-soma».
Pseudocódigo.
INICIO
soma ← 0
contador ← 0
ESCREVER "Insira notas (-1 para terminar):"
LER nota
ENQUANTO nota ≠ -1 FAÇA
SE nota ≥ 0 E nota ≤ 20 ENTÃO
soma ← soma + nota
contador ← contador + 1
SENÃO
ESCREVER "Nota inválida — ignorada"
FIM SE
LER nota
FIM ENQUANTO
SE contador > 0 ENTÃO
media ← soma / contador
ESCREVER "Média de ", contador, " notas: ", media
SENÃO
ESCREVER "Nenhuma nota válida lida"
FIM SE
FIM
Implementação em Python.
soma = 0.0
contador = 0
print("Insira notas (-1 para terminar):")
nota = float(input())
while nota != -1:
if 0 <= nota <= 20:
soma += nota
contador += 1
else:
print("Nota invalida — ignorada")
nota = float(input())
if contador > 0:
print(f"Media de {contador} notas: {soma / contador:.2f}")
else:
print("Nenhuma nota valida lida")
8.3 · Caso 3 · Tabuada de um número
Enunciado. Ler um número inteiro n e imprimir a sua tabuada (de 1 a 10).
Análise. Iteração simples com PARA e formatação de saída.
Pseudocódigo.
INICIO
LER n
PARA i DE 1 ATÉ 10 FAÇA
ESCREVER n, " x ", i, " = ", n * i
FIM PARA
FIM
Implementação em Python.
n = int(input("Numero: "))
for i in range(1, 11):
print(f"{n} x {i} = {n * i}")
8.4 · Caso 4 · Verificar se um número é primo
Enunciado. Ler um número inteiro positivo n e indicar se é primo (divisível apenas por 1 e por si próprio).
Análise. Um número é primo se não tem divisores entre 2 e n − 1. Estratégia ingénua: testar todos. Estratégia melhor: bastam os divisores até √n (porque se houver divisor maior, existe correspondente menor). Usaremos a versão simples para clareza.
Pseudocódigo.
INICIO
LER n
SE n < 2 ENTÃO
ESCREVER "Não é primo (n deve ser ≥ 2)"
SAIR
FIM SE
ehPrimo ← Verdadeiro
i ← 2
ENQUANTO i < n E ehPrimo FAÇA
SE n MOD i = 0 ENTÃO
ehPrimo ← Falso
FIM SE
i ← i + 1
FIM ENQUANTO
SE ehPrimo ENTÃO
ESCREVER n, " é primo"
SENÃO
ESCREVER n, " não é primo"
FIM SE
FIM
Implementação em Python.
n = int(input("Numero: "))
if n < 2:
print("Nao e primo (n deve ser >= 2)")
else:
eh_primo = True
i = 2
while i < n and eh_primo:
if n % i == 0:
eh_primo = False
i += 1
print(f"{n} {'e' if eh_primo else 'nao e'} primo")
Observação. A condição i < n E ehPrimo permite sair cedo — assim que se descobre que n não é primo, o ciclo termina sem testar os restantes divisores.
8.5 · Caso 5 · Máximo, mínimo e média numa só passagem
Enunciado. Ler uma sequência de n valores reais. Devolver simultaneamente o máximo, o mínimo e a média.
Análise. Combinação dos padrões «máximo», «mínimo», «acumulador-soma» e «contador» — todos actualizados na mesma passagem pelos dados, em vez de três passagens separadas.
Pseudocódigo.
INICIO
LER n
SE n ≤ 0 ENTÃO
ESCREVER "n tem de ser positivo"
SAIR
FIM SE
LER primeiro
max ← primeiro
min ← primeiro
soma ← primeiro
PARA i DE 2 ATÉ n FAÇA
LER valor
SE valor > max ENTÃO max ← valor FIM SE
SE valor < min ENTÃO min ← valor FIM SE
soma ← soma + valor
FIM PARA
ESCREVER "Máximo: ", max
ESCREVER "Mínimo: ", min
ESCREVER "Média: ", soma / n
FIM
Este caso é importante: ilustra que vários padrões podem coexistir num único ciclo, evitando passagens redundantes pelos dados. Em algoritmos sobre grandes volumes de dados, esta optimização é crítica para o desempenho.
Testar e depurar
Construir um algoritmo é metade do trabalho; garantir que está correcto é a outra metade. Esta secção apresenta as técnicas básicas de teste e depuração.
9.1 · Trace table — execução à mão
A trace table (tabela de execução) é uma tabela que regista, passo a passo, o valor de cada variável após cada instrução. Permite simular a execução do algoritmo no papel, sem computador.
Exemplo · trace table para o factorial de 4
LER n // 4
fact ← 1
PARA i DE 1 ATÉ n FAÇA
fact ← fact * i
FIM PARA
A trace table é especialmente útil quando um algoritmo produz um resultado errado e não se compreende porquê: a tabela mostra exactamente em que iteração e em que variável surgiu o desvio.
9.2 · Erros típicos
Listamos os erros mais frequentes em algoritmia básica, com sintomas e causas:
| Tipo | Sintoma | Exemplo |
|---|---|---|
| Off-by-one | Conta uma a mais ou a menos | PARA i DE 1 ATÉ n quando devia ser n − 1 (ou vice-versa) |
| Inicialização errada | Resultados absurdos | soma ← 1 em vez de ← 0; prod ← 0 em vez de ← 1 |
| Condição invertida | Caminho errado | SE x < 10 quando se queria > |
| Ciclo infinito | Algoritmo nunca termina | Esquecer i ← i + 1 no corpo de um ENQUANTO |
| Divisão por zero | Erro de execução | Falta SE contador > 0 antes de calcular média |
| Comparação de tipos diferentes | Comparações sempre falsas | Comparar a cadeia "10" com o inteiro 10 |
| Lógica errada | Resultado errado nos casos limite | Usar E quando se queria OU |
| Uso de variável não inicializada | Comportamento imprevisível | Usar total sem antes lhe atribuir valor |
A frequência do erro off-by-one justifica o seu nome próprio na literatura anglo-saxónica (lê-se off-by-one error). Ocorre tipicamente quando o programador hesita entre incluir ou excluir um limite do intervalo.
9.3 · Programação defensiva
A programação defensiva consiste em assumir que tudo o que pode correr mal eventualmente correrá. Em vez de confiar em utilizadores cooperativos e contextos perfeitos, antecipam-se falhas e protege-se o algoritmo:
- Validar entradas no início (em vez de propagar valores inválidos).
- Tratar casos limite explicitamente (lista vazia, valor zero, valor negativo, valor enorme).
- Verificar pré-condições antes de operações arriscadas (divisão por zero, raiz quadrada de negativo).
- Documentar pressupostos com comentários.
A regra prática: antes de cada operação arriscada, perguntar «em que circunstância isto pode falhar?» e acrescentar protecção apropriada.
9.4 · Estratégias de optimização
Optimizar significa tornar o algoritmo melhor — habitualmente mais rápido, mais económico em memória, ou mais legível — sem alterar o resultado.
| Estratégia | Exemplo |
|---|---|
| Sair cedo | Em vez de continuar um ciclo após já saber a resposta, interromper (SAIR DO CICLO) |
| Evitar recálculo | Guardar em variável um resultado intermédio que se reutiliza |
| Escolher a estrutura certa | PARA é mais claro que ENQUANTO quando o número de iterações é conhecido |
| Reduzir aninhamento | Achatar SE encadeados, recorrer a SENÃO SE |
| Nomes descritivos | mediaAlunos em vez de m — beneficio gratuito de legibilidade |
| Comentar o «porquê» | O quê já se vê; o porquê não |
A célebre advertência de Knuth permanece actual:
«A optimização prematura é a raiz de todo o mal.» Donald Knuth, 1974
A leitura correcta não é «nunca optimizar», mas sim: primeiro fazer funcionar correctamente, depois optimizar — e apenas onde for medível e justificado. Em particular, optimizar para legibilidade é sempre defensável; código é lido muitas mais vezes do que escrito.
Apêndices
A · Sintaxe de pseudocódigo · referência rápida
INICIO // delimita o algoritmo
...
FIM
LER variavel // entrada
ESCREVER expressao // saída
variavel ← valor // atribuição
SE condição ENTÃO // selecção
...
SENÃO SE condição ENTÃO
...
SENÃO
...
FIM SE
PARA i DE 1 ATÉ n FAÇA // iteração contada
...
FIM PARA
ENQUANTO condição FAÇA // iteração pré-teste
...
FIM ENQUANTO
REPETIR // iteração pós-teste
...
ATÉ condição
SAIR DO CICLO // interrompe ciclo
SAIR // interrompe algoritmo
// comentário de linha
/* comentário de bloco */
B · Glossário
Abstração. Processo de simplificar a realidade, ignorando detalhes irrelevantes para o problema em causa.
Acumulador. Variável que armazena a soma (ou produto) progressiva de uma sequência de valores.
Algoritmo. Sequência finita, ordenada e não-ambígua de instruções que resolve um problema em tempo finito.
Atribuição. Operação que associa um valor a uma variável. Notada por ← em pseudocódigo PT.
Booleano. Tipo de dado lógico, com dois valores possíveis: Verdadeiro e Falso.
Cadeia (string). Tipo de dado que representa uma sequência ordenada de caracteres.
Ciclo infinito. Iteração cuja condição de paragem nunca se torna falsa, violando a finitude do algoritmo.
Constante. Identificador cujo valor não muda durante a execução do algoritmo.
Contador. Variável que regista o número de ocorrências de um evento.
Critério de desempenho. No referencial SNQ, requisito qualitativo que o aluno deve cumprir para a realização ser considerada bem executada.
Decomposição. Divisão de um problema complexo em sub-problemas mais pequenos.
Determinismo. Propriedade de um algoritmo cujo resultado depende exclusivamente da entrada.
Estado. Conjunto dos valores de todas as variáveis num dado instante da execução.
Fluxograma. Representação visual de um algoritmo, usando símbolos geométricos normalizados (ISO 5807).
Iteração. Estrutura de controlo que repete um bloco de instruções enquanto uma condição se mantém verdadeira (ou até deixar de ser falsa).
Padrão de programação. Receita reutilizável aplicável a uma família de problemas semelhantes.
Pseudocódigo. Notação textual semi-formal para descrever algoritmos.
Selecção. Estrutura de controlo que escolhe entre dois ou mais caminhos consoante o valor de uma condição.
Sentinela. Valor especial que sinaliza o fim de uma sequência de comprimento desconhecido.
Sequência. Estrutura de controlo na qual as instruções são executadas pela ordem em que aparecem.
Tipo de dado. Categoria que define os valores possíveis para uma variável e as operações que lhe podem ser aplicadas.
Trace table (tabela de execução). Tabela que regista o valor das variáveis a cada passo do algoritmo.
Variável. Identificador associado a um valor que pode mudar durante a execução.
C · Recursos para aprofundamento
Software e ambientes.
- Portugol Studio — ambiente português gratuito para escrever e executar pseudocódigo. https://portugol.dev
- VisuAlg — alternativa em português brasileiro, igualmente gratuita.
- Python.org — instalador oficial do Python (versão 3.x recomendada). https://www.python.org
- draw.io — ferramenta gratuita para desenhar fluxogramas. https://www.drawio.com
Cursos online (gratuitos).
- Khan Academy — secção «Hour of Code» disponível em português.
- Coursera — Computational Thinking for Problem Solving (Universidade da Pensilvânia).
- CS50 Harvard — introdução clássica à programação; primeiras semanas cobrem pensamento computacional.
Leitura complementar.
- Knuth, D. The Art of Computer Programming, Vol. 1: Fundamental Algorithms (1968) — referência clássica avançada.
- Wing, J. Computational Thinking (Communications of the ACM, 2006) — o artigo seminal.
- Manuais portugueses para cursos profissionais: Editora Areal, Porto Editora, ASA — capítulos introdutórios de programação geralmente seguem estrutura semelhante a esta sebenta.
Referencial oficial.
- ANQEP — Catálogo Nacional de Qualificações. https://catalogo.snq.gov.pt — consultar a unidade UC00245 para verificar a versão actualizada dos critérios de desempenho oficiais.