Através da programação é possível automatizar processos, isto é, tarefas que seriam feitas manualmente por seres humanos passam a ser realizadas total ou parcialmente pelo computador. Isto gera um ganho enorme de tempo e, caso tudo seja bem estruturado, não há perda de qualidade; em muitos casos há até ganho de qualidade pois as falhas humanas não serão mais inerentes ao processo.
A sequência de passos a ser seguida para realização de uma tarefa é chamada de algoritmo. Para que o computador realize esta sequência de passos é necessário que isso esteja especificado de uma forma que a máquina entenda, isto é, através de um programa escrito em uma linguagem de programação.
Portanto, um programa de computador é um algoritmo escrito em uma linguagem de programação. Existem diversas linguagens, como Java, Python, C, PHP, dentre outras. Cada uma com suas peculiridades, isto é, em cada linguagem a forma que se escreve é diferente.
Contudo, as estruturas existentes nas linguagens são as mesmas e, por este motivo, é interessante compreender bem estas estruturas de forma genérica para que seja mais simples generalizá-las para diferentes linguagens de programação.
Entenda: é mais fácil você aprender a lógica (que é geral e genérica) antes da linguagem (que é única e segue padrões próprios).
Existem formas de se representar algoritmos fora de uma linguagem de programação. As principais são: a descrição narrativa, o fluxograma e o pseudocódigo. A mais interessante das 3 é o pseudocódigo, também chamado de portugol ou português estruturado. É a mais próxima de uma linguagem de programação real e, por este motivo, a mais simples de “traduzir” para uma linguagem.
Sendo assim, neste post a ideia é apresentar as principais estruturas para que seja possível compreender a lógica das linguagens de programação e escrever um algoritmo em pseudocódigo.
Como já mencionado, a representação de algoritmos através de pseudocódigo é uma das formas mais eficientes de se compreender a lógica de programação. Em tempos remotos, o estudo de algoritmos por pseudocódigo era feito com papel e caneta. Atualmente existem ferramentas que auxiliam no aprendizado de lógica de programação e algoritmos, isto é, aplicativos que interpretam e executam um algoritmo escrito em pseudocódigo. Desta forma é mais simples verificar o funcionamento do código e identificar erros. Uma interessante ferramenta para este propóstito é o visualg. Segundo a descrição dos próprios autores:
“O Visualg é um programa que permite criar, editar, interpretar e que também executa os algoritmos em português estruturado (portugol) como se fosse um “programa” normal de computador.”
Eis o aspecto do aplicativo:
\[\\\]
A estrutura básica de um algoritmo no visualg tem a seguinte forma:
"Nome do algoritmo"
Algoritmo
Var
Inicio Fimalgoritmo
Inicia-se com Algoritmo
e declara-se o nome do
algoritmo. Na seção Var
são declaradas as variáveis (nomes
e tipos) que serão usadas no código. E entre Inicio
e
Fimalgoritmo
são escritos os comandos.
O visualg é facilmente instalado em qualquer sistema operacional e recomendo fortemente àqueles que desejam aprender ou mesmo revisar algoritmos e lógica de programação.
O visualg tem 2 comandos de saída, isto é, comandos que vão retornar
algo ao usuário. São eles: Escreva
e Escreval
.
A diferença entre eles é a que o Escreval quebra uma linha antes de
mostrar em tela o que foi solicitado. No visualg basta escrever:
Escreva("Qualquer coisa")
ou
Escreval("Qualquer coisa")
, executar, e a mensagem
“Qualquer coisa” será printada em tela.
A estrutura do código seria algo como:
"Escreva"
Algoritmo
Var
InicioEscreval("Qualquer coisa")
Fimalgoritmo
Note como o Escreval("Qualquer coisa")
está a frente,
isto é, há um espaço antes. Isto é usualmente feito para deixar o código
mais organizado, de forma que saibamos que o Escreval
está
dentro do Inicio
e
Fimalgoritmo
, esta técnica é chamada
indentação e não é obrigatória, contudo, códigos
indentados são bem mais atrativos.
Portanto, indentar é afastar o texto da margem. Em linguagens de programação consiste em escrever o código afastado por espaço da margem de forma que a escrita fique disposta hierarquicamente, para facilitar a visualização e percepção do programa.
Uma variável é nada mais que uma entidade em que
algo é armazenado, em geral variáveis são utilizadas para armazenar
informações que serão recorrentemente usadas no código. No visualg há a
seção Var
, na qual deve-se declarar o identificador (nome)
da variável e seu tipo. Algumas convenções para declarar nomes para
variáveis são:
A maioria das regras é autoexplicativa e varia pouco de linguagem para linguagem. Esclarecendo a 5ª regra: palavras reservadas são palavras utilizadas pela linguagem com alguma finalidade. Por exemplo, no visualg a palavra Inicio serve para especificar que a partir dali serão escritos os códigos que deverão ser interpretados pelo computador; como a palavra Inicio tem esta finalidade, ela é uma palavra reservada e não pode ser usada para nomear uma variável.
Além do nome é necessário declarar o tipo da variável, os tipos primitivos são:
No visualg a seção Var
é utilizada da seguinte
forma:
Var:tipo indentificador
Para atribuir valores às variáveis declaradas, utiliza-se o símbolo
“<-”, lê-se “recebe”. Por exemplo, caso haja uma variável nomeada
como x e declarada como inteiro, poderíamos colocar entre o
Inicio
e Fimalgoritmo
algo como: x <- 10; a
partir deste momento, na memória do computador, x vale 10 e todas as
operações são válidas.
No ensino de algoritmos e lógica de programação, a declaração de
variáveis é controversa. Alguns professores exigem que o programa seja
todo escrito de cima para baixo, o que obriga o aluno a declarar todas
as variáveis que serão usadas antes de escrever o código. Na prática não
é usual fazer desta forma; em geral começamos a escrever o código e, se
precisamos de uma variável para armazenar um valor, voltamos para a
seção Var
e a declaramos.
Os comandos de entrada servem para ler alguma informação a ser
fornecida pelo usuário. No visualg existe o comando Leia
,
ele exige que o usuário informe um valor a ser armazenado em uma
variável previamente declarada. Um exemplo é:
"Nome"
Algoritmo
Var: caractere
nome
InicioEscreval("Qual é o seu nome?")
Leia(nome)
Escreval("Olá, ", nome)
Fimalgoritmo
Ao executar o algoritmo será printada a mensagem que pergunta qual o
nome do usuário, então o usuário informa seu nome, que será armazenado
na variável nome que foi declarada como caractere e, após isso, a
variável foi utilizada para um último Escreval
.
Importante notar que o Leia(nome)
exige que o usuário
informe o valor que será armazenado na variável, caso ele não forneça o
programa fica parado. Note também como o último Escreval
foi utilizado para printar um fragmento de texto (que está entre aspas)
concatenado com o valor que foi armazenado na variável.
Considere o problema de calcular a soma de 2 números fornecidos pelo usuário, uma solução possível é:
"soma2n"
algoritmo
var: inteiro
n1,n2,soma
inicio
escreval("Informe o primeiro número")
leia(n1)
escreval("Informe o segundo número")
leia(n2)
<- n1+n2
soma escreval(n1,"+",n2, "=",soma)
fimalgoritmo
Note como neste programa todas as estruturas apresentadas foram utilizadas: variáveis foram declaradas, comandos de saída e entrada foram utilizados, bem como uma atribuição para armazenar a soma em uma variável.
Os operadores aritméticos servem para realizar operações matemáticas básicas. Podem haver mudanças sutis em como os operadores são representados em algumas linguagens. No visualg as representações são:
Operador | Operação |
---|---|
+ | Adição |
- | Subtração |
* | Multiplicação |
/ | Divisão |
\ | Divisão inteira |
^ | Exponenciação |
% | Módulo (resto da divisão) |
Os operadores seguem uma hierarquia, ou seja, uma ordem de precedência. Inicialmente são efetuadas as operações entre parênteses seguindo a ordem: exponenciação, multiplicação/divisão e por fim adição/subtração. Note como a ordem de precedência não é exclusiva de algoritmos, ela segue a mesma lógica das operações matemáticas usuais.
As funções aritméticas não triviais variam de acordo com a linguagem, o visualg possui:
Operador | Operação |
---|---|
Abs | Valor absoluto |
Exp | Exponenciação |
Int | Valor inteiro |
RaizQ | Raiz quadrada |
Pi | Número pi |
Sen | Seno em radianos |
Cos | Cosseno em radianos |
Tan | Tangente em radianos |
GraupRad | Transforma graus para radianos |
Os operadores relacionais são utilizados para comparar valores das variáveis e sempre retornam valores lógicos, ou seja, verdadeiro ou falso. No visualg, os operadores relacionais são:
Operador | Operação |
---|---|
> | Maior que |
< | Menor que |
>= | Maior ou igual que |
<= | Menor ou igual que |
= | Igual |
<> | Diferente |
Considere que o problema de interesse é comparar 3 números fornecidos pelo usuário, uma solução possível é dada por:
"3compara3n"
algoritmo
var: inteiro
a,b,c
inicioescreval("Digite o primeiro valor")
leia(a)
escreval("Digite o segundo valor")
leia(b)
escreval("Digite o terceiro valor")
leia(c)
escreval()
escreval(a," é igual a",b,"?",a=b)
escreval(a," é igual a",c,"?",a=c)
escreval(b," é igual a",c,"?",b=c)
escreval()
escreval(a," é maior que",b,"?",a>b)
escreval(a," é maior que",c,"?",a>c)
escreval(b," é maior que",c,"?",b>c)
escreval()
escreval(a," é maior que ",b," ou maior que ",c,"?",(a>b)ou(a>c))
escreval()
fimalgoritmo
Os operadores lógicos, assim como os relacionais, retornam resultados lógicos. Contudo sua finalidade é outra, diferentemente dos aritméticos eles servem para comparar outros resultados lógicos. No visualg existem 3 operadores lógicos: E, OU e NÃO. Para exemplificar o funcionamento dos operadores, considere as variáveis p e q:
Já para o operador OU, se qualquer uma das opções for verdadeira, o resultado será verdadeiro. Por fim, o operador NÃO trabalha com negativas, por exemplo: se p é verdadeiro, NÃO p é falso.
Lembre-se que para utilizar os operadores lógicos é necessário comparar resultados lógicos, e que operadores relacionais geram resultados lógicos. Portanto é possível utilizar operadores lógicos com relacionais. Por exemplo: (A=B) OU (A=C), (A>B) E (A=C), etc.
Os operadores lógicos são os últimos da hierarquia de precedência, pois inicialmente são efetuadas as operações aritméticas, depois as relacionais e, por fim, as operações lógicas.
Uma estrutura condicional é utilizada quando a ação a ser tomada depende de uma condição ser ou não satisfeita, algo como: se tal coisa acontecer faça isso, senão faça aquilo. Em pseudocódigo isso é escrito da seguinte forma:
Se (condição) entao
bloco FimSe
Quando uma ação é tomada apenas se a condição de interesse for verdadeira, temos uma condicional simples. Para ilustrar considere o problema em que o usuário informa a idade e o programa retorna se ele pode ou não tirar carteira de motorista:
"cnh"
algoritmo
var: inteiro
idade
inicio
escreval("Quantos anos completos você tem?")
leia(idade)
escreval()
>= 18 entao
se idade escreval("Você é maior de idade, logo, pode tirar sua CNH.")
fimse
fimalgoritmo
Note que se o usuário for menor de idade o programa encerra, pois não
há instrução para caso a condição não seja satisfeita. Podemos melhorar
essa condicional acrescentando um bloco de código que será executado
caso a condição não seja atendida, isso é feito complementando a
estrutura simples com um senão
da seguinte forma:
Se (condição) entao
bloco1
Senao
bloco2 FimSe
A esta estrutura damos o nome de condicional composta. Melhorando o programa que retorna se o usuário pode ou não tirar carteira de motorista:
"cnh"
algoritmo
var: inteiro
idade
inicio
escreval("Quantos anos completos você tem?")
leia(idade)
escreval()
>= 18 entao
se idade escreval("Você é maior de idade, logo, pode tirar sua CNH.")
senaoescreval("Você ainda é menor de idade, portanto, não pode tirar sua CNH.")
fimse
fimalgoritmo
Note, além da apresentação da estrutura, como a indentação funciona e torna o código mais legível. Algumas linguagens possuem indentador automático, contudo é importante não se acostumar com esta ferramenta imaginando que algum dia pode ser necessário trabalhar com alguma linguagem que não possua tal artifício.
Outra situação que envolve condições são as chamdas condicionais aninhadas, trata-se da situação quando necessitamos de diversas condicionais, uma dentro da outra. Genericamente em pseudocódigo, a situação em que temos duas possíveis condições que podem ser satisfeitas fica da seguinte forma:
Se (condição1) entao
bloco1
SenaoSe (condição2) entao
bloco2
Senao
bloco3
FimSE FimSe
Desta forma temos quantas condicionais forem necessárias e blocos a ser executados para cada uma das situações. Por exemplo, considere o problema em que o usuário fornece o peso e a altura, o programa retorna o IMC (massa/altura^2) e uma mensagem a respeito do IMC. As mensagens são:
Uma possível solução é:
"imc"
algoritmo
var: real
peso, altura, imc
inicioescreval("Informe seu peso(Kg)")
leia(peso)
escreval("Informe sua altura(m)")
leia(altura)
<- peso/(altura^2)
imc
escreval("Seu IMC é igual a ", imc, ".")
<=17 entao
se imcescreval("Você está muito abaixo do peso.")
senaose (imc>17) e (imc<=18.5) entao
escreval("Você está abaixo do peso.")
senaose (imc>18.5) e (imc<=25) entao
escreval("Você está no peso ideal.")
senaose (imc>30) e (imc<=35) entao
escreval("Você está com obesidade.")
senaose (imc>35) e (imc<=40) entao
escreval("Você está com obesidade severa.")
senao>40 entao
se imcescreval("Você está com obesidade mórbida.")
senaoescreval("O peso e/ou a altura informados estão incorretos.")
fimse
fimse
fimse
fimse
fimse
fimse fimalgoritmo
A última estrutura condicional a ser apresentada é também chamada de estrutura de escolha, ou escolha/caso e tem a seguinte forma:
escolha variável
caso valor
bloco1
caso valor
bloco2
outrocaso
bloco3 fimescolha
A estrutura de escolha é uma opção bem mais simples que a solução de condicionais aninhadas, contudo há uma importante restrição: ela serve apenas para valores inteiros, ou seja, para variáveis que assumem valores inteiros; não sendo possível desta forma testar faixas de valores como foi feito no caso do IMC. Em certas linguagens esta estrutura pode ser usada em algumas outras situações, mas em geral é destinada apenas para o caso de valores inteiros.
Considere que uma empresa quer reajustar o salário dos seus funcionários baseado no número de dependentes financeiros de tal forma que:
Uma solução para o problema é:
"novosalario"
algoritmo
var: real
sal, novosal: inteiro
dep
inicioescreval("informe o salario do funcionário")
leia(sal)
escreval("informe o numero de dependentes do funcionário")
leia(dep)
escreval("atualmente recebe", sal, " reais")
escreval("e possui",dep, " dependentes.")
escolha dep0
caso <- sal+(sal*0.05)
novosal 1,2,3
caso <- sal+(sal*0.1)
novosal 4,5,6
caso <- sal+(sal*0.15)
novosal
outrocaso<- sal+(sal*0.18)
novosal
fimescolha
escreval("O salário reajustado é igual a ", novosal, " reais,")
fimalgoritmo
As estruturas de repetição permitem executar mais de uma vez um mesmo bloco de código sob determinadas condições quantas vezes forem necessárias. Por se tratar de uma ou mais operações que se repetem, também são chamadas de laços interativos ou loops.
A primeira forma de se utilizar uma estrutura de repetição é com o enquanto, de tal forma que dizemos: “enquanto a condição não for aceita faça tal coisa”. Normalmente a condição está associada a um contador, genericamente em pseudocodigo:
<=numero faca
enquanto contador
bloco<-contador+incremento
contador fimenquanto
Considere o problema em que o usuário fornece um valor inicial, um valor final, um incremento e o programa faz a contagem do valor inicial até o final. Utilizando o enquanto, uma solução é:
"contagem_enquanto"
algoritmo
var:inteiro
i,inicial,final,incremento
inicio
escreval("Digite o valor inicial")
leia(inicial)
escreval("Digite o valor final")
leia(final)
escreval("Digite o incremento")
leia(incremento)
escreval("-------------------------------")
escreval("Irei contar de ",inicial," até ",final," de ",incremento, " em ", incremento.)
escreval("-------------------------------")
<-inicial
i
<=final faca
enquanto iescreval(i)
<-i+incremento
i
fimenquantoescreval("Fim do laço.")
fimalgoritmo
Melhorando a solução, podemos fazer com que o algoritmo detecte se o valor incial é menor ou maior que o final e realizar uma contagem progressiva ou regressiva:
"contagem_enquanto"
algoritmo
var:inteiro
i,inicial,final,incremento,soma
inicio
escreval("Digite o valor inicial")
leia(inicial)
escreval("Digite o valor final")
leia(final)
escreval("Digite o incremento")
leia(incremento)
escreval("-------------------------------")
escreval("Irei contar de ",inicial," até ",final," de ",incremento, " em ", incremento.)
escreval("-------------------------------")
<-0
soma
>inicial entao
se finalescreval("Contagem progressiva detectada.")
<-inicial
i
<=final faca
enquanto iescreval(i)
<-soma+i
soma<-i+incremento
i
fimenquantoescreval("A soma dos números é igual a ", soma)
escreval("Fim do laço.")
senaoescreval("Contagem regressiva detectada.")
<-inicial
i
>=final faca
enquanto iescreval(i)
<-soma+i
soma<-i-incremento
i
fimenquantoescreval("A soma dos números é igual a ", soma)
escreval("Fim do laço.")
fimse
fimalgoritmo
Note que para solução deste problema foi necessário utilizar estruturas condicionais e de repetição além de comandos de entrada, saída, operadores aritméticos e atribuições.
A segunda estrutura de repetição é a repita, sua sintaxe é da seguinte forma:
Repita
bloco Ate condição
É uma estrutura extremamente parecida com o enquanto, porém é logicamente inversa. Trata-se de uma estrutura alternativa ao enquanto em que o teste lógico é feito no final da estrutura, e não no começo. Compare:
Para exemplificar, considere o problema em que o usuário fornece um valor e o programa retorna a tabuada deste valor:
"tabuada"
algoritmo
var:inteiro
i,valor
inicioescreval("Qual tabuada você deseja ver?")
leia(valor)
<-0
i
repitaescreval(valor,"x",i,"=",valor*i)
<- i+1
i>10
ate i
fimalgoritmo
Outro exemplo com a estrutura repita, considere que o problema de interesse é calcular o fatorial de um número fornecido pelo usuário e que, ao invés de efetuar a conta e o programa ser encerrado, queremos que o programa pergunte para o usuário se ele deseja ou não continuar, de tal forma que ele vai fornecer outro número, outro fatorial será efetuado e assim por diante, até que o usuário diga que não quer mais efetuar nenhum fatorial. Uma solução possível é:
"fatorial"
Algoritmo
Var:inteiro
n,fatorial,i:caractere
resp
Inicio
repitaescreval("Informe o numero que voce gostaria de obter o fatorial")
leia(n)
<- 1
fatorial
<- n
i
repita<- fatorial*i
fatorial <-i-1
i=1
ate i
escreval(n, "! = ", fatorial)
escreval("Deseja continuar? [s/n]")
leia(resp)
="n"
ate resp
Fimalgoritmo
A última das estruturas de repetição é o para, cuja sintaxe é dada por:
para (variavel) de (inicio) ate (fim) passo (incremento) faca
bloco fimpara
O para é uma das estruturas mais utilizadas e possui uma vantagem sobre as outras duas apresentadas: ela é auto incrementável, isto é, não há necessidade de especificar que uma variável contadora recebe ela mesma mais um incremento, o para faz isso automaticamente o que exige menos código para realização de uma tarefa que exige repetição.
Contudo, é uma estrutura que exige um limite superior, isto é, no para o número de vezes que o loop será executado é fixo. O que não acontece no enquanto e no repita, estruturas nas quais podemos escrever de tal forma que o usuário forneça quantos valores quiser com uma estrutura do tipo:
Inicio
repitaescreval("Deseja continuar? [s/n]")
="n"
ate resp Fimalgoritmo
Veja um algoritmo que conta até 10 utilizando o para:
"conta10_para"
algoritmo
var:inteiro
i
inicio1 ate 10 passo 1 faca
para i de escreval(i)
fimpara fimalgoritmo
Como exemplo mais completo, considere que precisamos escrever um programa que lê quantos valores o usuário quiser, retorna quantos estão entre 0 e 10 e a soma dos ímpares. Uma solução é dada por:
"entre010"
Algoritmo
Var:inteiro
qtd, i, valor, cont, somaimpar
Inicioescreva("Quantos valores vamos analisar?")
leia(qtd)
<- 0
cont <- 0
somaimpar
1 ate qtd faca
para i de escreva("digite o ",i,"º valor")
leia(valor)
se (valor<=10) e (valor>=0) entao
<- cont+1
cont
fimse
se (valor%2<>0) e (valor<=10) e (valor>=0) entao
<- somaimpar+valor
somaimpar
fimse
fimpara
escreval("Existem ", cont, " números entre 0 e 10")
escreval("A soma entre os impares digitados é ", somaimpar)
Fimalgoritmo
Como mencionado anteriormente a lógica de programação é indispensável para quem deseja aprender uma linguagem. Tentar aprender a linguagem antes da lógica ou ambos ao mesmo tempo não está errado, porém gera um problema de generalização, tornando estudar novas linguagens uma tarefa mais árdua.
Por isso, entender comandos, operadores e estruturas é algo salubre para aqueles que trabalham com programação pois, aprendendo estas estruturas com qualidade é infinitamente mais fácil passar para outras linguagens.
As linguagens têm suas peculiaridades, coisas que funcionam em uma, não funcionam em outra; todavia as estruturas gerais sempre estarão lá com uma ou outra diferença sutil de sintaxe.
Sendo assim, uma forma de entender as ferramentas que existem em qualquer linguagem e praticá-las é através do português estruturado (portugol) em aplicativos como o visualg.
Neste material todos os tópicos foram tratados de maneira ampla sem entrar com grandes detalhes nos assuntos ou resolver problemas com nível de dificuldade elevada. Porém lembre-se que programação, tal como matemática ou qualquer outra habilidade, exige prática para que a proficiência seja elevada.
Tópicos não abordados neste post foram vetores, matrizes, funções e procedimentos numa tentativa de tornar o material menos extenso.
Existe uma infinidade de materiais e cursos online a respeito do tema aqui abordado. Uma que gosto muito e considero bastante acessível é a playlist Curso de Lógica de Programação.
Críticas e sugestões a este material sempre serão bem vindas.
Para entrar em contato comigo, envie uma mensagem para lineuacf@gmail.com.