Docsity
Docsity

Prepare-se para as provas
Prepare-se para as provas

Estude fácil! Tem muito documento disponível na Docsity


Ganhe pontos para baixar
Ganhe pontos para baixar

Ganhe pontos ajudando outros esrudantes ou compre um plano Premium


Guias e Dicas
Guias e Dicas

Introdução à Programação em Algoritmos: Conceitos Fundamentais e Exemplos Práticos, Manuais, Projetos, Pesquisas de Algoritmos

Uma introdução abrangente à programação em algoritmos, explorando conceitos essenciais como variáveis, tipos de dados, vetores, matrizes, registros, procedimentos e funções. Através de exemplos práticos e bem explicados, o documento demonstra como implementar algoritmos para resolver problemas computacionais, desde a declaração de variáveis até a utilização de estruturas de dados e procedimentos. O conteúdo é ideal para estudantes que desejam iniciar sua jornada na programação, fornecendo uma base sólida para o desenvolvimento de habilidades de programação.

Tipologia: Manuais, Projetos, Pesquisas

2024

Compartilhado em 09/11/2024

alysson-pereira-de-melo
alysson-pereira-de-melo 🇧🇷

3 documentos

1 / 28

Toggle sidebar

Esta página não é visível na pré-visualização

Não perca as partes importantes!

bg1
6
Algoritmos II
Seções de estudo
1 - Introdução e estruturas básicas
1 - Introdução e estruturas básicas
2 - Comandos básicos
3 - Estruturas Condicionais e de Repetição
4 - Vetores e Matrizes
Antes de relembrarmos como escrevemos algoritmos,
vamos relembrar o que é um algoritmo. Na disciplina anterior,
vimos que Guimarães e Lages definem algoritmo como: “[...]
descrição de um padrão de comportamento, expressão em
termos de um repertório bem definido e finito de ações
primitivas, das quais damos por certo que elas podem ser
executadas” (GUIMARÃES; LAGES, 1994, p. 4).
Farrer et. al. (1999, p. 14) descreve Algoritmo como:
“um conjunto de comandos que, obedecidos, resultam numa
sucessão finita de ações.”
Assim, Algoritmo é uma série de passos que são
executados para chegarmos a uma solução. Uma receita de
bolo é um grande exemplo disso.
Na computação, escrevemos algoritmos para ordenarmos
ao computador o que deve ser feito. Para isso, usamos uma
sintaxe bem definida para que a máquina entenda o que
queremos.
Nesta aula, vamos relembrar a sintaxe do PORTUGOL
(adaptado ao programa Visualg) que é usada para construção
de algoritmos.
1.1 - Tipos de dados
Um algoritmo processa dados. Um algoritmo escrito em
Portugol reconhece os seguintes tipos de dados.
Inteiros: Representa números inteiros, que não possui
parte fracionada. Por exemplo: 2, -6, 999. Nos algoritmos,
declaramos com a palavra
inteiro
.
Reais: Representa números reais, com parte
fracionária. Ex: 3, 9.6, -90.2. É declarado através da palavra
real
.
Caracteres: É uma sequência de letras, números
e símbolos, que é declarada entre aspas (“”). É usado para
armazenar textos. Declarado através da palavra
caractere
.
Lógico: Representa valores verdadeiro ou falso.
Declarado através da palavra
logico
.
1.2 - Operadores
Podemos considerar um algoritmo como uma sequência
de instruções. Em cada instrução, podemos ter expressões.
Por sua vez, as expressões são formadas por operadores. São
avaliadas da esquerda para a direita, da mesma forma que
lemos um texto. Porém, existe uma ordem de precedência,
que indica quais expressões serão avaliadas primeiro. Vejamos:
expressões dentro de parênteses e funções;
operador unário menos ou negação;
operadores aritméticos de divisão e multiplicação;
operadores aritméticos de subtração e soma;
operadores relacionais;
operadores lógicos.
Há três tipos de operadores, que são:
Operadores aritméticos: São usados para operações
matemáticas a serem realizadas, para obter resultados
numéricos.
Quadro 1 - Operadores Aritméticos.
Operadores relacionais: São usados para testar uma
relação entre os elementos. Se houver, a expressão retorna
verdadeiro, caso contrário, a expressão retorna falso.
Quadro 2 - Operadores Relacionais.
Operadores lógicos: São usados para combinar
expressões relacionais, compondo expressões mais sofisticadas.
Quadro 3 - Operadores Lógicos.
1.3 - Palavras reservadas
São palavras que a linguagem utiliza para compor um
algoritmo, assim, já tem um sentido definido. O usuário
não pode usar essas palavras para nomear variáveis ou para
estabelecer outro sentido.
Quadro 4 - Palavras reservadas.
1.4 - Estrutura básica de um
algoritmo
Um algoritmo possui a seguinte estrutura básica:
algoritmo “Nome do Programa” //Entre aspas você nomeia o
algoritmo
// isto é um comentário
// abaixo você faz a declaração das variáveis do algoritmo
var
var01 : inteiro
var02 : logico
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff
pf12
pf13
pf14
pf15
pf16
pf17
pf18
pf19
pf1a
pf1b
pf1c

Pré-visualização parcial do texto

Baixe Introdução à Programação em Algoritmos: Conceitos Fundamentais e Exemplos Práticos e outras Manuais, Projetos, Pesquisas em PDF para Algoritmos, somente na Docsity!

Algoritmos II 6

Seções de estudo

1 - Introdução e estruturas básicas

1 - Introdução e estruturas básicas 2 - Comandos básicos 3 - Estruturas Condicionais e de Repetição 4 - Vetores e Matrizes Antes de relembrarmos como escrevemos algoritmos, vamos relembrar o que é um algoritmo. Na disciplina anterior, vimos que Guimarães e Lages definem algoritmo como: “[...] descrição de um padrão de comportamento, expressão em termos de um repertório bem definido e finito de ações primitivas, das quais damos por certo que elas podem ser executadas” (GUIMARÃES; LAGES, 1994, p. 4). Farrer et. al. (1999, p. 14) descreve Algoritmo como: “um conjunto de comandos que, obedecidos, resultam numa sucessão finita de ações.” Assim, Algoritmo é uma série de passos que são executados para chegarmos a uma solução. Uma receita de bolo é um grande exemplo disso. Na computação, escrevemos algoritmos para ordenarmos ao computador o que deve ser feito. Para isso, usamos uma sintaxe bem definida para que a máquina entenda o que queremos. Nesta aula, vamos relembrar a sintaxe do PORTUGOL (adaptado ao programa Visualg) que é usada para construção de algoritmos.

1.1 - Tipos de dados

Um algoritmo processa dados. Um algoritmo escrito em Portugol reconhece os seguintes tipos de dados.

  • Inteiros: Representa números inteiros, que não possui parte fracionada. Por exemplo: 2, -6, 999. Nos algoritmos, declaramos com a palavra inteiro.
  • Reais: Representa números reais, com parte fracionária. Ex: 3, 9.6, -90.2. É declarado através da palavra real.
  • Caracteres: É uma sequência de letras, números e símbolos, que é declarada entre aspas (“”). É usado para armazenar textos. Declarado através da palavra caractere.
  • Lógico: Representa valores verdadeiro ou falso. Declarado através da palavra logico.

1.2 - Operadores

Podemos considerar um algoritmo como uma sequência de instruções. Em cada instrução, podemos ter expressões. Por sua vez, as expressões são formadas por operadores. São avaliadas da esquerda para a direita, da mesma forma que lemos um texto. Porém, existe uma ordem de precedência, que indica quais expressões serão avaliadas primeiro. Vejamos:

  • expressões dentro de parênteses e funções;
  • operador unário menos ou negação;
  • operadores aritméticos de divisão e multiplicação;
  • operadores aritméticos de subtração e soma;
    • operadores relacionais;
    • operadores lógicos. Há três tipos de operadores, que são: Operadores aritméticos : São usados para operações matemáticas a serem realizadas, para obter resultados numéricos. Quadro 1 - Operadores Aritméticos. Operadores relacionais : São usados para testar uma relação entre os elementos. Se houver, a expressão retorna verdadeiro, caso contrário, a expressão retorna falso. Quadro 2 - Operadores Relacionais. Operadores lógicos : São usados para combinar expressões relacionais, compondo expressões mais sofisticadas. Quadro 3 - Operadores Lógicos.

1.3 - Palavras reservadas

São palavras que a linguagem utiliza para compor um algoritmo, assim, já tem um sentido definido. O usuário não pode usar essas palavras para nomear variáveis ou para estabelecer outro sentido. Quadro 4 - Palavras reservadas.

1.4 - Estrutura básica de um

algoritmo

Um algoritmo possui a seguinte estrutura básica: algoritmo “Nome do Programa” //Entre aspas você nomeia o algoritmo // isto é um comentário // abaixo você faz a declaração das variáveis do algoritmo var var01 : inteiro var02 : logico

var03 : real // (...) inicio // comeca a declaração das instruções do algoritmo fimalgoritmo

1.5 - Variáveis

O conceito de variável é um dos conceitos mais importantes em algoritmos, pois por meio dele armazenamos dados a serem salvos para serem processados em um algoritmo. Cada variável tem um nome para sua identificação. E esse nome deve obedecer às seguintes regras:

  • deve ser iniciado por uma letra ou pelo sinal de sublinhado ( underline );
  • a partir da segunda letra, podemos usar letras e números;
  • com exceção do sinal de sublinhado, outros símbolos são proibidos em nomes de variáveis;
  • não podem ter nomes iguais as palavras reservadas da sintaxe do PORTUGOL. As variáveis são declaradas em um algoritmo no bloco var, antes da declaração dos comandos do algoritmo. Em cada linha do bloco var, colocamos o nome da variável, depois escrevemos o sinal de dois-pontos (:) e depois colocamos o tipo dessa variável (inteiro, real, logico, caractere). Agora que vocês relembram as definições elementares de um algoritmo, vamos relembrar os comandos básicos.

2 - Comandos básicos

3 - Estruturas Condicionais e de

Repetição

Um algoritmo possui comandos básicos. Vamos relembrar?

2.1 - Atribuição

Para colocarmos dados em uma variável, usamos o comando de atribuição. O identificador fica no lado esquerdo da expressão. O valor ou a expressão que computará o valor a ser atribuído fica no lado direito da expressão. Eles são separados pelo sinal de atribuição (<-). X <- 9

2.2 - Expressões

Para calcular valores, usamos expressões. Essas expressões usam valores, variáveis e operadores. Seu resultado pode ser salvo em uma variável. SOMA <- x + 9 POTENCIA <- I ** 2

2.3 - Comentários

Vocês podem deixar mais claro seu código explicando o que esse programa faz. Para isso, existem os comentários. Durante a execução, o computador vai descartar tudo o que você escrever em um comentário. Para escrevermos comentários, usamos as chaves para delimitar o início e o fim de um comentário ou usamos as duas barras para declarar que o restante da linha é um comentário. X <- 9 // atribui o valor 9 a variável X

2.4 - Comando de leitura

Outra forma de definir valores em uma variável é usar o comando leia. Esse comando permite que o programa espere o usuário informar os valores para uma variável. Sua sintaxe é definida da seguinte forma: leia() Onde é uma lista de variáveis que devem ter seus valores indicados pelo usuário. As variáveis são separadas por vírgulas. Exemplos: leia(X) leia(X, X1) 2.5 Comando de escrita Para que o algoritmo possa apresentar dados ao usuário, usamos o comando escreva. Sua sintaxe é semelhante ao comando leia, mas além de aceitar variáveis, o comando escreva aceita caracteres. Exemplos: escreva(X) escreva(“Valor de X=”, X) Há o comando escreval, onde depois de escrever todos os dados especificados, ele pula uma linha na exibição. Agora, vamos rever as estruturas condicionais e de repetição, que são também importantes em algoritmos.

3.1 - Estruturas Condicionais

As estruturas condicionais permitem ao programador definir comandos que serão executados em determinadas condições. As condições são expressas por meio de valores, variáveis, operadores relacionais e operadores lógicos. As estruturas condicionais são expressas da seguinte forma: se <condição> entao //comandos caso resultado da condição seja verdadeira senao //opcional //comandos caso o resultado da condição seja falsa fimse Vamos a um exemplo: se media >= 7.0 entao escreva(“Aprovado!”) senao escreva(“Reprovado!”) fimse

3.2 - Estruturas de Repetição

As estruturas de repetição permitem que o programador indique comandos que serão repetidos várias vezes. Em algoritmos, temos três tipos de estruturas de repetição, a saber:

Seções de estudo

1 - Introdução aos Registros

1 - Introdução aos Registros 2 - Como criar e usar Registros 3 - Usando conjuntos dentro de um Registro 4 - Usando conjunto de registros Você viu, na aula anterior, que podemos criar variáveis compostas por um tipo só, denominadas de variáveis compostas homogêneas. Porém, na vida real, várias situações envolvem dados de diversos tipos, por exemplo:

  1. Uma pessoa pode ser identificada pelo seu nome (caractere), sua idade (inteiro), sua altura (real), pelo seu sexo (pode ser uma variável do tipo caractere) e se é um doador de órgãos (como os valores possíveis são sim ou não, podemos colocar do tipo lógico, para representar isso);
  2. Uma reserva de um hotel pode ser identificada pelo nome do responsável (caractere), quantidade de hóspedes (inteiro), e a data de saída (caractere);
  3. Um produto em uma loja tem um nome (caractere), valor (real) e a sua quantidade (inteiro). Para abrigar essas possibilidades, podemos usar as variáveis compostas heterogêneas, também denominadas de registros. Um registro é como se fosse um tipo novo de dados a ser acrescido no algoritmo. Esse tipo define campos a serem preenchidos.

2 - Como criar e usar Registros

Como falamos, um registro é um tipo de dados em que você define quais campos serão compostos de uma variável desse tipo. Assim, na linguagem PORTUGOL, devemos declarar primeiro a estrutura do registro. Para isso, usamos a sintaxe: tipo = registro fimregistro Atenção: O bloco tipo sempre deve ser declarado antes do bloco var. Após declararmos o registro, podemos criar variáveis desse tipo, por meio do bloco var. Ao invés de usarmos um dos tipos primitivos de dados (inteiro, real, caractere e lógico), usamos o identificador do registro que criamos. Depois de criarmos as variáveis desse tipo, podemos usá- las em nosso código, de forma similar que usamos em variáveis comuns. A única diferença que devemos atentar é que no registro, devemos indicar qual campo dele devemos usar. Para isso, devemos usar a sintaxe <nome da variável>.. A seguir, vamos mostrar alguns exemplos de uso de registros, dentro de um algoritmo. Exemplo 1: Escreva um algoritmo que leia e apresente os dados de uma pessoa. Uma pessoa tem como dados seu nome, sua idade, sua altura, seu sexo (deve ser lido um caractere M ou F) e se a pessoa é doadora de órgãos ou não. algoritmo “Exemplo Pessoa” //declara aqui o tipo pessoa tipo Pessoa = registro nome : caractere idade : inteiro altura : real sexo : caractere doadorOrgaos : logico fimregistro var cidadao : Pessoa //Aqui declaramos uma variável do tipo Pessoa inicio //leia os dados da pessoa leia(cidadao.nome) leia(cidadao.idade) leia(cidadao.altura) leia(cidadao.sexo) leia(cidadao.doadorOrgaos) //escreva os dados da pessoa escreva(cidadao.nome) escreva(cidadao.idade) escreva(cidadao.altura) escreva(cidadao.sexo) escreva(cidadao.doadorOrgaos) fimalgoritmo Exemplo 2: Escreva um algoritmo que leia e exiba na tela o nome, o seu preço e a quantidade em estoque de um produto na loja. algoritmo “Exemplo Produtos” //declara aqui o tipo Reg_Produtos tipo Reg_Produtos = registro nome : caractere preco : real estoque : inteiro fimregistro var produto : Reg_Produtos //Aqui declaramos uma variável do tipo Reg_Produtos inicio //leia os dados do produto leia(produto.nome) leia(produto.preco) leia(produto.estoque) //escreva os dados desse produto escreva(produto.nome) escreva(produto.preco) escreva(produto.estoque) fimalgoritmo

Algoritmos II 12

3 - Usando conjuntos dentro de um

Registro

Você pode usar além dos tipos primitivos, um conjunto (vetor ou matriz) de um tipo primitivo para ser um campo de um registro. Para isso, podemos usar a mesma notação que usamos para declarar um registro, só que aplicado a um campo de um registro. Supomos que queremos registrar as notas de um aluno durante quatro bimestres, além de seu nome. Para isso, podemos usar essa sintaxe: tipo Registro_Aluno = registro nome : caractere notas : vetor[1..4] de real fimregistro Para ler ou escrever dados em um campo composto de um vetor, usamos a mesma sintaxe para um campo comum, acrescentado pelo índice do elemento que devemos usar, assim como acessamos índices de um vetor ou matriz, que vimos em Algoritmos I. leia(aluno.notas[1]) escreva(aluno.notas[1]) Vamos ver um exemplo para contextualizar essa situação. Exemplo 3: Escreva um algoritmo que leia e escreva os dados de um aluno. Um aluno é identificado pelo seu nome, além das notas dos seus quatro bimestres. algoritmo “Exemplo Alunos” //declara aqui o tipo para o aluno tipo Registro_Aluno = registro nome : caractere notas : vetor[1..4] de real fimregistro var aluno : Registro_Aluno //Aqui declaramos uma variável do tipo Registro_Aluno i : inteiro inicio //leia os dados desse aluno leia(aluno.nome) para i de 1 ate 4 passo 1 faca leia(aluno.notas[i]) fimpara //escreva os dados desse aluno escreva(aluno.nome) para i de 1 ate 4 passo 1 faca escreva(aluno.notas[i]) fimpara fimalgoritmo

4 - Usando conjunto de registros

Normalmente, quando escrevemos algoritmos envolvendo registros, usamos um conjunto de registros para armazenar uma quantidade de dados. Um conjunto funciona da mesma forma que um vetor ou uma matriz, mas ao invés de cada posição armazenar um dado, ela armazena uma série de campos que foram definidos previamente. Figura 1 - Estrutura de um vetor de registros. Fonte: Acervo Pessoal. Para criarmos um vetor ou uma matriz de registros, devemos primeiro declarar a estrutura do registro, da mesma forma que você aprendeu na seção II. Depois, você deve declarar uma variável como um vetor ou uma matriz, da mesma forma que você aprendeu na disciplina anterior. A diferença fica no fato de que, ao invés de declarar como um dos tipos primitivos, você declara essa variável como sendo do tipo que você definiu previamente. Por exemplo, um registro para registrar alunos da seguinte estrutura: //declara aqui o tipo para o aluno tipo Registro_Aluno = registro nome : caractere notas : vetor[1..4] de real fimregistro Podemos declarar um vetor para armazenar 8 alunos da seguinte forma: var alunos : vetor[1..8] de Registro_Aluno Para declarar uma matriz de 8 linhas e 8 colunas para os alunos, podemos usar a seguinte instrução: alunosM :vetor[1..8,1..8] de Registro_Aluno Depois, para usar os dados do conjunto de registros, devemos primeiramente indicar o nome do conjunto, depois indicamos o(s) índice(s) do conjunto a ser acessado. Em seguida, colocamos um ponto e indicamos o nome do campo a ser acessado. //lê o campo nome da primeira posição do vetor de alunos leia(alunosV[1].nome) //escreve na tela a segunda posição do campo notas da posição 2, 2 da matriz de alunos. escreva(alunosM[2,2].notas[2]) Para ilustrar melhor, vamos ver mais um exemplo: Exemplo 4: Escreva um algoritmo que registre os dados de 10 praças de pedágio. Para cada praça, registre o nome da rodovia, o quilômetro da rodovia onde fica esse pedágio, a cidade onde fica esse pedágio e o seu valor. No final calcule o valor total dos pedágios neste trajeto. algoritmo “Calcula Pedágios” tipo Registro_Pedagios = registro nome : caractere quilometro : inteiro cidade : caractere valor : real fimregistro var pedagios : vetor[1..10] de Registro_Pedagios i : inteiro valorTotal : real

Seções de estudo

1 - Para que modularizar?

2 - Introdução aos Procedimentos

1 - Para que modularizar? 2 - Introdução aos Procedimentos 3 - Usando Parâmetros Durante a sua jornada de estudo, você desenvolveu vários algoritmos, de diversos tamanhos. Muitos desses algoritmos que você escreveu nesse tempo são pequenos, para ajudar na fixação do conteúdo estudado. Porém, é comum na Informática a criação de algoritmos mais complexos, com várias situações de execução. Nessas situações, podem ser criados algoritmos com centenas ou milhares (talvez milhões) de linhas, acarretando os seguintes problemas:

  • A primeira delas é a dificuldade de entendimento do programa. Suponhamos que você esteja iniciando o seu primeiro dia de trabalho em uma empresa e receba como tarefa a inclusão de uma leitura de dados adicional em um programa. Esse programa tem mais de mil linhas de código. Como não existe nenhuma documentação sobre esse programa, a única solução que você tem é ler linha por linha do programa, acarretando um trabalho grande;
  • O segundo problema vem em consequência do primeiro. A dificuldade na manutenção do programa. Voltemos a tarefa do item anterior, supondo que o seu chefe peça que você altere o nome de uma variável nesse mesmo programa. O problema é que esta variável aparece várias vezes nesse código. A chance de introduzir um erro ou de você esquecer-se de alterar uma parte é grande. Para diminuir esses problemas, os programadores descobriram uma possibilidade: ao invés de escrever um único programa enorme, podemos criar um programa simples, dividindo várias partes desse programa em módulos, onde cada módulo é também um programa simples. Vamos ilustrar o conceito explicando um projeto de algoritmo para uma calculadora. Sabemos que em uma calculadora, fornecemos dois números e a operação desejada, que pode ser adição, subtração, divisão e multiplicação. Podemos implementar esse programa por meio de um algoritmo grande, ou dividindo esse algoritmo em cinco módulos, a saber:
  • módulo de adição;
  • módulo de subtração;
  • módulo de divisão;
  • módulo de multiplicação;
  • um módulo principal, onde faz a leitura dos números, realiza o cálculo (através do chamamento do módulo correspondente) e apresenta na tela. Assim, se houver algum problema no módulo de divisão, podemos achar facilmente esse código e fazer alterações nele. Outra vantagem é que podemos agrupar módulos de uso gerais em bibliotecas, para que outros programadores utilizem esses módulos em outros programas, evitando o que é popularmente chamado de “reinventar a roda”. Portanto, um módulo é um trecho de código separado do restante do programa. Para ser executado, deve ser chamado pelo seu nome. Quando um módulo entrar em execução, a parte que chamou esse módulo no programa é suspensa e aguardará o término da execução deste módulo. Além disso, podemos declarar variáveis cujos valores são informados no ato da chamada desse módulo. A essas variáveis damos o nome de parâmetros. Na programação estruturada, podemos criar módulos através de duas estruturas: procedimentos e funções. Você aprenderá sobre funções na próxima aula. A partir da próxima seção, iniciaremos nosso estudo sobre procedimentos. Podemos implementar módulos usando procedimentos. Em algoritmos, podemos implementar procedimentos da seguinte forma: procedimento var <lista de variáveis> inicio <instruções> fim Onde:
  • é o nome onde o procedimento será chamado. Ele deve ser iniciado por letras, seguido por outras letras ou números. Por convenção, sempre escreveremos o nome de procedimentos usando letras maiúsculas;
  • <lista de variáveis> é a lista de variáveis que o procedimento usará. Por enquanto, saiba que essas variáveis somente existirão durante a execução do procedimento;
  • <instruções> é a lista de instruções que o procedimento executará. Suponhamos um procedimento que leia dois números e escreva a soma correspondente a esses dois números. Ela terá a seguinte forma: procedimento SOMA var N1, N2, RESP : inteiro inicio leia(N1) leia(N2) RESP <- N1 + N escreva(RESP) fim Para usar esses procedimentos, devemos declará-los em um programa antes da declaração das variáveis que o bloco principal do algoritmo usará. Depois, para que possamos executar esses procedimentos, devemos realizar a invocação (ou a chamada) desse procedimento. Quando chamamos um procedimento, o bloco de código que chamou esse procedimento é interrompido e aguarda o término desse procedimento. Uma vez terminado o procedimento, a execução continua na unidade chamadora, na linha seguinte a chamada. Para chamarmos um procedimento, escrevemos o nome dele, seguido por parênteses. Para deixar mais claro o

Algoritmos II 16

momento em que o procedimento é chamado, sublinhamos o nome desse procedimento. A seguir, mostramos um exemplo de uso de procedimentos em um algoritmo. Exemplo 5: crie um algoritmo que chame um procedimento que leia dois números e depois informe ao usuário a soma desses números. Esse procedimento deve ser chamado n vezes, sendo que o valor de n deve ser informado pelo usuário no início da execução. algoritmo “soma” procedimento SOMA var N1, N2, RESP : inteiro inicio leia(N1) leia(N2) RESP <- N1 + N escreva(RESP) fim var n: inteiro inicio escreva(“Informe o número de vezes que o procedimento deve ser executado”) leia(n) para i de 1 até n passo 1 faca SOMA() fimpara fimalgoritmo Lembrem-se de que nesse algoritmo que toda vez que chamamos o procedimento SOMA, o fluxo de execução é desviado para o procedimento SOMA, fazendo que o bloco principal do programa pare o loop que está executando e espere o fim desse procedimento. Você pode entender isso dessa maneira: toda vez que chamamos um procedimento, “incluímos” o código desse procedimento no lugar da chamada desse módulo. Figura 1 - Exemplo de analogia de como o computador interpreta as funções. Fonte: Acervo Pessoal. Vimos, de uma forma básica, como podemos declarar um procedimento. Mas não é só isso. Podemos declarar variáveis, cujos valores são passados ao procedimento no ato de sua chamada. A eles damos o nome de parâmetros, que veremos a seguir.

3 - Usando Parâmetros

Parâmetros são variáveis que declaramos em um procedimento, cujos valores serão definidos pelo bloco de código chamador no ato de sua chamada. É uma maneira de comunicação entre o bloco de código chamador e o procedimento chamado, onde é realizada uma transmissão de dados. Normalmente, os parâmetros são utilizados para passar valores ou definir qual comportamento que um procedimento irá fazer. Para o nosso exemplo do procedimento SOMA anterior, poderíamos, ao invés do procedimento ser encarregado de ler os valores do teclado, pedir ao chamador quais serão os valores a serem somados, onde o bloco chamador pode obter de diversas formas (de um vetor, do teclado, de um arquivo etc.). Para usarmos os parâmetros, devemos seguir as seguintes regras: ● Após o nome do procedimento, definimos entre parênteses uma lista de variáveis da seguinte forma: :, separados por vírgulas. Para o nosso exemplo do procedimento de soma, a lista de parâmetros poderia seguir a seguinte forma: procedimento SOMA(N1:inteiro, N2:inteiro) ● No momento da chamada, devemos indicar os valores que o procedimento irá receber. Declaramos esses valores entre parênteses, após o nome do procedimento. SOMA(5,3) Os valores informados irão para os seus respectivos parâmetros, obedecendo a sua ordem de declaração. Na linha acima, o valor 5 irá para o parâmetro N1 e o valor 3 irá para o parâmetro N2. É considerado um erro de sintaxe quando você declara na chamada do procedimento um número diferente de parâmetros do que declarado pelo procedimento. Por exemplo, você indicar na chamada de um procedimento 1 ou 3 valores, enquanto que na declaração deste mesmo procedimento é definido dois parâmetros. A seguir, veremos um exemplo de uso dos parâmetros no nosso programa de soma. Exemplo 6: Crie um algoritmo que chame um procedimento que some dois números informados na sua chamada e depois informe ao usuário esse resultado. Esse procedimento deve ser chamado n vezes, sendo que o valor de n deve ser informado pelo usuário no início da execução. algoritmo “soma” procedimento SOMA(N1:inteiro, N2:inteiro) var RESP : inteiro inicio RESP <- N1 + N escreva(RESP) fim var n, num1, num2: inteiro inicio escreva(“Informe o número de vezes que o procedimento deve ser executado”) leia(n) para i de 1 ate n passo 1 faca escreva(“Digite o primeiro número: ”) leia(num1) escreva(“Digite o segundo número: ”) leia(num2) //entrega os valores de num1 e num2 para o procedimento SOMA

Algoritmos II 18

3 - Usando Parâmetros Parâmetros são variáveis que declaramos em um procedimento, cujos valores serão definidos pelo bloco de código chamador no ato de sua chamada, sendo uma maneira de comunicação entre o bloco chamador e o procedimento invocado. Os parâmetros são especificados entre parênteses, após o seu nome, na declaração do procedimento. Existem duas formas de transmissão de parâmetros. A passagem de parâmetros por valor, em que o bloco chamador transmite uma cópia do conteúdo a ser passado. Já na passagem por referência, a posição de memória em que a variável se encontra é passada ao procedimento, possibilitando ao procedimento alterar o valor da variável do bloco chamador diretamente. MANZANO, José Augusto N. G.; OLIVEIRA, Jayr Figueiredo de Oliveira. Algoritmos - lógica para desenvolvimento de programação. 2. ed. São Paulo: Érica, 2014. VENANCIO, Claudio Ferreira. Desenvolvimento de Algoritmos : Uma Nova Abordagem. São Paulo: Érica, 2000. FARRER, Harry; et. al. Algoritmos Estruturados. 3. ed. São Paulo: LTC, 1999.

Vale a pena

Vale a pena ler

Vale a pena acessar

MELO, Pedro O. S. Vaz de. Passagem de Parâmetros. Belo Horizonte: UFMG. Disponível em: <http:// homepages.dcc.ufmg.br/~olmo/aula8-parametros.pdf>. Acesso em 26 out. 2017. GUIMARÃES, Rafael Silva. Funções e Procedimentos. IFES. Disponível em: <ftp://ftp.ci.ifes.edu.br/informatica/ rafael/Tecnico/Tecnicas_Programacao/Apresentacao/ IFES-TP-Aula04-Funcoes&Procedimentos.pdf >. Acesso em 26 out. 2017. VARELA, Marcelo. Os Procedimentos (Procedures) e Funções (Functions). Imasters, 2002. Disponível em: <https://imasters.com.br/artigo/345/linguagens/os- procedimentos-procedures-e-funcoes-functions?trace= 9021197&source=single>. Acesso em 20 out. 2007. SILVA, Elaine Quintino. Aprendendo a programar: procedimentos e funções. GlobalCoders, 2010. Disponível em: <http://blog.globalcode.com.br/2010/06/aprendendo- programar-procedimentos-e.html>. Acesso em 20 out. 2017. BARANAUSKAS, José Augusto. Sub-algoritmos: Funções e Procedimentos. Disponível em: <http:// dcm.ffclrp.usp.br/~augusto/teaching/ici/Funcoes-e- Procedimentos.pdf>. Acesso em 26 out. 2017.

Minhas anotações

Algoritmos II 20

Seções de estudo

1 - Conhecendo Funções

1 - Conhecendo Funções Você estudou na aula anterior os procedimentos, que é uma forma de implementar módulos em um algoritmo. Também aprendeu sobre como funciona os parâmetros, que é uma forma de comunicação entre o bloco chamador e o procedimento, consistindo em uma passagem de valores no início da execução do procedimento. Mas vocês, estimados(as) alunos(as), devem estar se perguntando: Existe uma forma de comunicação em que o procedimento entrega um valor ao bloco chamador? A resposta para esta pergunta é SIM. Mas o nome para estes módulos que devolvem valores no fim da execução muda. Eles se chamam funções. Funções são módulos que, quando avaliados dentro de uma expressão, retornam obrigatoriamente um valor à expressão. (VENANCIO, 2000, p. 46). Por esse motivo, quando uma função é encerrada, o bloco chamador é retomado na mesma linha da declaração da função (não na próxima, como ocorre em um procedimento) para que seja recebido o valor devolvido pela função. Em termos de funcionamento, essa é a única coisa que muda. Um procedimento não retorna um valor no fim da sua execução, enquanto que uma função sempre vai retornar um valor. O restante que vimos sobre o funcionamento de procedimentos se aplica as funções da mesma forma. Em termos de declaração, as funções têm mais diferenças do que os procedimentos. Vejamos a seguir como é declarada uma função em algoritmo: funcao (<parâmetros>): var <variáveis> inicio <instruções a serem executadas> retorne() fim Percebemos aqui algumas diferenças, que listamos a seguir:

  • Obviamente, o nome procedimento é trocado para função;
  • Após a declaração dos parâmetros, temos a declaração do tipo de dado que será retornado por esta função, representado pelo espaço ;
  • Por último, devemos retornar algum valor. Para isso, usamos a instrução retorne(), com a especificação do valor a ser passado ao bloco chamador. O dado que será passado nesta instrução deve ser do mesmo tipo que foi definido em . Como uma função retorna valores, podemos usar os valores retornados por essas funções em atribuições, em expressões e até mesmo em testes condicionais. Veremos sobre eles nos próximos exemplos. Exemplo 8: escreva um algoritmo que leia um valor de um salário de um funcionário da empresa. Após isso, calcule e mostre o valor corrigido do salário, de acordo com a seguinte tabela: Salário Reajuste Até R$ 1000,00 10% Maior que R$ 1000,00 e menor que R$ 2000,00 8% Maior igual que R$ 2000,00 6% A definição e o cálculo do porcentual a ser corrigido do salário devem ser por uma função. algoritmo “Reajuste” //função que reajusta o salário funcao REAJUSTAR(salario : real) : booleano var salarioNovo : real inicio se salario <= 1000.00 entao //a porcentagem é definida em partes de 100 //assim, para aplicarmos o reajuste, vamos multiplicar o salário pela sua porcentagem, para que possamos verificar o quanto irá aumentar. Depois somamos com o salario. salarioNovo <- salario + (salario * (10/100)) senão se salario > 1000.00 E salario < 2000.00 entao salarioNovo <- salario + (salario * (8/100)) senao salarioNovo <- salario + (salario * (6/100)) fimse fimse retorne(salarioNovo) fim var salarioAntigo, salarioNovo : real inicio escreva(“Digite o salário antigo:”) leia(salarioAntigo) //Observe aqui a atribuição que fizemos a variável salarioNovo através do resultado da função salarioNovo <- REAJUSTAR(salarioAntigo) escreva(“Seu salário novo é de R$: ”, salarioNovo) fimalgoritmo Perceba que usamos o resultado do reajuste calculado como valor da variável salarioNovo. Vamos continuar com os nossos exemplos. Exemplo 9: escreva um algoritmo que leia um valor de um salário de um funcionário da empresa, da mesma tabela que o exemplo anterior. A diferença é que a função deve retornar o valor da porcentagem a ser aplicado ao salário, passando o trabalho de calcular o novo salário ao programa principal. algoritmo “Reajuste” //função que reajusta o salário função PORCENTAGEM_AUMENTO(salario:real) : real

Algoritmos II 22

Vale a pena acessar

VARELA, Marcelo. Os Procedimentos (Procedures) e Funções (Functions). Imasters, 2002. Disponível em: <https://imasters.com.br/artigo/345/linguagens/os- procedimentos-procedures-e-funcoes-functions?trace= 9021197&source=single>. Acesso em: 20 out. 2007. SILVA, Elaine Quintino. Aprendendo a programar: procedimentos e funções. GlobalCoders, 2010. Disponível em: <http://blog.globalcode.com.br/2010/06/aprendendo- programar-procedimentos-e.html>. Acesso em: 20 out. 2017.

Minhas anotações

Algoritmos II 24

Seções de estudo

1 - Introdução ao escopo de variáveis

2 - Escopo Local

1 - Introdução ao escopo de variáveis 2 - Escopo Local 3 - Escopo Global 4 - Cuidados com o escopo de variáveis Até meados dos anos 2000, os computadores pessoais não tinham uma fartura de memória disponível que existem nos computadores hoje. Enquanto que os computadores de hoje possuem de 2 a 8 Gigabytes (equivalente a 2000 a 8000 Megabytes) de memória, os computadores do final da década de 1990 possuíam até 64 Megabytes de memória. Já na década de 1980 existiam computadores de apenas 1 Megabyte de memória, enquanto que os computadores da décadas de 1960 e 1970 possuíam valores de memória ainda menores. Figura 1 - Anúncio de um computador em 1995, nos Estados Unidos. Perceba que a quantidade de memória disponível é de apenas 4 Megabytes. Fonte: Disponível em: http://i.imgur.com/sf2dD.jpg. Acesso em: 23 out. 2017. Devido a essa escassez de memória, os programadores daquela época tinham uma preocupação sobre o uso eficiente de memória. Assim, a programação estruturada, que havia surgido na década de 1960, propõe uma técnica para facilitar o gerenciamento de variáveis, para que o programador use o mínimo possível de memória. Ela se chama escopo de variáveis. Manzano e Figueiredo oferecem uma definição sobre isso: “O escopo de uma variável, ou sua abrangência operacional, está vinculado à forma de sua visibilidade no programa (...) em relação às sub-rotinas que compõem um programa (...)” (MANZANO, FIGUEIREDO; 2014; p. 216). Diante dessa definição, podemos entender que o escopo de uma variável se refere a que locais uma variável vai existir durante o tempo de vida de um programa. Em programas, uma variável pode ser de dois escopos. Ou pode ser de escopo local ou pode ser de escopo global. Detalharemos sobre eles nas próximas seções. Uma variável é de escopo local quando existir somente no local onde foi declarado. Ou seja, se foi declarado no corpo principal de um programa, só existirá no corpo principal. Se for declarado em um procedimento, essa variável só existirá durante a execução do procedimento. Uma variável de escopo local (pode ser chamada também de variável local) pode ser declarada de duas formas: ● declarada dentro de uma função ou de um procedimento. Neste caso, essa variável só será visível durante a execução do módulo onde foi criado; ● declarada após todas as funções e procedimentos do programa. Nessa situação, a variável só existirá apenas no bloco principal do programa, não sendo visível para todos os módulos do programa. Podemos fazer uma analogia a esta situação. Digamos que o bloco principal e cada módulo ou procedimento do programa seja uma caixa. Em variáveis de escopo local, cada variável ficaria em uma caixa, dentro do seu mundo que ele conhece. Ele não existe nos outros blocos do programa. Figura 2 - Analogia com as variáveis locais. Fonte: Acervo Pessoal. Vamos a um exemplo para mostrar o funcionamento das variáveis locais: Exemplo 11: crie um programa que leia duas variáveis no teclado, e inverta esses valores das duas variáveis após a leitura. Por exemplo, se foram lidos os valores 7 e 2, o programa deve invertê-los e essas variáveis deverão estar com os valores 2 e 7, respectivamente. O código para troca de valores deverá ser implementado em um procedimento. algoritmo “Inverte_Valores” procedimento TROCA(num1:inteiro, num2:inteiro) var X : inteiro inicio X <- num num1 <- num num2 <- X fim var //neste bloco, temos apenas variáveis locais //visíveis apenas no bloco principais num1, num2 : inteiro

Algoritmos II 26

comprovarmos, veja o teste de mesa que foi feito para esse programa, apresentado a seguir: Variáveis globais Comentário num1 num 2 7 Antes da chamada do procedimento 2 7 Foi chamado o procedimento 2 7 X = 2 (num1) 7 7 num1 recebe o valor de num 7 2 num2 recebe o valor de X 7 2 Procedimento encerrado Porém, nem tudo são flores nas variáveis globais. Por sua natureza, essas variáveis podem causar vários tipos de problemas. Vamos discutir sobre elas a seguir.

4 - Cuidados com o escopo de

variáveis

Devido ao fato que as variáveis globais são visíveis por todo o código e também qualquer alteração que seja feita por um trecho de código em uma variável global impacta diretamente em todos os demais, o uso de variáveis globais deve ser feito com cuidado, pois uma alteração mal planejada em alguma das variáveis globais pode causar um erro difícil de ser detectado no código. Vamos a um exemplo. Exemplo 13: escreva um algoritmo que somente conte quantas vezes um procedimento foi chamado. algoritmo “TesteErro” var //Aqui temos uma variável global contador : inteiro procedimento CONTA inicio contador <- contador + 1 fim procedimento EXIBE inicio contador <- 5 escreva(“contador = ”, contador) fim inicio contador <- 0 CONTA() CONTA() CONTA() EXIBE() fimalgoritmo Nesse exemplo, se você não olhasse o que tem dentro do procedimento EXIBE, você falaria que o programa vai exibir o valor 4, pois o procedimento CONTA foi chamado 4 vezes. Está errado. Nesse exemplo, o programador colocou uma atribuição equivocada no procedimento EXIBE, colocando o valor 5 na variável contador. Assim, por mais que o procedimento CONTA fosse chamado várias e várias vezes, o programa sempre vai exibir o valor 5 no final da execução, devido a essa atribuição. Nesse exemplo, pode ser fácil encontrar o erro relacionado às variáveis globais. Mas em programas complexos, com dezenas de procedimentos e funções, pode ser uma tarefa árdua achar um erro semelhante a que tratamos aqui. Assim, outro problema que é associado ao uso de globais é o aumento da complexidade da manutenção do código , visto que como uma variável pode ser usada em vários locais ao mesmo tempo, o tempo que é gasto para a manutenção, devido ao trabalho de alterar em vários locais. Isso também acarreta na perda de flexibilidade do código, pois os módulos dependerão de variáveis dentro do programa. Lembre-se de que a flexibilidade é a grande vantagem de usar a modularização. Por isso, somente use variáveis globais em casos estritos, como, por exemplo, em variáveis que indicam o status do sistema, por exemplo. Sempre que possível, use variáveis locais para o programa principal e seus módulos e use a passagem de parâmetros para passar valores para um módulo. Com isso, finalizamos aqui o nosso estudo sobre o escopo de variáveis. Na próxima aula, veremos sobre a recursividade, para finalizar nossos estudos sobre a modularização.

Retomando a aula

Chegamos ao final da nossa aula 05, que abordamos sobre escopo de variáveis. Vamos recordar? 1 - Introdução ao escopo de variáveis O escopo de variáveis é o nome dado a forma de visibilidade de uma variável em um programa. Foi uma técnica criada para aperfeiçoar o gerenciamento de memória dos programas nos primórdios da informática, quando as máquinas possuíam pouca memória, em relação aos computadores dos tempos atuais. 2 - Escopo Local Chamamos de variáveis de escopo local aquelas que foram declaradas após todas as funções e procedimentos ou dentro de uma função ou procedimento. Essas variáveis existem somente no bloco onde foi declarado, não sendo possível usar em outros locais do código. 3 - Escopo Global As variáveis de escopo global são aquelas que foram declaradas antes da declaração de funções e procedimentos. São chamadas assim porque podem ser usadas em qualquer lugar do programa, possuindo um valor para todos os locais durante a sua execução.

4 - Cuidados com o escopo de variáveis As variáveis globais, devido a sua natureza, podem causar vários problemas ao programa, como erros ocasionados por atribuições inesperadas, dificuldade na manutenção e perda de flexibilidade no programa. Por isso, é recomendado sempre usar variáveis locais e passagem de parâmetros no programa. MANZANO, José Augusto N. G.; OLIVEIRA, Jayr Figueiredo de Oliveira. Algoritmos - lógica para desenvolvimento de programação. 2. ed. São Paulo: Érica, 2014. VENANCIO, Claudio Ferreira. Desenvolvimento de Algoritmos : Uma Nova Abordagem. São Paulo: Érica, 2000. FARRER, Harry; et. al. Algoritmos Estruturados. 3. ed. São Paulo: LTC, 1999.

Vale a pena

Vale a pena ler

Minhas anotações

Algoritmos II 30

fimenquanto retorne(resp) fim var numero, fat : inteiro inicio escreva(“Entre com um número:”) leia(numero) fat <- FATORIAL(numero) escreva(“Resultado: ”, fat) fimalgoritmo Nesse algoritmo, perceba o uso das variáveis auxiliares para controlar a repetição do cálculo do fatorial. Vamos ver o teste de mesa dessa função, para o fatorial do número 5. resp i 1 5 5 4 20 3 60 2 120 1 120 0 Agora, vamos ver um algoritmo recursivo para o cálculo do fatorial. Exemplo 15: Implemente um algoritmo que contenha uma função recursiva para o cálculo do fatorial. algoritmo “Fatorial_Recursivo” funcao FATORIAL(N : inteiro) : inteiro var resp : inteiro inicio se (n > 0) entao resp <- n * FATORIAL(N - 1) senao resp <- 1 fimse retorne(resp) fim var numero, fat : inteiro inicio escreva(“Entre com um número:”) leia(numero) fat <- FATORIAL(numero) escreva(“Resultado: ”, fat) fimalgoritmo Aqui nesse algoritmo, eliminamos a estrutura de repetição e trocamos por uma estrutura recursiva. Aproveitamos o fato que podemos usar os resultados de funções em expressões de cálculo de resultados e colocamos o resultado da chamada recursiva para ser multiplicado por n. Para entendermos uma função recursiva, devemos entender que neste caso, há uma pilha de funções, onde a cada nova chamada recursiva, é empilhada uma nova função da memória. Para compreendermos esse conceito, vamos explicar o mesmo exemplo do fatorial do número 5:

  1. O bloco principal chama a função FATORIAL(5) para iniciar o cálculo;
  2. A função FATORIAL(5) constata que 5 é maior que zero. Assim, chama FATORIAL(N - 1) o que é equivalente a FATORIAL(4);
  3. Na função FATORIAL(4) ainda persiste a condição de parâmetro maior que zero, assim, a função chama FATORIAL(3);
  4. Diante da mesma situação, FATORIAL(3) chama novamente a si mesmo (FATORIAL(2));
  5. Em FATORIAL(2) persiste as condições de continuidade. Logo, ela chama FATORIAL(1);
  6. Ainda em FATORIAL(1) continua a condição de continuidade. Portanto, ela chama FATORIAL(0);
  7. Nesse ponto, o bloco principal e cinco instâncias de execução da função FATORIAL estão esperando o término das funções seguintes. Mas nesta situação, a função FATORIAL(0) já não satisfaz a condição de N > 0. Portanto, ela retorna o resultado para um caso mínimo. Ou seja, 1. Ela devolve para sua função chamadora, FATORIAL(1);
  8. A partir daí, cada função vai calcular o valor de sua variável resp, retornando para a função anterior, assim, em FATORIAL(1), é calculado 1 * 1 = 1 (N * FATORIAL(N - 1)), retornando 1 para FATORIAL(2);
  9. Em FATORIAL(2), calcula-se 2 * 1 = 2, retornando 2 para FATORIAL(3);
  10. Em FATORIAL(3), calcula-se 3 * 2 = 6, retornando 6 para FATORIAL(4);
  11. Já em FATORIAL(4), calcula-se 4 * 6 = 24, devolvendo 24 para FATORIAL(5);
  12. Agora em FATORIAL(5) é calculado 5 * 24 = 120. Como quem chamou foi o bloco principal do programa, devolve 120 para o bloco principal, encerrando a recursão. A figura a seguir, mostra graficamente esse processo de execução da recursividade. Figura 3 - Como funciona a recursão. Fonte: Acervo Pessoal. Manzano e Figueiredo (2014, p. 225) afirmam que a recursividade permite ao programador escrever “código mais elegante com alto grau de abstração”. Utilize esse recurso para melhorar seus códigos. Com isso, encerramos o nosso estudo sobre recursividade,

nosso último tópico sobre modularização de programas. Caso você tenha dúvidas, use os recursos que você tem a sua disposição em sua área do aluno. Na próxima aula, veremos outro tópico importante em algoritmo, o uso de arquivos.

Retomando a aula

Chegamos ao final da nossa aula sobre recursividade. Vamos recordar? 1 - Conceito de Recursividade Em computação, o nome recursividade é dado a capacidade de uma função poder chamar a si mesma. Essa possibilidade pode transformar algoritmos complexos em algoritmos mais simples e elegantes. 2 - Criando algoritmos recursivos Qualquer situação que envolva uma estrutura de repetição pode ser programada de maneira recursiva. Porém, devemos ter em mente duas observações: sempre colocar uma situação onde a recursividade para (caso contrário, a recursão pode repetir-se indefinidamente) e usar em determinadas situações (pois a recursão consome mais recursos de memória do que uma estrutura de repetição simples). MANZANO, José Augusto N. G.; OLIVEIRA, Jayr Figueiredo de Oliveira. Algoritmos - lógica para desenvolvimento de programação. 2. ed. São Paulo: Érica, 2014. VENANCIO, Claudio Ferreira. Desenvolvimento de Algoritmos : Uma Nova Abordagem. São Paulo: Érica, 2000. FARRER, Harry; et. al. Algoritmos Estruturados. 3. ed. São Paulo: LTC, 1999.

Vale a pena

Vale a pena ler

Vale a pena acessar

FEOFILOFF, Paulo. Recursão e algoritmos recursivos. São Paulo: USP, 2017. Disponível em: <https://www.ime. usp.br/~pf/algoritmos/aulas/recu.html>. Acesso em: 30 out. 2017.

Minhas anotações