Prévia do material em texto
W
BA
11
50
_V
1.
0
LÓGICA DE PROGRAMAÇÃO
2
Fabiano Gonçalves dos Santos
São Paulo
Platos Soluções Educacionais S.A
2022
LÓGICA DE PROGRAMAÇÃO
1ª edição
3
2022
Platos Soluções Educacionais S.A
Alameda Santos, n° 960 – Cerqueira César
CEP: 01418-002— São Paulo — SP
Homepage: https://www.platosedu.com.br/
Head de Platos Soluções Educacionais S.A
Silvia Rodrigues Cima Bizatto
Conselho Acadêmico
Alessandra Cristina Fahl
Ana Carolina Gulelmo Staut
Camila Turchetti Bacan Gabiatti
Camila Braga de Oliveira Higa
Giani Vendramel de Oliveira
Gislaine Denisale Ferreira
Henrique Salustiano Silva
Mariana Gerardi Mello
Nirse Ruscheinsky Breternitz
Priscila Pereira Silva
Coordenador
Henrique Salustiano Silva
Revisor
Virginia Mara Cardoso
Editorial
Beatriz Meloni Montefusco
Carolina Yaly
Márcia Regina Silva
Paola Andressa Machado Leal
Dados Internacionais de Catalogação na Publicação (CIP)_____________________________________________________________________________
Santos, Fabiano Gonçalves dos
Lógica de programação / Fabiano Gonçalves dos Santos. -
São Paulo: Platos Soluções Educacionais S.A., 2022.
34 p.
ISBN 978-65-5356-362-9
1. Lógica de programação. 2. Algorítmico.
3. Programação estruturada. I. Título.
CDD 005
_____________________________________________________________________________
Evelyn Moraes – CRB 010289/O
S237l
© 2022 por Platos Soluções Educacionais S.A.
Todos os direitos reservados. Nenhuma parte desta publicação poderá ser reproduzida ou
transmitida de qualquer modo ou por qualquer outro meio, eletrônico ou mecânico, incluindo
fotocópia, gravação ou qualquer outro tipo de sistema de armazenamento e transmissão de
informação, sem prévia autorização, por escrito, da Platos Soluções Educacionais S.A.
4
SUMÁRIO
Apresentação da disciplina __________________________________ 05
Estruturas básicas de programação __________________________ 07
Estruturas de controle _______________________________________ 21
Estruturas de dados básicas _________________________________ 36
Modularização de programas ________________________________ 50
LÓGICA DE PROGRAMAÇÃO
5
Apresentação da disciplina
Lógica de programação é uma disciplina muito importante para várias
áreas do conhecimento. Ela é mais direcionada para aqueles que vão, de
alguma forma, criar programas, scripts, macros e outros procedimentos
que serão realizados por uma máquina, mas profissionais de outras
áreas podem se beneficiar dos conceitos que são vistos nesta disciplina.
O objetivo principal deste estudo é apresentar os principais blocos de
construção de algoritmos, seus recursos e o que se pode fazer com eles.
Para isso, você aprenderá sobre os conceitos de variáveis, constantes,
estruturas de controle, estruturas de dados e formas de dividir os
programas para deixar mais bem estruturados e reaproveitáveis.
Com este estudo, você se capaz de expressar soluções que abstrai de
vários problemas do dia a dia e estruturar o seu raciocínio, obtendo uma
visão crítica e sistemática da resolução de problemas.
A disciplina começa introduzindo os fundamentos dos algoritmos,
mostrando o que são variáveis, constantes e tipos de dados. É
importante ressaltar que os conceitos vistos nesta disciplina servirão
de base para qualquer implementação em linguagem de programação
moderna.
O segundo tema envolve uma parte bastante importante, que é o
conhecimento das principais estruturas de controle: as sequenciais, as
de repetição e as de decisão, estruturas que estão presentes em todas
as linguagens de programação existentes.
6
O terceiro tema abrange o básico de uma grande área da ciência da
computação: as estruturas de dados. Por meio do conhecimento dos
arrays e das matrizes, o estudante poderá expandir seu conhecimento e
criar novos tipos de dados para usar em seus algoritmos.
Por fim, no quarto tema, você entrará em contato com os refinamentos
e a decomposição de problemas em partes menores, chamados de
subprogramas (funções e procedimentos) e seus principais assuntos
(recursividade e passagem de parâmetros).
Esta disciplina é bem ampla e abrange os principais tópicos relacionados
aos algoritmos, dando base e fundamento para que você continue os
seus estudos.
Bons estudos!
7
Estruturas básicas de
programação
Autoria: Fabiano Goncalves dos Santos
Leitura crítica: Virgínia Mara Cardoso
Objetivos
• Conhecer as estruturas de dados e tipos de dados.
• Estudar as expressões mais comuns.
• Conhecer a formação de tabelas-verdade.
8
1. Introdução
Conhecer a lógica de programação é o jeito certo de começar seus
estudos na área de programação. Esta é uma disciplina fundamental
para qualquer área da tecnologia. Além disso, a lógica de programação
é uma área que pode, e deve, ser usada principalmente para resolver
problemas e para expressar o seu raciocínio de uma maneira
organizada. Portanto, não serve apenas para futuros programadores.
Engenheiros, analistas financeiros e todos os profissionais que
necessitem com que outra pessoa entenda o seu raciocínio podem usar
a lógica de programação para expressar aquilo que deseja.
Contudo, o que é lógica? Esse é um conceito vasto e que excede nosso
contexto de tecnologia, mas Forbellone e Eberspacher (2005) afirmam
que se trata de uma “correção do pensamento”, ou seja, é uma forma
de determinar quais operações são válidas ou não; quando agimos,
analisando as formas e leis do pensamento, ou, de forma resumida, é
a “arte de bem pensar” ou é a “ciência das formas do pensamento”, de
acordo com Silva (2017).
Você aprenderá que a lógica está intimamente ligada à programação de
computadores, porque se não pensarmos corretamente para resolver
um problema, depois de tê-lo analisado bem e entendido o que deve ser
feito, certamente criaremos um processo automático errado, com vários
tipos de consequências. Além disso, precisamos considerar que um
problema pode ser resolvido de várias maneiras diferentes.
Neste tema, trabalharemos com os conceitos iniciais da área. Uma vez
aprendidos os principais fundamentos desta disciplina, você será capaz
de programar qualquer linguagem de programação ou, até mesmo,
uma máquina, como um torno CNC, um robô, além de criar macros em
planilhas eletrônicas, programar dispositivos de automação e outros.
9
2. Algoritmos
Imagine que você precisa ensinar uma pessoa a fazer alguma tarefa
e, por mais simples que seja, talvez não seja tão fácil assim, por
exemplo, ensinar alguém a “passar um café” pode se tornar uma tarefa
complicada. Como que você poderia escrever no papel os passos para
passar um café usando um coador de papel? Vamos tentar! Os números
indicam os passos de cada etapa.
1. Pegue um coador de papel.
2. Coloque duas colheres de café dentro do coador.
3. Esquente meio litro de água e não deixe ferver.
4. Um pouco antes de ferver, jogue a água no coador com café.
Basicamente é isso, concorda? No entanto, existem várias etapas
intermediárias as quais uma pessoa que nunca fez café pode se perder
ou se queimar.
Um algoritmo, segundo Souza (2019), é uma sequência de passos
que tem como objetivo atingir um objetivo definido, mas, para isso
precisamos pensar com uma certa ordem e, nesse momento, é que
entra a lógica. Lembre-se, a lógica está relacionada à forma com que
organizamos nosso pensamento. Logo, se organizamos corretamente
nosso pensamento para resolver um problema, somos capazes de criar
um algoritmo que resolva o problema em questão.
Outros autores, como Forbellone e Eberspacher (2005), dizem que
algoritmo é uma sequência finita de comandos executáveis que tem
como objetivo solucionar um determinado problema. Já para Alves
(2014), trata-se de um conjunto de comandos que devem ser seguidos
por um computador para realizar cálculos ou outras operações de
resolução de problemas. Se você procurar outros autores, você notará
que a definição não é muito diferente dessas.
10
No caso do café, cada pessoa prepara de uma forma diferente, mashá um certo consenso a respeito das etapas que devem ser seguidas
para ter um bom café. Por exemplo: em primeiro lugar, precisamos
colocar o coador em um suporte para que ele não caia; depois, temos
que despejar a água devagar no coador enquanto evitamos que ela
transborde; entre outros passos.
Observe que, se você seguir à risca as instruções dadas até aqui, você
fará o café com água fria! Então, para criar um algoritmo precisamos
pensar com clareza e ordem.
O algoritmo serve para você expressar corretamente o seu raciocínio.
E é por isso que ele é tão importante nas nossas vidas, pois, como você
pode perceber, não se limita apenas a programar computadores.
O ato de expressar o raciocínio no papel pode ser feito de várias
formas. Por exemplo, uma receita de bolo é um texto corrido e de
fácil entendimento. No nosso caso, utilizaremos um recurso chamado
pseudocódigo para expressar um algoritmo e usaremos uma linguagem
de pseudocódigo, chamada Portugol, para padronizar nosso estudo. Ela
é bem fácil de entender e usar, sendo uma forma bastante usada nas
empresas para expressar raciocínios e ideias.
Para testar os exemplos apresentados, use o Portugol Studio, que é uma
ferramenta muito interessante para praticar e que roda em qualquer
navegador conectado à internet, podendo ser usada livremente.
A Figura 1 mostra o Portugol Studio em execução. Observe o link que
você pode acessar para usá-lo.
11
Figura 1 – Portugol Studio
Fonte: captura de tela Portugol Studio.
3. Variáveis e tipos primitivos
Suponha que você é um professor que gostaria de criar uma planilha ou
programa para controlar quais alunos foram aprovados e reprovados
em sua disciplina.
Para isso, você provavelmente construiria uma tabela com os seguintes
dados em cada coluna: nome do aluno, nota da primeira prova, nota da
segunda prova e média. Se a média for maior do que cinco e o aluno
tiver mais do que 75% de presença nas aulas, ele estará aprovado; se for
diferente disso, ele estará reprovado.
12
Nesta escola, as notas das provas não podem ser “quebradas” (em
decimais), só podem ser notas “cheias”, como 5, 8 ou 10, ou seja,
números inteiros.
Porém, uma média aritmética pode gerar um número decimal, mesmo
que seus operandos sejam inteiros, então, temos algumas situações
para considerar. Na Tabela 1 temos a representação de como seria a
planilha do professor.
Tabela 1 – Representação do diário de classe do professor
Fonte: elaborada pelo autor.
Na célula B2, que contém a nota 1 do aluno Adriano, temos um número,
a nota “2” que ele obteve. A escola limitou que as notas não poderiam
ser decimais. Logo, o valor da Nota 1 e Nota 2 devem ser o que
chamamos de tipos inteiros, ou seja, números, não podem ser letras ou
caracteres especiais, como “*”, “&” ou outros, sendo obrigatoriamente
números sem casas decimais.
O nome do aluno, por sua vez, não deve conter números. É bem
difícil que uma pessoa tenha um número no nome, portanto,
vamos considerar que os nomes dos alunos devem ser formados
obrigatoriamente por caracteres alfabéticos, assim como o status de
cada aluno.
13
Já a média é diferente, devendo ser um número decimal, porque, como
podemos perceber, temos valores que podem ser decimais, ou não, mas
temos que considerar sempre o “pior” caso.
Até aqui, você teve contato com os conceitos de tipos primitivos: inteiros,
decimais e caracteres. Xavier (2017) diz que a partir dos tipos primitivos
são formados quaisquer tipos de dados.
Os principais tipos primitivos são:
• Inteiros: números pertencentes ao conjunto dos números inteiros,
incluindo os números negativos e o zero. No exemplo do diário,
trata-se das notas parciais.
• Caracteres, ou chamados também de Strings: qualquer tipo
de caractere que você tem no seu teclado, como os nomes dos
alunos.
• Reais: compostos pelos números com pontos flutuantes, ou
racionais, incluindo negativos. No exemplo do diário, trata-se dos
valores das médias dos alunos.
• Valores lógicos, ou booleanos, compostos apenas por dois
valores: verdadeiro ou falso. No exemplo do diário de classe, o
status final do aluno pode ser considerado booleano, pois ele está
aprovado ou reprovado, não existe um estado intermediário.
Observe, na Tabela 2, como os tipos são aplicados ao controle de notas
exemplificado.
14
Tabela 2 – Controle de notas com os tipos
Fonte: elaborada pelo autor.
Cada tipo primitivo pode derivar dezenas de tipos diferentes que são
utilizados nas linguagens de programação. Neste estudo, você usará
apenas os quatro tipos apresentados, que são mais do que suficientes
para os casos aqui exemplificados.
De volta ao exemplo do diário de classe do professor, observe em cada
linha e note que: para cada aluno temos: nota 1, nota 2, média, presença
e status. Você concorda que o valor de cada uma dessas colunas varia
entre cada linha? Ou seja, a palavra “aluno” pode conter valores variáveis
que, no exemplo, são “Adriano”, “Bianca”, “Carlos”, “Daniela”, “Eliane” e
“Fabiano”, podendo ter até mais alunos do que apenas os expostos.
Uma variável é, portanto, como um local que guardará um valor
momentaneamente até que outro valor seja colocado no seu lugar. Por
exemplo, a sua idade, hoje você pode ter 30 anos, mas, no ano que vem,
esse valor dá lugar para o 31 e assim por diante.
15
Toda variável tem um tipo (inteiro, decimal, string etc.) e um
identificador. No caso dos nomes dos alunos, temos uma variável
chamada “Aluno” do tipo “String” (ou caractere).
Já para as médias, teremos a variável “Média” de tipo decimal, e assim
por diante.
Na prática, a variável é uma porção de memória que guardará um
valor até que o computador seja desligado. Segundo Souza (2019), uma
variável é algo que varia ou pode sofrer variação, instável, inconstante
e sujeito a alterações. Forbellone e Eberspacher (2005) conceituam que
uma variável é algo que tem a possibilidade de ser alterado em algum
instante do tempo.
Em algumas situações especiais, o valor não mudará ao longo da
execução do algoritmo, assim temos uma variável imutável ou uma
constante (ALVES, 2014).
4. Expressões
Nas linguagens de programação e nos algoritmos, é possível construir
uma grande variedade de expressões, entre elas, a expressão
mais conhecida é a expressão matemática, com seus operandos e
operadores.
Os operadores das expressões aritméticas são mostrados no quadro a
seguir.
Quadro 1 – Operadores matemáticos
Operador Função Exemplo
+ Adição 1 + 1
- Subtração 3 – 2
16
* Multiplicação 4,5 * 8
/ Divisão 9 / 3
Fonte: elaborado pelo autor.
A depender da linguagem de programação a ser aprendida
posteriormente, outros operadores podem aparecer, como os
operadores que nos dão o resto de uma divisão, operadores para
exponenciação, radiciação e outros.
Para expressões mais complexas, pode-se usar parênteses para priorizar
as operações intermediárias.
Para expressões mais complexas, pode-se usar parênteses para priorizar
as operações intermediárias.Além das expressões aritméticas, temos
um tipo de expressão muito importante para a lógica de programação,
as chamadas expressões lógicas, que tem esse nome porque usam
operadores relacionais e operandos que são relações, variáveis ou
constantes do tipo lógica (FORBELLONE; EBERSPACHER, 2005).
No exemplo do diário de classe, um aluno é considerado aprovado
se tiver média aritmética maior ou igual a cinco e presença igual ou
superior a 75% das aulas dadas; qualquer outra combinação diferente
dessa condição fará com que o aluno seja reprovado.
Os operadores relacionais serão utilizados são mostrados no quadro a
seguir.
Quadro 2 – Operadores relacionais
Operador Função Exemplos
= Igual a 1 = 1, x = x
> Maior que 3 > 2, x > y
>= Maior ou igual a 3 >= 2, x >= y
< Menor que 2 < 3, x < y
17
<= Menor ou igual a 2 <= 3, x <= y
<> Diferente de 2 <> 3, x <> y
Fonte: elaborado pelo autor.
Para entender um pouco mais sobre as expressões lógicas, é importante
conhecer as tabelas-verdade.Elas compõem todo o conjunto de
possibilidades combinatórias que existem entre os valores lógicos
V (verdadeiro) ou F (falso) e os operadores lógicos. A seguir, temos
algumas tabelas-verdade envolvendo os operadores e as expressões
lógicas.
O Quadro 3 apresenta o funcionamento do operador de negação, em
que sua funcionalidade é apenas negar o operando. Nesse quadro é
possível perceber que, quando o operador “A” for “falso”, sua negação
será “verdadeira” e vice-versa.
Quadro 3 – Operação de negação
A não A
Falso Verdadeiro
Verdadeiro Falso
Fonte: elaborado pelo autor.
O Quadro 4 mostra o funcionamento do operador de conjunção (E ou
AND). Para que a expressão seja verdadeira por completo, todos os seus
operandos devem ser, obrigatoriamente, verdadeiros.
Quadro 4 – Operador de conjunção (e)
A B A e B
Verdadeiro Verdadeiro Verdadeiro
Verdadeiro Falso Falso
Falso Verdadeiro Falso
Falso Falso Falso
Fonte: elaborado pelo autor.
18
O Quadro 5 mostra o operador de disjunção não exclusiva. Apesar
do nome complexo, ele perfaz a função do “ou”, em que para que a
expressão lógica seja verdadeira por completo ao menos um de seus
operandos precisa ser verdadeiro.
Quadro 5 – Operador de disjunção não exclusiva (ou)
A B A ou B
Verdadeiro Verdadeiro Verdadeiro
Verdadeiro Falso Verdadeiro
Falso Verdadeiro Verdadeiro
Falso Falso Falso
Fonte: elaborado pelo autor.
A seguir, analise alguns exemplos envolvendo as tabelas-verdade
anteriores.
Exemplo 1: se fizer sol e estiver calor, eu vou para a praia. Quando eu
vou à praia?
Figura 2 – Exemplo do operador E
Fonte: elaborada pelo autor.
Nesse exemplo, observe o operador “E” que conecta as duas partes
da frase. Como a Figura 2 apresenta, você irá para a praia somente se
estiver sol “e” estiver calor. Se estiver sol, mas estiver frio, você não irá.
Isso é diferente de dizer: se fizer sol ou estiver calor, eu vou para a praia.
Nesse caso, você irá para a praia em qualquer uma das condições, ou
seja, se estiver sol, mas estiver frio, você irá para a praia.
Agora, veja um exemplo mais numérico e com mais “cara” de
programação.
19
Exemplo 2: verifique se a expressão “3<6 E 16/4 = 4” é verdadeira ou
falsa. Temos duas partes nessa expressão, observe o quadro a seguir.
Quadro 6 – Exemplo de expressão lógica
Parte 1 Operador lógico Parte 2
3 < 6 E 16/4 = 4
V E 4 = 4
V E V
V
Fonte: elaborado pelo autor.
Existem inúmeras formas de compor expressões lógicas. Elas aparecem
em programas de computadores, macros, algoritmos e qualquer
assunto envolvendo lógica de programação, portanto, estude mais sobre
o assunto e pratique bastante para obter o pleno entendimento sobre as
possibilidades e as combinações que podem ser feitas para criar essas
expressões e seus futuros programas e algoritmos.
5. Considerações finais
Neste tema, você teve uma breve introdução à disciplina de Lógica
de Programação, em que procuramos, de maneira sucinta e direta,
introduzir os principais elementos que iniciam qualquer estudante no
mundo da programação e da elaboração de algoritmos.
Referências
ALVES, William. Linguagem e lógica de programação. São Paulo: Érica, 2014.
FORBELLONE, André Luiz Villar; EBERSPACHER; Henri Frederico. Lógica de
programação: a construção de algoritmos e estruturas de dados. São Paulo:
Prentice Hall, 2005.
20
SILVA, Flávio. Lógica para computação. São Paulo: Cengage Learning, 2017.
SOUZA, Marco. Algoritmos e lógica de programação: um texto introdutório para
engenharia. São Paulo: Cengage Learning, 2019.
21
Estruturas de controle
Autoria: Fabiano Goncalves dos Santos
Leitura crítica: Virgínia Mara Cardoso
Objetivos
• Fazer entradas pelo usuário e saídas na tela.
• Conhecer as estruturas sequenciais.
• Conhecer as estruturas de decisão.
• Conhecer as estruturas de repetição.
22
1. Entradas pelo teclado e saídas em tela
Neste tema, você estudará alguns pontos fundamentais na elaboração
de praticamente todos os algoritmos que você desenvolverá, sendo
capaz de escrever seus primeiros algoritmos.
Você aprenderá a mostrar informações na tela, coletar os dados que o
usuário digita por meio do teclado e aprender as principais estruturas
de controle de programa, as quais podem ser usadas em qualquer
algoritmo e linguagem de programação posteriormente.
Inicialmente, mostraremos como fazer a entrada e a saída de dados,
também conhecido por E/S ou I/O (Input/Output).
Basicamente, todo algoritmo funciona conforme a Figura 1, em que
temos uma entrada de dados, o processamento deles e a saída de
dados.
Figura 1 – Funcionamento de um algoritmo
Fonte: elaborada pelo autor.
A entrada de dados pode ser feita de várias maneiras: digitação pelo
teclado, leitura de scanner, reconhecimento biométrico ou voz, enfim,
conforme a tecnologia atual, temos muitas possibilidades. Neste estudo,
utilizaremos a digitação pelo teclado.
O processamento é o que o algoritmo realizará para processar a
entrada. Ele pode ser uma conta simples, como o cálculo de uma folha
23
de pagamento de uma empresa, verificação de senha, enfim, inúmeras
possibilidades que estão relacionadas ao objetivo do algoritmo.
Já a saída de dados será o resultado do processamento. Por exemplo,
uma mensagem na tela do seu dispositivo, um som, um acionamento de
um mecanismo externo, luz, entre outras possibilidades. Neste tema, as
saídas serão na tela do dispositivo.
Portanto, para resumir, um algoritmo apresentará esses três elementos.
Suponha que você queira desenvolver um algoritmo que calcule os
juros de um empréstimo que você fez junto ao banco. Para iniciar, é
importante saber que existe uma fórmula para calcular juros simples:
F = P * (1 + n * i)
Em: F é o montante final; P é o principal; n é o período (dias, meses); e i é
a taxa.
Trata-se de uma conta bem simples, em que se deve ter o valor das
variáveis e fazer a conta conforme a fórmula. E se for necessário
fazer o cálculo novamente e várias vezes seguidas? Você percebe que
também podemos ter um número variável de execução desse processo/
algoritmo?
Isto é, não se pode fixar valores para as variáveis. O legal é variar o
período, a taxa ou, até mesmo, o aporte inicial a cada execução do
algoritmo. Então, devemos pensar também no tipo que essas variáveis
terão:
• n é um valor inteiro, pois, expressará o período que se deseja
calcular os juros. O período pode ser em dias, meses ou anos.
Então, se quisermos fazer a conta para 1,5 ano, é melhor usar 18
meses.
24
• P e i podem ser valores decimais, pois, nesse caso, é bem provável
que tenhamos um valor com casas decimais, principalmente na
taxa de juros.
Assim, podemos convencionar que sempre que quisermos ler alguma
informação do usuário precisamos:
1. Criar uma variável adequada para o que precisamos, com um tipo
e um identificador.
2. Usar o comando leia() para fazer a leitura dos dados.
Por exemplo, observe o algoritmo a seguir, escrito em uma linguagem
chamada Portugol. Caso você deseje, ele pode ser executado por meio
do software Portugol Webstudio e incentivamos que você acesse o site e
reproduza-o para praticar.
Porém, não digite os números no início de cada linha, eles servem
apenas didaticamente para indicar o número da linha.
1 programa {
2 funcao inicio() {
3 inteiro n
4 real P,i, F
5 escreva(“Digite o aporte inicial, o período e a taxa: \n”)
6 leia(P,n,i)
7 F = P * (1 + n*i)
8 escreva(“O valor dos juros no final do período é: “,F)
9 }
10 }
25
É importante saber que os algoritmos podem ser escritos de várias
formas, por exemplo, a maneira mais natural é escrevê-los como
ocorre nas receitas culinárias. Já a maneira mais técnica é usando uma
linguagem de programação.
Segundo Fernandes e Fernandes (2014), existe uma maneira
intermediária, chamada pseudocódigo, que é a forma computacional de
representar um algoritmo, como foi mostrado no exemplo anterior.
Além disso, o pseudocódigo usa uma sintaxe específica, como foi
mostrado, e deve ser respeitadapara o algoritmo ser executado
corretamente. Essa sintaxe faz parte da linguagem Portugol, pois usa
comandos em português para criar os algoritmos.
Os programas que executam os algoritmos em uma linguagem de
programação são chamados de compiladores, os quais basicamente
executam os comandos que escrevemos, portanto, precisamos escrevê-
los corretamente. De acordo com Meio e Silva (2003), um compilador
traduz uma linguagem de alto nível para um código em linguagem de
máquina para ser executado. Não faz parte do nosso escopo entrar
em detalhes sobre os compiladores, mas é uma sugestão para você
continuar suas pesquisas. Por enquanto, deixe de lado as linhas 1, 2, 11
e 12, que serão tratadas mais adiante.
Na linha 3 criamos uma variável do tipo inteiro com o identificador “n”.
Ela vai armazenar o período que desejamos calcular os juros.
Os espaços que existem nas linhas 2, 3 a 7, 8 e 9 são chamados de
indentações e servem, nesse caso, apenas para organizar visual e
estruturalmente o algoritmo. Por essa ótica, é possível saber quais
instruções estão abaixo de outras. É uma boa prática indentar o código.
Além disso, existem linguagens de programação, como o Python, em
que a indentação é obrigatória.
26
Já falamos da declaração das variáveis na linha 3. No Portugol, declarar
variáveis é obrigatório para que elas sejam usadas depois.
Na linha 4 declaramos as outras variáveis que serão utilizadas no
algoritmo e explicamos anteriormente o objetivo de cada uma delas.
Lembre-se, você pode escolher o nome (identificador) que quiser para
suas variáveis.
A primeira leitura de dados é feita na linha 6, em que utilizamos o
comando leia() e colocamos dentro dos parênteses as variáveis que
desejamos que o algoritmo leia. Assim, criamos nossa primeira entrada
de dados.
A linha 7 faz o processamento dos dados de entradas e calcula o valor
dos juros dentro do período, de acordo com a taxa e o montante inicial.
Já a saída de dados no algoritmo é feita na linha 8, por meio do comando
escreva(). Veja a figura a seguir.
Figura 2 – Saída de dados
Fonte: elaborada pelo autor.
O que estiver dentro dos parênteses e dentro das aspas duplas será
mostrado na tela. Nesse algoritmo, o objetivo é mostrar uma frase
amigável para o usuário, note que essa frase é composta por uma
parte fixa, ou seja, as palavras que formam a frase, combinada com o
resultado da conta da linha 7, e ainda queremos que, ao final da frase, o
cursor passe para a linha de baixo, como uma nova linha.
Para combinar as palavras com o resultado da conta, separa-se as frases
que desejamos dentro das aspas, com vírgulas, e inserimos a variável
27
que representa a conta. Volte a linha 7 do algoritmo para entender
melhor.
O “\n” inserido no final da linha representa um comando especial que faz
com que o cursor se desloque para a linha seguinte, o “n” significa new
line. O ato de combinar textos e variáveis para formar uma saída só é
chamado de concatenação.
Anteriormente, citamos o que é pseudocódigo e Portugol. Nossos
exemplos em Portugol terão a estrutura mostrada na figura a seguir.
Figura 3 – Estrutura dos algoritmos em pseudocódigo/Portugol
Fonte: elaborada pelo autor.
Todo algoritmo é iniciado com o comando programa e seguido por “{“.
Note que, todo “{“ (abre chave) tem o seu correspondente “}” (fecha
chave), mesmo que ele esteja localizado várias linhas depois. Na lógica
de programação, é obrigatório fechar tudo o que se abre, seja chaves “{“
e “}”, colchetes “[“ e “]”, parênteses “(“ e “)”, aspas simples, duplas etc.
No caso das chaves em Portugol, tudo que está entre o “{“ e o “}” é
chamado de bloco. Portanto, os algoritmos terão dois blocos: o bloco do
comando programa e o bloco da função “inicio” (sem acento, pois não se
deve acentuar nomes de variáveis e outras palavra em Portugol), que é
obrigatório e é onde será inserido o bloco de programação principal.
28
Algumas palavras como “programa”, “funcao”, “leia” e “escreva” não
podem ser usadas como identificadores de variáveis.
Dentro do bloco “programa”, podemos criar a função onde vamos digitar
o código principal do algoritmo. Essa função tem como nome “inicio” e
é obrigatória para que o compilador saiba por onde ele deve começar a
executar o programa. Posteriormente, você estudará sobre as funções.
O código principal é inserido dentro do bloco da função “inicio”. Toda
função possui um par de parênteses, entre os quais se pode ou não
conter elementos. Nesse caso, não é necessário.
2. Estruturas sequenciais
Observe novamente o programa utilizado como exemplo. Perceba que,
ele tem uma sequência de ações lineares, uma após a outra, nas linhas
de 3 a 7.
Então, o algoritmo é executado nessa sequência, desde a linha 1 até a 9.
As linhas 3 a 7 são mais claras para perceber que existe uma sequência
no algoritmo, mas o algoritmo todo é uma sequência e o compilador irá
executá-lo linha a linha.
Assim, temos a primeira estrutura de programação: a estrutura
sequencial.
3. Estruturas de decisão
Em diversas situações, durante a sequência de ações em um algoritmo, é
muito comum que seja necessário tomar alguma decisão ou fazer algum
tipo de desvio no fluxo principal do algoritmo ou, até mesmo, tratar
29
uma variável. Por exemplo, suponha que para aprovar um aluno em
uma disciplina, ele precise cumprir duas condições principais: ter média
maior ou igual a 5 e ter mais de 75% de presença nas aulas. Perceba
que, na condição, usamos uma expressão relacional, em que temos
operadores relacionais. Isso é obrigatório nas estruturas de decisão.
A fim de entender melhor esse conceito, observe o exemplo do seguinte
programa:
1 programa {
2 funcao inicio()
3 {
4 inteiro n1, n2, presenca
5 real media
6 escreva(“Digite a primeira nota do aluno\n”)
7 leia(n1)
8 escreva(“Digite a segunda nota do aluno\n”)
9 leia(n2)
10 escreva(“Qual a porcentagem de presenca?\n”)
11 leia(presenca)
12 media = (n1+n2)/2
13 se (media>=5 e presenca>=75)
14 {
15 escreva(“Aprovado”)
16 }
30
17 senao
18 {
19 escreva(“Reprovado”)
20 }
21 }
22 }
As linhas de 1 a 11 são sequenciais e de fácil entendimento. Na linha
1 iniciamos o programa; na linha 2 criamos a função principal; na
linha 4 declaramos as variáveis inteiras que serão utilizadas; na linha 5
declaramos outra variável, mas agora do tipo real, pois a média é um
número que pode ser decimal e assim por diante; até a linha 13 não
temos muitas novidades.
Na linha 13 aparece um detalhe. O cálculo da média do aluno foi feito
na linha 12 e precisamos avaliar se a média é maior ou igual a 5 para ele
ser aprovado; além disso, a porcentagem de presença foi lida na linha
10. Estamos considerando que as notas e as presenças foram digitadas
corretamente e não estamos preocupados, nesse momento, com a
validação da entrada de dados, ou seja, consideramos que o usuário não
vai errar as entradas.
A linha 13 usa o comando “se” para verificar a condição do aluno
ter média maior do que 5 e mais do que 75% de presença. Agora,
precisamos do conhecimento das expressões lógicas, perceba que
temos duas partes para ser avaliadas: media>=5 e presença>=75. Essa
condição só será verdadeira se ambas as partes forem verdadeiras.
Se a condição for verdadeira, tudo que estiver dentro do bloco abaixo do
“se” será executado. É possível criar blocos dentro de blocos, nesse caso,
31
temos um (linhas 14 a 16), mas em vários algoritmos você verá que é
necessário criar blocos dentro de blocos.
E se a condição não for verdadeira? O compilador, após avaliar a
condição da linha 13, entra na linha 17, onde vai executar o bloco do
comando “senao” nas linhas 18 a 20.
Então, conforme Forbellone e Eberspacher (2005), dois tipos de
estruturas de decisão: simples e composta, conforme a Figura 4.
Lembre-se, você pode encadear as estruturas que está aprendendo, ou
seja, colocar uma dentro da outra.
Figura 4 – Tipos de estruturas de decisãoFonte: elaborada pelo autor.
Logo, a essa é a estrutura condicional, muito usada na grande maioria
dos algoritmos e dos softwares utilizados no dia a dia.
4. Estruturas de repetição
As estruturas de repetição também é muito usada em qualquer tipo de
algoritmo. Não é possível imaginar algum software atual que não use
uma estrutura como essa, que serve para repetir blocos de comandos.
32
Existem algumas formas de montar as estruturas de repetição, como:
• Quando você sabe o número de vezes que o bloco de comando
será repetido. Por exemplo, no ano temos 12 meses, então, em
um algoritmo que calcula a média dos juros da poupança durante
o ano, a soma cumulativa para depois dividir pela quantidade de
meses será repetida por um número conhecido, 12.
• Quando você não sabe quantas vezes o bloco irá repetir. Nesse
caso, deve-se pensar em uma condição de repetição, caso
contrário, a repetição irá ser executada infinitamente, o que é
chamado de loop infinito. Aliás, as repetições podem ser chamadas
também de loop.
Voltando ao exemplo do programa da média do aluno, o algoritmo
só poderá ser executado para um aluno, mas e se o professor tiver
20 alunos? Nesse caso, temos que encontrar um jeito de repetir o
algoritmo.
Há várias formas de montar esse algoritmo, no entanto, podemos
simplificar criando uma variável para contar o número de repetições,
essa variável tem o criativo nome de “contador”. Observe o exemplo:
1 programa {
2 funcao inicio() {
3 inteiro n1, n2, contador
4 real media, media_final, acumula
5 contador = 1
6 acumula = 0.0
7 enquanto (contador<=20)
8 {
9 escreva(“Aluno “, contador,”–Digite a nota 1: “)
33
10 leia(n1)
11 escreva(“Aluno “, contador,”–Digite a nota 2: “)
12 leia(n2)
13 escreva(media)
14 acumula = acumula + media
15 contador = contador+1
16 }
17 media_final = acumula/5
18 escreva(“Média da classe = “, media_final)
19 }
20 }
Nesse algoritmo, temos duas variáveis importantes sendo declaradas
nas linhas 3 e 4: a variável “contador” e a variável “acumula”, a qual vai
acumular as médias parciais de cada aluno, na linha 14. O algoritmo
calcula a média de cada aluno e, depois, quando sair do loop, calcula a
média global dos alunos.
Observe atentamente a linha 7 e perceba que ela usa o comando
“enquanto” e coloca uma condição para que a repetição ocorra. É
fundamental que você inicialize a variável “contador” antes disso,
caso contrário, a repetição não será iniciada. Não é possível que uma
repetição seja iniciada sem que a variável de controle esteja declarada e
inicializada.
Do mesmo modo que é preciso iniciar uma repetição, ela também
deve ser parada. Então, sempre coloque uma condição de parada. No
exemplo, isso ocorre na linha 15, onde incrementamos em 1 a variável
“contador”.
34
O bloco de repetição termina no “}”, na linha 16, e o compilador, ao
chegar nesse ponto, faz com que a execução volte para a condição ser
avaliada novamente na linha 7. Como o “contador” estará incrementado,
dependendo do valor do contador e do resultado da expressão
relacional da condição, o bloco será executado novamente ou não.
Desse modo, quando a condição não é mais satisfeita, a execução pula
imediatamente para a linha posterior ao bloco, no exemplo, a linha 17, e
segue em frente até o final do algoritmo.
Lembre-se, esse é um exemplo para fins didáticos. Na realidade, você
terá e criará repetições bem mais complexas do que essa, como o
processo de cálculo de uma folha de pagamento, em que repetições são
muito utilizadas.
Com isso, você estudou as três principais e fundamentais estruturas
de controle que qualquer linguagem de programação moderna possui.
Bons estudos!
Referências
FERNANDES, Nidia Mara Melchiades Castelli; FERNANDES, Wagner Luiz. Lógica de
programação: pseudocódigo. Joinville: Clube de Autores, 2014.
FORBELLONE, André Luiz Villar; EBERSPACHER, Henri Frederico. Lógica de
programação: a construção de algoritmos e estruturas de dados. São Paulo:
Prentice Hall, 2005.
GUEDES, Sérgio (org.). Lógica de programação algorítmica. São Paulo: Pearson,
2014.
MEIO, Ana Cristina; SILVA, Flávio Soares Corrêa da. Princípios de linguagem de
programação. São Paulo: Blucher, 2003.
https://www.amazon.com.br/s/ref=dp_byline_sr_book_2?ie=UTF8&field-author=Fl%C3%A1vio+Soares+Corr%C3%AAa+da+Silva&text=Fl%C3%A1vio+Soares+Corr%C3%AAa+da+Silva&sort=relevancerank&search-alias=stripbooks
35
Estruturas de dados básicas
Autoria: Fabiano Goncalves dos Santos
Leitura crítica: Virgínia Mara Cardoso
Objetivos
• Conhecer as estruturas de dados homogêneas:
vetores e matrizes.
• Estudar as estruturas de dados heterogêneas:
registros.
• Manipular cadeias de caracteres.
36
1. Estruturas de dados homogêneas
Neste tema, você terá contato com alguns recursos usados nos
algoritmos, principalmente nas linguagens de programação, chamados
de estruturas de dados, e seus principais tipos básicos. As estruturas
de dados fazem parte de uma vasta área da Ciência da Computação,
aqui, você estudará as estruturas de dados mais básicas e que auxiliam
os algoritmos.
Como visto anteriormente, para armazenar valores de salário,
temperatura, direção etc., utilizaremos um tipo primitivo como inteiro,
caractere, booleano, entre outros. Em alguns casos, você pode precisar
armazenar um conjunto de informações como uma lista de alunos,
endereços, funcionários e não é possível criar essa lista com uma
variável simples. Nesse caso, temos que usar as estruturas de dados
que, de acordo com Forbellone e Eberspacher (2005), trata-se da criação
de novos tipos de dados, construídos a partir de tipos primitivos e que
são organizados sob um determinado identificador, criando novos tipos
de dados de acordo com o que for necessário.
A primeira estrutura de dados que será estudada é chamada de vetor,
matriz ou array. Você deve lembrar das matrizes aprendidas na matéria
de Matemática, do Ensino Médio. Lembre-se, na escola, você deve ter
estudado matrizes de duas dimensões, entretanto, neste estudo, vamos
focar nas matrizes de apenas uma dimensão.
A Figura 1 mostra uma representação genérica de uma matriz com
m linhas e n colunas, ou seja, duas dimensões. Para uma dimensão,
deve-se considerar a representação de apenas uma linha ou uma
coluna. Por ser de uma dimensão, dizemos que se trata de um vetor
unidimensional.
37
Figura 1 – Exemplo de uma matriz
Fonte: https://pt.wikipedia.org/wiki/Matriz_%28matem%C3%A1tica%29#/media/
Ficheiro:Matriz_organizacao.png. Acesso em: 30 set. 2022.
O array pode armazenar uma coleção sequencial de tamanho fixo de
elementos do mesmo tipo, observe a Figura 2.
Figura 2 – Exemplo de um array
Fonte: elaborada pelo autor.
A Figura 2 mostra um array chamado conjunto, com 9 posições ou
elementos, indexadas de 0 a 9, cujos valores são somente números
inteiros, por isso é classificado como homogêneo. Não é possível
misturar variáveis de tipos diferentes nessa estrutura.
O identificador pode ser qualquer um válido, ele obedece às mesmas
regras usadas para nomear variáveis.
https://pt.wikipedia.org/wiki/Matriz_%28matem%C3%A1tica%29#/media/Ficheiro:Matriz_organizacao.png
https://pt.wikipedia.org/wiki/Matriz_%28matem%C3%A1tica%29#/media/Ficheiro:Matriz_organizacao.png
38
Outro detalhe é que a estrutura é indexada, o que significa que para
acessar um determinado valor, como o 84 mostrado na Figura 2, temos
que usar o índice da seguinte forma:
conjunto[4] = 84
Para acessar os valores da estrutura, precisamos usar o nome da
estrutura mais o índice dentro de colchetes.
Note que os índices vão de 0 a 8, logo, se você contar cada elemento,
teremos 9 elementos na estrutura. Na maioria das linguagens de
programação é usual começar os arrays com 0 em vez de 1.
Portanto, para o array conjunto mostrado na Figura 1, temos:
conjunto[0] = 2, conjunto[1] = 33, conjunto[3] = 12, ..., conjunto[8] = 99
Na prática, um array ocupará posições contíguas na memóriado
computador, logo, ele é finito, de tamanho fixo. O endereço (índice) mais
baixo corresponde ao primeiro elemento e o endereço mais alto ao
último elemento.
1.1 Declarando e inicializando arrays
Como dito anteriormente, para declarar um array precisamos usar a
seguinte sintaxe:
tipo identificador [tamanho do array]
Exemplos:
1. int meses[12]
2. caracter vogal[5] = [‘a’,’e’,’i’,’o’,’u’]
39
Observe que, no segundo exemplo, além de criar e declarar o array, o
inicializamos com os valores desejados.
No primeiro exemplo, o array estará reservado com as 12 posições,
porém estará vazio. Para atribuir os valores aos seus índices, podemos
fazer:
meses[0] = 1 lembre-se que essas estruturas sempre começam
com o índice 0.
meses[1] = 2
Um detalhe importante é que é natural atribuirmos os valores aos
índices sequencialmente, mas você pode atribuir conforme julgar
necessário e de acordo com a situação que o algoritmo exigir.
Um array não precisa ter seus valores ordenados, pois é o índice que
se preocupa com esse detalhe. Existem algoritmos específicos que
ordenam as estruturas de dados de maneiras diferentes da utilizada
aqui.
1.2 Manipulando arrays unidimensionais
Para exemplificar o que pode ser feito com arrays, considere o seguinte
array chamado “a”, de inteiros, com 10 posições:
int a[10] = [2,6,8,3,10,9,1,21,33,14]
int x=2, y=4
a 0 1 2 3 4 5 6 7 8 9
2 6 8 3 10 9 1 21 33 14
Com ele, é possível fazer várias operações:
40
a[x+1] como x=2, temos a[3], que contém atualmente o valor 3.
a[x+ y ] como x=2 e y=4, temos a[6], que contém o valor 1.
a[a[2] ] a[2] contém 8, logo, a[8] é a posição onde 33 está contido.
a[a[1] * a[4] ] a[1] contém 6 e a[4] contém 10, logo, a [ 6 * 4 ] = Erro!
Pois não temos nesse array, o índice 24. Nesse caso, o erro é chamado
em muitas linguagens de programação como Index out of bounds (índice
fora dos limites), ou seja, não existe.
2. Estruturas de dados multidimensionais:
matrizes
Tendo conhecimento de como os arrays unidimensionais se comportam,
saiba que os multidimensionais são bem parecidos, porém, com a
inserção de mais uma dimensão.
A seguir, você estudará os arrays de duas dimensões. É possível
trabalhar com arrays (ou matrizes) de várias dimensões, pois existem
muitas aplicações matemáticas que usam arrays com mais de duas
dimensões. Lembre-se, no nosso contexto, array e matriz são sinônimos.
Para entender melhor, observe alguns exemplos. Acompanhe como é a
representação das matrizes na Figura 3.
41
Figura 3 – Representação das matrizes do exemplo
Fonte: elaborada pelo autor.
Na Figura 3, a matriz M mostra como fica a disposição dos índices nessa
matriz. É possível entender que, em outros tamanhos, as matrizes terão
o mesmo comportamento com relação aos índices, ou seja, o primeiro
índice se refere normalmente à linha e o segundo à coluna. Lembre-se
que os índices sempre começam com “0”.
Já a matriz N mostra a representação de uma matriz 2x2 inicializada na
sua declaração, a seguir, você verá como é a declaração da matriz, seus
valores e sua respectiva representação.
Da mesma forma que podemos manipular as estruturas
unidimensionais fazendo operações com seus índices, é possível fazer
isso com as estruturas multidimensionais.
Por exemplo, seja a matriz “a” de 3 linhas e 4 colunas, de números
inteiros:
inteiro a[3,4] declaração e criação da matriz.
a[1][3] = 100 atribuindo o valor 100 à posição da linha 1, coluna 3.
42
a[2][1] = 2 atribuindo o valor 2 à posição da linha 3, coluna 1.
a[2][2] = 7 atribuindo o valor 7 à posição da linha 2, coluna 2.
Sendo X = 1 e Y = 0, podemos fazer:
a[1+x][0+y] a[1+1][0+0] = a[2][0] e podemos atribuir o valor 5: a[2][0] =
5
a[1][1] = a[2][1] * a[1][3] a[1][1] = 2 * 100 a[1][1] = 200
Assim, obtemos a matriz a seguir (Figura 4).
Figura 4 – Matriz do exemplo
Fonte: elaborada pelo autor.
Como você pode perceber, a partir de agora os algoritmos ficarão
maiores. Por exemplo, e se quisermos mostrar todos os valores de uma
matriz? Pense em um jogo da velha, é possível implementá-lo usando
uma matriz de 3x3. Como você faria para mostrar na tela o desenho do
jogo da velha, usando os caracteres ‘X’ e ‘O’? Você consegue pensar em
um algoritmo para isso?
Observe o seguinte algoritmo:
1 programa {
2 funcao inicio() {
3 inteiro x,y
4 caracter vez=’X’
43
5 caracter jogo[3][3] = {{‘ ‘,’ ‘,’ ‘},{‘ ‘,’ ‘,’ ‘},{‘
‘,’ ‘,’ ‘}}
6 para (inteiro i=1; i<=9; i++) {
7 escreva(“Digite a posição X e Y: “)
8 leia(x,y)
9 se (vez==’X’) {
10 jogo[x][y]=’X’
11 vez=’O’
12 }
13 senao {
14 jogo[x][y]=’O’
15 vez=’X’
16 }
17 para (inteiro linha = 0; linha < 3; linha++){
18 para (inteiro coluna = 0; coluna < 3; coluna++){
19 escreva(“[“, jogo[linha][coluna], “]”)
20 }
21 escreva (“\n”)
22 }
23 }
24 }
25 }
Para isso, temos que considerar que se trata de uma implementação
simples, em que será simulado o jogo da velha, entre duas pessoas,
em que cada uma escolhe a posição X e Y de onde gostaria de marcar
o seu sinal (“X” ou “O”). Não estamos levando em consideração o caso
de a pessoa marcar a mesma posição. Portanto, caso você queira uma
44
implementação mais real, o desafiamos a criá-la, pois é um excelente
exercício de algoritmo, estruturas de controle e manipulação de matriz.
Voltando ao algoritmo, nas linhas 3 e 4 temos a criação das variáveis
usadas durante o algoritmo. Note que a variável “vez” foi iniciada com
“X”, que é o sinal escolhido para começar o jogo.
Na linha 5 temos a criação da matriz 3x3, chamada “jogo”, já inicializando
com o caractere de espaço em cada posição para dar a impressão de
que temos um jogo vazio.
Entre as linhas 6 e 23 temos a repetição do algoritmo principal por 9
vezes, uma vez para cada posição da matriz.
As linhas 7 e 8 fazem a leitura dos valores X e Y, que é a posição onde o
jogador vai colocar o seu sinal.
Entre as linhas 9 e 16 é feito o teste de qual é o sinal da vez e atribuído o
sinal da vez à posição escolhida da matriz.
Entre as linhas 17 e 22 é feita a impressão da matriz na tela. Veja que
temos um looping para as linhas e outro para as colunas dentro do
primeiro. Dessa forma, a pergunta que feita no desafio é respondida:
para imprimir os valores de uma matriz multidimensional, usamos dois
loopings, em que um deles é interno. Para uma matriz unidimensional é
necessário apenas um looping.
3. Estruturas compostas heterogêneas -
registros
Como última estrutura de dados básica, introduziremos os registros ou
as estruturas compostas heterogêneas (FORBELLONE; EBERSPACHER,
2005).
45
De acordo com Guedes (2014), um registro é uma variável composta
por várias partes, por exemplo, um produto que é composto pelo
código, nome e preço. Todas essas partes, as quais podemos chamar
de “campos”, compõe um endereço e são formadas de tipos de dados
diferentes, por isso são chamadas de heterogêneas.
Um registro permite a criação de novos tipos de dados. Você sabe
que existem tipos primitivos como: inteiro, real, caractere, booleano,
mas agora você pode criar os nossos próprios tipos para suprir as
necessidades de acordo com o algoritmo. Os registros são também
chamados de structs (estruturas) em várias linguagens de programação.
Contudo, a ferramenta que utilizada aqui não tem implementação
para registros, mas isso não impede que eles possam ser utilizados em
algoritmos. Veja um exemplo da criação de um registro para um produto
e, em seguida, uma variável chamada “produto” do novo tipo criado.
tipo r_produto = registro {
inteiro codigo
caractere nome
real preco
}
registro_produto produto
Note que foi criado o registro r_produto e, depois, uma variável composta
chamada produto. Com isso, podemos ampliar as possibilidades e os
poderes dos algoritmos. Veja o exemplo:
1 inicio
2 tipo r_produto = registro {
3 inteiro codigo
46
4 caractere nome
5real preco
6 int estoque
7 }
8 registro_produto produto
9 produto caneta, lapis, borracha
10 int cod,qtd
11 leia(caneta.codigo, caneta.nome, caneta.preco, caneta
estoque)
12 escreva(“Digite o código da caneta”)
13 leia(cod)
14 escreva(“Digite a quantidade desejada”)
15 leia(cod)
16 if(cod==caneta.codigo){
17 if(qtd<=caneta.estoque) {
18 caneta.estoque = caneta.estoque—
19 escreva(“Canetas baixadas do estoque:”,qtd)
20 escreva(“Canetas restantes no estoque:”,caneta
estoque)
21 }
22 }
23 fim_algoritmo
O algoritmo tem como objetivo simular a baixa de estoque de produtos.
As linhas de 2 a 8 mostram a criação do registro e do tipo produto
explicado anteriormente.
A linha 9 mostra como se criam variáveis baseadas no novo tipo produto
recém-criado. Caneta, lápis, borracha são variáveis que possuem os
campos codigo, nome, preco e estoque como definidos no registro.
47
A linha 11 mostra como podemos atribuir valores para cada campo
do registro. Observe que foi utilizado o identificador da variável, em
seguida, temos um ponto “.” e o campo que queremos trabalhar
daquela variável. Faça isso toda vez que quiser trabalhar com os campos
individuais de cada variável.
As linhas de 16 a 22 simulam a baixa de um produto no estoque, de
acordo com a quantidade informada na linha 14, e se há estoque
suficiente, conforme a linha 17. Se o usuário digitar o código correto da
caneta (linha 16), o estoque será diminuído (linha 18) em tantas canetas
digitadas na linha 14.
Lembre-se, esse é apenas um exemplo didático para você entender
como manipular registros. O controle de estoque real é algo bem mais
complexo e com mais detalhes.
Neste tema, você pode aprender sobre os principais tipos de estruturas
de dados básicas que podem ser usados em seus algoritmos. Existem
outros detalhes e outras estruturas que você poderá encontrar na
prática, mas com o que foi mostrado aqui é possível criar novos
algoritmos estruturados e poderosos.
Não deixe de investir no aprendizado de uma linguagem de
programação também, para você aplicar os ensinamentos que você
tem visto aqui, bem como usar o software sugerido para praticar os
algoritmos.
48
Referências
FORBELLONE, André Luiz Villar; EBERSPACHER, Henri Frederico. Lógica de
programação: a construção de algoritmos e estruturas de dados. São Paulo:
Prentice Hall, 2005.
GUEDES, Sérgio (org.). Lógica de programação algorítmica. São Paulo: Pearson,
2014.
MEIO, Ana Cristina. Princípios de linguagem de programação. São Paulo: Blucher,
2003.
49
Modularização de programas
Autoria: Fabiano Goncalves dos Santos
Leitura crítica: Virgínia Mara Cardoso
Objetivos
• Apresentar os principais tópicos sobre os
subprogramas: funções e procedimentos.
• Estudar as passagens de parâmetros por valor e por
referência.
• Introduzir o conceito de recursividade.
50
1. Introdução aos subprogramas
Alguma vez você pode ter ouvido que, para resolver um grande
problema, é preciso dividi-lo em partes menores. Isso é uma verdade em
várias áreas da nossa vida, inclusive para os algoritmos. Nesta aula, você
verá alguns pontos que podem ajudá-lo a resolver os problemas que
encontrará no desenvolvimento estruturado de algoritmos.
Ao dividir o problema em partes menores, a maior preocupação que se
deve ter é garantir a integração dessas partes em busca do objetivo do
algoritmo.
Outro ponto importante é saber como e quando dividir o problema
até encontrar uma boa solução. Existe uma técnica chamada de
Refinamentos Sucessivos, ou Top-Down, que parte de conceitos mais
abrangentes até chegar a um nível de detalhe considerado ideal
(MEIO, 2003). Já a técnica inversa, Bottom-Up, parte de conceitos mais
detalhados, agrupando-os e generalizando, até chegar a um nível de
abstração desejado.
De acordo com Guedes (2014), um módulo, ou subprograma, é
um pedaço de programa que realiza uma determinada tarefa. Os
subprogramas são combinados para formar programas maiores
e tornam o algoritmo modular. Existem basicamente dois tipos de
subprogramas na maioria das linguagens de programação usadas
atualmente: as funções e os procedimentos (FORBELLONE;
EBERSPACHER, 2005).
51
2. Funções
A função nada mais é do que um grupo de comandos e instruções
que realiza uma tarefa específica. Segundo Meio (2003), uma função,
diferentemente de um procedimento, sempre terá um valor de retorno.
Usando o Portugol como linguagem de algoritmos, uma função tem a
seguinte sintaxe:
funcao tipo_de_retorno nome_da_funcao (tipo_parâmetro nome_parâmetro
{
corpo do módulo
retorne variável ou valor
}
Por exemplo:
1 funcao real media(inteiro m1, inteiro m2, inteiro m3) {
2 real media
3 media = (m1 * 2 + m2 * 3 + m3 * 8) / 13.0
4 retorne media
5 }
Figura 1 – Estrutura de uma função
Fonte: Elaborado pelo autor
52
No exemplo, temos uma função chamada “media” que tem o tipo de
retorno “real”. Toda função deve possuir obrigatoriamente um tipo de
retorno e um nome que a identifica. O objetivo dessa função é calcular
a média ponderada, note que não se trata de uma média aritmética
tradicional.
Em seguida, entre parênteses temos uma lista opcional de parâmetros.
No caso do exemplo, temos três: m1, m2 e m3, todos do tipo inteiro.
É possível ter quantos parâmetros desejar, separando-os por vírgula e
declarando o seu tipo.
O corpo da função está entre as linhas 2 e 4 e, como você pode
perceber, é muito parecido com um algoritmo normal. A linha 4 tem o
comando “retorne”, obrigatório dentro de toda função, o qual faz com
que o valor da variável “media”, calculada na linha 3, seja retornada para
o programa que chamou a função.
2.1 Chamando funções
Para usar uma função, você terá que “chamar” essa função para
executar a tarefa definida. Segundo Guedes (2014), quando um
programa chama uma função, o controle do programa é transferido
para a função chamada. Uma função chamada executa uma tarefa
definida e, quando sua instrução de retorno é executada ou quando sua
última instrução final é alcançada, ela retorna o controle do programa de
volta ao programa principal. Isso pode parecer complicado, mas não é,
observe o código a seguir e a Figura 2.
1 programa {
2 funcao inicio () {
3 inteiro v1,v2,v3
4 real mp
5 escreva (“Entre com os três valores:\n”)
53
6 leia (v1,v2,v3)
7 mp = media (v1,v2,v3)
8 escreva(“A média ponderada entre os três valores é:
“,mp)
9 }
10
11 funcao real media(inteiro m1, inteiro m2, inteiro m3) {
12 real media
13 media = (m1*2 + m2*3 + m3*8)/13.0
14 retorne media
15 }
16 }
Figura 2 – Chamada de funções
Fonte: elaborada pelo autor.
A Figura 2 mostra como é o funcionamento da chamada de uma função.
Analise a figura junto com o código anterior.
Nas linhas 2 a 9 temos o programa principal do nosso algoritmo.
Perceba que ele também é uma função que não tem tipo de retorno e
nem parâmetros de entrada, o que abordaremos adiante. Na linha 7
temos a chamada da função “media”. O compilador, ao chegar nesse
comando, desvia a execução do algoritmo para a linha 11, onde a função
54
foi declarada. Caso o compilador não encontre a função, será gerado um
código de erro.
A Figura 2 mostra que as variáveis lidas no programa principal: v1, v2 e
v3 correspondem, e devem corresponder, exatamente aos parâmetros
m1, m2 e m3 da função. Caso exista alguma incompatibilidade de tipo
ou número de parâmetros diferentes, ocorrerá erro.
Então, o compilador passa a executar a função nas linhas 12 e 13; e
quando encontra o comando “retorne”, passa o resultado do cálculo na
variável de retorno “media” e devolve esse valor para o local de onde a
função foi chamada, na linha 7; e o resultado é atribuído à variável “mp”.
Assim, o programa prossegue com sua execução até o final.
2.2 Funções sem retorno–procedimentos
Como você pode perceber, os algoritmos que estão sendo desenvolvidos
tem uma função “inicio()”, em que inserimos ocódigo do algoritmo
dentro do corpo dessa função.
Note que a função “inicio()” não tem um tipo de retorno (e não precisa
ter o comando “retorne” no final) e nem parâmetros de entrada. Já
sabemos que os parâmetros são opcionais, mas existem algumas
funções que não precisam necessariamente retornar algum valor para
o chamador, essas são chamadas de “procedimentos” ou também
“procedures” em algumas linguagens de programação (GUEDES, 2014).
Portanto, sua maior diferença em relação às funções é a não
obrigatoriedade de um tipo de retorno.
A sintaxe de uma procedure é muito parecida com a de uma função:
funcao nome_da_funcao (tipo_parâmetro nome_parâmetro) {
55
corpo do módulo
}
Por exemplo:
1 programa {
2 funcao inicio() {
3 mensagem(“Olá mundo!”)
4 }
5
6 funcao mensagem (cadeia texto) {
7 inteiro i
8 para(i = 0; i < 50; i++) {
9 escreva (“-”)
10 }
11 escreva (“\n”, texto, “\n”)
12 para(i = 0; i < 50; i++) {
13 escreva (“-”)
14 }
15 escreva(“\n”)
16 }
17 }
A procedure “mensagem()” está definida entre as linhas 6 a 16. Ela recebe
uma string chamada “mensagem” como parâmetro e tem como objetivo
mostrar a mensagem estilizada na tela. O algoritmo para estilizar a
mensagem é bem simples e está dentro do bloco nas linhas 8 e 15, seu
resultado é explicitado a seguir:
56
—————————————————————————
Olá mundo!
—————————————————————————
3. Passagem de parâmetros
Como você estudou, uma função ou uma procedure pode aceitar
parâmetros que são valores passados pelo chamador do subprograma.
Dentro do programa principal, esses valores são chamados de
argumentos e, ao chegarem no subprograma, têm o nome alterado
para parâmetros.
Os parâmetros se comportam como outras variáveis locais dentro
do subprograma e são criados na entrada e destruídos na saída do
subprograma. Ao chamar um subprograma, existem duas maneiras
pelas quais os argumentos podem ser passados ao subprograma:
• Chamada por valor: método que copia o valor real de um
argumento no parâmetro formal do subprograma. Nesse caso, as
alterações feitas no parâmetro dentro do subprograma não têm
efeito sobre o argumento.
• Chamada por referência: método que copia o endereço de
um argumento no parâmetro formal. Dentro do subprograma,
o endereço é usado para acessar o argumento real usado na
chamada. Isso significa que as alterações feitas no parâmetro
afetam o argumento (FORBELLONE; EBERSPACHER, 2005).
Nos algoritmos elaborados, e na maioria deles, é feita a chamada por
valor para passar argumentos. Em geral, isso significa que o código
dentro de um subprograma não pode alterar os argumentos usados
para chamar o subprograma.
57
Por exemplo, observe o algoritmo a seguir.
1 programa {
2 funcao inicio() {
3 inteiro a,b,c,m=0
4 leia(a,b,c)
5 minimo(a,b,c,m)
6 escreva(“Mínimo = “,m)
7 }
8
9 funcao minimo(inteiro x, inteiro y, inteiro z, inteiro
&min){
10 se (x<y) {
11 min=x
12 }
13 senao {
14 min=y
15 }
16 se (z<min){
17 min = z
18 }
19 }
20 }
Trata-se, basicamente, de um algoritmo muito parecido com os
estudados nesta disciplina. No entanto, na linha 9 percebemos que a
variável “min” tem um “&”. Isso denota que essa variável está sendo
passada por referência, ou seja, a variável “m”, que corresponde a ela na
chamada da função (linha 5), vai ter o seu valor alterado.
58
Então, até isso não era possível porque o escopo das variáveis era
diferente. Com o “&” no início da variável, toda modificação que for feita
na variável correspondente (nesse caso é a variável “min”), dentro da
função, afetará o valor da variável “m”, fora da função.
Lembre-se que esse recurso não é o padrão de passagem de parâmetros
na maioria das linguagens de programação e é usado somente em
algumas situações.
4. Recursividade
É possível que uma função seja chamada dentro de outra função.
Voltando ao exemplo da função “media()” e da procedure “mensagem()”,
pode-se chamar a procedure dentro da função “media()” para mostrar
uma mensagem com o valor da média ponderada.
Também é possível executar uma função dentro dela mesma. Isso é
chamado de recursividade e o processo que é executado é chamado de
recursão.
O exemplo mais fácil e usado para explicar a recursividade é o cálculo
de um número fatorial. Por exemplo, você sabe que o fatorial de 5 é
calculado por:
5! = 5 * 4 * 3 * 2 * 1 = 120
Logo, como você faria para calcular o fatorial de um número qualquer?
O exemplo foi do número 5, que é pequeno e fácil, mas e se o número
fosse 349? Para resolver isso, seria necessário um algoritmo. O algoritmo
a seguir faz esse cálculo:
1 programa {
2 funcao inicio() {
59
3 inteiro numero
4 escreva(“Digite um número: “)
5 leia(numero)
6 escreva(“Fatorial= “, fatorial(numero), “\n”)
7 }
8
9 funcao inteiro fatorial(inteiro numero) {
10 se (numero == 1 ou numero == 0) {
11 retorne 1
12 }
13 retorne numero * fatorial(numero–1)
14 }
15 }
As linhas 1 a 7 compõem o programa principal, com destaque para a
linha 6, onde ocorre a chamada da função “fatorial()” para calcular o
fatorial do número lido na linha 5.
As linhas 9 a 14 compõem a função “fatorial()” recursiva. Perceba que,
na linha 13, ela é chamada novamente até que a variável “numero” seja
igual a 1.
A linha 10 é a que determinará o fim da recursividade. Sabendo a
fórmula do cálculo do fatorial, temos que criar um loop que pega o
número desejado e o multiplica pelo seu antecessor até chegar o
número 1, onde ocorre a multiplicação final. É claro que o teste também
é feito para o número 0, pois 0!=1.
De acordo com Guedes (2014), uma função recursiva é dividida em duas
partes:
60
• Existe um ou mais casos base onde não é necessária nenhuma
recursão. No exemplo anterior, quando a variável “numero”
for igual a 0 ou 1, nesses casos, a resposta pode ser dada
imediatamente, sem precisar da recursão e, como dizemos, é o
caso em que a recursão eventualmente possa parar.
• Há um ou mais casos recursivos e definem a função em termos de
uma chamada mais simples a si mesma.
É possível criar o mesmo algoritmo sem ser recursivo, entretanto, esse
recurso pode tornar o algoritmo mais simples e legível, pois é provável
que a versão não recursiva do algoritmo que você está estudando será
bem maior em tamanho e complexidade do que a versão recursiva.
O insight para perceber que uma versão recursiva possa ser criada de
um algoritmo que você está desenvolvendo, normalmente, vem com a
experiência, portanto, é importante que você pratique e compreenda os
exemplos apresentados.
Nesta aula, procuramos apresentar os principais tópicos do uso de
subprogramas nos seus algoritmos, lembrando que existem outros
tópicos relacionados que podem ser estudados por você baseado nos
conceitos mostrados nesta aula. Bons estudos!
Referências
FORBELLONE, André Luiz Villar; EBERSPACHER; Henri Frederico. Lógica de
programação: a construção de algoritmos e estruturas de dados. São Paulo:
Prentice Hall, 2005.
GUEDES, Sérgio (org.). Lógica de programação algorítmica. São Paulo: Pearson,
2014.
MEIO, Ana Cristina. Princípios de linguagem de programação. São Paulo: Blucher,
2003.
61
Sumário
Apresentação da disciplina
Estruturas básicas de programação
Objetivos
1. Introdução
2. Algoritmos
3. Variáveis e tipos primitivos
4. Expressões
5. Considerações finais
Referências
Estruturas de controle
Objetivos
1. Entradas pelo teclado e saídas em tela
2. Estruturas sequenciais
3. Estruturas de decisão
4. Estruturas de repetição
Referências
Estruturas de dados básicas
Objetivos
1. Estruturas de dados homogêneas
2. Estruturas de dados multidimensionais: matrizes
3. Estruturas compostas heterogêneas - registros
Referências
Modularização de programas
Objetivos
1. Introdução aos subprogramas
2. Funções
3. Passagem de parâmetros
4. Recursividade
Referências